Beispiel #1
0
    def _set_record(self):
        request = self.request
        record_id = self.record_id

        # Check IsSuperAdmin or IsDomainOwner permissions in get_domain
        self.domain = get_domain(request, self.domain_name, exists_ok=True, noexists_fail=True)

        # Records for slave domains cannot be modified
        if request.method != 'GET' and self.domain.type in (Domain.SLAVE, Domain.SUPERSLAVE):
            raise ExpectationFailed(_('Changing DNS records is not allowed for %s domain') % self.domain.type)

        if record_id is None:  # Get many
            records = self.data.get('records', None)
            qs = self.domain.record_set.select_related('domain').order_by(*self.order_by)

            if records is None:
                self.record = qs
            else:
                if not isinstance(records, (tuple, list)):
                    raise InvalidInput('Invalid records')
                self.record = qs.filter(id__in=records)
        else:
            if record_id == 0:  # New record
                self.record = Record(domain=self.domain)
            else:  # Existing record
                self.record = get_object(request, Record, {'domain': self.domain, 'id': record_id}, sr=('domain',),
                                         noexists_fail=True)
Beispiel #2
0
    def __init__(self, request, vm, *args, **kwargs):
        self.dns = None
        self.dns_content = None

        # Cache vm._fqdn hostname/domain pair and find dns record
        # This will also fill the _available_domains list
        if vm and vm.hostname_is_valid_fqdn(cache=False):  # Will return False if DNS_ENABLED is False
            self.dns = Record.get_records_A(vm.hostname, vm.fqdn_domain)
            if self.dns:
                self.dns_content = ', '.join([d.content for d in self.dns])

        # Initial data
        if vm and 'initial' not in kwargs:
            kwargs['initial'] = self._initial_data(request, vm)

        # Parent constructor
        super(ServerSettingsForm, self).__init__(request, vm, *args, **kwargs)

        if vm:
            # noinspection PyProtectedMember
            domains = [(i, i) for i in vm._available_domains]
            # Invalid (empty) domain must be added into domain choices
            if not vm.fqdn_domain:
                domains.append(('', ''))
                self.fields['domain'].required = False
        else:
            domains = [(i, i) for i in Vm.available_domains(request.dc, request.user)]
            if not request.dc.settings.DNS_ENABLED:
                self.fields['domain'].required = False

        # Set available domains
        domains.sort()
        self.fields['domain'].choices = domains
Beispiel #3
0
def record_PTR(vm, ip):
    if ip and vm.dc.settings.DNS_ENABLED:
        ptr_domain = get_ptr_domain_by_ip(vm, ip)
        return Record.get_record_PTR(ip, ptr_domain)

    else:
        return None
Beispiel #4
0
    def add_or_update_record(cls,
                             request,
                             record_type,
                             domain_name,
                             name,
                             content,
                             task_id=None,
                             **kwargs):
        """Called internally by some api functions"""
        if not request.dc.settings.DNS_ENABLED:
            logger.info(
                'DNS support disabled: skipping add_or_update_record(%r, %r, %r %r)',
                record_type, domain_name, name, content)
            return None

        name = name.lower()  # DB constraint c_lowercase_name
        domain = cls.internal_domain_get(domain_name, task_id=task_id)

        try:
            record = Record.objects.get(type=record_type,
                                        name=name,
                                        domain=domain)
        except Record.DoesNotExist:
            logger.info(
                'Adding %s record "%s" with content "%s" on domain "%s"',
                record_type, name, content, domain)
            record = Record(domain=domain)
            method = 'POST'
            data = {
                'type': record_type,
                'domain': domain_name,
                'name': name,
                'content': content
            }
        else:
            logger.info(
                'Updating %s record "%s" with content "%s" on domain "%s"',
                record_type, name, content, domain)
            method = 'PUT'
            data = {'content': content}

        return cls.internal_response(request,
                                     method,
                                     record,
                                     data,
                                     task_id=task_id,
                                     **kwargs)
Beispiel #5
0
def record_PTR(vm, ip):
    if ip and vm.dc.settings.DNS_ENABLED:
        return Record.get_record_PTR(ip)
    else:
        return None
Beispiel #6
0
class RecordView(APIView):
    Domain = Domain
    Record = Record
    _log_failure = False
    dc_bound = False
    order_by_default = ('id',)
    order_by_fields = ('id', 'name', 'type', 'ttl', 'disabled', 'changed')
    order_by_field_map = {'changed': 'change_date'}

    def __init__(self, request, domain_name, record_id, data, record=None, task_id=None, related_obj=None):
        super(RecordView, self).__init__(request)
        self.domain_name = domain_name
        self.record_id = record_id
        self.data = data
        self.task_id = task_id
        self.related_obj = related_obj  # Added into detail dict for task log purposes

        if record:  # Shortcut used by VmDefineSerializer.save_ptr/save_a and NodeDefineView/node_sysinfo_cb
            self.record = record
            self.domain = record.domain
            self._log_failure = True
        else:
            self._set_record()

    def _set_record(self):
        request = self.request
        record_id = self.record_id

        # Check IsSuperAdmin or IsDomainOwner permissions in get_domain
        self.domain = get_domain(request, self.domain_name, exists_ok=True, noexists_fail=True)

        # Records for slave domains cannot be modified
        if request.method != 'GET' and self.domain.type in (Domain.SLAVE, Domain.SUPERSLAVE):
            raise ExpectationFailed(_('Changing DNS records is not allowed for %s domain') % self.domain.type)

        if record_id is None:  # Get many
            records = self.data.get('records', None)
            qs = self.domain.record_set.select_related('domain').order_by(*self.order_by)

            if records is None:
                self.record = qs
            else:
                if not isinstance(records, (tuple, list)):
                    raise InvalidInput('Invalid records')
                self.record = qs.filter(id__in=records)
        else:
            if record_id == 0:  # New record
                self.record = Record(domain=self.domain)
            else:  # Existing record
                self.record = get_object(request, Record, {'domain': self.domain, 'id': record_id}, sr=('domain',),
                                         noexists_fail=True)

    def _fix_detail_dict(self, dd):
        related_obj = self.related_obj

        if related_obj:
            # noinspection PyProtectedMember
            dd[related_obj._meta.verbose_name_raw.lower()] = related_obj.log_name

        return dd

    def log_failure(self, msg):
        if self._log_failure:
            return {
                'detail_dict': self._fix_detail_dict(self.data.copy()),
                'msg': msg,
            }
        else:
            return {}

    def get(self, many=False):
        if many or not self.record_id:
            if self.full:
                if self.record:
                    res = RecordSerializer(self.request, self.record, many=True).data
                else:
                    res = []
            else:
                res = list(self.record.values_list('id', flat=True))
        else:
            res = RecordSerializer(self.request, self.record).data

        return SuccessTaskResponse(self.request, res, dc_bound=False)

    def post(self):
        ser = RecordSerializer(self.request, self.record, data=self.data)

        if not ser.is_valid():
            return FailureTaskResponse(self.request, ser.errors, obj=self.domain, dc_bound=False,
                                       task_id=self.task_id, **self.log_failure(LOG_RECORD_CREATE))

        ser.object.save()

        return SuccessTaskResponse(self.request, ser.data, status=HTTP_201_CREATED, obj=self.domain,
                                   detail_dict=self._fix_detail_dict(ser.detail_dict()), msg=LOG_RECORD_CREATE,
                                   task_id=self.task_id, dc_bound=False)

    def put(self):
        record = self.record
        ser = RecordSerializer(self.request, record, data=self.data, partial=True)

        if not ser.is_valid():
            return FailureTaskResponse(self.request, ser.errors, obj=self.domain, dc_bound=False,
                                       task_id=self.task_id, **self.log_failure(LOG_RECORD_UPDATE))

        ser.object.save()

        return SuccessTaskResponse(self.request, ser.data, obj=self.domain, msg=LOG_RECORD_UPDATE, dc_bound=False,
                                   task_id=self.task_id, detail_dict=self._fix_detail_dict(ser.detail_dict()))

    def delete(self, many=False):
        record = self.record

        if many:
            assert not self.record_id

            if not record:  # SELECT count(*) from record ???
                raise ObjectNotFound(model=Record)

            msg = LOG_RECORDS_DELETE
            dd = {'records': [r.desc for r in record]}
        else:
            msg = LOG_RECORD_DELETE
            dd = {'record': record.desc}

        record.delete()

        return SuccessTaskResponse(self.request, None, obj=self.domain, msg=msg, detail_dict=self._fix_detail_dict(dd),
                                   task_id=self.task_id, dc_bound=False)

    @classmethod
    def internal_response(cls, request, method, record, data, task_id=None, related_obj=None):
        """Called by VmDefineSerializer"""
        return call_api_view(request, method, cls, record.domain.name, record.id, data=data, record=record,
                             task_id=task_id, related_obj=related_obj, api_class=True, log_response=True)

    @classmethod
    def internal_domain_get(cls, domain_name, task_id=None):
        """Used internally by some api functions"""
        try:
            return Domain.objects.get(name=domain_name)
        except Domain.DoesNotExist:
            raise ObjectNotFound(model=Domain, task_id=task_id)

    @classmethod
    @catch_api_exception
    def add_or_update_record(cls, request, record_type, domain_name, name, content, task_id=None, **kwargs):
        """Called internally by some api functions"""
        if not request.dc.settings.DNS_ENABLED:
            logger.info('DNS support disabled: skipping add_or_update_record(%r, %r, %r %r)',
                        record_type, domain_name, name, content)
            return None

        name = name.lower()  # DB constraint c_lowercase_name
        domain = cls.internal_domain_get(domain_name, task_id=task_id)

        try:
            record = Record.objects.get(type=record_type, name=name, domain=domain)
        except Record.DoesNotExist:
            logger.info('Adding %s record "%s" with content "%s" on domain "%s"', record_type, name, content, domain)
            record = Record(domain=domain)
            method = 'POST'
            data = {'type': record_type, 'domain': domain_name, 'name': name, 'content': content}
        else:
            logger.info('Updating %s record "%s" with content "%s" on domain "%s"', record_type, name, content, domain)
            method = 'PUT'
            data = {'content': content}

        return cls.internal_response(request, method, record, data, task_id=task_id, **kwargs)

    @classmethod
    @catch_api_exception
    def delete_record(cls, request, record_type, domain_name, name, task_id=None, **kwargs):
        """Called internally by some api functions"""
        if not request.dc.settings.DNS_ENABLED:
            logger.info('DNS support disabled: skipping delete_record(%r, %r, %r)',
                        record_type, domain_name, name)
            return None

        name = name.lower()  # DB constraint c_lowercase_name
        domain = cls.internal_domain_get(domain_name, task_id=task_id)

        try:
            record = Record.objects.get(name=name, type=record_type, domain=domain)
        except Record.DoesNotExist:
            raise ObjectNotFound(model=Record)

        logger.info('Deleting %s record "%s" on domain "%s"', record_type, name, domain)

        return cls.internal_response(request, 'DELETE', record, {}, task_id=task_id, **kwargs)