CORD-1252 eliminate hardcoded dependencies in VTN
Change-Id: I2765829dd7e7939e98d8d01ad2f3372e18561e7f
diff --git a/xos/synchronizer/vtnnetport.py b/xos/synchronizer/vtnnetport.py
index 82f5a0c..eaa037f 100644
--- a/xos/synchronizer/vtnnetport.py
+++ b/xos/synchronizer/vtnnetport.py
@@ -14,24 +14,8 @@
# limitations under the License.
-# This library can be used in two different contexts:
-# 1) From the VTN synchronizer
-# 2) From the handcrafted VTN API endpoint
-#
-# If (1) then the modelaccessor module can provide us with models from the API
-# or django as appropriate. If (2) then we must use django, until we can
-# reconcile what to do about handcrafted API endpoints
-
-import __main__ as main_program
-
-if "synchronizer" in main_program.__file__:
- from synchronizers.new_base.modelaccessor import *
- in_synchronizer = True
-else:
- from core.models import *
- in_synchronizer = False
-
-VTN_SERVCOMP_KINDS=["PRIVATE","VSG"]
+from synchronizers.new_base.modelaccessor import *
+in_synchronizer = True
class VTNNetwork(object):
def __init__(self, xos_network=None):
@@ -160,43 +144,102 @@
return cn
return None
- def get_vsg_tenants(self):
- # If the VSG service isn't onboarded, then return an empty list.
- if (in_synchronizer):
- if not model_accessor.has_model_class("VSGTenant"):
- print "VSGTenant model does not exist. Returning no tenants"
- return []
- VSGTenant = model_accessor.get_model_class("VSGTenant") # suppress undefined local variable error
- else:
- try:
- from services.vsg.models import VSGTenant
- except ImportError:
- # TODO: Set up logging for this library...
- print "Failed to import VSG, returning no tenants"
- return []
+ def is_access_network(self):
+ """ Determines whether this port is attached to an access network. Currently we do this by examining the
+ network template's vtn_kind field. See if there is a better way...
+ """
+ return self.xos_port.network.template.vtn_kind in ["VSG", ]
- vsg_tenants=[]
- for tenant in VSGTenant.objects.all():
- if tenant.instance.id == self.xos_port.instance.id:
- vsg_tenants.append(tenant)
- return vsg_tenants
+ def get_vm_addresses(self):
+ if not self.is_access_network():
+ # If not an access network, do not apply any addresses
+ return []
+
+ if not self.xos_port.instance:
+ return []
+
+ # See if the Instance has any public address (aka "VrouterTenant) service instances associated with it.
+ # If so, then add each of those to the set of address pairs.
+
+ # TODO: Perhaps this should be implemented as a link instead of a tag...
+
+ tags = Tag.objects.filter(name="vm_public_service_instance", object_id=self.xos_port.instance.id,
+ content_type=self.xos_port.instance.self_content_type_id)
+
+ if not tags:
+ # DEPRECATED
+ # Historically, VSG instances are tagged with "vm_vrouter_tenant" instead of "vm_public_service_instance"
+ tags = Tag.objects.filter(name="vm_vrouter_tenant", object_id=self.xos_port.instance.id,
+ content_type=self.xos_port.instance.self_content_type_id)
+
+ address_pairs = []
+ for tag in tags:
+ si = ServiceInstance.objects.get(id = int(tag.value))
+
+ # cast from Tenant to descendant class (VRouterTenant, etc)
+ si = si.leaf_model
+
+ if (not hasattr(si, "public_ip")) or (not hasattr(si, "public_mac")):
+ raise Exception("Object %s does not have public_ip and/or public_mac fields" % si)
+ address_pairs.append({"ip_address": si.public_ip,
+ "mac_address": si.public_mac})
+
+ return address_pairs
+
+ def get_container_addresses(self):
+ if not self.is_access_network():
+ # If not an access network, do not apply any addresses
+ return []
+
+ if not self.xos_port.instance:
+ return []
+
+ addrs = []
+ for si in ServiceInstance.objects.all():
+ # cast from tenant to its descendant class (VSGTenant, etc)
+ si = si.leaf_model
+
+ if not hasattr(si, "instance_id"):
+ # ignore ServiceInstance that don't have instances
+ continue
+
+ if si.instance_id != self.xos_port.instance.id:
+ # ignore ServiceInstances that don't relate to our instance
+ continue
+
+ # Check to see if there is a link public address (aka VRouterTenant)
+ links = si.subscribed_links.all()
+ for link in links:
+ # cast from ServiceInstance to descendant class (VRouterTenant, etc)
+ pubaddr_si = link.provider_service_instance.leaf_model
+ if hasattr(pubaddr_si, "public_ip") and hasattr(pubaddr_si, "public_mac"):
+ addrs.append({"ip_address": pubaddr_si.public_ip,
+ "mac_address": pubaddr_si.public_mac})
+ return addrs
@property
def vlan_id(self):
+ """ Return the vlan_id associated with this instance. This assumes the instance was tagged with either a
+ vlan_id or s_tag tag.
+ """
+
+ if not self.is_access_network():
+ # If not an access network, do not apply any tags
+ return []
+
if not self.xos_port.instance:
return None
- # Only some kinds of networks can have s-tags associated with them.
- # Currently, only VSG access networks qualify.
- if not self.xos_port.network.template.vtn_kind in ["VSG",]:
- return None
+ tags = Tag.objects.filter(content_type=model_accessor.get_content_type_id(self.xos_port.instance),
+ object_id=self.xos_port.instance.id,
+ name="vlan_id")
- if (in_synchronizer):
+ if not tags:
+ # DEPRECATED
+ # Historically, VSG instances are tagged with "s_tag" instead of "vlan_id"
tags = Tag.objects.filter(content_type=model_accessor.get_content_type_id(self.xos_port.instance),
object_id=self.xos_port.instance.id,
name="s_tag")
- else:
- tags = Tag.select_by_content_object(self.xos_port.instance).filter(name="s_tag")
if not tags:
return None
@@ -208,18 +251,10 @@
# Floating_address_pairs is the set of WAN addresses that should be
# applied to this port.
- address_pairs = []
+ # We only want to apply these addresses to an "access" network.
- # only look apply the VSG addresses if the Network is of the VSG vtn_kind
- if self.xos_port.network.template.vtn_kind in ["VSG", ]:
- for vsg in self.get_vsg_tenants():
- if vsg.wan_container_ip and vsg.wan_container_mac:
- address_pairs.append({"ip_address": vsg.wan_container_ip,
- "mac_address": vsg.wan_container_mac})
- if vsg.wan_vm_ip and vsg.wan_vm_mac:
- address_pairs.append({"ip_address": vsg.wan_vm_ip,
- "mac_address": vsg.wan_vm_mac})
+ address_pairs = self.get_vm_addresses() + self.get_container_addresses()
return address_pairs