예제 #1
0
    def get_one(self, zone_id):
        context = pecan.request.environ['context']
        policy.check('zone_export', context)

        zones = self.central_api.export_zone(context, zone_id)

        return zones
예제 #2
0
    def ping(self, context):
        policy.check('diagnostics_ping', context)

        try:
            backend_status = self.backend.ping(context)
        except Exception, e:
            backend_status = {'status': False, 'message': str(e)}
예제 #3
0
    def show_basic(self, context, request, zt_request):
        """Basic view of a ZoneTransferRequest"""

        try:
            target = {
                'tenant_id': zt_request.tenant_id,
            }

            policy.check('get_zone_transfer_request_detailed', context, target)

        except exceptions.Forbidden:
            return {
                "id": zt_request.id,
                "description": zt_request.description,
                "zone_id": zt_request.domain_id,
                "zone_name": zt_request.domain_name,
                "status": zt_request.status,
                "links": self._get_resource_links(request, zt_request)
            }
        else:
            return {
                "id": zt_request.id,
                "description": zt_request.description,
                "zone_id": zt_request.domain_id,
                "zone_name": zt_request.domain_name,
                "target_project_id": zt_request.target_tenant_id,
                "project_id": zt_request.tenant_id,
                "created_at": zt_request.created_at,
                "updated_at": zt_request.updated_at,
                "status": zt_request.status,
                "key": zt_request.key,
                "links": self._get_resource_links(request, zt_request)
            }
예제 #4
0
    def delete_domain(self, context, domain_id):
        domain = self.storage_api.get_domain(context, domain_id)

        target = {
            'domain_id': domain_id,
            'domain_name': domain['name'],
            'tenant_id': domain['tenant_id']
        }

        policy.check('delete_domain', context, target)

        # Prevent deletion of a zone which has child zones
        criterion = {'parent_domain_id': domain_id}

        if self.storage_api.count_domains(context, criterion) > 0:
            raise exceptions.DomainHasSubdomain('Please delete any subdomains '
                                                'before deleting this domain')

        with self.storage_api.delete_domain(context, domain_id) as domain:
            with wrap_backend_call():
                self.backend.delete_domain(context, domain)

        utils.notify(context, 'central', 'domain.delete', domain)

        return domain
예제 #5
0
    def find_records(self, context, criterion=None, marker=None, limit=None,
                     sort_key=None, sort_dir=None):
        target = {'tenant_id': context.tenant}
        policy.check('find_records', context, target)

        return self.storage_api.find_records(context, criterion, marker, limit,
                                             sort_key, sort_dir)
예제 #6
0
    def get_one(self, zone_id):
        context = pecan.request.environ['context']

        policy.check('zone_export', context)

        servers = self.central_api.get_domain_servers(context, zone_id)
        domain = self.central_api.get_domain(context, zone_id)

        criterion = {'domain_id': zone_id}
        recordsets = self.central_api.find_recordsets(context, criterion)

        records = []

        for recordset in recordsets:
            criterion = {
                'domain_id': domain['id'],
                'recordset_id': recordset['id']
            }

            raw_records = self.central_api.find_records(context, criterion)

            for record in raw_records:
                records.append({
                    'name': recordset['name'],
                    'type': recordset['type'],
                    'ttl': recordset['ttl'],
                    'data': record['data'],
                })

        return utils.render_template('bind9-zone.jinja2',
                                     servers=servers,
                                     domain=domain,
                                     records=records)
예제 #7
0
    def get_record(self, context, domain_id, recordset_id, record_id):
        domain = self.storage_api.get_domain(context, domain_id)
        recordset = self.storage_api.get_recordset(context, recordset_id)
        record = self.storage_api.get_record(context, record_id)

        # Ensure the domain_id matches the record's domain_id
        if domain['id'] != record['domain_id']:
            raise exceptions.RecordNotFound()

        # Ensure the recordset_id matches the record's recordset_id
        if recordset['id'] != record['recordset_id']:
            raise exceptions.RecordNotFound()

        target = {
            'domain_id': domain_id,
            'domain_name': domain['name'],
            'recordset_id': recordset_id,
            'recordset_name': recordset['name'],
            'record_id': record['id'],
            'tenant_id': domain['tenant_id']
        }

        policy.check('get_record', context, target)

        return record
예제 #8
0
    def get_one(self, zone_id):
        context = pecan.request.environ['context']

        policy.check('zone_export', context)

        servers = self.central_api.get_domain_servers(context, zone_id)
        domain = self.central_api.get_domain(context, zone_id)

        criterion = {'domain_id': zone_id}
        recordsets = self.central_api.find_recordsets(context, criterion)

        records = []

        for recordset in recordsets:
            criterion = {
                'domain_id': domain['id'],
                'recordset_id': recordset['id']
            }

            raw_records = self.central_api.find_records(context, criterion)

            for record in raw_records:
                records.append({
                    'name': recordset['name'],
                    'type': recordset['type'],
                    'ttl': recordset['ttl'],
                    'data': record['data'],
                })

        return utils.render_template('bind9-zone.jinja2',
                                     servers=servers,
                                     domain=domain,
                                     records=records)
예제 #9
0
    def delete_record(self,
                      context,
                      domain_id,
                      record_id,
                      increment_serial=True):
        domain = self.storage_api.get_domain(context, domain_id)
        record = self.storage_api.get_record(context, record_id)

        # Ensure the domain_id matches the record's domain_id
        if domain['id'] != record['domain_id']:
            raise exceptions.RecordNotFound()

        target = {
            'domain_id': domain_id,
            'domain_name': domain['name'],
            'record_id': record['id'],
            'tenant_id': domain['tenant_id']
        }

        policy.check('delete_record', context, target)

        with self.storage_api.delete_record(context, record_id) as record:
            with wrap_backend_call():
                self.backend.delete_record(context, domain, record)

            if increment_serial:
                self._increment_domain_serial(context, domain_id)

        # Send Record deletion notification
        utils.notify(context, 'central', 'record.delete', record)

        return record
예제 #10
0
    def delete_record(self, context, domain_id, record_id,
                      increment_serial=True):
        domain = self.storage_api.get_domain(context, domain_id)
        record = self.storage_api.get_record(context, record_id)

        # Ensure the domain_id matches the record's domain_id
        if domain['id'] != record['domain_id']:
            raise exceptions.RecordNotFound()

        target = {
            'domain_id': domain_id,
            'domain_name': domain['name'],
            'record_id': record['id'],
            'tenant_id': domain['tenant_id']
        }

        policy.check('delete_record', context, target)

        with self.storage_api.delete_record(context, record_id) as record:
            with wrap_backend_call():
                self.backend.delete_record(context, domain, record)

            if increment_serial:
                self._increment_domain_serial(context, domain_id)

        # Send Record deletion notification
        self.notifier.info(context, 'dns.record.delete', record)

        return record
예제 #11
0
    def create_record(self, context, domain_id, values, increment_serial=True):
        domain = self.storage_api.get_domain(context, domain_id)

        target = {
            'domain_id': domain_id,
            'domain_name': domain['name'],
            'record_name': values['name'],
            'tenant_id': domain['tenant_id']
        }

        policy.check('create_record', context, target)

        # Ensure the tenant has enough quota to continue
        self._enforce_record_quota(context, domain)

        # Ensure the record name and placement is valid
        self._is_valid_record_name(context, domain, values['name'],
                                   values['type'])
        self._is_valid_record_placement(context, domain, values['name'],
                                        values['type'])

        with self.storage_api.create_record(
                context, domain_id, values) as record:
            with wrap_backend_call():
                self.backend.create_record(context, domain, record)

            if increment_serial:
                self._increment_domain_serial(context, domain_id)

        # Send Record creation notification
        self.notifier.info(context, 'dns.record.create', record)

        return record
예제 #12
0
    def delete_domain(self, context, domain_id):
        domain = self.storage_api.get_domain(context, domain_id)

        target = {
            'domain_id': domain_id,
            'domain_name': domain['name'],
            'tenant_id': domain['tenant_id']
        }

        policy.check('delete_domain', context, target)

        # Prevent deletion of a zone which has child zones
        criterion = {'parent_domain_id': domain_id}

        if self.storage_api.count_domains(context, criterion) > 0:
            raise exceptions.DomainHasSubdomain('Please delete any subdomains '
                                                'before deleting this domain')

        with self.storage_api.delete_domain(context, domain_id) as domain:
            with wrap_backend_call():
                self.backend.delete_domain(context, domain)

        self.notifier.info(context, 'dns.domain.delete', domain)

        return domain
예제 #13
0
    def create_record(self, context, domain_id, values, increment_serial=True):
        domain = self.storage_api.get_domain(context, domain_id)

        target = {
            'domain_id': domain_id,
            'domain_name': domain['name'],
            'record_name': values['name'],
            'tenant_id': domain['tenant_id']
        }

        policy.check('create_record', context, target)

        # Ensure the tenant has enough quota to continue
        self._enforce_record_quota(context, domain)

        # Ensure the record name and placement is valid
        self._is_valid_record_name(context, domain, values['name'],
                                   values['type'])
        self._is_valid_record_placement(context, domain, values['name'],
                                        values['type'])

        with self.storage_api.create_record(context, domain_id,
                                            values) as record:
            with wrap_backend_call():
                self.backend.create_record(context, domain, record)

            if increment_serial:
                self._increment_domain_serial(context, domain_id)

        # Send Record creation notification
        utils.notify(context, 'central', 'record.create', record)

        return record
예제 #14
0
파일: context.py 프로젝트: CingHu/designate
    def sudo(self, tenant):

        policy.check("use_sudo", self)

        LOG.info(_LI("Accepted sudo from user %(user)s to tenant %(tenant)s") % {"user": self.user, "tenant": tenant})
        self.original_tenant = self.tenant
        self.tenant = tenant
    def filter(self, context, pools, zone):
        """Attempt to load and set the pool to the one provided in the
        Zone attributes.

        :param context: :class:`designate.context.DesignateContext` - Context
            Object from request
        :param pools: :class:`designate.objects.pool.PoolList` - List of pools
            to choose from
        :param zone: :class:`designate.objects.zone.Zone` - Zone to be created
        :return: :class:`designate.objects.pool.PoolList` -- A PoolList with
            containing a single pool.
        :raises: Forbidden, PoolNotFound
        """

        try:
            if zone.attributes.get('pool_id'):
                pool_id = zone.attributes.get('pool_id')
                try:
                    pool = self.storage.get_pool(context, pool_id)
                except Exception:
                    return objects.PoolList()
                policy.check('zone_create_forced_pool', context, pool)
                if pool in pools:
                    pools = objects.PoolList()
                    pools.append(pool)
                return pools
            else:
                return pools
        except exceptions.RelationNotLoaded:
            return pools
예제 #16
0
    def delete_tsigkey(self, context, tsigkey_id):
        policy.check('delete_tsigkey', context, {'tsigkey_id': tsigkey_id})

        with self.storage_api.delete_tsigkey(context, tsigkey_id) as tsigkey:
            with wrap_backend_call():
                self.backend.delete_tsigkey(context, tsigkey)

        utils.notify(context, 'central', 'tsigkey.delete', tsigkey)
예제 #17
0
    def sudo(self, tenant):

        policy.check('use_sudo', self)

        LOG.info('Accepted sudo from user %(user)s to tenant %(tenant)s',
                 {'user': self.user, 'tenant': tenant})
        self.original_tenant = self.tenant
        self.tenant = tenant
예제 #18
0
    def delete_tsigkey(self, context, tsigkey_id):
        policy.check('delete_tsigkey', context, {'tsigkey_id': tsigkey_id})

        with self.storage_api.delete_tsigkey(context, tsigkey_id) as tsigkey:
            with wrap_backend_call():
                self.backend.delete_tsigkey(context, tsigkey)

        self.notifier.info(context, 'dns.tsigkey.delete', tsigkey)
예제 #19
0
    def get_tenant(self, context, tenant_id):
        target = {
            'tenant_id': tenant_id
        }

        policy.check('get_tenant', context, target)

        return self.storage_api.get_tenant(context, tenant_id)
예제 #20
0
    def find_domain(self, context, criterion):
        target = {'tenant_id': context.tenant_id}
        policy.check('find_domain', context, target)

        if not context.is_admin:
            criterion['tenant_id'] = context.tenant_id

        return self.storage_api.find_domain(context, criterion)
예제 #21
0
 def _is_valid_ttl(self, context, ttl):
     min_ttl = cfg.CONF['service:central'].min_ttl
     if min_ttl != "None" and ttl < int(min_ttl):
         try:
             policy.check('use_low_ttl', context)
         except exceptions.Forbidden:
             raise exceptions.InvalidTTL('TTL is below the minimum: %s'
                                         % min_ttl)
예제 #22
0
    def delete_tsigkey(self, context, tsigkey_id):
        policy.check('delete_tsigkey', context, {'tsigkey_id': tsigkey_id})

        with self.storage_api.delete_tsigkey(context, tsigkey_id) as tsigkey:
            with wrap_backend_call():
                self.backend.delete_tsigkey(context, tsigkey)

        utils.notify(context, 'central', 'tsigkey.delete', tsigkey)
예제 #23
0
    def delete_server(self, context, server_id):
        policy.check('delete_server', context, {'server_id': server_id})

        with self.storage_api.delete_server(context, server_id) as server:
            # TODO(kiall): Update backend with the new server..
            pass

        utils.notify(context, 'central', 'server.delete', server)
예제 #24
0
    def find_domain(self, context, criterion):
        target = {'tenant_id': context.tenant_id}
        policy.check('find_domain', context, target)

        if not context.is_admin:
            criterion['tenant_id'] = context.tenant_id

        return self.storage_api.find_domain(context, criterion)
예제 #25
0
    def delete_blacklist(self, context, blacklist_id):
        policy.check('delete_blacklist', context)

        with self.storage_api.delete_blacklist(context,
                                               blacklist_id) as blacklist:
            pass  # NOTE: No other systems need updating

        self.notifier.info(context, 'dns.blacklist.delete', blacklist)
예제 #26
0
    def create_domain(self, context, values):
        # TODO(kiall): Refactor this method into *MUCH* smaller chunks.

        # Default to creating in the current users tenant
        if 'tenant_id' not in values:
            values['tenant_id'] = context.tenant

        target = {
            'tenant_id': values['tenant_id'],
            'domain_name': values['name']
        }

        policy.check('create_domain', context, target)

        # Ensure the tenant has enough quota to continue
        self._enforce_domain_quota(context, values['tenant_id'])

        # Ensure the domain name is valid
        self._is_valid_domain_name(context, values['name'])

        # Ensure TTL is above the minimum
        ttl = values.get('ttl', None)
        if ttl is not None:
            self._is_valid_ttl(context, ttl)

        # Handle sub-domains appropriately
        parent_domain = self._is_subdomain(context, values['name'])

        if parent_domain:
            if parent_domain['tenant_id'] == values['tenant_id']:
                # Record the Parent Domain ID
                values['parent_domain_id'] = parent_domain['id']
            else:
                raise exceptions.Forbidden('Unable to create subdomain in '
                                           'another tenants domain')

        # TODO(kiall): Handle super-domains properly

        # NOTE(kiall): Fetch the servers before creating the domain, this way
        #              we can prevent domain creation if no servers are
        #              configured.
        servers = self.storage_api.find_servers(context)

        if len(servers) == 0:
            LOG.critical('No servers configured. Please create at least one '
                         'server')
            raise exceptions.NoServersConfigured()

        # Set the serial number
        values['serial'] = utils.increment_serial()

        with self.storage_api.create_domain(context, values) as domain:
            with wrap_backend_call():
                self.backend.create_domain(context, domain)

        self.notifier.info(context, 'dns.domain.create', domain)

        return domain
예제 #27
0
    def find_blacklists(self, context, criterion=None, marker=None,
                        limit=None, sort_key=None, sort_dir=None):
        policy.check('find_blacklists', context)

        blacklists = self.storage_api.find_blacklists(context, criterion,
                                                      marker, limit,
                                                      sort_key, sort_dir)

        return blacklists
예제 #28
0
    def update_tld(self, context, tld_id, values):
        policy.check('update_tld', context, {'tld_id': tld_id})

        with self.storage_api.update_tld(context, tld_id, values) as tld:
            pass

        self.notifier.info(context, 'dns.tld.update', tld)

        return tld
예제 #29
0
    def create_blacklist(self, context, values):
        policy.check('create_blacklist', context)

        with self.storage_api.create_blacklist(context, values) as blacklist:
            pass  # NOTE: No other systems need updating

        self.notifier.info(context, 'dns.blacklist.create', blacklist)

        return blacklist
예제 #30
0
    def set_quota(self, context, tenant_id, resource, hard_limit):
        target = {
            'tenant_id': tenant_id,
            'resource': resource,
            'hard_limit': hard_limit,
        }

        policy.check('set_quota', context, target)

        return self.quota.set_quota(context, tenant_id, resource, hard_limit)
예제 #31
0
    def create_tsigkey(self, context, values):
        policy.check('create_tsigkey', context)

        with self.storage_api.create_tsigkey(context, values) as tsigkey:
            with wrap_backend_call():
                self.backend.create_tsigkey(context, tsigkey)

        utils.notify(context, 'central', 'tsigkey.create', tsigkey)

        return tsigkey
예제 #32
0
    def create_server(self, context, values):
        policy.check('create_server', context)

        with self.storage_api.create_server(context, values) as server:
            # TODO(kiall): Update backend with the new server..
            pass

        utils.notify(context, 'central', 'server.create', server)

        return server
예제 #33
0
    def sync_domains(self, context):
        policy.check('diagnostics_sync_domains', context)

        domains = self.storage_api.find_domains(context)

        results = {}
        for domain in domains:
            results[domain['id']] = self._sync_domain(context, domain)

        return results
예제 #34
0
    def create_tsigkey(self, context, values):
        policy.check('create_tsigkey', context)

        with self.storage_api.create_tsigkey(context, values) as tsigkey:
            with wrap_backend_call():
                self.backend.create_tsigkey(context, tsigkey)

        utils.notify(context, 'central', 'tsigkey.create', tsigkey)

        return tsigkey
예제 #35
0
    def count_records(self, context, criterion=None):
        if criterion is None:
            criterion = {}

        target = {
            'tenant_id': criterion.get('tenant_id', None)
        }

        policy.check('count_records', context, target)
        return self.storage_api.count_records(context, criterion)
예제 #36
0
    def set_quota(self, context, tenant_id, resource, hard_limit):
        target = {
            'tenant_id': tenant_id,
            'resource': resource,
            'hard_limit': hard_limit,
        }

        policy.check('set_quota', context, target)

        return self.quota.set_quota(context, tenant_id, resource, hard_limit)
예제 #37
0
    def create_tsigkey(self, context, values):
        policy.check('create_tsigkey', context)

        with self.storage_api.create_tsigkey(context, values) as tsigkey:
            with wrap_backend_call():
                self.backend.create_tsigkey(context, tsigkey)

        self.notifier.info(context, 'dns.tsigkey.create', tsigkey)

        return tsigkey
예제 #38
0
    def create_server(self, context, values):
        policy.check('create_server', context)

        with self.storage_api.create_server(context, values) as server:
            # Update backend with the new server..
            with wrap_backend_call():
                self.backend.create_server(context, server)

        utils.notify(context, 'central', 'server.create', server)

        return server
예제 #39
0
    def get_domain(self, context, domain_id):
        domain = self.storage_api.get_domain(context, domain_id)

        target = {
            'domain_id': domain_id,
            'domain_name': domain['name'],
            'tenant_id': domain['tenant_id']
        }
        policy.check('get_domain', context, target)

        return domain
예제 #40
0
    def update_tsigkey(self, context, tsigkey_id, values):
        policy.check('update_tsigkey', context, {'tsigkey_id': tsigkey_id})

        with self.storage_api.update_tsigkey(
                context, tsigkey_id, values) as tsigkey:
            with wrap_backend_call():
                self.backend.update_tsigkey(context, tsigkey)

        self.notifier.info(context, 'dns.tsigkey.update', tsigkey)

        return tsigkey
예제 #41
0
    def update_tsigkey(self, context, tsigkey_id, values):
        policy.check('update_tsigkey', context, {'tsigkey_id': tsigkey_id})

        with self.storage_api.update_tsigkey(context, tsigkey_id,
                                             values) as tsigkey:
            with wrap_backend_call():
                self.backend.update_tsigkey(context, tsigkey)

        utils.notify(context, 'central', 'tsigkey.update', tsigkey)

        return tsigkey
예제 #42
0
    def get_domain(self, context, domain_id):
        domain = self.storage_api.get_domain(context, domain_id)

        target = {
            'domain_id': domain_id,
            'domain_name': domain['name'],
            'tenant_id': domain['tenant_id']
        }
        policy.check('get_domain', context, target)

        return domain
예제 #43
0
    def update_server(self, context, server_id, values):
        policy.check('update_server', context, {'server_id': server_id})

        with self.storage_api.update_server(context, server_id,
                                            values) as server:
            # Update backend with the new details..
            with wrap_backend_call():
                self.backend.update_server(context, server)

        utils.notify(context, 'central', 'server.update', server)

        return server
예제 #44
0
    def find_record(self, context, domain_id, criterion=None):
        domain = self.storage_api.get_domain(context, domain_id)

        target = {
            'domain_id': domain_id,
            'domain_name': domain['name'],
            'tenant_id': domain['tenant_id']
        }

        policy.check('find_record', context, target)

        return self.storage_api.find_record(context, domain_id, criterion)
예제 #45
0
    def create_domain(self, context, values):
        # TODO(kiall): Refactor this method into *MUCH* smaller chunks.
        values['tenant_id'] = context.tenant_id

        target = {
            'tenant_id': values['tenant_id'],
            'domain_name': values['name']
        }

        policy.check('create_domain', context, target)

        # Ensure the tenant has enough quota to continue
        self._enforce_domain_quota(context, values['tenant_id'])

        # Ensure the domain name is valid
        self._is_valid_domain_name(context, values['name'])

        # Handle sub-domains appropriately
        parent_domain = self._is_subdomain(context, values['name'])

        if parent_domain:
            if parent_domain['tenant_id'] == values['tenant_id']:
                # Record the Parent Domain ID
                values['parent_domain_id'] = parent_domain['id']
            else:
                raise exceptions.Forbidden('Unable to create subdomain in '
                                           'another tenants domain')

        # TODO(kiall): Handle super-domains properly

        # NOTE(kiall): Fetch the servers before creating the domain, this way
        #              we can prevent domain creation if no servers are
        #              configured.
        servers = self.storage_api.find_servers(context)

        if len(servers) == 0:
            LOG.critical('No servers configured. Please create at least one '
                         'server')
            raise exceptions.NoServersConfigured()

        # Set the serial number
        values['serial'] = utils.increment_serial()

        with self.storage_api.create_domain(context, values) as domain:
            with wrap_backend_call():
                self.backend.create_domain(context, domain)

        utils.notify(context, 'central', 'domain.create', domain)

        return domain
예제 #46
0
    def get_domain_servers(self, context, domain_id, criterion=None):
        domain = self.storage_api.get_domain(context, domain_id)

        target = {
            'domain_id': domain_id,
            'domain_name': domain['name'],
            'tenant_id': domain['tenant_id']
        }

        policy.check('get_domain_servers', context, target)

        # TODO(kiall): Once we allow domains to be allocated on 1 of N server
        #              pools, return the filtered list here.
        return self.storage_api.find_servers(context, criterion)
예제 #47
0
    def delete_server(self, context, server_id):
        policy.check('delete_server', context, {'server_id': server_id})

        # don't delete last of servers
        servers = self.storage_api.find_servers(context)
        if len(servers) == 1 and server_id == servers[0]['id']:
            raise exceptions.LastServerDeleteNotAllowed(
                "Not allowed to delete last of servers")

        with self.storage_api.delete_server(context, server_id) as server:
            # Update backend with the new server..
            with wrap_backend_call():
                self.backend.delete_server(context, server)

        utils.notify(context, 'central', 'server.delete', server)
예제 #48
0
    def touch_domain(self, context, domain_id):
        domain = self.storage_api.get_domain(context, domain_id)

        target = {
            'domain_id': domain_id,
            'domain_name': domain['name'],
            'tenant_id': domain['tenant_id']
        }

        policy.check('touch_domain', context, target)

        domain = self._increment_domain_serial(context, domain_id)

        utils.notify(context, 'central', 'domain.touch', domain)

        return domain
예제 #49
0
    def get_record(self, context, domain_id, record_id):
        domain = self.storage_api.get_domain(context, domain_id)
        record = self.storage_api.get_record(context, record_id)

        # Ensure the domain_id matches the record's domain_id
        if domain['id'] != record['domain_id']:
            raise exceptions.RecordNotFound()

        target = {
            'domain_id': domain_id,
            'domain_name': domain['name'],
            'record_id': record['id'],
            'tenant_id': domain['tenant_id']
        }

        policy.check('get_record', context, target)

        return record
예제 #50
0
    def update_record(self,
                      context,
                      domain_id,
                      record_id,
                      values,
                      increment_serial=True):
        domain = self.storage_api.get_domain(context, domain_id)
        record = self.storage_api.get_record(context, record_id)

        # Ensure the domain_id matches the record's domain_id
        if domain['id'] != record['domain_id']:
            raise exceptions.RecordNotFound()

        target = {
            'domain_id': domain_id,
            'domain_name': domain['name'],
            'record_id': record['id'],
            'tenant_id': domain['tenant_id']
        }

        policy.check('update_record', context, target)

        # Ensure the record name is valid
        record_name = values['name'] if 'name' in values else record['name']
        record_type = values['type'] if 'type' in values else record['type']

        self._is_valid_record_name(context, domain, record_name, record_type)
        self._is_valid_record_placement(context, domain, record_name,
                                        record_type, record_id)

        # Update the record
        with self.storage_api.update_record(context, record_id,
                                            values) as record:
            with wrap_backend_call():
                self.backend.update_record(context, domain, record)

            if increment_serial:
                self._increment_domain_serial(context, domain_id)

        # Send Record update notification
        utils.notify(context, 'central', 'record.update', record)

        return record