Exemplo n.º 1
0
    def delete(self):
        """Delete [DELETE] image from DB and from Image server.

        The task group is always DC unbound, but the current DC depends on the dc_bound flag:
            - dc_bound=False:   task DC is default DC
            - dc_bound=[DC]:    task DC is dc_bound DC
        The callback is responsible for detaching the image from each DC and deleting it from DB.
        """
        request, img, data = self.request, self.img, self.data

        # Check if image is used by som VMs
        if img.is_used_by_vms():
            raise PreconditionRequired(_('Image is used by some VMs'))

        # Preliminary checks
        self._run_checks()  # This sets self.img_server to ImageVm()

        request.disable_throttling = True
        delete_node_image_tasks = []

        # Run task for removing the image from all NodeStorages which have the image imported locally
        for ns in img.nodestorage_set.select_related('node').all():
            # We need to bypass the permission checks, because node_image can be called by SuperAdmin only
            try:
                res = NodeImageView(request, ns, img, data).delete()
            except Exception as ex:
                res = exception_handler(ex, request)
                if res is None:
                    raise
                res.exception = True
                logger.error('DELETE node_image(%s, %s, %s) failed (%s): %s',
                             ns.node.hostname, ns.zpool, img.name, res.status_code, res.data)
            else:
                logger.info('DELETE node_image(%s, %s, %s) was successful (%s): %s',
                            ns.node.hostname, ns.zpool, img.name, res.status_code, res.data)

            if res.status_code == 200:
                continue
            elif res.status_code == 201:
                delete_node_image_tasks.append(res.data['task_id'])
            else:
                return res

        if self.img_server:
            # Set PENDING status
            img.save_status(Image.PENDING)

            return self._run_execute(LOG_IMAGE_DELETE, 'esimg delete -u %s' % img.uuid,
                                     cb_add={'delete_node_image_tasks': delete_node_image_tasks})

        else:
            if wait_for_delete_node_image_tasks(img, delete_node_image_tasks, timeout=30):
                obj = img.log_list
                owner = img.owner
                img.delete()

                return SuccessTaskResponse(self.request, None, obj=obj, owner=owner, msg=LOG_IMAGE_DELETE,
                                           dc_bound=self.dc_bound)
            else:
                raise PreconditionRequired(_('Image is being deleted from compute node storages; Try again later'))
Exemplo n.º 2
0
def call_api_view(request, method, fun, *args, **kwargs):
    """
    A handy wrapper for calling api view functions or classes.
    """
    # We need a shallow copy of the request object because the original request object is still used by our caller
    request = copy(request)

    if method:
        request = set_request_method(request, method, copy_request=False)

    request.disable_throttling = kwargs.pop('disable_throttling', True)
    log_response = kwargs.pop('log_response', False)
    api_class = kwargs.pop('api_class', False)

    try:
        res = fun(request, *args, **kwargs)

        if api_class:
            res = res.response()
    except Exception as ex:
        res = exception_handler(ex, request)
        if res is None:
            raise
        res.exception = True
    finally:
        request.disable_throttling = False

    if log_response:
        logger.info(
            'Called API view %s %s(%s, %s) by user %s in DC %s \n\twith response (%s): %s',
            method, fun.__name__, args, kwargs, request.user, request.dc,
            res.status_code, res.data)

    return res
Exemplo n.º 3
0
    def import_for_vm(cls, request, ns, img, vm):
        """Import image required by VM. Return block_key or raise a FailedDependency API Exception (424)."""
        node = ns.node
        logger.warn(
            'Image %s required for VM %s must be imported to node=%s, zpool=%s',
            img.name, vm, node, ns.zpool)
        img_ns_status = img.get_ns_status(ns)

        if img_ns_status == img.DELETING:  # Someone is currently removing the image from node pool
            # We can't do anything about this
            raise ExpectationFailed(
                'Required disk image is processed by another task')

        block_key = img.get_block_key(ns)

        if img_ns_status == img.IMPORTING:
            logger.warn(
                'Image %s is being imported to node=%s, zpool=%s; vm_manage will be blocked by block_key=%s',
                img, node, ns.zpool, block_key)
            return block_key

        req = set_request_method(request, 'POST')

        try:
            res = cls(req, ns, img, None).post()
        except Exception as ex:
            res = exception_handler(ex, req)
            if res is None:
                raise ex
            res.exception = True

        if res.status_code in (200, 201):
            logger.warn(
                'POST node_image(%s, %s, %s) was successful: %s; task will be blocked by block_key=%s',
                node.hostname, ns.zpool, img.name, res.data, block_key)
            return block_key
        else:
            logger.error(
                'POST node_image(%s, %s, %s) failed: %s (%s): %s; raising 424 API exception',
                node.hostname, ns.zpool, img.name, res.status_code,
                res.status_text, res.data)
            errmsg = get_task_error_message(res.data)
            raise FailedDependency(
                'Cannot import required image %s to node %s (%s: %s)' %
                (img.name, node.hostname, res.status_code, errmsg))