summaryrefslogtreecommitdiffstats
path: root/nova
diff options
context:
space:
mode:
authorVishvananda Ishaya <vishvananda@yahoo.com>2010-09-21 05:08:31 +0000
committerTarmac <>2010-09-21 05:08:31 +0000
commit4e727faf450154d89687b1a33dae2159d5b691a0 (patch)
tree150f932687ed3ae9e97eb05e2b526fb600d0ba8b /nova
parent8a841dd6d5ea21e28c2396b1f7a0a24923a56202 (diff)
parent026f6f2b7f5457f15a258ebed66bb8dda3263eec (diff)
Moves keypairs out of ldap and into the common datastore.
Diffstat (limited to 'nova')
-rw-r--r--nova/auth/ldapdriver.py60
-rw-r--r--nova/auth/manager.py103
-rw-r--r--nova/cloudpipe/pipelib.py4
-rw-r--r--nova/crypto.py2
-rw-r--r--nova/db/api.py28
-rw-r--r--nova/db/sqlalchemy/api.py40
-rw-r--r--nova/db/sqlalchemy/models.py36
-rw-r--r--nova/endpoint/cloud.py57
-rw-r--r--nova/tests/api_unittest.py7
-rw-r--r--nova/tests/auth_unittest.py31
-rw-r--r--nova/tests/cloud_unittest.py53
11 files changed, 198 insertions, 223 deletions
diff --git a/nova/auth/ldapdriver.py b/nova/auth/ldapdriver.py
index cc8e2caa3..021851ebf 100644
--- a/nova/auth/ldapdriver.py
+++ b/nova/auth/ldapdriver.py
@@ -99,13 +99,6 @@ class LdapDriver(object):
dn = FLAGS.ldap_user_subtree
return self.__to_user(self.__find_object(dn, query))
- def get_key_pair(self, uid, key_name):
- """Retrieve key pair by uid and key name"""
- dn = 'cn=%s,%s' % (key_name,
- self.__uid_to_dn(uid))
- attr = self.__find_object(dn, '(objectclass=novaKeyPair)')
- return self.__to_key_pair(uid, attr)
-
def get_project(self, pid):
"""Retrieve project by id"""
dn = 'cn=%s,%s' % (pid,
@@ -119,12 +112,6 @@ class LdapDriver(object):
'(objectclass=novaUser)')
return [self.__to_user(attr) for attr in attrs]
- def get_key_pairs(self, uid):
- """Retrieve list of key pairs"""
- attrs = self.__find_objects(self.__uid_to_dn(uid),
- '(objectclass=novaKeyPair)')
- return [self.__to_key_pair(uid, attr) for attr in attrs]
-
def get_projects(self, uid=None):
"""Retrieve list of projects"""
pattern = '(objectclass=novaProject)'
@@ -154,21 +141,6 @@ class LdapDriver(object):
self.conn.add_s(self.__uid_to_dn(name), attr)
return self.__to_user(dict(attr))
- def create_key_pair(self, uid, key_name, public_key, fingerprint):
- """Create a key pair"""
- # TODO(vish): possibly refactor this to store keys in their own ou
- # and put dn reference in the user object
- attr = [
- ('objectclass', ['novaKeyPair']),
- ('cn', [key_name]),
- ('sshPublicKey', [public_key]),
- ('keyFingerprint', [fingerprint]),
- ]
- self.conn.add_s('cn=%s,%s' % (key_name,
- self.__uid_to_dn(uid)),
- attr)
- return self.__to_key_pair(uid, dict(attr))
-
def create_project(self, name, manager_uid,
description=None, member_uids=None):
"""Create a project"""
@@ -283,19 +255,10 @@ class LdapDriver(object):
"""Delete a user"""
if not self.__user_exists(uid):
raise exception.NotFound("User %s doesn't exist" % uid)
- self.__delete_key_pairs(uid)
self.__remove_from_all(uid)
self.conn.delete_s('uid=%s,%s' % (uid,
FLAGS.ldap_user_subtree))
- def delete_key_pair(self, uid, key_name):
- """Delete a key pair"""
- if not self.__key_pair_exists(uid, key_name):
- raise exception.NotFound("Key Pair %s doesn't exist for user %s" %
- (key_name, uid))
- self.conn.delete_s('cn=%s,uid=%s,%s' % (key_name, uid,
- FLAGS.ldap_user_subtree))
-
def delete_project(self, project_id):
"""Delete a project"""
project_dn = 'cn=%s,%s' % (project_id, FLAGS.ldap_project_subtree)
@@ -306,10 +269,6 @@ class LdapDriver(object):
"""Check if user exists"""
return self.get_user(uid) != None
- def __key_pair_exists(self, uid, key_name):
- """Check if key pair exists"""
- return self.get_key_pair(uid, key_name) != None
-
def __project_exists(self, project_id):
"""Check if project exists"""
return self.get_project(project_id) != None
@@ -359,13 +318,6 @@ class LdapDriver(object):
"""Check if group exists"""
return self.__find_object(dn, '(objectclass=groupOfNames)') != None
- def __delete_key_pairs(self, uid):
- """Delete all key pairs for user"""
- keys = self.get_key_pairs(uid)
- if keys != None:
- for key in keys:
- self.delete_key_pair(uid, key['name'])
-
@staticmethod
def __role_to_dn(role, project_id=None):
"""Convert role to corresponding dn"""
@@ -490,18 +442,6 @@ class LdapDriver(object):
'secret': attr['secretKey'][0],
'admin': (attr['isAdmin'][0] == 'TRUE')}
- @staticmethod
- def __to_key_pair(owner, attr):
- """Convert ldap attributes to KeyPair object"""
- if attr == None:
- return None
- return {
- 'id': attr['cn'][0],
- 'name': attr['cn'][0],
- 'owner_id': owner,
- 'public_key': attr['sshPublicKey'][0],
- 'fingerprint': attr['keyFingerprint'][0]}
-
def __to_project(self, attr):
"""Convert ldap attributes to Project object"""
if attr == None:
diff --git a/nova/auth/manager.py b/nova/auth/manager.py
index c4efc03de..bc3a8a12e 100644
--- a/nova/auth/manager.py
+++ b/nova/auth/manager.py
@@ -128,24 +128,6 @@ class User(AuthBase):
def is_project_manager(self, project):
return AuthManager().is_project_manager(self, project)
- def generate_key_pair(self, name):
- return AuthManager().generate_key_pair(self.id, name)
-
- def create_key_pair(self, name, public_key, fingerprint):
- return AuthManager().create_key_pair(self.id,
- name,
- public_key,
- fingerprint)
-
- def get_key_pair(self, name):
- return AuthManager().get_key_pair(self.id, name)
-
- def delete_key_pair(self, name):
- return AuthManager().delete_key_pair(self.id, name)
-
- def get_key_pairs(self):
- return AuthManager().get_key_pairs(self.id)
-
def __repr__(self):
return "User('%s', '%s', '%s', '%s', %s)" % (self.id,
self.name,
@@ -154,29 +136,6 @@ class User(AuthBase):
self.admin)
-class KeyPair(AuthBase):
- """Represents an ssh key returned from the datastore
-
- Even though this object is named KeyPair, only the public key and
- fingerprint is stored. The user's private key is not saved.
- """
-
- def __init__(self, id, name, owner_id, public_key, fingerprint):
- AuthBase.__init__(self)
- self.id = id
- self.name = name
- self.owner_id = owner_id
- self.public_key = public_key
- self.fingerprint = fingerprint
-
- def __repr__(self):
- return "KeyPair('%s', '%s', '%s', '%s', '%s')" % (self.id,
- self.name,
- self.owner_id,
- self.public_key,
- self.fingerprint)
-
-
class Project(AuthBase):
"""Represents a Project returned from the datastore"""
@@ -663,67 +622,13 @@ class AuthManager(object):
return User(**user_dict)
def delete_user(self, user):
- """Deletes a user"""
- with self.driver() as drv:
- drv.delete_user(User.safe_id(user))
-
- def generate_key_pair(self, user, key_name):
- """Generates a key pair for a user
+ """Deletes a user
- Generates a public and private key, stores the public key using the
- key_name, and returns the private key and fingerprint.
-
- @type user: User or uid
- @param user: User for which to create key pair.
-
- @type key_name: str
- @param key_name: Name to use for the generated KeyPair.
-
- @rtype: tuple (private_key, fingerprint)
- @return: A tuple containing the private_key and fingerprint.
- """
- # NOTE(vish): generating key pair is slow so check for legal
- # creation before creating keypair
+ Additionally deletes all users key_pairs"""
uid = User.safe_id(user)
+ db.key_pair_destroy_all_by_user(None, uid)
with self.driver() as drv:
- if not drv.get_user(uid):
- raise exception.NotFound("User %s doesn't exist" % user)
- if drv.get_key_pair(uid, key_name):
- raise exception.Duplicate("The keypair %s already exists"
- % key_name)
- private_key, public_key, fingerprint = crypto.generate_key_pair()
- self.create_key_pair(uid, key_name, public_key, fingerprint)
- return private_key, fingerprint
-
- def create_key_pair(self, user, key_name, public_key, fingerprint):
- """Creates a key pair for user"""
- with self.driver() as drv:
- kp_dict = drv.create_key_pair(User.safe_id(user),
- key_name,
- public_key,
- fingerprint)
- if kp_dict:
- return KeyPair(**kp_dict)
-
- def get_key_pair(self, user, key_name):
- """Retrieves a key pair for user"""
- with self.driver() as drv:
- kp_dict = drv.get_key_pair(User.safe_id(user), key_name)
- if kp_dict:
- return KeyPair(**kp_dict)
-
- def get_key_pairs(self, user):
- """Retrieves all key pairs for user"""
- with self.driver() as drv:
- kp_list = drv.get_key_pairs(User.safe_id(user))
- if not kp_list:
- return []
- return [KeyPair(**kp_dict) for kp_dict in kp_list]
-
- def delete_key_pair(self, user, key_name):
- """Deletes a key pair for user"""
- with self.driver() as drv:
- drv.delete_key_pair(User.safe_id(user), key_name)
+ drv.delete_user(uid)
def get_credentials(self, user, project=None):
"""Get credential zip for user in project"""
diff --git a/nova/cloudpipe/pipelib.py b/nova/cloudpipe/pipelib.py
index 2867bcb21..de6a97fb6 100644
--- a/nova/cloudpipe/pipelib.py
+++ b/nova/cloudpipe/pipelib.py
@@ -58,7 +58,7 @@ class CloudPipe(object):
z.write(FLAGS.boot_script_template,'autorun.sh')
z.close()
- key_name = self.setup_keypair(project.project_manager_id, project_id)
+ key_name = self.setup_key_pair(project.project_manager_id, project_id)
zippy = open(zippath, "r")
context = api.APIRequestContext(handler=None, user=project.project_manager, project=project)
@@ -74,7 +74,7 @@ class CloudPipe(object):
security_groups=["vpn-secgroup"])
zippy.close()
- def setup_keypair(self, user_id, project_id):
+ def setup_key_pair(self, user_id, project_id):
key_name = '%s%s' % (project_id, FLAGS.vpn_key_suffix)
try:
private_key, fingerprint = self.manager.generate_key_pair(user_id, key_name)
diff --git a/nova/crypto.py b/nova/crypto.py
index b05548ea1..1c6fe57ad 100644
--- a/nova/crypto.py
+++ b/nova/crypto.py
@@ -18,7 +18,7 @@
"""
Wrappers around standard crypto, including root and intermediate CAs,
-SSH keypairs and x509 certificates.
+SSH key_pairs and x509 certificates.
"""
import base64
diff --git a/nova/db/api.py b/nova/db/api.py
index 9f6ff99c3..8e418f9f0 100644
--- a/nova/db/api.py
+++ b/nova/db/api.py
@@ -296,6 +296,34 @@ def instance_update(context, instance_id, values):
return IMPL.instance_update(context, instance_id, values)
+###################
+
+
+def key_pair_create(context, values):
+ """Create a key_pair from the values dictionary."""
+ return IMPL.key_pair_create(context, values)
+
+
+def key_pair_destroy(context, user_id, name):
+ """Destroy the key_pair or raise if it does not exist."""
+ return IMPL.key_pair_destroy(context, user_id, name)
+
+
+def key_pair_destroy_all_by_user(context, user_id):
+ """Destroy all key_pairs by user."""
+ return IMPL.key_pair_destroy_all_by_user(context, user_id)
+
+
+def key_pair_get(context, user_id, name):
+ """Get a key_pair or raise if it does not exist."""
+ return IMPL.key_pair_get(context, user_id, name)
+
+
+def key_pair_get_all_by_user(context, user_id):
+ """Get all key_pairs by user."""
+ return IMPL.key_pair_get_all_by_user(context, user_id)
+
+
####################
diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py
index d612fe669..30c550105 100644
--- a/nova/db/sqlalchemy/api.py
+++ b/nova/db/sqlalchemy/api.py
@@ -462,6 +462,46 @@ def instance_update(_context, instance_id, values):
###################
+def key_pair_create(_context, values):
+ key_pair_ref = models.KeyPair()
+ for (key, value) in values.iteritems():
+ key_pair_ref[key] = value
+ key_pair_ref.save()
+ return key_pair_ref
+
+
+def key_pair_destroy(_context, user_id, name):
+ session = get_session()
+ with session.begin():
+ key_pair_ref = models.KeyPair.find_by_args(user_id,
+ name,
+ session=session)
+ key_pair_ref.delete(session=session)
+
+
+def key_pair_destroy_all_by_user(_context, user_id):
+ session = get_session()
+ with session.begin():
+ # TODO(vish): do we have to use sql here?
+ session.execute('update key_pairs set deleted=1 where user_id=:id',
+ {'id': user_id})
+
+
+def key_pair_get(_context, user_id, name):
+ return models.KeyPair.find_by_args(user_id, name)
+
+
+def key_pair_get_all_by_user(_context, user_id):
+ session = get_session()
+ return session.query(models.KeyPair
+ ).filter_by(user_id=user_id
+ ).filter_by(deleted=False
+ ).all()
+
+
+###################
+
+
def network_count(_context):
return models.Network.count()
diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py
index 41013f41b..f62b79af8 100644
--- a/nova/db/sqlalchemy/models.py
+++ b/nova/db/sqlalchemy/models.py
@@ -323,6 +323,42 @@ class ExportDevice(BASE, NovaBase):
uselist=False))
+class KeyPair(BASE, NovaBase):
+ """Represents a public key pair for ssh"""
+ __tablename__ = 'key_pairs'
+ id = Column(Integer, primary_key=True)
+ name = Column(String(255))
+
+ user_id = Column(String(255))
+
+ fingerprint = Column(String(255))
+ public_key = Column(Text)
+
+ @property
+ def str_id(self):
+ return '%s.%s' % (self.user_id, self.name)
+
+ @classmethod
+ def find_by_str(cls, str_id, session=None, deleted=False):
+ user_id, _sep, name = str_id.partition('.')
+ return cls.find_by_str(user_id, name, session, deleted)
+
+ @classmethod
+ def find_by_args(cls, user_id, name, session=None, deleted=False):
+ if not session:
+ session = get_session()
+ try:
+ return session.query(cls
+ ).filter_by(user_id=user_id
+ ).filter_by(name=name
+ ).filter_by(deleted=deleted
+ ).one()
+ except exc.NoResultFound:
+ new_exc = exception.NotFound("No model for user %s, name %s" %
+ (user_id, name))
+ raise new_exc.__class__, new_exc, sys.exc_info()[2]
+
+
class Network(BASE, NovaBase):
"""Represents a network"""
__tablename__ = 'networks'
diff --git a/nova/endpoint/cloud.py b/nova/endpoint/cloud.py
index 206a88c72..28aee37d2 100644
--- a/nova/endpoint/cloud.py
+++ b/nova/endpoint/cloud.py
@@ -30,6 +30,7 @@ import time
from twisted.internet import defer
+from nova import crypto
from nova import db
from nova import exception
from nova import flags
@@ -37,7 +38,6 @@ from nova import quota
from nova import rpc
from nova import utils
from nova.auth import rbac
-from nova.auth import manager
from nova.compute.instance_types import INSTANCE_TYPES
from nova.endpoint import images
@@ -51,14 +51,30 @@ class QuotaError(exception.ApiError):
pass
-def _gen_key(user_id, key_name):
- """ Tuck this into AuthManager """
+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."""
try:
- mgr = manager.AuthManager()
- private_key, fingerprint = mgr.generate_key_pair(user_id, key_name)
+ # 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.Duplicate("The key_pair %s already exists"
+ % key_name)
+ except exception.NotFound:
+ pass
+ 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}
except Exception as ex:
return {'exception': ex}
- return {'private_key': private_key, 'fingerprint': fingerprint}
class CloudController(object):
@@ -194,18 +210,18 @@ class CloudController(object):
@rbac.allow('all')
def describe_key_pairs(self, context, key_name=None, **kwargs):
- key_pairs = context.user.get_key_pairs()
+ key_pairs = db.key_pair_get_all_by_user(context, context.user.id)
if not key_name is None:
- key_pairs = [x for x in key_pairs if x.name in key_name]
+ key_pairs = [x for x in key_pairs if x['name'] in key_name]
result = []
for key_pair in key_pairs:
# filter out the vpn keys
suffix = FLAGS.vpn_key_suffix
- if context.user.is_admin() or not key_pair.name.endswith(suffix):
+ if context.user.is_admin() or not key_pair['name'].endswith(suffix):
result.append({
- 'keyName': key_pair.name,
- 'keyFingerprint': key_pair.fingerprint,
+ 'keyName': key_pair['name'],
+ 'keyFingerprint': key_pair['fingerprint'],
})
return {'keypairsSet': result}
@@ -221,14 +237,18 @@ class CloudController(object):
dcall.callback({'keyName': key_name,
'keyFingerprint': kwargs['fingerprint'],
'keyMaterial': kwargs['private_key']})
- pool.apply_async(_gen_key, [context.user.id, key_name],
+ # TODO(vish): when context is no longer an object, pass it here
+ pool.apply_async(_gen_key, [None, context.user.id, key_name],
callback=_complete)
return dcall
@rbac.allow('all')
def delete_key_pair(self, context, key_name, **kwargs):
- context.user.delete_key_pair(key_name)
- # aws returns true even if the key doens't exist
+ try:
+ db.key_pair_destroy(context, context.user.id, key_name)
+ except exception.NotFound:
+ # aws returns true even if the key doesn't exist
+ pass
return True
@rbac.allow('all')
@@ -576,11 +596,10 @@ class CloudController(object):
launch_time = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())
key_data = None
if kwargs.has_key('key_name'):
- key_pair = context.user.get_key_pair(kwargs['key_name'])
- if not key_pair:
- raise exception.ApiError('Key Pair %s not found' %
- kwargs['key_name'])
- key_data = key_pair.public_key
+ key_pair_ref = db.key_pair_get(context,
+ context.user.id,
+ kwargs['key_name'])
+ key_data = key_pair_ref['public_key']
# TODO: Get the real security group of launch in here
security_group = "default"
diff --git a/nova/tests/api_unittest.py b/nova/tests/api_unittest.py
index 462d1b295..fdb9e21d8 100644
--- a/nova/tests/api_unittest.py
+++ b/nova/tests/api_unittest.py
@@ -41,8 +41,8 @@ FLAGS = flags.FLAGS
# it's pretty damn circuitous so apologies if you have to fix
# a bug in it
# NOTE(jaypipes) The pylint disables here are for R0913 (too many args) which
-# isn't controllable since boto's HTTPRequest needs that many
-# args, and for the version-differentiated import of tornado's
+# isn't controllable since boto's HTTPRequest needs that many
+# args, and for the version-differentiated import of tornado's
# httputil.
# NOTE(jaypipes): The disable-msg=E1101 and E1103 below is because pylint is
# unable to introspect the deferred's return value properly
@@ -224,7 +224,8 @@ class ApiEc2TestCase(test.BaseTestCase):
for x in range(random.randint(4, 8)))
user = self.manager.create_user('fake', 'fake', 'fake')
project = self.manager.create_project('fake', 'fake', 'fake')
- self.manager.generate_key_pair(user.id, keyname)
+ # NOTE(vish): create depends on pool, so call helper directly
+ cloud._gen_key(None, user.id, keyname)
rv = self.ec2.get_all_key_pairs()
results = [k for k in rv if k.name == keyname]
diff --git a/nova/tests/auth_unittest.py b/nova/tests/auth_unittest.py
index c19f5a9b4..cbf7b22e2 100644
--- a/nova/tests/auth_unittest.py
+++ b/nova/tests/auth_unittest.py
@@ -17,8 +17,6 @@
# under the License.
import logging
-from M2Crypto import BIO
-from M2Crypto import RSA
from M2Crypto import X509
import unittest
@@ -65,35 +63,6 @@ class AuthTestCase(test.BaseTestCase):
'export S3_URL="http://127.0.0.1:3333/"\n' +
'export EC2_USER_ID="test1"\n')
- def test_006_test_key_storage(self):
- user = self.manager.get_user('test1')
- user.create_key_pair('public', 'key', 'fingerprint')
- key = user.get_key_pair('public')
- self.assertEqual('key', key.public_key)
- self.assertEqual('fingerprint', key.fingerprint)
-
- def test_007_test_key_generation(self):
- user = self.manager.get_user('test1')
- private_key, fingerprint = user.generate_key_pair('public2')
- key = RSA.load_key_string(private_key, callback=lambda: None)
- bio = BIO.MemoryBuffer()
- public_key = user.get_key_pair('public2').public_key
- key.save_pub_key_bio(bio)
- converted = crypto.ssl_pub_to_ssh_pub(bio.read())
- # assert key fields are equal
- self.assertEqual(public_key.split(" ")[1].strip(),
- converted.split(" ")[1].strip())
-
- def test_008_can_list_key_pairs(self):
- keys = self.manager.get_user('test1').get_key_pairs()
- self.assertTrue(filter(lambda k: k.name == 'public', keys))
- self.assertTrue(filter(lambda k: k.name == 'public2', keys))
-
- def test_009_can_delete_key_pair(self):
- self.manager.get_user('test1').delete_key_pair('public')
- keys = self.manager.get_user('test1').get_key_pairs()
- self.assertFalse(filter(lambda k: k.name == 'public', keys))
-
def test_010_can_list_users(self):
users = self.manager.get_users()
logging.warn(users)
diff --git a/nova/tests/cloud_unittest.py b/nova/tests/cloud_unittest.py
index c36d5a34f..317200e01 100644
--- a/nova/tests/cloud_unittest.py
+++ b/nova/tests/cloud_unittest.py
@@ -17,13 +17,18 @@
# under the License.
import logging
+from M2Crypto import BIO
+from M2Crypto import RSA
import StringIO
import time
+
from tornado import ioloop
from twisted.internet import defer
import unittest
from xml.etree import ElementTree
+from nova import crypto
+from nova import db
from nova import flags
from nova import rpc
from nova import test
@@ -55,16 +60,21 @@ class CloudTestCase(test.BaseTestCase):
proxy=self.compute)
self.injected.append(self.compute_consumer.attach_to_tornado(self.ioloop))
- try:
- manager.AuthManager().create_user('admin', 'admin', 'admin')
- except: pass
- admin = manager.AuthManager().get_user('admin')
- project = manager.AuthManager().create_project('proj', 'admin', 'proj')
- self.context = api.APIRequestContext(handler=None,project=project,user=admin)
+ self.manager = manager.AuthManager()
+ self.user = self.manager.create_user('admin', 'admin', 'admin', True)
+ self.project = self.manager.create_project('proj', 'admin', 'proj')
+ self.context = api.APIRequestContext(handler=None,
+ user=self.user,
+ project=self.project)
def tearDown(self):
- manager.AuthManager().delete_project('proj')
- manager.AuthManager().delete_user('admin')
+ self.manager.delete_project(self.project)
+ self.manager.delete_user(self.user)
+ super(CloudTestCase, self).setUp()
+
+ def _create_key(self, name):
+ # NOTE(vish): create depends on pool, so just call helper directly
+ return cloud._gen_key(self.context, self.context.user.id, name)
def test_console_output(self):
if FLAGS.connection_type == 'fake':
@@ -77,6 +87,33 @@ class CloudTestCase(test.BaseTestCase):
self.assert_(output)
rv = yield self.compute.terminate_instance(instance_id)
+
+ def test_key_generation(self):
+ result = self._create_key('test')
+ private_key = result['private_key']
+ key = RSA.load_key_string(private_key, callback=lambda: None)
+ bio = BIO.MemoryBuffer()
+ public_key = db.key_pair_get(self.context,
+ self.context.user.id,
+ 'test')['public_key']
+ key.save_pub_key_bio(bio)
+ converted = crypto.ssl_pub_to_ssh_pub(bio.read())
+ # assert key fields are equal
+ self.assertEqual(public_key.split(" ")[1].strip(),
+ converted.split(" ")[1].strip())
+
+ def test_describe_key_pairs(self):
+ self._create_key('test1')
+ self._create_key('test2')
+ result = self.cloud.describe_key_pairs(self.context)
+ keys = result["keypairsSet"]
+ self.assertTrue(filter(lambda k: k['keyName'] == 'test1', keys))
+ self.assertTrue(filter(lambda k: k['keyName'] == 'test2', keys))
+
+ def test_delete_key_pair(self):
+ self._create_key('test')
+ self.cloud.delete_key_pair(self.context, 'test')
+
def test_run_instances(self):
if FLAGS.connection_type == 'fake':
logging.debug("Can't test instances without a real virtual env.")