diff options
| author | Jenkins <jenkins@review.openstack.org> | 2013-04-04 20:48:19 +0000 |
|---|---|---|
| committer | Gerrit Code Review <review@openstack.org> | 2013-04-04 20:48:19 +0000 |
| commit | 7a65d7ed74a634cbb61d0d555438bf011a4046eb (patch) | |
| tree | 802948a3e5ea67645f5691cf583b31fedd671b1f /nova/api | |
| parent | d6715e843c422466452c59a6536cf21d5dee026e (diff) | |
| parent | 55a04a4bc3228e698bb84a641d50507810ae9a02 (diff) | |
Merge "Add CRUD methods for tags to the EC2 API."
Diffstat (limited to 'nova/api')
| -rw-r--r-- | nova/api/ec2/cloud.py | 135 | ||||
| -rw-r--r-- | nova/api/ec2/ec2utils.py | 25 |
2 files changed, 160 insertions, 0 deletions
diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index 0d06dde33..3d210404c 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -1174,6 +1174,10 @@ class CloudController(object): i['ipAddress'] = floating_ip or fixed_ip i['dnsName'] = i['publicDnsName'] or i['privateDnsName'] i['keyName'] = instance['key_name'] + i['tagSet'] = [] + for k, v in self.compute_api.get_instance_metadata( + context, instance).iteritems(): + i['tagSet'].append({'key': k, 'value': v}) if context.is_admin: i['keyName'] = '%s (%s, %s)' % (i['keyName'], @@ -1677,6 +1681,137 @@ class CloudController(object): return {'imageId': ec2_id} + def create_tags(self, context, **kwargs): + """Add tags to a resource + + Returns True on success, error on failure. + + :param context: context under which the method is called + """ + resources = kwargs.get('resource_id', None) + tags = kwargs.get('tag', None) + if resources is None or tags is None: + raise exception.EC2APIError(_('resource_id and tag are required')) + + if not isinstance(resources, (tuple, list, set)): + raise exception.EC2APIError(_('Expecting a list of resources')) + + for r in resources: + if ec2utils.resource_type_from_id(context, r) != 'instance': + raise exception.EC2APIError(_('Only instances implemented')) + + if not isinstance(tags, (tuple, list, set)): + raise exception.EC2APIError(_('Expecting a list of tagSets')) + + metadata = {} + for tag in tags: + if not isinstance(tag, dict): + raise exception.EC2APIError(_ + ('Expecting tagSet to be key/value pairs')) + + key = tag.get('key', None) + val = tag.get('value', None) + + if key is None or val is None: + raise exception.EC2APIError(_ + ('Expecting both key and value to be set')) + + metadata[key] = val + + for ec2_id in resources: + instance_uuid = ec2utils.ec2_inst_id_to_uuid(context, ec2_id) + instance = self.compute_api.get(context, instance_uuid) + self.compute_api.update_instance_metadata(context, + instance, metadata) + + return True + + def delete_tags(self, context, **kwargs): + """Delete tags + + Returns True on success, error on failure. + + :param context: context under which the method is called + """ + resources = kwargs.get('resource_id', None) + tags = kwargs.get('tag', None) + if resources is None or tags is None: + raise exception.EC2APIError(_('resource_id and tag are required')) + + if not isinstance(resources, (tuple, list, set)): + raise exception.EC2APIError(_('Expecting a list of resources')) + + for r in resources: + if ec2utils.resource_type_from_id(context, r) != 'instance': + raise exception.EC2APIError(_('Only instances implemented')) + + if not isinstance(tags, (tuple, list, set)): + raise exception.EC2APIError(_('Expecting a list of tagSets')) + + for ec2_id in resources: + instance_uuid = ec2utils.ec2_inst_id_to_uuid(context, ec2_id) + instance = self.compute_api.get(context, instance_uuid) + for tag in tags: + if not isinstance(tag, dict): + raise exception.EC2APIError(_ + ('Expecting tagSet to be key/value pairs')) + + key = tag.get('key', None) + if key is None: + raise exception.EC2APIError(_('Expecting key to be set')) + + self.compute_api.delete_instance_metadata(context, + instance, key) + + return True + + def describe_tags(self, context, **kwargs): + """List tags + + Returns a dict with a single key 'tagSet' on success, error on failure. + + :param context: context under which the method is called + """ + filters = kwargs.get('filter', None) + + search_filts = [] + if filters: + for filter_block in filters: + key_name = filter_block.get('name', None) + val = filter_block.get('value', None) + if val: + if isinstance(val, dict): + val = val.values() + if not isinstance(val, (tuple, list, set)): + val = (val,) + if key_name: + search_block = {} + if key_name == 'resource_id': + search_block['resource_id'] = [] + for res_id in val: + search_block['resource_id'].append( + ec2utils.ec2_inst_id_to_uuid(context, res_id)) + elif key_name in ['key', 'value']: + search_block[key_name] = val + elif key_name == 'resource_type': + for res_type in val: + if res_type != 'instance': + raise exception.EC2APIError(_ + ('Only instances implemented')) + search_block[key_name] = 'instance' + if len(search_block.keys()) > 0: + search_filts.append(search_block) + ts = [] + for tag in self.compute_api.get_all_instance_metadata(context, + search_filts): + ts.append({ + 'resource_id': ec2utils.id_to_ec2_inst_id(tag['instance_id']), + 'resource_type': 'instance', + 'key': tag['key'], + 'value': tag['value'] + }) + return {"tagSet": ts} + class EC2SecurityGroupExceptions(object): @staticmethod diff --git a/nova/api/ec2/ec2utils.py b/nova/api/ec2/ec2utils.py index 311d0baf1..660c0e8d4 100644 --- a/nova/api/ec2/ec2utils.py +++ b/nova/api/ec2/ec2utils.py @@ -72,6 +72,31 @@ def image_type(image_type): return image_type +def resource_type_from_id(context, resource_id): + """Get resource type by ID + + Returns a string representation of the Amazon resource type, if known. + Returns None on failure. + + :param context: context under which the method is called + :param resource_id: resource_id to evaluate + """ + + known_types = { + 'i': 'instance', + 'r': 'reservation', + 'vol': 'volume', + 'snap': 'snapshot', + 'ami': 'image', + 'aki': 'image', + 'ari': 'image' + } + + type_marker = resource_id.split('-')[0] + + return known_types.get(type_marker) + + @memoize def id_to_glance_id(context, image_id): """Convert an internal (db) id to a glance id.""" |
