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'))
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
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