X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=snaps%2Fopenstack%2Fcreate_project.py;h=0cf6d4af566d39f4e1676d05f474be9518cdf802;hb=92d57dd388e5ad292d476298ad79d8a566780e2a;hp=2658d13ec805829f1822d41dd570df7228523b33;hpb=d1c4675e5c35257b84cd69969c6e67575faf19db;p=snaps.git diff --git a/snaps/openstack/create_project.py b/snaps/openstack/create_project.py index 2658d13..0cf6d4a 100644 --- a/snaps/openstack/create_project.py +++ b/snaps/openstack/create_project.py @@ -14,18 +14,19 @@ # limitations under the License. import logging -from keystoneclient.exceptions import NotFound +from keystoneclient.exceptions import NotFound, Conflict -from snaps.openstack.utils import keystone_utils +from snaps.openstack.openstack_creator import OpenStackIdentityObject +from snaps.openstack.utils import keystone_utils, neutron_utils, nova_utils __author__ = 'spisarski' logger = logging.getLogger('create_image') -class OpenStackProject: +class OpenStackProject(OpenStackIdentityObject): """ - Class responsible for creating a project/project in OpenStack + Class responsible for managing a project/project in OpenStack """ def __init__(self, os_creds, project_settings): @@ -35,26 +36,42 @@ class OpenStackProject: :param project_settings: The project's settings :return: """ - self.__os_creds = os_creds + super(self.__class__, self).__init__(os_creds) + self.project_settings = project_settings self.__project = None self.__role = None - self.__keystone = keystone_utils.keystone_client(self.__os_creds) + self.__role_name = self.project_settings.name + '-role' - def create(self, cleanup=False): + def initialize(self): """ - Creates the image in OpenStack if it does not already exist - :param cleanup: Denotes whether or not this is being called for cleanup or not - :return: The OpenStack Image object + Loads the existing Project object if it exists + :return: The Project domain object """ - self.__project = keystone_utils.get_project(keystone=self.__keystone, - project_name=self.project_settings.name) - if self.__project: - logger.info('Found project with name - ' + self.project_settings.name) - elif not cleanup: - self.__project = keystone_utils.create_project(self.__keystone, self.project_settings) - else: - logger.info('Did not create image due to cleanup mode') + super(self.__class__, self).initialize() + + self.__project = keystone_utils.get_project( + keystone=self._keystone, project_settings=self.project_settings) + return self.__project + + def create(self): + """ + Creates a Project/Tenant in OpenStack if it does not already exist + :return: The Project domain object + """ + self.initialize() + + if not self.__project: + self.__project = keystone_utils.create_project( + self._keystone, self.project_settings) + for username in self.project_settings.users: + user = keystone_utils.get_user(self._keystone, username) + if user: + try: + self.assoc_user(user) + except Conflict as e: + logger.warn('Unable to associate user %s due to %s', + user.name, e) return self.__project @@ -64,19 +81,38 @@ class OpenStackProject: :return: void """ if self.__project: + # Delete security group 'default' if exists + neutron = neutron_utils.neutron_client(self._os_creds) + default_sec_grp = neutron_utils.get_security_group( + neutron, sec_grp_name='default', + project_id=self.__project.id) + if default_sec_grp: + try: + neutron_utils.delete_security_group( + neutron, default_sec_grp) + except: + pass + + # Delete Project try: - keystone_utils.delete_project(self.__keystone, self.__project) + keystone_utils.delete_project(self._keystone, self.__project) except NotFound: pass self.__project = None if self.__role: try: - keystone_utils.delete_role(self.__keystone, self.__role) + keystone_utils.delete_role(self._keystone, self.__role) except NotFound: pass self.__project = None + # Final role check in case init was done from an existing instance + role = keystone_utils.get_role_by_name( + self._keystone, self.__role_name) + if role: + keystone_utils.delete_role(self._keystone, role) + def get_project(self): """ Returns the OpenStack project object populated on create() @@ -87,48 +123,90 @@ class OpenStackProject: def assoc_user(self, user): """ The user object to associate with the project - :param user: the OpenStack user object to associate with project + :param user: the OpenStack User domain object to associate with project :return: """ if not self.__role: - self.__role = keystone_utils.create_role(self.__keystone, self.project_settings.name + '-role') + self.__role = keystone_utils.get_role_by_name( + self._keystone, self.__role_name) + if not self.__role: + self.__role = keystone_utils.create_role( + self._keystone, self.__role_name) - keystone_utils.assoc_user_to_project(self.__keystone, self.__role, user, self.__project) + keystone_utils.grant_user_role_to_project(self._keystone, self.__role, + user, self.__project) + + def get_compute_quotas(self): + """ + Returns the compute quotas as an instance of the ComputeQuotas class + :return: + """ + nova = nova_utils.nova_client(self._os_creds) + return nova_utils.get_compute_quotas(nova, self.__project.id) + + def get_network_quotas(self): + """ + Returns the network quotas as an instance of the NetworkQuotas class + :return: + """ + neutron = neutron_utils.neutron_client(self._os_creds) + return neutron_utils.get_network_quotas(neutron, self.__project.id) + + def update_compute_quotas(self, compute_quotas): + """ + Updates the compute quotas for this project + :param compute_quotas: a ComputeQuotas object. + """ + nova = nova_utils.nova_client(self._os_creds) + nova_utils.update_quotas(nova, self.__project.id, compute_quotas) + + def update_network_quotas(self, network_quotas): + """ + Updates the network quotas for this project + :param network_quotas: a NetworkQuotas object. + """ + neutron = neutron_utils.neutron_client(self._os_creds) + neutron_utils.update_quotas(neutron, self.__project.id, network_quotas) class ProjectSettings: """ - Class to hold the configuration settings required for creating OpenStack project objects + Class to hold the configuration settings required for creating OpenStack + project objects """ - def __init__(self, config=None, name=None, domain='default', description=None, enabled=True): + + def __init__(self, **kwargs): """ Constructor - :param config: dict() object containing the configuration settings using the attribute names below as each - member's the key and overrides any of the other parameters. :param name: the project's name (required) - :param domain: the project's domain name (default 'default'). Field is used for v3 clients + :param domain or domain_name: the project's domain name + (default = 'Default'). + Field is used for v3 clients :param description: the description (optional) - :param enabled: denotes whether or not the user is enabled (default True) + :param users: list of users to associat project to (optional) + :param enabled: denotes whether or not the user is enabled + (default True) """ - if config: - self.name = config.get('name') - if config.get('domain'): - self.domain = config['domain'] - else: - self.domain = domain + self.name = kwargs.get('name') + self.domain_name = kwargs.get( + 'domain', kwargs.get('domain', 'Default')) - self.description = config.get('description') - if config.get('enabled') is not None: - self.enabled = config['enabled'] - else: - self.enabled = enabled + self.description = kwargs.get('description') + if kwargs.get('enabled') is not None: + self.enabled = kwargs['enabled'] else: - self.name = name - self.domain = domain - self.description = description - self.enabled = enabled + self.enabled = True + + self.users = kwargs.get('users', list()) if not self.name: - raise Exception("The attribute name is required for ProjectSettings") + raise ProjectSettingsError( + "The attribute name is required for ProjectSettings") + + +class ProjectSettingsError(Exception): + """ + Exception to be thrown when project settings attributes are incorrect + """