diff options
| author | Jenkins <jenkins@review.openstack.org> | 2012-05-15 09:02:36 +0000 |
|---|---|---|
| committer | Gerrit Code Review <review@openstack.org> | 2012-05-15 09:02:36 +0000 |
| commit | 8823f7bef2142a807b3c92e512f602b6b415a3e2 (patch) | |
| tree | 83aef3cd63cde931108a8316e372fe870053e7a0 /nova/api | |
| parent | fbae8d09fdb9ad370fa827aab0f9bfe0c0c7041f (diff) | |
| parent | ec0a65d81fd11d26be77b45827a4dd7c77711675 (diff) | |
Merge "Create an internal key pair API."
Diffstat (limited to 'nova/api')
| -rw-r--r-- | nova/api/ec2/cloud.py | 94 | ||||
| -rw-r--r-- | nova/api/openstack/compute/contrib/keypairs.py | 82 |
2 files changed, 58 insertions, 118 deletions
diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index 70933d2bc..797cf35bf 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -34,7 +34,6 @@ from nova import block_device from nova import compute from nova.compute import instance_types from nova.compute import vm_states -from nova import crypto from nova import db from nova import exception from nova import flags @@ -61,33 +60,6 @@ def validate_ec2_id(val): raise exception.InvalidInstanceIDMalformed(val) -def _gen_key(context, user_id, key_name): - """Generate a key - - This is a module level method because it is slow and we need to defer - it into a process pool.""" - # NOTE(vish): generating key pair is slow so check for legal - # creation before creating key_pair - try: - db.key_pair_get(context, user_id, key_name) - raise exception.KeyPairExists(key_name=key_name) - except exception.NotFound: - pass - - if quota.allowed_key_pairs(context, 1) < 1: - msg = _("Quota exceeded, too many key pairs.") - raise exception.EC2APIError(msg) - - private_key, public_key, fingerprint = crypto.generate_key_pair() - key = {} - key['user_id'] = user_id - key['name'] = key_name - key['public_key'] = public_key - key['fingerprint'] = fingerprint - db.key_pair_create(context, key) - return {'private_key': private_key, 'fingerprint': fingerprint} - - # EC2 API can return the following values as documented in the EC2 API # http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ # ApiReference-ItemType-InstanceStateType.html @@ -217,6 +189,7 @@ class CloudController(object): self.volume_api = volume.API() self.compute_api = compute.API(network_api=self.network_api, volume_api=self.volume_api) + self.keypair_api = compute.api.KeypairAPI() self.sgh = importutils.import_object(FLAGS.security_group_handler) def __str__(self): @@ -357,7 +330,7 @@ class CloudController(object): return True def describe_key_pairs(self, context, key_name=None, **kwargs): - key_pairs = db.key_pair_get_all_by_user(context, context.user_id) + key_pairs = self.keypair_api.get_key_pairs(context, context.user_id) if not key_name is None: key_pairs = [x for x in key_pairs if x['name'] in key_name] @@ -374,52 +347,55 @@ class CloudController(object): return {'keySet': result} def create_key_pair(self, context, key_name, **kwargs): - if not re.match('^[a-zA-Z0-9_\- ]+$', str(key_name)): - err = _("Value (%s) for KeyName is invalid." - " Content limited to Alphanumeric character, " - "spaces, dashes, and underscore.") % key_name - raise exception.EC2APIError(err) - - if len(str(key_name)) > 255: - err = _("Value (%s) for Keyname is invalid." - " Length exceeds maximum of 255.") % key_name - raise exception.EC2APIError(err) - LOG.audit(_("Create key pair %s"), key_name, context=context) - data = _gen_key(context, context.user_id, key_name) + + try: + keypair = self.keypair_api.create_key_pair(context, + context.user_id, + key_name) + except exception.KeypairLimitExceeded: + msg = _("Quota exceeded, too many key pairs.") + raise exception.EC2APIError(msg) + except exception.InvalidKeypair: + msg = _("Keypair data is invalid") + raise exception.EC2APIError(msg) + except exception.KeyPairExists: + msg = _("Key pair '%s' already exists.") % key_name + raise exception.KeyPairExists(msg) return {'keyName': key_name, - 'keyFingerprint': data['fingerprint'], - 'keyMaterial': data['private_key']} + 'keyFingerprint': keypair['fingerprint'], + 'keyMaterial': keypair['private_key']} # TODO(vish): when context is no longer an object, pass it here def import_key_pair(self, context, key_name, public_key_material, **kwargs): LOG.audit(_("Import key %s"), key_name, context=context) - try: - db.key_pair_get(context, context.user_id, key_name) - raise exception.KeyPairExists(key_name=key_name) - except exception.NotFound: - pass - if quota.allowed_key_pairs(context, 1) < 1: + public_key = base64.b64decode(public_key_material) + + try: + keypair = self.keypair_api.import_key_pair(context, + context.user_id, + key_name, + public_key) + except exception.KeypairLimitExceeded: msg = _("Quota exceeded, too many key pairs.") raise exception.EC2APIError(msg) + except exception.InvalidKeypair: + msg = _("Keypair data is invalid") + raise exception.EC2APIError(msg) + except exception.KeyPairExists: + msg = _("Key pair '%s' already exists.") % key_name + raise exception.EC2APIError(msg) - public_key = base64.b64decode(public_key_material) - fingerprint = crypto.generate_fingerprint(public_key) - key = {} - key['user_id'] = context.user_id - key['name'] = key_name - key['public_key'] = public_key - key['fingerprint'] = fingerprint - db.key_pair_create(context, key) return {'keyName': key_name, - 'keyFingerprint': fingerprint} + 'keyFingerprint': keypair['fingerprint']} def delete_key_pair(self, context, key_name, **kwargs): LOG.audit(_("Delete key pair %s"), key_name, context=context) try: - db.key_pair_destroy(context, context.user_id, key_name) + self.keypair_api.delete_key_pair(context, context.user_id, + key_name) except exception.NotFound: # aws returns true even if the key doesn't exist pass diff --git a/nova/api/openstack/compute/contrib/keypairs.py b/nova/api/openstack/compute/contrib/keypairs.py index 5a764978c..186d836de 100644 --- a/nova/api/openstack/compute/contrib/keypairs.py +++ b/nova/api/openstack/compute/contrib/keypairs.py @@ -17,18 +17,14 @@ """ Keypair management extension""" -import string - import webob import webob.exc from nova.api.openstack import wsgi from nova.api.openstack import xmlutil from nova.api.openstack import extensions -from nova import crypto -from nova import db +from nova.compute import api as compute_api from nova import exception -from nova import quota authorize = extensions.extension_authorizer('compute', 'keypairs') @@ -50,26 +46,10 @@ class KeypairsTemplate(xmlutil.TemplateBuilder): class KeypairController(object): - """ Keypair API controller for the OpenStack API """ - # TODO(ja): both this file and nova.api.ec2.cloud.py have similar logic. - # move the common keypair logic to nova.compute.API? - - def _gen_key(self): - """ - Generate a key - """ - private_key, public_key, fingerprint = crypto.generate_key_pair() - return {'private_key': private_key, - 'public_key': public_key, - 'fingerprint': fingerprint} - - def _validate_keypair_name(self, value): - safechars = "_-" + string.digits + string.ascii_letters - clean_value = "".join(x for x in value if x in safechars) - if clean_value != value: - msg = _("Keypair name contains unsafe characters") - raise webob.exc.HTTPBadRequest(explanation=msg) + """ Keypair API controller for the OpenStack API """ + def __init__(self): + self.api = compute_api.KeypairAPI() @wsgi.serializers(xml=KeypairTemplate) def create(self, req, body): @@ -90,45 +70,29 @@ class KeypairController(object): authorize(context) params = body['keypair'] name = params['name'] - self._validate_keypair_name(name) - if not 0 < len(name) < 256: - msg = _('Keypair name must be between 1 and 255 characters long') - raise webob.exc.HTTPBadRequest(explanation=msg) - # NOTE(ja): generation is slow, so shortcut invalid name exception try: - db.key_pair_get(context, context.user_id, name) - msg = _("Key pair '%s' already exists.") % name - raise webob.exc.HTTPConflict(explanation=msg) - except exception.NotFound: - pass + if 'public_key' in params: + keypair = self.api.import_key_pair(context, + context.user_id, name, + params['public_key']) + else: + keypair = self.api.create_key_pair(context, context.user_id, + name) - keypair = {'user_id': context.user_id, - 'name': name} + return {'keypair': keypair} - if quota.allowed_key_pairs(context, 1) < 1: + except exception.KeypairLimitExceeded: msg = _("Quota exceeded, too many key pairs.") raise webob.exc.HTTPRequestEntityTooLarge( - explanation=msg, - headers={'Retry-After': 0}) - # import if public_key is sent - if 'public_key' in params: - try: - fingerprint = crypto.generate_fingerprint(params['public_key']) - except exception.InvalidKeypair: - msg = _("Keypair data is invalid") - raise webob.exc.HTTPBadRequest(explanation=msg) - - keypair['public_key'] = params['public_key'] - keypair['fingerprint'] = fingerprint - else: - generated_key = self._gen_key() - keypair['private_key'] = generated_key['private_key'] - keypair['public_key'] = generated_key['public_key'] - keypair['fingerprint'] = generated_key['fingerprint'] - - db.key_pair_create(context, keypair) - return {'keypair': keypair} + explanation=msg, + headers={'Retry-After': 0}) + except exception.InvalidKeypair: + msg = _("Keypair data is invalid") + raise webob.exc.HTTPBadRequest(explanation=msg) + except exception.KeyPairExists: + msg = _("Key pair '%s' already exists.") % name + raise webob.exc.HTTPConflict(explanation=msg) def delete(self, req, id): """ @@ -137,7 +101,7 @@ class KeypairController(object): context = req.environ['nova.context'] authorize(context) try: - db.key_pair_destroy(context, context.user_id, id) + self.api.delete_key_pair(context, context.user_id, id) except exception.KeypairNotFound: raise webob.exc.HTTPNotFound() return webob.Response(status_int=202) @@ -149,7 +113,7 @@ class KeypairController(object): """ context = req.environ['nova.context'] authorize(context) - key_pairs = db.key_pair_get_all_by_user(context, context.user_id) + key_pairs = self.api.get_key_pairs(context, context.user_id) rval = [] for key_pair in key_pairs: rval.append({'keypair': { |
