Beispiel #1
0
    def _delete(self, zone_id, resource_id=None, resource_type='instance',
                criterion=None):
        """
        Handle a generic delete of a fixed ip within a zone

        :param zone_id: The ID of the designate zone.
        :param resource_id: The managed resource ID
        :param resource_type: The managed resource type
        :param criterion: Criterion to search and destroy records
        """
        criterion = criterion or {}

        context = DesignateContext().elevated()
        context.all_tenants = True
        context.edit_managed_records = True

        criterion.update({
            'zone_id': zone_id,
            'managed': True,
            '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,
                                           zone_id,
                                           record['recordset_id'],
                                           record['id'])
Beispiel #2
0
    def _delete(self, zone_id, resource_id=None, resource_type='instance',
                criterion=None):
        """
        Handle a generic delete of a fixed ip within a zone

        :param zone_id: The ID of the designate zone.
        :param resource_id: The managed resource ID
        :param resource_type: The managed resource type
        :param criterion: Criterion to search and destroy records
        """
        criterion = criterion or {}

        context = DesignateContext().elevated()
        context.all_tenants = True
        context.edit_managed_records = True

        criterion.update({
            'zone_id': zone_id,
            'managed': True,
            '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,
                                           zone_id,
                                           record['recordset_id'],
                                           record['id'])
Beispiel #3
0
    def _delete_proxy_dns_record(self, proxyzone):
        if not proxyzone.endswith('.'):
            proxyzone += '.'
        context = DesignateContext().elevated()
        context.all_tenants = True
        context.edit_managed_records = True

        parentzone = '.'.join(proxyzone.split('.')[1:])
        crit = {'name': parentzone}

        zonerecords = central_api.find_zones(context, crit)
        if len(zonerecords) != 1:
            LOG.warning("Unable to clean up this DNS proxy record. "
                        "Looked for zone %s and found %s" %
                        (parentzone, zonerecords))
            return

        crit = {'zone_id': zonerecords[0].id, 'name': proxyzone}
        recordsets = central_api.find_recordsets(context, crit)
        if len(recordsets) != 1:
            LOG.warning("Unable to clean up this DNS proxy record. "
                        "Looked for recordsets for %s and found %s" (
                            proxyzone, recordsets))
            return

        LOG.warning("Deleting DNS entry for proxy: %s" % recordsets[0])
        central_api.delete_recordset(context, zonerecords[0].id,
                                     recordsets[0].id)
Beispiel #4
0
    def process_notification(self, context, event_type, payload):
        # Do something with the notification.. e.g:
        zone_id = cfg.CONF[self.name].zone_id
        zone_name = cfg.CONF[self.name].zone_name

        record_name = '%s.%s' % (payload['instance_id'], zone_name)

        context = DesignateContext().elevated()
        context.all_tenants = True
        # context.edit_managed_records = True

        for fixed_ip in payload['fixed_ips']:
            recordset_values = {
                'zone_id': zone_id,
                'name': record_name,
                'type': 'A' if fixed_ip['version'] == 4 else 'AAAA'
            }

            record_values = {
                'data': fixed_ip['address'],
            }

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

            self.central_api.create_record(context, zone_id, recordset['id'],
                                           Record(**record_values))
Beispiel #5
0
    def _delete_proxy_dns_record(self, proxydomain):
        if not proxydomain.endswith('.'):
            proxydomain += '.'
        context = DesignateContext().elevated()
        context.all_tenants = True
        context.edit_managed_records = True

        parentdomain = '.'.join(proxydomain.split('.')[1:])
        crit = {'name': parentdomain}

        domainrecords = central_api.find_domains(context, crit)
        if len(domainrecords) != 1:
            LOG.warning("Unable to clean up this DNS proxy record. "
                        "Looked for domain %s and found %s" %
                        (parentdomain, domainrecords))
            return

        crit = {'domain_id': domainrecords[0].id, 'name': proxydomain}
        recordsets = central_api.find_recordsets(context, crit)
        if len(recordsets) != 1:
            LOG.warning("Unable to clean up this DNS proxy record. "
                        "Looked for recordsets for %s and found %s" (
                            proxydomain, recordsets))
            return

        LOG.warning("Deleting DNS entry for proxy: %s" % recordsets[0])
        central_api.delete_recordset(context, domainrecords[0].id,
                                     recordsets[0].id)
Beispiel #6
0
    def process_notification(self, context, event_type, payload):
        # Do something with the notification.. e.g:
        zone_id = cfg.CONF[self.name].zone_id
        zone_name = cfg.CONF[self.name].zone_name

        record_name = '%s.%s' % (payload['instance_id'], zone_name)

        context = DesignateContext().elevated()
        context.all_tenants = True
        # context.edit_managed_records = True

        for fixed_ip in payload['fixed_ips']:
            recordset_values = {
                'zone_id': zone_id,
                'name': record_name,
                'type': 'A' if fixed_ip['version'] == 4 else 'AAAA'
            }

            record_values = {
                'data': fixed_ip['address'],
            }

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

            self.central_api.create_record(context, zone_id, recordset['id'],
                                           Record(**record_values))
Beispiel #7
0
    def _create(self, addresses, extra, zone_id, 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
        """
        if not managed:
            LOG.warning(
                _LW(
                    "Deprecation notice: Unmanaged designate-sink records are "
                    "being deprecated please update the call "
                    "to remove managed=False"
                )
            )
        LOG.debug("Using Zone ID: %s", zone_id)
        zone = self.get_zone(zone_id)
        LOG.debug("Domain: %r", zone)

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

        context = DesignateContext().elevated()
        context.all_tenants = True
        context.edit_managed_records = True

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

            for fmt in cfg.CONF[self.name].get("format"):
                recordset_values = {
                    "zone_id": zone["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.debug("Creating record in %s / %s with values %r", zone["id"], recordset["id"], record_values)
                self.central_api.create_record(context, zone["id"], recordset["id"], Record(**record_values))
Beispiel #8
0
    def _create(self, addresses, extra, zone_id, 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
        """
        if not managed:
            LOG.warning(_LW(
                'Deprecation notice: Unmanaged designate-sink records are '
                'being deprecated please update the call '
                'to remove managed=False'))
        LOG.debug('Using Zone ID: %s' % zone_id)
        zone = self.get_zone(zone_id)
        LOG.debug('Zone: %r' % zone)

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

        context = DesignateContext().elevated()
        context.all_tenants = True
        context.edit_managed_records = True

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

            for fmt in cfg.CONF[self.name].get('format'):
                recordset_values = {
                    'zone_id': zone['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.debug('Creating record in %s / %s with values %r' %
                          (zone['id'], recordset['id'], record_values))
                self.central_api.create_record(context,
                                               zone['id'],
                                               recordset['id'],
                                               Record(**record_values))
Beispiel #9
0
    def _create(self, addresses, extra, zone_id, 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 zone_id: The ID of the designate zone.
        :param resource_type: The managed resource type
        :param resource_id: The managed resource ID
        """
        LOG.debug('Using Zone ID: %s', zone_id)
        zone = self.get_zone(zone_id)
        LOG.debug('Domain: %r', zone)

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

        context = DesignateContext().elevated()
        context.all_tenants = True
        context.edit_managed_records = True

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

            if addr['version'] == 4:
                format = self._get_formatv4()
            else:
                format = self._get_formatv6()

            for fmt in format:
                recordset_values = {
                    'zone_id': zone['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'],
                    'managed': True,
                    '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',
                          zone['id'], recordset['id'], record_values)
                self.central_api.create_record(context,
                                               zone['id'],
                                               recordset['id'],
                                               Record(**record_values))
Beispiel #10
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().elevated()
        context.all_tenants = True
        context.edit_managed_records = True

        forward_crit = criterion.copy()
        forward_crit['domain_id'] = cfg.CONF[self.name].domain_id

        if managed:
            forward_crit.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, forward_crit)

        for record in records:
            LOG.warn('Deleting forward record %s in recordset %s' % (record['id'],
                                                                     record['recordset_id']))

            central_api.delete_record(context, cfg.CONF[self.name].domain_id,
                                      record['recordset_id'], record['id'])

        reverse_domain_id = cfg.CONF[self.name].get('reverse_domain_id')
        if reverse_domain_id:
            reverse_crit = criterion.copy()
            reverse_crit.update({'domain_id': reverse_domain_id})

            if managed:
                reverse_crit.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, reverse_crit)

            for record in records:
                LOG.warn('Deleting reverse record %s in recordset %s' % (record['id'],
                                                                         record['recordset_id']))

                central_api.delete_record(context,
                                          reverse_domain_id,
                                          record['recordset_id'], record['id'])
Beispiel #11
0
    def _create(self, addresses, extra, zone_id, 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 zone_id: The ID of the designate zone.
        :param resource_type: The managed resource type
        :param resource_id: The managed resource ID
        """
        LOG.debug('Using Zone ID: %s', zone_id)
        zone = self.get_zone(zone_id)
        LOG.debug('Domain: %r', zone)

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

        context = DesignateContext().elevated()
        context.all_tenants = True
        context.edit_managed_records = True

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

            if addr['version'] == 4:
                format = self._get_formatv4()
            else:
                format = self._get_formatv6()

            for fmt in format:
                recordset_values = {
                    'zone_id': zone['id'],
                    'name': fmt % event_data,
                    'type': 'A' if addr['version'] == 4 else 'AAAA'}

                record_values = {
                    'data': addr['address'],
                    'managed': True,
                    'managed_plugin_name': self.get_plugin_name(),
                    'managed_plugin_type': self.get_plugin_type(),
                    'managed_resource_type': resource_type,
                    'managed_resource_id': resource_id
                }
                self._create_or_update_recordset(
                    context, [Record(**record_values)], **recordset_values
                )
Beispiel #12
0
    def process_notification(self, context, event_type, payload):
        LOG.debug('FilteredHandler received notification - %s', event_type)
        context = DesignateContext().elevated()
        context.all_tenants = True

        zone_id = cfg.CONF[self.name].zone_id
        zone_name = cfg.CONF[self.name].zone_name
        LOG.debug('FilteredHandler zone_id - %s', zone_id)
        LOG.debug('FilteredHandler zone_name - %s', zone_name)
        if event_type == 'compute.instance.create.end':
            valid_address = lambda x: IP(x) in IP(cfg.CONF[self.name].address_filter)
            payload['project'] = getattr(context, 'tenant', None)
            record_name = '%s.%s' % (payload['host'], zone_name)
            LOG.debug('FilteredHandler record_name - %s', record_name)
            filtered_addresses = []
            for address in payload['fixed_ips']:
                if valid_address(address['address']):
                    filtered_addresses.append(address)

            if filtered_addresses:
                LOG.debug('FilteredHandler Before Filtered %d', len(payload['fixed_ips']))
                LOG.debug('FilteredHandler After Filtered %d', len(filtered_addresses))
                for address in filtered_addresses:
                    recordset_values = {
                        'zone_id': zone_id,
                        'name': record_name,
                        'type': 'A' if address['version'] == 4 else 'AAAA'
                    }
                    record_values = {
                        'data': address['address'], 
                    }
                    LOG.debug('FilteredHandler:recordset_values:zone_id:', recordset_values['zone_id'])
                    LOG.debug('FilteredHandler:recordset_values:record_name:', recordset_values['name'])
                    LOG.debug('FilteredHandler:recordset_values:type:', recordset_values['type'])
                    LOG.debug('FilteredHandler:record_values:data:', record_values['data'])
                    recordset = self._find_or_create_recordset(context, **recordset_values)

                    LOG.debug('FilteredHandler:recordset:id:', recordset['id'])
                    self.central_api.create_record(context, zone_id, recordset['id'], Record(**record_values))
            else:
                LOG.debug('FilteredHandler No Results after filtering for %s', self.address_filter)

        elif event_type == 'compute.instance.delete.start':
            self._delete(zone_id=zone_id,
                         resource_id=payload['instance_id'],
                         resource_type='instance')
Beispiel #13
0
    def _delete(self,
                zone_id,
                managed=True,
                resource_id=None,
                resource_type='instance',
                criterion=None):
        """
        Handle a generic delete of a fixed ip within a zone

        :param zone_id: The ID of the designate zone.
        :param managed: Is it a managed resource
        :param resource_id: The managed resource ID
        :param resource_type: The managed resource type
        :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().elevated()
        context.all_tenants = True
        context.edit_managed_records = True

        criterion.update({'zone_id': zone_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, zone_id,
                                           record['recordset_id'],
                                           record['id'])
Beispiel #14
0
    def _delete(self, zone_id, managed=True, resource_id=None,
                resource_type='instance', criterion=None):
        """
        Handle a generic delete of a fixed ip within a zone

        :param zone_id: The ID of the designate zone.
        :param managed: Is it a managed resource
        :param resource_id: The managed resource ID
        :param resource_type: The managed resource type
        :param criterion: Criterion to search and destroy records
        """
        if not managed:
            LOG.warning(
                'Deprecation notice: Unmanaged designate-sink records are '
                'being deprecated please update the call '
                'to remove managed=False')
        criterion = criterion or {}

        context = DesignateContext().elevated()
        context.all_tenants = True
        context.edit_managed_records = True

        criterion.update({'zone_id': zone_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,
                                           zone_id,
                                           record['recordset_id'],
                                           record['id'])
Beispiel #15
0
    def _delete(self, zone_id, managed=True, resource_id=None, resource_type="instance", criterion=None):
        """
        Handle a generic delete of a fixed ip within a zone

        :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().elevated()
        context.all_tenants = True
        context.edit_managed_records = True

        criterion.update({"zone_id": zone_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, zone_id, record["recordset_id"], record["id"])
Beispiel #16
0
    def _create(self, addresses, extra, zone_id, 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 zone_id: The ID of the designate zone.
        :param managed: Is it a managed resource
        :param resource_type: The managed resource type
        :param resource_id: The managed resource ID
        """
        if not managed:
            LOG.warning(_LW(
                'Deprecation notice: Unmanaged designate-sink records are '
                'being deprecated please update the call '
                'to remove managed=False'))
        LOG.debug('Using Zone ID: %s', zone_id)
        zone = self.get_zone(zone_id)
        LOG.debug('Domain: %r', zone)

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

        context = DesignateContext().elevated()
        context.all_tenants = True
        context.edit_managed_records = True

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

            if addr['version'] == 4:
                format = self._get_formatv4()
            else:
                format = self._get_formatv6()

            for fmt in format:
                recordset_values = {
                    'zone_id': zone['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.debug('Creating record in %s / %s with values %r',
                          zone['id'], recordset['id'], record_values)
                self.central_api.create_record(context,
                                               zone['id'],
                                               recordset['id'],
                                               Record(**record_values))
Beispiel #17
0
    def _delete(self,
                extra,
                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
        """

        domain = self.get_domain(cfg.CONF[self.name].domain_id)

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

        data['project_name'] = data['tenant_id']

        event_data = data.copy()

        # Clean salt and puppet keys for deleted instance
        if (cfg.CONF[self.name].puppet_key_format
                and cfg.CONF[self.name].puppet_master_host):
            puppetkey = cfg.CONF[self.name].puppet_key_format % event_data
            puppetkey = puppetkey.rstrip('.').encode('utf8')
            LOG.debug('Cleaning puppet key %s' % puppetkey)
            self._run_remote_command(
                cfg.CONF[self.name].puppet_master_host,
                cfg.CONF[self.name].certmanager_user,
                'sudo puppet cert clean %s' % pipes.quote(puppetkey))

        if (cfg.CONF[self.name].salt_key_format
                and cfg.CONF[self.name].salt_master_host):
            saltkey = cfg.CONF[self.name].salt_key_format % event_data
            saltkey = saltkey.rstrip('.').encode('utf8')
            LOG.debug('Cleaning salt key %s' % saltkey)
            self._run_remote_command(
                cfg.CONF[self.name].salt_master_host,
                cfg.CONF[self.name].certmanager_user,
                'sudo salt-key -y -d  %s' % pipes.quote(saltkey))

        # Finally, delete any proxy records pointing to this instance.
        #
        # For that, we need the IP which we can dig out of the old DNS record.
        crit = criterion.copy()

        # Make sure we only look at forward records
        crit['domain_id'] = cfg.CONF[self.name].domain_id

        if managed:
            crit.update({
                'managed': managed,
                'managed_resource_id': resource_id,
                'managed_resource_type': resource_type
            })

        context = DesignateContext().elevated()
        context.all_tenants = True
        context.edit_managed_records = True

        records = central_api.find_records(context, crit)

        # We only care about the IP, and that's the same in both records.
        ip = records[0].data
        LOG.debug("Cleaning up proxy records for IP %s" % ip)
        self._delete_proxies_for_ip(data['project_name'], ip)
    def process_notification(self, context, event_type, payload):
        """Process floating IP notifications from Neutron"""

        LOG.info('%s received notification - %s' %
                 (self.get_canonical_name(), event_type))

        # We need a context that will allow us to manipulate records that are
        # flagged as managed, so we can't use the context that was provided
        # with the notification.
        elevated_context = DesignateContext(tenant=context['tenant']).elevated()
        elevated_context.all_tenants = True
        elevated_context.edit_managed_records = True

        # Create an object from the original context so we can use it with the
        # RPC API calls.  We want this limited to the single tenant so we can
        # use it to find their domains.
        orig_context = DesignateContext(tenant=context['tenant']).elevated()

        # When an instance is deleted, we never get a floating IP update event,
        # we just get notified that the underlying port was deleted.  In that
        # case look for it under the other key.
        if event_type.startswith('port.delete'):
            self._disassociate_port_id(context=elevated_context,
                                       port_id=payload['port_id'])

        if event_type.startswith('floatingip.'):
            # A floating IP can only be associated with a single instance at a
            # time, so the first thing we always do is remove any existing
            # association when we get an update.  This is always safe whether
            # or not we're deleting it or reassigning it.
            if 'floatingip' in payload:
                # floatingip.update.end
                floating_ip = payload['floatingip']['floating_ip_address']
                floating_ip_id = payload['floatingip']['id']
            elif 'floatingip_id' in payload:
                # floatingip.delete.end
                floating_ip = None
                floating_ip_id = payload['floatingip_id']

            self._disassociate_floating_ip(context=elevated_context,
                                           floating_ip_id=floating_ip_id,
                                           )

        # If it turns out that the event is an update and it has a fixed ip in
        # the update, then we create the new record.
        if event_type.startswith('floatingip.update'):
            if payload['floatingip']['fixed_ip_address']:
                domain = self._pick_tenant_domain(orig_context,
                                                  default_regex=cfg.CONF[self.name].default_regex,
                                                  require_default_regex=cfg.CONF[self.name].require_default_regex,
                                                  )
                if domain is None:
                    LOG.info('No domains found for tenant %s(%s), ignoring Floating IP update for %s' %
                             (context['tenant_name'], context['tenant_id'], floating_ip))
                else:
                    LOG.debug('Using domain %s(%s) for tenant %s(%s)' %
                              (domain.name, domain.id,
                               context['tenant_name'], context['tenant_id']))

                    kc = keystone_c.Client(token=context['auth_token'],
                                           tenant_id=context['tenant_id'],
                                           region_name=cfg.CONF[self.name].region_name,
                                           auth_url=cfg.CONF[self.name].keystone_auth_uri)

                    port_id = payload['floatingip']['port_id']
                    instance_info = self._get_instance_info(kc, port_id)

                    extra = payload.copy()
                    extra.update({'instance_name': instance_info['name'],
                                  'instance_short_name': instance_info['name'].partition('.')[0],
                                  'domain': domain.name})
                    self._associate_floating_ip(context=elevated_context,
                                                domain_id=domain.id,
                                                extra=extra,
                                                floating_ip_id=floating_ip_id,
                                                floating_ip=floating_ip,
                                                port_id=port_id)
    def process_notification(self, context, event_type, payload):
        """Process floating IP notifications from Neutron"""

        LOG.info('%s received notification - %s' %
                 (self.get_canonical_name(), event_type))

        # We need a context that will allow us to manipulate records that are
        # flagged as managed, so we can't use the context that was provided
        # with the notification.
        elevated_context = DesignateContext(tenant=context['tenant']).elevated()
        elevated_context.all_tenants = True
        elevated_context.edit_managed_records = True

        # Create an object from the original context so we can use it with the
        # RPC API calls.  We want this limited to the single tenant so we can
        # use it to find their domains.
        orig_context = DesignateContext(tenant=context['tenant']).elevated()

        # When an instance is deleted, we never get a floating IP update event,
        # we just get notified that the underlying port was deleted.  In that
        # case look for it under the other key.
        if event_type.startswith('port.delete'):
            self._disassociate_port_id(context=elevated_context,
                                       port_id=payload['port_id'])

        if event_type.startswith('floatingip.'):
            # A floating IP can only be associated with a single instance at a
            # time, so the first thing we always do is remove any existing
            # association when we get an update.  This is always safe whether
            # or not we're deleting it or reassigning it.
            if 'floatingip' in payload:
                # floatingip.update.end
                floating_ip = payload['floatingip']['floating_ip_address']
                floating_ip_id = payload['floatingip']['id']
            elif 'floatingip_id' in payload:
                # floatingip.delete.end
                floating_ip = None
                floating_ip_id = payload['floatingip_id']

            self._disassociate_floating_ip(context=elevated_context,
                                           floating_ip_id=floating_ip_id,
                                           )

        # If it turns out that the event is an update and it has a fixed ip in
        # the update, then we create the new record.
        if event_type.startswith('floatingip.update'):
            if payload['floatingip']['fixed_ip_address']:
                domain = self._pick_tenant_domain(orig_context,
                                                  default_regex=cfg.CONF[self.name].default_regex,
                                                  require_default_regex=cfg.CONF[self.name].require_default_regex,
                                                  )
                if domain is None:
                    LOG.info('No domains found for tenant %s(%s), ignoring Floating IP update for %s' %
                             (context['tenant_name'], context['tenant_id'], floating_ip))
                else:
                    LOG.debug('Using domain %s(%s) for tenant %s(%s)' %
                              (domain.name, domain.id,
                               context['tenant_name'], context['tenant_id']))

                    kc = keystone_c.Client(token=context['auth_token'],
                                           tenant_id=context['tenant_id'],
                                           region_name=cfg.CONF[self.name].region_name,
                                           auth_url=cfg.CONF[self.name].keystone_auth_uri)

                    port_id = payload['floatingip']['port_id']
                    instance_info = self._get_instance_info(kc, port_id)

                    extra = payload.copy()
                    extra.update({'instance_name': instance_info['name'],
                                  'instance_short_name': instance_info['name'].partition('.')[0],
                                  'domain': domain.name})
                    self._associate_floating_ip(context=elevated_context,
                                                domain_id=domain.id,
                                                extra=extra,
                                                floating_ip_id=floating_ip_id,
                                                floating_ip=floating_ip,
                                                port_id=port_id)
Beispiel #20
0
    def _delete(self,
                extra,
                managed=True,
                resource_id=None,
                resource_type='instance',
                criterion={}):
        """
        Handle a generic delete of a fixed ip within a zone

        :param criterion: Criterion to search and destroy records
        """

        zone = self.get_zone(cfg.CONF[self.name].domain_id)

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

        data['project_name'] = data['tenant_id']

        event_data = data.copy()

        fqdn = cfg.CONF[self.name].fqdn_format % event_data
        fqdn = fqdn.rstrip('.')

        keystone = keystone_client.Client(session=self._get_keystone_session(),
                                          interface='public',
                                          connect_retries=5)
        region_recs = keystone.regions.list()
        regions = [region.id for region in region_recs]
        if len(regions) > 1:
            # We need to make sure this VM doesn't exist in another region.  If it does
            #  then we don't want to purge anything because we'll break that one.
            for region in regions:
                if region == cfg.CONF[self.name].region:
                    continue
                nova = novaclient.Client('2',
                                         session=self._get_keystone_session(
                                             data['tenant_id']),
                                         region_name=region)
                servers = nova.servers.list()
                servernames = [server.name for server in servers]
                if event_data['hostname'] in servernames:
                    LOG.warning(
                        "Skipping cleanup of %s because it is also present in region %s"
                        % (fqdn, region))
                    return

        # Clean puppet keys for deleted instance
        if cfg.CONF[self.name].puppet_master_host:
            LOG.debug('Cleaning puppet key %s' % fqdn)
            self._run_remote_command(
                cfg.CONF[self.name].puppet_master_host,
                cfg.CONF[self.name].certmanager_user,
                'sudo puppet cert clean %s' % pipes.quote(fqdn))

        # Clean up the puppet config for this instance, if there is one
        self._delete_puppet_config(data['tenant_id'], fqdn)
        self._delete_puppet_git_config(data['tenant_id'], fqdn)

        # For good measure, look around for things associated with the old domain as well
        if cfg.CONF[self.name].legacy_domain_id:
            legacy_zone = self.get_zone(cfg.CONF[self.name].legacy_domain_id)
            legacy_data = data.copy()
            legacy_data['zone'] = legacy_zone['name']
            legacy_fqdn = cfg.CONF[self.name].fqdn_format % legacy_data
            legacy_fqdn = legacy_fqdn.rstrip('.')
            if cfg.CONF[self.name].puppet_master_host:
                LOG.debug('Cleaning puppet key %s' % legacy_fqdn)
                self._run_remote_command(
                    cfg.CONF[self.name].puppet_master_host,
                    cfg.CONF[self.name].certmanager_user,
                    'sudo puppet cert clean %s' % pipes.quote(legacy_fqdn))

            # Clean up the puppet config for this instance, if there is one
            self._delete_puppet_config(legacy_data['tenant_id'], legacy_fqdn)
            self._delete_puppet_git_config(legacy_data['tenant_id'],
                                           legacy_fqdn)

        # Finally, delete any proxy records pointing to this instance.
        #
        # For that, we need the IP which we can dig out of the old DNS record.
        crit = criterion.copy()

        # Make sure we only look at forward records
        crit['zone_id'] = cfg.CONF[self.name].domain_id

        if managed:
            crit.update({
                'managed': managed,
                'managed_resource_id': resource_id,
                'managed_resource_type': resource_type
            })

        context = DesignateContext().elevated()
        context.all_tenants = True
        context.edit_managed_records = True

        records = central_api.find_records(context, crit)

        # We only care about the IP, and that's the same in both records.
        ip = records[0].data
        LOG.debug("Cleaning up proxy records for IP %s" % ip)
        try:
            self._delete_proxies_for_ip(data['project_name'], ip)
        except requests.exceptions.ConnectionError:
            LOG.warning("Caught exception when deleting proxy records",
                        exc_info=True)