Example #1
0
    def _get_dns_ips(self, member, dns_member_settings):
        member_dns_ip = None
        member_dns_ipv6 = None
        member_name = member['host_name']
        member_ip, member_ipv6 = self._get_lan1_ips(member)

        if member_name in dns_member_settings:
            dns_settings = dns_member_settings[member_name]
            # Assign IPv4 address
            if dns_settings.get('use_lan_port'):
                member_dns_ip = member_ip
            elif dns_settings.get('use_lan2_port'):
                l2 = member.get('lan2_port_setting')
                if l2 and l2.get('network_setting'):
                    member_dns_ip = l2['network_setting'].get('address')
            elif dns_settings.get('use_mgmt_port'):
                n_info = member.get('node_info')
                if n_info and n_info[0].get('mgmt_network_setting'):
                    member_dns_ip = n_info[0]['mgmt_network_setting'].get(
                        'address')
            elif dns_settings.get('additional_ip_list'):
                for ip in dns_settings.get('additional_ip_list'):
                    if utils.get_ip_version(ip) == 4:
                        member_dns_ip = ip
                        break

            # If ip is still blank fallback to member ip
            if not member_dns_ip:
                member_dns_ip = member_ip

            # Assign IPv6 address
            if dns_settings.get('use_lan_ipv6_port'):
                member_dns_ipv6 = member_ipv6
            elif dns_settings.get('use_lan2_ipv6_port'):
                l2 = member.get('lan2_port_setting')
                if l2 and l2.get('v6_network_setting'):
                    member_dns_ipv6 = l2['v6_network_setting'].get(
                        'virtual_ip')
            elif dns_settings.get('use_mgmt_ipv6_port'):
                n_info = member.get('node_info')
                if n_info and n_info[0].get('v6_mgmt_network_setting'):
                    member_dns_ipv6 = n_info[0]['v6_mgmt_network_setting'].get(
                        'virtual_ip')
            elif dns_settings.get('additional_ip_list'):
                for ip in dns_settings.get('additional_ip_list'):
                    if utils.get_ip_version(ip) == 6:
                        member_dns_ipv6 = ip
                        break

            # If ipv6 is still blank fallback to member ipv6
            if not member_dns_ipv6:
                member_dns_ipv6 = member_ipv6

        return member_dns_ip, member_dns_ipv6
Example #2
0
    def _get_dns_ips(self, member, dns_member_settings):
        member_dns_ip = None
        member_dns_ipv6 = None
        member_name = member['host_name']
        member_ip, member_ipv6 = self._get_lan1_ips(member)

        if member_name in dns_member_settings:
            dns_settings = dns_member_settings[member_name]
            # Assign IPv4 address
            if dns_settings.get('use_lan_port'):
                member_dns_ip = member_ip
            elif dns_settings.get('use_lan2_port'):
                l2 = member.get('lan2_port_setting')
                if l2 and l2.get('network_setting'):
                    member_dns_ip = l2['network_setting'].get('address')
            elif dns_settings.get('use_mgmt_port'):
                n_info = member.get('node_info')
                if n_info and n_info[0].get('mgmt_network_setting'):
                    member_dns_ip = n_info[0]['mgmt_network_setting'].get(
                        'address')
            elif dns_settings.get('additional_ip_list'):
                for ip in dns_settings.get('additional_ip_list'):
                    if utils.get_ip_version(ip) == 4:
                        member_dns_ip = ip
                        break

            # If ip is still blank fallback to member ip
            if not member_dns_ip:
                member_dns_ip = member_ip

            # Assign IPv6 address
            if dns_settings.get('use_lan_ipv6_port'):
                member_dns_ipv6 = member_ipv6
            elif dns_settings.get('use_lan2_ipv6_port'):
                l2 = member.get('lan2_port_setting')
                if l2 and l2.get('v6_network_setting'):
                    member_dns_ipv6 = l2['v6_network_setting'].get(
                        'virtual_ip')
            elif dns_settings.get('use_mgmt_ipv6_port'):
                n_info = member.get('node_info')
                if n_info and n_info[0].get('v6_mgmt_network_setting'):
                    member_dns_ipv6 = n_info[0]['v6_mgmt_network_setting'].get(
                        'virtual_ip')
            elif dns_settings.get('additional_ip_list'):
                for ip in dns_settings.get('additional_ip_list'):
                    if utils.get_ip_version(ip) == 6:
                        member_dns_ipv6 = ip
                        break

            # If ipv6 is still blank fallback to member ipv6
            if not member_dns_ipv6:
                member_dns_ipv6 = member_ipv6

        return member_dns_ip, member_dns_ipv6
Example #3
0
    def test_get_ip_version(self):
        ips = ('10.10.0.1', '8.8.8.8')
        for ip in ips:
            self.assertEqual(4, utils.get_ip_version(ip))

        ips = ('fffe::1', '2001:ff::1')
        for ip in ips:
            self.assertEqual(6, utils.get_ip_version(ip))

        # invalid addresses
        ips = ('1.0.1.555', '2001:gg:1')
        for ip in ips:
            self.assertRaises(netaddr.core.AddrFormatError,
                              utils.get_ip_version, ip)
    def test_get_ip_version(self):
        ips = ('10.10.0.1', '8.8.8.8')
        for ip in ips:
            self.assertEqual(4, utils.get_ip_version(ip))

        ips = ('fffe::1', '2001:ff::1')
        for ip in ips:
            self.assertEqual(6, utils.get_ip_version(ip))

        # invalid addresses
        ips = ('1.0.1.555', '2001:gg:1')
        for ip in ips:
            self.assertRaises(netaddr.core.AddrFormatError,
                              utils.get_ip_version,
                              ip)
Example #5
0
    def _report_sync_time(self):
        if self.grid_config.report_grid_sync_time is False:
            return

        conn = self.grid_config.gm_connector
        host_ip = getattr(conn, "host")
        if utils.get_ip_version(host_ip) == 4:
            gm = ib_objects.Member.search(conn, ipv4_address=host_ip)
        else:
            gm = ib_objects.Member.search(conn, ipv6_address=host_ip)

        sync_info = (
            str(self.grid_config.grid_id)
            + ":"
            + self.hostname
            + " => "
            + self.last_sync_time.strftime("%Y-%m-%d %H:%M:%S")
        )

        sync_info_list = gm.extattrs.get(const.EA_LAST_GRID_SYNC_TIME)
        if sync_info_list:
            # if a single entry exits. NIOS returns as string rather than list.
            if isinstance(sync_info_list, six.string_types):
                sync_info_list = [sync_info_list]

            found_sync_idx_lst = [idx for idx, si in enumerate(sync_info_list) if self.hostname in si]
            if found_sync_idx_lst:
                sync_info_list[found_sync_idx_lst[0]] = sync_info
            else:
                sync_info_list.append(sync_info)
        else:
            sync_info_list = [sync_info]

        gm.extattrs.set(const.EA_LAST_GRID_SYNC_TIME, sync_info_list)
        gm.update()
Example #6
0
    def _get_gm_info(self):
        """Get detail GM info.

        'grid_master_host' configuration accepts host IP or name of GM, so
        we need to figure whether hostname is used or ip address for either
        ipv4 or ipv6.
        """
        gm_ipv4 = None
        gm_ipv6 = None
        gm_hostname = None

        gm_host = self._grid_config.grid_master_host
        if utils.is_valid_ip(gm_host):
            ip_version = utils.get_ip_version(gm_host)
            if ip_version == 4:
                gm_ipv4 = gm_host
            else:
                gm_ipv6 = gm_host
        else:
            gm_hostname = gm_host

        return {'ipv4': gm_ipv4, 'ipv6': gm_ipv6, 'host': gm_hostname}
Example #7
0
    def _get_gm_info(self):
        """Get detail GM info.

        'grid_master_host' configuration accepts host IP or name of GM, so
        we need to figure whether hostname is used or ip address for either
        ipv4 or ipv6.
        """
        gm_ipv4 = None
        gm_ipv6 = None
        gm_hostname = None

        gm_host = self._grid_config.grid_master_host
        if utils.is_valid_ip(gm_host):
            ip_version = utils.get_ip_version(gm_host)
            if ip_version == 4:
                gm_ipv4 = gm_host
            else:
                gm_ipv6 = gm_host
        else:
            gm_hostname = gm_host

        return {'ipv4': gm_ipv4, 'ipv6': gm_ipv6, 'host': gm_hostname}
Example #8
0
def sync_neutron_to_infoblox(context, credentials, grid_manager):
    """Sync neutron objects to Infoblox grid

    Prerequisites:
        1. network views to sync must have "Cloud Adapter ID" EA set.
        2. infoblox agent sync should have been processed and updated members
           and network views.
    """
    LOG.info("Starting migration...\n")

    delete_unknown_ips = cfg.CONF.delete_unknown_ips

    grid_config = grid_manager.grid_config
    grid_id = grid_config.grid_id
    session = context.session

    neutron_api = neutron_client.Client(**credentials)
    payload = neutron_api.list_networks()
    networks = payload['networks']
    if not networks:
        LOG.info("No network exists...Exiting...")
        return

    payload = neutron_api.list_subnets()
    subnets = payload['subnets']
    if not subnets:
        LOG.info("No subnet exists...Exiting...")
        return

    payload = neutron_api.list_ports()
    ports = payload['ports']
    nova_api = nova_client.Client(NOVA_API_VERSION,
                                  session=credentials['session'])

    instance_names_by_instance_id = dict()
    instance_names_by_floating_ip = dict()
    for server in nova_api.servers.list(search_opts={'all_tenants': 1}):
        instance_names_by_instance_id[server.id] = server.name
        floating_ips = []
        for net in server.addresses:
            floating_ips += [
                ip['addr'] for ip in server.addresses[net]
                if ip['OS-EXT-IPS:type'] == 'floating'
            ]
        for fip in floating_ips:
            instance_names_by_floating_ip[fip] = server.name

    user_id = neutron_api.httpclient.get_user_id()
    user_tenant_id = neutron_api.httpclient.get_project_id()

    ib_networks = []
    should_exit = False

    # sync subnets
    for subnet in subnets:
        subnet_id = subnet['id']
        subnet_name = subnet['name']
        network_id = subnet['network_id']
        network = utils.find_one_in_list('id', network_id, networks)
        if not network:
            LOG.warning("network (%s) is not found. Skipping subnet (%s)",
                        network_id, subnet_id)
            continue

        network_name = network['name']
        ib_cxt = ib_context.InfobloxContext(context,
                                            user_id,
                                            network,
                                            subnet,
                                            grid_config,
                                            plugin=neutron_api)
        db_mapped_netview = dbi.get_network_view_by_mapping(
            session,
            grid_id=grid_id,
            network_id=network_id,
            subnet_id=subnet_id)
        if db_mapped_netview:
            LOG.info("Mapping found for network (%s), subnet (%s)",
                     network_name, subnet_name)
            if len(db_mapped_netview) > 1:
                LOG.warning("More that one db_mapped_netview returned")
            if delete_unknown_ips:
                ib_network = ib_objects.Network.search(
                    ib_cxt.connector,
                    network_view=db_mapped_netview[0].network_view,
                    cidr=subnet.get('cidr'))
                ib_networks.append(ib_network)
            continue

        ipam_controller = ipam.IpamSyncController(ib_cxt)
        dns_controller = dns.DnsController(ib_cxt)

        rollback_list = []
        try:
            ib_network = ipam_controller.create_subnet(rollback_list)
            if ib_network:
                if delete_unknown_ips:
                    ib_networks.append(ib_network)
                dns_controller.create_dns_zones(rollback_list)
            LOG.info("Created network (%s), subnet (%s)", network_name,
                     subnet_name)
        except Exception as e:
            LOG.error(_LE("Error occurred: %(error)s"), {'error': e})
            for ib_obj in reversed(rollback_list):
                try:
                    ib_obj.delete()
                except ib_exc.InfobloxException as e:
                    LOG.warning(
                        _LW("Unable to delete %(obj)s due to "
                            "error: %(error)s."), {
                                'obj': ib_obj,
                                'error': e
                            })
            should_exit = True
            break

    if should_exit:
        LOG.info("Exiting due to the error in creating subnet...")
        return

    # sync ports
    for port in ports:
        port_id = port['id']
        port_name = port['name']
        port_mac_address = port['mac_address']
        tenant_id = port.get('tenant_id') or user_tenant_id
        network_id = port['network_id']
        device_owner = port['device_owner']
        device_id = port['device_id']

        instance_name = (instance_names_by_instance_id[device_id] if device_id
                         in instance_names_by_instance_id else None)

        network = utils.find_one_in_list('id', network_id, networks)
        if not network:
            LOG.error("network (%s) not found", network_id)
            break

        for ip_set in port.get('fixed_ips'):
            subnet_id = ip_set['subnet_id']
            ip_address = ip_set['ip_address']
            LOG.info("Adding port for %s: %s...", device_owner, ip_address)

            subnet = utils.find_one_in_list('id', subnet_id, subnets)
            if not subnet:
                should_exit = True
                LOG.error("subnet (%s) not found", subnet_id)
                break

            ib_cxt = ib_context.InfobloxContext(context,
                                                user_id,
                                                network,
                                                subnet,
                                                grid_config,
                                                plugin=neutron_api)
            connector = ib_cxt.connector
            netview = ib_cxt.mapping.network_view

            search_fields = {'network_view': netview, 'ip_address': ip_address}
            obj_type = ('ipv4address' if utils.get_ip_version(ip_address) == 4
                        else 'ipv6address')
            ib_address = connector.get_object(obj_type,
                                              search_fields,
                                              return_fields=['objects'],
                                              force_proxy=True)
            if ib_address and ib_address[0]['objects']:
                LOG.info("%s is found...no need to create", ip_address)
                continue

            ipam_controller = ipam.IpamSyncController(ib_cxt)
            dns_controller = dns.DnsController(ib_cxt)

            # for a floating ip port, check for its association.
            # if associated, then port info needs to be the associated port,
            # not the floating ip port because the associated port contains
            # actual attached device info
            is_floating_ip = False
            if ip_address in instance_names_by_floating_ip:
                db_floatingip = dbi.get_floatingip_by_ip_address(
                    session, ip_address)
                db_port = dbi.get_port_by_id(session,
                                             db_floatingip.fixed_port_id)
                port_id = db_port.id
                port_name = db_port.name
                tenant_id = db_port.tenant_id
                device_id = db_port.device_id
                device_owner = db_port.device_owner
                instance_name = instance_names_by_floating_ip[ip_address]
                is_floating_ip = True

            allocated_ip = ipam_controller.allocate_specific_ip(
                ip_address, port_mac_address, port_id, tenant_id, device_id,
                device_owner)
            if allocated_ip and device_owner:
                try:
                    dns_controller.bind_names(allocated_ip, instance_name,
                                              port_id, tenant_id, device_id,
                                              device_owner, is_floating_ip,
                                              port_name)
                except Exception as e:
                    should_exit = True
                    LOG.error("Unable to allocate ip (%s): %s", ip_address, e)
                    ipam_controller.deallocate_ip(allocated_ip)
                    break

            LOG.info("Allocated %s", ip_address)

        if should_exit:
            LOG.info("Existing due to error in port creation...")
            break

    if delete_unknown_ips:
        LOG.info("Start deleting unknown Fixed IP's from Infoblox...")
        for ib_network in ib_networks:

            nw_ea = ib_network.extattrs
            # Skip network if it doesn't have EA or if EA indicates it's
            # shared or external.
            if (not nw_ea or nw_ea.get('Is External')
                    or nw_ea.get('Is Shared')):
                continue

            LOG.info("Searching for Fixed IP: network_view='%s', cidr='%s'" %
                     (ib_network.network_view, ib_network.network))
            fixed_ips = ib_objects.FixedAddress.search_all(
                ib_cxt.connector,
                network_view=ib_network.network_view,
                network=ib_network.network)

            if not fixed_ips:
                LOG.info("No FixedIP found: network_view='%s', cidr='%s'" %
                         (ib_network.network_view, ib_network.network))
                continue

            for fixed_ip in fixed_ips:
                ea = fixed_ip.extattrs
                port_id = None
                if ea:
                    port_id = ea.get('Port ID')

                # Delete Fixed IP if:
                #   - Fixed IP does not have 'Port ID' EA, or
                #   - No port_id in neutron matches 'Port ID' EA value
                if not (port_id
                        and utils.find_one_in_list('id', port_id, ports)):
                    LOG.info("Deleting Fixed IP from Infoblox: '%s'" %
                             fixed_ip)
                    fixed_ip.delete()

    LOG.info("Ending migration...")
def sync_neutron_to_infoblox(context, credentials, grid_manager):
    """Sync neutron objects to Infoblox grid

    Prerequisites:
        1. network views to sync must have "Cloud Adapter ID" EA set.
        2. infoblox agent sync should have been processed and updated members
           and network views.
    """
    LOG.info("Starting migration...\n")

    delete_unknown_ips = cfg.CONF.delete_unknown_ips

    grid_config = grid_manager.grid_config
    grid_id = grid_config.grid_id
    session = context.session

    neutron_api = neutron_client.Client(**credentials)
    payload = neutron_api.list_networks()
    networks = payload['networks']
    if not networks:
        LOG.info("No network exists...Exiting...")
        return

    payload = neutron_api.list_subnets()
    subnets = payload['subnets']
    if not subnets:
        LOG.info("No subnet exists...Exiting...")
        return

    payload = neutron_api.list_ports()
    ports = payload['ports']
    nova_api = nova_client.Client(NOVA_API_VERSION,
                                  session=credentials['session'])

    instance_names_by_instance_id = dict()
    instance_names_by_floating_ip = dict()
    for server in nova_api.servers.list(search_opts={'all_tenants': 1}):
        instance_names_by_instance_id[server.id] = server.name
        floating_ips = []
        for net in server.addresses:
            floating_ips += [ip['addr'] for ip in server.addresses[net]
                             if ip['OS-EXT-IPS:type'] == 'floating']
        for fip in floating_ips:
            instance_names_by_floating_ip[fip] = server.name

    user_id = neutron_api.httpclient.get_user_id()
    user_tenant_id = neutron_api.httpclient.get_project_id()

    ib_networks = []
    should_exit = False

    # sync subnets
    for subnet in subnets:
        subnet_id = subnet['id']
        subnet_name = subnet['name']
        network_id = subnet['network_id']
        network = utils.find_one_in_list('id', network_id, networks)
        if not network:
            LOG.warning("network (%s) is not found. Skipping subnet (%s)",
                        network_id, subnet_id)
            continue

        network_name = network['name']
        ib_cxt = ib_context.InfobloxContext(context, user_id,
                                            network, subnet,
                                            grid_config,
                                            plugin=neutron_api)
        db_mapped_netview = dbi.get_network_view_by_mapping(
            session,
            grid_id=grid_id,
            network_id=network_id,
            subnet_id=subnet_id)
        if db_mapped_netview:
            LOG.info("Mapping found for network (%s), subnet (%s)",
                     network_name, subnet_name)
            if len(db_mapped_netview) > 1:
                LOG.warning("More that one db_mapped_netview returned")
            if delete_unknown_ips:
                ib_network = ib_objects.Network.search(
                    ib_cxt.connector,
                    network_view=db_mapped_netview[0].network_view,
                    cidr=subnet.get('cidr'))
                ib_networks.append(ib_network)
            continue

        ipam_controller = ipam.IpamSyncController(ib_cxt)
        dns_controller = dns.DnsController(ib_cxt)

        rollback_list = []
        try:
            ib_network = ipam_controller.create_subnet(rollback_list)
            if ib_network:
                if delete_unknown_ips:
                    ib_networks.append(ib_network)
                dns_controller.create_dns_zones(rollback_list)
            LOG.info("Created network (%s), subnet (%s)",
                     network_name, subnet_name)
        except Exception as e:
            LOG.error(_LE("Error occurred: %(error)s"), {'error': e})
            for ib_obj in reversed(rollback_list):
                try:
                    ib_obj.delete()
                except ib_exc.InfobloxException as e:
                    LOG.warning(_LW("Unable to delete %(obj)s due to "
                                    "error: %(error)s."),
                                {'obj': ib_obj, 'error': e})
            should_exit = True
            break

    if should_exit:
        LOG.info("Exiting due to the error in creating subnet...")
        return

    # sync ports
    for port in ports:
        port_id = port['id']
        port_name = port['name']
        port_mac_address = port['mac_address']
        tenant_id = port.get('tenant_id') or user_tenant_id
        network_id = port['network_id']
        device_owner = port['device_owner']
        device_id = port['device_id']

        instance_name = (instance_names_by_instance_id[device_id]
                         if device_id in instance_names_by_instance_id
                         else None)

        network = utils.find_one_in_list('id', network_id, networks)
        if not network:
            LOG.error("network (%s) not found", network_id)
            break

        for ip_set in port.get('fixed_ips'):
            subnet_id = ip_set['subnet_id']
            ip_address = ip_set['ip_address']
            LOG.info("Adding port for %s: %s...", device_owner, ip_address)

            subnet = utils.find_one_in_list('id', subnet_id, subnets)
            if not subnet:
                should_exit = True
                LOG.error("subnet (%s) not found", subnet_id)
                break

            ib_cxt = ib_context.InfobloxContext(context, user_id,
                                                network, subnet,
                                                grid_config,
                                                plugin=neutron_api)
            connector = ib_cxt.connector
            netview = ib_cxt.mapping.network_view

            search_fields = {
                'network_view': netview,
                'ip_address': ip_address
            }
            obj_type = ('ipv4address'if utils.get_ip_version(ip_address) == 4
                        else 'ipv6address')
            ib_address = connector.get_object(obj_type,
                                              search_fields,
                                              return_fields=['objects'],
                                              force_proxy=True)
            if ib_address and ib_address[0]['objects']:
                LOG.info("%s is found...no need to create", ip_address)
                continue

            ipam_controller = ipam.IpamSyncController(ib_cxt)
            dns_controller = dns.DnsController(ib_cxt)

            # for a floating ip port, check for its association.
            # if associated, then port info needs to be the associated port,
            # not the floating ip port because the associated port contains
            # actual attached device info
            is_floating_ip = False
            if ip_address in instance_names_by_floating_ip:
                db_floatingip = dbi.get_floatingip_by_ip_address(session,
                                                                 ip_address)
                db_port = dbi.get_port_by_id(session,
                                             db_floatingip.fixed_port_id)
                port_id = db_port.id
                port_name = db_port.name
                tenant_id = db_port.tenant_id
                device_id = db_port.device_id
                device_owner = db_port.device_owner
                instance_name = instance_names_by_floating_ip[ip_address]
                is_floating_ip = True

            allocated_ip = ipam_controller.allocate_specific_ip(
                ip_address,
                port_mac_address,
                port_id,
                tenant_id,
                device_id,
                device_owner)
            if allocated_ip and device_owner:
                try:
                    dns_controller.bind_names(
                        allocated_ip,
                        instance_name,
                        port_id,
                        tenant_id,
                        device_id,
                        device_owner,
                        is_floating_ip,
                        port_name)
                except Exception as e:
                    should_exit = True
                    LOG.error("Unable to allocate ip (%s): %s", ip_address, e)
                    ipam_controller.deallocate_ip(allocated_ip)
                    break

            LOG.info("Allocated %s", ip_address)

        if should_exit:
            LOG.info("Existing due to error in port creation...")
            break

    if delete_unknown_ips:
        LOG.info("Start deleting unknown Fixed IP's from Infoblox...")
        for ib_network in ib_networks:

            nw_ea = ib_network.extattrs
            # Skip network if it doesn't have EA or if EA indicates it's
            # shared or external.
            if (not nw_ea or
                    nw_ea.get('Is External') or nw_ea.get('Is Shared')):
                continue

            LOG.info("Searching for Fixed IP: network_view='%s', cidr='%s'" %
                     (ib_network.network_view, ib_network.network))
            fixed_ips = ib_objects.FixedAddress.search_all(
                ib_cxt.connector,
                network_view=ib_network.network_view,
                network=ib_network.network)

            if not fixed_ips:
                LOG.info("No FixedIP found: network_view='%s', cidr='%s'" %
                         (ib_network.network_view, ib_network.network))
                continue

            for fixed_ip in fixed_ips:
                ea = fixed_ip.extattrs
                port_id = None
                if ea:
                    port_id = ea.get('Port ID')

                # Delete Fixed IP if:
                #   - Fixed IP does not have 'Port ID' EA, or
                #   - No port_id in neutron matches 'Port ID' EA value
                if not (port_id and
                        utils.find_one_in_list('id', port_id, ports)):
                    LOG.info("Deleting Fixed IP from Infoblox: '%s'" %
                             fixed_ip)
                    fixed_ip.delete()

    LOG.info("Ending migration...")