Пример #1
0
def node_vm_backup_list(request, hostname, data=None):
    """
    List (:http:get:`GET </node/(hostname)/backup>`) all VM backups on a compute node.

    .. http:get:: /node/(hostname)/backup

        :DC-bound?:
            * |dc-no|
        :Permissions:
            * |SuperAdmin|
        :Asynchronous?:
            * |async-no|
        :arg hostname: **required** - Node hostname
        :type hostname: string
        :arg data.full: Return list of objects with all backup details (default: false)
        :type data.full: boolean
        :arg data.disk_id: Filter by original disk number/ID
        :type data.disk_id: integer
        :arg data.vm: Filter by original server hostname
        :type data.vm: string
        :arg data.define: Filter by backup definition
        :type data.define: string
        :arg data.order_by: :ref:`Available fields for sorting <order_by>`: ``name``, ``disk_id``, ``hostname``, \
``size``, ``time``, ``created`` (default: ``-created``)
        :type data.order_by: string
        :status 200: SUCCESS
        :status 403: Forbidden
        :status 404: Node not found
        :status 412: Invalid disk_id
    """
    node = get_node(request, hostname, exists_ok=True, noexists_fail=True)

    return VmBackupList(request, hostname, data, node=node).get()
Пример #2
0
def node_vm_list(request, hostname, data=None):
    """
    List (:http:get:`GET </node/(hostname)/vm>`) VMs existing on a specific compute node (hostname).

    .. http:get:: /node/(hostname)/vm

        :DC-bound?:
            * |dc-no|
        :Permissions:
            * |SuperAdmin|
        :Asynchronous?:
            * |async-no|
        :arg hostname: **required** - Node hostname
        :type hostname: string
        :arg data.full: Return list of objects with some VM details (default: false)
        :type data.full: boolean
        :arg data.extended: Return list of objects with extended VM details (default: false)
        :type data.extended: boolean
        :arg data.order_by: :ref:`Available fields for sorting <order_by>`: ``hostname`` (default: ``hostname``)
        :type data.order_by: string
        :status 200: SUCCESS
        :status 403: Forbidden
    """
    node = get_node(request, hostname)

    return NodeVmView(request, node, data).get(many=True)
Пример #3
0
 def __init__(self, request, hostname, data):
     super(NodeUpdateView, self).__init__(request)
     self.hostname = hostname
     self.data = data
     self.node = get_node(request, hostname)
     self.task_id = task_id_from_request(self.request,
                                         dummy=True,
                                         tt=TT_DUMMY,
                                         tg=TG_DC_UNBOUND)
Пример #4
0
    def __init__(self, request, hostname, data):
        super(NodeVersionView, self).__init__(request)
        self.hostname = hostname
        self.data = data

        if hostname:
            self.node = get_node(request, hostname)
        else:
            self.node = get_nodes(request)
Пример #5
0
    def __init__(self, request, hostname, service, data=None):
        super(NodeServiceStatusView, self).__init__(request)
        self.service = service
        self.hostname = hostname
        self.data = data
        self.node = get_node(request, hostname)
        self.ctrl = NodeServiceControl(self.node)

        if service and service not in self.ctrl.services:
            raise ObjectNotFound(object_name='Service')
Пример #6
0
    def __init__(self, request, hostname, data):
        super(NodeVersionView, self).__init__(request)
        self.hostname = hostname
        self.data = data

        if hostname:
            self.node = get_node(request, hostname)

            if self.data and get_boolean_value(self.data.get('fresh', None)):
                del self.node.system_version  # Remove cached version information
        else:
            self.node = get_nodes(request)
Пример #7
0
def get_node_storages(request,
                      hostname,
                      sr=('storage', 'node', 'storage__owner'),
                      pr=('dc', ),
                      order_by=('zpool', )):
    """Return queryset of NodeStorage objects. Used only by staff users!"""
    node = get_node(request, hostname, exists_ok=True, noexists_fail=True)
    qs = node.nodestorage_set.select_related(*sr).order_by(*order_by)
    extended = output_extended(request)

    if extended:
        qs = qs.prefetch_related(*pr).extra(extended)

    return qs
Пример #8
0
def harvest_vm(request, hostname, data=None):
    """
    Fetch server metadata from compute node and create server(s) in the DB
    (:http:post:`POST </node/(hostname)/vm-harvest>`).

    .. http:post:: /node/(hostname)/vm-harvest

        :DC-bound?:
            * |dc-yes|
        :Permissions:
            * |SuperAdmin|
        :Asynchronous?:
            * |async-yes|
        :arg hostname: **required** - Node hostname
        :type hostname: string
        :arg data.vm: Optional server uuid. Fetch all servers defined on the compute node if not provided
        :type data.vm: string
        :status 200: SUCCESS
        :status 201: PENDING
        :status 400: FAILURE
        :status 403: Forbidden
        :status 404: Node not found
        :status 406: VM already exists
        :status 423: Node is not operational
    """
    node = get_node(request,
                    hostname,
                    dc=request.dc,
                    exists_ok=True,
                    noexists_fail=True)
    vm = data.get('vm', None)

    if vm:
        if Vm.objects.filter(uuid=vm).exists():
            raise ObjectAlreadyExists(model=Vm)

    if node.status != node.ONLINE:
        raise NodeIsNotOperational

    return VmHarvestView(request, node, vm_uuid=vm).post()
Пример #9
0
def node_vm_define_backup_list(request, hostname, data=None):
    """
    List (:http:get:`GET </node/(hostname)/define/backup>`) all backup definitions targeted onto a specific backup node.

    .. http:get:: /node/(hostname)/define/backup

        :DC-bound?:
            * |dc-no|
        :Permissions:
            * |Superadmin|
        :Asynchronous?:
            * |async-no|
        :arg hostname: **required** - Node hostname
        :type hostname: string
        :arg data.full: Return list of objects with all backup definition details (default: false)
        :type data.full: boolean
        :arg data.extended: Include total number of backups for each backup definition (default: false)
        :type data.extended: boolean
        :arg data.order_by: :ref:`Available fields for sorting <order_by>`: ``name``, ``disk_id``, ``hostname``, \
``created`` (default: ``hostname,-created``)
        :type data.order_by: string
        :status 200: SUCCESS
        :status 403: Forbidden
    """
    node = get_node(request, hostname, exists_ok=True, noexists_fail=True)
    extra = output_extended_backup_count(request, data)
    # TODO: check indexes
    bkp_define = BackupDefine.objects.select_related('vm', 'vm__dc', 'node', 'zpool', 'periodic_task',
                                                     'periodic_task__crontab')\
                                     .filter(node=node).order_by(*BackupDefineView.get_order_by(data))

    if extra:
        bkp_define = bkp_define.extra(extra)

    return BackupDefineView(request, data=data).get(None,
                                                    bkp_define,
                                                    many=True,
                                                    extended=bool(extra))
Пример #10
0
    def get(self, hostname, many=False):
        request = self.request
        sr = ('owner', )

        if self.extended:
            ser_class = ExtendedNodeSerializer
            pr = ('dc', )
            extra = {'select': ExtendedNodeSerializer.extra_select}
        else:
            ser_class = NodeSerializer
            pr = ()
            extra = None

        if many:
            if self.full or self.extended:
                nodes = get_nodes(request,
                                  sr=sr,
                                  pr=pr,
                                  extra=extra,
                                  order_by=self.order_by)

                if nodes:
                    # noinspection PyUnresolvedReferences
                    res = ser_class(nodes, many=True).data
                else:
                    res = []
            else:
                res = list(
                    get_nodes(request,
                              order_by=self.order_by).values_list('hostname',
                                                                  flat=True))

        else:
            node = get_node(request, hostname, sr=sr, pr=pr, extra=extra)
            # noinspection PyUnresolvedReferences
            res = ser_class(node).data

        return SuccessTaskResponse(request, res, dc_bound=False)
Пример #11
0
def get_node_storage(request,
                     hostname,
                     zpool,
                     sr=('node', 'storage', 'storage__owner')):
    """Return NodeStorage object. Used only by staff users!"""
    node = get_node(request, hostname, exists_ok=True, noexists_fail=True)
    extended = output_extended(request)

    if extended:
        extra = {'select': extended}
        pr = ('dc', )
    else:
        pr = ()
        extra = None

    return get_object(request,
                      NodeStorage, {
                          'node': node,
                          'zpool': zpool
                      },
                      sr=sr,
                      pr=pr,
                      extra=extra)
Пример #12
0
 def __init__(self, request, hostname, data):
     super(NodeLogsView, self).__init__(request)
     self.node = get_node(request, hostname)
     self.data = data
Пример #13
0
def node_define(request, hostname, data=None):
    """
    Show (:http:get:`GET </node/(hostname)/define>`),
    update (:http:put:`PUT </node/(hostname)/define>`) or
    delete (:http:delete:`DELETE </node/(hostname)/define>`)
    a node definition.

    .. http:get:: /node/(hostname)/define

        :DC-bound?:
            * |dc-no|
        :Permissions:
            * |SuperAdmin|
        :Asynchronous?:
            * |async-no|
        :arg hostname: **required** - Node hostname
        :type hostname: string
        :status 200: SUCCESS
        :status 403: Forbidden
        :status 404: Node not found

    .. http:put:: /node/(hostname)/define

        :DC-bound?:
            * |dc-no|
        :Permissions:
            * |SuperAdmin|
        :Asynchronous?:
            * |async-no|
        :arg hostname: **required** - Node hostname
        :type hostname: string
        :arg data.status: Compute node status (DB only) (1 - maintenance, 2 - online)
        :type data.status: integer
        :arg data.is_compute: Compute capability
        :type data.is_compute: boolean
        :arg data.is_backup: Backup capability
        :type data.is_backup: boolean
        :arg data.note: Custom text information about this compute node
        :type data.note: string
        :arg data.owner: Node owner
        :type data.owner: string
        :arg data.address: Node IP address used for communication between compute nodes, in particular for: \
VM VNC console, \
VM backups, \
VM migration, \
VM replication, \
VM snapshot restore and image creation, \
internal VM and compute node monitoring. \
**WARNING**: Changing this IP address may lead to unexpected behaviour.
        :type data.address: string
        :arg data.cpu_coef: Coefficient for calculating the total number of virtual CPUs
        :type data.cpu_coef: float
        :arg data.ram_coef: Coefficient for calculating the maximum amount of memory available for virtual machines
        :type data.ram_coef: float
        :arg data.monitoring_hostgroups: Custom compute node monitoring hostgroups
        :type data.monitoring_hostgroups: array
        :arg data.monitoring_templates: Custom compute node monitoring templates
        :type data.monitoring_templates: array
        :status 200: SUCCESS
        :status 400: FAILURE
        :status 403: Forbidden
        :status 404: Node not found
        :status 409: Node has pending tasks / Node has related objects with pending tasks

    .. http:delete:: /node/(hostname)/define

        :DC-bound?:
            * |dc-no|
        :Permissions:
            * |SuperAdmin|
        :Asynchronous?:
            * |async-no|
        :arg hostname: **required** - Node hostname
        :type hostname: string
        :arg data.force: Force delete even when compute node has existing servers and backups. \
Use with caution! (default: false)
        :type data.force: boolean
        :status 200: SUCCESS
        :status 400: FAILURE
        :status 403: Forbidden
        :status 404: Node not found
        :status 409: Node has pending tasks / Node has related objects with pending tasks

    """
    node = get_node(request, hostname, sr=('owner', ))

    return NodeDefineView(request, node, data=data).response()
Пример #14
0
    def put(self):
        request, vm = self.request, self.vm

        # only admin
        if not (request.user and request.user.is_admin(request)):
            raise PermissionDenied

        node = vm.node
        apiview = self.apiview
        apiview['force'] = bool(ForceSerializer(data=self.data, default=False))
        queue = vm.node.fast_queue
        new_node_uuid = None
        detail_dict = {}

        if vm.status not in (vm.RUNNING, vm.STOPPED):
            raise VmIsNotOperational('VM is not stopped or running')

        if apiview['force']:
            detail_dict['force'] = True
            # final cmd and empty stdin
            cmd = 'vmadm get %s 2>/dev/null' % vm.uuid
            stdin = None
            block_key = None
            node_param = self.data.get('node')

            if node_param:
                if not request.user.is_staff:
                    raise PermissionDenied

                node = get_node(request, node_param, dc=request.dc, exists_ok=True, noexists_fail=True)

                if node.hostname == vm.node.hostname:
                    raise InvalidInput('VM already has the requested node set in DB')

                apiview['node'] = detail_dict['node'] = node.hostname
                queue = node.fast_queue
                new_node_uuid = node.uuid

        elif vm.json_changed():
            if vm.locked:
                raise VmIsLocked

            json_update = vm.json_update()
            self.check_update(json_update)

            if (vm.json_disks_changed() or vm.json_nics_changed()) and vm.tasks:
                raise VmHasPendingTasks

            # create json suitable for update
            stdin, cmd1 = self.fix_update(json_update)
            self.validate_update(vm, stdin, cmd1)
            stdin = stdin.dump()

            # final cmd
            cmd = cmd1 + 'vmadm update %s >&2; e=$?; vmadm get %s 2>/dev/null; exit $e' % (vm.uuid, vm.uuid)

            # Possible node_image import task which will block this task on node worker
            block_key = self.node_image_import(vm.node, json_update.get('add_disks', []))

        else:  # JSON unchanged and not force
            detail = 'Successfully updated VM %s (locally)' % vm.hostname
            res = SuccessTaskResponse(request, detail, msg=LOG_VM_UPDATE, vm=vm, detail=detail)
            vm_updated.send(TaskID(res.data.get('task_id'), request=request), vm=vm)  # Signal!

            return res

        # Check compute node status after we know which compute node the task is going to be run on
        # The internal vm.node.status checking is disabled in get_vm() in __init__
        if node.status != node.ONLINE:
            raise NodeIsNotOperational

        msg = LOG_VM_UPDATE
        meta = {
            'output': {'returncode': 'returncode', 'stderr': 'message', 'stdout': 'json'},
            'replace_stderr': ((vm.uuid, vm.hostname),), 'msg': msg, 'vm_uuid': vm.uuid, 'apiview': apiview
        }
        callback = ('api.vm.base.tasks.vm_update_cb', {'vm_uuid': vm.uuid, 'new_node_uuid': new_node_uuid})

        logger.debug('Updating VM %s with json: """%s"""', vm, stdin)

        err = True
        vm.set_notready()

        try:
            tid, err = execute(request, vm.owner.id, cmd, stdin=stdin, meta=meta, lock=self.lock, callback=callback,
                               queue=queue, block_key=block_key)

            if err:
                return FailureTaskResponse(request, err, vm=vm)
            else:
                return TaskResponse(request, tid, msg=msg, vm=vm, api_view=apiview, data=self.data,
                                    detail_dict=detail_dict)
        finally:
            if err:
                vm.revert_notready()
Пример #15
0
 def __init__(self, request, hostname, graph_type, data):
     super(NodeHistoryView, self).__init__(request)
     self.node = get_node(request, hostname)
     self.graph_type = graph_type
     self.data = data
Пример #16
0
def node_define(request, hostname, data=None):
    """
    Show (:http:get:`GET </node/(hostname)/define>`),
    update (:http:put:`PUT </node/(hostname)/define>`) or
    delete (:http:delete:`DELETE </node/(hostname)/define>`)
    a node definition.

    .. http:get:: /node/(hostname)/define

        :DC-bound?:
            * |dc-no|
        :Permissions:
            * |SuperAdmin|
        :Asynchronous?:
            * |async-no|
        :arg hostname: **required** - Node hostname
        :type hostname: string
        :status 200: SUCCESS
        :status 403: Forbidden
        :status 404: Node not found

    .. http:put:: /node/(hostname)/define

        :DC-bound?:
            * |dc-no|
        :Permissions:
            * |SuperAdmin|
        :Asynchronous?:
            * |async-no|
        :arg hostname: **required** - Node hostname
        :type hostname: string
        :arg data.status: Compute node status (DB only) (1 - maintenance, 2 - online)
        :type data.status: integer
        :arg data.is_compute: Compute capability
        :type data.is_compute: boolean
        :arg data.is_backup: Backup capability
        :type data.is_backup: boolean
        :arg data.owner: Node owner
        :type data.owner: string
        :arg data.cpu_coef: Coefficient for calculating the the total number of virtual CPUs
        :type data.cpu_coef: float
        :arg data.ram_coef: Coefficient for calculating the maximum amount of memory available for virtual machines
        :type data.ram_coef: float
        :arg data.monitoring_hostgroups: Custom compute node monitoring hostgroups
        :type data.monitoring_hostgroups: array
        :arg data.monitoring_templates: Custom compute node monitoring templates
        :type data.monitoring_templates: array
        :status 200: SUCCESS
        :status 400: FAILURE
        :status 403: Forbidden
        :status 404: Node not found
        :status 409: Node has pending tasks / Node has related objects with pending tasks

    .. http:delete:: /node/(hostname)/define

        :DC-bound?:
            * |dc-no|
        :Permissions:
            * |SuperAdmin|
        :Asynchronous?:
            * |async-no|
        :arg hostname: **required** - Node hostname
        :type hostname: string
        :arg data.force: Force delete even when compute node has existing servers and backups. \
Use with caution! (default: false)
        :type data.force: boolean
        :status 200: SUCCESS
        :status 400: FAILURE
        :status 403: Forbidden
        :status 404: Node not found
        :status 409: Node has pending tasks / Node has related objects with pending tasks

    """
    node = get_node(request, hostname, sr=('owner', ))

    return NodeDefineView(request, node, data=data).response()
Пример #17
0
 def __init__(self, request, hostname, data):
     super(NodeUpdateView, self).__init__(request)
     self.hostname = hostname
     self.data = data
     self.node = get_node(request, hostname)
Пример #18
0
 def __init__(self, request, hostname, yyyymm, data):
     super(NodeSLAView, self).__init__(request)
     self.node = get_node(request, hostname)
     self.yyyymm = yyyymm
     self.data = data