CORD-2594: Autodetect blueprints from EPC component services
CORD-2595: Generalize instance dependency checks
Change-Id: I5656782bfeeccca5a9855ffc1a5bd8de646fa9e3
diff --git a/xos/synchronizer/steps/sync_vspgwctenant.py b/xos/synchronizer/steps/sync_vspgwctenant.py
index 0318ad6..aa1e8b2 100644
--- a/xos/synchronizer/steps/sync_vspgwctenant.py
+++ b/xos/synchronizer/steps/sync_vspgwctenant.py
@@ -19,9 +19,13 @@
from synchronizers.new_base.modelaccessor import *
from synchronizers.new_base.SyncInstanceUsingAnsible import SyncInstanceUsingAnsible
+from collections import defaultdict
+
parentdir = os.path.join(os.path.dirname(__file__), "..")
sys.path.insert(0, parentdir)
+blueprints = Config().get('blueprints')
+
class ServiceGraphException(Exception):
pass
@@ -30,16 +34,53 @@
template_name = "vspgwctenant_playbook.yaml"
service_key_name = "/opt/xos/configurations/mcord/mcord_private_key"
+ """ Convert ServiceInstance graph into an adjacency set"""
+ def adj_set_of_service_graph(self, o, visited = None, adj_set = None):
+ def key(o):
+ return o.leaf_model_name
+
+ if not adj_set:
+ adj_set = defaultdict(set)
+
+ if not o:
+ return adj_set
+ else:
+ if not visited:
+ visited = set()
+
+ ko = key(o)
+ visited.add(ko)
+
+ provider_links = ServiceInstanceLink.objects.filter(subscriber_service_instance_id = o.id)
+ for l in provider_links:
+ n = l.provider_service_instance
+ kn = key(n)
+ adj_set[ko].add(kn)
+ adj_set[kn].update([])
+ if kn not in visited:
+ adj_set = self.adj_set_of_service_graph(n, visited, adj_set)
+
+ subscriber_links = ServiceInstanceLink.objects.filter(provider_service_instance_id = o.id)
+ for l in subscriber_links:
+ n = l.subscriber_service_instance
+ sn = key(n)
+ adj_set[sn].add(ko)
+ adj_set[ko].update([])
+ if sn not in visited:
+ adj_set = self.adj_set_of_service_graph(n, visited, adj_set)
+
+ return adj_set
+
def __init__(self, *args, **kwargs):
super(SyncVSPGWCTenant, self).__init__(*args, **kwargs)
def get_extra_attributes(self, o):
- scenario = self.get_scenario(o)
+ blueprint = self.get_blueprint_and_check_dependencies(o)
- if scenario == 'cord_4_1_scenario':
+ if blueprint == 'cord_4_1_scenario':
return self.get_values_for_CORD_4_1(o)
- elif scenario == 'cord_5_0_scenario':
+ elif blueprint == 'cord_5_0_scenario':
return self.get_values_for_CORD_5_0(o)
else:
return self.get_extra_attributes_for_manual(o)
@@ -132,38 +173,51 @@
'sgi_network', "VSPGWUTenant", o, 'sgi_spgwu_ip')
return fields
+
+ def find_first_blueprint_subgraph(self, blueprints, adj_set):
+ found_blueprint = None
+ for blueprint in blueprints:
+ found = True
+ for node in blueprint['graph']:
+ if node['name'] not in adj_set:
+ found = False
+ break
+ try:
+ links = node['links']
+ except KeyError:
+ links = []
- def get_scenario(self, o):
- venb_flag = self.has_instance("VENBServiceInstance", o)
- vmme_flag = self.has_instance("VMMETenant", o)
- sdncontroller_flag = self.has_instance(
- "SDNControllerServiceInstance", o)
- vspgwu_flag = self.has_instance("VSPGWUTenant", o)
- internetemulator_flag = self.has_instance(
- "InternetEmulatorServiceInstance", o)
- vhss_flag = self.has_instance("VHSSTenant", o)
- hssdb_flag = self.has_instance("HSSDBServiceInstance", o)
+ for link in links:
+ if link['name'] not in adj_set[node['name']]:
+ found = False
+ break
+ if not found:
+ break
- if (o.blueprint == "build") or (o.blueprint == "MCORD 4.1"):
- if not venb_flag:
- self.defer_sync(o, "Waiting for eNB image to become available")
- if not vspgwu_flag:
- self.defer_sync(o, "Waiting for SPGWU image to become available")
- return 'cord_4_1_scenario'
+ if found:
+ found_blueprint = blueprint['name']
+ break
- if (o.blueprint == "mcord_5") or (o.blueprint == "MCORD 5"):
- if not hssdb_flag:
- self.defer_sync(o, "Waiting for HSS_DB image to become available")
- if not vhss_flag:
- self.defer_sync(o, "Waiting for vHSS image to become available")
- if not vmme_flag:
- self.defer_sync(o, "Waiting for vMME image to become available")
- if not vspgwu_flag:
- self.defer_sync(o, "Waiting for vSPGWU image to become available")
- return 'cord_5_0_scenario'
+ return found_blueprint
- return 'manual'
+ def check_instance_dependencies(self, blueprints, blueprint_name, o):
+ blueprint = next(
+ b for b in blueprints if b['name'] == blueprint_name)
+ node = next(n for n in blueprint['graph'] if n['name'] == o.leaf_model_name)
+ for link in node['links']:
+ flag = self.has_instance(link['name'], o)
+ if not flag:
+ self.defer_sync('%s does not have an instance. Deferring synchronization.'%link['name'])
+
+ def get_blueprint_and_check_dependencies(self, o):
+ adj_set = self.adj_set_of_service_graph(o)
+ blueprint_name = self.find_first_blueprint_subgraph(blueprints, adj_set)
+ if blueprint_name:
+ self.check_instance_dependencies(blueprints, blueprint_name, o)
+
+ ret_blueprint = 'manual' if not blueprint_name else blueprint_name
+ return ret_blueprint
def get_ip_address_from_peer_service_instance(self, network_name, sitype, o, parameter=None):
peer_si = self.get_peer_serviceinstance_of_type(sitype, o)
diff --git a/xos/synchronizer/vspgwc_config.yaml b/xos/synchronizer/vspgwc_config.yaml
index 54c487e..a824b80 100644
--- a/xos/synchronizer/vspgwc_config.yaml
+++ b/xos/synchronizer/vspgwc_config.yaml
@@ -20,3 +20,28 @@
steps_dir: "/opt/xos/synchronizers/vspgwc/steps"
sys_dir: "/opt/xos/synchronizers/vspgwc/sys"
model_policies_dir: "/opt/xos/synchronizers/vspgwc/model_policies"
+blueprints:
+ - name: cord_5_0_blueprint
+ graph:
+ - name: VMMETenant
+ links:
+ - name: VSPGWCTenant
+ links:
+ - name: VMMETenant
+ - name: VSPGWUTenant
+ - name: VSPGWUTenant
+ - name: VHSSTenant
+ links:
+ - name: HSSDBServiceInstance
+ - name: HSSDBServiceInstance
+ - name: cord_4_1_blueprint
+ graph:
+ - name: VSPGWUTenant
+ links:
+ - name: VENBServiceInstance
+ - name: VENBServiceInstance
+ - name: VSPGWCTenant
+ links:
+ - name: VENBServiceInstance
+ - name: VSPGWUTenant
+
diff --git a/xos/vspgwc.xproto b/xos/vspgwc.xproto
index 9038da1..22a24af 100644
--- a/xos/vspgwc.xproto
+++ b/xos/vspgwc.xproto
@@ -21,5 +21,4 @@
optional string enodeb_mac_addr = 3 [help_text = "external eNodeB MAC address (for 5.0)", default = "11:11:11:11:11:11", max_length = 32, null = True, db_index = False, blank = True];
optional string appserver_ip_addr = 4 [help_text = "external app server IP address (for 5.0)", default = "127.0.0.1", max_length = 32, null = True, db_index = False, blank = True];
optional string appserver_mac_addr = 5 [help_text = "external app server MAC address (for 5.0)", default = "11:11:11:11:11:11", max_length = 32, null = True, db_index = False, blank = True];
- optional string blueprint = 6 [help_text = "name of blueprint", default = "manual", max_length = 32, null = True, db_index = False, blank = True];
}