Beispiel #1
0
    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)
Beispiel #2
0
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
Beispiel #3
0
    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
Beispiel #4
0
    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)
Beispiel #5
0
    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)
Beispiel #6
0
    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
Beispiel #7
0
    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)
Beispiel #8
0
    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)
Beispiel #9
0
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
Beispiel #10
0
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