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
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
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
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
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
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
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
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
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
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)
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
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
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
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
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)
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
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
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
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
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
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
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
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
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
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
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
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
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