From 5c3d352cee5003395d078dcfe01e8f4743027074 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Mon, 26 Jul 2010 12:49:21 -0700 Subject: class based singleton for SharedPool --- nova/process.py | 13 +++++++------ nova/tests/process_unittest.py | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) (limited to 'nova') diff --git a/nova/process.py b/nova/process.py index 8ecef1584..2dc56372f 100644 --- a/nova/process.py +++ b/nova/process.py @@ -205,12 +205,13 @@ class ProcessPool(object): self._pool.release() return rv -_instance = None -def SharedPool(): - global _instance - if _instance is None: - _instance = ProcessPool() - return _instance +class SharedPool(object): + _instance = None + def __init__(self): + if SharedPool._instance is None: + self.__class__._instance = ProcessPool() + def __getattr__(self, key): + return getattr(self._instance, key) def simple_execute(cmd, **kwargs): return SharedPool().simple_execute(cmd, **kwargs) diff --git a/nova/tests/process_unittest.py b/nova/tests/process_unittest.py index c96bb5913..75187e1fc 100644 --- a/nova/tests/process_unittest.py +++ b/nova/tests/process_unittest.py @@ -118,7 +118,7 @@ class ProcessTestCase(test.TrialTestCase): def test_shared_pool_is_singleton(self): pool1 = process.SharedPool() pool2 = process.SharedPool() - self.assert_(id(pool1) == id(pool2)) + self.assertEqual(id(pool1._instance), id(pool2._instance)) def test_shared_pool_works_as_singleton(self): d1 = process.simple_execute('sleep 1') -- cgit From c42b214c61342089401b5191e70c0c6b09fb5a4a Mon Sep 17 00:00:00 2001 From: Devin Carlen Date: Tue, 27 Jul 2010 00:11:18 +0000 Subject: Began wiring up rbac admin api --- nova/adminclient.py | 102 +++++++++++++++++++++++++++++++++++++++++++++++++ nova/endpoint/admin.py | 71 ++++++++++++++++++++++++++++++++++ 2 files changed, 173 insertions(+) (limited to 'nova') diff --git a/nova/adminclient.py b/nova/adminclient.py index db392feb1..9b9505ac1 100644 --- a/nova/adminclient.py +++ b/nova/adminclient.py @@ -56,6 +56,29 @@ class UserInfo(object): elif name == 'secretkey': self.secretkey = str(value) +class ProjectInfo(object): + """ + Information about a Nova project, as parsed through SAX + fields include: + projectname + description + member_ids + """ + + def __init__(self, connection=None, projectname=None, endpoint=None): + self.connection = connection + self.projectname = projectname + self.endpoint = endpoint + + def __repr__(self): + return 'ProjectInfo:%s' % self.projectname + + def startElement(self, name, attrs, connection): + return None + + def endElement(self, name, value, connection): + setattr(self, name, str(value)) + class HostInfo(object): """ Information about a Nova Host, as parsed through SAX: @@ -137,6 +160,85 @@ class NovaAdminClient(object): """ deletes a user """ return self.apiconn.get_object('DeregisterUser', {'Name': username}, UserInfo) + def add_user_role(self, user, role, project=None): + """ + Add a role to a user either globally or for a specific project. + """ + return self.modify_user_role(user, role, project=project, + operation='add') + + def remove_user_role(self, user, role, project=None): + """ + Remove a role from a user either globally or for a specific project. + """ + return self.modify_user_role(user, role, project=project, + operation='remove') + + def modify_user_role(self, user, role, project=None, operation='add', + **kwargs): + """ + Add or remove a role for a user and project. + """ + params = { + 'User': user, + 'Role': role, + 'Project': project, + 'Operation': operation + + } + return self.apiconn.get_status('ModifyUserRole', params) + + def get_projects(self): + """ + Returns a list of all projects. + """ + return self.apiconn.get_list('DescribeProjects', {}, + [('item', ProjectInfo)]) + + def get_project(self, name): + """ + Returns a single project with the specified name. + """ + project = self.apiconn.get_object('DescribeProject', + {'Name': name}, + ProjectInfo) + + if project.projectname != None: + return project + + def create_project(self, projectname, manager_user, description=None, + member_users=None): + """ + Creates a new project. + """ + params = { + 'Name': projectname, + 'ManagerUser': manager_user, + 'Description': description, + 'MemberUsers': member_users + } + return self.apiconn.get_object('RegisterProject', params, ProjectInfo) + + def delete_project(self, projectname): + """ + Permanently deletes the specified project. + """ + return self.apiconn.get_object('DeregisterProject', + {'Name': projectname}, + ProjectInfo) + + def modify_project_user(self, user, project, operation='add', + **kwargs): + """ + Adds or removes a user from a project. + """ + params = { + 'User': user, + 'Project': project, + 'Operation': operation + } + return self.apiconn.get_status('ModifyProjectUser', params) + def get_zip(self, username): """ returns the content of a zip file containing novarc and access credentials. """ return self.apiconn.get_object('GenerateX509ForUser', {'Name': username}, UserInfo).file diff --git a/nova/endpoint/admin.py b/nova/endpoint/admin.py index 55a8e4238..e3762e2af 100644 --- a/nova/endpoint/admin.py +++ b/nova/endpoint/admin.py @@ -37,6 +37,17 @@ def user_dict(user, base64_file=None): else: return {} +def project_dict(project): + """Convert the project object to a result dict""" + if project: + return { + 'projectname': project.id, + 'description': project.description, + 'member_ids': project.member_ids + } + else: + return {} + def host_dict(host): """Convert a host model object to a result dict""" if host: @@ -92,6 +103,22 @@ class AdminController(object): return True + @admin_only + def modify_user_role(self, context, user, role, project=None, + operation='add', **kwargs): + """ + Add or remove a role for a user and project. + """ + + if operation == 'add': + manager.AuthManager().add_role(user, role, project) + elif operation == 'remove': + manager.AuthManager().remove_role(user, role, project) + else: + raise exception.ApiError('operation must be add or remove') + + return True + @admin_only def generate_x509_for_user(self, _context, name, project=None, **kwargs): """Generates and returns an x509 certificate for a single user. @@ -104,6 +131,50 @@ class AdminController(object): user = manager.AuthManager().get_user(name) return user_dict(user, base64.b64encode(project.get_credentials(user))) + @admin_only + def describe_project(self, context, name, **kwargs): + """Returns project data, including member ids.""" + return project_dict(manager.AuthManager().get_project(name)) + + @admin_only + def describe_projects(self, context, **kwargs): + """Returns all projects - should be changed to deal with a list.""" + return {'projectSet': + [project_dict(u) for u in + manager.AuthManager().get_projects()]} + + @admin_only + def register_project(self, context, name, manager_user, description=None, + member_users=None, **kwargs): + """Creates a new project""" + return project_dict( + manager.AuthManager().create_project( + name, + manager_user, + description=None, + member_users=None + ) + ) + + @admin_only + def deregister_project(self, context, name): + """Permanently deletes a project.""" + manager.AuthManager().delete_project(name) + return True + + @admin_only + def modify_project_user(self, context, user, project, operation, **kwargs): + """ + Add or remove a user from a project. + """ + + if operation =='add': + manager.AuthManager().add_to_project(user, project) + elif operation == 'remove': + manager.AuthManager().remove_from_project(user, project) + else: + raise exception.ApiError('operation must be add or remove') + @admin_only def describe_hosts(self, _context, **_kwargs): """Returns status info for all nodes. Includes: -- cgit From 40dfe6316fae4b14f9fa694653341349a86d55ab Mon Sep 17 00:00:00 2001 From: Devin Carlen Date: Wed, 28 Jul 2010 00:28:56 +0000 Subject: Wired up user:project auth calls --- nova/adminclient.py | 5 +++-- nova/auth/manager.py | 1 + nova/endpoint/admin.py | 13 ++++--------- 3 files changed, 8 insertions(+), 11 deletions(-) (limited to 'nova') diff --git a/nova/adminclient.py b/nova/adminclient.py index 9b9505ac1..e81e0470f 100644 --- a/nova/adminclient.py +++ b/nova/adminclient.py @@ -122,13 +122,14 @@ class NovaAdminClient(object): **kwargs) self.apiconn.APIVersion = 'nova' - def connection_for(self, username, **kwargs): + def connection_for(self, username, project, **kwargs): """ Returns a boto ec2 connection for the given username. """ user = self.get_user(username) + access_key = '%s:%s' % (user.accesskey, project) return boto.connect_ec2( - aws_access_key_id=user.accesskey, + aws_access_key_id=access_key, aws_secret_access_key=user.secretkey, is_secure=False, region=RegionInfo(None, self.region, self.clc_ip), diff --git a/nova/auth/manager.py b/nova/auth/manager.py index bc373fd26..8c8c7377c 100644 --- a/nova/auth/manager.py +++ b/nova/auth/manager.py @@ -532,6 +532,7 @@ class AuthManager(object): def get_projects(self): """Retrieves list of all projects""" + # TODO(devcamcar): Implement filter by user. with self.driver() as drv: project_list = drv.get_projects() if not project_list: diff --git a/nova/endpoint/admin.py b/nova/endpoint/admin.py index e3762e2af..e1e06e944 100644 --- a/nova/endpoint/admin.py +++ b/nova/endpoint/admin.py @@ -106,10 +106,7 @@ class AdminController(object): @admin_only def modify_user_role(self, context, user, role, project=None, operation='add', **kwargs): - """ - Add or remove a role for a user and project. - """ - + """Add or remove a role for a user and project.""" if operation == 'add': manager.AuthManager().add_role(user, role, project) elif operation == 'remove': @@ -137,8 +134,9 @@ class AdminController(object): return project_dict(manager.AuthManager().get_project(name)) @admin_only - def describe_projects(self, context, **kwargs): + def describe_projects(self, context, user=None, **kwargs): """Returns all projects - should be changed to deal with a list.""" + # TODO(devcamcar): Implement filter by user. return {'projectSet': [project_dict(u) for u in manager.AuthManager().get_projects()]} @@ -164,10 +162,7 @@ class AdminController(object): @admin_only def modify_project_user(self, context, user, project, operation, **kwargs): - """ - Add or remove a user from a project. - """ - + """Add or remove a user from a project.""" if operation =='add': manager.AuthManager().add_to_project(user, project) elif operation == 'remove': -- cgit From a46e9aecb9a0de4d06dc00979795b33f788959fa Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Wed, 28 Jul 2010 01:12:14 -0700 Subject: use default kernel and ramdisk and check for legal access --- nova/endpoint/cloud.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'nova') diff --git a/nova/endpoint/cloud.py b/nova/endpoint/cloud.py index 76ca35320..e7c4542f8 100644 --- a/nova/endpoint/cloud.py +++ b/nova/endpoint/cloud.py @@ -515,8 +515,12 @@ class CloudController(object): # get defaults from imagestore image_id = image['imageId'] - kernel_id = image.get('kernelId', None) - ramdisk_id = image.get('ramdiskId', None) + kernel_id = image.get('kernelId', FLAGS.default_kernel) + ramdisk_id = image.get('ramdiskId', FLAGS.default_ramdisk) + + # make sure we have access to kernel and ramdisk + self._get_image(context, kernel_id) + self._get_image(context, ramdisk_id) # API parameters overrides of defaults kernel_id = kwargs.get('kernel_id', kernel_id) -- cgit From 2c6bf00a35c45cb63a0c8688bbf2504dd8610bb1 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Wed, 28 Jul 2010 02:21:11 -0700 Subject: Fix dnsmasq commands to pass in environment properly --- nova/compute/linux_net.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'nova') diff --git a/nova/compute/linux_net.py b/nova/compute/linux_net.py index 861ce779b..4a4b4c8a8 100644 --- a/nova/compute/linux_net.py +++ b/nova/compute/linux_net.py @@ -94,7 +94,7 @@ def bridge_create(net): execute("sudo ifconfig %s up" % net['bridge_name']) def dnsmasq_cmd(net): - cmd = ['sudo dnsmasq', + cmd = ['sudo -E dnsmasq', ' --strict-order', ' --bind-interfaces', ' --conf-file=', @@ -143,8 +143,9 @@ def start_dnsmasq(network): if os.path.exists(lease_file): os.unlink(lease_file) - # FLAGFILE in env - env = {'FLAGFILE' : FLAGS.dhcpbridge_flagfile} + # FLAGFILE and DNSMASQ_INTERFACE in env + env = {'FLAGFILE': FLAGS.dhcpbridge_flagfile, + 'DNSMASQ_INTERFACE': network['bridge_name']} execute(dnsmasq_cmd(network), addl_env=env) def stop_dnsmasq(network): -- cgit From 2ecdf8cdd81df36ef34fc7522aae3f5f1b217d81 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Wed, 28 Jul 2010 10:47:53 -0700 Subject: Specify a filter by user for get projects --- nova/auth/ldapdriver.py | 7 +++++-- nova/auth/manager.py | 6 +++--- nova/tests/auth_unittest.py | 6 ++++++ 3 files changed, 14 insertions(+), 5 deletions(-) (limited to 'nova') diff --git a/nova/auth/ldapdriver.py b/nova/auth/ldapdriver.py index 1591c88e9..055e8332b 100644 --- a/nova/auth/ldapdriver.py +++ b/nova/auth/ldapdriver.py @@ -120,10 +120,13 @@ class LdapDriver(object): '(objectclass=novaKeyPair)') return [self.__to_key_pair(uid, attr) for attr in attrs] - def get_projects(self): + def get_projects(self, uid=None): """Retrieve list of projects""" + filter = '(objectclass=novaProject)' + if uid: + filter = "(&%s(member=%s))" % (filter, self.__uid_to_dn(uid)) attrs = self.__find_objects(FLAGS.ldap_project_subtree, - '(objectclass=novaProject)') + filter) return [self.__to_project(attr) for attr in attrs] def create_user(self, name, access_key, secret_key, is_admin): diff --git a/nova/auth/manager.py b/nova/auth/manager.py index 66027f6c2..7307f673b 100644 --- a/nova/auth/manager.py +++ b/nova/auth/manager.py @@ -547,10 +547,10 @@ class AuthManager(object): if project_dict: return Project(**project_dict) - def get_projects(self): - """Retrieves list of all projects""" + def get_projects(self, user=None): + """Retrieves list of projects, optionally filtered by user""" with self.driver() as drv: - project_list = drv.get_projects() + project_list = drv.get_projects(User.safe_id(user)) if not project_list: return [] return [Project(**project_dict) for project_dict in project_list] diff --git a/nova/tests/auth_unittest.py b/nova/tests/auth_unittest.py index 0cd377b70..6f35bab4e 100644 --- a/nova/tests/auth_unittest.py +++ b/nova/tests/auth_unittest.py @@ -193,9 +193,15 @@ class AuthTestCase(test.BaseTestCase): for vpn in vpns: vpn.destroy() + def test_214_can_retrieve_project_by_user(self): + project = self.manager.create_project('testproj2', 'test2', 'Another test project', ['test2']) + self.assert_(len(self.manager.get_projects()) > 1) + self.assertEqual(len(self.manager.get_projects('test2')), 1) + def test_299_can_delete_project(self): self.manager.delete_project('testproj') self.assertFalse(filter(lambda p: p.name == 'testproj', self.manager.get_projects())) + self.manager.delete_project('testproj2') def test_999_can_delete_users(self): self.manager.delete_user('test1') -- cgit From e53caccb7a242bdabd4ea6aed914ab77cb1fca32 Mon Sep 17 00:00:00 2001 From: Devin Carlen Date: Wed, 28 Jul 2010 18:16:09 +0000 Subject: Fixed project api --- nova/adminclient.py | 6 +++++- nova/endpoint/admin.py | 1 + nova/endpoint/cloud.py | 3 +-- 3 files changed, 7 insertions(+), 3 deletions(-) (limited to 'nova') diff --git a/nova/adminclient.py b/nova/adminclient.py index e81e0470f..7ef3497bc 100644 --- a/nova/adminclient.py +++ b/nova/adminclient.py @@ -69,6 +69,7 @@ class ProjectInfo(object): self.connection = connection self.projectname = projectname self.endpoint = endpoint + self.memberIds = [] def __repr__(self): return 'ProjectInfo:%s' % self.projectname @@ -77,7 +78,10 @@ class ProjectInfo(object): return None def endElement(self, name, value, connection): - setattr(self, name, str(value)) + if name == 'item': + self.memberIds.append(value) + elif name != 'memberIds': + setattr(self, name, str(value)) class HostInfo(object): """ diff --git a/nova/endpoint/admin.py b/nova/endpoint/admin.py index e1e06e944..120396b4a 100644 --- a/nova/endpoint/admin.py +++ b/nova/endpoint/admin.py @@ -42,6 +42,7 @@ def project_dict(project): if project: return { 'projectname': project.id, + 'project_manager_id': project.project_manager_id, 'description': project.description, 'member_ids': project.member_ids } diff --git a/nova/endpoint/cloud.py b/nova/endpoint/cloud.py index 76ca35320..754b0780c 100644 --- a/nova/endpoint/cloud.py +++ b/nova/endpoint/cloud.py @@ -49,8 +49,7 @@ flags.DEFINE_string('cloud_topic', 'cloud', 'the topic clouds listen on') def _gen_key(user_id, key_name): """ Tuck this into AuthManager """ try: - manager = manager.AuthManager() - private_key, fingerprint = manager.generate_key_pair(user_id, key_name) + private_key, fingerprint = manager.AuthManager().generate_key_pair(user_id, key_name) except Exception as ex: return {'exception': ex} return {'private_key': private_key, 'fingerprint': fingerprint} -- cgit From 47408dc8c901a431e358cad0420b756439d93a80 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Wed, 28 Jul 2010 11:33:11 -0700 Subject: make redis name default to lower case --- nova/datastore.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova') diff --git a/nova/datastore.py b/nova/datastore.py index e57177e04..45a710aaf 100644 --- a/nova/datastore.py +++ b/nova/datastore.py @@ -103,7 +103,7 @@ class BasicModel(object): @classmethod def _redis_name(cls): - return cls.override_type or cls.__name__ + return cls.override_type or cls.__name__.lower() @classmethod def lookup(cls, identifier): -- cgit From a7e5d47d8e49f8fc10900ede3376ddc515799811 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Wed, 28 Jul 2010 12:53:27 -0700 Subject: allow driver to be passed in to auth manager instead of depending solely on flag --- nova/auth/manager.py | 24 ++++++++++-------------- nova/utils.py | 10 ++++++++++ 2 files changed, 20 insertions(+), 14 deletions(-) (limited to 'nova') diff --git a/nova/auth/manager.py b/nova/auth/manager.py index 66027f6c2..7c0ee9cb4 100644 --- a/nova/auth/manager.py +++ b/nova/auth/manager.py @@ -323,25 +323,21 @@ class AuthManager(object): """ _instance=None def __new__(cls, *args, **kwargs): - """Returns the AuthManager singleton with driver set - - __init__ is run every time AuthManager() is called, so we need to do - any constructor related stuff here. The driver that is specified - in the flagfile is loaded here. - """ + """Returns the AuthManager singleton""" if not cls._instance: cls._instance = super(AuthManager, cls).__new__( cls, *args, **kwargs) - mod_str, sep, driver_str = FLAGS.auth_driver.rpartition('.') - try: - __import__(mod_str) - cls._instance.driver = getattr(sys.modules[mod_str], - driver_str) - except (ImportError, AttributeError): - raise exception.Error('Auth driver %s cannot be found' - % FLAGS.auth_driver) return cls._instance + def __init__(self, driver=None, *args, **kwargs): + """Inits the driver from parameter or flag + + __init__ is run every time AuthManager() is called, so we only + reset the driver if it is not set or a new driver is specified. + """ + if driver or not getattr(self, 'driver', None): + self.driver = utils.import_class(driver or FLAGS.auth_driver) + def authenticate(self, access, signature, params, verb='GET', server_string='127.0.0.1:8773', path='/', check_type='ec2', headers=None): diff --git a/nova/utils.py b/nova/utils.py index a1eb0a092..0016b656e 100644 --- a/nova/utils.py +++ b/nova/utils.py @@ -29,11 +29,21 @@ import subprocess import socket import sys +from nova import exception from nova import flags FLAGS = flags.FLAGS TIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ" +def import_class(import_str): + """Returns a class from a string including module and class""" + mod_str, _sep, class_str = import_str.rpartition('.') + try: + __import__(mod_str) + return getattr(sys.modules[mod_str], class_str) + except (ImportError, AttributeError): + raise exception.NotFound('Class %s cannot be found' % class_str) + def fetchfile(url, target): logging.debug("Fetching %s" % url) # c = pycurl.Curl() -- cgit From 93236b6b5f4f18fabf0852c6cbb9540578935961 Mon Sep 17 00:00:00 2001 From: Devin Carlen Date: Wed, 28 Jul 2010 21:04:05 +0000 Subject: Wired up get/add/remove project members --- nova/adminclient.py | 79 ++++++++++++++++++++++++++++++++++++++++++-------- nova/endpoint/admin.py | 15 +++++++--- 2 files changed, 78 insertions(+), 16 deletions(-) (limited to 'nova') diff --git a/nova/adminclient.py b/nova/adminclient.py index 7ef3497bc..3a2ce2f01 100644 --- a/nova/adminclient.py +++ b/nova/adminclient.py @@ -59,16 +59,18 @@ class UserInfo(object): class ProjectInfo(object): """ Information about a Nova project, as parsed through SAX - fields include: + Fields include: projectname description - member_ids + projectManagerId + memberIds """ - def __init__(self, connection=None, projectname=None, endpoint=None): + def __init__(self, connection=None): self.connection = connection - self.projectname = projectname - self.endpoint = endpoint + self.projectname = None + self.description = None + self.projectManagerId = None self.memberIds = [] def __repr__(self): @@ -78,11 +80,40 @@ class ProjectInfo(object): return None def endElement(self, name, value, connection): - if name == 'item': + if name == 'projectname': + self.projectname = value + elif name == 'description': + self.description = value + elif name == 'projectManagerId': + self.projectManagerId = value + elif name == 'memberId': self.memberIds.append(value) - elif name != 'memberIds': + else: setattr(self, name, str(value)) +class ProjectMember(object): + """ + Information about a Nova project member, as parsed through SAX. + Fields include: + memberId + """ + def __init__(self, connection=None): + self.connection = connection + self.memberId = None + + def __repr__(self): + return 'ProjectMember:%s' % self.memberId + + def startElement(self, name, attrs, connection): + return None + + def endElement(self, name, value, connection): + if name == 'member': + self.memberId = value + else: + setattr(self, name, str(value)) + + class HostInfo(object): """ Information about a Nova Host, as parsed through SAX: @@ -193,11 +224,16 @@ class NovaAdminClient(object): } return self.apiconn.get_status('ModifyUserRole', params) - def get_projects(self): + def get_projects(self, user=None): """ Returns a list of all projects. """ - return self.apiconn.get_list('DescribeProjects', {}, + if user: + params = {'User': user} + else: + params = {} + return self.apiconn.get_list('DescribeProjects', + params, [('item', ProjectInfo)]) def get_project(self, name): @@ -232,8 +268,27 @@ class NovaAdminClient(object): {'Name': projectname}, ProjectInfo) - def modify_project_user(self, user, project, operation='add', - **kwargs): + def get_project_members(self, name): + """ + Returns a list of members of a project. + """ + return self.apiconn.get_list('DescribeProjectMembers', + {'Name': name}, + [('item', ProjectMember)]) + + def add_project_member(self, user, project): + """ + Adds a user to a project. + """ + return self.modify_project_member(user, project, operation='add') + + def remove_project_member(self, user, project): + """ + Removes a user from a project. + """ + return self.modify_project_member(user, project, operation='remove') + + def modify_project_member(self, user, project, operation='add'): """ Adds or removes a user from a project. """ @@ -242,7 +297,7 @@ class NovaAdminClient(object): 'Project': project, 'Operation': operation } - return self.apiconn.get_status('ModifyProjectUser', params) + return self.apiconn.get_status('ModifyProjectMember', params) def get_zip(self, username): """ returns the content of a zip file containing novarc and access credentials. """ diff --git a/nova/endpoint/admin.py b/nova/endpoint/admin.py index 120396b4a..db1d319f9 100644 --- a/nova/endpoint/admin.py +++ b/nova/endpoint/admin.py @@ -44,7 +44,6 @@ def project_dict(project): 'projectname': project.id, 'project_manager_id': project.project_manager_id, 'description': project.description, - 'member_ids': project.member_ids } else: return {} @@ -137,10 +136,9 @@ class AdminController(object): @admin_only def describe_projects(self, context, user=None, **kwargs): """Returns all projects - should be changed to deal with a list.""" - # TODO(devcamcar): Implement filter by user. return {'projectSet': [project_dict(u) for u in - manager.AuthManager().get_projects()]} + manager.AuthManager().get_projects(user=user)]} @admin_only def register_project(self, context, name, manager_user, description=None, @@ -162,7 +160,15 @@ class AdminController(object): return True @admin_only - def modify_project_user(self, context, user, project, operation, **kwargs): + def describe_project_members(self, context, name, **kwargs): + project = manager.AuthManager().get_project(name) + result = { + 'members': [{'member': m} for m in project.member_ids] + } + return result + + @admin_only + def modify_project_member(self, context, user, project, operation, **kwargs): """Add or remove a user from a project.""" if operation =='add': manager.AuthManager().add_to_project(user, project) @@ -170,6 +176,7 @@ class AdminController(object): manager.AuthManager().remove_from_project(user, project) else: raise exception.ApiError('operation must be add or remove') + return True @admin_only def describe_hosts(self, _context, **_kwargs): -- cgit From bb375bbeffb1249c653d3589acb521a25f8824c7 Mon Sep 17 00:00:00 2001 From: Devin Carlen Date: Wed, 28 Jul 2010 23:41:43 +0000 Subject: pep8 --- nova/adminclient.py | 37 +++++++++++++++---------------------- nova/endpoint/admin.py | 14 +++++--------- 2 files changed, 20 insertions(+), 31 deletions(-) (limited to 'nova') diff --git a/nova/adminclient.py b/nova/adminclient.py index 3a2ce2f01..fceeac274 100644 --- a/nova/adminclient.py +++ b/nova/adminclient.py @@ -23,6 +23,7 @@ import base64 import boto from boto.ec2.regioninfo import RegionInfo + class UserInfo(object): """ Information about a Nova user, as parsed through SAX @@ -170,8 +171,7 @@ class NovaAdminClient(object): region=RegionInfo(None, self.region, self.clc_ip), port=8773, path='/services/Cloud', - **kwargs - ) + **kwargs) def get_users(self): """ grabs the list of all users """ @@ -215,13 +215,10 @@ class NovaAdminClient(object): """ Add or remove a role for a user and project. """ - params = { - 'User': user, - 'Role': role, - 'Project': project, - 'Operation': operation - - } + params = {'User': user, + 'Role': role, + 'Project': project, + 'Operation': operation} return self.apiconn.get_status('ModifyUserRole', params) def get_projects(self, user=None): @@ -241,8 +238,8 @@ class NovaAdminClient(object): Returns a single project with the specified name. """ project = self.apiconn.get_object('DescribeProject', - {'Name': name}, - ProjectInfo) + {'Name': name}, + ProjectInfo) if project.projectname != None: return project @@ -252,12 +249,10 @@ class NovaAdminClient(object): """ Creates a new project. """ - params = { - 'Name': projectname, - 'ManagerUser': manager_user, - 'Description': description, - 'MemberUsers': member_users - } + params = {'Name': projectname, + 'ManagerUser': manager_user, + 'Description': description, + 'MemberUsers': member_users} return self.apiconn.get_object('RegisterProject', params, ProjectInfo) def delete_project(self, projectname): @@ -292,11 +287,9 @@ class NovaAdminClient(object): """ Adds or removes a user from a project. """ - params = { - 'User': user, - 'Project': project, - 'Operation': operation - } + params = {'User': user, + 'Project': project, + 'Operation': operation} return self.apiconn.get_status('ModifyProjectMember', params) def get_zip(self, username): diff --git a/nova/endpoint/admin.py b/nova/endpoint/admin.py index db1d319f9..c4b8c05ca 100644 --- a/nova/endpoint/admin.py +++ b/nova/endpoint/admin.py @@ -25,6 +25,7 @@ import base64 from nova.auth import manager from nova.compute import model + def user_dict(user, base64_file=None): """Convert the user object to a result dict""" if user: @@ -32,8 +33,7 @@ def user_dict(user, base64_file=None): 'username': user.id, 'accesskey': user.access, 'secretkey': user.secret, - 'file': base64_file, - } + 'file': base64_file} else: return {} @@ -43,8 +43,7 @@ def project_dict(project): return { 'projectname': project.id, 'project_manager_id': project.project_manager_id, - 'description': project.description, - } + 'description': project.description} else: return {} @@ -149,9 +148,7 @@ class AdminController(object): name, manager_user, description=None, - member_users=None - ) - ) + member_users=None)) @admin_only def deregister_project(self, context, name): @@ -163,8 +160,7 @@ class AdminController(object): def describe_project_members(self, context, name, **kwargs): project = manager.AuthManager().get_project(name) result = { - 'members': [{'member': m} for m in project.member_ids] - } + 'members': [{'member': m} for m in project.member_ids]} return result @admin_only -- cgit From b01c531ba5cb408a630e992beda769032b135f6a Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Thu, 29 Jul 2010 01:21:50 +0100 Subject: Move the reading of API parameters above the call to _get_image, so that they have a chance to take effect. --- nova/endpoint/cloud.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'nova') diff --git a/nova/endpoint/cloud.py b/nova/endpoint/cloud.py index acba50b95..7e51cc83b 100644 --- a/nova/endpoint/cloud.py +++ b/nova/endpoint/cloud.py @@ -518,14 +518,14 @@ class CloudController(object): kernel_id = image.get('kernelId', FLAGS.default_kernel) ramdisk_id = image.get('ramdiskId', FLAGS.default_ramdisk) - # make sure we have access to kernel and ramdisk - self._get_image(context, kernel_id) - self._get_image(context, ramdisk_id) - # API parameters overrides of defaults kernel_id = kwargs.get('kernel_id', kernel_id) ramdisk_id = kwargs.get('ramdisk_id', ramdisk_id) + # make sure we have access to kernel and ramdisk + self._get_image(context, kernel_id) + self._get_image(context, ramdisk_id) + logging.debug("Going to run instances...") reservation_id = utils.generate_uid('r') launch_time = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime()) -- cgit From bc96d6daa425f7c38d67ad43b8cf46f3ba5989c3 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Thu, 29 Jul 2010 09:08:31 +0100 Subject: Replace the second singleton unit test, lost during a merge. --- nova/tests/process_unittest.py | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'nova') diff --git a/nova/tests/process_unittest.py b/nova/tests/process_unittest.py index f5f304aa2..75187e1fc 100644 --- a/nova/tests/process_unittest.py +++ b/nova/tests/process_unittest.py @@ -120,3 +120,10 @@ class ProcessTestCase(test.TrialTestCase): pool2 = process.SharedPool() self.assertEqual(id(pool1._instance), id(pool2._instance)) + def test_shared_pool_works_as_singleton(self): + d1 = process.simple_execute('sleep 1') + d2 = process.simple_execute('sleep 0.005') + # lp609749: would have failed with + # exceptions.AssertionError: Someone released me too many times: + # too many tokens! + return d1 -- cgit