def get_ptr_from_ip(ip, region_name, request_session=None) -> dict: params = {'ip': ip, 'region_name': region_name} serializer = GetPtrFromIpSerializer(data=params) serializer.is_valid(raise_exception=True) if request_session: designate = designate_client(api_session=IdentityAdminApi( request_session=request_session).session, region_name=serializer.validated_data.pop( 'region_name', None)) else: designate = designate_client(api_session=IdentityAdminApi().session, region_name=serializer.validated_data.pop( 'region_name', None)) related_ip = ip_address(serializer.validated_data['ip']) ptr_record = related_ip.reverse_pointer + '.' if isinstance(related_ip, IPv6Address): zone_name = ptr_record else: # cut the first segment (last segment from the ip) zone_name = ptr_record[ptr_record.index('.') + 1:] try: zones = designate.zones.list(criterion={'name': zone_name}) except (designate_exceptions.Base, ClientException) as e: raise e if zones: zone_id = zones[0]['id'] try: recordsets = designate.recordsets.list(zone=zone_id, criterion={ 'type': 'PTR', 'name': ptr_record }) except (designate_exceptions.Base, ClientException) as e: LOG.error('Unable to list record sets, reason {0}'.format(e)) raise e if recordsets: # TODO(erno): returns only the first PTR entry, and the first record record = recordsets[0]['records'][0] if record.endswith('.'): record = record[:-1] return dict( record=record, zone_id=zone_id, ) else: dict( record='', zone_id=zone_id, ) return dict( record='', zone_id='', )
def run(): os_admin_api = IdentityAdminApi() for client in Client.objects.all(): # type: Client try: LOG.debug('Cleaning up for client {}'.format(client)) if not client.first_project: LOG.debug('Skipping client without project ...') continue openstack_settings = OpenstackSettings.for_client(client=client) if openstack_settings.auto_cleanup_images: max_create_date = utcnow() - timedelta( days=openstack_settings.auto_cleanup_number_of_days) images_to_cleanup = Image.objects.filter( disk_format__in=openstack_settings. auto_cleanup_image_types, created_at__lte=max_create_date, project=client.first_project, ).all() for image in images_to_cleanup: os_api = Images(api_session=os_admin_api.session) os_image = os_api.get(image=image) # TODO: implement protected image deletion if not image.protected: os_image.delete() except Exception as e: LOG.exception('Error processing client {} - {}'.format(client, e))
def sync_hypervisors(self): del self # unused now = utcnow() timestamp = now.isoformat() deletion_timestamp = (now - timedelta(hours=1)).isoformat() hh = HypervisorSyncHandler() version_to_delete = hh.get_version(deletion_timestamp) all_regions = sync_regions(auth_cache=AUTH_CACHE) try: for region in all_regions: for hypervisor in Hypervisors( api_session=IdentityAdminApi().session).get_hypervisors( region=region.id): hh.create_or_update(data=hypervisor, region=region.id, timestamp=timestamp) # delete hypervisors that were not synced in a version represented by a time less than one hour ago delete_filter = { '{}__lt'.format(hh.version_field): version_to_delete, 'region': region.id } Hypervisor.objects.filter(**delete_filter).delete() except Exception as e: LOG.error(str(e)) return
def __init__(self, api_session=None): self.api_session = api_session or IdentityAdminApi().session self.event_handlers = { 'volume.update.start': self.create_or_update, 'volume.create.start': self.create_or_update, 'volume.delete.start': self.create_or_update, 'volume.attach.start': self.create_or_update, 'volume.detach.start': self.create_or_update, 'volume.resize.start': self.create_or_update, 'volume.update.end': self.update_end, 'volume.create.end': self.create_end, 'volume.delete.end': self.delete, 'volume.attach.end': self.create_or_update_attachment, 'volume.detach.end': self.delete_attachment, 'volume.resize.end': self.create_or_update, 'volume.revert.start': self.create_or_update, 'volume.revert.end': self.update_end, 'volume.retype': self.create_or_update, 'volume.exists': self.create_or_update, 'compute.instance.volume.attach': self.volume_attach } self.error_handlers = { 'scheduler.create_volume': self.create_or_update }
def upload_empty_qcow2_image(self, image_id, region_name, disk_size_in_bytes=0): """ Upload an image data to Glance as admin. Do not use this task in user views. """ del self # unused # ensure we have an empty qcow2 file to upload if not path.isdir(settings.FLEIO_TEMP_DIR): os.mkdir(settings.FLEIO_TEMP_DIR) qcow2_file_path = path.join(settings.FLEIO_TEMP_DIR, 'boot_from_iso_img.qcow2') if not path.isfile(qcow2_file_path): subprocess.call([ 'qemu-img', 'create', '-f', 'qcow2', qcow2_file_path, str(disk_size_in_bytes) ]) if not path.isfile(qcow2_file_path): raise IOError('Failed to initialize temporary qcow2 file') admin_api = IdentityAdminApi() gc = glance_client(api_session=admin_api.session, region_name=region_name) with open(qcow2_file_path, mode="rb") as temp_file: gc.images.upload(image_id=image_id, image_data=temp_file)
def run(self, *args, **kwargs): operation_params = json.loads(self.db_operation.params) region = operation_params.get('region') if not region: return self.abort_operation() nc = nova_client( api_session=IdentityAdminApi(request_session=AUTH_CACHE).session, region_name=region) try: instance = nc.servers.get( server={'id': self.db_operation.primary_object_id}) except (Exception, NotFound): instance = None if not instance: resource_usage_log = ResourceUsageLog.objects.filter( resource_uuid=self.db_operation.primary_object_id).order_by( 'start').last() if not resource_usage_log: return self.abort_operation() if not resource_usage_log.end: timestamp = utcnow().isoformat() LOG.info( 'Instance delete operation successfully set the resource usage log end date' ) resource_usage_log.end = timestamp resource_usage_log.save() return self.mark_as_completed() else: LOG.info( 'Instance related resource usage log was already ended by OS messages' ) return self.mark_as_completed()
def __init__(self, api_session=None): self.api_session = api_session or IdentityAdminApi().session self.event_handlers = { 'qos_specs.create': self.create_or_update, 'qos_specs.update': self.create_or_update, 'qos_specs.delete': self.delete, 'qos_specs.delete_keys': self.create_or_update } self.error_handlers = {'qos_specs.create': self.create_error}
def upload_zero_filled_image(self, image_id, region_name, length_in_bytes=0): """ Upload an image data to Glance as admin. Do not use this task in user views. """ del self # unused admin_api = IdentityAdminApi() gc = glance_client(api_session=admin_api.session, region_name=region_name) buffer = BytesIO(bytearray(length_in_bytes)) gc.images.upload(image_id=image_id, image_data=buffer)
def __init__(self, api_session=None): self.api_session = api_session or IdentityAdminApi().session self.event_handlers = { 'backup.delete.start': self.create_or_update_on_deletion_start, 'backup.create.start': self.create_or_update, 'backup.createprogress': self.create_or_update, 'backup.restore.start': self.create_or_update, 'backup.restore.end': self.create_or_update, 'backup.exists': self.create_or_update, 'backup.delete.end': self.delete, 'backup.create.end': self.create_or_update_end, }
def __init__(self, api_session=None): self.api_session = api_session or IdentityAdminApi().session self.event_handlers = { 'magnum.cluster.create': self.create_or_update, 'magnum.cluster.delete': self.create_or_update, 'magnum.cluster.update': self.create_or_update, } self.error_handlers = { 'magnum.cluster.create': self.create_or_update, 'magnum.cluster.delete': self.create_or_update, 'magnum.cluster.update': self.create_or_update, }
def collect(self, project_id, region_name): api_session = IdentityAdminApi().session for collector in self.collector_instances: end_date = utcnow().replace(microsecond=0) last_collected = end_date - datetime.timedelta(days=31) try: collector.collect_events(start_date=last_collected, end_date=end_date, api_session=api_session, region_name=region_name, project_id=project_id) except CollectorException as e: LOG.error(e) continue
def get_network_rbac(network_id, region): """ Network creation and deletion does not trigger rbac events even if rbac rules are created if the network is shared or external, in Mitaka. We sync directly from the API just in case. """ rbac_policies = dict(rbac_policies=list()) try: admin_session = IdentityAdminApi().session nc = neutron_client(api_session=admin_session, region_name=region) rbac_policies = nc.list_rbac_policies(retrieve_all=True, object_id=network_id) except Exception as e: LOG.exception(e) return rbac_policies
def delete_resources(project_id): admin_session = IdentityAdminApi().session gnocchi_cl = gnocchi_client(api_session=admin_session) try: resources = gnocchi_cl.resource.search( query={'=': { 'project_id': project_id }}) for resource in resources: try: gnocchi_cl.resource.delete(resource['id']) except NotFound: pass except Exception as e: LOG.error(e)
def create_router_interface(self, data, region, timestamp): try: port_id = data['router_interface']['port_id'] except KeyError: return admin_session = IdentityAdminApi().session nc = neutron_client(api_session=admin_session, region_name=region) try: port = nc.show_port(port=port_id)['port'] PortSyncHandler().create_or_update(data=port, region=None, timestamp=timestamp) except NotFound: pass
def __init__(self, api_session=None): self.api_session = api_session or IdentityAdminApi().session # TODO: these need to be checked and updated self.event_handlers = { 'snapshot.delete.start': self.create_or_update, 'snapshot.create.start': self.create_or_update, 'snapshot.createprogress': self.create_or_update, 'snapshot.exists': self.create_or_update, 'snapshot.update.start': self.create_or_update, 'snapshot.update.end': self.create_or_update, 'snapshot.revert.start': self.create_or_update, 'snapshot.revert.end': self.create_or_update, 'snapshot.delete.end': self.delete, 'snapshot.create.end': self.create_or_update, 'snapshots.reset_status.start': self.reset_status, 'snapshots.reset_status.end': self.reset_status, }
def delete_openstack_apiusers(self, project_id): del self # unused os_api = IdentityAdminApi() os_user_api = OpenStackUserApi(keystone_client=os_api.client) role_assignments = os_user_api.list_role_assignments(project=project_id, include_names=True) # NOTE(Marius): If a user has more than one role on a project then they will have two entries for that user. users = [ role_assignment.user for role_assignment in role_assignments if role_assignment.user['name'] != plugin_settings.username ] unique_users = {user['id']: user for user in users} for user_id in unique_users.keys(): os_user_api.delete_user(user_id)
def import_image_from_url(self, image_id, url, region_name): """ Upload an image data to Glance as admin, by downloading it first from a URL. Do not use this task in user views. """ del self # unused admin_api = IdentityAdminApi() gc = glance_client(api_session=admin_api.session, region_name=region_name) with requests.get(url, stream=True) as response: response.raise_for_status() temp_image_dir = getattr(settings, 'OPENSTACK_IMAGE_TEMP_DIR', None) with tempfile.TemporaryFile(dir=temp_image_dir, prefix='glance_') as temp_image_file: for chunk in response.iter_content(chunk_size=4096): if chunk: temp_image_file.write(chunk) temp_image_file.seek( 0) # Go to the beginning to be able to read it gc.images.upload(image_id=image_id, image_data=temp_image_file)
def import_image_from_file(self, image_id, region_name, file_path): """ Upload an image data to Glance as admin. Do not use this task in user views. """ del self # unused LOG.info('Uploading image {} in region {} from file {}'.format( image_id, region_name, file_path, )) admin_api = IdentityAdminApi() gc = glance_client(api_session=admin_api.session, region_name=region_name) with open(file_path, mode="rb") as temp_file: try: gc.images.upload(image_id=image_id, image_data=temp_file) finally: filename = str(temp_file.name) os.remove(filename)
def __init__(self): self.event_handlers = { 'compute.instance.create.end': self.create_or_update, 'compute.instance.update': self.create_or_update, 'compute.instance.power_off.end': self.create_or_update, 'compute.instance.power_on.end': self.create_or_update, 'compute.instance.resize.end': self.create_or_update, 'compute.instance.resize.revert.end': self.create_or_update, 'compute.instance.finish_resize.end': self.create_or_update, 'compute.instance.resize.confirm.end': self.create_or_update, 'compute.instance.rescue.end': self.create_or_update, 'compute.instance.unrescue.end': self.create_or_update, 'compute.instance.rebuild.end': self.create_or_update, 'compute.instance.migrate.end': self.create_or_update, 'compute.instance.shutdown.end': self.create_or_update, 'compute.instance.delete.end': self.delete, 'compute.instance.create.start': self.create_or_update, 'compute.instance.delete.start': self.create_or_update } self.error_handlers = {} self.admin_api_session = IdentityAdminApi().session
def get_current_cores(): if 'fleio.openstack' not in settings.INSTALLED_APPS: return 0 from fleio.openstack.api.identity import IdentityAdminApi from fleio.openstack.api.nova import nova_client from fleio.openstack.models import OpenstackRegion physical_cores = 0 for region in OpenstackRegion.objects.all(): try: client = nova_client(api_session=IdentityAdminApi().session, region_name=region.id) for virtual_node in client.hypervisors.list(): cpu_info = virtual_node.cpu_info if isinstance(cpu_info, str): cpu_info = json.loads(cpu_info) physical_cores += int(cpu_info['topology']['cores']) except (ClientException, ConnectTimeout, Unauthorized, ConnectFailure, TypeError, JSONDecodeError, DiscoveryFailure): raise exceptions.APIException() except EndpointNotFound: # region not available LOG.error( 'Region not found when attempting to get number of cores for region {}, ignoring' .format(region.id), ) except ConfigException: # configuration error LOG.exception( 'Invalid configuration when attempting to get number of cores for region {}, ignoring' .format(region.id), ) # region not available except Exception as e: del e # unused LOG.exception( 'Exception when attempting to get number of cores for region {}, ignoring' .format(region.id), ) return physical_cores
def to_internal_value(self, data): """ Perform any data modification here. to_internal_value is called before .validate() and after each field is validated. """ request = self.context.get('request', None) assert request, 'Serializer can only be used with http requests' value = super(AdminInstanceCreateSerializer, self).to_internal_value(data) errors = OrderedDict() db_region = value['region'] client = value['client'] flavor = value['flavor'] boot_source = value['boot_source'] share_image = value['share_image'] # Try to get a project by client project = client.first_project if project is None: raise ValidationError({ 'detail': _('Unable to find a client with an OpenStack project associated' ) }) value['project'] = project # Validate boot source if boot_source['source_type'] in ('image', 'owned_image', 'shared_image', 'requested_image', 'community_image'): try: openstack_models.Image.objects.get_images_for_project( project_id=project.project_id).get( id=boot_source['source_id']) except openstack_models.Image.DoesNotExist: # Share the image with the client's project if it exists if share_image: try: db_image = openstack_models.Image.objects.get( id=boot_source['source_id']) except openstack_models.Image.DoesNotExist: raise ValidationError( {'boot_source': _('Image not found')}) else: try: request_session = getattr( self.context.get('request'), 'session', None) admapi = IdentityAdminApi( request_session=request_session) if db_image.visibility == OpenStackImageVisibility.PRIVATE: api_image = Image(db_image=db_image, api_session=admapi.session) api_image.set_visibility( visibility=OpenStackImageVisibility.SHARED) api_image.create_member( member_project_id=client.first_project. project_id) elif db_image.visibility == OpenStackImageVisibility.SHARED: api_image = Image(db_image=db_image, api_session=admapi.session) api_image.create_member( member_project_id=client.first_project. project_id) except Exception as e: LOG.exception(e) raise ValidationError({ 'boot_source': _('Unable to boot: {}').format(e) }) else: raise ValidationError( {'boot_source': _('Image not found')}) else: try: if boot_source['source_type'] in ('volume', 'requested_volume'): openstack_models.Volume.objects.get( id=boot_source['source_id'], project__project_id=project.project_id) elif boot_source['source_type'] == 'volume_snapshot': openstack_models.VolumeSnapshot.objects.get( id=boot_source['source_id'], project__project_id=project.project_id) else: openstack_models.Volume.objects.get( id=boot_source['source_id'], project__project_id=project.project_id) except openstack_models.Volume.DoesNotExist: raise ValidationError( {'boot_source': _('Volume not available')}) except openstack_models.VolumeSnapshot.DoesNotExist: raise ValidationError( {'boot_source': _('Volume snapshot not available')}) # Nics compute_api_version = APIVersion(plugin_settings.COMPUTE_API_VERSION) nics = value.get('nics') if nics: value['nics'] = [{'net-id': n} for n in nics] elif compute_api_version > APIVersion('2.37'): if plugin_settings.AUTO_ALLOCATED_TOPOLOGY: value['nics'] = 'auto' else: value[ 'nics'] = 'none' # neutron expects it as none string rather than bool # SSH Keys ssh_keys = value.get('ssh_keys', None) if ssh_keys: ssh_keys = json.loads(ssh_keys) pkm_keys_dict = {} for ssh_key in ssh_keys: try: pkm_key = PublicKey.objects.get( id=ssh_key, user__in=client.users.all()) pkm_keys_dict[ssh_key] = newlines_substract( pkm_key.public_key) except PublicKey.DoesNotExist: errors['ssh_keys'] = [_('SSH Key not found')] value['ssh_keys'] = pkm_keys_dict # Set the actual flavor. Note that flavor names are unique per region. if flavor.region != db_region: errors['flavor'] = [_('Flavor not in {}'.format(db_region.id))] if errors: raise ValidationError(errors) return value
def identity_admin_api(self): if hasattr(self, 'request'): return IdentityAdminApi(request_session=self.request.session) else: return IdentityAdminApi()
def create_project(self, client, openstack_product=None, openstack_product_cycle=None, **kwargs): """ Create the project with the OpenStack Keystone API, add `admin` (plugin_settings.USERNAME) user rights (plugin_settings.DEFAULT_ROLE) to it and return the corresponding Fleio database object. """ extra_fields = kwargs.copy() admin_api = IdentityAdminApi() service_external_id = extra_fields.pop('service_external_id', None) if 'project_id' not in extra_fields: project_context = {'client': client} try: project_name = Template(settings.plugin_settings.default_project_name).render(Context(project_context)) desc_tpl = settings.plugin_settings.default_project_description project_description = Template(desc_tpl).render(Context(project_context)) except Exception as e: LOG.exception(e) project_name = '{} - {}'.format(client.name, client.id) project_description = 'Fleio created for {}'.format(client.name) project = admin_api.create_project(project_name, settings.plugin_settings.PROJECT_DOMAIN_ID, project_description) admin_api.grant_user_role(project.id, settings.plugin_settings.USERNAME, settings.plugin_settings.DEFAULT_ROLE) extra_fields['project_id'] = project.id extra_fields['name'] = project_name extra_fields['description'] = project_description else: admin_api.grant_user_role(extra_fields['project_id'], settings.plugin_settings.USERNAME, settings.plugin_settings.DEFAULT_ROLE) if openstack_product is None: # no openstack product provided, get product from client configuration client_configuration = client.billing_settings try: openstack_product = Product.objects.get(id=client_configuration.auto_order_service) except Product.DoesNotExist: openstack_product = Product.objects.filter(product_type='openstack').first() if openstack_product: cycle_id = client_configuration.auto_order_service_cycle openstack_product_cycle = openstack_product.cycles.filter(id=cycle_id).first() else: openstack_product_cycle = None try: with transaction.atomic(): # create service service = self.create_service(client, openstack_product, openstack_product_cycle, service_external_id) # create project db_project = self.create(service=service, **extra_fields) except IntegrityError: # TODO: we are getting integrity errors because updated manages to create project first # attempt to update existing project db_project = self.filter(project_id=extra_fields['project_id']).first() if db_project is not None: with transaction.atomic(): # create service for project service = self.create_service( client, openstack_product, openstack_product_cycle, service_external_id ) db_project.service = service db_project.save(update_fields=['service']) else: LOG.error('Failed to create or update project') return db_project
def gnocchi_admin(self): if self.gca is None: self.gca = gnocchi_client(api_session=IdentityAdminApi().session, region_name=self.region_name) return self.gca
def create_instance_from_iso_task(volume_id, project_id, project_domain_id, region_name, name, image, flavor, nics, block_device_mapping_v2, block_device_mapping, user_data, admin_pass=None, key_name=None, key_content=None, **create_args): boot_image_id = image identity_admin_api = IdentityAdminApi() # wait for image if not wait_for( lambda: Image.objects.filter(id=boot_image_id).first().status == OpenStackImageStatus.ACTIVE, 600): raise InstanceTaskException(_('Upload image failed ')) region = OpenstackRegion.objects.get(id=region_name) boot_image_model = Image.objects.get(id=boot_image_id) unique_name = '{}'.format(uuid4()) os_image_api = Images(api_session=identity_admin_api.session) # copy properties starting with hw_ to new image extra_properties = {} prefixes = getattr(settings, 'OPENSTACK_CREATE_FROM_ISO_PROPERTY_PREFIXES', []) for property_name in boot_image_model.properties: # type: str for prefix in prefixes: if property_name.startswith(prefix): extra_properties[property_name] = boot_image_model.properties[ property_name] owner = project_id if project_id else identity_admin_api.project_id disk_format = getattr(settings, 'OPENSTACK_CREATE_FROM_ISO_IMAGE_TYPE', 'raw') try: new_image = os_image_api.create( owner=owner, name=unique_name, min_disk=1, min_ram=1, container_format='bare', disk_format=disk_format, visibility='community', protected=False, architecture=boot_image_model.architecture, os_distro=boot_image_model.os_distro, os_version=boot_image_model.os_version, region=region, hypervisor_type=boot_image_model.hypervisor_type, file=None, url=None, source=None, properties=extra_properties, ) except Exception as e: del e # unused LOG.exception( 'Create instance failed. (owner: {}, disk_format: {}, extra_properties: {}' .format(owner, disk_format, extra_properties)) return None else: try: if disk_format == 'qcow2': upload_empty_qcow2_image(new_image.id, region_name=region_name, disk_size_in_bytes=1) else: upload_zero_filled_image(new_image.id, region_name=region_name, length_in_bytes=1) except Exception as e: LOG.exception( 'Failed to create temporary image when booting from iso: {}'. format(e)) try: db_image = Image.objects.get(id=new_image.id) os_image_api.get(image=db_image).delete() except Exception as e: LOG.exception('Failed to delete image: {}'.format(e)) return None instance_id = create_instance_task( volume_id=volume_id, project_id=project_id, project_domain_id=project_domain_id, region_name=region_name, name=name, image=new_image.id, flavor=flavor, admin_pass=admin_pass, nics=nics, key_name=key_name, key_content=key_content, block_device_mapping_v2=block_device_mapping_v2, user_data=user_data, block_device_mapping=block_device_mapping, **create_args, ) activity_helper.add_current_activity_params(object_id=instance_id) if not wait_for( lambda: ModelInstance.objects.filter(id=instance_id).first(), max_time=300): raise InstanceTaskException(_('Failed to create instance')) if not wait_for(lambda: ModelInstance.objects.filter(id=instance_id). first().status == 'active', max_time=300): raise InstanceTaskException(_('Failed to create instance')) if not wait_for(lambda: not ModelInstance.objects.filter( id=instance_id).first().task_state, max_time=300): raise InstanceTaskException(_('Failed to create instance')) try: db_image = Image.objects.get(id=new_image.id) os_image_api.get(image=db_image).delete() except Exception as e: LOG.exception('Failed to delete image: {}'.format(e)) instance_model = ModelInstance.objects.get(id=instance_id) instance_model.booted_from_iso = True instance_model.save() instance_api = Instance.with_admin_session(instance=instance_model) instance_api.rescue(image=boot_image_id) signal_boot_from_iso.delay(instance_id=instance_id, is_new_instance=True) return instance_id
def move_instance_task(self, instance_id: str, destination_project_id: str): del self # unused # intentionally let this throw an error to fail task if UUID not found in DB db_instance = ModelInstance.objects.get(id=instance_id) api_instance = Instance.with_admin_session(instance=db_instance) destination_project = OpenstackProject.objects.get( project_id=destination_project_id) identity_admin_api = IdentityAdminApi() unique_name = '{}.{}.{}'.format('move', api_instance.instance.id, uuid4()) if api_instance.instance.status == 'active': api_instance.stop() if not wait_for( lambda: ModelInstance.objects.get(id=api_instance.instance.id). status == 'stopped', max_time=300, ): raise InstanceTaskException( _('Move instance: failed to stop source instance')) api_instance.instance.refresh_from_db() api_instance.create_snapshot(unique_name) if not wait_for( lambda: ModelImage.objects.filter(name=unique_name).count() > 0, max_time=300, ): raise InstanceTaskException( _('Move instance: failed to create source instance snapshot')) if not wait_for( lambda: ModelImage.objects.filter(name=unique_name).first().status == OpenStackImageStatus.ACTIVE, max_time=300, ): raise InstanceTaskException( _('Move instance: failed to create source instance snapshot')) db_image = ModelImage.objects.get(name=unique_name) os_image = APIImages(api_session=identity_admin_api.session).get( image=db_image) # type: APIImage os_image.set_visibility(visibility=OpenStackImageVisibility.SHARED) os_image.create_member(member_project_id=destination_project.project_id) nics = [] for port in OpenstackPort.objects.filter( device_id=api_instance.instance.id).all(): if port.network: nic = { 'net-id': port.network.id, } if len(port.fixed_ips) > 0: api_port = APIPorts( api_session=identity_admin_api.session).get( port=port) # type: APIPort args = { 'region': api_instance.instance.region, 'fixed_ips': [port.fixed_ips[0]] } api_port.remove_ip(kwargs=args) nic['v4-fixed-ip'] = port.fixed_ips[0]['ip_address'] del port.fixed_ips[0] port.save() nics.append(nic) new_instance_id = create_instance_task( volume_id=None, project_id=destination_project.project_id, project_domain_id=destination_project.project_domain_id, region_name=api_instance.instance.region, name=api_instance.instance.name, image=db_image.id, flavor=api_instance.instance.flavor_id, admin_pass=None, nics=nics, key_name=None, key_content=None, block_device_mapping_v2=None, block_device_mapping=None) if not wait_for(lambda: ModelInstance.objects.filter(id=new_instance_id). count() > 0, max_time=600): raise InstanceTaskException( _('Move instance: failed to create instance from snapshot')) if not wait_for(lambda: ModelInstance.objects.filter(id=new_instance_id). first().status == 'active', max_time=600): raise InstanceTaskException( _('Move instance: failed to create instance from snapshot')) if not wait_for(lambda: not ModelInstance.objects.filter( id=new_instance_id).first().task_state, max_time=600): raise InstanceTaskException( _('Move instance: failed to create instance from snapshot')) os_image.delete() for port in OpenstackPort.objects.filter( device_id=api_instance.instance.id).all(): if port.network: new_instance_port = OpenstackPort.objects.filter( device_id=new_instance_id, network__id=port.network.id).first() if new_instance_port: api_port = APIPorts( api_session=identity_admin_api.session).get( port=port) # type: APIPort new_instance_api_port = APIPorts( api_session=identity_admin_api.session).get( port=new_instance_port) # type: APIPort for index in range(len(port.fixed_ips)): args = { 'region': api_instance.instance.region, 'fixed_ips': [port.fixed_ips[index]] } api_port.remove_ip(kwargs=args) new_instance_api_port.add_ip(kwargs=args) api_instance.rename('{} ({})'.format(api_instance.instance.name, _('MOVED'))) return True
def openstack_admin_session(self): if self.request and self.request.session: return IdentityAdminApi( request_session=self.request.session).session else: return IdentityAdminApi().session
def create_openstack_service(self, request, pk): del pk # unused # TODO - #1019: implement proper creation of service here serializer = CreateServiceSerializer(data=request.data) serializer.is_valid(raise_exception=True) client = self.get_object() if client.first_project is not None and client.first_project.deleted is False: raise ForbiddenException( {'detail': _('Client already has a project')}) project_id = serializer.validated_data.get('project_id', 'none') if Client.objects.filter( services__openstack_project__project_id=project_id): raise ForbiddenException( {'detail': _('Project already associated with a client')}) openstack_product = Product.objects.get( id=serializer.validated_data['product_id']) openstack_product_cycle = openstack_product.cycles.filter( id=serializer.validated_data['product_cycle_id'])[0] service_external_id = serializer.validated_data.get( 'service_external_id', None) with transaction.atomic(): if serializer.validated_data['create_new_project']: try: ProjectModel.objects.create_project( client=client, openstack_product=openstack_product, openstack_product_cycle=openstack_product_cycle, service_external_id=service_external_id, ) except Conflict: return Response( status=409, data={ 'detail': _('A project already exists for this client') }) except RoleDoesNotExist: # TODO: going to the exact settings page and field isn't implemented yet in frontend # on implementation in frontend change section and configuration_id if necessary # (Issue: https://git.fleio.org/fleio/fleio/issues/1922) if plugin_settings.default_role: error_message = _( 'Role "{}" does not exist in OpenStack. Set an existing role as default ' 'role.').format(plugin_settings.default_role) else: error_message = _( 'OpenStack role was not set in OpenStack settings -> defaults tab. ' 'Set an existing role as default role.') raise ConfigException(message=error_message, section='openstack_plugin_defaults', configuration_id='default_role') else: try: project = IdentityAdminApi( request_session=request.session).client.projects.get( project_id) except NotFound: raise ObjectNotFound({'detail': _('Project not found')}) except ConnectFailure: raise ServiceUnavailable( {'detail': _('Could not connect to openstack')}) with transaction.atomic(): try: ProjectModel.objects.create_project( client=client, openstack_product=openstack_product, openstack_product_cycle=openstack_product_cycle, service_external_id=service_external_id, project_id=project.id, project_domain_id=project.domain_id, disabled=not project.enabled, extras={ 'name': project.name, 'description': project.description, 'is_domain': project.is_domain }).save() except RoleDoesNotExist: # TODO: going to the exact settings page and field isn't implemented yet in frontend # on implementation in frontend change section and configuration_id if necessary # (Issue: https://git.fleio.org/fleio/fleio/issues/1922) if plugin_settings.default_role: error_message = _( 'Role "{}" does not exist in OpenStack. Set an existing role as default ' 'role.').format(plugin_settings.default_role) else: error_message = _( 'OpenStack role was not set in OpenStack settings -> defaults tab. ' 'Set an existing role as default role.') raise ConfigException( message=error_message, section='openstack_plugin_defaults', configuration_id='default_role') return Response({'detail': _('Ok')})
LOG = logging.getLogger(__name__) from django.conf import settings # noqa from fleio.billing.settings import CyclePeriods # noqa from fleio.openstack.models.network_port_traffic import NetworkPortTrafficTypes # noqa from fleio.openstack.api.identity import IdentityAdminApi # noqa from fleio.openstack.metrics import GnocchiMetrics # noqa from fleio.openstack.models import Instance, Project # noqa from fleio.openstack.models import OpenstackRegion, NetworkPortResource # noqa from fleio.openstack.models import Port as PortModel # noqa from fleio.openstack.models import NetworkPortTraffic # noqa os_admin_api = IdentityAdminApi() IGNORE_UNRESOLVED_RESOURCE = True INCOMING_BYTES_METRIC = 'network.incoming.bytes' OUTGOING_BYTES_METRIC = 'network.outgoing.bytes' RESOURCE_LIST_PAGE_SIZE = 100 RESOURCE_TYPE = 'instance_network_interface' BYTES_PER_GB = 1024 * 1024 * 1024 TRAFFIC_DATA_GRANULARITY = getattr(settings, 'TRAFIC_DATA_GRANULARITY', 300) PUBLIC_TRAFFIC_ONLY = getattr(settings, 'INSTANCE_TRAFFIC_DISPLAY', 'all') == 'public'
def get_session(): return IdentityAdminApi().session