def _add_pod_to_service(self, service_id, pod_id, port=None):
        lb = LoadbalancerKM.get(service_id)
        if not lb:
            return
        vm = VirtualMachineKM.get(pod_id)
        if not vm:
            return

        for lb_listener_id in lb.loadbalancer_listeners:
            pool = self._get_loadbalancer_pool(lb_listener_id, port)
            if not pool:
                continue

            for vmi_id in vm.virtual_machine_interfaces:
                vmi = VirtualMachineInterfaceKM.get(vmi_id)
                if not vmi:
                    continue

                for member_id in pool.members:
                    member = LoadbalancerMemberKM.get(member_id)
                    if member and member.vmi == vmi_id:
                        break
                else:
                    self.logger.debug(
                        "Creating LB member for Pod/VM: %s in LB: %s with "
                        "target-port: %d"
                        % (vm.fq_name, lb.name, port['port']))
                    member_obj = self._vnc_create_member(
                        pool, pod_id, vmi_id, port['port'])
                    LoadbalancerMemberKM.locate(member_obj.uuid)
Exemple #2
0
    def vnc_service_add(self, service_id, service_name, service_namespace,
                        service_ip, selectors, ports, service_type,
                        externalIps, loadBalancerIp,
                        specified_fip_pool_fq_name_str):
        ingress_update = False
        lb = LoadbalancerKM.get(service_id)
        if not lb:
            ingress_update = True
            self._check_service_uuid_change(service_id, service_name,
                                            service_namespace, ports)

        self._lb_create(service_id, service_name, service_namespace,
                        service_ip, ports)

        # "kubernetes" service needs a link-local service to be created.
        # This link-local service will steer traffic destined for
        # "kubernetes" service from slave (compute) nodes to kube-api server
        # running on master (control) node.
        if service_name == self._kubernetes_service_name:
            self._create_link_local_service(service_name, service_namespace,
                                            service_ip, ports)

        self._update_service_public_ip(service_id, service_name,
                                       service_namespace, service_type,
                                       externalIps, loadBalancerIp,
                                       specified_fip_pool_fq_name_str)

        if ingress_update:
            self._ingress_mgr.update_ingress_backend(service_namespace,
                                                     service_name, 'ADD')
    def _add_pod_to_service(self, service_id, pod_id, port=None):
        lb = LoadbalancerKM.get(service_id)
        if not lb:
            return
        vm = VirtualMachineKM.get(pod_id)
        if not vm:
            return

        for lb_listener_id in lb.loadbalancer_listeners:
            pool = self._get_loadbalancer_pool(lb_listener_id, port)
            if not pool:
                continue

            for vmi_id in vm.virtual_machine_interfaces:
                vmi = VirtualMachineInterfaceKM.get(vmi_id)
                if not vmi:
                    continue

                for member_id in pool.members:
                    member = LoadbalancerMemberKM.get(member_id)
                    if member and member.vmi == vmi_id:
                        break
                else:
                    self.logger.debug(
                        "Creating LB member for Pod/VM: %s in LB: %s with "
                        "target-port: %d" %
                        (vm.fq_name, lb.name, port['port']))
                    member_obj = self._vnc_create_member(
                        pool, pod_id, vmi_id, port['port'])
                    LoadbalancerMemberKM.locate(member_obj.uuid)
    def _get_pods_attached_to_service(self, service_id, port=None):
        """
        Get list of Pods attached to the Service for a given port.
        """
        pod_members = set()
        lb = LoadbalancerKM.get(service_id)
        if not lb:
            return pod_members

        # No listeners on LB. Error condition. Handle gracefully..
        if len(lb.loadbalancer_listeners) == 0:
            self.logger.warning("No listeners on LB ({})".format(lb.name))
            return pod_members

        for lb_listener_id in lb.loadbalancer_listeners:
            pool = self._get_loadbalancer_pool(lb_listener_id, port)
            if not pool:
                continue

            for member_id in pool.members:
                member = LoadbalancerMemberKM.get(member_id)
                if member.vm:
                    pod_members.add(member.vm)

        return pod_members
Exemple #5
0
    def _sync_service_lb(self):
        lb_uuid_set = set(LoadbalancerKM.keys())
        service_uuid_set = set(ServiceKM.keys())
        deleted_uuid_set = lb_uuid_set - service_uuid_set
        for uuid in deleted_uuid_set:
            lb = LoadbalancerKM.get(uuid)
            if not lb:
                continue
            if not lb.annotations:
                continue
            owner = None
            kind = None
            cluster = None
            for kvp in lb.annotations['key_value_pair'] or []:
                if kvp['key'] == 'cluster':
                    cluster = kvp['value']
                elif kvp['key'] == 'owner':
                    owner = kvp['value']
                elif kvp['key'] == 'kind':
                    kind = kvp['value']

                if cluster == vnc_kube_config.cluster_name() and \
                   owner == 'k8s' and \
                   kind == self._k8s_event_type:
                    self._create_service_event('delete', uuid, lb)
                    break
        return
Exemple #6
0
    def _read_allocated_floating_ips(self, service_id):
        floating_ips = set()
        lb = LoadbalancerKM.get(service_id)
        if not lb:
            return
        vmi_ids = lb.virtual_machine_interfaces
        if vmi_ids is None:
            return None
        interface_found = False
        for vmi_id in vmi_ids:
            vmi = VirtualMachineInterfaceKM.get(vmi_id)
            if vmi is not None:
                interface_found = True
                break
        if not interface_found:
            return

        fip_ids = vmi.floating_ips
        if fip_ids is None:
            return None
        for fip_id in list(fip_ids):
            fip = FloatingIpKM.get(fip_id)
            if fip is not None:
                floating_ips.add(fip.address)

        return floating_ips
Exemple #7
0
    def _remove_pod_from_service(self, service_id, pod_id, port=None):
        lb = LoadbalancerKM.get(service_id)
        if not lb:
            return

        for lb_listener_id in lb.loadbalancer_listeners:
            pool = self._get_loadbalancer_pool(lb_listener_id, port)
            if not pool:
                continue

            for member_id in pool.members:
                member = LoadbalancerMemberKM.get(member_id)
                if member and member.vm == pod_id:
                    self.logger.debug(
                        "Delete LB member for Pod/VM: %s from LB: %s" %
                        (pod_id, lb.name))

                    try:
                        vmi_obj = self._vnc_lib.virtual_machine_interface_read(
                            id=member.vmi)

                        # Remove service member label from vmi.
                        svc_member_label = self._labels.get_service_label(
                            lb.service_name)
                        for k, v in svc_member_label.items():
                            self._vnc_lib.unset_tag(vmi_obj, k)
                    except NoIdError:
                        # VMI has already been deleted. Nothing to unset/remove.
                        pass

                    self.service_lb_member_mgr.delete(member_id)
                    LoadbalancerMemberKM.delete(member.uuid)
                    break
Exemple #8
0
    def _get_pods_attached_to_service(self, service_id, port=None):
        """
        Get list of Pods attached to the Service for a given port.
        """
        pod_members = set()
        lb = LoadbalancerKM.get(service_id)
        if not lb:
            return pod_members

        # No listeners on LB. Error condition. Handle gracefully..
        if len(lb.loadbalancer_listeners) == 0:
            self.logger.warning("No listeners on LB ({})".format(lb.name))
            return pod_members

        for lb_listener_id in lb.loadbalancer_listeners:
            pool = self._get_loadbalancer_pool(lb_listener_id, port)
            if not pool:
                continue

            for member_id in pool.members:
                member = LoadbalancerMemberKM.get(member_id)
                if member.vm:
                    pod_members.add(member.vm)

        return pod_members
Exemple #9
0
    def update_ingress_backend(self, ns_name, service_name, oper):
        ingress_ids = self._find_ingress(self._ingress_label_cache, ns_name,
                                         service_name)
        for ingress_id in ingress_ids or []:
            ingress = IngressKM.get(ingress_id)
            lb = LoadbalancerKM.get(ingress_id)
            if not ingress or not lb:
                continue
            if oper == 'ADD':
                new_backend_list = self._get_new_backend_list(
                    ingress.spec, ns_name)
                for new_backend in new_backend_list[:] or []:
                    if new_backend['member']['serviceName'] == service_name:

                        # Create a firewall rule for ingress to this service.
                        fw_uuid = VncIngress.add_ingress_to_service_rule(
                            ns_name, ingress.name, service_name)
                        lb.add_firewall_rule(fw_uuid)

                        self._create_listener_pool_member(
                            ns_name, lb, new_backend)
            else:
                old_backend_list = self._get_old_backend_list(lb)
                for old_backend in old_backend_list[:] or []:
                    if old_backend['member']['serviceName'] == service_name:
                        self._delete_listener(old_backend['listener_id'])

                        # Delete rules created for this ingress to service.
                        deleted_fw_rule_uuid =\
                            VncIngress.delete_ingress_to_service_rule(
                                ns_name, ingress.name, service_name)
                        lb.remove_firewall_rule(deleted_fw_rule_uuid)
    def _add_pod_to_service(self, service_id, pod_id, port=None, address=None):
        lb = LoadbalancerKM.get(service_id)
        if not lb:
            return
        vm = VirtualMachineKM.get(pod_id)
        host_vmi = None
        if not vm:
            if not self._args.host_network_service:
                return
            host_vmi = self._get_vmi_from_ip(address)
            if host_vmi == None:
                return
            else:
                vm = VirtualMachine(name="host", display_name="host")
                vm.virtual_machine_interfaces = [host_vmi]

        for lb_listener_id in lb.loadbalancer_listeners:
            pool = self._get_loadbalancer_pool(lb_listener_id, port)
            if not pool:
                continue

            for vmi_id in vm.virtual_machine_interfaces:
                if host_vmi == None:
                    vmi = VirtualMachineInterfaceKM.get(vmi_id)
                else:
                    vmi = self._vnc_lib.virtual_machine_interface_read(
                        id=vmi_id)
                if not vmi:
                    continue

                for member_id in pool.members:
                    member = LoadbalancerMemberKM.get(member_id)
                    if member and member.vmi == vmi_id:
                        break
                else:
                    self.logger.debug(
                        "Creating LB member for Pod/VM: %s in LB: %s with "
                        "target-port: %d" %
                        (vm.fq_name, lb.name, port['port']))
                    member_obj = self._vnc_create_member(
                        pool, pod_id, vmi_id, port['port'])

                    try:
                        vmi_obj = self._vnc_lib.virtual_machine_interface_read(
                            id=vmi_id)
                    except:
                        raise

                    # Attach the service label to underlying pod vmi.
                    self._labels.append(
                        vmi_id,
                        self._labels.get_service_label(lb.service_name))
                    # Set tags on the vmi.
                    self._vnc_lib.set_tags(
                        vmi_obj, self._labels.get_labels_dict(vmi_id))

                    LoadbalancerMemberKM.locate(member_obj.uuid)
Exemple #11
0
    def delete(self, service_id):
        lb = LoadbalancerKM.get(service_id)
        if not lb:
            return

        vmi_ids = lb.virtual_machine_interfaces
        self._vnc_lib.loadbalancer_delete(id=service_id)
        if vmi_ids is None:
            return None
        self._delete_virtual_interface(vmi_ids)
Exemple #12
0
    def _lb_create(self, service_id, service_name, service_namespace,
                   service_ip, ports):
        lb = LoadbalancerKM.get(service_id)
        if not lb:
            lb_obj = self._vnc_create_lb(service_id, service_name,
                                         service_namespace, service_ip)
            if not lb_obj:
                raise NoIdError
            lb = LoadbalancerKM.locate(service_id)

        self._create_listeners(service_namespace, lb, ports)
Exemple #13
0
    def _lb_delete(self, service_id, service_name, service_namespace):
        lb = LoadbalancerKM.get(service_id)
        if not lb:
            self.logger.debug(
                "LB doesnot exist for (%s,%s) in cfg db, return" %
                (service_namespace, service_name))
            return

        self._vnc_delete_listeners(lb)
        self._vnc_delete_lb(service_id)
        LoadbalancerKM.delete(service_id)
Exemple #14
0
    def _delete_lb(self, uid):
        lb = LoadbalancerKM.get(uid)
        if not lb:
            return
        # Delete rules created for this member.
        firewall_rules = set(lb.get_firewall_rules())
        for fw_rule_uuid in firewall_rules:
            VncIngress.delete_ingress_to_service_rule_by_id(fw_rule_uuid)
            lb.remove_firewall_rule(fw_rule_uuid)

        self._delete_all_listeners(lb)
        self._vnc_delete_lb(lb)
        LoadbalancerKM.delete(uid)
    def _remove_pod_from_service(self, service_id, pod_id, port=None):
        lb = LoadbalancerKM.get(service_id)
        if not lb:
            return

        for lb_listener_id in lb.loadbalancer_listeners:
            pool = self._get_loadbalancer_pool(lb_listener_id, port)
            if not pool:
                continue

            for member_id in pool.members:
                member = LoadbalancerMemberKM.get(member_id)
                if member and member.vm == pod_id:
                    self.logger.debug(
                        "Delete LB member for Pod/VM: %s from LB: %s"
                        % (pod_id, lb.name))
                    self.service_lb_member_mgr.delete(member_id)
                    LoadbalancerMemberKM.delete(member.uuid)
                    break
    def _remove_pod_from_service(self, service_id, pod_id, port=None):
        lb = LoadbalancerKM.get(service_id)
        if not lb:
            return

        for lb_listener_id in lb.loadbalancer_listeners:
            pool = self._get_loadbalancer_pool(lb_listener_id, port)
            if not pool:
                continue

            for member_id in pool.members:
                member = LoadbalancerMemberKM.get(member_id)
                if member and member.vm == pod_id:
                    self.logger.debug(
                        "Delete LB member for Pod/VM: %s from LB: %s" %
                        (pod_id, lb.name))
                    self.service_lb_member_mgr.delete(member_id)
                    LoadbalancerMemberKM.delete(member.uuid)
                    break
Exemple #17
0
    def _deallocate_floating_ips(self, service_id):
        lb = LoadbalancerKM.get(service_id)
        if not lb:
            return
        vmi_ids = lb.virtual_machine_interfaces
        if vmi_ids is None:
            return None
        interface_found = False
        for vmi_id in vmi_ids:
            vmi = VirtualMachineInterfaceKM.get(vmi_id)
            if vmi is not None:
                interface_found = True
                break
        if interface_found is False:
            return

        fip_ids = vmi.floating_ips.copy()
        for fip_id in fip_ids:
            try:
                self._vnc_lib.floating_ip_delete(id=fip_id)
            except NoIdError:
                pass
    def _remove_pod_from_service(self, service_id, pod_id, port=None):
        lb = LoadbalancerKM.get(service_id)
        if not lb:
            return

        for lb_listener_id in lb.loadbalancer_listeners:
            pool = self._get_loadbalancer_pool(lb_listener_id, port)
            if not pool:
                continue

            for member_id in pool.members:
                member = LoadbalancerMemberKM.get(member_id)
                if member and member.vm == pod_id:
                    self.logger.debug(
                        "Delete LB member for Pod/VM: %s from LB: %s"
                        % (pod_id, lb.name))

                    try:
                        vmi_obj = self._vnc_lib.virtual_machine_interface_read(
                                      id = member.vmi)

                        # Remove service member label from vmi.
                        svc_member_label = self._labels.get_service_label(
                            lb.service_name)
                        for k,v in svc_member_label.iteritems():
                            self._vnc_lib.unset_tag(vmi_obj, k)

                    except NoIdError:
                        # VMI has already been deleted. Nothing to unset/remove.
                        pass
                    except:
                        raise

                    self.service_lb_member_mgr.delete(member_id)
                    LoadbalancerMemberKM.delete(member.uuid)
                    break
Exemple #19
0
    def _create_lb(self, uid, name, ns_name, event):
        annotations = event['object']['metadata'].get('annotations')
        ingress_controller = 'opencontrail'
        if annotations:
            if 'kubernetes.io/ingress.class' in annotations:
                ingress_controller = annotations['kubernetes.io/ingress.class']
        if ingress_controller != 'opencontrail':
            self._logger.warning(
                "%s - ingress controller is not opencontrail for ingress %s" %
                (self._name, name))
            self._delete_ingress(uid)
            return
        lb = LoadbalancerKM.get(uid)
        if not lb:
            lb_obj = self._vnc_create_lb(uid, name, ns_name, annotations)
            if lb_obj is None:
                return
            lb = LoadbalancerKM.locate(uid)
        else:
            external_ip = None
            if annotations and 'externalIP' in annotations:
                external_ip = annotations['externalIP']
            specified_fip_pool_fq_name_str = None
            if annotations and 'opencontrail.org/fip-pool' in annotations:
                specified_fip_pool_fq_name_str = annotations[
                    'opencontrail.org/fip-pool']
            if external_ip != lb.external_ip:
                self._deallocate_floating_ip(lb)
                lb_obj = self._vnc_lib.loadbalancer_read(id=lb.uuid)
                fip = self._update_floating_ip(name, ns_name, external_ip,
                                               lb_obj,
                                               specified_fip_pool_fq_name_str)
                if fip:
                    lb.external_ip = external_ip
                self._update_kube_api_server(name, ns_name, lb_obj, fip)

        self._clear_ingress_cache_uuid(self._ingress_label_cache, uid)

        spec = event['object']['spec']
        new_backend_list = self._get_new_backend_list(spec, ns_name)
        old_backend_list = self._get_old_backend_list(lb)

        # find the unchanged backends
        for new_backend in new_backend_list[:] or []:
            self._update_ingress_cache(self._ingress_label_cache, ns_name,
                                       new_backend['member']['serviceName'],
                                       uid)
            for old_backend in old_backend_list[:] or []:
                if (new_backend['annotations'] == old_backend['annotations']
                        and new_backend['listener'] == old_backend['listener']
                        and new_backend['pool'] == old_backend['pool']
                        and new_backend['member'] == old_backend['member']):
                    # Create a firewall rule for this member.
                    fw_uuid = VncIngress.add_ingress_to_service_rule(
                        ns_name, name, new_backend['member']['serviceName'])
                    lb.add_firewall_rule(fw_uuid)

                    old_backend_list.remove(old_backend)
                    new_backend_list.remove(new_backend)
                    break
        if len(old_backend_list) == 0 and len(new_backend_list) == 0:
            return lb

        # find the updated backends and update
        backend_update_list = []
        for new_backend in new_backend_list[:] or []:
            for old_backend in old_backend_list[:] or []:
                if (new_backend['annotations'] == old_backend['annotations']
                        and new_backend['listener'] == old_backend['listener']
                        and new_backend['pool'] == old_backend['pool']):
                    backend = old_backend
                    backend['member']['member_id'] = old_backend['member_id']
                    backend['member']['serviceName'] = new_backend['member'][
                        'serviceName']
                    backend['member']['servicePort'] = new_backend['member'][
                        'servicePort']
                    backend_update_list.append(backend)
                    old_backend_list.remove(old_backend)
                    new_backend_list.remove(new_backend)
        for backend in backend_update_list or []:
            ll = LoadbalancerListenerKM.get(backend['listener_id'])
            pool = LoadbalancerPoolKM.get(backend['pool_id'])
            backend_member = backend['member']
            member = self._update_member(ns_name, backend_member, pool)
            if member is None:
                self._logger.error("%s - Deleting Listener %s and Pool %s" %
                                   (self._name, ll.name, pool.name))
                self._vnc_delete_pool(pool.uuid)
                LoadbalancerPoolKM.delete(pool.uuid)
                self._vnc_delete_listener(ll.uuid)
                LoadbalancerListenerKM.delete(ll.uuid)
        if len(old_backend_list) == 0 and len(new_backend_list) == 0:
            return lb

        # delete the old backends
        for backend in old_backend_list or []:
            self._delete_listener(backend['listener_id'])

            deleted_fw_rule_uuid =\
                VncIngress.delete_ingress_to_service_rule(
                    ns_name, name, backend['member']['serviceName'])
            lb.remove_firewall_rule(deleted_fw_rule_uuid)

        # create the new backends
        for backend in new_backend_list:

            # Create a firewall rule for this member.
            fw_uuid = VncIngress.add_ingress_to_service_rule(
                ns_name, name, backend['member']['serviceName'])
            lb.add_firewall_rule(fw_uuid)

            self._create_listener_pool_member(ns_name, lb, backend)

        return lb
Exemple #20
0
    def _add_pod_to_service(self, service_id, pod_id, port=None, address=None):
        lb = LoadbalancerKM.get(service_id)
        if not lb:
            return
        vm = VirtualMachineKM.get(pod_id)
        host_vmi = None
        if not vm:
            if not self._args.host_network_service:
                return
            host_vmi = self._get_vmi_from_ip(address)
            if host_vmi is None:
                return
            else:
                vm = VirtualMachine(name="host", display_name="host")
                vm.virtual_machine_interfaces = [host_vmi]

        for lb_listener_id in lb.loadbalancer_listeners:
            pool = self._get_loadbalancer_pool(lb_listener_id, port)
            if not pool:
                continue

            for vmi_id in vm.virtual_machine_interfaces:
                vmi = VirtualMachineInterfaceKM.get(vmi_id)
                if not vmi:
                    continue

                if host_vmi is None:
                    # Add VMI only if it matches the default address for endpoint,
                    # ignore other interfaces for pod
                    ip_found = False
                    for iip_uuid in vmi.instance_ips:
                        iip = InstanceIpKM.get(iip_uuid)
                        if iip and iip.address == address:
                            ip_found = True
                            break
                    if not ip_found:
                        continue

                for member_id in pool.members:
                    member = LoadbalancerMemberKM.get(member_id)
                    if member and member.vmi == vmi_id:
                        break
                else:
                    self.logger.debug(
                        "Creating LB member for Pod/VM: %s in LB: %s with "
                        "target-port: %d" %
                        (vm.fq_name, lb.name, port['port']))
                    member_obj = self._vnc_create_member(
                        pool, pod_id, vmi_id, port['port'])

                    vmi_obj = self._vnc_lib.virtual_machine_interface_read(
                        id=vmi_id)

                    # Attach the service label to underlying pod vmi.
                    self._labels.append(
                        vmi_id,
                        self._labels.get_service_label(lb.service_name))
                    # Set tags on the vmi.
                    self._vnc_lib.set_tags(
                        vmi_obj, self._labels.get_labels_dict(vmi_id))

                    LoadbalancerMemberKM.locate(member_obj.uuid)
Exemple #21
0
    def _allocate_floating_ips(self,
                               service_id,
                               specified_fip_pool_fq_name_str,
                               service_namespace,
                               external_ips=set()):
        lb = LoadbalancerKM.get(service_id)
        if not lb:
            return None
        vmi_ids = lb.virtual_machine_interfaces
        if vmi_ids is None:
            return None
        interface_found = False
        for vmi_id in vmi_ids:
            vmi = VirtualMachineInterfaceKM.get(vmi_id)
            if vmi is not None:
                interface_found = True
                break
        if not interface_found:
            return

        vmi_obj = self._vnc_lib.virtual_machine_interface_read(id=vmi_id)
        if vmi_obj is None:
            return None

        fip_pool = None
        if specified_fip_pool_fq_name_str is not None:
            fip_pool = self._get_specified_fip_pool(
                specified_fip_pool_fq_name_str)
        if fip_pool is None and self._get_annotated_ns_fip_pool(
                service_namespace) is not None:
            fip_pool = self._get_annotated_ns_fip_pool(service_namespace)
        if fip_pool is None:
            fip_pool = self._get_public_fip_pool()
        if fip_pool is None:
            self.logger.warning("public_fip_pool doesn't exists")
            return None

        def _check_ip_with_fip_pool(external_ip, fip_pool_obj):
            try:
                vn_obj = self._vnc_lib.virtual_network_read(
                    id=fip_pool_obj.parent_uuid)
            except NoIdError:
                return True
            ipam_refs = vn_obj.__dict__.get('network_ipam_refs', [])
            for ipam_ref in ipam_refs:
                vnsn_data = ipam_ref['attr'].__dict__
                ipam_subnets = vnsn_data.get('ipam_subnets', [])
                for ipam_subnet in ipam_subnets:
                    subnet_dict = ipam_subnet.__dict__.get('subnet', {})
                    if 'ip_prefix' in subnet_dict.__dict__:
                        ip_subnet_str = (
                            subnet_dict.__dict__.get('ip_prefix', '') + '/' +
                            str(subnet_dict.__dict__.get('ip_prefix_len')))
                        if IPAddress(external_ip) in IPNetwork(ip_subnet_str):
                            return True
            self.logger.error("external_ip not in fip_pool subnet")
            return False

        def _allocate_floating_ip(lb, vmi, fip_pool, external_ip=None):
            fip_obj = FloatingIp(lb.name + str(external_ip) + "-externalIP",
                                 fip_pool)
            fip_obj.set_virtual_machine_interface(vmi_obj)
            if external_ip:
                if not (_check_ip_with_fip_pool(external_ip, fip_pool)):
                    err_str = "external_ip " + external_ip + " not in fip_pool subnet"
                    self.logger.error(err_str)
                    return None
                fip_obj.set_floating_ip_address(external_ip)
            project = self._vnc_lib.project_read(id=lb.parent_uuid)
            fip_obj.set_project(project)
            try:
                self._vnc_lib.floating_ip_create(fip_obj)
            except RefsExistError:
                string_buf = StringIO()
                cgitb_hook(file=string_buf, format="text")
                err_msg = string_buf.getvalue()
                self.logger.error("%s" % (err_msg))
            except Exception:
                string_buf = StringIO()
                cgitb_hook(file=string_buf, format="text")
                err_msg = string_buf.getvalue()
                self.logger.error("%s" % (err_msg))

            fip = FloatingIpKM.locate(fip_obj.uuid)
            self.logger.notice("floating ip allocated : %s for Service (%s)" %
                               (fip.address, service_id))
            return (fip.address)

        fips = set()
        if len(external_ips) == 0:
            fip_addr = _allocate_floating_ip(lb, vmi, fip_pool)
            if fip_addr:
                fips.add(fip_addr)

            return fips

        for external_ip in external_ips:
            fip_addr = _allocate_floating_ip(lb, vmi, fip_pool, external_ip)
            if fip_addr:
                fips.add(fip_addr)
        return fips
    def _add_pod_to_service(self, service_id, pod_id, port=None, address=None):
        lb = LoadbalancerKM.get(service_id)
        if not lb:
            return
        vm = VirtualMachineKM.get(pod_id)
        host_vmi = None
        if not vm:
            if not self._args.host_network_service:
                return
            host_vmi = self._get_vmi_from_ip(address)
            if host_vmi == None:
                return
            else:
                vm = VirtualMachine(name="host", display_name="host")
                vm.virtual_machine_interfaces = [host_vmi]


        for lb_listener_id in lb.loadbalancer_listeners:
            pool = self._get_loadbalancer_pool(lb_listener_id, port)
            if not pool:
                continue

            for vmi_id in vm.virtual_machine_interfaces:
                if host_vmi == None:
                    vmi = VirtualMachineInterfaceKM.get(vmi_id)
                else:
                    vmi = self._vnc_lib.virtual_machine_interface_read(id=vmi_id)
                if not vmi:
                    continue

                # Add VMI only if it matches the default address for endpoint,
                # ignore other interfaces for pod
                ip_found = False
                for iip_uuid in vmi.instance_ips:
                    iip = InstanceIpKM.get(iip_uuid)
                    if iip and iip.address == address:
                        ip_found = True
                        break

                if ip_found == False:
                    continue

                for member_id in pool.members:
                    member = LoadbalancerMemberKM.get(member_id)
                    if member and member.vmi == vmi_id:
                        break
                else:
                    self.logger.debug(
                        "Creating LB member for Pod/VM: %s in LB: %s with "
                        "target-port: %d"
                        % (vm.fq_name, lb.name, port['port']))
                    member_obj = self._vnc_create_member(
                        pool, pod_id, vmi_id, port['port'])

                    try:
                        vmi_obj = self._vnc_lib.virtual_machine_interface_read(
                                      id = vmi_id)
                    except:
                        raise

                    # Attach the service label to underlying pod vmi.
                    self._labels.append(vmi_id,
                        self._labels.get_service_label(lb.service_name))
                    # Set tags on the vmi.
                    self._vnc_lib.set_tags(vmi_obj,
                        self._labels.get_labels_dict(vmi_id))

                    LoadbalancerMemberKM.locate(member_obj.uuid)