From 5bdc35b11574439057cfbdee17cf83c40da2cea2 Mon Sep 17 00:00:00 2001 From: MotoKen Date: Tue, 27 Dec 2011 14:44:11 +0800 Subject: [PATCH] Adds EC2 ImportKeyPair API support. Implements import_key_pair instead of import_public_key. Change-Id: I256b76aeb4ff94030a58692bfd12b2d7c53ae461 --- Authors | 1 + nova/api/ec2/__init__.py | 2 +- nova/api/ec2/cloud.py | 39 +++++++++++++++++++++----------- nova/tests/api/ec2/test_cloud.py | 27 ++++++++-------------- 4 files changed, 37 insertions(+), 32 deletions(-) diff --git a/Authors b/Authors index 186bb02d3c9a..47235cf7a5bc 100644 --- a/Authors +++ b/Authors @@ -107,6 +107,7 @@ Mohammed Naser Monsyne Dragon Monty Taylor MORITA Kazutaka +MotoKen Muneyuki Noguchi Nachi Ueno Naveed Massjouni diff --git a/nova/api/ec2/__init__.py b/nova/api/ec2/__init__.py index 3c1250f978ea..fcd08531a32f 100644 --- a/nova/api/ec2/__init__.py +++ b/nova/api/ec2/__init__.py @@ -278,7 +278,7 @@ class Authorizer(wsgi.Middleware): 'CreateKeyPair': ['all'], 'DeleteKeyPair': ['all'], 'DescribeSecurityGroups': ['all'], - 'ImportPublicKey': ['all'], + 'ImportKeyPair': ['all'], 'AuthorizeSecurityGroupIngress': ['netadmin'], 'RevokeSecurityGroupIngress': ['netadmin'], 'CreateSecurityGroup': ['netadmin'], diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index 1f5405dea453..a965b84b6292 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -388,26 +388,39 @@ class CloudController(object): 'keyMaterial': data['private_key']} # TODO(vish): when context is no longer an object, pass it here - def import_public_key(self, context, key_name, public_key, - fingerprint=None): + def _get_fingerprint(self, public_key): + tmpdir = tempfile.mkdtemp() + pubfile = os.path.join(tmpdir, 'temp.pub') + fh = open(pubfile, 'w') + fh.write(public_key) + fh.close() + try: + (out, err) = utils.execute('ssh-keygen', '-l', '-f', + '%s' % (pubfile)) + return out.split(' ')[1] + except: + raise + finally: + shutil.rmtree(tmpdir) + + 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 + public_key = base64.b64decode(public_key_material) + fingerprint = self._get_fingerprint(public_key) key = {} key['user_id'] = context.user_id key['name'] = key_name key['public_key'] = public_key - if fingerprint is None: - tmpdir = tempfile.mkdtemp() - pubfile = os.path.join(tmpdir, 'temp.pub') - fh = open(pubfile, 'w') - fh.write(public_key) - fh.close() - (out, err) = utils.execute('ssh-keygen', '-q', '-l', '-f', - '%s' % (pubfile)) - fingerprint = out.split(' ')[1] - shutil.rmtree(tmpdir) key['fingerprint'] = fingerprint db.key_pair_create(context, key) - return True + return {'keyName': key_name, + 'keyFingerprint': fingerprint} def delete_key_pair(self, context, key_name, **kwargs): LOG.audit(_("Delete key pair %s"), key_name, context=context) diff --git a/nova/tests/api/ec2/test_cloud.py b/nova/tests/api/ec2/test_cloud.py index 7487db4a607d..aa07aae1e644 100644 --- a/nova/tests/api/ec2/test_cloud.py +++ b/nova/tests/api/ec2/test_cloud.py @@ -1164,19 +1164,7 @@ class CloudTestCase(test.TestCase): self.assertTrue(filter(lambda k: k['keyName'] == 'test1', keys)) self.assertTrue(filter(lambda k: k['keyName'] == 'test2', keys)) - def test_import_public_key(self): - # test when user provides all values - result1 = self.cloud.import_public_key(self.context, - 'testimportkey1', - 'mytestpubkey', - 'mytestfprint') - self.assertTrue(result1) - keydata = db.key_pair_get(self.context, - self.context.user_id, - 'testimportkey1') - self.assertEqual('mytestpubkey', keydata['public_key']) - self.assertEqual('mytestfprint', keydata['fingerprint']) - # test when user omits fingerprint + def test_import_key_pair(self): pubkey_path = os.path.join(os.path.dirname(__file__), 'public_key') f = open(pubkey_path + '/dummy.pub', 'r') dummypub = f.readline().rstrip() @@ -1184,13 +1172,16 @@ class CloudTestCase(test.TestCase): f = open(pubkey_path + '/dummy.fingerprint', 'r') dummyfprint = f.readline().rstrip() f.close - result2 = self.cloud.import_public_key(self.context, - 'testimportkey2', - dummypub) - self.assertTrue(result2) + key_name = 'testimportkey' + public_key_material = base64.b64encode(dummypub) + result = self.cloud.import_key_pair(self.context, + key_name, + public_key_material) + self.assertEqual(result['keyName'], key_name) + self.assertEqual(result['keyFingerprint'], dummyfprint) keydata = db.key_pair_get(self.context, self.context.user_id, - 'testimportkey2') + key_name) self.assertEqual(dummypub, keydata['public_key']) self.assertEqual(dummyfprint, keydata['fingerprint'])