diff --git a/cinder/objects/volume.py b/cinder/objects/volume.py index 0099aaea8d1..53db5debb4b 100644 --- a/cinder/objects/volume.py +++ b/cinder/objects/volume.py @@ -180,6 +180,13 @@ class Volume(cleanable.CinderCleanableObject, base.CinderObject, md = {d['key']: d['value'] for d in value} self.admin_metadata = md + def admin_metadata_update(self, metadata, delete, add=True, update=True): + new_metadata = db.volume_admin_metadata_update(self._context, self.id, + metadata, delete, add, + update) + self.admin_metadata = new_metadata + self._reset_metadata_tracking(fields=('admin_metadata',)) + @property def volume_glance_metadata(self): md = [MetadataObject(k, v) for k, v in self.glance_metadata.items()] diff --git a/cinder/volume/api.py b/cinder/volume/api.py index 4bcad1c14fd..7198f97b622 100644 --- a/cinder/volume/api.py +++ b/cinder/volume/api.py @@ -1195,15 +1195,17 @@ class API(base.Base): context.authorize(vol_meta_policy.UPDATE_ADMIN_METADATA_POLICY, target_obj=volume) utils.check_metadata_properties(metadata) - db_meta = self.db.volume_admin_metadata_update(context, volume.id, - metadata, delete, add, - update) + # Policy could allow non admin users to update admin metadata, but + # underlying DB methods require admin privileges, so we elevate the + # context. + with volume.obj_as_admin(): + volume.admin_metadata_update(metadata, delete, add, update) # TODO(jdg): Implement an RPC call for drivers that may use this info LOG.info("Update volume admin metadata completed successfully.", resource=volume) - return db_meta + return volume.admin_metadata def get_snapshot_metadata(self, context, snapshot): """Get all metadata associated with a snapshot."""