def _get_pod_subnet(self, pod, ip):
     project_id = self._drv_pod_project.get_project(pod)
     subnets_map = self._drv_pod_subnets.get_subnets(pod, project_id)
     subnet_ids = [subnet_id for subnet_id, network in subnets_map.items()
                   for subnet in network.subnets.objects
                   if ip in subnet.cidr]
     if subnet_ids:
         return subnet_ids[0]
     else:
         # NOTE(ltomasbo): We are assuming that if IP is not on the
         # pod subnet it's because the member is using hostNetworking. In
         # this case we look for the IP in worker_nodes_subnets.
         subnet = utils.get_subnet_by_ip(self._get_nodes_subnets(), ip)
         if subnet:
             return subnet[0]
         else:
             # This shouldn't ever happen but let's return just the first
             # worker_nodes_subnet id.
             return self._get_nodes_subnets()[0][0]
示例#2
0
 def _get_subnet_by_octavia_mode(self, target_pod, target_ip, lb_crd):
     # TODO(apuimedo): Do not pass subnet_id at all when in
     # L3 mode once old neutron-lbaasv2 is not supported, as
     # octavia does not require it
     subnet_id = None
     if (CONF.octavia_defaults.member_mode == k_const.OCTAVIA_L2_MEMBER_MODE
         ):
         if target_pod:
             subnet_id = self._get_pod_subnet(target_pod, target_ip)
         else:
             subnet = utils.get_subnet_by_ip(self._get_nodes_subnets(),
                                             target_ip)
             if subnet:
                 subnet_id = subnet[0]
     else:
         # We use the service subnet id so that the connectivity
         # from VIP to pods happens in layer 3 mode, i.e.,
         # routed.
         subnet_id = lb_crd['status']['loadbalancer']['subnet_id']
     return subnet_id
示例#3
0
    def _add_new_members(self, loadbalancer_crd):
        changed = False

        if loadbalancer_crd['status'].get('loadbalancer'):
            loadbalancer_crd = self._sync_lbaas_sgs(loadbalancer_crd)
        if not loadbalancer_crd:
            return changed

        lsnr_by_id = {
            l['id']: l
            for l in loadbalancer_crd['status'].get('listeners', [])
        }
        pool_by_lsnr_port = {
            (lsnr_by_id[p['listener_id']]['protocol'],
             lsnr_by_id[p['listener_id']]['port']): p
            for p in loadbalancer_crd['status'].get('pools', [])
        }

        # NOTE(yboaron): Since LBaaSv2 doesn't support UDP load balancing,
        #              the LBaaS driver will return 'None' in case of UDP port
        #              listener creation.
        #              we should consider the case in which
        #              'pool_by_lsnr_port[p.protocol, p.port]' is missing
        pool_by_tgt_name = {}
        for p in loadbalancer_crd['spec'].get('ports', []):
            try:
                pool_by_tgt_name[p['name']] = pool_by_lsnr_port[p['protocol'],
                                                                p['port']]
            except KeyError:
                continue

        current_targets = [
            (str(m['ip']), m['port'], m['pool_id'])
            for m in loadbalancer_crd['status'].get('members', [])
        ]

        for ep_slice in loadbalancer_crd['spec']['endpointSlices']:
            ep_slices_ports = ep_slice.get('ports', [])
            for endpoint in ep_slice.get('endpoints', []):
                try:
                    target_ip = endpoint['addresses'][0]
                    target_ref = endpoint.get('targetRef')
                    target_namespace = None
                    if target_ref:
                        target_namespace = target_ref['namespace']
                    # Avoid to point to a Pod on hostNetwork
                    # that isn't the one to be added as Member.
                    if not target_ref and utils.get_subnet_by_ip(
                            self._get_nodes_subnets(), target_ip):
                        target_pod = {}
                    else:
                        target_pod = utils.get_pod_by_ip(
                            target_ip, target_namespace)
                except KeyError:
                    continue
                if not pool_by_tgt_name:
                    continue
                for ep_slice_port in ep_slices_ports:
                    target_port = ep_slice_port['port']
                    port_name = ep_slice_port.get('name')
                    try:
                        pool = pool_by_tgt_name[port_name]
                    except KeyError:
                        LOG.debug("No pool found for port: %r", port_name)
                        continue

                    if (target_ip, target_port, pool['id']) in current_targets:
                        continue

                    member_subnet_id = self._get_subnet_by_octavia_mode(
                        target_pod, target_ip, loadbalancer_crd)

                    if not member_subnet_id:
                        LOG.warning("Skipping member creation for %s",
                                    target_ip)
                        continue

                    target_name, target_namespace = self._get_target_info(
                        target_ref, loadbalancer_crd)

                    first_member_of_the_pool = True
                    for member in loadbalancer_crd['status'].get(
                            'members', []):
                        if pool['id'] == member['pool_id']:
                            first_member_of_the_pool = False
                            break
                    if first_member_of_the_pool:
                        listener_port = lsnr_by_id[pool['listener_id']]['port']
                    else:
                        listener_port = None
                    loadbalancer = loadbalancer_crd['status']['loadbalancer']
                    member = self._drv_lbaas.ensure_member(
                        loadbalancer=loadbalancer,
                        pool=pool,
                        subnet_id=member_subnet_id,
                        ip=target_ip,
                        port=target_port,
                        target_ref_namespace=target_namespace,
                        target_ref_name=target_name,
                        listener_port=listener_port)
                    if not member:
                        continue
                    members = loadbalancer_crd['status'].get('members', [])
                    if members:
                        loadbalancer_crd['status'].get('members',
                                                       []).append(member)
                    else:
                        loadbalancer_crd['status']['members'] = []
                        loadbalancer_crd['status'].get('members',
                                                       []).append(member)
                    if not self._patch_status(loadbalancer_crd):
                        return False
                    changed = True
        return changed