def perform_create(self, serializer: StaffVolumeCreateSerializer): if not validate_cloud_objects_limit(): raise APIBadRequest( _('Licence cloud objects limit reached. Please check your license.' )) os_api = OSApi.from_project_id( project_id=serializer.validated_data['project'].project_id) volume_source = serializer.validated_data.pop('source', {}) source_type = volume_source.get('source_type') source = volume_source.get('source') source_id = source.pk if source else None try: os_api.volumes.create( name=serializer.validated_data['name'], size=serializer.validated_data['size'], region_name=serializer.validated_data['region'], type=serializer.validated_data.get('type', None), source_type=source_type, source_id=source_id) except EndpointNotFound as e: LOG.error(e) raise APIBadRequest( detail=_('Cinder endpoint not found for region {}').format( serializer.validated_data['region'], )) except Unauthorized as e: LOG.error(e) raise OpenstackAuthError(_('Operation not allowed')) except Exception as e: LOG.error(e) handle(self.request, message=e)
def get_instance_backups_and_backup_schedules(self, request, id): if not staff_active_features.is_enabled('openstack.osbackup'): raise APIBadRequest(_('Backup feature is disabled.')) del request # unused instance = self.get_instance() backup_schedules_qs = OpenStackBackupSchedule.objects.filter(instance__id=instance.uuid) backups = models.Image.objects.filter(type='backup', instance_uuid=instance.uuid) return Response({ 'schedules': BackupScheduleSerializer(instance=backup_schedules_qs, many=True).data, 'backups': images_serializers.ImageBriefSerializer(instance=backups, many=True).data, })
def perform_create(self, serializer): if not validate_cloud_objects_limit(): raise APIBadRequest( _('Licence cloud objects limit reached. Please check your license.' )) serializer.is_valid(raise_exception=True) router_admin_api = Routers(api_session=self.identity_admin_api.session) try: router_admin_api.create(kwargs=serializer.validated_data) except Exception as e: LOG.error(e) handle(self.request, message=_('Unable to create router'))
def check_if_can_move(self, api_instance: APIInstance, client: Client) -> bool: if api_instance.instance.project.service: if api_instance.instance.project.service.client.id == client.id: raise APIBadRequest(_('Instance already belongs to selected client')) instance_details = api_instance.api_instance.to_dict() hypervisor_name = instance_details.get('OS-EXT-SRV-ATTR:hypervisor_hostname') if super().get_instance_hypervisor_details( instance=api_instance, admin_session=self.identity_admin_api.session, hypervisor_name=hypervisor_name )['type'] in ['lxd', 'ironic']: raise APIBadRequest(_('Moving LXD or Ironic instances is not supported')) if api_instance.instance.status == 'error': raise APIBadRequest(_('Instance is in error state')) if len(api_instance.list_attached_volumes()) > 0: raise APIBadRequest(_('Instance has volumes attached')) return True
def remove_interface(self, request, pk): """Remove an interface from a router""" db_router = self.get_object() router_admin_api = Routers(api_session=self.identity_admin_api.session) router = router_admin_api.get(router=db_router) if 'interface_id' not in request.data: raise APIBadRequest(_('Parameter interface_id is missing')) try: router.remove_interface(region=db_router.region.id, interface_id=request.data['interface_id']) except Exception as e: LOG.error(e) handle(self.request, message=_('Unable to remove interface')) return Response({'detail': _('Removing interface in progress')})
def add_interface(self, request, pk): """Add an interface to a router""" db_router = self.get_object() router_admin_api = Routers(api_session=self.identity_admin_api.session) router = router_admin_api.get(router=db_router) if 'subnet' not in request.data: raise APIBadRequest(_('Parameter subnet is missing')) try: router.add_interface(region=db_router.region.id, subnet=request.data['subnet'], ip=request.data.get('ip', None)) except Exception as e: LOG.error(e) handle(self.request, message=_('Unable to add interface')) return Response({'detail': _('Adding interface in progress')})
def create_snapshot(self, request, id): create_snapshot_as_client = request.data.pop('create_snapshot_as_client', False) serializer = InstanceNameSerializer(data=request.data) serializer.is_valid(raise_exception=True) if create_snapshot_as_client: instance = self.get_object() try: project = instance.project except instance.project.DoesNotExist: raise APIBadRequest(_('Instance is not related to any project. Aborting.')) custom_api_session = IdentityUserApi( project.project_id, project.project_domain_id, cache=request.session ).session instances_api = Instances(api_session=custom_api_session) instance_user_api = instances_api.get(db_instance=instance) try: image_uuid = instance_user_api.create_snapshot(name=serializer.validated_data['name']) return Response({'image_uuid': image_uuid}) except Exception as e: LOG.error(e) msg = _('Unable to create snapshot for instance {0}').format(instance.name) handle(self.request, message=msg) else: instance = self.get_instance() try: image_uuid = instance.create_snapshot(name=serializer.validated_data['name']) reseller_resources = user_reseller_resources(self.request.user) if reseller_resources: Image.objects.update_or_create( defaults={ 'reseller_resources': reseller_resources, 'min_disk': 0, 'min_ram': 0, 'region': OpenstackRegion.objects.get(id=instance.instance.region) }, id=image_uuid, ) return Response({'image_uuid': image_uuid}) except Exception as e: LOG.error(e) msg = _('Unable to create snapshot for instance {0}').format(instance.instance.name) handle(self.request, message=msg)
def move(self, request, id): serializer = MoveSerializer(data=request.data) serializer.is_valid(raise_exception=True) api_instance = self.get_instance() try: # NOTE: client should and have a project since serializer checked for this client = Client.objects.get(id=serializer.validated_data['client']) project = client.first_project # type: Project if self.check_if_can_move(api_instance=api_instance, client=client): move_instance_task.delay( instance_id=api_instance.instance.id, destination_project_id=project.project_id) else: raise APIBadRequest('Cannot move instance') except Exception as e: LOG.error(e) exceptions.handle(request, message=_('Cannot move instance.')) return Response({'detail': _('Move in progress')})
def create_backup(self, request, id): if not staff_active_features.is_enabled('openstack.osbackup'): raise APIBadRequest(_('Backup feature is disabled.')) instance = self.get_instance() serializer = BackupSerializer(data=request.data) serializer.is_valid(raise_exception=True) backup_name = serializer.validated_data['backup_name'] backup_type = serializer.validated_data['backup_type'] rotation = serializer.validated_data['rotation'] try: instance.compute_api.servers.backup( server=instance.uuid, backup_name=backup_name, backup_type=backup_type, rotation=rotation ) return Response({ 'detail': _('Backup for instance {} was scheduled for creation').format(instance.instance.name) }) except Exception as e: LOG.error(e) return Response({ 'detail': _('Unable to create backup for instance {0}').format(instance.instance.name) })
def perform_create(self, serializer): if not validate_cloud_objects_limit(): raise APIBadRequest(_('Licence cloud objects limit reached. Please check your license.')) project = serializer.validated_data['project'] region = serializer.validated_data.get('region') nics = serializer.validated_data['nics'] flavor = serializer.validated_data['flavor'] user_supplied_user_data = serializer.validated_data.get('user_data', None) user = serializer.validated_data.get('user', 'root') password = serializer.validated_data.get('root_password') user_data_passwd_template = None if password: password = crypt.crypt(password, crypt.mksalt( method=getattr(settings, 'INSTANCE_PASSWORD_HASH_METHOD', crypt.METHOD_SHA512) )) if user == 'root': user_data_passwd_template = getattr( settings, 'INSTANCE_CLOUD_INIT_ROOT_PASSWORD_SET', '' ).format(root_password=password) else: user_data_passwd_template = getattr( settings, 'INSTANCE_CLOUD_INIT_NEW_USER_AND_PASSWORD_SET', '' ).format(new_user_name=user, new_user_password=password) ssh_keys_set_template = getattr( settings, 'INSTANCE_CLOUD_INIT_SSH_KEYS_SET', '' ).format(user=user) ssh_keys = serializer.validated_data.get('ssh_keys', None) try: final_user_data = parse_user_data_mime( user_data_passwd_template=user_data_passwd_template, user_supplied_user_data=user_supplied_user_data, ssh_keys_set_template=ssh_keys_set_template, keys_content=ssh_keys, additional_userdata=getattr(settings, 'STAFF_INSTANCE_ADDITIONAL_CLOUD_INIT_USERDATA', None), ) except Exception as e: raise APIBadRequest(str(e)) dev_mapping_v1 = serializer.validated_data['boot_source'].get('dev_mapping_v1') dev_mapping_v2 = serializer.validated_data['boot_source'].get('dev_mapping_v2') volume_type = serializer.validated_data['boot_source'].get('volume_type') boot_image = serializer.validated_data['boot_source'].get('image') first_boot_device = serializer.validated_data['boot_source'].get('boot_device') boot_image_id = boot_image.id if boot_image else None create_args = dict(project_id=project.project_id, project_domain_id=project.project_domain_id, region_name=region.id) user_id = self.request.user.id if dev_mapping_v2 and first_boot_device and volume_type: # NOTE(tomo): Volume type was requested, we need to create the volume first # since nova does not support this directly chain = (create_instance_volume.s(source_type=first_boot_device['source_type'], source_id=first_boot_device['uuid'], volume_type=volume_type, volume_size=first_boot_device['volume_size'], **create_args) | wait_for_volume_status.s(status='available', **create_args) | create_instance_task.s(name=serializer.validated_data.get('name'), image=boot_image_id, flavor=flavor.id, nics=nics, user_data=final_user_data, block_device_mapping_v2=dev_mapping_v2, block_device_mapping=dev_mapping_v1, user_id=user_id, **create_args)) chain() else: # TODO(tomo): This create instance task is ran in sync so we can catch the exception below # however, we need to unify this with the above, mainly run the create async and deal with errors # in another way try: boot_from_iso = False if boot_image_id: # wait for image wait_for(lambda: Image.objects.filter(id=boot_image_id).count() > 0, 600) boot_image_model = Image.objects.get(id=boot_image_id) boot_from_iso = boot_image_model.disk_format == 'iso' if boot_from_iso: create_instance_from_iso_task.delay( volume_id=None, name=serializer.validated_data.get('name'), image=boot_image_id, flavor=flavor.id, nics=nics, user_data=final_user_data, block_device_mapping_v2=dev_mapping_v2, block_device_mapping=dev_mapping_v1, **create_args, ) else: instance_id = create_instance_task( volume_id=None, name=serializer.validated_data.get('name'), image=boot_image_id, flavor=flavor.id, nics=nics, user_data=final_user_data, block_device_mapping_v2=dev_mapping_v2, block_device_mapping=dev_mapping_v1, user_id=user_id, **create_args, ) activity_helper.add_current_activity_params(object_id=instance_id) except Unauthorized as e: LOG.error(e) raise exceptions.OpenstackAuthError( _('Project id for client does not exist, or does not have the permission for the operation')) except Exception as e: LOG.error(e) exceptions.handle(self.request, message=e)
def perform_update(self, serializer): try: serializer.save() except IntegrityError as e: raise APIBadRequest(e)