Merge trunk
This commit is contained in:
10
.bzrignore
10
.bzrignore
@@ -1,3 +1,13 @@
|
|||||||
run_tests.err.log
|
run_tests.err.log
|
||||||
.nova-venv
|
.nova-venv
|
||||||
ChangeLog
|
ChangeLog
|
||||||
|
_trial_temp
|
||||||
|
keys
|
||||||
|
networks
|
||||||
|
nova.sqlite
|
||||||
|
CA/cacert.pem
|
||||||
|
CA/index.txt*
|
||||||
|
CA/openssl.cnf
|
||||||
|
CA/serial*
|
||||||
|
CA/newcerts/*.pem
|
||||||
|
CA/private/cakey.pem
|
||||||
|
|||||||
4
Authors
4
Authors
@@ -3,6 +3,7 @@ Anne Gentle <anne@openstack.org>
|
|||||||
Anthony Young <sleepsonthefloor@gmail.com>
|
Anthony Young <sleepsonthefloor@gmail.com>
|
||||||
Armando Migliaccio <Armando.Migliaccio@eu.citrix.com>
|
Armando Migliaccio <Armando.Migliaccio@eu.citrix.com>
|
||||||
Chris Behrens <cbehrens@codestud.com>
|
Chris Behrens <cbehrens@codestud.com>
|
||||||
|
Chmouel Boudjnah <chmouel@chmouel.com>
|
||||||
Dean Troyer <dtroyer@gmail.com>
|
Dean Troyer <dtroyer@gmail.com>
|
||||||
Devin Carlen <devin.carlen@gmail.com>
|
Devin Carlen <devin.carlen@gmail.com>
|
||||||
Eric Day <eday@oddments.org>
|
Eric Day <eday@oddments.org>
|
||||||
@@ -20,8 +21,11 @@ Michael Gundlach <michael.gundlach@rackspace.com>
|
|||||||
Monty Taylor <mordred@inaugust.com>
|
Monty Taylor <mordred@inaugust.com>
|
||||||
Paul Voccio <paul@openstack.org>
|
Paul Voccio <paul@openstack.org>
|
||||||
Rick Clark <rick@openstack.org>
|
Rick Clark <rick@openstack.org>
|
||||||
|
Ryan Lucio <rlucio@internap.com>
|
||||||
|
Sandy Walsh <sandy.walsh@rackspace.com>
|
||||||
Soren Hansen <soren.hansen@rackspace.com>
|
Soren Hansen <soren.hansen@rackspace.com>
|
||||||
Todd Willey <todd@ansolabs.com>
|
Todd Willey <todd@ansolabs.com>
|
||||||
|
Trey Morris <trey.morris@rackspace.com>
|
||||||
Vishvananda Ishaya <vishvananda@gmail.com>
|
Vishvananda Ishaya <vishvananda@gmail.com>
|
||||||
Youcef Laribi <Youcef.Laribi@eu.citrix.com>
|
Youcef Laribi <Youcef.Laribi@eu.citrix.com>
|
||||||
Zhixue Wu <Zhixue.Wu@citrix.com>
|
Zhixue Wu <Zhixue.Wu@citrix.com>
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ from nova import utils
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
utils.default_flagfile()
|
||||||
twistd.serve(__file__)
|
twistd.serve(__file__)
|
||||||
|
|
||||||
if __name__ == '__builtin__':
|
if __name__ == '__builtin__':
|
||||||
utils.default_flagfile()
|
|
||||||
application = service.Service.create() # pylint: disable=C0103
|
application = service.Service.create() # pylint: disable=C0103
|
||||||
|
|||||||
@@ -42,10 +42,10 @@ logging.getLogger('boto').setLevel(logging.WARN)
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
utils.default_flagfile()
|
||||||
twistd.serve(__file__)
|
twistd.serve(__file__)
|
||||||
|
|
||||||
if __name__ == '__builtin__':
|
if __name__ == '__builtin__':
|
||||||
utils.default_flagfile()
|
|
||||||
logging.warn('Starting instance monitor')
|
logging.warn('Starting instance monitor')
|
||||||
# pylint: disable-msg=C0103
|
# pylint: disable-msg=C0103
|
||||||
monitor = monitor.InstanceMonitor()
|
monitor = monitor.InstanceMonitor()
|
||||||
|
|||||||
@@ -359,9 +359,14 @@ class ProjectCommands(object):
|
|||||||
def zipfile(self, project_id, user_id, filename='nova.zip'):
|
def zipfile(self, project_id, user_id, filename='nova.zip'):
|
||||||
"""Exports credentials for project to a zip file
|
"""Exports credentials for project to a zip file
|
||||||
arguments: project_id user_id [filename='nova.zip]"""
|
arguments: project_id user_id [filename='nova.zip]"""
|
||||||
zip_file = self.manager.get_credentials(user_id, project_id)
|
try:
|
||||||
with open(filename, 'w') as f:
|
zip_file = self.manager.get_credentials(user_id, project_id)
|
||||||
f.write(zip_file)
|
with open(filename, 'w') as f:
|
||||||
|
f.write(zip_file)
|
||||||
|
except db.api.NoMoreNetworks:
|
||||||
|
print ('No more networks available. If this is a new '
|
||||||
|
'installation, you need\nto call something like this:\n\n'
|
||||||
|
' nova-manage network create 10.0.0.0/8 10 64\n\n')
|
||||||
|
|
||||||
|
|
||||||
class FloatingIpCommands(object):
|
class FloatingIpCommands(object):
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ from nova import utils
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
utils.default_flagfile()
|
||||||
twistd.serve(__file__)
|
twistd.serve(__file__)
|
||||||
|
|
||||||
if __name__ == '__builtin__':
|
if __name__ == '__builtin__':
|
||||||
utils.default_flagfile()
|
|
||||||
application = service.Service.create() # pylint: disable-msg=C0103
|
application = service.Service.create() # pylint: disable-msg=C0103
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ FLAGS = flags.FLAGS
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
utils.default_flagfile()
|
||||||
twistd.serve(__file__)
|
twistd.serve(__file__)
|
||||||
|
|
||||||
if __name__ == '__builtin__':
|
if __name__ == '__builtin__':
|
||||||
utils.default_flagfile()
|
|
||||||
application = handler.get_application() # pylint: disable-msg=C0103
|
application = handler.get_application() # pylint: disable-msg=C0103
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ from nova import utils
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
utils.default_flagfile()
|
||||||
twistd.serve(__file__)
|
twistd.serve(__file__)
|
||||||
|
|
||||||
if __name__ == '__builtin__':
|
if __name__ == '__builtin__':
|
||||||
utils.default_flagfile()
|
|
||||||
application = service.Service.create()
|
application = service.Service.create()
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ from nova import utils
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
utils.default_flagfile()
|
||||||
twistd.serve(__file__)
|
twistd.serve(__file__)
|
||||||
|
|
||||||
if __name__ == '__builtin__':
|
if __name__ == '__builtin__':
|
||||||
utils.default_flagfile()
|
|
||||||
application = service.Service.create() # pylint: disable-msg=C0103
|
application = service.Service.create() # pylint: disable-msg=C0103
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ flags.DEFINE_string('ldap_user_dn', 'cn=Manager,dc=example,dc=com',
|
|||||||
flags.DEFINE_string('ldap_user_unit', 'Users', 'OID for Users')
|
flags.DEFINE_string('ldap_user_unit', 'Users', 'OID for Users')
|
||||||
flags.DEFINE_string('ldap_user_subtree', 'ou=Users,dc=example,dc=com',
|
flags.DEFINE_string('ldap_user_subtree', 'ou=Users,dc=example,dc=com',
|
||||||
'OU for Users')
|
'OU for Users')
|
||||||
|
flags.DEFINE_boolean('ldap_user_modify_only', False,
|
||||||
|
'Modify attributes for users instead of creating/deleting')
|
||||||
flags.DEFINE_string('ldap_project_subtree', 'ou=Groups,dc=example,dc=com',
|
flags.DEFINE_string('ldap_project_subtree', 'ou=Groups,dc=example,dc=com',
|
||||||
'OU for Projects')
|
'OU for Projects')
|
||||||
flags.DEFINE_string('role_project_subtree', 'ou=Groups,dc=example,dc=com',
|
flags.DEFINE_string('role_project_subtree', 'ou=Groups,dc=example,dc=com',
|
||||||
@@ -89,8 +91,7 @@ class LdapDriver(object):
|
|||||||
|
|
||||||
def get_user(self, uid):
|
def get_user(self, uid):
|
||||||
"""Retrieve user by id"""
|
"""Retrieve user by id"""
|
||||||
attr = self.__find_object(self.__uid_to_dn(uid),
|
attr = self.__get_ldap_user(uid)
|
||||||
'(objectclass=novaUser)')
|
|
||||||
return self.__to_user(attr)
|
return self.__to_user(attr)
|
||||||
|
|
||||||
def get_user_from_access_key(self, access):
|
def get_user_from_access_key(self, access):
|
||||||
@@ -110,7 +111,12 @@ class LdapDriver(object):
|
|||||||
"""Retrieve list of users"""
|
"""Retrieve list of users"""
|
||||||
attrs = self.__find_objects(FLAGS.ldap_user_subtree,
|
attrs = self.__find_objects(FLAGS.ldap_user_subtree,
|
||||||
'(objectclass=novaUser)')
|
'(objectclass=novaUser)')
|
||||||
return [self.__to_user(attr) for attr in attrs]
|
users = []
|
||||||
|
for attr in attrs:
|
||||||
|
user = self.__to_user(attr)
|
||||||
|
if user is not None:
|
||||||
|
users.append(user)
|
||||||
|
return users
|
||||||
|
|
||||||
def get_projects(self, uid=None):
|
def get_projects(self, uid=None):
|
||||||
"""Retrieve list of projects"""
|
"""Retrieve list of projects"""
|
||||||
@@ -125,21 +131,52 @@ class LdapDriver(object):
|
|||||||
"""Create a user"""
|
"""Create a user"""
|
||||||
if self.__user_exists(name):
|
if self.__user_exists(name):
|
||||||
raise exception.Duplicate("LDAP user %s already exists" % name)
|
raise exception.Duplicate("LDAP user %s already exists" % name)
|
||||||
attr = [
|
if FLAGS.ldap_user_modify_only:
|
||||||
('objectclass', ['person',
|
if self.__ldap_user_exists(name):
|
||||||
'organizationalPerson',
|
# Retrieve user by name
|
||||||
'inetOrgPerson',
|
user = self.__get_ldap_user(name)
|
||||||
'novaUser']),
|
# Entry could be malformed, test for missing attrs.
|
||||||
('ou', [FLAGS.ldap_user_unit]),
|
# Malformed entries are useless, replace attributes found.
|
||||||
('uid', [name]),
|
attr = []
|
||||||
('sn', [name]),
|
if 'secretKey' in user.keys():
|
||||||
('cn', [name]),
|
attr.append((self.ldap.MOD_REPLACE, 'secretKey', \
|
||||||
('secretKey', [secret_key]),
|
[secret_key]))
|
||||||
('accessKey', [access_key]),
|
else:
|
||||||
('isAdmin', [str(is_admin).upper()]),
|
attr.append((self.ldap.MOD_ADD, 'secretKey', \
|
||||||
]
|
[secret_key]))
|
||||||
self.conn.add_s(self.__uid_to_dn(name), attr)
|
if 'accessKey' in user.keys():
|
||||||
return self.__to_user(dict(attr))
|
attr.append((self.ldap.MOD_REPLACE, 'accessKey', \
|
||||||
|
[access_key]))
|
||||||
|
else:
|
||||||
|
attr.append((self.ldap.MOD_ADD, 'accessKey', \
|
||||||
|
[access_key]))
|
||||||
|
if 'isAdmin' in user.keys():
|
||||||
|
attr.append((self.ldap.MOD_REPLACE, 'isAdmin', \
|
||||||
|
[str(is_admin).upper()]))
|
||||||
|
else:
|
||||||
|
attr.append((self.ldap.MOD_ADD, 'isAdmin', \
|
||||||
|
[str(is_admin).upper()]))
|
||||||
|
self.conn.modify_s(self.__uid_to_dn(name), attr)
|
||||||
|
return self.get_user(name)
|
||||||
|
else:
|
||||||
|
raise exception.NotFound("LDAP object for %s doesn't exist"
|
||||||
|
% name)
|
||||||
|
else:
|
||||||
|
attr = [
|
||||||
|
('objectclass', ['person',
|
||||||
|
'organizationalPerson',
|
||||||
|
'inetOrgPerson',
|
||||||
|
'novaUser']),
|
||||||
|
('ou', [FLAGS.ldap_user_unit]),
|
||||||
|
('uid', [name]),
|
||||||
|
('sn', [name]),
|
||||||
|
('cn', [name]),
|
||||||
|
('secretKey', [secret_key]),
|
||||||
|
('accessKey', [access_key]),
|
||||||
|
('isAdmin', [str(is_admin).upper()]),
|
||||||
|
]
|
||||||
|
self.conn.add_s(self.__uid_to_dn(name), attr)
|
||||||
|
return self.__to_user(dict(attr))
|
||||||
|
|
||||||
def create_project(self, name, manager_uid,
|
def create_project(self, name, manager_uid,
|
||||||
description=None, member_uids=None):
|
description=None, member_uids=None):
|
||||||
@@ -155,7 +192,7 @@ class LdapDriver(object):
|
|||||||
if description is None:
|
if description is None:
|
||||||
description = name
|
description = name
|
||||||
members = []
|
members = []
|
||||||
if member_uids != None:
|
if member_uids is not None:
|
||||||
for member_uid in member_uids:
|
for member_uid in member_uids:
|
||||||
if not self.__user_exists(member_uid):
|
if not self.__user_exists(member_uid):
|
||||||
raise exception.NotFound("Project can't be created "
|
raise exception.NotFound("Project can't be created "
|
||||||
@@ -256,7 +293,24 @@ class LdapDriver(object):
|
|||||||
if not self.__user_exists(uid):
|
if not self.__user_exists(uid):
|
||||||
raise exception.NotFound("User %s doesn't exist" % uid)
|
raise exception.NotFound("User %s doesn't exist" % uid)
|
||||||
self.__remove_from_all(uid)
|
self.__remove_from_all(uid)
|
||||||
self.conn.delete_s(self.__uid_to_dn(uid))
|
if FLAGS.ldap_user_modify_only:
|
||||||
|
# Delete attributes
|
||||||
|
attr = []
|
||||||
|
# Retrieve user by name
|
||||||
|
user = self.__get_ldap_user(uid)
|
||||||
|
if 'secretKey' in user.keys():
|
||||||
|
attr.append((self.ldap.MOD_DELETE, 'secretKey', \
|
||||||
|
user['secretKey']))
|
||||||
|
if 'accessKey' in user.keys():
|
||||||
|
attr.append((self.ldap.MOD_DELETE, 'accessKey', \
|
||||||
|
user['accessKey']))
|
||||||
|
if 'isAdmin' in user.keys():
|
||||||
|
attr.append((self.ldap.MOD_DELETE, 'isAdmin', \
|
||||||
|
user['isAdmin']))
|
||||||
|
self.conn.modify_s(self.__uid_to_dn(uid), attr)
|
||||||
|
else:
|
||||||
|
# Delete entry
|
||||||
|
self.conn.delete_s(self.__uid_to_dn(uid))
|
||||||
|
|
||||||
def delete_project(self, project_id):
|
def delete_project(self, project_id):
|
||||||
"""Delete a project"""
|
"""Delete a project"""
|
||||||
@@ -265,7 +319,7 @@ class LdapDriver(object):
|
|||||||
self.__delete_group(project_dn)
|
self.__delete_group(project_dn)
|
||||||
|
|
||||||
def modify_user(self, uid, access_key=None, secret_key=None, admin=None):
|
def modify_user(self, uid, access_key=None, secret_key=None, admin=None):
|
||||||
"""Modify an existing project"""
|
"""Modify an existing user"""
|
||||||
if not access_key and not secret_key and admin is None:
|
if not access_key and not secret_key and admin is None:
|
||||||
return
|
return
|
||||||
attr = []
|
attr = []
|
||||||
@@ -279,11 +333,21 @@ class LdapDriver(object):
|
|||||||
|
|
||||||
def __user_exists(self, uid):
|
def __user_exists(self, uid):
|
||||||
"""Check if user exists"""
|
"""Check if user exists"""
|
||||||
return self.get_user(uid) != None
|
return self.get_user(uid) is not None
|
||||||
|
|
||||||
|
def __ldap_user_exists(self, uid):
|
||||||
|
"""Check if the user exists in ldap"""
|
||||||
|
return self.__get_ldap_user(uid) is not None
|
||||||
|
|
||||||
def __project_exists(self, project_id):
|
def __project_exists(self, project_id):
|
||||||
"""Check if project exists"""
|
"""Check if project exists"""
|
||||||
return self.get_project(project_id) != None
|
return self.get_project(project_id) is not None
|
||||||
|
|
||||||
|
def __get_ldap_user(self, uid):
|
||||||
|
"""Retrieve LDAP user entry by id"""
|
||||||
|
attr = self.__find_object(self.__uid_to_dn(uid),
|
||||||
|
'(objectclass=novaUser)')
|
||||||
|
return attr
|
||||||
|
|
||||||
def __find_object(self, dn, query=None, scope=None):
|
def __find_object(self, dn, query=None, scope=None):
|
||||||
"""Find an object by dn and query"""
|
"""Find an object by dn and query"""
|
||||||
@@ -330,12 +394,12 @@ class LdapDriver(object):
|
|||||||
|
|
||||||
def __group_exists(self, dn):
|
def __group_exists(self, dn):
|
||||||
"""Check if group exists"""
|
"""Check if group exists"""
|
||||||
return self.__find_object(dn, '(objectclass=groupOfNames)') != None
|
return self.__find_object(dn, '(objectclass=groupOfNames)') is not None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __role_to_dn(role, project_id=None):
|
def __role_to_dn(role, project_id=None):
|
||||||
"""Convert role to corresponding dn"""
|
"""Convert role to corresponding dn"""
|
||||||
if project_id == None:
|
if project_id is None:
|
||||||
return FLAGS.__getitem__("ldap_%s" % role).value
|
return FLAGS.__getitem__("ldap_%s" % role).value
|
||||||
else:
|
else:
|
||||||
return 'cn=%s,cn=%s,%s' % (role,
|
return 'cn=%s,cn=%s,%s' % (role,
|
||||||
@@ -349,7 +413,7 @@ class LdapDriver(object):
|
|||||||
raise exception.Duplicate("Group can't be created because "
|
raise exception.Duplicate("Group can't be created because "
|
||||||
"group %s already exists" % name)
|
"group %s already exists" % name)
|
||||||
members = []
|
members = []
|
||||||
if member_uids != None:
|
if member_uids is not None:
|
||||||
for member_uid in member_uids:
|
for member_uid in member_uids:
|
||||||
if not self.__user_exists(member_uid):
|
if not self.__user_exists(member_uid):
|
||||||
raise exception.NotFound("Group can't be created "
|
raise exception.NotFound("Group can't be created "
|
||||||
@@ -375,7 +439,7 @@ class LdapDriver(object):
|
|||||||
res = self.__find_object(group_dn,
|
res = self.__find_object(group_dn,
|
||||||
'(member=%s)' % self.__uid_to_dn(uid),
|
'(member=%s)' % self.__uid_to_dn(uid),
|
||||||
self.ldap.SCOPE_BASE)
|
self.ldap.SCOPE_BASE)
|
||||||
return res != None
|
return res is not None
|
||||||
|
|
||||||
def __add_to_group(self, uid, group_dn):
|
def __add_to_group(self, uid, group_dn):
|
||||||
"""Add user to group"""
|
"""Add user to group"""
|
||||||
@@ -447,18 +511,22 @@ class LdapDriver(object):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def __to_user(attr):
|
def __to_user(attr):
|
||||||
"""Convert ldap attributes to User object"""
|
"""Convert ldap attributes to User object"""
|
||||||
if attr == None:
|
if attr is None:
|
||||||
|
return None
|
||||||
|
if ('accessKey' in attr.keys() and 'secretKey' in attr.keys() \
|
||||||
|
and 'isAdmin' in attr.keys()):
|
||||||
|
return {
|
||||||
|
'id': attr['uid'][0],
|
||||||
|
'name': attr['cn'][0],
|
||||||
|
'access': attr['accessKey'][0],
|
||||||
|
'secret': attr['secretKey'][0],
|
||||||
|
'admin': (attr['isAdmin'][0] == 'TRUE')}
|
||||||
|
else:
|
||||||
return None
|
return None
|
||||||
return {
|
|
||||||
'id': attr['uid'][0],
|
|
||||||
'name': attr['cn'][0],
|
|
||||||
'access': attr['accessKey'][0],
|
|
||||||
'secret': attr['secretKey'][0],
|
|
||||||
'admin': (attr['isAdmin'][0] == 'TRUE')}
|
|
||||||
|
|
||||||
def __to_project(self, attr):
|
def __to_project(self, attr):
|
||||||
"""Convert ldap attributes to Project object"""
|
"""Convert ldap attributes to Project object"""
|
||||||
if attr == None:
|
if attr is None:
|
||||||
return None
|
return None
|
||||||
member_dns = attr.get('member', [])
|
member_dns = attr.get('member', [])
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -624,6 +624,10 @@ class AuthManager(object):
|
|||||||
with self.driver() as drv:
|
with self.driver() as drv:
|
||||||
drv.modify_user(uid, access_key, secret_key, admin)
|
drv.modify_user(uid, access_key, secret_key, admin)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_key_pairs(context):
|
||||||
|
return db.key_pair_get_all_by_user(context.elevated(), context.user_id)
|
||||||
|
|
||||||
def get_credentials(self, user, project=None):
|
def get_credentials(self, user, project=None):
|
||||||
"""Get credential zip for user in project"""
|
"""Get credential zip for user in project"""
|
||||||
if not isinstance(user, User):
|
if not isinstance(user, User):
|
||||||
|
|||||||
84
nova/auth/nova_openldap.schema
Normal file
84
nova/auth/nova_openldap.schema
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
#
|
||||||
|
# Person object for Nova
|
||||||
|
# inetorgperson with extra attributes
|
||||||
|
# Author: Vishvananda Ishaya <vishvananda@yahoo.com>
|
||||||
|
#
|
||||||
|
#
|
||||||
|
|
||||||
|
# using internet experimental oid arc as per BP64 3.1
|
||||||
|
objectidentifier novaSchema 1.3.6.1.3.1.666.666
|
||||||
|
objectidentifier novaAttrs novaSchema:3
|
||||||
|
objectidentifier novaOCs novaSchema:4
|
||||||
|
|
||||||
|
attributetype (
|
||||||
|
novaAttrs:1
|
||||||
|
NAME 'accessKey'
|
||||||
|
DESC 'Key for accessing data'
|
||||||
|
EQUALITY caseIgnoreMatch
|
||||||
|
SUBSTR caseIgnoreSubstringsMatch
|
||||||
|
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
|
||||||
|
SINGLE-VALUE
|
||||||
|
)
|
||||||
|
|
||||||
|
attributetype (
|
||||||
|
novaAttrs:2
|
||||||
|
NAME 'secretKey'
|
||||||
|
DESC 'Secret key'
|
||||||
|
EQUALITY caseIgnoreMatch
|
||||||
|
SUBSTR caseIgnoreSubstringsMatch
|
||||||
|
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
|
||||||
|
SINGLE-VALUE
|
||||||
|
)
|
||||||
|
|
||||||
|
attributetype (
|
||||||
|
novaAttrs:3
|
||||||
|
NAME 'keyFingerprint'
|
||||||
|
DESC 'Fingerprint of private key'
|
||||||
|
EQUALITY caseIgnoreMatch
|
||||||
|
SUBSTR caseIgnoreSubstringsMatch
|
||||||
|
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
|
||||||
|
SINGLE-VALUE
|
||||||
|
)
|
||||||
|
|
||||||
|
attributetype (
|
||||||
|
novaAttrs:4
|
||||||
|
NAME 'isAdmin'
|
||||||
|
DESC 'Is user an administrator?'
|
||||||
|
EQUALITY booleanMatch
|
||||||
|
SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
|
||||||
|
SINGLE-VALUE
|
||||||
|
)
|
||||||
|
|
||||||
|
attributetype (
|
||||||
|
novaAttrs:5
|
||||||
|
NAME 'projectManager'
|
||||||
|
DESC 'Project Managers of a project'
|
||||||
|
SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
|
||||||
|
)
|
||||||
|
|
||||||
|
objectClass (
|
||||||
|
novaOCs:1
|
||||||
|
NAME 'novaUser'
|
||||||
|
DESC 'access and secret keys'
|
||||||
|
AUXILIARY
|
||||||
|
MUST ( uid )
|
||||||
|
MAY ( accessKey $ secretKey $ isAdmin )
|
||||||
|
)
|
||||||
|
|
||||||
|
objectClass (
|
||||||
|
novaOCs:2
|
||||||
|
NAME 'novaKeyPair'
|
||||||
|
DESC 'Key pair for User'
|
||||||
|
SUP top
|
||||||
|
STRUCTURAL
|
||||||
|
MUST ( cn $ sshPublicKey $ keyFingerprint )
|
||||||
|
)
|
||||||
|
|
||||||
|
objectClass (
|
||||||
|
novaOCs:3
|
||||||
|
NAME 'novaProject'
|
||||||
|
DESC 'Container for project'
|
||||||
|
SUP groupOfNames
|
||||||
|
STRUCTURAL
|
||||||
|
MUST ( cn $ projectManager )
|
||||||
|
)
|
||||||
16
nova/auth/nova_sun.schema
Normal file
16
nova/auth/nova_sun.schema
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#
|
||||||
|
# Person object for Nova
|
||||||
|
# inetorgperson with extra attributes
|
||||||
|
# Author: Vishvananda Ishaya <vishvananda@yahoo.com>
|
||||||
|
# Modified for strict RFC 4512 compatibility by: Ryan Lane <ryan@ryandlane.com>
|
||||||
|
#
|
||||||
|
# using internet experimental oid arc as per BP64 3.1
|
||||||
|
dn: cn=schema
|
||||||
|
attributeTypes: ( 1.3.6.1.3.1.666.666.3.1 NAME 'accessKey' DESC 'Key for accessing data' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE )
|
||||||
|
attributeTypes: ( 1.3.6.1.3.1.666.666.3.2 NAME 'secretKey' DESC 'Secret key' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE )
|
||||||
|
attributeTypes: ( 1.3.6.1.3.1.666.666.3.3 NAME 'keyFingerprint' DESC 'Fingerprint of private key' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE)
|
||||||
|
attributeTypes: ( 1.3.6.1.3.1.666.666.3.4 NAME 'isAdmin' DESC 'Is user an administrator?' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE )
|
||||||
|
attributeTypes: ( 1.3.6.1.3.1.666.666.3.5 NAME 'projectManager' DESC 'Project Managers of a project' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
|
||||||
|
objectClasses: ( 1.3.6.1.3.1.666.666.4.1 NAME 'novaUser' DESC 'access and secret keys' SUP top AUXILIARY MUST ( uid ) MAY ( accessKey $ secretKey $ isAdmin ) )
|
||||||
|
objectClasses: ( 1.3.6.1.3.1.666.666.4.2 NAME 'novaKeyPair' DESC 'Key pair for User' SUP top STRUCTURAL MUST ( cn $ sshPublicKey $ keyFingerprint ) )
|
||||||
|
objectClasses: ( 1.3.6.1.3.1.666.666.4.3 NAME 'novaProject' DESC 'Container for project' SUP groupOfNames STRUCTURAL MUST ( cn $ projectManager ) )
|
||||||
119
nova/auth/opendj.sh
Executable file
119
nova/auth/opendj.sh
Executable file
@@ -0,0 +1,119 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2010 United States Government as represented by the
|
||||||
|
# Administrator of the National Aeronautics and Space Administration.
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
# LDAP INSTALL SCRIPT - IS IDEMPOTENT, does not scrub users
|
||||||
|
|
||||||
|
apt-get install -y ldap-utils python-ldap openjdk-6-jre
|
||||||
|
|
||||||
|
if [ ! -d "/usr/opendj" ]
|
||||||
|
then
|
||||||
|
# TODO(rlane): Wikimedia Foundation is the current package maintainer.
|
||||||
|
# After the package is included in Ubuntu's channel, change this.
|
||||||
|
wget http://apt.wikimedia.org/wikimedia/pool/main/o/opendj/opendj_2.4.0-7_amd64.deb
|
||||||
|
dpkg -i opendj_2.4.0-7_amd64.deb
|
||||||
|
fi
|
||||||
|
|
||||||
|
abspath=`dirname "$(cd "${0%/*}" 2>/dev/null; echo "$PWD"/"${0##*/}")"`
|
||||||
|
schemapath='/var/opendj/instance/config/schema'
|
||||||
|
cp $abspath/openssh-lpk_sun.schema $schemapath/97-openssh-lpk_sun.ldif
|
||||||
|
cp $abspath/nova_sun.schema $schemapath/98-nova_sun.ldif
|
||||||
|
chown opendj:opendj $schemapath/97-openssh-lpk_sun.ldif
|
||||||
|
chown opendj:opendj $schemapath/98-nova_sun.ldif
|
||||||
|
|
||||||
|
cat >/etc/ldap/ldap.conf <<LDAP_CONF_EOF
|
||||||
|
# LDAP Client Settings
|
||||||
|
URI ldap://localhost
|
||||||
|
BASE dc=example,dc=com
|
||||||
|
BINDDN cn=Directory Manager
|
||||||
|
SIZELIMIT 0
|
||||||
|
TIMELIMIT 0
|
||||||
|
LDAP_CONF_EOF
|
||||||
|
|
||||||
|
cat >/etc/ldap/base.ldif <<BASE_LDIF_EOF
|
||||||
|
# This is the root of the directory tree
|
||||||
|
dn: dc=example,dc=com
|
||||||
|
description: Example.Com, your trusted non-existent corporation.
|
||||||
|
dc: example
|
||||||
|
o: Example.Com
|
||||||
|
objectClass: top
|
||||||
|
objectClass: dcObject
|
||||||
|
objectClass: organization
|
||||||
|
|
||||||
|
# Subtree for users
|
||||||
|
dn: ou=Users,dc=example,dc=com
|
||||||
|
ou: Users
|
||||||
|
description: Users
|
||||||
|
objectClass: organizationalUnit
|
||||||
|
|
||||||
|
# Subtree for groups
|
||||||
|
dn: ou=Groups,dc=example,dc=com
|
||||||
|
ou: Groups
|
||||||
|
description: Groups
|
||||||
|
objectClass: organizationalUnit
|
||||||
|
|
||||||
|
# Subtree for system accounts
|
||||||
|
dn: ou=System,dc=example,dc=com
|
||||||
|
ou: System
|
||||||
|
description: Special accounts used by software applications.
|
||||||
|
objectClass: organizationalUnit
|
||||||
|
|
||||||
|
# Special Account for Authentication:
|
||||||
|
dn: uid=authenticate,ou=System,dc=example,dc=com
|
||||||
|
uid: authenticate
|
||||||
|
ou: System
|
||||||
|
description: Special account for authenticating users
|
||||||
|
userPassword: {MD5}TLnIqASP0CKUR3/LGkEZGg==
|
||||||
|
objectClass: account
|
||||||
|
objectClass: simpleSecurityObject
|
||||||
|
|
||||||
|
# create the sysadmin entry
|
||||||
|
|
||||||
|
dn: cn=developers,ou=Groups,dc=example,dc=com
|
||||||
|
objectclass: groupOfNames
|
||||||
|
cn: developers
|
||||||
|
description: IT admin group
|
||||||
|
member: uid=admin,ou=Users,dc=example,dc=com
|
||||||
|
|
||||||
|
dn: cn=sysadmins,ou=Groups,dc=example,dc=com
|
||||||
|
objectclass: groupOfNames
|
||||||
|
cn: sysadmins
|
||||||
|
description: IT admin group
|
||||||
|
member: uid=admin,ou=Users,dc=example,dc=com
|
||||||
|
|
||||||
|
dn: cn=netadmins,ou=Groups,dc=example,dc=com
|
||||||
|
objectclass: groupOfNames
|
||||||
|
cn: netadmins
|
||||||
|
description: Network admin group
|
||||||
|
member: uid=admin,ou=Users,dc=example,dc=com
|
||||||
|
|
||||||
|
dn: cn=cloudadmins,ou=Groups,dc=example,dc=com
|
||||||
|
objectclass: groupOfNames
|
||||||
|
cn: cloudadmins
|
||||||
|
description: Cloud admin group
|
||||||
|
member: uid=admin,ou=Users,dc=example,dc=com
|
||||||
|
|
||||||
|
dn: cn=itsec,ou=Groups,dc=example,dc=com
|
||||||
|
objectclass: groupOfNames
|
||||||
|
cn: itsec
|
||||||
|
description: IT security users group
|
||||||
|
member: uid=admin,ou=Users,dc=example,dc=com
|
||||||
|
BASE_LDIF_EOF
|
||||||
|
|
||||||
|
/etc/init.d/opendj stop
|
||||||
|
su - opendj -c '/usr/opendj/setup -i -b "dc=example,dc=com" -l /etc/ldap/base.ldif -S -w changeme -O -n --noPropertiesFile'
|
||||||
|
/etc/init.d/opendj start
|
||||||
19
nova/auth/openssh-lpk_openldap.schema
Normal file
19
nova/auth/openssh-lpk_openldap.schema
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#
|
||||||
|
# LDAP Public Key Patch schema for use with openssh-ldappubkey
|
||||||
|
# Author: Eric AUGE <eau@phear.org>
|
||||||
|
#
|
||||||
|
# Based on the proposal of : Mark Ruijter
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
# octetString SYNTAX
|
||||||
|
attributetype ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey'
|
||||||
|
DESC 'MANDATORY: OpenSSH Public key'
|
||||||
|
EQUALITY octetStringMatch
|
||||||
|
SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
|
||||||
|
|
||||||
|
# printableString SYNTAX yes|no
|
||||||
|
objectclass ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY
|
||||||
|
DESC 'MANDATORY: OpenSSH LPK objectclass'
|
||||||
|
MAY ( sshPublicKey $ uid )
|
||||||
|
)
|
||||||
10
nova/auth/openssh-lpk_sun.schema
Normal file
10
nova/auth/openssh-lpk_sun.schema
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#
|
||||||
|
# LDAP Public Key Patch schema for use with openssh-ldappubkey
|
||||||
|
# Author: Eric AUGE <eau@phear.org>
|
||||||
|
#
|
||||||
|
# Schema for Sun Directory Server.
|
||||||
|
# Based on the original schema, modified by Stefan Fischer.
|
||||||
|
#
|
||||||
|
dn: cn=schema
|
||||||
|
attributeTypes: ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey' DESC 'MANDATORY: OpenSSH Public key' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
|
||||||
|
objectClasses: ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY DESC 'MANDATORY: OpenSSH LPK objectclass' MAY ( sshPublicKey $ uid ) )
|
||||||
@@ -20,115 +20,9 @@
|
|||||||
|
|
||||||
apt-get install -y slapd ldap-utils python-ldap
|
apt-get install -y slapd ldap-utils python-ldap
|
||||||
|
|
||||||
cat >/etc/ldap/schema/openssh-lpk_openldap.schema <<LPK_SCHEMA_EOF
|
abspath=`dirname "$(cd "${0%/*}" 2>/dev/null; echo "$PWD"/"${0##*/}")"`
|
||||||
#
|
cp $abspath/openssh-lpk_openldap.schema /etc/ldap/schema/openssh-lpk_openldap.schema
|
||||||
# LDAP Public Key Patch schema for use with openssh-ldappubkey
|
cp $abspath/nova_openldap.schema /etc/ldap/schema/nova_openldap.schema
|
||||||
# Author: Eric AUGE <eau@phear.org>
|
|
||||||
#
|
|
||||||
# Based on the proposal of : Mark Ruijter
|
|
||||||
#
|
|
||||||
|
|
||||||
|
|
||||||
# octetString SYNTAX
|
|
||||||
attributetype ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey'
|
|
||||||
DESC 'MANDATORY: OpenSSH Public key'
|
|
||||||
EQUALITY octetStringMatch
|
|
||||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
|
|
||||||
|
|
||||||
# printableString SYNTAX yes|no
|
|
||||||
objectclass ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY
|
|
||||||
DESC 'MANDATORY: OpenSSH LPK objectclass'
|
|
||||||
MAY ( sshPublicKey $ uid )
|
|
||||||
)
|
|
||||||
LPK_SCHEMA_EOF
|
|
||||||
|
|
||||||
cat >/etc/ldap/schema/nova.schema <<NOVA_SCHEMA_EOF
|
|
||||||
#
|
|
||||||
# Person object for Nova
|
|
||||||
# inetorgperson with extra attributes
|
|
||||||
# Author: Vishvananda Ishaya <vishvananda@yahoo.com>
|
|
||||||
#
|
|
||||||
#
|
|
||||||
|
|
||||||
# using internet experimental oid arc as per BP64 3.1
|
|
||||||
objectidentifier novaSchema 1.3.6.1.3.1.666.666
|
|
||||||
objectidentifier novaAttrs novaSchema:3
|
|
||||||
objectidentifier novaOCs novaSchema:4
|
|
||||||
|
|
||||||
attributetype (
|
|
||||||
novaAttrs:1
|
|
||||||
NAME 'accessKey'
|
|
||||||
DESC 'Key for accessing data'
|
|
||||||
EQUALITY caseIgnoreMatch
|
|
||||||
SUBSTR caseIgnoreSubstringsMatch
|
|
||||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
|
|
||||||
SINGLE-VALUE
|
|
||||||
)
|
|
||||||
|
|
||||||
attributetype (
|
|
||||||
novaAttrs:2
|
|
||||||
NAME 'secretKey'
|
|
||||||
DESC 'Secret key'
|
|
||||||
EQUALITY caseIgnoreMatch
|
|
||||||
SUBSTR caseIgnoreSubstringsMatch
|
|
||||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
|
|
||||||
SINGLE-VALUE
|
|
||||||
)
|
|
||||||
|
|
||||||
attributetype (
|
|
||||||
novaAttrs:3
|
|
||||||
NAME 'keyFingerprint'
|
|
||||||
DESC 'Fingerprint of private key'
|
|
||||||
EQUALITY caseIgnoreMatch
|
|
||||||
SUBSTR caseIgnoreSubstringsMatch
|
|
||||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
|
|
||||||
SINGLE-VALUE
|
|
||||||
)
|
|
||||||
|
|
||||||
attributetype (
|
|
||||||
novaAttrs:4
|
|
||||||
NAME 'isAdmin'
|
|
||||||
DESC 'Is user an administrator?'
|
|
||||||
EQUALITY booleanMatch
|
|
||||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
|
|
||||||
SINGLE-VALUE
|
|
||||||
)
|
|
||||||
|
|
||||||
attributetype (
|
|
||||||
novaAttrs:5
|
|
||||||
NAME 'projectManager'
|
|
||||||
DESC 'Project Managers of a project'
|
|
||||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
|
|
||||||
)
|
|
||||||
|
|
||||||
objectClass (
|
|
||||||
novaOCs:1
|
|
||||||
NAME 'novaUser'
|
|
||||||
DESC 'access and secret keys'
|
|
||||||
AUXILIARY
|
|
||||||
MUST ( uid )
|
|
||||||
MAY ( accessKey $ secretKey $ isAdmin )
|
|
||||||
)
|
|
||||||
|
|
||||||
objectClass (
|
|
||||||
novaOCs:2
|
|
||||||
NAME 'novaKeyPair'
|
|
||||||
DESC 'Key pair for User'
|
|
||||||
SUP top
|
|
||||||
STRUCTURAL
|
|
||||||
MUST ( cn $ sshPublicKey $ keyFingerprint )
|
|
||||||
)
|
|
||||||
|
|
||||||
objectClass (
|
|
||||||
novaOCs:3
|
|
||||||
NAME 'novaProject'
|
|
||||||
DESC 'Container for project'
|
|
||||||
SUP groupOfNames
|
|
||||||
STRUCTURAL
|
|
||||||
MUST ( cn $ projectManager )
|
|
||||||
)
|
|
||||||
|
|
||||||
NOVA_SCHEMA_EOF
|
|
||||||
|
|
||||||
mv /etc/ldap/slapd.conf /etc/ldap/slapd.conf.orig
|
mv /etc/ldap/slapd.conf /etc/ldap/slapd.conf.orig
|
||||||
cat >/etc/ldap/slapd.conf <<SLAPD_CONF_EOF
|
cat >/etc/ldap/slapd.conf <<SLAPD_CONF_EOF
|
||||||
|
|||||||
@@ -223,8 +223,6 @@ DEFINE_string('rabbit_virtual_host', '/', 'rabbit virtual host')
|
|||||||
DEFINE_integer('rabbit_retry_interval', 10, 'rabbit connection retry interval')
|
DEFINE_integer('rabbit_retry_interval', 10, 'rabbit connection retry interval')
|
||||||
DEFINE_integer('rabbit_max_retries', 12, 'rabbit connection attempts')
|
DEFINE_integer('rabbit_max_retries', 12, 'rabbit connection attempts')
|
||||||
DEFINE_string('control_exchange', 'nova', 'the main exchange to connect to')
|
DEFINE_string('control_exchange', 'nova', 'the main exchange to connect to')
|
||||||
DEFINE_string('cc_host', '127.0.0.1', 'ip of api server')
|
|
||||||
DEFINE_integer('cc_port', 8773, 'cloud controller port')
|
|
||||||
DEFINE_string('ec2_url', 'http://127.0.0.1:8773/services/Cloud',
|
DEFINE_string('ec2_url', 'http://127.0.0.1:8773/services/Cloud',
|
||||||
'Url to ec2 api server')
|
'Url to ec2 api server')
|
||||||
|
|
||||||
@@ -264,7 +262,7 @@ DEFINE_string('scheduler_manager', 'nova.scheduler.manager.SchedulerManager',
|
|||||||
'Manager for scheduler')
|
'Manager for scheduler')
|
||||||
|
|
||||||
# The service to use for image search and retrieval
|
# The service to use for image search and retrieval
|
||||||
DEFINE_string('image_service', 'nova.image.local.LocalImageService',
|
DEFINE_string('image_service', 'nova.image.s3.S3ImageService',
|
||||||
'The service to use for retrieving and searching for images.')
|
'The service to use for retrieving and searching for images.')
|
||||||
|
|
||||||
DEFINE_string('host', socket.gethostname(),
|
DEFINE_string('host', socket.gethostname(),
|
||||||
|
|||||||
@@ -126,6 +126,19 @@ class CloudTestCase(test.TrialTestCase):
|
|||||||
db.instance_destroy(self.context, inst['id'])
|
db.instance_destroy(self.context, inst['id'])
|
||||||
db.floating_ip_destroy(self.context, address)
|
db.floating_ip_destroy(self.context, address)
|
||||||
|
|
||||||
|
def test_describe_volumes(self):
|
||||||
|
"""Makes sure describe_volumes works and filters results."""
|
||||||
|
vol1 = db.volume_create(self.context, {})
|
||||||
|
vol2 = db.volume_create(self.context, {})
|
||||||
|
result = self.cloud.describe_volumes(self.context)
|
||||||
|
self.assertEqual(len(result['volumeSet']), 2)
|
||||||
|
result = self.cloud.describe_volumes(self.context,
|
||||||
|
volume_id=[vol2['ec2_id']])
|
||||||
|
self.assertEqual(len(result['volumeSet']), 1)
|
||||||
|
self.assertEqual(result['volumeSet'][0]['volumeId'], vol2['ec2_id'])
|
||||||
|
db.volume_destroy(self.context, vol1['id'])
|
||||||
|
db.volume_destroy(self.context, vol2['id'])
|
||||||
|
|
||||||
def test_console_output(self):
|
def test_console_output(self):
|
||||||
image_id = FLAGS.default_image
|
image_id = FLAGS.default_image
|
||||||
instance_type = FLAGS.default_instance_type
|
instance_type = FLAGS.default_instance_type
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ from nova import flags
|
|||||||
from nova import test
|
from nova import test
|
||||||
from nova import utils
|
from nova import utils
|
||||||
from nova.auth import manager
|
from nova.auth import manager
|
||||||
|
from nova.compute import api as compute_api
|
||||||
|
|
||||||
FLAGS = flags.FLAGS
|
FLAGS = flags.FLAGS
|
||||||
|
|
||||||
@@ -43,6 +44,7 @@ class ComputeTestCase(test.TrialTestCase):
|
|||||||
self.flags(connection_type='fake',
|
self.flags(connection_type='fake',
|
||||||
network_manager='nova.network.manager.FlatManager')
|
network_manager='nova.network.manager.FlatManager')
|
||||||
self.compute = utils.import_object(FLAGS.compute_manager)
|
self.compute = utils.import_object(FLAGS.compute_manager)
|
||||||
|
self.compute_api = compute_api.ComputeAPI()
|
||||||
self.manager = manager.AuthManager()
|
self.manager = manager.AuthManager()
|
||||||
self.user = self.manager.create_user('fake', 'fake', 'fake')
|
self.user = self.manager.create_user('fake', 'fake', 'fake')
|
||||||
self.project = self.manager.create_project('fake', 'fake', 'fake')
|
self.project = self.manager.create_project('fake', 'fake', 'fake')
|
||||||
@@ -66,26 +68,31 @@ class ComputeTestCase(test.TrialTestCase):
|
|||||||
inst['ami_launch_index'] = 0
|
inst['ami_launch_index'] = 0
|
||||||
return db.instance_create(self.context, inst)['id']
|
return db.instance_create(self.context, inst)['id']
|
||||||
|
|
||||||
|
def test_create_instance_defaults_display_name(self):
|
||||||
|
"""Verify that an instance cannot be created without a display_name."""
|
||||||
|
cases = [dict(), dict(display_name=None)]
|
||||||
|
for instance in cases:
|
||||||
|
ref = self.compute_api.create_instances(self.context,
|
||||||
|
FLAGS.default_instance_type, None, **instance)
|
||||||
|
try:
|
||||||
|
self.assertNotEqual(ref[0].display_name, None)
|
||||||
|
finally:
|
||||||
|
db.instance_destroy(self.context, ref[0]['id'])
|
||||||
|
|
||||||
def test_create_instance_associates_security_groups(self):
|
def test_create_instance_associates_security_groups(self):
|
||||||
"""Make sure create_instance associates security groups"""
|
"""Make sure create_instances associates security groups"""
|
||||||
inst = {}
|
|
||||||
inst['user_id'] = self.user.id
|
|
||||||
inst['project_id'] = self.project.id
|
|
||||||
values = {'name': 'default',
|
values = {'name': 'default',
|
||||||
'description': 'default',
|
'description': 'default',
|
||||||
'user_id': self.user.id,
|
'user_id': self.user.id,
|
||||||
'project_id': self.project.id}
|
'project_id': self.project.id}
|
||||||
group = db.security_group_create(self.context, values)
|
group = db.security_group_create(self.context, values)
|
||||||
ref = self.compute.create_instance(self.context,
|
ref = self.compute_api.create_instances(self.context,
|
||||||
security_groups=[group['id']],
|
FLAGS.default_instance_type, None, security_group=['default'])
|
||||||
**inst)
|
|
||||||
# reload to get groups
|
|
||||||
instance_ref = db.instance_get(self.context, ref['id'])
|
|
||||||
try:
|
try:
|
||||||
self.assertEqual(len(instance_ref['security_groups']), 1)
|
self.assertEqual(len(ref[0]['security_groups']), 1)
|
||||||
finally:
|
finally:
|
||||||
db.security_group_destroy(self.context, group['id'])
|
db.security_group_destroy(self.context, group['id'])
|
||||||
db.instance_destroy(self.context, instance_ref['id'])
|
db.instance_destroy(self.context, ref[0]['id'])
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def test_run_terminate(self):
|
def test_run_terminate(self):
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import subprocess
|
|
||||||
|
|
||||||
from nova import test
|
from nova import test
|
||||||
from nova.utils import parse_mailmap, str_dict_replace
|
from nova.utils import parse_mailmap, str_dict_replace
|
||||||
@@ -24,18 +23,23 @@ from nova.utils import parse_mailmap, str_dict_replace
|
|||||||
class ProjectTestCase(test.TrialTestCase):
|
class ProjectTestCase(test.TrialTestCase):
|
||||||
def test_authors_up_to_date(self):
|
def test_authors_up_to_date(self):
|
||||||
if os.path.exists('../.bzr'):
|
if os.path.exists('../.bzr'):
|
||||||
log_cmd = subprocess.Popen(["bzr", "log", "-n0"],
|
contributors = set()
|
||||||
stdout=subprocess.PIPE)
|
|
||||||
changelog = log_cmd.communicate()[0]
|
|
||||||
mailmap = parse_mailmap('../.mailmap')
|
mailmap = parse_mailmap('../.mailmap')
|
||||||
|
|
||||||
contributors = set()
|
import bzrlib.workingtree
|
||||||
for l in changelog.split('\n'):
|
tree = bzrlib.workingtree.WorkingTree.open('..')
|
||||||
l = l.strip()
|
tree.lock_read()
|
||||||
if (l.startswith('author:') or l.startswith('committer:')
|
parents = tree.get_parent_ids()
|
||||||
and not l == 'committer: Tarmac'):
|
g = tree.branch.repository.get_graph()
|
||||||
email = l.split(' ')[-1]
|
for p in parents[1:]:
|
||||||
contributors.add(str_dict_replace(email, mailmap))
|
rev_ids = [r for r, _ in g.iter_ancestry(parents)
|
||||||
|
if r != "null:"]
|
||||||
|
revs = tree.branch.repository.get_revisions(rev_ids)
|
||||||
|
for r in revs:
|
||||||
|
for author in r.get_apparent_authors():
|
||||||
|
email = author.split(' ')[-1]
|
||||||
|
contributors.add(str_dict_replace(email, mailmap))
|
||||||
|
|
||||||
authors_file = open('../Authors', 'r').read()
|
authors_file = open('../Authors', 'r').read()
|
||||||
|
|
||||||
|
|||||||
@@ -94,11 +94,12 @@ class QuotaTestCase(test.TrialTestCase):
|
|||||||
for i in range(FLAGS.quota_instances):
|
for i in range(FLAGS.quota_instances):
|
||||||
instance_id = self._create_instance()
|
instance_id = self._create_instance()
|
||||||
instance_ids.append(instance_id)
|
instance_ids.append(instance_id)
|
||||||
self.assertRaises(cloud.QuotaError, self.cloud.run_instances,
|
self.assertRaises(quota.QuotaError, self.cloud.run_instances,
|
||||||
self.context,
|
self.context,
|
||||||
min_count=1,
|
min_count=1,
|
||||||
max_count=1,
|
max_count=1,
|
||||||
instance_type='m1.small')
|
instance_type='m1.small',
|
||||||
|
image_id='fake')
|
||||||
for instance_id in instance_ids:
|
for instance_id in instance_ids:
|
||||||
db.instance_destroy(self.context, instance_id)
|
db.instance_destroy(self.context, instance_id)
|
||||||
|
|
||||||
@@ -106,11 +107,12 @@ class QuotaTestCase(test.TrialTestCase):
|
|||||||
instance_ids = []
|
instance_ids = []
|
||||||
instance_id = self._create_instance(cores=4)
|
instance_id = self._create_instance(cores=4)
|
||||||
instance_ids.append(instance_id)
|
instance_ids.append(instance_id)
|
||||||
self.assertRaises(cloud.QuotaError, self.cloud.run_instances,
|
self.assertRaises(quota.QuotaError, self.cloud.run_instances,
|
||||||
self.context,
|
self.context,
|
||||||
min_count=1,
|
min_count=1,
|
||||||
max_count=1,
|
max_count=1,
|
||||||
instance_type='m1.small')
|
instance_type='m1.small',
|
||||||
|
image_id='fake')
|
||||||
for instance_id in instance_ids:
|
for instance_id in instance_ids:
|
||||||
db.instance_destroy(self.context, instance_id)
|
db.instance_destroy(self.context, instance_id)
|
||||||
|
|
||||||
@@ -119,7 +121,7 @@ class QuotaTestCase(test.TrialTestCase):
|
|||||||
for i in range(FLAGS.quota_volumes):
|
for i in range(FLAGS.quota_volumes):
|
||||||
volume_id = self._create_volume()
|
volume_id = self._create_volume()
|
||||||
volume_ids.append(volume_id)
|
volume_ids.append(volume_id)
|
||||||
self.assertRaises(cloud.QuotaError, self.cloud.create_volume,
|
self.assertRaises(quota.QuotaError, self.cloud.create_volume,
|
||||||
self.context,
|
self.context,
|
||||||
size=10)
|
size=10)
|
||||||
for volume_id in volume_ids:
|
for volume_id in volume_ids:
|
||||||
@@ -129,7 +131,7 @@ class QuotaTestCase(test.TrialTestCase):
|
|||||||
volume_ids = []
|
volume_ids = []
|
||||||
volume_id = self._create_volume(size=20)
|
volume_id = self._create_volume(size=20)
|
||||||
volume_ids.append(volume_id)
|
volume_ids.append(volume_id)
|
||||||
self.assertRaises(cloud.QuotaError,
|
self.assertRaises(quota.QuotaError,
|
||||||
self.cloud.create_volume,
|
self.cloud.create_volume,
|
||||||
self.context,
|
self.context,
|
||||||
size=10)
|
size=10)
|
||||||
@@ -146,6 +148,6 @@ class QuotaTestCase(test.TrialTestCase):
|
|||||||
# make an rpc.call, the test just finishes with OK. It
|
# make an rpc.call, the test just finishes with OK. It
|
||||||
# appears to be something in the magic inline callbacks
|
# appears to be something in the magic inline callbacks
|
||||||
# that is breaking.
|
# that is breaking.
|
||||||
self.assertRaises(cloud.QuotaError, self.cloud.allocate_address,
|
self.assertRaises(quota.QuotaError, self.cloud.allocate_address,
|
||||||
self.context)
|
self.context)
|
||||||
db.floating_ip_destroy(context.get_admin_context(), address)
|
db.floating_ip_destroy(context.get_admin_context(), address)
|
||||||
|
|||||||
@@ -41,15 +41,14 @@ class LibvirtConnTestCase(test.TrialTestCase):
|
|||||||
FLAGS.instances_path = ''
|
FLAGS.instances_path = ''
|
||||||
|
|
||||||
test_ip = '10.11.12.13'
|
test_ip = '10.11.12.13'
|
||||||
test_instance = {
|
test_instance = {'memory_kb': '1024000',
|
||||||
'memory_kb' : '1024000',
|
'basepath': '/some/path',
|
||||||
'basepath' : '/some/path',
|
'bridge_name': 'br100',
|
||||||
'bridge_name' : 'br100',
|
'mac_address': '02:12:34:46:56:67',
|
||||||
'mac_address' : '02:12:34:46:56:67',
|
'vcpus': 2,
|
||||||
'vcpus' : 2,
|
'project_id': 'fake',
|
||||||
'project_id' : 'fake',
|
'bridge': 'br101',
|
||||||
'bridge' : 'br101',
|
'instance_type': 'm1.small'}
|
||||||
'instance_type' : 'm1.small'}
|
|
||||||
|
|
||||||
def test_xml_and_uri_no_ramdisk_no_kernel(self):
|
def test_xml_and_uri_no_ramdisk_no_kernel(self):
|
||||||
instance_data = dict(self.test_instance)
|
instance_data = dict(self.test_instance)
|
||||||
@@ -83,7 +82,6 @@ class LibvirtConnTestCase(test.TrialTestCase):
|
|||||||
expect_kernel=True, expect_ramdisk=True,
|
expect_kernel=True, expect_ramdisk=True,
|
||||||
rescue=True)
|
rescue=True)
|
||||||
|
|
||||||
|
|
||||||
def do_test_xml_and_uri(self, instance,
|
def do_test_xml_and_uri(self, instance,
|
||||||
expect_ramdisk, expect_kernel,
|
expect_ramdisk, expect_kernel,
|
||||||
rescue=False):
|
rescue=False):
|
||||||
@@ -94,14 +92,14 @@ class LibvirtConnTestCase(test.TrialTestCase):
|
|||||||
self.network.set_network_host(context.get_admin_context(),
|
self.network.set_network_host(context.get_admin_context(),
|
||||||
network_ref['id'])
|
network_ref['id'])
|
||||||
|
|
||||||
fixed_ip = { 'address' : self.test_ip,
|
fixed_ip = {'address': self.test_ip,
|
||||||
'network_id' : network_ref['id'] }
|
'network_id': network_ref['id']}
|
||||||
|
|
||||||
ctxt = context.get_admin_context()
|
ctxt = context.get_admin_context()
|
||||||
fixed_ip_ref = db.fixed_ip_create(ctxt, fixed_ip)
|
fixed_ip_ref = db.fixed_ip_create(ctxt, fixed_ip)
|
||||||
db.fixed_ip_update(ctxt, self.test_ip,
|
db.fixed_ip_update(ctxt, self.test_ip,
|
||||||
{ 'allocated': True,
|
{'allocated': True,
|
||||||
'instance_id': instance_ref['id'] })
|
'instance_id': instance_ref['id']})
|
||||||
|
|
||||||
type_uri_map = {'qemu': ('qemu:///system',
|
type_uri_map = {'qemu': ('qemu:///system',
|
||||||
[(lambda t: t.find('.').get('type'), 'qemu'),
|
[(lambda t: t.find('.').get('type'), 'qemu'),
|
||||||
@@ -131,15 +129,15 @@ class LibvirtConnTestCase(test.TrialTestCase):
|
|||||||
check_list.append(check)
|
check_list.append(check)
|
||||||
else:
|
else:
|
||||||
if expect_kernel:
|
if expect_kernel:
|
||||||
check = (lambda t: t.find('./os/kernel').text.split('/')[1],
|
check = (lambda t: t.find('./os/kernel').text.split('/'
|
||||||
'kernel')
|
)[1], 'kernel')
|
||||||
else:
|
else:
|
||||||
check = (lambda t: t.find('./os/kernel'), None)
|
check = (lambda t: t.find('./os/kernel'), None)
|
||||||
check_list.append(check)
|
check_list.append(check)
|
||||||
|
|
||||||
if expect_ramdisk:
|
if expect_ramdisk:
|
||||||
check = (lambda t: t.find('./os/initrd').text.split('/')[1],
|
check = (lambda t: t.find('./os/initrd').text.split('/'
|
||||||
'ramdisk')
|
)[1], 'ramdisk')
|
||||||
else:
|
else:
|
||||||
check = (lambda t: t.find('./os/initrd'), None)
|
check = (lambda t: t.find('./os/initrd'), None)
|
||||||
check_list.append(check)
|
check_list.append(check)
|
||||||
@@ -189,7 +187,8 @@ class LibvirtConnTestCase(test.TrialTestCase):
|
|||||||
expected_result,
|
expected_result,
|
||||||
'%s failed common check %d' % (xml, i))
|
'%s failed common check %d' % (xml, i))
|
||||||
|
|
||||||
# This test is supposed to make sure we don't override a specifically set uri
|
# This test is supposed to make sure we don't override a specifically
|
||||||
|
# set uri
|
||||||
#
|
#
|
||||||
# Deliberately not just assigning this string to FLAGS.libvirt_uri and
|
# Deliberately not just assigning this string to FLAGS.libvirt_uri and
|
||||||
# checking against that later on. This way we make sure the
|
# checking against that later on. This way we make sure the
|
||||||
|
|||||||
Reference in New Issue
Block a user