示例#1
0
    def validate_node(self, attrs, source):
        """Basic node validation"""
        node = attrs.get(source, None)

        if not node:
            attrs.pop(source, None)
            return attrs

        vm = self.vm

        if node == vm.node:
            raise s.ValidationError(
                _('Target node is the same as current node.'))

        if node.status != Node.ONLINE:
            raise s.ValidationError(_('Target node is not in online state.'))

        # Check nic tags
        try:
            validate_nic_tags(vm, new_node=node)
        except s.ValidationError:
            raise s.ValidationError(
                _('Some networks are not available on target node.'))

        return attrs
    def validate_base_image_id(self, attrs, source):
        """
        Initialize default base image (if any).
        Check if provided base image ID exists and has compatible
        arch with the node.
        
        """
        value = attrs.get(source, None)
        config = Config.objects.get()
        base_img_qs = config.get_images(self.node)

        if not value:
            base_image = base_img_qs.order_by('-default').first()
            if base_image is None:
                raise serializers.ValidationError(
                    "No base image compatible with the architecture of this "
                    "node.")
            attrs[source] = base_image.pk

        else:
            try:
                base_image = base_img_qs.get(pk=value)
            except BaseImage.DoesNotExist as e:
                raise serializers.ValidationError(
                    "Invalid ID - object does not exist.")

        return attrs
示例#3
0
    def validate_VMS_IMAGE_VM(self, attrs, source):
        try:
            value = attrs[source]
        except KeyError:
            pass
        else:
            if value:
                try:
                    vm = get_vm(self.request,
                                value,
                                exists_ok=True,
                                noexists_fail=True,
                                dc_bound=False)
                except ObjectNotFound as exc:
                    raise s.ValidationError(exc.detail)
                else:
                    if vm.status not in (Vm.RUNNING, Vm.STOPPED):
                        raise s.ValidationError(
                            _('Invalid VM status; VM must be running or stopped.'
                              ))

                    if vm.ostype != Vm.SUNOS_ZONE:
                        raise s.ValidationError(
                            _('Invalid OS type; VM must be a SunOS Zone.'))

                    attrs[source] = vm.uuid

        return attrs
示例#4
0
    def validate_status(self, attrs, source):
        """Mark the status change -> used for triggering the signal.
        Do not allow a manual status change from unlicensed status."""
        try:
            value = attrs[source]
        except KeyError:
            return attrs

        if self.object.status != value:
            node = self.object

            if node.is_unlicensed():
                raise s.ValidationError(
                    _('Cannot change status. Please add a valid license first.'
                      ))

            if node.is_unreachable() or node.is_offline(
            ):  # Manual switch from unreachable and offline state
                if settings.DEBUG:
                    logger.warning(
                        'DEBUG mode on => skipping status checking of node %s',
                        self.object)
                elif not node_ping(self.object, all_workers=False
                                   ):  # requires that node is really online
                    raise s.ValidationError(
                        _('Cannot change status. Compute node is down.'))

            self.clear_cache = True
            self.status_changed = value

        return attrs
    def validate(self, attrs):
        """
        Initialize registry defaults and check if certificate is
        provided for HTTPS base URIs.
        
        """
        base_uri = attrs.get('registry_base_uri', '')
        cert = attrs.get('registry_cert', '')

        if not base_uri:
            if cert:
                raise serializers.ValidationError(
                    {'registry_base_uri': ['this field is required.']})

            # initialize registry defaults
            base_uri = self.get_default_registry().base_uri
            cert = self.get_default_registry().cert or ''
            attrs['registry_base_uri'] = base_uri
            attrs['registry_cert'] = cert

        if base_uri.startswith('https://') and not cert:
            raise serializers.ValidationError(
                "Certificate is required for HTTPS.")

        # serializer is valid - apply changes
        # FIXME(santiago): changes are applied even if fails plugins validation.
        # http://tomchristie.github.io/rest-framework-2-docs/api-guide/serializers#saving-object-state
        gw_name = attrs.get('tinc_default_gateway', None)
        if gw_name:
            default_gateway = TincHost.objects.get(name=gw_name)
            self.node.tinc.default_connect_to = default_gateway
            self.node.tinc.save()
        return attrs
示例#6
0
    def validate_ip(self, attrs, source):
        try:
            value = attrs[source]
        except KeyError:
            return attrs

        net = self.net
        # Was already validated by IPAddressField
        ipaddr = ipaddress.ip_address(text_type(value))
        network = net.ip_network

        if ipaddr not in network:
            raise s.ValidationError(
                _('IP address "%(ip)s" does not belong to network %(net)s.') %
                {
                    'ip': value,
                    'net': net.name
                })

        # Check if IP does not exist in another network with same VLAN ID
        if IPAddress.objects.exclude(subnet=net).filter(
                ip=value, subnet__vlan_id=net.vlan_id).exists():
            raise s.ValidationError(
                _('IP address "%(ip)s" already exists in another network with the same VLAN ID.'
                  ) % {'ip': value})

        return attrs
示例#7
0
    def validate_manifest_url(self, attrs, source):
        try:
            url = attrs[source]
        except KeyError:
            return attrs

        img = self.img

        try:
            req = HttpClient(url)
            res = req.get(timeout=5, max_size=8192)
        except RequestException as e:
            raise s.ValidationError(
                _('Image manifest URL is unreachable (%s).') % e)

        try:
            self.manifest = manifest = res.json()
        except ValueError:
            raise s.ValidationError(_('Could not parse image manifest.'))

        try:
            self.img_file = manifest['files'][0]
            img.uuid = manifest['uuid']
            img.version = manifest['version']
            img.ostype = Image.os_to_ostype(manifest)
            img.size = int(manifest.get('image_size', Image.DEFAULT_SIZE))
            img.desc = manifest.get('description', '')[:128]
            tags = manifest.pop('tags', {})
            img.tags = tags.get(Image.TAGS_KEY, [])
            img.deploy = tags.get('deploy', False)
            img.resize = tags.get('resize', img.ostype in img.ZONE)
        except Exception:
            raise s.ValidationError(_('Invalid image manifest.'))

        if len(manifest['files']) > 1:
            raise s.ValidationError(
                'Multiple files inside manifest are not supported.')

        if img.uuid:
            try:
                x = Image.objects.only('name').get(uuid=img.uuid)
            except Image.DoesNotExist:
                pass
            else:
                raise s.ValidationError(
                    _('Image UUID is already registered by image "%(name)s".')
                    % {'name': x.name})

        return attrs
示例#8
0
    def validate_is_backup(self, attrs, source):
        """Search for existing backup definitions, which are using this node"""
        if source in attrs and self.object.is_backup != attrs[source]:
            if self.object.backupdefine_set.exists():
                raise s.ValidationError(
                    _('Found existing VM backup definitions.'))
            self.clear_cache = True

        # Check existing backups when removing node
        if self.request.method == 'DELETE':
            if self.object.backup_set.exists():
                raise s.ValidationError(_('Found existing VM backups.'))
            self.clear_cache = True

        return attrs
示例#9
0
    def validate_groups(self, attrs, source):
        try:
            value = attrs[source]
        except KeyError:
            pass
        else:
            groups = []

            for grp in value:
                try:
                    group = Role.objects.get(name=grp)
                except Role.DoesNotExist:
                    raise s.ObjectDoesNotExist(grp)
                else:
                    if self.request.user.is_staff:
                        groups.append(group)
                    else:
                        if group.dc_bound and self._dc_bound and group.dc_bound == self._dc_bound:
                            groups.append(group)
                        else:
                            raise s.ValidationError(
                                _('You don\'t have permission to use DC-unbound groups.'
                                  ))

            attrs[source] = groups

        return attrs
示例#10
0
    def validate(self, attrs):
        try:
            zpool = attrs['zpool']
        except KeyError:
            zpool = self.object.zpool

        try:
            node = attrs['node']
        except KeyError:
            node = self.object.node

        try:
            attrs['zpool'] = get_zpools(self.request).get(node=node,
                                                          zpool=zpool)
        except NodeStorage.DoesNotExist:
            self._errors['zpool'] = s.ErrorList(
                [_('Zpool does not exist on node.')])

        # Check total number of existing backup definitions - Issue #chili-447
        if self.request.method == 'POST':
            limit = self.request.dc.settings.VMS_VM_BACKUP_DEFINE_LIMIT

            if limit is not None:
                total = self._model_.objects.filter(vm=self.object.vm).count()
                if int(limit) <= total:
                    raise s.ValidationError(
                        _('Maximum number of backup definitions reached.'))

        return attrs
示例#11
0
    def validate(self, attrs):
        total = UserSSHKey.objects.filter(user=self.object.user).count()

        if total >= settings.PROFILE_SSH_KEY_LIMIT:
            raise s.ValidationError(_('SSH keys limit reached'))

        return attrs
示例#12
0
    def validate(self, attrs):
        db_only_manifest_keys = {'dc_bound', 'dc_bound_bool', 'owner'}

        if db_only_manifest_keys.issuperset(attrs.keys()):
            self.update_manifest = False

        try:
            alias = attrs['alias']
        except KeyError:
            alias = self.object.alias

        try:
            version = attrs['version']
        except KeyError:
            version = self.object.version

        qs = Image.objects

        if self.object.pk:
            qs = qs.exclude(pk=self.object.pk)

        if qs.filter(alias__iexact=alias, version=version).exists():
            self._errors['alias'] = s.ErrorList([_('This alias is already in use. '
                                                   'Please supply a different alias or version.')])

        if self.request.method == 'POST' and self._dc_bound:
            limit = self._dc_bound.settings.VMS_IMAGE_LIMIT

            if limit is not None:
                if Image.objects.filter(dc_bound=self._dc_bound).count() >= int(limit):
                    raise s.ValidationError(_('Maximum number of server disk images reached'))

        return super(ImageSerializer, self).validate(attrs)
示例#13
0
    def validate(self, attrs):
        attrs = super(APIAuthTokenSerializer, self).validate(attrs)

        if not attrs['user'].api_access:
            raise s.ValidationError('User account is not allowed to access API.')

        return attrs
示例#14
0
    def validate_VMS_VM_DOMAIN_DEFAULT(self, attrs, source):
        if self.dc_settings.DNS_ENABLED:
            try:
                value = attrs[source]
            except KeyError:
                pass
            else:
                try:
                    domain = Domain.objects.get(name=value)
                except Domain.DoesNotExist:
                    raise s.ValidationError(_('Object with name=%s does not exist.') % value)
                else:
                    if not self.dc.domaindc_set.filter(domain_id=domain.id).exists():
                        raise s.ValidationError(_('Domain is not available in this datacenter.'))

        return attrs
示例#15
0
    def validate_disk_zpools(self, attrs, source):
        disk_zpools = attrs.get(source, None)

        if disk_zpools:
            if max(disk_zpools.keys()) > len(self._disks):
                raise s.ValidationError(_('Invalid disk_id.'))

        return attrs
示例#16
0
    def validate_is_compute(self, attrs, source):
        """Search for defined VMs when turning compute capability off"""
        if source in attrs and self.object.is_compute != attrs[source]:
            if self.object.vm_set.exists():
                raise s.ValidationError(_('Found existing VMs on node.'))
            self.clear_cache = True

        return attrs
示例#17
0
    def validate(self, attrs):
        if self.request.method == 'POST' and self._dc_bound:
            limit = self._dc_bound.settings.VMS_ISO_LIMIT

            if limit is not None:
                if Iso.objects.filter(dc_bound=self._dc_bound).count() >= int(limit):
                    raise s.ValidationError(_('Maximum number of ISO images reached'))

        return super(IsoSerializer, self).validate(attrs)
示例#18
0
    def validate(self, attrs):
        nic = attrs.get('nic')
        assert nic

        if nic in self.obj.used_nics:
            self.item_id = nic
        else:
            raise s.ValidationError(_('NIC not defined on compute node.'))

        return attrs
示例#19
0
    def validate(self, attrs):
        nic_id = attrs.get('nic_id')
        assert nic_id

        try:
            self.item_id = self.obj.get_real_nic_id(self.obj.json_active_get_nics()[nic_id - 1])
        except IndexError:
            raise s.ValidationError(_('NIC ID not defined on VM.'))

        return attrs
示例#20
0
 def validate_interfaces(self, attrs, source):
     """Check that one interface of type private has been defined."""
     interfaces = attrs.get(source, [])
     
     # check that mandatory private interface has been defined
     priv_ifaces = 0
     for iface in interfaces:
         if iface.type == 'private':
             priv_ifaces += 1
         if priv_ifaces > 1:
             raise serializers.ValidationError('There can only be one interface of type private.')
     if priv_ifaces == 0:
         raise serializers.ValidationError('There must exist one interface of type private.')
     
     validate_private_iface(interfaces)
     
     for name, iface_cls in Sliver.get_registered_ifaces().items():
         validate_ifaces_nr(name, iface_cls, interfaces)
     return attrs
示例#21
0
    def validate(self, attrs):
        zpool = attrs.get('zpool')
        assert zpool

        if zpool in self.obj.zpools:
            self.item_id = zpool
        else:
            raise s.ValidationError(_('Zpool not defined on compute node.'))

        return attrs
示例#22
0
    def validate_access(self, attrs, source):
        try:
            value = attrs[source]
        except KeyError:
            pass
        else:
            if self.object.pk and self.object.is_default() and int(value) != Dc.PUBLIC:
                raise s.ValidationError(_('Default datacenter must be public.'))

        return attrs
示例#23
0
    def validate_tinc_default_gateway(self, attrs, source):
        value = attrs.get(source, None)
        choices = TincHost.objects.servers().values_list('name', flat=True)

        if value is not None and value not in choices:
            raise serializers.ValidationError(
                'Select a valid choice. "%s" is not one of the available '
                'choices.' % value)

        return attrs
示例#24
0
    def validate(self, attrs):
        disk_id = attrs.get('disk_id')
        assert disk_id

        try:
            self.item_id = disk_id - 1  # KVM IO templates are using "array_disk_id"
            self.obj.get_real_disk_id(self.obj.json_active_get_disks()[self.item_id])
        except IndexError:
            raise s.ValidationError(_('Disk ID not defined on VM.'))

        return attrs
示例#25
0
    def validate(self, attrs):
        disk_id = attrs.get('disk_id')
        assert disk_id

        try:
            self.item_id = self.obj.get_real_disk_id(
                self.obj.json_active_get_disks()[disk_id - 1])
        except IndexError:
            raise s.ValidationError(_('Disk ID not defined on VM.'))

        return attrs
示例#26
0
    def validate(self, attrs):
        if self.request.method == 'POST' and self._dc_bound:
            limit = self._dc_bound.settings.VMS_TEMPLATE_LIMIT

            if limit is not None:
                if VmTemplate.objects.filter(
                        dc_bound=self._dc_bound).count() >= int(limit):
                    raise s.ValidationError(
                        _('Maximum number of server templates reached'))

        return attrs
示例#27
0
    def validate_live(self, attrs, source):
        value = attrs.get(source, None)

        if value:
            self._live = True

            if not self.vm.is_kvm():
                raise s.ValidationError(
                    _('Live migration is currently available only for KVM.'))

        return attrs
示例#28
0
    def validate(self, attrs):
        # Check total number of existing snapshot definitions - Issue #chili-447
        if self.request.method == 'POST':
            limit = self.request.dc.settings.VMS_VM_SNAPSHOT_DEFINE_LIMIT

            if limit is not None:
                total = self._model_.objects.filter(vm=self.object.vm).count()
                if int(limit) <= total:
                    raise s.ValidationError(_('Maximum number of snapshot definitions reached.'))

        return attrs
示例#29
0
    def validate_usergroups(self, attrs, source):
        # User groups are created in the monitoring system according to groups in the DB. We should validate this array
        # against groups available in the current DC.
        try:
            groups_requested = set(attrs[source])
        except KeyError:
            pass
        else:
            if not groups_requested:  # The Zabbix API does not allow to set empty operations
                raise s.ValidationError(s.WritableField.default_error_messages['invalid'])

            groups_available = set(Role.objects.filter(dc=self.request.dc, name__in=groups_requested)
                                               .values_list('name', flat=True))
            groups_unavailable = groups_requested - groups_available

            if groups_unavailable:
                raise s.ValidationError([_('User group with name=%s does not exist.') % group
                                         for group in groups_unavailable])

        return attrs
示例#30
0
    def validate(self, attrs):
        if self.object.rep_reinit_required:
            raise s.ValidationError(
                _('Server replica requires re-initialization.'))

        if self.request.method == 'POST':
            total = SlaveVm.objects.filter(
                master_vm=self.object.master_vm).exclude(name=u'').count()
            self.object.rep_id = total + 1
            limit = self.request.dc.settings.VMS_VM_REPLICA_LIMIT

            if limit is not None:
                if int(limit) <= total:
                    raise s.ValidationError(
                        _('Maximum number of server replicas reached.'))

            self._validate_create(attrs)
        else:  # PUT
            self._validate_update(attrs)

        return attrs