def delete(self, vm, data, **kwargs): """Delete VM definition""" if vm.is_deployed(): raise VmIsNotOperational(_('VM is not notcreated')) owner = vm.owner dead_vm = vm.log_list uuid = vm.uuid hostname = vm.hostname alias = vm.alias zabbix_sync = vm.is_zabbix_sync_active() external_zabbix_sync = vm.is_external_zabbix_sync_active() task_id = SuccessTaskResponse.gen_task_id(self.request, vm=dead_vm, owner=owner) # Every VM NIC could have an association to other tables. Cleanup first: for nic in vm.json_get_nics(): # noinspection PyBroadException try: nic_ser = VmDefineNicSerializer(self.request, vm, nic) nic_ser.delete_ip(task_id) except Exception as ex: logger.exception(ex) continue # Finally delete VM logger.debug('Deleting VM %s from DB', vm) vm.delete() try: return SuccessTaskResponse(self.request, None, vm=dead_vm, owner=owner, task_id=task_id, msg=LOG_DEF_DELETE) finally: # Signal! vm_undefined.send(TaskID(task_id, request=self.request), vm_uuid=uuid, vm_hostname=hostname, vm_alias=alias, dc=self.request.dc, zabbix_sync=zabbix_sync, external_zabbix_sync=external_zabbix_sync)
def get_vm_define_nic(request, vm, nic_id=None): """ Like GET api.vm.define.vm_define_nic_list. """ request.method = 'GET' if nic_id is not None: return VmDefineNicSerializer(request, vm, vm.json_get_nics()[nic_id], nic_id=nic_id).data return VmDefineNicSerializer(request, vm, vm.json_get_nics(), many=True).data
def delete(self, vm, nic_id, nics, nic, data): """Delete VM nic definition""" ser = VmDefineNicSerializer(self.request, vm, nic) del nics[nic_id] vm.save_nics(nics, monitoring_ip=ser.get_monitoring_ip(delete=True)) res = SuccessTaskResponse(self.request, None, vm=vm, detail='nic_id=' + str(nic_id + 1), msg=LOG_NIC_DELETE) ser.delete_ip(res.data.get('task_id')) # Set ip.vm to None return res
def get_diff(self, vm): """Show nic differences between active and in db json. Implies full and denies active vm_define_nic.""" def_current = VmDefineNicSerializer(self.request, vm, vm.json_get_nics(), nic_id=None, many=True).data def_active = VmDefineNicSerializer(self.request, vm, vm.json_active_get_nics(), nic_id=None, many=True).data return self._diff_lists(def_active, def_current)
def get(self, vm, nic_id, nics, nic, data, many=False): """Get VM nic definition""" ser = VmDefineNicSerializer(self.request, vm, nic, nic_id=nic_id, many=many) return SuccessTaskResponse(self.request, ser.data, vm=vm)
def _get_vm_define(self, vm): """Get one VM definition""" if self.active: vm.revert_active() res = VmDefineSerializer(self.request, vm).data if self.full: res['disks'] = VmDefineDiskSerializer(self.request, vm, vm.json_get_disks(), many=True).data res['nics'] = VmDefineNicSerializer(self.request, vm, vm.json_get_nics(), many=True).data return res
def put(self, vm, nic_id, nics, nic, data): """Update VM nic definition""" ser = VmDefineNicSerializer(self.request, vm, nic.copy(), nic_id=nic_id, data=data, partial=True) if ser.is_valid(): nics[nic_id].update(ser.jsondata) vm.resolvers = ser.resolvers vm.save_nics(nics, monitoring_ip=ser.get_monitoring_ip()) res = SuccessTaskResponse(self.request, ser.data, vm=vm, detail='nic_id=' + str(nic_id + 1), detail_dict=ser.detail_dict(), msg=LOG_NIC_UPDATE) ser.update_ip(res.data.get('task_id')) # Always update ip.vm return res return FailureTaskResponse(self.request, ser.errors, vm=vm)
def post(self, vm, nic_id, nics, nic, data): """Create VM nic definition""" ser = VmDefineNicSerializer(self.request, vm, nic_id=nic_id, data=data) if ser.is_valid(): nics[nic_id] = ser.jsondata vm.resolvers = ser.resolvers vm.save_nics(nics, monitoring_ip=ser.get_monitoring_ip()) res = SuccessTaskResponse(self.request, ser.data, status=scode.HTTP_201_CREATED, vm=vm, detail='nic_id=' + str(nic_id + 1), detail_dict=ser.detail_dict(), msg=LOG_NIC_CREATE) ser.save_ip(res.data.get('task_id')) # Always save ip.vm return res return FailureTaskResponse(self.request, ser.errors, vm=vm)
def vm_from_json(request, task_id, json, dc, owner=settings.ADMIN_USER, template=True, save=False, update_ips=True, update_dns=True): """Parse json a create new Vm object @param dict json: loaded json dictionary obtained via vmadm get @param int owner: whether to fetch the vm.owner User object. Also indicates an user id, \ which will be used as fallback @param bool template: True if the template should be set according to internal_metadata.template @param Dc dc: Dc object for the Vm @param bool save: Should the new Vm be saved in DB? @param bool update_ips: Update server <-> IpAddress relations. Only performed if save and update_ips are True. @param bool update_dns: Try to update/create DNS record for server's primary IP. Only performed if save is True. @return: new Vm instance """ # noinspection PyUnresolvedReferences hostname_length = VmDefineSerializer.base_fields['hostname'].max_length # noinspection PyUnresolvedReferences alias_length = VmDefineSerializer.base_fields['alias'].max_length # basic information (KeyError) vm = Vm(uuid=json['uuid'], hostname=json['hostname'][:hostname_length], status=Vm.STATUS_DICT[json['state']], dc=dc) vm.new = True brand = json['brand'] # json and json_active vm.json = vm.json_active = json # node & vnc_port (no check) vm.node_id = json.get('server_uuid', None) vm.vnc_port = json.get('vnc_port', None) # alias try: vm.alias = json['internal_metadata']['alias'][:alias_length] except KeyError: try: alias = json['alias'] except KeyError: alias = vm.hostname vm.alias = alias.split('.')[0][:alias_length] logger.warning( 'Alias for new VM %s could not be auto-detected. Fallback to alias=%s', vm, vm.alias) # ostype try: vm.ostype = int(json['internal_metadata']['ostype']) except KeyError: if brand == 'kvm': vm.ostype = Vm.LINUX elif brand == 'lx': vm.ostype = Vm.LINUX_ZONE else: vm.ostype = Vm.SUNOS_ZONE logger.warning( 'OS type for new VM %s could not be auto-detected. Fallback to ostype=%s', vm, vm.ostype) # owner if owner: try: vm.owner = User.objects.get(id=int(json['owner_uuid'])) except (KeyError, ValueError, User.DoesNotExist): vm.owner = User.objects.get(id=owner) logger.warning( 'Owner for new VM %s could not be auto-detected. Fallback to owner=%s', vm, vm.owner) # template if template: tmpname = None try: tmpname = json['internal_metadata']['template'] if tmpname: vm.template = VmTemplate.objects.get( name=json['internal_metadata']['template'], dc=dc) except (KeyError, VmTemplate.DoesNotExist): vm.template = None if tmpname: logger.warning( 'Template "%s" for new VM %s could not be auto-detected', tmpname, vm) # images for img_uuid in vm.get_image_uuids(): Image.objects.get(uuid=img_uuid, dc=dc) # May raise Image.DoesNotExist # subnets for net_uuid in vm.get_network_uuids(): Subnet.objects.get(uuid=net_uuid, dc=dc) # May raise Subnet.DoesNotExist # Initialize uptime now logger.info(vm.update_uptime(force_init=True)) if save: vm.save(sync_json=True, update_node_resources=True, update_storage_resources=True) logger.info('Server %s (%s) was saved', vm.uuid, vm) exc = None primary_ip = None if update_ips: for i, nic in enumerate(vm.json_get_nics()): if 'network_uuid' not in nic: logger.error( 'Server %s NIC ID %s has no network_uuid defined', vm, i) exc = KeyError('network_uuid') break try: net = Subnet.objects.get(uuid=nic['network_uuid'], dc=dc) except Subnet.DoesNotExist as e: exc = e break else: if net.dhcp_passthrough: logger.info( 'Server %s NIC ID %s uses an externally managed network %s', vm, i, net.name) continue ip, err = _vm_save_ip_from_json(vm, net, nic['ip'], allowed_ips=False) if err: logger.critical(err) exc = SystemError(err) break if i == 0: primary_ip = ip for ipaddress in nic.get('allowed_ips', ()): _, err = _vm_save_ip_from_json(vm, net, ipaddress, allowed_ips=True) if err: logger.critical(err) exc = SystemError(err) break if exc: vm.delete() logger.info('Server %s was deleted', json['uuid']) raise exc try: vm_update_ipaddress_usage(vm) except ValueError as exc: vm.delete() logger.info('Server %s was deleted', json['uuid']) raise exc if update_dns and primary_ip: # This will fail silently (exception is logged) VmDefineNicSerializer.save_a(request, task_id, vm, primary_ip) if primary_ip.subnet.ptr_domain: # This will fail silently (exception is logged) VmDefineNicSerializer.save_ptr(request, task_id, vm, primary_ip, primary_ip.subnet, content=vm.hostname) return vm
def vm_from_json(request, task_id, json, dc, owner=settings.ADMIN_USER, template=True, save=False, # noqa: R701 update_ips=True, update_dns=True): """Parse json a create new Vm object @param dict json: loaded json dictionary obtained via vmadm get @param int owner: whether to fetch the vm.owner User object. Also indicates an user id, \ which will be used as fallback @param bool template: True if the template should be set according to internal_metadata.template @param Dc dc: Dc object for the Vm @param bool save: Should the new Vm be saved in DB? @param bool update_ips: Update server <-> IpAddress relations. Only performed if save and update_ips are True. @param bool update_dns: Try to update/create DNS record for server's primary IP. Only performed if save is True. @return: new Vm instance """ # noinspection PyUnresolvedReferences hostname_length = VmDefineSerializer.base_fields['hostname'].max_length # noinspection PyUnresolvedReferences alias_length = VmDefineSerializer.base_fields['alias'].max_length # basic information (KeyError) vm = Vm(uuid=json['uuid'], hostname=json['hostname'][:hostname_length], status=Vm.STATUS_DICT[json['state']], dc=dc) vm.new = True brand = json['brand'] # json and json_active vm.json = vm.json_active = json # node & vnc_port (no check) vm.node_id = json.get('server_uuid', None) vm.vnc_port = json.get('vnc_port', None) # alias try: vm.alias = json['internal_metadata']['alias'][:alias_length] except KeyError: try: alias = json['alias'] except KeyError: alias = vm.hostname vm.alias = alias.split('.')[0][:alias_length] logger.warning('Alias for new VM %s could not be auto-detected. Fallback to alias=%s', vm, vm.alias) # ostype try: vm.ostype = int(json['internal_metadata']['ostype']) except KeyError: if brand == 'kvm': vm.ostype = Vm.LINUX elif brand == 'lx': vm.ostype = Vm.LINUX_ZONE else: vm.ostype = Vm.SUNOS_ZONE logger.warning('OS type for new VM %s could not be auto-detected. Fallback to ostype=%s', vm, vm.ostype) # owner if owner: try: vm.owner = User.objects.get(id=int(json['owner_uuid'])) except (KeyError, ValueError, User.DoesNotExist): vm.owner = User.objects.get(id=owner) logger.warning('Owner for new VM %s could not be auto-detected. Fallback to owner=%s', vm, vm.owner) # template if template: tmpname = None try: tmpname = json['internal_metadata']['template'] if tmpname: vm.template = VmTemplate.objects.get(name=json['internal_metadata']['template'], dc=dc) except (KeyError, VmTemplate.DoesNotExist): vm.template = None if tmpname: logger.warning('Template "%s" for new VM %s could not be auto-detected', tmpname, vm) # images for img_uuid in vm.get_image_uuids(): Image.objects.get(uuid=img_uuid, dc=dc) # May raise Image.DoesNotExist # subnets for net_uuid in vm.get_network_uuids(): if not Subnet.objects.filter(uuid=net_uuid, dc=dc).exists(): # VM uses subnet that doesn't exist in database. Let's create it. # retrieve nic config for the non-existent network from harvested VM nic = vm.get_nic_config(net_uuid) network = IPAddress.get_net_address(nic['ip'], nic['netmask']) logger.warning('VM "%s" uses undefined network "%s/%s" over nic tag "%s". Trying to create it.', vm.name, network, nic['netmask'], nic['nic_tag']) # take the network name from the nic tag net_name = nic['nic_tag'] if Subnet.objects.filter(name=net_name).exists(): logger.info('Network "%s" already exists, adding number at the end', net_name) net_name_number = 1 while net_name_number < 100: net_name = "%s-%s" % (net_name, net_name_number) if not Subnet.objects.filter(name=net_name).exists(): # this name doesn't exist, let's use it break # if there really exist 99 networks with name "${net_name}-${net_name_number}, # subnet creation will fail net_name_number += 1 gateway = None if 'gateway' in nic: gateway = nic['gateway'] mtu = None if 'mtu' in nic: mtu = nic['mtu'] # create the network new_network = Subnet(name=net_name, uuid=net_uuid, nic_tag=nic['nic_tag'], mtu=mtu, network=network, netmask=nic['netmask'], gateway=gateway, owner_id=settings.ADMIN_USER, alias=net_name) new_network.save() # attach network to specified dc new_network.dc.add(dc) if dc.name == settings.VMS_DC_ADMIN: # when attaching network to admin DC, attach it also to main dc main_dc = Dc.objects.get(name=settings.VMS_DC_MAIN) new_network.dc.add(main_dc) # Initialize uptime now logger.info(vm.update_uptime(force_init=True)) if save: vm.save(sync_json=True, update_node_resources=True, update_storage_resources=True) logger.info('Server %s (%s) was saved', vm.uuid, vm) exc = None primary_ip = None if update_ips: for i, nic in enumerate(vm.json_get_nics()): if 'network_uuid' not in nic: logger.error('Server %s NIC ID %s has no network_uuid defined', vm, i) exc = KeyError('network_uuid') break try: net = Subnet.objects.get(uuid=nic['network_uuid'], dc=dc) except Subnet.DoesNotExist as e: exc = e break else: if net.dhcp_passthrough: logger.info('Server %s NIC ID %s uses an externally managed network %s', vm, i, net.name) continue ip, err = _vm_save_ip_from_json(vm, net, nic['ip'], allowed_ips=False) if err: logger.critical(err) exc = SystemError(err) break if i == 0: primary_ip = ip for ipaddress in nic.get('allowed_ips', []): _, err = _vm_save_ip_from_json(vm, net, ipaddress, allowed_ips=True) if err: logger.critical(err) exc = SystemError(err) break if exc: vm.delete() logger.info('Server %s was deleted', json['uuid']) raise exc try: vm_update_ipaddress_usage(vm) except ValueError as exc: vm.delete() logger.info('Server %s was deleted', json['uuid']) raise exc if update_dns and primary_ip: # This will fail silently (exception is logged) VmDefineNicSerializer.save_a(request, task_id, vm, primary_ip) if primary_ip.subnet.ptr_domain: # This will fail silently (exception is logged) VmDefineNicSerializer.save_ptr(request, task_id, vm, primary_ip, primary_ip.subnet, content=vm.hostname) return vm