Exemple #1
0
 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)
Exemple #2
0
 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,
     })
Exemple #3
0
 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'))
Exemple #4
0
    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
Exemple #5
0
    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')})
Exemple #6
0
    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')})
Exemple #7
0
    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)
Exemple #8
0
 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')})
Exemple #9
0
 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)
         })
Exemple #10
0
    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)
Exemple #11
0
 def perform_update(self, serializer):
     try:
         serializer.save()
     except IntegrityError as e:
         raise APIBadRequest(e)