CORD-1252 eliminate hardcoded dependencies in VTN
Change-Id: I2765829dd7e7939e98d8d01ad2f3372e18561e7f
diff --git a/xos/synchronizer/steps/sync_onos_netcfg.py b/xos/synchronizer/steps/sync_onos_netcfg.py
index b084a66..67dc878 100644
--- a/xos/synchronizer/steps/sync_onos_netcfg.py
+++ b/xos/synchronizer/steps/sync_onos_netcfg.py
@@ -48,18 +48,18 @@
name=tagname)
return tags[0].value
- def get_tenants_who_want_config(self):
- tenants = []
+ def get_service_instances_who_want_config(self):
+ service_instances = []
# attribute is comma-separated list
for ta in ServiceInstanceAttribute.objects.filter(name="autogenerate"):
if ta.value:
for config in ta.value.split(','):
if config == "vtn-network-cfg":
- tenants.append(ta.service_instance)
- return tenants
+ service_instances.append(ta.service_instance)
+ return service_instances
- def save_tenant_attribute(self, tenant, name, value):
- tas = ServiceInstanceAttribute.objects.filter(service_instance_id=tenant.id, name=name)
+ def save_service_instance_attribute(self, service_instance, name, value):
+ tas = ServiceInstanceAttribute.objects.filter(service_instance_id=service_instance.id, name=name)
if tas:
ta = tas[0]
if ta.value != value:
@@ -68,7 +68,7 @@
ta.save()
else:
logger.info("saving autogenerated config %s" % name)
- ta = model_accessor.create_obj(ServiceInstanceAttribute, service_instance=tenant, name=name, value=value)
+ ta = model_accessor.create_obj(ServiceInstanceAttribute, service_instance=service_instance, name=name, value=value)
ta.save()
# This function currently assumes a single Deployment and Site
@@ -167,23 +167,26 @@
data["apps"]["org.opencord.vtn"]["cordvtn"]["nodes"].append(node_dict)
# Generate apps->org.onosproject.cordvtn->cordvtn->publicGateways
- # Pull the gateway information from vRouter
- if model_accessor.has_model_class("VRouterService"):
- vrouters = VRouterService.objects.all()
- if vrouters:
- for gateway in vrouters[0].get_gateways():
- gatewayIp = gateway['gateway_ip'].split('/',1)[0]
- gatewayMac = gateway['gateway_mac']
- gateway_dict = {
- "gatewayIp": gatewayIp,
- "gatewayMac": gatewayMac
- }
- data["apps"]["org.opencord.vtn"]["cordvtn"]["publicGateways"].append(gateway_dict)
- else:
- logger.info("No VRouter service present, not adding publicGateways to config")
+ # Pull the gateway information from Address Pool objects
+ for ap in AddressPool.objects.all():
+ if (not ap.gateway_ip) or (not ap.gateway_mac):
+ logger.info("Gateway_ip or gateway_mac is blank for addresspool %s. Skipping." % ap)
+ continue
+
+ gateway_dict = {
+ "gatewayIp": ap.gateway_ip,
+ "gatewayMac": ap.gateway_mac
+ }
+ data["apps"]["org.opencord.vtn"]["cordvtn"]["publicGateways"].append(gateway_dict)
+
+ if not AddressPool.objects.all().exists():
+ logger.info("No Address Pools present, not adding publicGateways to config")
return json.dumps(data, indent=4, sort_keys=True)
+ # TODO: Does this step execute every 5 seconds regardless of whether objects have changed?
+ # If so, what purpose does using watchers serve?
+
def call(self, **args):
vtn_service = VTNService.objects.all()
if not vtn_service:
@@ -194,6 +197,6 @@
# Check for autogenerate attribute
netcfg = self.get_onos_netcfg(vtn_service)
- tenants = self.get_tenants_who_want_config()
- for tenant in tenants:
- self.save_tenant_attribute(tenant, "rest_onos/v1/network/configuration/", netcfg)
+ service_instances = self.get_service_instances_who_want_config()
+ for service_instance in service_instances:
+ self.save_service_instance_attribute(service_instance, "rest_onos/v1/network/configuration/", netcfg)
diff --git a/xos/synchronizer/steps/sync_vtn_service.py b/xos/synchronizer/steps/sync_vtn_service.py
index 9aa2cb7..e4d4b4f 100644
--- a/xos/synchronizer/steps/sync_vtn_service.py
+++ b/xos/synchronizer/steps/sync_vtn_service.py
@@ -19,7 +19,7 @@
import socket
import sys
import base64
-from services.vtn.vtnnetport import VTNNetwork, VTNPort
+from synchronizers.vtn.vtnnetport import VTNNetwork, VTNPort
from synchronizers.new_base.syncstep import SyncStep
from synchronizers.new_base.modelaccessor import *
from xos.logger import Logger, logging
@@ -39,51 +39,52 @@
def __init__(self, **args):
SyncStep.__init__(self, **args)
- def get_vtn_onos_service(self):
- vtn_service = ONOSService.objects.filter(name="ONOS_CORD") # XXX fixme - harcoded
- if not vtn_service:
- raise "No VTN Onos Service"
+ def get_vtn_onos_app(self, vtn_service):
+ links = vtn_service.subscribed_links.all()
+ for link in links:
+ # We're looking for an ONOS App. It's the only ServiceInstance that VTN can be implemented on.
+ if link.provider_service_instance.leaf_model_name != "ONOSApp":
+ continue
- return vtn_service[0]
+ # TODO: Rather than checking model name, check for the right interface
+ # NOTE: Deferred until new Tosca engine is in place.
- def get_vtn_auth(self):
- return HTTPBasicAuth('karaf', 'karaf') # XXX fixme - hardcoded auth
+ #if not link.provider_service_interface:
+ # logger.warning("Link %s does not have a provider_service_interface. Skipping" % link)
+ # continue
+ #
+ #if link.provider_service_interface.interface_type.name != "onos_app_interface":
+ # logger.warning("Link %s provider_service_interface type is not equal to onos_app_interface" % link)
+ # continue
- def get_vtn_addr(self):
- vtn_service = self.get_vtn_onos_service()
+ # cast from ServiceInstance to ONOSApp
+ app = link.provider_service_instance.leaf_model
+ return app
- if vtn_service.rest_hostname:
- return vtn_service.rest_hostname
+ raise Exception("No ServiceInstanceLink from VTN Service to VTN ONOS App")
- # code below this point is for ONOS running in a slice, and is
- # probably outdated
+ def get_vtn_endpoint(self, vtn_service):
+ """ Get connection info for the ONOS that is hosting the VTN ONOS App.
- if not vtn_service.slices.exists():
- raise "VTN Service has no slices"
+ returns (hostname, port, auth)
+ """
+ app = self.get_vtn_onos_app(vtn_service)
+ # cast from Service to ONOSService
+ onos = app.owner.leaf_model
+ if not (onos.rest_hostname):
+ raise Exception("onos.rest_hostname is not set")
+ if not (onos.rest_port):
+ raise Exception("onos.rest_port is not set")
+ if not (onos.rest_password):
+ raise Exception("onos.rest_password is not set")
+ if not (onos.rest_username):
+ raise Exception("onos.rest_username is not set")
+ auth = HTTPBasicAuth(onos.rest_username, onos.rest_password)
+ return (onos.rest_hostname, onos.rest_port, auth)
- vtn_slice = vtn_service.slices.all()[0]
-
- if not vtn_slice.instances.exists():
- raise "VTN Slice has no instances"
-
- vtn_instance = vtn_slice.instances.all()[0]
-
- return vtn_instance.node.name
-
- def get_vtn_port(self):
- vtn_service = self.get_vtn_onos_service()
-
- if vtn_service.rest_port:
- return vtn_service.rest_port
-
- # code below this point is for ONOS running in a slice, and is
- # probably outdated
-
- raise Exception("Must set rest_port")
-
- def get_method(self, url, id):
+ def get_method(self, auth, url, id):
url_with_id = "%s/%s" % (url, id)
- r = requests.get(url_with_id, auth=self.get_vtn_auth())
+ r = requests.get(url_with_id, auth=auth)
if (r.status_code==200):
method="PUT"
url = url_with_id
@@ -95,7 +96,9 @@
exists=False
return (exists, url, method, req_func)
- def sync_service_networks(self):
+ def sync_service_networks(self, vtn_service):
+ (onos_hostname, onos_port, onos_auth) = self.get_vtn_endpoint(vtn_service)
+
valid_ids = []
for network in Network.objects.all():
network = VTNNetwork(network)
@@ -110,7 +113,7 @@
valid_ids.append(network.id)
if (glo_saved_networks.get(network.id, None) != network.to_dict()):
- (exists, url, method, req_func) = self.get_method("http://" + self.get_vtn_addr() + ":" + str(self.get_vtn_port()) + "/onos/cordvtn/serviceNetworks", network.id)
+ (exists, url, method, req_func) = self.get_method(onos_auth, "http://%s:%d/onos/cordvtn/serviceNetworks" % (onos_hostname, onos_port), network.id)
logger.info("%sing VTN API for network %s" % (method, network.id))
@@ -124,7 +127,7 @@
"providerNetworks": providerNetworks} }
logger.info("DATA: %s" % str(data))
- r=req_func(url, json=data, auth=self.get_vtn_auth() )
+ r=req_func(url, json=data, auth=onos_auth )
if (r.status_code in [200,201]):
glo_saved_networks[network.id] = network.to_dict()
else:
@@ -135,16 +138,18 @@
if network_id not in valid_ids:
logger.info("DELETEing VTN API for network %s" % network_id)
- url = "http://" + self.get_vtn_addr() + ":" + str(self.get_vtn_port()) + "/onos/cordvtn/serviceNetworks/%s" % network_id
+ url = "http://%s:%d/onos/cordvtn/serviceNetworks/%s" % (onos_hostname, onos_port, network_id)
logger.info("URL: %s" % url)
- r = requests.delete(url, auth=self.get_vtn_auth() )
+ r = requests.delete(url, auth=onos_auth )
if (r.status_code in [200,204]):
del glo_saved_networks[network_id]
else:
logger.error("Received error from vtn service (%d)" % r.status_code)
- def sync_service_ports(self):
+ def sync_service_ports(self, vtn_service):
+ (onos_hostname, onos_port, onos_auth) = self.get_vtn_endpoint(vtn_service)
+
valid_ids = []
for port in Port.objects.all():
port = VTNPort(port)
@@ -159,7 +164,7 @@
valid_ids.append(port.id)
if (glo_saved_ports.get(port.id, None) != port.to_dict()):
- (exists, url, method, req_func) = self.get_method("http://" + self.get_vtn_addr() + ":" + str(self.get_vtn_port()) + "/onos/cordvtn/servicePorts", port.id)
+ (exists, url, method, req_func) = self.get_method(onos_auth, "http://%s:%d/onos/cordvtn/servicePorts" % (onos_hostname, onos_port), port.id)
logger.info("%sing VTN API for port %s" % (method, port.id))
@@ -170,7 +175,7 @@
"floating_address_pairs": port.floating_address_pairs} }
logger.info("DATA: %s" % str(data))
- r=req_func(url, json=data, auth=self.get_vtn_auth() )
+ r=req_func(url, json=data, auth=onos_auth )
if (r.status_code in [200,201]):
glo_saved_ports[port.id] = port.to_dict()
else:
@@ -180,10 +185,10 @@
if port_id not in valid_ids:
logger.info("DELETEing VTN API for port %s" % port_id)
- url = "http://" + self.get_vtn_addr() + ":" + str(self.get_vtn_port()) + "/onos/cordvtn/servicePorts/%s" % port_id
+ url = "http://%s:%d/onos/cordvtn/servicePorts/%s" % (onos_hostname, onos_port, port_id)
logger.info("URL: %s" % url)
- r = requests.delete(url, auth=self.get_vtn_auth() )
+ r = requests.delete(url, auth=onos_auth )
if (r.status_code in [200,204]):
del glo_saved_ports[port_id]
else:
@@ -199,6 +204,9 @@
vtn_service = vtn_service[0]
+ # TODO: We should check get_vtn_onos_app() and make sure that it has been synced, and that any necessary
+ # attributes (netcfg, etc) is filled out.
+
if (vtn_service.resync):
# If the VTN app requested a full resync, clear our saved network
# so we will resync everything, then reset the 'resync' flag
@@ -211,8 +219,8 @@
if vtn_service.vtnAPIVersion>=2:
# version 2 means use new API
logger.info("Using New API")
- self.sync_service_networks()
- self.sync_service_ports()
+ self.sync_service_networks(vtn_service)
+ self.sync_service_ports(vtn_service)
else:
raise Exception("VTN API Version 1 is no longer supported by VTN Synchronizer")