Example #1
0
    def _create_disks_and_nics(self, vm):
        """Try to create disks and nics defined by template"""

        for i, data in enumerate(vm.template.vm_define_disk):
            if data:
                if i == 0 and not vm.is_hvm():  # Disk representation within a zone is created together with VM
                    request = set_request_method(self.request, 'PUT')
                    vm_define_disk = VmDefineDiskView(request)
                    logger.info('Updating disk_id=%d for vm %s defined by template %s', i, vm, vm.template)
                    res = vm_define_disk.put(vm, i, data)
                    if res.status_code != scode.HTTP_200_OK:
                        logger.warn('Failed (%s) to modify disk_id=%s in vm %s defined by template %s. '
                                    'Error: %s', res.status_code, i, vm, vm.template, res.data)
                else:
                    request = set_request_method(self.request, 'POST')
                    vm_define_disk = VmDefineDiskView(request)
                    logger.info('Creating disk_id=%d for vm %s defined by template %s', i, vm, vm.template)
                    res = vm_define_disk.post(vm, i, data)
                    if res.status_code != scode.HTTP_201_CREATED:
                        logger.warn('Failed (%s) to add disk_id=%s into vm %s defined by template %s. '
                                    'Error: %s', res.status_code, i, vm, vm.template, res.data)
                        break

        request = set_request_method(self.request, 'POST')
        vm_define_nic = VmDefineNicView(request)
        for i, data in enumerate(vm.template.vm_define_nic):
            if data:
                logger.info('Creating nic_id=%d for vm %s defined by template %s', i, vm, vm.template)
                res = vm_define_nic.post(vm, i, data)
                if res.status_code != scode.HTTP_201_CREATED:
                    logger.warn('Failed (%s) to add nic_id=%s into vm %s defined by template %s. '
                                'Error: %s', res.status_code, i, vm, vm.template, res.data)
                    break
Example #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
Example #3
0
    def _create_disks_and_nics(self, vm):
        """Try to create disks and nics defined by template"""
        # WARNING: This will temporary change the request.method to POST
        request = set_request_method(self.request, 'POST')

        if not vm.json_get_disks():
            vm_define_disk = VmDefineDiskView(request)
            for i, data in enumerate(vm.template.vm_define_disk):
                if data:
                    if i == 0 and not vm.is_kvm():  # Non-global zone's 1st disk can be only modified
                        logger.info('Updating disk_id=%d for vm %s defined by template %s', i, vm, vm.template)
                        res = vm_define_disk.put(vm, i, data)
                        if res.status_code != scode.HTTP_200_OK:
                            logger.warn('Failed (%s) to modify disk_id=%s in vm %s defined by template %s. '
                                        'Error: %s', res.status_code, i, vm, vm.template, res.data)
                    else:
                        logger.info('Creating disk_id=%d for vm %s defined by template %s', i, vm, vm.template)
                        res = vm_define_disk.post(vm, i, data)
                        if res.status_code != scode.HTTP_201_CREATED:
                            logger.warn('Failed (%s) to add disk_id=%s into vm %s defined by template %s. '
                                        'Error: %s', res.status_code, i, vm, vm.template, res.data)
                            break

        if not vm.json_get_nics():
            vm_define_nic = VmDefineNicView(request)
            for i, data in enumerate(vm.template.vm_define_nic):
                if data:
                    logger.info('Creating nic_id=%d for vm %s defined by template %s', i, vm, vm.template)
                    res = vm_define_nic.post(vm, i, data)
                    if res.status_code != scode.HTTP_201_CREATED:
                        logger.warn('Failed (%s) to add nic_id=%s into vm %s defined by template %s. '
                                    'Error: %s', res.status_code, i, vm, vm.template, res.data)
                        break
Example #4
0
def task_status_loop(request, response, task_id, stream=None):
    """
    Loop and check for task result. Send keep-alive whitespace for every loop.
    TODO: Trailing headers are not supported, so status code cannot be changed.
    """
    logger.debug('Starting APISyncMiddleware loop (%s)', request.path)
    logger.info('Waiting for pending task %s status in "%s" streaming loop',
                task_id, stream)
    elapsed = 0
    task_status_request = set_request_method(request, 'GET')

    # Task check loop
    while elapsed < settings.API_SYNC_TIMEOUT:
        if elapsed > 1200:
            nap = 30
        elif elapsed > 60:
            nap = 12
        elif elapsed > 30:
            nap = 6
        elif elapsed > 5:
            nap = 3
        else:
            nap = 1

        sleep(nap)
        elapsed += nap

        result, status = get_task_status(task_id, get_task_result)
        logger.debug('APISyncMiddleware loop (%s) status: %s', request.path,
                     status)

        if status != HTTP_201_CREATED:
            logger.debug('APISyncMiddleware loop finished (%s) in %d seconds',
                         request.path, elapsed)
            logger.info('Task %s finished', task_id)
            res = task_status(task_status_request, task_id=task_id)

            if stream == ES_STREAM_CLIENT:
                yield '%d\n' % res.status_code  # new status code (es knows how to interpret this)

            yield res.rendered_content  # will call render()
            break
        else:
            yield ' '  # keep-alive

    else:  # Timeout
        logger.debug('APISyncMiddleware loop finished with timeout (%s)',
                     request.path)
        logger.warning('Task %s is running too long; no point to wait',
                       task_id)
        yield response  # is already rendered
Example #5
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))
Example #6
0
    def create_from_template(cls, request, vm, vm_define_backup, log=logger):
        """Create backup definitions from vm.template.vm_define_backup list"""
        if vm_define_backup and isinstance(vm_define_backup, list):
            request = set_request_method(request, 'POST')

            for i, data in enumerate(vm_define_backup):
                try:
                    try:
                        bkpdef = data['bkpdef']
                    except KeyError:
                        bkpdef = data['name']

                    disk_id, real_disk_id, zfs_filesystem = get_disk_id(request, vm, data)
                    log.info('Creating backup definition [%d] "%s" for vm=%s, disk_id=%d defined by template %s',
                             i, bkpdef, vm, disk_id, vm.template)
                    define = get_object(request, BackupDefine, {'name': bkpdef, 'vm': vm, 'disk_id': real_disk_id})
                    res = cls(request, data=data).post(vm, define, vm_template=True)

                    if res.status_code != scode.HTTP_201_CREATED:
                        raise APIError('vm_define_backup error [%s]: %s' % (res.status_code, res.data))
                except Exception as ex:
                    log.warn('Failed to create backup definition [%d] for vm=%s defined by template %s with '
                             'data="%s". Error: %s', i, vm, vm.template, data, ex)
Example #7
0
    def choose_node(self, vm):
        """Used by POST vm_manage when node needs to be chosen automatically"""
        new_node = Node.choose(vm)
        err = 'Could not find node with free resources'

        if not new_node:
            raise ExpectationFailed(err)

        old_request = self.request
        self.request = set_request_method(old_request, 'PUT')

        try:
            res = self.put(vm, {'node': new_node.hostname})
        finally:
            self.request = old_request

        if res.status_code != scode.HTTP_200_OK:
            try:
                err = res.data['result']['node']
            except Exception as e:
                logger.exception(e)
            raise ExpectationFailed(err)

        return new_node
Example #8
0
    def _set_vm_tags(self, vm, tags, task_id=None):
        from api.vm.define.vm_define import VmDefineView

        request = set_request_method(self.request, 'PUT')
        VmDefineView(request).put(vm, {'tags': list(tags)}, task_id=task_id)