# limitations under the License.
import logging
-from keystoneclient.exceptions import NotFound
-from snaps.openstack.utils import keystone_utils
+from keystoneclient.exceptions import NotFound, Conflict
+
+from snaps.config.project import ProjectConfig
+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):
: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 = None
+ 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
- :return: The OpenStack Image object
+ Loads the existing Project object if it exists
+ :return: The Project domain object
"""
- self.__keystone = keystone_utils.keystone_client(self.__os_creds)
+ super(self.__class__, self).initialize()
+
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:
+ 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)
- else:
- logger.info('Did not create image due to cleanup mode')
+ 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)
+
+ if self.project_settings.quotas:
+ quota_dict = self.project_settings.quotas
+ nova = nova_utils.nova_client(self._os_creds, self._os_session)
+ quotas = nova_utils.get_compute_quotas(nova, self.__project.id)
+ if quotas:
+ if 'cores' in quota_dict:
+ quotas.cores = quota_dict['cores']
+ if 'instances' in quota_dict:
+ quotas.instances = quota_dict['instances']
+ if 'injected_files' in quota_dict:
+ quotas.injected_files = quota_dict['injected_files']
+ if 'injected_file_content_bytes' in quota_dict:
+ quotas.injected_file_content_bytes = \
+ quota_dict['injected_file_content_bytes']
+ if 'ram' in quota_dict:
+ quotas.ram = quota_dict['ram']
+ if 'fixed_ips' in quota_dict:
+ quotas.fixed_ips = quota_dict['fixed_ips']
+ if 'key_pairs' in quota_dict:
+ quotas.key_pairs = quota_dict['key_pairs']
+
+ nova_utils.update_quotas(nova, self.__project.id, quotas)
return self.__project
:return: void
"""
if self.__project:
+ # Delete security group 'default' if exists
+ neutron = neutron_utils.neutron_client(
+ self._os_creds, self._os_session)
+ try:
+ default_sec_grp = neutron_utils.get_security_group(
+ neutron, self._keystone, sec_grp_name='default',
+ project_name=self.__project.name)
+ if default_sec_grp:
+ try:
+ neutron_utils.delete_security_group(
+ neutron, default_sec_grp)
+ except:
+ pass
+ finally:
+ neutron.httpclient.session.session.close()
+
+ # 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)
+
+ super(self.__class__, self).clean()
+
def get_project(self):
"""
Returns the OpenStack project object populated on create()
: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.grant_user_role_to_project(self.__keystone, self.__role,
+ 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, self._os_session)
-class ProjectSettings:
+ try:
+ return nova_utils.get_compute_quotas(nova, self.__project.id)
+ finally:
+ nova.client.session.session.close()
+
+ 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, self._os_session)
+ try:
+ return neutron_utils.get_network_quotas(neutron, self.__project.id)
+ finally:
+ neutron.httpclient.session.session.close()
+
+ 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, self._os_session)
+ try:
+ nova_utils.update_quotas(nova, self.__project.id, compute_quotas)
+ finally:
+ nova.client.session.session.close()
+
+ 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, self._os_session)
+ try:
+ neutron_utils.update_quotas(
+ neutron, self.__project.id, network_quotas)
+ finally:
+ neutron.httpclient.session.session.close()
+
+
+class ProjectSettings(ProjectConfig):
"""
Class to hold the configuration settings required for creating OpenStack
project objects
+ deprecated
"""
def __init__(self, **kwargs):
-
- """
- Constructor
- :param name: the project's name (required)
- :param domain: 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)
- """
-
- self.name = kwargs.get('name')
- if kwargs.get('domain'):
- self.domain = kwargs['domain']
- else:
- self.domain = 'default'
-
- self.description = kwargs.get('description')
- if kwargs.get('enabled') is not None:
- self.enabled = kwargs['enabled']
- else:
- self.enabled = True
-
- if not self.name:
- raise Exception(
- "The attribute name is required for ProjectSettings")
+ from warnings import warn
+ warn('Use snaps.config.project.ProjectConfig instead',
+ DeprecationWarning)
+ super(self.__class__, self).__init__(**kwargs)