Example #1
0
class NetworkIPPlanSerializer(NetworkIPSerializer):
    """
    Read-only serializer. Includes subnet/netmask and network name to NetworkIPSerializer.
    """
    net = s.Field(source='subnet.name')
    subnet = s.Field(source='subnet.ip_network.with_prefixlen')
    vlan_id = s.IntegerField(source='subnet.vlan_id', read_only=True)
class NodeGeolocationSerializer(serializers.ModelSerializer):
    coordinates = serializers.CharField(source='geolocation')
    lat = serializers.Field()
    lon = serializers.Field()

    class Meta:
        model = NodeGeolocation
        fields = ('address', 'coordinates', 'lat', 'lon')
Example #3
0
class SliverSerializer(serializers.UriHyperlinkedModelSerializer):
    id = serializers.Field(source='api_id')
    interfaces = SliverIfaceSerializer(required=False, many=True, allow_add_remove=True)
    properties = serializers.PropertyField()
    data_uri = FakeFileField(field='data', required=False)
    instance_sn = serializers.IntegerField(read_only=True)
    mgmt_net = serializers.Field()
    
    # FIXME remove when api.aggregate supports nested serializers
    # is only required because SliverDefaultsSerializer imports resources
    # serializers, and breaks api.aggregate functionality based on
    # api._registry (see class SliverDefaultsSerializer)
    if is_installed('resources'):
        from resources.serializers import ResourceReqSerializer
        resources = ResourceReqSerializer(many=True, required=False)
    
    class Meta:
        model = Sliver
        exclude = ('data',)
    
    def to_native(self, obj):
        """ hack for implementing dynamic file_uri's on FakeFile """
        self.__object__ = obj
        return super(SliverSerializer, self).to_native(obj)
    
    def validate(self, attrs):
        """ workaround about nested serialization
            sliverifaces need to be validated with an associated sliver
        """
        super(SliverSerializer, self).validate(attrs)
        ifaces = attrs.get('interfaces', []) or []
        for iface in ifaces:
            Sliver.get_registered_ifaces()[iface.type].clean_model(iface)
        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
Example #4
0
class TaskLogEntrySerializer(s.ModelSerializer):
    """
    Serializes vms.models.TaskLogEntry
    """
    username = s.Field(source='get_username')
    object_name = s.Field(source='get_object_name')
    object_alias = s.Field(source='get_object_alias')
    object_type = s.Field(source='object_type')

    class Meta:
        model = TaskLogEntry
        fields = ('time', 'task', 'status', 'username', 'msg', 'detail',
                  'object_name', 'object_alias', 'object_type', 'flag')
class StateSerializer(serializers.ModelSerializer):
    current = serializers.Field()
    last_change_on = serializers.Field()
    url = serializers.URLField(source='get_url')
    verified = serializers.Field(source='ssl_verified')
    metadata = serializers.JSONField()
    data = serializers.JSONField()

    class Meta:
        model = State
        fields = ('url', 'current', 'last_change_on', 'last_seen_on',
                  'last_try_on', 'verified', 'metadata', 'data')
        read_only_fields = ('last_seen_on', 'last_try_on')
Example #6
0
class RecordSerializer(s.InstanceSerializer):
    """
    pdns.models.Record
    """
    _model_ = Record
    _update_fields_ = ('name', 'type', 'content', 'ttl', 'prio', 'disabled')
    _null_fields_ = frozenset({'content', 'ttl', 'prio'})

    id = s.Field()
    domain = s.Field()
    name = s.CharField(max_length=253)  # Validated via pdns.validators
    type = s.ChoiceField(choices=Record.TYPE)
    content = s.CharField(max_length=65535, required=False)
    ttl = s.IntegerField(default=Record.TTL, required=False, min_value=0, max_value=2147483647)
    prio = s.IntegerField(default=Record.PRIO, required=False, min_value=0, max_value=65535)
    disabled = s.BooleanField(default=False)
    changed = s.DateTimeField(read_only=True, required=False)

    # noinspection PyMethodMayBeStatic
    def validate_name(self, attrs, source):
        if source in attrs:
            name = attrs[source]

            if name == '@':
                name = self.object.domain.name

            attrs[source] = name.lower()  # The record name must be always lower-cased (DB requirement)

        return attrs

    def validate(self, attrs):
        record = self.object

        try:
            run_record_validator(record.domain, attrs.get('type', record.type), attrs.get('name', record.name),
                                 attrs.get('content', record.content))
        except RecordValidationError as exc:
            self._errors = exc.message_dict

        return attrs

    def detail_dict(self, **kwargs):
        """Always include id and name"""
        dd = super(RecordSerializer, self).detail_dict(**kwargs)
        dd['id'] = self.object.id
        dd['name'] = self.object.name

        return dd
class ResourceSerializer(serializers.ModelSerializer):
    avail = serializers.Field()
    unit = serializers.CharField(read_only=True)

    class Meta:
        model = Resource
        fields = ['name', 'max_req', 'dflt_req', 'unit', 'avail']
Example #8
0
class NodeSerializer(s.Serializer):
    """
    Node details serializer (read-only).
    """
    hostname = s.Field()
    address = s.Field()
    status = s.IntegerChoiceField(choices=Node.STATUS_DB, read_only=True)
    node_status = s.DisplayChoiceField(source='status',
                                       choices=Node.STATUS_DB,
                                       read_only=True)
    owner = s.SlugRelatedField(slug_field='username', read_only=True)
    is_head = s.BooleanField(read_only=True)
    cpu = s.IntegerField(source='cpu_total', read_only=True)
    ram = s.IntegerField(source='ram_total', read_only=True)
    cpu_free = s.IntegerField(read_only=True)
    ram_free = s.IntegerField(read_only=True)
    ram_kvm_overhead = s.IntegerField(read_only=True)
class UserCreateSerializer(serializers.UriHyperlinkedModelSerializer):
    id = serializers.Field()
    auth_tokens = AuthTokenField(required=False)
    date_joined = serializers.DateTimeField(read_only=True)
    last_login = serializers.DateTimeField(read_only=True)
    
    class Meta:
        model = User
        exclude = ['password', 'groups', 'username', 'email', 'is_active', 'is_superuser']
class ServerSerializer(serializers.UriHyperlinkedModelSerializer):
    id = serializers.Field()
    api = ServerApiSerializer(many=True, allow_add_remove=True)
    properties = serializers.PropertyField()
    
    class Meta:
        model = Server
    
    def validate_tinc(self, attrs, source):
        from tinc.serializers import validate_tinc
        return validate_tinc(self, attrs, source)
class HostCreateSerializer(serializers.UriHyperlinkedModelSerializer):
    id = serializers.Field()
    mgmt_net = MgmtNetConfRelatedField(source='related_mgmtnet')
    tinc = TincHostRelatedField(source='related_tinc', required=False)

    class Meta:
        model = Host
        exclude = ('owner', )

    def validate_tinc(self, attrs, source):
        return validate_tinc(self, attrs, source)
Example #12
0
class SliverIfaceSerializer(serializers.ModelSerializer):
    parent_name = serializers.Field(source='parent')
    
    class Meta:
        model = SliverIface
        fields = ('nr', 'name', 'type', 'parent_name')
    
    def get_identity(self, data):
        try:
            return data.get('nr', None)
        except AttributeError:
            return data
class FirmwareSerializer(serializers.ModelSerializer):
    state = serializers.Field()
    progress = serializers.SerializerMethodField('get_progress')
    next = serializers.SerializerMethodField('get_next')
    description = serializers.SerializerMethodField('get_description')
    content_message = serializers.SerializerMethodField('get_content_message')
    image_url = serializers.HyperlinkedFileField(source='image',
                                                 read_only=True)

    class Meta:
        model = Build
        fields = ('state', 'progress', 'next', 'description',
                  'content_message', 'image_url', 'date')

    def get_state(self, instance):
        if self.build:
            return self.build.state
        return None

    def get_task_info(self, info):
        if self.object:
            task = self.object.task
            result = task.result or {}
            try:
                return result.get(info, None)
            except AttributeError:  # result is an error or exception
                return result
        return None

    def get_progress(self, instance):
        return self.get_task_info('progress')

    def get_next(self, instance):
        return self.get_task_info('next')

    def get_description(self, instance):
        # TODO move to model ?
        if self.object:
            task = self.object.task
            result = task.result or {}
            if self.get_progress(instance) == 100:
                return "Building process finished"
            try:
                return "%s ..." % result.get(
                    'description', 'Waiting for your building task to begin.')
            except AttributeError:  # result is an error or exception
                return result
        return ""

    def get_content_message(self, instance):
        if self.object:
            return self.object.state_description
        return ""
Example #14
0
class VmSerializer(VmBaseSerializer):
    """
    VM details (read-only)
    """
    hostname = s.Field()
    uuid = s.CharField(read_only=True)
    alias = s.Field()
    node = s.SlugRelatedField(slug_field='hostname',
                              read_only=True,
                              required=False)
    owner = s.SlugRelatedField(slug_field='username', read_only=True)
    status = s.DisplayChoiceField(choices=Vm.STATUS, read_only=True)
    node_status = s.DisplayChoiceField(source='node.status',
                                       choices=Node.STATUS_DB,
                                       read_only=True)
    vcpus = s.IntegerField(read_only=True)
    ram = s.IntegerField(read_only=True)
    disk = s.IntegerField(read_only=True)
    ips = s.ArrayField(read_only=True)
    uptime = s.IntegerField(source='uptime_actual', read_only=True)
    locked = s.BooleanField(read_only=True)
class NodeCreateSerializer(serializers.UriHyperlinkedModelSerializer):
    id = serializers.Field()
    properties = serializers.PropertyField()
    arch = serializers.ChoiceField(choices=settings.NODES_NODE_ARCHS, required=True)
    slivers = serializers.RelHyperlinkedRelatedField(many=True, read_only=True,
        view_name='sliver-detail')
    direct_ifaces = DirectIfaceSerializer(required=False, many=True, allow_add_remove=True)
    cert = serializers.Field(source='api.cert')
    boot_sn = serializers.IntegerField(read_only=True)
    api = NodeApiSerializer(required=False)
    
    class Meta:
        model = Node
        exclude = ('set_state',) + FW_CONFIG_FIELDS

    def get_fields(self, *args, **kwargs):
        """
        Filter groups: the user creating this node must be a
        group or node administrator of this group, and the group
        must have node creation allowed (/allow_nodes=true).
        
        """
        fields = super(NodeCreateSerializer, self).get_fields(*args, **kwargs)
        try:
            user = self.context['view'].request.user
        except KeyError: # avoid error when used out of Rest API
            return fields
        queryset = fields['group'].queryset
        if not user.is_superuser:
            msg = " Check if you have group or node administrator roles at the provided group."
            fields['group'].error_messages['does_not_exist'] += msg
            # bug #321: filter by user.id (None for Anonymous users)
            fields['group'].queryset = queryset.filter(
                Q(roles__is_group_admin=True) | Q(roles__is_node_admin=True),
                allow_nodes=True, roles__user=user.id)
        return fields
    
    def validate_tinc(self, attrs, source):
        from tinc.serializers import validate_tinc
        return validate_tinc(self, attrs, source)
Example #16
0
class DcNodeStorageSerializer(s.InstanceSerializer):
    """
    vms.models.NodeStorage
    """
    _model_ = NodeStorage

    node = s.Field(source='node.hostname')
    zpool = s.Field()
    alias = s.Field(source='storage.alias')
    owner = s.Field(source='storage.owner.username')
    access = s.IntegerField(source='storage.access', read_only=True)
    type = s.IntegerField(source='storage.type', read_only=True)
    size = s.IntegerField(
        read_only=True)  # storage.size_total or dc_node.disk if local storage
    size_free = s.IntegerField(
        read_only=True
    )  # storage.size_free or dc_node.disk_free if local storage
    desc = s.Field(source='storage.desc')

    def detail_dict(self, **kwargs):
        # Add dc into detail dict
        return {'dc': self.request.dc}
Example #17
0
class SliceCreateSerializer(serializers.UriHyperlinkedModelSerializer):
    id = serializers.Field()
    expires_on = serializers.DateTimeField(read_only=True)
    instance_sn = serializers.IntegerField(read_only=True)
    properties = serializers.PropertyField()
    isolated_vlan_tag = serializers.IntegerField(read_only=True)
    sliver_defaults = SliverDefaultsSerializer()
    slivers = serializers.RelHyperlinkedRelatedField(many=True, read_only=True,
        view_name='sliver-detail')
    
    class Meta:
        model = Slice
        exclude = ('set_state',)
Example #18
0
class TemplateSerializer(serializers.UriHyperlinkedModelSerializer):
    id = serializers.Field()
    image_uri = FakeFileField(field='image')
    node_archs = serializers.MultiSelectField(choices=NODES_NODE_ARCHS)
    is_active = serializers.BooleanField()
    
    class Meta:
        model = Template
        exclude = ['image']
    
    def to_native(self, obj):
        """ hack for implementing dynamic file_uri's on FakeFile """
        self.__object__ = obj
        return super(TemplateSerializer, self).to_native(obj)
class GroupCreateSerializer(serializers.UriHyperlinkedModelSerializer):
    id = serializers.Field()
    
    class Meta:
        model = Group
        exclude = ('allow_nodes', 'allow_slices', 'user_roles')
Example #20
0
class NodeStorageSerializer(s.InstanceSerializer):
    """
    vms.models.NodeStorage
    """
    error_negative_resources = s.ErrorList([_('Value is too low because of existing virtual machines.')])

    _model_ = NodeStorage
    _default_fields_ = ('alias', 'owner', 'size_coef', 'zpool')

    node = s.Field(source='node.hostname')
    zpool = s.ChoiceField(source='zpool')
    alias = s.SafeCharField(source='storage.alias', max_length=32)
    owner = s.SlugRelatedField(source='storage.owner', slug_field='username', queryset=User.objects, required=False)
    access = s.IntegerChoiceField(source='storage.access', choices=Storage.ACCESS, default=Storage.PRIVATE)
    type = s.IntegerChoiceField(source='storage.type', choices=Storage.TYPE, default=Storage.LOCAL)
    size = s.IntegerField(source='storage.size_total', read_only=True)
    size_coef = s.DecimalField(source='storage.size_coef', min_value=0, max_digits=4, decimal_places=2)
    size_free = s.IntegerField(source='storage.size_free', read_only=True)
    created = s.DateTimeField(source='storage.created', read_only=True, required=False)
    desc = s.SafeCharField(source='storage.desc', max_length=128, required=False)

    def __init__(self, request, instance, *args, **kwargs):
        self._update_fields_ = ['alias', 'owner', 'access', 'desc', 'type', 'size_coef']
        super(NodeStorageSerializer, self).__init__(request, instance, *args, **kwargs)

        if not kwargs.get('many', False):
            self._size_coef = instance.storage.size_coef
            self.fields['owner'].queryset = get_owners(request)

            if request.method == 'POST':
                self.fields['zpool'].choices = [(i, i) for i in instance.node.zpools.keys()]
                self._update_fields_.append('zpool')
            else:
                self.fields['zpool'].read_only = True

    def validate_owner(self, attrs, source):
        """Cannot change owner while pending tasks exist"""
        validate_owner(self.object, attrs.get(source, None), _('Storage'))

        return attrs

    def validate_alias(self, attrs, source):
        try:
            value = attrs[source]
        except KeyError:
            pass
        else:
            validate_alias(self.object, value, field_comparison='storage__alias__iexact')

        return attrs

    def validate(self, attrs):
        # Default owner is request.user, but setting this in __init__ does not work
        if 'storage.owner' in attrs and attrs['storage.owner'] is None:
            if self.object.pk:
                del attrs['storage.owner']
            else:
                attrs['storage.owner'] = self.request.user

        return attrs

    @property
    def update_storage_resources(self):
        """True if size_coef changed"""
        return not(self.object.storage.size_coef == self._size_coef)
Example #21
0
class NodeDefineSerializer(s.InstanceSerializer):
    """
    vms.models.Node
    """
    error_negative_resources = s.ErrorList(
        [_('Value is too low because of existing virtual machines.')])

    _model_ = Node
    _update_fields_ = ('status', 'owner', 'is_compute', 'is_backup',
                       'cpu_coef', 'ram_coef', 'monitoring_hostgroups',
                       'monitoring_templates')

    hostname = s.CharField(read_only=True)
    uuid = s.CharField(read_only=True)
    address = s.CharField(read_only=True)
    status = s.IntegerChoiceField(choices=Node.STATUS_DB)
    node_status = s.DisplayChoiceField(source='status',
                                       choices=Node.STATUS_DB,
                                       read_only=True)
    owner = s.SlugRelatedField(slug_field='username',
                               queryset=User.objects,
                               read_only=False)
    is_head = s.BooleanField(read_only=True)
    is_compute = s.BooleanField()
    is_backup = s.BooleanField()
    cpu = s.IntegerField(source='cpu_total', read_only=True)
    ram = s.IntegerField(source='ram_total', read_only=True)
    cpu_coef = s.DecimalField(min_value=0, max_digits=4, decimal_places=2)
    ram_coef = s.DecimalField(min_value=0,
                              max_value=1,
                              max_digits=4,
                              decimal_places=2)
    cpu_free = s.IntegerField(read_only=True)
    ram_free = s.IntegerField(read_only=True)
    ram_kvm_overhead = s.IntegerField(read_only=True)
    sysinfo = s.Field(
        source='api_sysinfo')  # Field is read_only=True by default
    monitoring_hostgroups = s.ArrayField(max_items=16, default=[])
    monitoring_templates = s.ArrayField(max_items=32, default=[])
    created = s.DateTimeField(read_only=True, required=False)

    def __init__(self, request, instance, *args, **kwargs):
        super(NodeDefineSerializer, self).__init__(request, instance, *args,
                                                   **kwargs)
        self.clear_cache = False
        self.status_changed = False
        self.monitoring_changed = False

        if not kwargs.get('many', False):
            # Used for update_node_resources()
            self._cpu_coef = instance.cpu_coef
            self._ram_coef = instance.ram_coef
            # Only active users
            self.fields['owner'].queryset = get_owners(request)

    def validate_owner(self, attrs, source):
        """Cannot change owner while pending tasks exist"""
        validate_owner(self.object, attrs.get(source, None), _('Compute node'))

        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_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_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_monitoring_hostgroups(self, attrs, source):
        """Mark the monitoring change -> used for triggering the signal"""
        if source in attrs and self.object.monitoring_hostgroups != attrs[
                source]:
            self.monitoring_changed = True

        return attrs

    def validate_monitoring_templates(self, attrs, source):
        """Mark the monitoring change -> used for triggering the signal"""
        if source in attrs and self.object.monitoring_templates != attrs[
                source]:
            self.monitoring_changed = True

        return attrs

    @property
    def update_node_resources(self):
        """True if cpu_coef or ram_coef changed"""
        return not (self.object.cpu_coef == self._cpu_coef
                    and self.object.ram_coef == self._ram_coef)
class IslandSerializer(serializers.UriHyperlinkedModelSerializer):
    id = serializers.Field()
    
    class Meta:
        model = Island
Example #23
0
class NodeVersionSerializer(s.Serializer):
    hostname = s.Field()
    version = s.Field(source='system_version')
Example #24
0
class VmSerializer(_VmSerializer):
    dc = s.Field(source='dc.name')
Example #25
0
class NodeDefineSerializer(s.InstanceSerializer):
    """
    vms.models.Node
    """
    error_negative_resources = s.ErrorList(
        [_('Value is too low because of existing virtual machines.')])

    _model_ = Node
    _update_fields_ = ('status', 'owner', 'address', 'is_compute', 'is_backup',
                       'note', 'cpu_coef', 'ram_coef', 'monitoring_hostgroups',
                       'monitoring_templates')

    hostname = s.CharField(read_only=True)
    uuid = s.CharField(read_only=True)
    address = s.ChoiceField()
    status = s.IntegerChoiceField(choices=Node.STATUS_DB)
    node_status = s.DisplayChoiceField(source='status',
                                       choices=Node.STATUS_DB,
                                       read_only=True)
    owner = s.SlugRelatedField(slug_field='username',
                               queryset=User.objects,
                               read_only=False)
    is_head = s.BooleanField(read_only=True)
    is_compute = s.BooleanField()
    is_backup = s.BooleanField()
    note = s.CharField(required=False)
    cpu = s.IntegerField(source='cpu_total', read_only=True)
    ram = s.IntegerField(source='ram_total', read_only=True)
    cpu_coef = s.DecimalField(min_value=0, max_digits=4, decimal_places=2)
    ram_coef = s.DecimalField(min_value=0,
                              max_value=1,
                              max_digits=4,
                              decimal_places=2)
    cpu_free = s.IntegerField(read_only=True)
    ram_free = s.IntegerField(read_only=True)
    ram_kvm_overhead = s.IntegerField(read_only=True)
    sysinfo = s.Field(
        source='api_sysinfo')  # Field is read_only=True by default
    monitoring_hostgroups = s.ArrayField(
        max_items=16,
        default=[],
        validators=(RegexValidator(
            regex=MonitoringBackend.RE_MONITORING_HOSTGROUPS), ))
    monitoring_templates = s.ArrayField(max_items=32, default=[])
    created = s.DateTimeField(read_only=True, required=False)

    def __init__(self, request, instance, *args, **kwargs):
        super(NodeDefineSerializer, self).__init__(request, instance, *args,
                                                   **kwargs)
        self.clear_cache = False
        self.status_changed = False
        self.address_changed = False
        self.old_ip_address = None
        self.monitoring_changed = False

        if not kwargs.get('many', False):
            # Valid node IP addresses
            self.fields['address'].choices = [(ip, ip) for ip in instance.ips]
            # Used for update_node_resources()
            self._cpu_coef = instance.cpu_coef
            self._ram_coef = instance.ram_coef
            # Only active users
            self.fields['owner'].queryset = get_owners(request)

    def validate_owner(self, attrs, source):
        """Cannot change owner while pending tasks exist"""
        validate_owner(self.object, attrs.get(source, None), _('Compute node'))

        return attrs

    def validate_address(self, attrs, source):
        """Mark that node IP address is going to change"""
        new_address = attrs.get(source, None)

        if new_address and self.object.address != new_address:
            self.address_changed = True

            try:
                self.old_ip_address = self.object.ip_address
            except ObjectDoesNotExist:
                self.old_ip_address = None

        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_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_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_monitoring_hostgroups(self, attrs, source):
        """Mark the monitoring change -> used for triggering the signal"""
        if source in attrs and self.object.monitoring_hostgroups != attrs[
                source]:
            self.monitoring_changed = True

        return attrs

    def validate_monitoring_templates(self, attrs, source):
        """Mark the monitoring change -> used for triggering the signal"""
        if source in attrs and self.object.monitoring_templates != attrs[
                source]:
            self.monitoring_changed = True

        return attrs

    @property
    def update_node_resources(self):
        """True if cpu_coef or ram_coef changed"""
        return not (self.object.cpu_coef == self._cpu_coef
                    and self.object.ram_coef == self._ram_coef)

    def save(self):
        """Update compute node attributes in database"""
        node = self.object

        # NOTE:
        # Changing cpu or disk coefficients can lead to negative numbers in node.cpu/ram_free or dc_node.cpu/ram_free
        try:
            with transaction.atomic():
                node.save(update_resources=self.update_node_resources,
                          clear_cache=self.clear_cache)

                if self.update_node_resources:
                    if node.cpu_free < 0 or node.dcnode_set.filter(
                            cpu_free__lt=0).exists():
                        raise IntegrityError('cpu_check')

                    if node.ram_free < 0 or node.dcnode_set.filter(
                            ram_free__lt=0).exists():
                        raise IntegrityError('ram_check')

        except IntegrityError as exc:
            errors = {}
            exc_error = str(exc)
            # ram or cpu constraint was violated on vms_dcnode (can happen when DcNode strategy is set to RESERVED)
            # OR a an exception was raised above
            if 'ram_check' in exc_error:
                errors['ram_coef'] = self.error_negative_resources
            if 'cpu_check' in exc_error:
                errors['cpu_coef'] = self.error_negative_resources

            if not errors:
                raise exc

            return errors

        if self.update_node_resources:  # cpu_free or ram_free changed
            self.reload()

        return None
Example #26
0
class ExtendedVmSerializer(_ExtendedVmSerializer):
    dc = s.Field(source='dc.name')
Example #27
0
class DcNodeSerializer(s.InstanceSerializer):
    """
    vms.models.DcNode
    """
    _model_ = DcNode
    _update_fields_ = ('strategy', 'cpu', 'ram', 'disk', 'priority')
    _default_fields_ = ('cpu', 'ram', 'disk')

    hostname = s.Field(source='node.hostname')
    strategy = s.IntegerChoiceField(choices=DcNode.STRATEGY,
                                    default=DcNode.SHARED)
    priority = s.IntegerField(min_value=0, max_value=9999, default=100)
    cpu = s.IntegerField()
    ram = s.IntegerField()
    disk = s.IntegerField()
    cpu_free = s.IntegerField(read_only=True)
    ram_free = s.IntegerField(read_only=True)
    disk_free = s.IntegerField(read_only=True)
    ram_kvm_overhead = s.IntegerField(read_only=True)

    def __init__(self, request, instance, *args, **kwargs):
        super(DcNodeSerializer, self).__init__(request, instance, *args,
                                               **kwargs)
        if not kwargs.get('many', False):
            # Maximum = node resources
            cpu_n, ram_n, disk_n = instance.node.resources
            self.fields['cpu'].validators.append(
                validators.MaxValueValidator(int(cpu_n)))
            self.fields['ram'].validators.append(
                validators.MaxValueValidator(int(ram_n)))
            self.fields['disk'].validators.append(
                validators.MaxValueValidator(int(disk_n)))

            if request.method == 'PUT':
                # Minimum = used resources in this DC (recalculate from node)
                cpu_min, ram_min, disk_min = instance.node.get_used_resources(
                    request.dc)
            else:
                # Minimum = used resources in this DC (DcNode set - DcNode free)
                cpu_min = (instance.cpu or 0) - instance.cpu_free
                ram_min = (instance.ram or 0) - instance.ram_free
                disk_min = (instance.disk or 0) - instance.disk_free

            self.fields['cpu'].validators.append(
                validators.MinValueValidator(cpu_min))
            self.fields['ram'].validators.append(
                validators.MinValueValidator(ram_min))
            self.fields['disk'].validators.append(
                validators.MinValueValidator(disk_min))

    def validate(self, attrs):
        strategy = int(attrs.get('strategy', self.object.strategy))

        if strategy == DcNode.RESERVED:
            cpu = int(attrs.get('cpu', self.object.cpu))
            ram = int(attrs.get('ram', self.object.ram))
            disk = int(attrs.get('disk', self.object.disk))

            cpu_nf, ram_nf, disk_nf = self.object.get_nonreserved_free_resources(
                exclude_this_dc=True)

            if cpu > cpu_nf:
                self._errors['cpu'] = s.ErrorList(
                    [_('Not enough free CPUs on node.')])

            if ram > ram_nf:
                self._errors['ram'] = s.ErrorList(
                    [_('Not enough free RAM on node.')])

            if disk > disk_nf:
                self._errors['disk'] = s.ErrorList(
                    [_('Not enough free disk space on node.')])

        return attrs

    def detail_dict(self, **kwargs):
        # Add dc into detail dict
        details = super(DcNodeSerializer, self).detail_dict()
        details['dc'] = self.request.dc

        return details