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