def post(self, project):
        """Sync resources present in one region to another region.

        :param project: It's UUID of the project.
        """
        context = restcomm.extract_context_from_environ()
        if not uuidutils.is_uuid_like(project) or project != context.project:
            pecan.abort(400, _('Invalid request URL'))
        payload = eval(request.body)
        if not payload:
            pecan.abort(400, _('Body required'))
        payload = payload.get('resource_set')
        if not payload:
            pecan.abort(400, _('resource_set required'))
        resource_type = payload.get('resource_type')
        target_regions = payload.get('target')
        if not target_regions or not isinstance(target_regions, list):
            pecan.abort(400, _('Target regions required'))
        source_region = payload.get('source')
        if not source_region or not isinstance(source_region, str):
            pecan.abort(400, _('Source region required'))
        source_resources = payload.get('resources')
        if not source_resources:
            pecan.abort(400, _('Source resources required'))
        job_id = uuidutils.generate_uuid()
        if resource_type == consts.KEYPAIR:
            session = EndpointCache().get_session_from_token(
                context.auth_token, context.project)
            # Create Source Region object
            source_nova_client = NovaClient(source_region, session)
            # Check for keypairs in Source Region
            for source_keypair in source_resources:
                source_keypair = source_nova_client.\
                    get_keypairs(source_keypair)
                if not source_keypair:
                    pecan.abort(404)
            result = self._entries_to_database(context, target_regions,
                                               source_region, source_resources,
                                               resource_type, job_id)
            return self._keypair_sync(job_id, payload, context, result)

        elif resource_type == consts.IMAGE:
            # Create Source Region glance_object
            glance_driver = GlanceClient(source_region, context)
            # Check for images in Source Region
            for image in source_resources:
                source_image = glance_driver.check_image(image)
                if image != source_image:
                    pecan.abort(404)
            result = self._entries_to_database(context, target_regions,
                                               source_region, source_resources,
                                               resource_type, job_id)
            return self._image_sync(job_id, payload, context, result)
        else:
            pecan.abort(400, _('Bad resource_type'))
Exemple #2
0
 def __init__(self, region_name=None):
     # Check if objects are cached and try to use those
     self.region_name = region_name
     if 'keystone' in OpenStackDriver.os_clients_dict and \
             self._is_token_valid():
         self.keystone_client = OpenStackDriver.os_clients_dict['keystone']
     else:
         self.keystone_client = KeystoneClient()
         OpenStackDriver.os_clients_dict['keystone'] = self.keystone_client
     self.disabled_quotas = self._get_disabled_quotas(region_name)
     if region_name in OpenStackDriver.os_clients_dict and \
             self._is_token_valid():
         LOG.info('Using cached OS client objects')
         self.nova_client = OpenStackDriver.os_clients_dict[region_name][
             'nova']
         self.cinder_client = OpenStackDriver.os_clients_dict[region_name][
             'cinder']
         self.neutron_client = OpenStackDriver.os_clients_dict[region_name][
             'neutron']
     else:
         # Create new objects and cache them
         LOG.info(_("Creating fresh OS Clients objects"))
         self.neutron_client = NeutronClient(region_name,
                                             self.disabled_quotas,
                                             self.keystone_client.session)
         self.nova_client = NovaClient(region_name,
                                       self.keystone_client.session,
                                       self.disabled_quotas)
         self.cinder_client = CinderClient(region_name,
                                           self.disabled_quotas,
                                           self.keystone_client.session)
         OpenStackDriver.os_clients_dict[
             region_name] = collections.defaultdict(dict)
         OpenStackDriver.os_clients_dict[region_name][
             'nova'] = self.nova_client
         OpenStackDriver.os_clients_dict[region_name][
             'cinder'] = self.cinder_client
         OpenStackDriver.os_clients_dict[region_name][
             'neutron'] = self.neutron_client
    def resource_sync(self, context, job_id, payload):
        """Create resources in target regions.

        :param context: request context object.
        :param job_id: ID of the job which triggered image_sync.
        :payload: request payload.
        """
        LOG.info("Triggered Keypair Sync.")
        keypairs_thread = list()
        target_regions = payload['target']
        force = eval(str(payload.get('force', False)))
        resource_ids = payload.get('resources')
        source_region = payload['source']
        session = EndpointCache().get_session_from_token(
            context.auth_token, context.project)
        # Create Source Region object
        source_nova_client = NovaClient(source_region, session)
        for keypair in resource_ids:
            source_keypair = source_nova_client.get_keypairs(keypair)
            thread = threading.Thread(target=self.create_resources_in_region,
                                      args=(job_id, force, target_regions,
                                            source_keypair, session,
                                            context,))
            keypairs_thread.append(thread)
            thread.start()
            for keypair_thread in keypairs_thread:
                keypair_thread.join()
        try:
            resource_sync_details = db_api.\
                resource_sync_status(context, job_id)
        except exceptions.JobNotFound:
            raise
        result = consts.JOB_SUCCESS
        if consts.JOB_FAILURE in resource_sync_details:
            result = consts.JOB_FAILURE
        try:
            db_api.sync_job_update(context, job_id, result)
        except exceptions.JobNotFound:
            raise
 def create_resources(self, job_id, force, region, source_keypair,
                      session, context):
     """Create resources using threads."""
     target_nova_client = NovaClient(region, session)
     try:
         target_nova_client.create_keypairs(force, source_keypair)
         LOG.info('keypair %(keypair)s created in %(region)s'
                  % {'keypair': source_keypair.name, 'region': region})
         try:
             db_api.resource_sync_update(context, job_id, region,
                                         source_keypair.name,
                                         consts.JOB_SUCCESS)
         except exceptions.JobNotFound():
             raise
     except Exception as exc:
         LOG.error('Exception Occurred: %(msg)s in %(region)s'
                   % {'msg': exc.message, 'region': region})
         try:
             db_api.resource_sync_update(context, job_id, region,
                                         source_keypair.name,
                                         consts.JOB_FAILURE)
         except exceptions.JobNotFound():
             raise
         pass
Exemple #5
0
class OpenStackDriver(object):

    os_clients_dict = collections.defaultdict(dict)

    def __init__(self, region_name=None):
        # Check if objects are cached and try to use those
        self.region_name = region_name
        if 'keystone' in OpenStackDriver.os_clients_dict and \
                self._is_token_valid():
            self.keystone_client = OpenStackDriver.os_clients_dict['keystone']
        else:
            self.keystone_client = KeystoneClient()
            OpenStackDriver.os_clients_dict['keystone'] = self.keystone_client
        self.disabled_quotas = self._get_disabled_quotas(region_name)
        if region_name in OpenStackDriver.os_clients_dict and \
                self._is_token_valid():
            LOG.info('Using cached OS client objects')
            self.nova_client = OpenStackDriver.os_clients_dict[region_name][
                'nova']
            self.cinder_client = OpenStackDriver.os_clients_dict[region_name][
                'cinder']
            self.neutron_client = OpenStackDriver.os_clients_dict[region_name][
                'neutron']
        else:
            # Create new objects and cache them
            LOG.info(_("Creating fresh OS Clients objects"))
            self.neutron_client = NeutronClient(region_name,
                                                self.disabled_quotas,
                                                self.keystone_client.session)
            self.nova_client = NovaClient(region_name,
                                          self.keystone_client.session,
                                          self.disabled_quotas)
            self.cinder_client = CinderClient(region_name,
                                              self.disabled_quotas,
                                              self.keystone_client.session)
            OpenStackDriver.os_clients_dict[
                region_name] = collections.defaultdict(dict)
            OpenStackDriver.os_clients_dict[region_name][
                'nova'] = self.nova_client
            OpenStackDriver.os_clients_dict[region_name][
                'cinder'] = self.cinder_client
            OpenStackDriver.os_clients_dict[region_name][
                'neutron'] = self.neutron_client

    def get_enabled_projects(self):
        try:
            return self.keystone_client.get_enabled_projects()
        except Exception as exception:
            LOG.error('Error Occurred: %s', exception.message)

    def get_enabled_users(self):
        try:
            return self.keystone_client.get_enabled_users()
        except Exception as exception:
            LOG.error('Error Occurred : %s', exception.message)

    def get_resource_usages(self, project_id):
        try:
            nova_usages = self.nova_client.get_resource_usages(project_id)
            neutron_usages = self.neutron_client.get_resource_usages(
                project_id)
            cinder_usages = self.cinder_client.get_resource_usages(project_id)
            return nova_usages, neutron_usages, cinder_usages
        except (exceptions.ConnectionRefused, exceptions.NotAuthorized,
                exceptions.TimeOut):
            # Delete the cached objects for that region
            del OpenStackDriver.os_clients_dict[self.region_name]
        except Exception as exception:
            LOG.error('Error Occurred: %s', exception.message)

    def write_quota_limits(self, project_id, limits_to_write):
        try:
            self.nova_client.update_quota_limits(project_id,
                                                 **limits_to_write['nova'])
            self.cinder_client.update_quota_limits(project_id,
                                                   **limits_to_write['cinder'])
            self.neutron_client.update_quota_limits(project_id,
                                                    limits_to_write['neutron'])
        except (exceptions.ConnectionRefused, exceptions.NotAuthorized,
                exceptions.TimeOut):
            # Delete the cached objects for that region
            del OpenStackDriver.os_clients_dict[self.region_name]
        except Exception as exception:
            LOG.error('Error Occurred: %s', exception.message)

    def delete_quota_limits(self, project_id):
        try:
            self.nova_client.delete_quota_limits(project_id)
            self.neutron_client.delete_quota_limits(project_id)
            self.cinder_client.delete_quota_limits(project_id)
        except (exceptions.ConnectionRefused, exceptions.NotAuthorized,
                exceptions.TimeOut):
            # Delete the cached objects for that region
            del OpenStackDriver.os_clients_dict[self.region_name]
        except Exception as exception:
            LOG.error('Error Occurred: %s', exception.message)

    def _get_disabled_quotas(self, region):
        disabled_quotas = []
        if not self.keystone_client.is_service_enabled('volume') and \
                not self.keystone_client.is_service_enabled('volumev2'):
            disabled_quotas.extend(consts.CINDER_QUOTA_FIELDS)
        # Neutron
        if not self.keystone_client.is_service_enabled('network'):
            disabled_quotas.extend(consts.NEUTRON_QUOTA_FIELDS)
        else:
            disabled_quotas.extend(['floating_ips', 'fixed_ips'])
            disabled_quotas.extend(['security_groups', 'security_group_rules'])
        return disabled_quotas

    def get_all_regions_for_project(self, project_id):
        try:
            # Retrieve regions based on endpoint filter for the project.
            region_lists = self._get_filtered_regions(project_id)
            if not region_lists:
                # If endpoint filter is not used for the project, then
                # return all regions
                region_lists = endpoint_cache.EndpointCache().get_all_regions()
            return region_lists
        except Exception as exception:
            LOG.error('Error Occurred: %s', exception.message)
            raise

    def _get_filtered_regions(self, project_id):
        return self.keystone_client.get_filtered_region(project_id)

    def _is_token_valid(self):
        keystone = self.os_clients_dict['keystone'].keystone_client
        try:
            token = keystone.tokens.validate(keystone.session.get_token())
        except Exception as exception:
            LOG.info('Exception Occurred: %s', exception.message)
            # Reset the cached dictionary
            OpenStackDriver.os_clients_dict = collections.defaultdict(dict)
            return False

        expiry_time = timeutils.normalize_time(
            timeutils.parse_isotime(token['expires_at']))
        if timeutils.is_soon(expiry_time, STALE_TOKEN_DURATION):
            LOG.info('The cached keystone token will expire soon')
            # Reset the cached dictionary
            OpenStackDriver.os_clients_dict = collections.defaultdict(dict)
            return False
        else:
            return True