def _get_context(self, tenant_id=None):
     if tenant_id:
         return DesignateContext.get_admin_context(
             tenant=tenant_id, edit_managed_records=True)
     else:
         return DesignateContext.get_admin_context(
             all_tenants=True, edit_managed_records=True)
Beispiel #2
0
    def periodic_recovery(self):
        """
        :return: None
        """
        # TODO(kiall): Replace this inter-process-lock with a distributed
        #              lock, likely using the tooz library - see bug 1445127.
        with lockutils.lock('periodic_recovery', external=True, delay=30):
            context = DesignateContext.get_admin_context(all_tenants=True)

            LOG.debug("Starting Periodic Recovery")

            try:
                # Handle Deletion Failures
                domains = self._get_failed_domains(context, DELETE_ACTION)

                for domain in domains:
                    self.delete_domain(context, domain)

                # Handle Creation Failures
                domains = self._get_failed_domains(context, CREATE_ACTION)

                for domain in domains:
                    self.create_domain(context, domain)

                # Handle Update Failures
                domains = self._get_failed_domains(context, UPDATE_ACTION)

                for domain in domains:
                    self.update_domain(context, domain)

            except Exception:
                LOG.exception(
                    _LE('An unhandled exception in periodic '
                        'recovery occurred'))
Beispiel #3
0
    def periodic_sync(self):
        """
        :return: None
        """
        # NOTE(kiall): Only run this periodic task on the pool leader
        if self._pool_election.is_leader:
            context = DesignateContext.get_admin_context(all_tenants=True)

            LOG.debug("Starting Periodic Synchronization")

            criterion = {
                'pool_id': CONF['service:pool_manager'].pool_id,
                'status': '!%s' % ERROR_STATUS
            }

            periodic_sync_seconds = \
                CONF['service:pool_manager'].periodic_sync_seconds

            if periodic_sync_seconds is not None:
                # Generate the current serial, will provide a UTC Unix TS.
                current = utils.increment_serial()
                criterion['serial'] = ">%s" % (current - periodic_sync_seconds)

            zones = self.central_api.find_zones(context, criterion)

            try:
                for zone in zones:
                    # TODO(kiall): If the zone was created within the last
                    #              periodic_sync_seconds, attempt to recreate
                    #              to fill in targets which may have failed.
                    self.update_zone(context, zone)

            except Exception:
                LOG.exception(_LE('An unhandled exception in periodic '
                                  'synchronization occurred.'))
Beispiel #4
0
    def start(self):

        # Build the Pool (and related) Object from Config
        context = DesignateContext.get_admin_context()
        pool_id = CONF['service:pool_manager'].pool_id

        has_targets = False

        # TODO(kiall): This block of code should be replaced with a cleaner,
        #              limited version. e.g. should retry for X minutes, and
        #              backoff rather than fixed retry intervals.
        while not has_targets:
            try:
                self.pool = self.central_api.get_pool(context, pool_id)

                if len(self.pool.targets) > 0:
                    has_targets = True
                else:
                    LOG.error(_LE("No targets for %s found."), self.pool)
                    time.sleep(5)

            # Pool data may not have migrated to the DB yet
            except exceptions.PoolNotFound:
                LOG.error(_LE("Pool ID %s not found."), pool_id)
                time.sleep(5)
            # designate-central service may not have started yet
            except messaging.exceptions.MessagingTimeout:
                time.sleep(0.2)
            # designate-central failed in an unknown way, don't allow another
            # failing / not started service to cause pool-manager to crash.
            except Exception:
                LOG.exception(_LE("An unknown exception occurred while "
                                  "fetching pool details"))
                time.sleep(5)

        # Create the necessary Backend instances for each target
        self._setup_target_backends()

        for target in self.pool.targets:
            self.target_backends[target.id].start()

        super(Service, self).start()

        # Setup a Leader Election, use for ensuring certain tasks are executed
        # on exactly one pool-manager instance at a time]
        self._pool_election = coordination.LeaderElection(
            self._coordinator, '%s:%s' % (self.service_name, self.pool.id))
        self._pool_election.start()

        if CONF['service:pool_manager'].enable_recovery_timer:
            interval = CONF['service:pool_manager'].periodic_recovery_interval
            LOG.info(_LI('Starting periodic recovery timer every'
                         ' %(interval)s s') % {'interval': interval})
            self.tg.add_timer(interval, self.periodic_recovery, interval)

        if CONF['service:pool_manager'].enable_sync_timer:
            interval = CONF['service:pool_manager'].periodic_sync_interval
            LOG.info(_LI('Starting periodic synchronization timer every'
                         ' %(interval)s s') % {'interval': interval})
            self.tg.add_timer(interval, self.periodic_sync, interval)
Beispiel #5
0
    def periodic_sync(self):
        """
        :return: None
        """
        LOG.debug("Calling periodic_sync.")

        context = DesignateContext.get_admin_context(all_tenants=True)

        criterion = {
            'pool_id': cfg.CONF['service:pool_manager'].pool_id,
            'status': '%s%s' % ('!', ERROR_STATUS)
        }

        periodic_sync_seconds = \
            cfg.CONF['service:pool_manager'].periodic_sync_seconds

        if periodic_sync_seconds is not None:
            # Generate the current serial, will provide a UTC Unix TS.
            current = utils.increment_serial()
            criterion['serial'] = ">%s" % (current - periodic_sync_seconds)

        domains = self.central_api.find_domains(context, criterion)

        try:
            for domain in domains:
                self.update_domain(context, domain)
        except Exception:
            LOG.exception(
                _LE('An unhandled exception in periodic sync '
                    'occurred.  This should never happen!'))
Beispiel #6
0
    def _delete(self, managed=True, resource_id=None, resource_type='instance',
                criterion={}):
        """
        Handle a generic delete of a fixed ip within a domain

        :param criterion: Criterion to search and destroy records
        """
        context = DesignateContext.get_admin_context()

        if managed:
            criterion.update({
                'managed': managed,
                'managed_plugin_name': self.get_plugin_name(),
                'managed_plugin_type': self.get_plugin_type(),
                'managed_resource_id': resource_id,
                'managed_resource_type': resource_type
            })

        records = central_api.find_records(context,
                                           cfg.CONF[self.name].domain_id,
                                           criterion)

        for record in records:
            LOG.debug('Deleting record %s' % record['id'])

            central_api.delete_record(context, cfg.CONF[self.name].domain_id,
                                      record['id'])
Beispiel #7
0
    def periodic_recovery(self):
        """
        :return: None
        """
        # TODO(kiall): Replace this inter-process-lock with a distributed
        #              lock, likely using the tooz library - see bug 1445127.
        with lockutils.lock('periodic_recovery', external=True, delay=30):
            context = DesignateContext.get_admin_context(all_tenants=True)

            LOG.debug("Starting Periodic Recovery")

            try:
                # Handle Deletion Failures
                domains = self._get_failed_domains(context, DELETE_ACTION)

                for domain in domains:
                    self.delete_domain(context, domain)

                # Handle Creation Failures
                domains = self._get_failed_domains(context, CREATE_ACTION)

                for domain in domains:
                    self.create_domain(context, domain)

                # Handle Update Failures
                domains = self._get_failed_domains(context, UPDATE_ACTION)

                for domain in domains:
                    self.update_domain(context, domain)

            except Exception:
                LOG.exception(_LE('An unhandled exception in periodic '
                                  'recovery occurred'))
 def _create_reverse_record(self, context, managed, host_fqdn, interface):
     LOG.info('Create reverse record for interface: %s and address: %s',
              interface['label'], interface['address'])
     host_reverse_fqdn = self._get_reverse_fqdn(interface['address'],
                                                interface['version'])
     LOG.info('Create reverse record: %s', host_reverse_fqdn)
     reverse_domains = self._get_reverse_domains(host_reverse_fqdn)
     admin_context = DesignateContext.get_admin_context(all_tenants=True)
     for reverse_domain in reverse_domains:
         LOG.info('Create reverse record for domain: %s',
                  reverse_domain.name)
         try:
             recordset = self.central_api.create_recordset(
                 admin_context, reverse_domain.id,
                 RecordSet(name=host_reverse_fqdn, type='PTR'))
         except exceptions.DuplicateRecordSet:
             LOG.warn('The reverse record: %s was already registered',
                      host_reverse_fqdn)
         else:
             record_values = dict(managed, data=host_fqdn)
             LOG.debug('Creating reverse record in %s / %s with values %r',
                       reverse_domain.id, recordset['id'], record_values)
             self.central_api.create_record(admin_context,
                                            reverse_domain.id,
                                            recordset['id'],
                                            Record(**record_values))
Beispiel #9
0
    def _delete(self,
                managed=True,
                resource_id=None,
                resource_type='instance',
                criterion={}):
        """
        Handle a generic delete of a fixed ip within a domain

        :param criterion: Criterion to search and destroy records
        """
        context = DesignateContext.get_admin_context(all_tenants=True)

        criterion.update({'domain_id': cfg.CONF[self.name].domain_id})

        if managed:
            criterion.update({
                'managed': managed,
                'managed_plugin_name': self.get_plugin_name(),
                'managed_plugin_type': self.get_plugin_type(),
                'managed_resource_id': resource_id,
                'managed_resource_type': resource_type
            })

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

        for record in records:
            LOG.debug('Deleting record %s' % record['id'])

            self.central_api.delete_record(context,
                                           cfg.CONF[self.name].domain_id,
                                           record['recordset_id'],
                                           record['id'])
Beispiel #10
0
    def load_pool(self, pool_id):
        # Build the Pool (and related) Object from Config
        context = DesignateContext.get_admin_context()

        pool = None
        has_targets = False

        while not has_targets:
            try:
                pool = self.central_api.get_pool(context, pool_id)

                if len(pool.targets) > 0:
                    has_targets = True
                else:
                    LOG.error("No targets for %s found.", pool)
                    time.sleep(5)

            # Pool data may not have migrated to the DB yet
            except exceptions.PoolNotFound:
                LOG.error("Pool ID %s not found.", pool_id)
                time.sleep(5)
            # designate-central service may not have started yet
            except messaging.exceptions.MessagingTimeout:
                time.sleep(0.2)

        return self._setup_target_backends(pool)
Beispiel #11
0
    def _create(self,
                addresses,
                extra,
                managed=True,
                resource_type=None,
                resource_id=None):
        """
        Create a a record from addresses

        :param addresses: Address objects like
                          {'version': 4, 'ip': '10.0.0.1'}
        :param extra: Extra data to use when formatting the record
        :param managed: Is it a managed resource
        :param resource_type: The managed resource type
        :param resource_id: The managed resource ID
        """
        LOG.debug('Using DomainID: %s' % cfg.CONF[self.name].domain_id)
        domain = self.get_domain(cfg.CONF[self.name].domain_id)
        LOG.debug('Domain: %r' % domain)

        data = extra.copy()
        LOG.debug('Event data: %s' % data)
        data['domain'] = domain['name']

        context = DesignateContext.get_admin_context(all_tenants=True)

        for addr in addresses:
            event_data = data.copy()
            event_data.update(get_ip_data(addr))

            recordset_values = {
                'domain_id': domain['id'],
                'name': self._get_format() % event_data,
                'type': 'A' if addr['version'] == 4 else 'AAAA'
            }

            recordset = self._find_or_create_recordset(context,
                                                       **recordset_values)

            record_values = {'data': addr['address']}

            if managed:
                record_values.update({
                    'managed':
                    managed,
                    'managed_plugin_name':
                    self.get_plugin_name(),
                    'managed_plugin_type':
                    self.get_plugin_type(),
                    'managed_resource_type':
                    resource_type,
                    'managed_resource_id':
                    resource_id
                })

            LOG.debug('Creating record in %s / %s with values %r',
                      domain['id'], recordset['id'], record_values)
            self.central_api.create_record(context, domain['id'],
                                           recordset['id'],
                                           Record(**record_values))
Beispiel #12
0
    def load_pool(self, pool_id):
        # Build the Pool (and related) Object from Config
        context = DesignateContext.get_admin_context()

        pool = None
        has_targets = False

        while not has_targets:
            try:
                pool = self.central_api.get_pool(context, pool_id)

                if len(pool.targets) > 0:
                    has_targets = True
                else:
                    LOG.error("No targets for %s found.", pool)
                    time.sleep(5)

            # Pool data may not have migrated to the DB yet
            except exceptions.PoolNotFound:
                LOG.error("Pool ID %s not found.", pool_id)
                time.sleep(5)
            # designate-central service may not have started yet
            except messaging.exceptions.MessagingTimeout:
                time.sleep(0.2)

        return self._setup_target_backends(pool)
Beispiel #13
0
    def periodic_recovery(self):
        """
        :return: None
        """
        # NOTE(kiall): Only run this periodic task on the pool leader
        if self._pool_election.is_leader:
            context = DesignateContext.get_admin_context(all_tenants=True)

            LOG.debug("Starting Periodic Recovery")

            try:
                # Handle Deletion Failures
                zones = self._get_failed_zones(context, DELETE_ACTION)

                for zone in zones:
                    self.delete_zone(context, zone)

                # Handle Creation Failures
                zones = self._get_failed_zones(context, CREATE_ACTION)

                for zone in zones:
                    self.create_zone(context, zone)

                # Handle Update Failures
                zones = self._get_failed_zones(context, UPDATE_ACTION)

                for zone in zones:
                    self.update_zone(context, zone)

            except Exception:
                LOG.exception(_LE('An unhandled exception in periodic '
                                  'recovery occurred'))
Beispiel #14
0
    def start(self):
        # Build the Pool (and related) Object from Config
        context = DesignateContext.get_admin_context()
        pool_id = CONF['service:pool_manager'].pool_id

        has_targets = False

        # TODO(kiall): This block of code should be replaced with a cleaner,
        #              limited version. e.g. should retry for X minutes, and
        #              backoff rather than fixed retry intervals.
        while not has_targets:
            try:
                self.pool = self.central_api.get_pool(context, pool_id)

                if len(self.pool.targets) > 0:
                    has_targets = True
                else:
                    LOG.error("No targets for %s found.", self.pool)
                    time.sleep(5)

            # Pool data may not have migrated to the DB yet
            except exceptions.PoolNotFound:
                LOG.error("Pool ID %s not found.", pool_id)
                time.sleep(5)
            # designate-central service may not have started yet
            except messaging.exceptions.MessagingTimeout:
                time.sleep(0.2)
            # designate-central failed in an unknown way, don't allow another
            # failing / not started service to cause pool-manager to crash.
            except Exception:
                LOG.exception("An unknown exception occurred while "
                              "fetching pool details")
                time.sleep(5)

        # Create the necessary Backend instances for each target
        self._setup_target_backends()

        for target in self.pool.targets:
            self.target_backends[target.id].start()

        super(Service, self).start()

        # Setup a Leader Election, use for ensuring certain tasks are executed
        # on exactly one pool-manager instance at a time]
        self._pool_election = coordination.LeaderElection(
            self._coordinator, '%s:%s' % (self.service_name, self.pool.id))
        self._pool_election.start()

        if CONF['service:pool_manager'].enable_recovery_timer:
            interval = CONF['service:pool_manager'].periodic_recovery_interval
            LOG.info('Starting periodic recovery timer every'
                     ' %(interval)s s', {'interval': interval})
            self.tg.add_timer(interval, self.periodic_recovery, interval)

        if CONF['service:pool_manager'].enable_sync_timer:
            interval = CONF['service:pool_manager'].periodic_sync_interval
            LOG.info('Starting periodic synchronization timer every'
                     ' %(interval)s s', {'interval': interval})
            self.tg.add_timer(interval, self.periodic_sync, interval)
Beispiel #15
0
    def test_invalid_event_type(self):
        context = DesignateContext.get_admin_context(all_tenants=True)
        if not hasattr(self, 'plugin'):
            raise NotImplementedError
        event_type = 'invalid'

        self.assertNotIn(event_type, self.plugin.get_event_types())

        with testtools.ExpectedException(ValueError):
            self.plugin.process_notification(context, event_type, 'payload')
Beispiel #16
0
    def test_invalid_event_type(self):
        context = DesignateContext.get_admin_context(all_tenants=True)
        if not hasattr(self, 'plugin'):
            raise NotImplementedError
        event_type = 'invalid'

        self.assertNotIn(event_type, self.plugin.get_event_types())

        with testtools.ExpectedException(ValueError):
            self.plugin.process_notification(context, event_type, 'payload')
Beispiel #17
0
    def __init__(self, target):
        super(Backend, self).__init__()

        self.target = target
        self.options = target.options
        self.masters = target.masters

        # TODO(kiall): Context's should never be shared accross requests.
        self.admin_context = DesignateContext.get_admin_context()
        self.admin_context.all_tenants = True
Beispiel #18
0
    def __init__(self):
        # Get a storage connection
        storage_driver = cfg.CONF['service:mdns'].storage_driver
        self.storage = storage.get_storage(storage_driver)
        self.admin_context = DesignateContext.get_admin_context(
            all_tenants=True)

        # Fake request is used to send a response when we cannot decipher the
        # request.
        self._fake_request = dns.message.make_query('unknown', dns.rdatatype.A)
Beispiel #19
0
    def __init__(self, target):
        super(Backend, self).__init__()

        self.target = target
        self.options = target.options
        self.masters = target.masters

        # TODO(kiall): Context's should never be shared accross requests.
        self.admin_context = DesignateContext.get_admin_context()
        self.admin_context.all_tenants = True
Beispiel #20
0
    def start(self):

        # Build the Pool (and related) Object from Config
        context = DesignateContext.get_admin_context()
        pool_id = CONF['service:pool_manager'].pool_id

        has_targets = False

        while not has_targets:
            try:
                self.pool = self.central_api.get_pool(context, pool_id)

                if len(self.pool.targets) > 0:
                    has_targets = True
                else:
                    LOG.error(_LE("No targets for %s found."), self.pool)
                    time.sleep(5)

            # Pool data may not have migrated to the DB yet
            except exceptions.PoolNotFound:
                LOG.error(_LE("Pool ID %s not found."), pool_id)
                time.sleep(5)
            # designate-central service may not have started yet
            except messaging.exceptions.MessagingTimeout:
                time.sleep(0.2)

        # Create the necessary Backend instances for each target
        self._setup_target_backends()

        for target in self.pool.targets:
            self.target_backends[target.id].start()

        super(Service, self).start()

        # Setup a Leader Election, use for ensuring certain tasks are executed
        # on exactly one pool-manager instance at a time]
        self._pool_election = coordination.LeaderElection(
            self._coordinator, '%s:%s' % (self.service_name, self.pool.id))
        self._pool_election.start()

        if CONF['service:pool_manager'].enable_recovery_timer:
            interval = CONF['service:pool_manager'].periodic_recovery_interval
            LOG.info(
                _LI('Starting periodic recovery timer every'
                    ' %(interval)s s') % {'interval': interval})
            self.tg.add_timer(interval, self.periodic_recovery, interval)

        if CONF['service:pool_manager'].enable_sync_timer:
            interval = CONF['service:pool_manager'].periodic_sync_interval
            LOG.info(
                _LI('Starting periodic synchronization timer every'
                    ' %(interval)s s') % {'interval': interval})
            self.tg.add_timer(interval, self.periodic_sync, interval)
Beispiel #21
0
    def start(self):

        # Build the Pool (and related) Object from Config
        context = DesignateContext.get_admin_context()
        pool_id = CONF['service:pool_manager'].pool_id

        has_targets = False

        while not has_targets:
            try:
                self.pool = self.central_api.get_pool(context, pool_id)

                if len(self.pool.targets) > 0:
                    has_targets = True
                else:
                    LOG.error(_LE("No targets for %s found."), self.pool)
                    time.sleep(5)

            # Pool data may not have migrated to the DB yet
            except exceptions.PoolNotFound:
                LOG.error(_LE("Pool ID %s not found."), pool_id)
                time.sleep(5)
            # designate-central service may not have started yet
            except messaging.exceptions.MessagingTimeout:
                time.sleep(0.2)

        # Create the necessary Backend instances for each target
        self._setup_target_backends()

        for target in self.pool.targets:
            self.target_backends[target.id].start()

        super(Service, self).start()

        # Setup a Leader Election, use for ensuring certain tasks are executed
        # on exactly one pool-manager instance at a time]
        self._pool_election = coordination.LeaderElection(
            self._coordinator, '%s:%s' % (self.service_name, self.pool.id))
        self._pool_election.start()

        if CONF['service:pool_manager'].enable_recovery_timer:
            interval = CONF['service:pool_manager'].periodic_recovery_interval
            LOG.info(_LI('Starting periodic recovery timer every'
                         ' %(interval)s s') % {'interval': interval})
            self.tg.add_timer(interval, self.periodic_recovery, interval)

        if CONF['service:pool_manager'].enable_sync_timer:
            interval = CONF['service:pool_manager'].periodic_sync_interval
            LOG.info(_LI('Starting periodic synchronization timer every'
                         ' %(interval)s s') % {'interval': interval})
            self.tg.add_timer(interval, self.periodic_sync, interval)
Beispiel #22
0
    def _create(self, addresses, extra, managed=True,
                resource_type=None, resource_id=None):
        """
        Create a a record from addresses

        :param addresses: Address objects like
                          {'version': 4, 'ip': '10.0.0.1'}
        :param extra: Extra data to use when formatting the record
        :param managed: Is it a managed resource
        :param resource_type: The managed resource type
        :param resource_id: The managed resource ID
        """
        LOG.debug('Using DomainID: %s' % cfg.CONF[self.name].domain_id)
        domain = self.get_domain(cfg.CONF[self.name].domain_id)
        LOG.debug('Domain: %r' % domain)

        data = extra.copy()
        LOG.debug('Event data: %s' % data)
        data['domain'] = domain['name']

        context = DesignateContext.get_admin_context(all_tenants=True)

        for addr in addresses:
            event_data = data.copy()
            event_data.update(get_ip_data(addr))

            recordset_values = {
                'domain_id': domain['id'],
                'name': self._get_format() % event_data,
                'type': 'A' if addr['version'] == 4 else 'AAAA'}

            recordset = self._find_or_create_recordset(
                context, **recordset_values)

            record_values = {
                'data': addr['address']}

            if managed:
                record_values.update({
                    'managed': managed,
                    'managed_plugin_name': self.get_plugin_name(),
                    'managed_plugin_type': self.get_plugin_type(),
                    'managed_resource_type': resource_type,
                    'managed_resource_id': resource_id})

            LOG.debug('Creating record in %s / %s with values %r' %
                      (domain['id'], recordset['id'], record_values))
            self.central_api.create_record(context,
                                           domain['id'],
                                           recordset['id'],
                                           Record(**record_values))
Beispiel #23
0
    def periodic_recovery(self):
        """
        :return:
        """
        LOG.debug("Calling periodic_recovery.")

        context = DesignateContext.get_admin_context(all_tenants=True)

        try:
            self._periodic_delete_domains_that_failed(context)
            self._periodic_create_domains_that_failed(context)
            self._periodic_update_domains_that_failed(context)
        except Exception:
            LOG.exception(
                _LE('An unhandled exception in periodic recovery '
                    'occurred.  This should never happen!'))
Beispiel #24
0
    def __init__(self, target):
        super(Backend, self).__init__()

        self.target = target
        self.options = target.options
        self.masters = target.masters
        self.host = self.options.get('host', '127.0.0.1')
        self.port = int(self.options.get('port', 53))

        # TODO(kiall): Context's should never be shared across requests.
        self.admin_context = DesignateContext.get_admin_context()
        self.admin_context.all_tenants = True

        # Options for sending NOTIFYs
        self.timeout = CONF['service:worker'].poll_timeout
        self.retry_interval = CONF['service:worker'].poll_retry_interval
        self.max_retries = CONF['service:worker'].poll_max_retries
        self.delay = CONF['service:worker'].poll_delay
Beispiel #25
0
    def __init__(self, target):
        super(Backend, self).__init__()

        self.target = target
        self.options = target.options
        self.masters = target.masters
        self.host = self.options.get('host', '127.0.0.1')
        self.port = int(self.options.get('port', 53))

        # TODO(kiall): Context's should never be shared across requests.
        self.admin_context = DesignateContext.get_admin_context()
        self.admin_context.all_tenants = True

        # Options for sending NOTIFYs
        self.timeout = CONF['service:pool_manager'].poll_timeout
        self.retry_interval = CONF['service:pool_manager'].poll_retry_interval
        self.max_retries = CONF['service:pool_manager'].poll_max_retries
        self.delay = CONF['service:pool_manager'].poll_delay
Beispiel #26
0
def main():
    args = parse_args()
    logging.setup('cirrus_floatingip')
    LOG.logger.setLevel('DEBUG')
    load_config(args.config_file)

    kc = keystone_c.Client(username=args.username,
                           password=args.password,
                           tenant_name=args.tenantname,
                           auth_url=args.authurl,
                           endpoint_type=args.endpoint_type,
                           region_name=args.regionname)

    policy.init()
    rpc.init(cfg.CONF)
    context = DesignateContext.get_admin_context(tenant=kc.auth_tenant_id)

    handler = cirrus.CirrusFloatingIPHandler()

    args.func(kc, handler, context, args)
def main():
    args = parse_args()
    logging.setup('cirrus_floatingip')
    LOG.logger.setLevel('DEBUG')
    load_config(args.config_file)

    kc = keystone_c.Client(
        username=args.username,
        password=args.password,
        tenant_name=args.tenantname,
        auth_url=args.authurl,
        endpoint_type=args.endpoint_type,
        region_name=args.regionname)

    policy.init()
    rpc.init(cfg.CONF)
    context = DesignateContext.get_admin_context(tenant=kc.auth_tenant_id)

    handler = cirrus.CirrusFloatingIPHandler()

    args.func(kc, handler, context, args)
Beispiel #28
0
 def _create_reverse_record(self, context, managed, host_fqdn, interface):
     LOG.info('Create reverse record for interface: %s and address: %s', interface['label'], interface['address'])
     host_reverse_fqdn = self._get_reverse_fqdn(interface['address'], interface['version'])
     LOG.info('Create reverse record: %s', host_reverse_fqdn)
     reverse_domains = self._get_reverse_domains(host_reverse_fqdn)
     admin_context = DesignateContext.get_admin_context(all_tenants=True)
     for reverse_domain in reverse_domains:
         LOG.info('Create reverse record for domain: %s', reverse_domain.name)
         try:
             recordset = self.central_api.create_recordset(admin_context,
                                                           reverse_domain.id,
                                                           RecordSet(name=host_reverse_fqdn, type='PTR'))
         except exceptions.DuplicateRecordSet:
             LOG.warn('The reverse record: %s was already registered', host_reverse_fqdn)
         else:
             record_values = dict(managed, data=host_fqdn)
             LOG.debug('Creating reverse record in %s / %s with values %r',
                       reverse_domain.id, recordset['id'], record_values)
             self.central_api.create_record(admin_context,
                                            reverse_domain.id,
                                            recordset['id'],
                                            Record(**record_values))
Beispiel #29
0
    def _delete(self,
                managed=True,
                resource_id=None,
                resource_type='instance',
                criterion=None):
        """
        Handle a generic delete of a fixed ip within a domain

        :param criterion: Criterion to search and destroy records
        """
        if not managed:
            LOG.warning(
                _LW('Deprecation notice: Unmanaged designate-sink records are '
                    'being deprecated please update the call '
                    'to remove managed=False'))
        criterion = criterion or {}

        context = DesignateContext.get_admin_context(all_tenants=True)

        criterion.update({'domain_id': cfg.CONF[self.name].domain_id})

        if managed:
            criterion.update({
                'managed': managed,
                'managed_plugin_name': self.get_plugin_name(),
                'managed_plugin_type': self.get_plugin_type(),
                'managed_resource_id': resource_id,
                'managed_resource_type': resource_type
            })

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

        for record in records:
            LOG.debug('Deleting record %s' % record['id'])

            self.central_api.delete_record(context,
                                           cfg.CONF[self.name].domain_id,
                                           record['recordset_id'],
                                           record['id'])
Beispiel #30
0
    def _create(self, addresses, extra, managed=True,
                resource_type=None, resource_id=None):
        """
        Create a a record from addresses

        :param addresses: Address objects like
                          {'version': 4, 'ip': '10.0.0.1'}
        :param extra: Extra data to use when formatting the record
        :param managed: Is it a managed resource
        :param resource_type: The managed resource type
        :param resource_id: The managed resource ID
        """
        LOG.debug('Using DomainID: %s' % cfg.CONF[self.name].domain_id)
        domain = self.get_domain(cfg.CONF[self.name].domain_id)
        LOG.debug('Domain: %r' % domain)

        data = extra.copy()
        data['domain'] = domain['name']

        context = DesignateContext.get_admin_context()

        for addr in addresses:
            record_data = data.copy()
            record_data.update(get_ip_data(addr))

            record_name = self._get_format() % record_data
            record_values = {
                'type': 'A' if addr['version'] == 4 else 'AAAA',
                'name': record_name,
                'data': addr['address']}
            if managed:
                record_values.update({
                    'managed': managed,
                    'managed_plugin_name': self.get_plugin_name(),
                    'managed_plugin_type': self.get_plugin_type(),
                    'managed_resource_type': resource_type,
                    'managed_resource_id': resource_id})
            central_api.create_record(context, domain['id'], record_values)
Beispiel #31
0
    def periodic_sync(self):
        """
        :return: None
        """
        # TODO(kiall): Replace this inter-process-lock with a distributed
        #              lock, likely using the tooz library - see bug 1445127.
        with lockutils.lock('periodic_sync', external=True, delay=30):
            context = DesignateContext.get_admin_context(all_tenants=True)

            LOG.debug("Starting Periodic Synchronization")

            criterion = {
                'pool_id': CONF['service:pool_manager'].pool_id,
                'status': '!%s' % ERROR_STATUS
            }

            periodic_sync_seconds = \
                CONF['service:pool_manager'].periodic_sync_seconds

            if periodic_sync_seconds is not None:
                # Generate the current serial, will provide a UTC Unix TS.
                current = utils.increment_serial()
                criterion['serial'] = ">%s" % (current - periodic_sync_seconds)

            domains = self.central_api.find_domains(context, criterion)

            try:
                for domain in domains:
                    # TODO(kiall): If the domain was created within the last
                    #              periodic_sync_seconds, attempt to recreate
                    #              to fill in targets which may have failed.
                    self.update_domain(context, domain)

            except Exception:
                LOG.exception(
                    _LE('An unhandled exception in periodic '
                        'synchronization occurred.'))
Beispiel #32
0
    def periodic_sync(self):
        """
        :return: None
        """
        # TODO(kiall): Replace this inter-process-lock with a distributed
        #              lock, likely using the tooz library - see bug 1445127.
        with lockutils.lock('periodic_sync', external=True, delay=30):
            context = DesignateContext.get_admin_context(all_tenants=True)

            LOG.debug("Starting Periodic Synchronization")

            criterion = {
                'pool_id': CONF['service:pool_manager'].pool_id,
                'status': '!%s' % ERROR_STATUS
            }

            periodic_sync_seconds = \
                CONF['service:pool_manager'].periodic_sync_seconds

            if periodic_sync_seconds is not None:
                # Generate the current serial, will provide a UTC Unix TS.
                current = utils.increment_serial()
                criterion['serial'] = ">%s" % (current - periodic_sync_seconds)

            domains = self.central_api.find_domains(context, criterion)

            try:
                for domain in domains:
                    # TODO(kiall): If the domain was created within the last
                    #              periodic_sync_seconds, attempt to recreate
                    #              to fill in targets which may have failed.
                    self.update_domain(context, domain)

            except Exception:
                LOG.exception(_LE('An unhandled exception in periodic '
                                  'synchronization occurred.'))
Beispiel #33
0
 def get_admin_context(self):
     return DesignateContext.get_admin_context()
Beispiel #34
0
    def _create(self, addresses, extra, managed=True,
                resource_type=None, resource_id=None):
        """
        Create a a record from addresses

        :param addresses: Address objects like
                          {'version': 4, 'ip': '10.0.0.1'}
        :param extra: Extra data to use when formatting the record
        :param managed: Is it a managed resource
        :param resource_type: The managed resource type
        :param resource_id: The managed resource ID
        """
        LOG.debug('Using DomainID: %s' % cfg.CONF[self.name].domain_id)
        domain = self.get_domain(cfg.CONF[self.name].domain_id)
        LOG.debug('Domain: %r' % domain)

        data = extra.copy()
        LOG.debug('Event data: %s' % data)
        data['domain'] = domain['name']

        context = DesignateContext.get_admin_context(all_tenants=True)

        # Extra magic!  The event record contains a tenant id but not a tenant name.  So
        #  if our formats include project_name then we need to ask keystone for the name.
        need_project_name = False
        for fmt in cfg.CONF[self.name].get('format'):
            if 'project_name' in fmt:
                need_project_name = True
                break
        if 'project_name' in cfg.CONF[self.name].get('reverse_format'):
            need_project_name = True
        if need_project_name:
            project_name = self._resolve_project_name(data['tenant_id'])
            data['project_name'] = project_name

        for addr in addresses:
            event_data = data.copy()
            event_data.update(self._get_ip_data(addr))

            if addr['version'] == 4:
                reverse_format = cfg.CONF[self.name].get('reverse_format')
                reverse_domain_id = cfg.CONF[self.name].get('reverse_domain_id')
                if reverse_format and reverse_domain_id:
                    reverse_domain = self.get_domain(reverse_domain_id)
                    LOG.debug('Reverse domain: %r' % reverse_domain)

                    ip_digits = addr['address'].split('.')
                    ip_digits.reverse()
                    name = "%s.in-addr.arpa." % '.'.join(ip_digits)

                    recordset_values = {
                        'domain_id': reverse_domain['id'],
                        'name': name,
                        'type': 'PTR',
                    }
                    recordset = self._find_or_create_recordset(
                        context, **recordset_values)

                    record_values = {'data': reverse_format % event_data}

                    if managed:
                        record_values.update({
                            'managed': managed,
                            'managed_plugin_name': self.get_plugin_name(),
                            'managed_plugin_type': self.get_plugin_type(),
                            'managed_resource_type': resource_type,
                            'managed_resource_id': resource_id})

                    LOG.warn('Creating record in %s / %s with values %r',
                             reverse_domain['id'],
                             recordset['id'], record_values)
                    central_api.create_record(context,
                                              reverse_domain['id'],
                                              recordset['id'],
                                              Record(**record_values))

            for fmt in cfg.CONF[self.name].get('format'):
                recordset_values = {
                    'domain_id': domain['id'],
                    'name': fmt % event_data,
                    'type': 'A' if addr['version'] == 4 else 'AAAA'}

                recordset = self._find_or_create_recordset(
                    context, **recordset_values)

                record_values = {
                    'data': addr['address']}

                if managed:
                    record_values.update({
                        'managed': managed,
                        'managed_plugin_name': self.get_plugin_name(),
                        'managed_plugin_type': self.get_plugin_type(),
                        'managed_resource_type': resource_type,
                        'managed_resource_id': resource_id})

                LOG.warn('Creating record in %s / %s with values %r',
                         domain['id'], recordset['id'], record_values)
                central_api.create_record(context,
                                          domain['id'],
                                          recordset['id'],
                                          Record(**record_values))
Beispiel #35
0
 def _get_admin_context_all_tenants(self):
     return DesignateContext.get_admin_context(all_tenants=True)
Beispiel #36
0
 def _get_context(self, tenant_id=None):
     if tenant_id:
         return DesignateContext.get_admin_context(tenant=tenant_id, edit_managed_records=True)
     else:
         return DesignateContext.get_admin_context(all_tenants=True, edit_managed_records=True)
Beispiel #37
0
    def process_notification(self, context, event_type, payload):
        # Take notification and create a record
        LOG.debug('FloatingV4Handler: Event type received: %s', event_type)
        zone = self.get_zone(cfg.CONF[self.name].zone_id)

        domain_id = zone['id']

        # Gather extra information (need to compare payload['floating_ip'] and figure out which zone it fits in.
        # The domains are owned by admin so we need admin context?

        elevated_context = DesignateContext.get_admin_context(
            all_tenants=True, edit_managed_records=True)

        criterion = {
            "tenant_id": cfg.CONF[self.name].admin_tenant_id,
        }

        zones = self.central_api.find_zones(elevated_context, criterion)

        # Calculate Reverse Address
        v4address = ipaddress.ip_address(payload['floating_ip'])
        reverse_address = v4address.reverse_pointer + '.'
        reverse_id = None

        for i in zones:
            if i.name == reverse_address[4:]:
                reverse_id = i.id

        if event_type == 'network.floating_ip.associate':
            LOG.debug('FloatingV4Handler: Creating A record for %s on %s',
                      payload['floating_ip'], payload['instance_id'])

            # Get ec2id for hostname (in user's context)
            kc = keystone_c.Client(
                token=context['auth_token'],
                tenant_id=context['tenant'],
                auth_url=cfg.CONF['handler:nova_floating'].auth_uri)

            nova_endpoint = kc.service_catalog.url_for(
                service_type='compute', endpoint_type='internalURL')

            nvc = nova_c.Client(auth_token=kc.auth_token,
                                tenant_id=kc.auth_tenant_id,
                                bypass_url=nova_endpoint)

            server_info = nvc.servers.get(payload['instance_id'])

            # Determine the hostname
            ec2id = getattr(server_info, 'OS-EXT-SRV-ATTR:instance_name')
            ec2id = ec2id.split('-', 1)[1].lstrip('0')
            hostname = '%s.%s' % (ec2id, zone['name'])

            record_type = 'A'

            recordset_values = {
                'zone_id': domain_id,
                'name': hostname,
                'type': record_type
            }

            recordset = self._find_or_create_recordset(elevated_context,
                                                       **recordset_values)

            record_values = {
                'data': payload['floating_ip'],
                'managed': True,
                'managed_plugin_name': self.get_plugin_name(),
                'managed_plugin_type': self.get_plugin_type(),
                'managed_resource_type': 'instance',
                'managed_resource_id': payload['instance_id']
            }

            LOG.debug('Creating record in %s / %s with values %r' %
                      (domain_id, recordset['id'], record_values))
            self.central_api.create_record(elevated_context, domain_id,
                                           recordset['id'],
                                           Record(**record_values))

            # Reverse Record

            record_type = 'PTR'

            if reverse_id == None:
                LOG.debug('UNABLE TO DETERMINE REVERSE ZONE: %s',
                          payload['floating_ip'])

            else:
                recordset_values = {
                    'zone_id': reverse_id,
                    'name': reverse_address,
                    'type': record_type
                }

                recordset = self._find_or_create_recordset(
                    elevated_context, **recordset_values)
                record_values = {
                    'data': hostname,
                    'managed': True,
                    'managed_plugin_name': self.get_plugin_name(),
                    'managed_plugin_type': self.get_plugin_type(),
                    'managed_resource_type': 'instance',
                    'managed_resource_id': payload['instance_id']
                }

                LOG.debug('Creating record in %s / %s with values %r' %
                          (reverse_id, recordset['id'], record_values))
                self.central_api.create_record(elevated_context, reverse_id,
                                               recordset['id'],
                                               Record(**record_values))

        elif event_type == 'network.floating_ip.disassociate':
            LOG.debug('FloatingV4Handler: Deleting A record for %s on %s',
                      payload['floating_ip'], payload['instance_id'])

            self._delete(zone_id=domain_id,
                         resource_id=payload['instance_id'],
                         resource_type='instance')

            if reverse_id == None:
                LOG.debug('UNABLE TO DETERMINE REVERSE ZONE: %s',
                          payload['floating_ip'])

            else:
                self._delete(zone_id=reverse_id,
                             resource_id=payload['instance_id'],
                             resource_type='instance')
Beispiel #38
0
 def get_admin_context(self):
     return DesignateContext.get_admin_context(
         tenant=utils.generate_uuid(),
         user=utils.generate_uuid())
Beispiel #39
0
 def get_domain(self, domain_id):
     """
     Return the domain for this context
     """
     context = DesignateContext.get_admin_context(all_tenants=True)
     return self.central_api.get_domain(context, domain_id)
Beispiel #40
0
 def __init__(self, central_service):
     super(Backend, self).__init__()
     self.central_service = central_service
     self.admin_context = DesignateContext.get_admin_context()
Beispiel #41
0
    def _create(self,
                addresses,
                extra,
                managed=True,
                resource_type=None,
                resource_id=None):
        """
        Create a record from addresses

        :param addresses: Address objects like
                          {'version': 4, 'ip': '10.0.0.1'}
        :param extra: Extra data to use when formatting the record
        :param managed: Is it a managed resource
        :param resource_type: The managed resource type
        :param resource_id: The managed resource ID
        """
        LOG.debug('Using DomainID: %s' % cfg.CONF[self.name].domain_id)
        zone = self.get_zone(cfg.CONF[self.name].domain_id)
        LOG.debug('Domain: %r' % zone)

        data = extra.copy()
        LOG.debug('Event data: %s' % data)
        data['zone'] = zone['name']

        context = DesignateContext.get_admin_context(all_tenants=True)

        # We have a hack elsewhere in keystone to ensure that tenant id == tenant name.
        #  So... we can safely use the id in the fqdn.
        data['project_name'] = data['tenant_id']

        for addr in addresses:
            event_data = data.copy()
            event_data.update(self._get_ip_data(addr))

            if addr['version'] == 4:
                reverse_format = cfg.CONF[self.name].get('reverse_format')
                reverse_zone_id = cfg.CONF[self.name].get('reverse_domain_id')
                if reverse_format and reverse_zone_id:
                    reverse_zone = self.get_zone(reverse_zone_id)
                    LOG.debug('Reverse zone: %r' % reverse_zone)

                    ip_digits = addr['address'].split('.')
                    ip_digits.reverse()
                    name = "%s.in-addr.arpa." % '.'.join(ip_digits)

                    recordset_values = {
                        'zone_id': reverse_zone['id'],
                        'name': name,
                        'type': 'PTR',
                    }
                    recordset = self._find_or_create_recordset(
                        context, **recordset_values)

                    record_values = {'data': reverse_format % event_data}

                    if managed:
                        record_values.update({
                            'managed':
                            managed,
                            'managed_plugin_name':
                            self.get_plugin_name(),
                            'managed_plugin_type':
                            self.get_plugin_type(),
                            'managed_resource_type':
                            resource_type,
                            'managed_resource_id':
                            resource_id
                        })

                    LOG.warn(
                        'Creating reverse record in %s / %s with values %r',
                        reverse_zone['id'], recordset['id'], record_values)
                    central_api.create_record(context, reverse_zone['id'],
                                              recordset['id'],
                                              Record(**record_values))

            for fmt in cfg.CONF[self.name].get('format'):
                self._create_record(context, fmt, zone, event_data, addr,
                                    managed, resource_type, resource_id)

            legacy_zone_id = cfg.CONF[self.name].get('legacy_domain_id')
            if legacy_zone_id:
                legacy_zone = self.get_zone(legacy_zone_id)
                event_data['zone'] = legacy_zone['name']
                for fmt in cfg.CONF[self.name].get('legacy_format'):
                    self._create_record(context, fmt, legacy_zone, event_data,
                                        addr, managed, resource_type,
                                        resource_id)
Beispiel #42
0
    def __init__(self, backend_options):
        super(Backend, self).__init__()
        self.backend_options = backend_options

        self.admin_context = DesignateContext.get_admin_context()
        self.admin_context.all_tenants = True
Beispiel #43
0
 def _get_admin_context_all_tenants(self):
     return DesignateContext.get_admin_context(all_tenants=True)
Beispiel #44
0
 def get_domain(self, domain_id):
     """
     Return the domain for this context
     """
     context = DesignateContext.get_admin_context()
     return central_api.get_domain(context, domain_id)
    def process_notification(self, context, event_type, payload):
        # Take notification and create a record
        LOG.debug('FloatingV4Handler: Event type received: %s', event_type)
        zone = self.get_zone(cfg.CONF[self.name].zone_id)

        domain_id = zone['id']

        # Gather extra information (need to compare payload['floating_ip'] and figure out which zone it fits in.
        # The domains are owned by admin so we need admin context?

        elevated_context = DesignateContext.get_admin_context(all_tenants=True, edit_managed_records=True)

        criterion = {
            "tenant_id": cfg.CONF[self.name].admin_tenant_id,
        }

        zones = self.central_api.find_zones(elevated_context, criterion)

        # Calculate Reverse Address
        v4address = ipaddress.ip_address(payload['floating_ip'])
        reverse_address = v4address.reverse_pointer + '.'
        reverse_network = '.'.join(reverse_address.split('.')[1:])
        reverse_id = None

        for i in zones:
            if i.name == reverse_network:
                reverse_id = i.id

        if event_type == 'network.floating_ip.associate':
            LOG.debug('FloatingV4Handler: Creating A record for %s on %s', payload['floating_ip'], payload['instance_id'])

            # Get ec2id for hostname (must be admin
            kc = keystone_c.Client(username=cfg.CONF['keystone_authtoken'].admin_user,
                    password=cfg.CONF['keystone_authtoken'].admin_password,
                    tenant_name=cfg.CONF['keystone_authtoken'].admin_tenant_name,
                    auth_url = cfg.CONF['handler:nova_fixed_v6'].auth_uri)

            nova_endpoint = kc.service_catalog.url_for(service_type='compute',
                        endpoint_type='internalURL')

            nvc = nova_c.Client(auth_token=kc.auth_token,
                        tenant_id=kc.auth_tenant_id,
                        bypass_url=nova_endpoint)

            server_info = nvc.servers.get(payload['instance_id'])

            # Determine the hostname
            ec2id = getattr(server_info, 'OS-EXT-SRV-ATTR:instance_name')
            ec2id = ec2id.split('-', 1)[1].lstrip('0')
            hostname = '%s.%s' % (ec2id, zone['name'])

            record_type = 'A'

            recordset_values = {
                'zone_id': domain_id,
                'name': hostname,
                'type': record_type
            }

            recordset = self._find_or_create_recordset(elevated_context, **recordset_values)

            record_values = {
                'data': payload['floating_ip'],
                'managed': True,
                'managed_plugin_name': self.get_plugin_name(),
                'managed_plugin_type': self.get_plugin_type(),
                'managed_resource_type': 'instance',
                'managed_resource_id': payload['instance_id']
            }

            LOG.debug('Creating record in %s / %s with values %r' %
                      (domain_id, recordset['id'], record_values))
            self.central_api.create_record(elevated_context,
                                       domain_id,
                                       recordset['id'],
                                       Record(**record_values))

            # Reverse Record

            record_type = 'PTR'

            if reverse_id == None:
                LOG.debug('UNABLE TO DETERMINE REVERSE ZONE: %s', payload['floating_ip'])

            else:
                recordset_values = {
                    'zone_id': reverse_id,
                    'name': reverse_address,
                    'type': record_type
                }

                recordset = self._find_or_create_recordset(elevated_context, **recordset_values)
                record_values = {
                    'data': hostname,
                    'managed': True,
                    'managed_plugin_name': self.get_plugin_name(),
                    'managed_plugin_type': self.get_plugin_type(),
                    'managed_resource_type': 'instance',
                    'managed_resource_id': payload['instance_id']
                }

                LOG.debug('Creating record in %s / %s with values %r' %
                          (reverse_id, recordset['id'], record_values))
                self.central_api.create_record(elevated_context,
                                           reverse_id,
                                           recordset['id'],
                                           Record(**record_values))

        elif event_type == 'network.floating_ip.disassociate':
            LOG.debug('FloatingV4Handler: Deleting A record for %s on %s', payload['floating_ip'], payload['instance_id'])

            self._delete(zone_id=domain_id,
                    resource_id=payload['instance_id'],
                    resource_type='instance')

            if reverse_id == None:
                LOG.debug('UNABLE TO DETERMINE REVERSE ZONE: %s', payload['floating_ip'])

            else:
                self._delete(zone_id=reverse_id,
                    resource_id=payload['instance_id'],
                    resource_type='instance')
Beispiel #46
0
 def __init__(self, central_service):
     super(Backend, self).__init__()
     self.central_service = central_service
     self.admin_context = DesignateContext.get_admin_context()
     self.admin_context.all_tenants = True
    def process_notification(self, context, event_type, payload):
        LOG.debug('NovaFixedV6Handler: %s', event_type)
        zone = self.get_zone(cfg.CONF[self.name].zone_id)
        reverse_zone = self.get_zone(cfg.CONF[self.name].reverse_zone_id)

        domain_id = zone['id']
        reverse_domain_id = reverse_zone['id']

        if event_type == 'compute.instance.create.end':
            kc = keystone_c.Client(token=context['auth_token'],
                        tenant_id=context['tenant'],
                        auth_url=cfg.CONF['handler:nova_fixed_v6'].auth_uri)

            context = DesignateContext.get_admin_context(all_tenants=True)
            nova_endpoint = kc.service_catalog.url_for(service_type='compute',
                        endpoint_type='internalURL')

            nvc = nova_c.Client(auth_token=kc.auth_token,
                        tenant_id=kc.auth_tenant_id,
                        bypass_url=nova_endpoint)

            server_info = nvc.servers.get(payload['instance_id'])

            # Determine the hostname
            ec2id = getattr(server_info, 'OS-EXT-SRV-ATTR:instance_name')
            ec2id = ec2id.split('-', 1)[1].lstrip('0')
            hostname = '%s.%s' % (ec2id, zone['name'])

            LOG.debug('NovaFixedV6Handler creating AAAA record (%s) for - %s', hostname, payload['instance_id'])

            # 1 recordset of an A and AAAA record

            for fixed_ip in payload['fixed_ips']:
                # Don't create an A record for the private address.
                if fixed_ip['version'] == 4:
                    continue

                record_type = 'AAAA'

                recordset_values = {
                    'zone_id': domain_id,
                    'name': hostname,
                    'type': record_type
                }

                recordset = self._find_or_create_recordset(context, **recordset_values)
                LOG.debug('NovaFixedv6Hadler AAAA %s' % fixed_ip['address'])

                record_values = {
                    'data': fixed_ip['address'],
                    'managed': True,
                    'managed_plugin_name': self.get_plugin_name(),
                    'managed_plugin_type': self.get_plugin_type(),
                    'managed_resource_type': 'instance',
                    'managed_resource_id': payload['instance_id']
                }

                LOG.debug('Creating record in %s / %s with values %r' %
                          (domain_id, recordset['id'], record_values))
                self.central_api.create_record(context,
                                           domain_id,
                                           recordset['id'],
                                           Record(**record_values))

                # Create PTR
                record_type = 'PTR'

                # Calculate reverse address
                v6address = ipaddress.ip_address(fixed_ip['address'])
                reverse_address = v6address.reverse_pointer + '.'

                recordset_values = {
                    'zone_id' : reverse_domain_id,
                    'name' : reverse_address,
                    'type' : record_type
                }

                reverse_recordset = self._find_or_create_recordset(context, **recordset_values)

                record_values = {
                    'data': hostname,
                    'managed': True,
                    'managed_plugin_name': self.get_plugin_name(),
                    'managed_plugin_type': self.get_plugin_type(),
                    'managed_resource_type': 'instance',
                    'managed_resource_id': payload['instance_id']
                }

                LOG.debug('NovaFixedV6Handler Creating record in %s / %s with values %r' %
                          (reverse_domain_id, reverse_recordset['id'], record_values))
                self.central_api.create_record(context,
                                           reverse_domain_id,
                                           reverse_recordset['id'],
                                           Record(**record_values))

        elif event_type == 'compute.instance.delete.start':
            # Nova Delete Event does not include fixed_ips. Hence why we had the instance ID in the records.
            LOG.debug('NovaFixedV6Handler delete AAAA record for - %s', payload['instance_id'])

            self._delete(zone_id=domain_id,
                    resource_id=payload['instance_id'],
                    resource_type='instance')
            self._delete(zone_id=reverse_domain_id,
                    resource_id=payload['instance_id'],
                    resource_type='instance')
Beispiel #48
0
 def get_zone(self, zone_id):
     """
     Return the zone for this context
     """
     context = DesignateContext.get_admin_context(all_tenants=True)
     return self.central_api.get_zone(context, zone_id)
    def process_notification(self, context, event_type, payload):
        LOG.debug('NeutronFloatingHandler: Event type received: %s', event_type)
        LOG.debug('NeutronFloatingHandler: Event body received: %s', payload)
        zone_id = cfg.CONF[self.name].zone_id
        zone = self.get_zone(zone_id)

        # Get a list all all zones owned by the zone tenant owner.
        # This is so we can find the reverse DNS zone.
        elevated_context = DesignateContext.get_admin_context(
            all_tenants=True, edit_managed_records=True)

        criterion = {
            "tenant_id": cfg.CONF[self.name].zone_owner_tenant_id,
        }

        zones = self.central_api.find_zones(elevated_context, criterion)


        if event_type.startswith('floatingip.delete'):
            self._delete(zone_id=zone_id,
                         resource_id=payload['floatingip_id'],
                         resource_type='instance')
        elif event_type.startswith('floatingip.update'):
            floatingip = payload['floatingip']['floating_ip_address']

            # Calculate Reverse Address
            v4address = ipaddress.ip_address(floatingip)
            reverse_address = v4address.reverse_pointer + '.'
            reverse_network = '.'.join(reverse_address.split('.')[1:])
            reverse_id = None

            # Loop through all zones and see if one matches the reverse zone
            reverse_id = None
            for i in zones:
                if i.name == reverse_network:
                    reverse_id = i.id

            if payload['floatingip']['fixed_ip_address']:
                # Create a nova client
                username = cfg.CONF[self.name].admin_user
                password = cfg.CONF[self.name].admin_password
                tenant_name = cfg.CONF[self.name].admin_tenant_name
                auth_url = cfg.CONF[self.name].auth_url
                auth = v3.Password(username=username, password=password,
                                   project_name=tenant_name, project_domain_name='default',
                                   user_domain_name='default', auth_url=auth_url)
                sess = session.Session(auth=auth)
                nvc = nova_c.Client(2.1, session=sess)

                # Search for an instance with the matching fixed ip
                search_opts = {
                    'ip': payload['floatingip']['fixed_ip_address'],
                    'status': 'ACTIVE',
                    'all_tenants': True,
                    'tenant_id': payload['floatingip']['tenant_id'],
                }
                instances = nvc.servers.list(detailed=True, search_opts=search_opts)

                if len(instances) == 1:
                    instance = instances[0]
                    # Get the ec2 id of the instance and build the hostname from it
                    ec2id = getattr(instance, 'OS-EXT-SRV-ATTR:instance_name')
                    ec2id = ec2id.split('-', 1)[1].lstrip('0')
                    hostname = '%s.%s' % (ec2id, zone['name'])

                    # create a recordset
                    record_type = 'A'
                    recordset_values = {
                        'zone_id': zone_id,
                        'name': hostname,
                        'type': record_type
                    }
                    recordset = self._find_or_create_recordset(
                        elevated_context, **recordset_values)
                    record_values = {
                        'data': floatingip,
                        'managed': True,
                        'managed_plugin_name': self.get_plugin_name(),
                        'managed_plugin_type': self.get_plugin_type(),
                        'managed_resource_type': 'instance',
                        'managed_resource_id': payload['floatingip']['id'],
                        'managed_extra': 'instance:%s' % (getattr(instance, 'id')),
                    }

                    LOG.debug('Creating record in %s / %s with values %r' %
                              (zone_id, recordset['id'], record_values))
                    self.central_api.create_record(elevated_context,
                                                   zone_id,
                                                   recordset['id'],
                                                   Record(**record_values))

                    # create a reverse recordset
                    record_type = 'PTR'

                    if reverse_id == None:
                        LOG.debug('UNABLE TO DETERMINE REVERSE ZONE: %s', payload['floatingip'])

                    else:
                        recordset_values = {
                            'zone_id': reverse_id,
                            'name': reverse_address,
                            'type': record_type
                        }

                        recordset = self._find_or_create_recordset(
                            elevated_context, **recordset_values)
                        record_values = {
                            'data': hostname,
                            'managed': True,
                            'managed_plugin_name': self.get_plugin_name(),
                            'managed_plugin_type': self.get_plugin_type(),
                            'managed_resource_type': 'instance',
                            'managed_resource_id': payload['floatingip']['id'],
                            'managed_extra': 'instance:%s' % (getattr(instance, 'id')),
                        }

                        LOG.debug('Creating record in %s / %s with values %r' %
                                  (reverse_id, recordset['id'], record_values))
                        self.central_api.create_record(elevated_context,
                                                       reverse_id,
                                                       recordset['id'],
                                                       Record(**record_values))
            else:
                LOG.debug('Deleting records for %s / %s' % (zone_id, payload['floatingip']['id']))
                self._delete(zone_id=zone_id,
                             resource_id=payload['floatingip']['id'],
                             resource_type='instance')

                if reverse_id == None:
                    LOG.debug('UNABLE TO DETERMINE REVERSE ZONE: %s', payload['floatingip'])
                else:
                    LOG.debug('Deleting records for %s / %s' % (reverse_id, payload['floatingip']['id']))
                    self._delete(zone_id=reverse_id,
                        resource_id=payload['floatingip']['id'],
                        resource_type='instance')
    def process_notification(self, context, event_type, payload):
        LOG.debug('NovaFixedV6Handler: Event type received %s', event_type)
        LOG.debug('NovaFixedV6Handler: Event body received %s', payload)
        zone = self.get_zone(cfg.CONF[self.name].zone_id)
        reverse_zone = self.get_zone(cfg.CONF[self.name].reverse_zone_id)

        domain_id = zone['id']
        reverse_domain_id = reverse_zone['id']

        if event_type == 'compute.instance.create.end':
            # Need admin context to get the ec2id. Otherwise using the normal context would have worked.
            username = cfg.CONF[self.name].admin_user
            password = cfg.CONF[self.name].admin_password
            tenant_name = cfg.CONF[self.name].admin_tenant_name
            auth_url = cfg.CONF[self.name].auth_url
            auth = v3.Password(username=username, password=password,
                               project_name=tenant_name, project_domain_name='default',
                               user_domain_name='default', auth_url=auth_url)
            sess = session.Session(auth=auth)
            nvc = nova_c.Client(2.1, session=sess)

            instance = nvc.servers.get(payload['instance_id'])

            # Determine the hostname
            ec2id = getattr(instance, 'OS-EXT-SRV-ATTR:instance_name')
            ec2id = ec2id.split('-', 1)[1].lstrip('0')
            hostname = '%s.%s' % (ec2id, zone['name'])

            LOG.debug('NovaFixedV6Handler creating AAAA record (%s) for - %s', hostname, payload['instance_id'])
            # Become Designate Admin to manage records
            context = DesignateContext.get_admin_context(all_tenants=True)

            # 1 recordset of an A and AAAA record

            for fixed_ip in payload['fixed_ips']:
                # Don't create an A record for the private address.
                if fixed_ip['version'] == 4:
                    continue

                record_type = 'AAAA'

                recordset_values = {
                    'zone_id': domain_id,
                    'name': hostname,
                    'type': record_type
                }

                recordset = self._find_or_create_recordset(context, **recordset_values)

                record_values = {
                    'data': fixed_ip['address'],
                    'managed': True,
                    'managed_plugin_name': self.get_plugin_name(),
                    'managed_plugin_type': self.get_plugin_type(),
                    'managed_resource_type': 'instance',
                    'managed_resource_id': payload['instance_id']
                }

                LOG.debug('Creating record in %s / %s with values %r' %
                          (domain_id, recordset['id'], record_values))
                self.central_api.create_record(context,
                                           domain_id,
                                           recordset['id'],
                                           Record(**record_values))

                # Create PTR
                record_type = 'PTR'

                # Calculate reverse address
                v6address = ipaddress.ip_address(fixed_ip['address'])
                reverse_address = v6address.reverse_pointer + '.'

                recordset_values = {
                    'zone_id' : reverse_domain_id,
                    'name' : reverse_address,
                    'type' : record_type
                }

                reverse_recordset = self._find_or_create_recordset(context, **recordset_values)

                record_values = {
                    'data': hostname,
                    'managed': True,
                    'managed_plugin_name': self.get_plugin_name(),
                    'managed_plugin_type': self.get_plugin_type(),
                    'managed_resource_type': 'instance',
                    'managed_resource_id': payload['instance_id']
                }

                LOG.debug('NovaFixedV6Handler Creating record in %s / %s with values %r' %
                          (reverse_domain_id, reverse_recordset['id'], record_values))
                self.central_api.create_record(context,
                                           reverse_domain_id,
                                           reverse_recordset['id'],
                                           Record(**record_values))

                nvc.servers.set_meta_item(instance, 'dns', hostname[:-1])

        elif event_type == 'compute.instance.delete.start':
            # Nova Delete Event does not include fixed_ips. Hence why we had the instance ID in the records.
            LOG.debug('NovaFixedV6Handler delete A and AAAA record for - %s', payload['instance_id'])

            self._delete(zone_id=domain_id,
                    resource_id=payload['instance_id'],
                    resource_type='instance')
            self._delete(zone_id=reverse_domain_id,
                    resource_id=payload['instance_id'],
                    resource_type='instance')

            # search for and delete floating IPs
            elevated_context = DesignateContext.get_admin_context(
                all_tenants=True, edit_managed_records=True)

            criterion = {
                'managed': True,
                'managed_plugin_name': 'neutron_floating',
                'managed_resource_type': 'instance',
                'managed_extra': 'instance:%s' % (payload['instance_id']),
            }
            records = self.central_api.find_records(elevated_context, criterion)
            LOG.debug('Found %d floating ip records to delete for %s' % (len(records), payload['instance_id']))
            for record in records:
                zones = self.central_api.find_zones(elevated_context)
                for zone in zones:
                    try:
                        recordset = self.central_api.get_recordset(elevated_context, zone['id'], record['recordset_id'])
                        LOG.debug('Deleting record %s from %s / %s' % (record['id'], zone['id'], record['recordset_id']))
                        #self.central_api.delete_record(elevated_context, zone['id'], record['recordset_id'], record['id'])
                        self.central_api.delete_recordset(elevated_context, zone['id'], record['recordset_id'])
                    except:
                        pass
Beispiel #51
0
 def get_admin_context(self):
     return DesignateContext.get_admin_context(
         project_id=utils.generate_uuid(), user_id=utils.generate_uuid())
Beispiel #52
0
 def __init__(self):
     self.context = DesignateContext.get_admin_context(
         request_id='designate-manage')
     policy.init()
Beispiel #53
0
 def get_zone(self, zone_id):
     """
     Return the zone for this context
     """
     context = DesignateContext.get_admin_context(all_tenants=True)
     return self.central_api.get_zone(context, zone_id)
Beispiel #54
0
 def get_domain(self, domain_id):
     """
     Return the domain for this context
     """
     context = DesignateContext.get_admin_context()
     return central_api.get_domain(context, domain_id)
Beispiel #55
0
 def get_domain(self, domain_id):
     """
     Return the domain for this context
     """
     context = DesignateContext.get_admin_context(all_tenants=True)
     return self.central_api.get_domain(context, domain_id)
Beispiel #56
0
 def __init__(self):
     self.context = DesignateContext.get_admin_context(
         request_id='designate-manage')
     policy.init()
Beispiel #57
0
 def get_admin_context(self):
     return DesignateContext.get_admin_context(
         tenant=utils.generate_uuid(),
         user=utils.generate_uuid())
Beispiel #58
0
    def run(self, parsed_args):
        self.context = DesignateContext.get_admin_context(
            request_id="designate-manage")

        return super(Command, self).run(parsed_args)