canonical / canonical/microceph
Dashboard GET /api/rgw/bucket/<name> returns 500 for buckets with lifecycle config (missing xmltodict dependency)
- Dominant language
- Go
- Stars
- 396
- Forks
- 74
- Avg merge
- 2d 20h
- Merged PRs (30d)
- 7
Description
Summary
GET /api/rgw/bucket/ in the Ceph Dashboard returns 500 Internal Server Error for any bucket that has an S3 lifecycle configuration set, regardless of the lifecycle rule's content. This breaks the bucket detail/edit view in the Dashboard for every such bucket. Root cause is a NameError on xmltodict, which is missing from the snap's bundled Python packages.
Environment
MicroCeph snap, channel squid/stable
Installed revision at time of report: 19.2.3+snapfd93b718e2 (rev 1701)
Ceph version: 19.2.3 (c92aebb279828e9c3c1f5d24613efca272649e62) squid (stable) — confirmed identical across mon/mgr/osd/mds/rgw via ceph versions
Host OS: Ubuntu (Noble-based), single-node MicroCeph deployment
Deployment: single host, 1 mon / 1 mgr / 4 OSDs / 1 RGW
Steps to reproduce
Create (or use an existing) RGW bucket.
Enable versioning on the bucket (via Dashboard or S3 API) — not required to trigger the bug, but was the original context.
Set any S3 lifecycle configuration on the bucket, e.g.:
expire-noncurrent-versions
Enabled
30
(Confirmed via direct PUT .../?lifecycle with proper AWS SigV4 signing — RGW itself accepts and stores the configuration correctly, returns 200.)
In the Dashboard (or via GET /api/rgw/bucket/?daemon_name=), fetch bucket details.
Expected behavior
Bucket details load normally, including the lifecycle configuration.
Actual behavior
500 Internal Server Error:
{"status": "500 Internal Server Error", "detail": "The server encountered an unexpected condition which prevented it from fulfilling the request.", "request_id": "..."}
Isolated this with a disposable test bucket:
Versioning alone (no lifecycle): no crash, 200.
Any lifecycle rule present (single rule, multiple rules, with/without Expiration, with/without NoncurrentVersionExpiration): always 500, regardless of rule content.
Root cause (confirmed via mgr log traceback)
Traceback (most recent call last):
File "/usr/share/ceph/mgr/dashboard/services/exception.py", line 47, in dashboard_exceptio_handler
return handler(*args, **kwargs)
File "/snap/microceph/1701/lib/python3/dist-packages/cherrypy/_cpdispatch.py", line 54, in __call__
return self.callable(*self.args, **self.kwargs)
File "/usr/share/ceph/mgr/dashboard/controllers/_base_controller.py", line 263, in inner
ret = func(*args, **kwargs)
File "/usr/share/ceph/mgr/dashboard/controllers/_rest_controller.py", line 193, in wrapper
return func(*vpath, **params)
File "/usr/share/ceph/mgr/dashboard/controllers/rgw.py", line 525, in get
result['lifecycle'] = self._get_lifecycle(bucket_name, daemon_name, owner)
File "/usr/share/ceph/mgr/dashboard/controllers/rgw.py", line 432, in _get_lifecycle
return rgw_client.get_lifecycle(bucket_name)
File "/usr/share/ceph/mgr/dashboard/rest_client.py", line 538, in func_wrapper
return func(
File "/usr/share/ceph/mgr/dashboard/services/rgw_client.py", line 811, in get_lifecycle
return xmltodict.parse(remove_namespace(result), process_namespaces=False)
NameError: name 'xmltodict' is not defined
Upstream rgw_client.py imports xmltodict defensively:
try:
import xmltodict
except ModuleNotFoundError:
logging.error("Module 'xmltodict' is not installed.")
If the import fails, the error is only logged — xmltodict is left undefined, and any later call to xmltodict.parse(...) in get_lifecycle() raises NameError instead of a clean, catchable error.
Confirmed the package is genuinely absent from the snap's bundled site-packages:
$ find /snap/microceph/1701/lib/python3/dist-packages -iname 'xmltodict*'
(no output)
Looking at snap/snapcraft.yaml, the Ceph dashboard's Python dependencies are pulled in indirectly by staging the ceph-mgr-dashboard Debian package rather than being explicitly listed. On a normal Ubuntu install, apt would automatically resolve ceph-mgr-dashboard's dependency on python3-xmltodict and install it alongside — but snapcraft's stage-packages only pulls in exactly what is listed, not the full transitive dependency chain of each staged package's own Depends. It looks like python3-xmltodict (or equivalent) was never added to stage-packages for the relevant part, so it's silently absent from the built snap even though ceph-mgr-dashboard requires it.
Suggested fix
Add python3-xmltodict to the stage-packages list for the part that stages ceph-mgr-dashboard in snap/snapcraft.yaml.
Impact / scope
This is purely a Dashboard-layer bug. Confirmed via direct S3 API calls (signed with real AWS SigV4) that RGW itself correctly stores and serves the lifecycle configuration — PUT/GET .../?lifecycle behave correctly at the RGW layer.
Bucket versioning and lifecycle rules continue to function correctly at the storage layer; only the Dashboard's bucket detail/edit view is broken for affected buckets.
Separately observed (may be worth a second look, possibly related or a distinct bug): DELETE .../?lifecycle returns a genuine 204 No Content from RGW, but a subsequent GET .../?lifecycle (via both radosgw-admin lc get and direct signed GET) still shows the lifecycle configuration as unchanged — i.e., deleting the lifecycle configuration does not appear to actually clear it. Happy to file this separately with its own repro if useful.
Contributor guide
Research direction
Inspect the ceph-mgr-dashboard staging part in snap/snapcraft.yaml and the dashboard dependency context described in the issue. Add the missing package dependency, build the MicroCeph snap, and verify that GET /api/rgw/bucket/ returns bucket details successfully for a bucket with an S3 lifecycle configuration.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python, yaml
- Domain
- backend, build-system
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 82/100