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 create(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) if not validate_cloud_objects_limit(): raise APIBadRequest(_('Licence cloud objects limit reached. Please check your license.')) try: os_image_api = Images(api_session=self.os_admin_api.session) image = os_image_api.create(owner=self.os_admin_api.project_id, **serializer.validated_data) except Exception as e: LOG.error(e) handle(self.request, message='Unable to create the image') else: headers = self.get_success_headers(serializer.data) data = serializer.data data['id'] = image.id reseller_resources = user_reseller_resources(self.request.user) if reseller_resources: Image.objects.update_or_create( defaults={ 'reseller_resources': reseller_resources, 'min_disk': serializer.validated_data.get('min_disk', 0), 'min_ram': serializer.validated_data.get('min_ram', 0), 'region': serializer.validated_data.get('region') }, id=image.id, ) return Response(data, status=status.HTTP_201_CREATED, headers=headers)
def perform_update(self, serializer): db_image = serializer.instance try: serializer.validated_data.pop('reseller_resources', None) Images(api_session=self.os_admin_api.session).update(db_image, **serializer.validated_data) except Exception as e: LOG.error("Cannot update image, reason: {}".format(repr(e))) handle(self.request, message='Unable to create the image')
def download(self, request, pk): del pk, request # unused if not staff_active_features.is_enabled('openstack.images.download'): raise ForbiddenException(_('Image download not allowed')) db_image = self.get_object() # type: OpenstackImage try: images_api = Images(api_session=self.os_admin_api.session) image_data = images_api.download(image=db_image) except (Exception, HTTPNotFound) as e: if type(e) == HTTPNotFound: raise ObjectNotFound(detail=e.details) LOG.exception(e) handle(self.request) else: response = StreamingHttpResponse(streaming_content=image_data) response['Content-Type'] = 'application/octet-stream' response['Content-Disposition'] = 'attachment; filename="{}"'.format(db_image.name) return response
def deactivate(self, request, pk): del request, pk # unused image = self.get_object() try: Images(api_session=self.os_admin_api.session).deactivate(image=image) except (Exception, HTTPNotFound) as e: if type(e) == HTTPNotFound: raise ObjectNotFound(detail=e.details) LOG.exception(e) handle(self.request) return Response({'detail': _('Image {} deactivated').format(image)})
def get_image(self): db_image = self.get_object() os_api = Images(api_session=self.os_admin_api.session) return os_api.get(image=db_image)
def images(self): return Images(api_session=self.get_session())
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 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