From 1d121a42f5072026a3ad19cb5fd1915d7cd2ff63 Mon Sep 17 00:00:00 2001 From: "vladimir.p" Date: Mon, 22 Aug 2011 17:31:48 -0700 Subject: initial cut on volume type APIs --- nova/volume/api.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'nova/volume/api.py') diff --git a/nova/volume/api.py b/nova/volume/api.py index 52b3a9fed..7a78e244f 100644 --- a/nova/volume/api.py +++ b/nova/volume/api.py @@ -41,7 +41,8 @@ LOG = logging.getLogger('nova.volume') class API(base.Base): """API for interacting with the volume manager.""" - def create(self, context, size, snapshot_id, name, description): + def create(self, context, size, snapshot_id, name, description, + volume_type=None, metadata=None): if snapshot_id != None: snapshot = self.get_snapshot(context, snapshot_id) if snapshot['status'] != "available": @@ -66,7 +67,10 @@ class API(base.Base): 'status': "creating", 'attach_status': "detached", 'display_name': name, - 'display_description': description} + 'display_description': description, + 'volume_type_id': volume_type.get('id', None), + 'metadata' metadata, + } volume = self.db.volume_create(context, options) rpc.cast(context, -- cgit From ddc7d9470674a4d7300d15e5c6fa54b784b6a36f Mon Sep 17 00:00:00 2001 From: "vladimir.p" Date: Tue, 23 Aug 2011 15:18:50 -0700 Subject: added volume_types APIs --- nova/volume/api.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'nova/volume/api.py') diff --git a/nova/volume/api.py b/nova/volume/api.py index 7a78e244f..80e8bd85f 100644 --- a/nova/volume/api.py +++ b/nova/volume/api.py @@ -42,7 +42,7 @@ class API(base.Base): """API for interacting with the volume manager.""" def create(self, context, size, snapshot_id, name, description, - volume_type=None, metadata=None): + volume_type=None, metadata=None, availability_zone=None): if snapshot_id != None: snapshot = self.get_snapshot(context, snapshot_id) if snapshot['status'] != "available": @@ -58,18 +58,21 @@ class API(base.Base): raise quota.QuotaError(_("Volume quota exceeded. You cannot " "create a volume of size %sG") % size) + if availability_zone is None: + availability_zone = FLAGS.storage_availability_zone + options = { 'size': size, 'user_id': context.user_id, 'project_id': context.project_id, 'snapshot_id': snapshot_id, - 'availability_zone': FLAGS.storage_availability_zone, + 'availability_zone': availability_zone, 'status': "creating", 'attach_status': "detached", 'display_name': name, 'display_description': description, 'volume_type_id': volume_type.get('id', None), - 'metadata' metadata, + 'metadata': metadata, } volume = self.db.volume_create(context, options) -- cgit From 29940dd27f3a40a4ad54bc2f7a4cea5ac2226b83 Mon Sep 17 00:00:00 2001 From: "vladimir.p" Date: Tue, 23 Aug 2011 20:22:27 -0700 Subject: added volume metadata APIs (OS & volume layers), search volume by metadata & other --- nova/volume/api.py | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 69 insertions(+), 4 deletions(-) (limited to 'nova/volume/api.py') diff --git a/nova/volume/api.py b/nova/volume/api.py index 80e8bd85f..195ab24aa 100644 --- a/nova/volume/api.py +++ b/nova/volume/api.py @@ -61,6 +61,11 @@ class API(base.Base): if availability_zone is None: availability_zone = FLAGS.storage_availability_zone + if volume_type is None: + volume_type_id = None + else: + volume_type_id = volume_type.get('id', None) + options = { 'size': size, 'user_id': context.user_id, @@ -71,7 +76,7 @@ class API(base.Base): 'attach_status': "detached", 'display_name': name, 'display_description': description, - 'volume_type_id': volume_type.get('id', None), + 'volume_type_id': volume_type_id, 'metadata': metadata, } @@ -112,10 +117,44 @@ class API(base.Base): rv = self.db.volume_get(context, volume_id) return dict(rv.iteritems()) - def get_all(self, context): + def get_all(self, context, search_opts={}): if context.is_admin: - return self.db.volume_get_all(context) - return self.db.volume_get_all_by_project(context, context.project_id) + volumes = self.db.volume_get_all(context) + else: + volumes = self.db.volume_get_all_by_project(context, + context.project_id) + + if search_opts: + LOG.debug(_("Searching by: %s") % str(search_opts)) + + def _check_metadata_match(volume, searchdict): + volume_metadata = {} + for i in volume.get('volume_metadata'): + volume_metadata[i['key']] = i['value'] + + for k, v in searchdict: + if k not in volume_metadata.keys()\ + or volume_metadata[k] != v: + return False + return True + + # search_option to filter_name mapping. + filter_mapping = {'metadata': _check_metadata_match} + + for volume in volumes: + # go over all filters in the list + for opt, values in search_opts.iteritems(): + try: + filter_func = filter_mapping[opt] + except KeyError: + # no such filter - ignore it, go to next filter + continue + else: + if filter_func(volume, values) == False: + # if one of conditions didn't match - remove + volumes.remove(volume) + break + return volumes def get_snapshot(self, context, snapshot_id): rv = self.db.snapshot_get(context, snapshot_id) @@ -190,3 +229,29 @@ class API(base.Base): {"method": "delete_snapshot", "args": {"topic": FLAGS.volume_topic, "snapshot_id": snapshot_id}}) + + def get_volume_metadata(self, context, volume_id): + """Get all metadata associated with a volume.""" + rv = self.db.volume_metadata_get(context, volume_id) + return dict(rv.iteritems()) + + def delete_volume_metadata(self, context, volume_id, key): + """Delete the given metadata item from an volume.""" + self.db.volume_metadata_delete(context, volume_id, key) + + def update_volume_metadata(self, context, volume_id, + metadata, delete=False): + """Updates or creates volume metadata. + + If delete is True, metadata items that are not specified in the + `metadata` argument will be deleted. + + """ + if delete: + _metadata = metadata + else: + _metadata = self.get_volume_metadata(context, volume_id) + _metadata.update(metadata) + + self.db.volume_metadata_update(context, volume_id, _metadata, True) + return _metadata -- cgit