+class PortPairs(object):
+
+ DOWNLINK = "downlink"
+ UPLINK = "uplink"
+
+ def __init__(self, interfaces):
+ super(PortPairs, self).__init__()
+ self.interfaces = interfaces
+ self._all_ports = None
+ self._uplink_ports = None
+ self._downlink_ports = None
+ self._networks = None
+ self._port_pair_list = None
+ self._valid_networks = None
+
+ @property
+ def networks(self):
+ if self._networks is None:
+ self._networks = {}
+ for intf in self.interfaces:
+ vintf = intf['virtual-interface']
+ try:
+ vld_id = vintf['vld_id']
+ except KeyError:
+ # probably unused port?
+ LOG.warning("intf without vld_id, %s", vintf)
+ else:
+ self._networks.setdefault(vld_id, []).append(vintf["ifname"])
+ return self._networks
+
+ @classmethod
+ def get_downlink_id(cls, vld_id):
+ # partition returns a tuple
+ parts = list(vld_id.partition(cls.UPLINK))
+ if parts[0]:
+ # 'uplink' was not in or not leftmost in the string
+ return
+ parts[1] = cls.DOWNLINK
+ public_id = ''.join(parts)
+ return public_id
+
+ @property
+ # this only works for vnfs that have both uplink and public visible
+ def valid_networks(self):
+ if self._valid_networks is None:
+ self._valid_networks = []
+ for vld_id in self.networks:
+ downlink_id = self.get_downlink_id(vld_id)
+ if downlink_id in self.networks:
+ self._valid_networks.append((vld_id, downlink_id))
+ return self._valid_networks
+
+ @property
+ def all_ports(self):
+ if self._all_ports is None:
+ self._all_ports = sorted(set(self.uplink_ports + self.downlink_ports))
+ return self._all_ports
+
+ @property
+ def uplink_ports(self):
+ if self._uplink_ports is None:
+ intfs = chain.from_iterable(
+ intfs for vld_id, intfs in self.networks.items() if
+ vld_id.startswith(self.UPLINK))
+ self._uplink_ports = sorted(set(intfs))
+ return self._uplink_ports
+
+ @property
+ def downlink_ports(self):
+ if self._downlink_ports is None:
+ intfs = chain.from_iterable(
+ intfs for vld_id, intfs in self.networks.items() if
+ vld_id.startswith(self.DOWNLINK))
+ self._downlink_ports = sorted(set(intfs))
+ return self._downlink_ports
+
+ @property
+ def port_pair_list(self):
+ if self._port_pair_list is None:
+ self._port_pair_list = []
+
+ for uplink, downlink in self.valid_networks:
+ for uplink_intf in self.networks[uplink]:
+ # only VNFs have uplink, public peers
+ peer_intfs = self.networks.get(downlink, [])
+ if peer_intfs:
+ for downlink_intf in peer_intfs:
+ port_pair = uplink_intf, downlink_intf
+ self._port_pair_list.append(port_pair)
+ return self._port_pair_list
+
+