Skip to content

Conversation

@mhkadhum
Copy link

Description

This PR adds support for a Dell EMC ECS S3 object storage plugin for Apache CloudStack. ECS is a software-defined object storage platform that supports both object and file-system protocols, with a focus on scalable and reliable object storage. We have been using ECS in production for three years, and this work extends CloudStack’s existing MinIO plugin to provide similar functionality for ECS.

The implementation supports the full lifecycle of S3-compatible buckets on ECS, including user provisioning, bucket creation, policy management, versioning, creation-time encryption, and integration with CloudStack’s S3 Browser. All functionality has been tested in a lab environment on Ubuntu using a CloudStack development setup based on the official installation guidelines.

Key architectural differences from MinIO:

Management API Integration
ECS requires use of the ECS Management API (port 4443, or 443 when fronted by HAProxy). CloudStack authenticates with management-user credentials to perform bucket and user operations.

Namespace Requirements
A dedicated ECS namespace is required for CloudStack-managed buckets. Multiple namespaces allow different CloudStack environments to share the same ECS cluster.

S3 Endpoints (Public and Private)
ECS exposes S3 services on ports 9020/9021 (non-TLS/TLS). In our deployment, these are routed through HAProxy and exposed externally on port 443. The Public URL is displayed to CloudStack users, while the Private URL is used internally.

TLS Handling
The “Allow Insecure HTTPS” option controls whether CloudStack accepts untrusted certificates when communicating with the ECS Management API.

User Provisioning Workflow
When a CloudStack user creates their first bucket, CloudStack provisions a corresponding ECS object user using the CloudStack UUID with a cs- prefix. ECS generates access and secret keys once, which CloudStack securely stores and reuses for subsequent bucket operations.

Bucket features:

  • Encryption: Supported only during bucket creation; CloudStack hides encryption in the update view.
  • Bucket Policy: Supports Private and Public configurations.
  • Versioning: Fully supported through the S3 API rather than the Management API.
  • Object Lock: Not supported in this release; the UI hides the option and API calls return a clear error.

Bucket modification supports quota changes, versioning updates, and policy changes. Encryption is excluded because ECS does not allow changing it after creation.

CloudStack’s S3 Browser supports upload, download, delete, listing, and prefix filtering through the ECS S3 endpoint. ECS prevents deletion of non-empty buckets, and CloudStack surfaces these errors accordingly.

We welcome review and feedback. The development fork is available here:
https://github.com/mhkadhum/cloudstack

Types of changes

  • Breaking change (fix or feature that would cause existing functionality to change)
  • New feature (non-breaking change which adds functionality)
  • Bug fix (non-breaking change which fixes an issue)
  • Enhancement (improves an existing feature and functionality)
  • Cleanup (Code refactoring and cleanup, that may add test cases)
  • Build/CI
  • Test (unit or integration test code)

Feature/Enhancement Scale or Bug Severity

Feature/Enhancement Scale

  • Major
  • Minor

Bug Severity

  • BLOCKER
  • Critical
  • Major
  • Minor
  • Trivial

Screenshots (if appropriate):

Screenshot from 2025-11-24 16-58-08 image image

How Has This Been Tested?

The plugin was tested in an Ubuntu-based CloudStack development environment created by cloning the CloudStack source and following the official installation instructions. Testing included:

  • Management API authentication and namespace operations
  • Object-user provisioning and credential handling
  • Bucket creation, deletion, versioning, quota updates, and policy changes
  • S3 Browser operations (upload, download, delete, listing, prefix navigation)
  • Error handling for invalid configurations and unsupported Object Lock requests
  • TLS and insecure-TLS scenarios
  • HAProxy-fronted deployments for both Management API and S3 endpoints

@boring-cyborg
Copy link

boring-cyborg bot commented Nov 24, 2025

Congratulations on your first Pull Request and welcome to the Apache CloudStack community! If you have any issues or are unsure about any anything please check our Contribution Guide (https://github.com/apache/cloudstack/blob/main/CONTRIBUTING.md)
Here are some useful points:

Copy link
Member

@jbampton jbampton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have failing tests for pre-commit and license checks.

Have a quick read up on pre-commit it really is a series of basic checks we run:

https://github.com/apache/cloudstack/blob/main/PRE-COMMIT.md

Also we normally add the ASF license header to all files or add an exclude

@codecov
Copy link

codecov bot commented Nov 24, 2025

Codecov Report

❌ Patch coverage is 0% with 1024 lines in your changes missing coverage. Please review.
✅ Project coverage is 17.57%. Comparing base (34b8870) to head (03a7134).
⚠️ Report is 7 commits behind head on main.

Files with missing lines Patch % Lines
...age/datastore/driver/EcsObjectStoreDriverImpl.java 0.00% 773 Missing ⚠️
...tastore/lifecycle/EcsObjectStoreLifeCycleImpl.java 0.00% 132 Missing ⚠️
.../storage/datastore/driver/EcsMgmtTokenManager.java 0.00% 60 Missing ⚠️
...udstack/storage/datastore/driver/EcsXmlParser.java 0.00% 46 Missing ⚠️
...datastore/provider/EcsObjectStoreProviderImpl.java 0.00% 13 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main   #12124      +/-   ##
============================================
- Coverage     17.60%   17.57%   -0.04%     
- Complexity    15668    15669       +1     
============================================
  Files          5915     5920       +5     
  Lines        529963   531034    +1071     
  Branches      64734    64952     +218     
============================================
+ Hits          93300    93309       +9     
- Misses       426194   427257    +1063     
+ Partials      10469    10468       -1     
Flag Coverage Δ
uitests 3.57% <ø> (-0.01%) ⬇️
unittests 18.63% <0.00%> (-0.04%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@sureshanaparti
Copy link
Contributor

@mhkadhum can you check the build errors?

@boring-cyborg boring-cyborg bot added component:marvin Python Warning... Python code Ahead! labels Nov 26, 2025
@mhkadhum
Copy link
Author

Thanks for the feedback!

ive added the missing license headers and ran pre-commit locally, and pushed an updated commit



VERSION = "4.23.0.0-SNAPSHOT"
VERSION = "4.23.0.0"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should not be in the PR

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @DaanHoogland
This was updated after running the pre-commit, should i keep it as
VERSION = "4.23.0.0-SNAPSHOT"
?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, it should only be updated by building (not by pre-commit) somebody introduced that behaviour for testing I think and it forces us to be more vigilent at checking in, so I don’t mind. We need to keep snapshot though untill releasing .

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok,
I've just added it back.

@DaanHoogland
Copy link
Contributor

looks generally good @mhkadhum , thanks for the contribution. Will you be maintaining this? As it is a 3rd party component and it may require hardware or licenses not available to the project.

@mhkadhum
Copy link
Author

looks generally good @mhkadhum , thanks for the contribution. Will you be maintaining this? As it is a 3rd party component and it may require hardware or licenses not available to the project.

Yes, I will be the maintainer for the plugin. I have made a new commit to fix the previous build. Could you kindly review it

Copy link
Contributor

@DaanHoogland DaanHoogland left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have not found any oddities in the code, but one remark (in two parts ;) ) Feel free to ignore but I think it will help in the future.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

methods createBucket, listBuckets, listBucketObjects, deleteBucket, setBucketPolicy, getBucketPolicy, setOrSuspendVersioning, setBucketQuota, ensureAccountUserAndSecretandecsBucketExists` are rather great. Again not my code to maintain, but extracting smaller methods will make it more readible and may help find some code deduplication possibilities.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @DaanHoogland ,

I've been working the comments you provided in order to optimize the code. While these changes may not reduce the lines in the driver file :) but they will enhance the readability of the methods. Additionally, I am working on implementing token caching for the communication between CloudStack and ECS. Currently, the token is being generated for each request, but due to rate limits on token generation, this approach is inefficient. I will update the code soon.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

He @mhkadhum , this file still contains a few very large methods and also methods that contain nested try blocks. Will you address those? As discussed earlier, this will remain your responsibility so I am not demanding any change but I highly recommend you address these conditions of the code.

@DaanHoogland DaanHoogland requested a review from abh1sar December 3, 2025 06:58
@yadvr yadvr requested a review from weizhouapache December 18, 2025 05:35
@mhkadhum
Copy link
Author

mhkadhum commented Dec 18, 2025

Reviewed EcsObjectStoreDriverImpl Overall functionality looks good but there are some comments on code maintainability and organisation. Please check. Overall, I think use of reflections can be avoided in most cases.

Hello @abh1sar
Thank you for ur feedback, am working on addressing all the issues u provided, and updated the new code

@mhkadhum mhkadhum requested a review from abh1sar December 29, 2025 07:27
@DaanHoogland
Copy link
Contributor

@blueorangutan package

@blueorangutan
Copy link

@DaanHoogland a [SL] Jenkins job has been kicked to build packages. It will be bundled with no SystemVM templates. I'll keep you posted as I make progress.

@blueorangutan
Copy link

Packaging result [SF]: ✖️ el8 ✖️ el9 ✖️ debian ✖️ suse15. SL-JID 16184

@mhkadhum
Copy link
Author

Hello @blueorangutan
Had some stuff going on my build now should work now

from my server
mvn -pl :cloud-plugin-storage-object-ecs -Dcheckstyle.consoleOutput=true checkstyle:check
[INFO] Scanning for projects...
[INFO]
[INFO] -------< org.apache.cloudstack:cloud-plugin-storage-object-ecs >--------
[INFO] Building Apache CloudStack Plugin - ECS object storage provider 4.23.0.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-checkstyle-plugin:3.1.0:check (default-cli) @ cloud-plugin-storage-object-ecs ---
[INFO] Starting audit...
Audit done.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.275 s
[INFO] Finished at: 2025-12-29T13:25:30+03:00
[INFO] ------------------------------------------------------------------------

@DaanHoogland
Copy link
Contributor

sorry @mhkadhum , still compile errors (not lint anymore): https://github.com/apache/cloudstack/actions/runs/20570652663/job/59082786785?pr=12124#step:7:18860

@blueorangutan
Copy link

Packaging result [SF]: ✖️ el8 ✖️ el9 ✖️ debian ✖️ suse15. SL-JID 16193

<!-- ECS Object Store Configuration -->
<div v-else-if="form.provider === 'ECS'">
<!-- S3 URL (for UI: this becomes addObjectStoragePool url=...) -->
<a-form-item name="url" ref="url">
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't url a required field?

Copy link
Author

@mhkadhum mhkadhum Dec 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mhkadhum mhkadhum requested a review from abh1sar January 4, 2026 12:26
@DaanHoogland
Copy link
Contributor

@blueorangutan package

@blueorangutan
Copy link

@DaanHoogland a [SL] Jenkins job has been kicked to build packages. It will be bundled with no SystemVM templates. I'll keep you posted as I make progress.

@blueorangutan
Copy link

Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ el10 ✔️ debian ✔️ suse15. SL-JID 16248

@DaanHoogland
Copy link
Contributor

@blueorangutan test

@blueorangutan
Copy link

@DaanHoogland a [SL] Trillian-Jenkins test job (ol8 mgmt + kvm-ol8) has been kicked to run smoke tests

@blueorangutan
Copy link

[SF] Trillian test result (tid-15110)
Environment: kvm-ol8 (x2), zone: Advanced Networking with Mgmt server ol8
Total time taken: 60102 seconds
Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr12124-t15110-kvm-ol8.zip
Smoke tests completed. 149 look OK, 1 have errors, 0 did not run
Only failed and skipped tests results shown below:

Test Result Time (s) Test File
test_03_deploy_and_scale_kubernetes_cluster Failure 27.81 test_kubernetes_clusters.py

}
}

private TokenEntry loginAndGetTokenFresh(final String mgmtUrl,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this method contains three levels of try blocks. the second level has no catch or final blocks. @mhkadhum , are you sure about this? I’d try to dissect it in smaller methods (no 👎 !)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

He @mhkadhum , this file still contains a few very large methods and also methods that contain nested try blocks. Will you address those? As discussed earlier, this will remain your responsibility so I am not demanding any change but I highly recommend you address these conditions of the code.

@DaanHoogland
Copy link
Contributor

@mhkadhum , it looks like you are ready to merge. If you wish to ignore my latest comments please let us know. (cc @abh1sar ).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants