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()
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)
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)
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)
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')
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)
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
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()
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))
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)
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)
def __init__(self, request, hostname, data): super(NodeLogsView, self).__init__(request) self.node = get_node(request, hostname) self.data = data
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()
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()
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
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()
def __init__(self, request, hostname, data): super(NodeUpdateView, self).__init__(request) self.hostname = hostname self.data = data self.node = get_node(request, hostname)
def __init__(self, request, hostname, yyyymm, data): super(NodeSLAView, self).__init__(request) self.node = get_node(request, hostname) self.yyyymm = yyyymm self.data = data