blob: d48bea5b0b2fcdb1e39a4ba4e31c489e06fb421e [file] [log] [blame]
JianHao4a9550f2017-10-19 11:05:14 +08001# Copyright 2017-present Open Networking Foundation
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15import os
16import sys
Woojoong Kim4f09cbf2017-11-19 21:25:37 -080017import time
JianHao4a9550f2017-10-19 11:05:14 +080018from django.db.models import Q, F
19from synchronizers.new_base.modelaccessor import *
20from synchronizers.new_base.SyncInstanceUsingAnsible import SyncInstanceUsingAnsible
21
Sapan Bhatia0c7f2602018-01-23 23:53:43 -050022from collections import defaultdict
23
JianHao4a9550f2017-10-19 11:05:14 +080024parentdir = os.path.join(os.path.dirname(__file__), "..")
25sys.path.insert(0, parentdir)
26
Sapan Bhatia0c7f2602018-01-23 23:53:43 -050027blueprints = Config().get('blueprints')
28
Sapan Bhatia28b75602017-11-28 14:18:21 -050029class ServiceGraphException(Exception):
30 pass
Sapan Bhatiaa1fbd382017-11-22 13:18:11 -050031
JianHao4a9550f2017-10-19 11:05:14 +080032class SyncVSPGWCTenant(SyncInstanceUsingAnsible):
JianHao4a9550f2017-10-19 11:05:14 +080033 observes = VSPGWCTenant
JianHao4a9550f2017-10-19 11:05:14 +080034 template_name = "vspgwctenant_playbook.yaml"
JianHao4a9550f2017-10-19 11:05:14 +080035 service_key_name = "/opt/xos/configurations/mcord/mcord_private_key"
36
Sapan Bhatia0c7f2602018-01-23 23:53:43 -050037 """ Convert ServiceInstance graph into an adjacency set"""
38 def adj_set_of_service_graph(self, o, visited = None, adj_set = None):
39 def key(o):
40 return o.leaf_model_name
41
42 if not adj_set:
43 adj_set = defaultdict(set)
44
45 if not o:
46 return adj_set
47 else:
48 if not visited:
49 visited = set()
50
51 ko = key(o)
52 visited.add(ko)
53
54 provider_links = ServiceInstanceLink.objects.filter(subscriber_service_instance_id = o.id)
55 for l in provider_links:
56 n = l.provider_service_instance
57 kn = key(n)
58 adj_set[ko].add(kn)
59 adj_set[kn].update([])
60 if kn not in visited:
61 adj_set = self.adj_set_of_service_graph(n, visited, adj_set)
62
63 subscriber_links = ServiceInstanceLink.objects.filter(provider_service_instance_id = o.id)
64 for l in subscriber_links:
65 n = l.subscriber_service_instance
66 sn = key(n)
67 adj_set[sn].add(ko)
68 adj_set[ko].update([])
69 if sn not in visited:
70 adj_set = self.adj_set_of_service_graph(n, visited, adj_set)
71
72 return adj_set
73
JianHao4a9550f2017-10-19 11:05:14 +080074 def __init__(self, *args, **kwargs):
75 super(SyncVSPGWCTenant, self).__init__(*args, **kwargs)
76
Woojoong Kimf000eda2017-10-20 15:00:43 -070077 def get_extra_attributes(self, o):
JianHao4a9550f2017-10-19 11:05:14 +080078
Sapan Bhatia0c7f2602018-01-23 23:53:43 -050079 blueprint = self.get_blueprint_and_check_dependencies(o)
JianHao4a9550f2017-10-19 11:05:14 +080080
Woojoong Kim8f468142018-01-29 16:31:51 -080081 if blueprint == 'cord_4_1_blueprint':
Woojoong Kim103fba02018-01-18 20:01:06 -080082 return self.get_values_for_CORD_4_1(o)
Woojoong Kim8f468142018-01-29 16:31:51 -080083 elif blueprint == 'cord_5_0_blueprint':
Woojoong Kim103fba02018-01-18 20:01:06 -080084 return self.get_values_for_CORD_5_0(o)
Woojoong Kim8f468142018-01-29 16:31:51 -080085 elif blueprint == 'cord_5_p4_blueprint':
86 return self.get_extra_attributes_for_manual(o) # should be changed to appropriate playbook
Woojoong Kimf000eda2017-10-20 15:00:43 -070087 else:
Sapan Bhatiaa1fbd382017-11-22 13:18:11 -050088 return self.get_extra_attributes_for_manual(o)
Woojoong Kimf000eda2017-10-20 15:00:43 -070089
90 # fields for manual case
Sapan Bhatiaa1fbd382017-11-22 13:18:11 -050091 def get_extra_attributes_for_manual(self, o):
Woojoong Kimf000eda2017-10-20 15:00:43 -070092 fields = {}
Woojoong Kim8f468142018-01-29 16:31:51 -080093 fields['blueprint'] = "manual"
Woojoong Kim103fba02018-01-18 20:01:06 -080094 fields['cord_version'] = "manual"
Woojoong Kimf000eda2017-10-20 15:00:43 -070095 # for interface.cfg file
96 fields['zmq_sub_ip'] = "manual"
97 fields['zmq_pub_ip'] = "manual"
98 fields['dp_comm_ip'] = "manual"
99 fields['cp_comm_ip'] = "manual"
100 fields['fpc_ip'] = "manual"
101 fields['cp_nb_server_ip'] = "manual"
102
103 # for cp_config.cfg file
104 fields['s11_sgw_ip'] = "manual"
105 fields['s11_mme_ip'] = "manual"
106 fields['s1u_sgw_ip'] = "manual"
107
Woojoong Kim4f09cbf2017-11-19 21:25:37 -0800108 # for rules setup in ONOS
109 fields['sgi_as_ip'] = "manual"
110 fields['sgi_spgwu_ip'] = "manual"
111
Woojoong Kimf000eda2017-10-20 15:00:43 -0700112 return fields
113
Woojoong Kim103fba02018-01-18 20:01:06 -0800114 def get_values_for_CORD_4_1(self, o):
Woojoong Kim1a1e3702017-10-27 13:26:34 -0700115 fields = {}
Woojoong Kim103fba02018-01-18 20:01:06 -0800116 fields['cord_version'] = "4.1"
Woojoong Kim8f468142018-01-29 16:31:51 -0800117 fields['blueprint'] = "cord_4_1_blueprint"
Woojoong Kim1a1e3702017-10-27 13:26:34 -0700118 # for interface.cfg file
119 fields['zmq_sub_ip'] = "127.0.0.1"
120 fields['zmq_pub_ip'] = "127.0.0.1"
Sapan Bhatiaa1fbd382017-11-22 13:18:11 -0500121 fields['dp_comm_ip'] = self.get_ip_address_from_peer_service_instance(
Sapan Bhatia97536292017-11-27 21:35:34 -0500122 'spgw_network', "VSPGWUTenant", o, 'dp_comm_ip')
Sapan Bhatiaa1fbd382017-11-22 13:18:11 -0500123 fields['cp_comm_ip'] = self.get_ip_address_from_peer_service_instance_instance(
Sapan Bhatia97536292017-11-27 21:35:34 -0500124 'spgw_network', o, o, 'cp_comm_ip')
Woojoong Kim1a1e3702017-10-27 13:26:34 -0700125 fields['fpc_ip'] = "127.0.0.1"
126 fields['cp_nb_server_ip'] = "127.0.0.1"
127
128 # for cp_config.cfg file
Sapan Bhatiaa1fbd382017-11-22 13:18:11 -0500129 fields['s11_sgw_ip'] = self.get_ip_address_from_peer_service_instance_instance(
Sapan Bhatia97536292017-11-27 21:35:34 -0500130 's11_network', o, o, 's11_sgw_ip')
Sapan Bhatiaa1fbd382017-11-22 13:18:11 -0500131 fields['s1u_sgw_ip'] = self.get_ip_address_from_peer_service_instance(
Sapan Bhatia97536292017-11-27 21:35:34 -0500132 's1u_network', "VSPGWUTenant", o, 's1u_sgw_ip')
Sapan Bhatiaa1fbd382017-11-22 13:18:11 -0500133 fields['s11_mme_ip'] = self.get_ip_address_from_peer_service_instance(
Sapan Bhatia97536292017-11-27 21:35:34 -0500134 's11_network', "VENBServiceInstance", o, 's11_mme_ip')
Woojoong Kim1a1e3702017-10-27 13:26:34 -0700135
Woojoong Kim4f09cbf2017-11-19 21:25:37 -0800136 # for rules setup in ONOS
Sapan Bhatiaa1fbd382017-11-22 13:18:11 -0500137 fields['sgi_as_ip'] = self.get_ip_address_from_peer_service_instance(
Sapan Bhatia97536292017-11-27 21:35:34 -0500138 'sgi_network', "VENBServiceInstance", o, 'sgi_as_ip')
Sapan Bhatiaa1fbd382017-11-22 13:18:11 -0500139 fields['sgi_spgwu_ip'] = self.get_ip_address_from_peer_service_instance(
Sapan Bhatia97536292017-11-27 21:35:34 -0500140 'sgi_network', "VSPGWUTenant", o, 'sgi_spgwu_ip')
Woojoong Kim4f09cbf2017-11-19 21:25:37 -0800141
Woojoong Kim1a1e3702017-10-27 13:26:34 -0700142 return fields
143
Woojoong Kim103fba02018-01-18 20:01:06 -0800144 def get_values_for_CORD_5_0(self, o):
Woojoong Kim313d35c2017-12-18 17:15:46 -0800145 fields = {}
Woojoong Kim103fba02018-01-18 20:01:06 -0800146 fields['cord_version'] = "5.0"
Woojoong Kim8f468142018-01-29 16:31:51 -0800147 fields['blueprint'] = "cord_5_0_blueprint"
Woojoong Kim313d35c2017-12-18 17:15:46 -0800148
149 # for interface.cfg file
150 fields['zmq_sub_ip'] = "127.0.0.1"
151 fields['zmq_pub_ip'] = "127.0.0.1"
152 fields['dp_comm_ip'] = self.get_ip_address_from_peer_service_instance(
153 'spgw_network', "VSPGWUTenant", o, 'dp_comm_ip')
154 fields['cp_comm_ip'] = self.get_ip_address_from_peer_service_instance_instance(
155 'spgw_network', o, o, 'cp_comm_ip')
156 fields['fpc_ip'] = "127.0.0.1"
157 fields['cp_nb_server_ip'] = "127.0.0.1"
158
159 # for cp_config.cfg file
160 fields['s11_sgw_ip'] = self.get_ip_address_from_peer_service_instance_instance(
161 's11_network', o, o, 's11_sgw_ip')
162 fields['s1u_sgw_ip'] = self.get_ip_address_from_peer_service_instance(
Woojoong Kimc96c24f2018-01-22 17:37:05 -0800163 'flat_network_s1u', "VSPGWUTenant", o, 's1u_sgw_ip')
Woojoong Kim313d35c2017-12-18 17:15:46 -0800164 fields['s11_mme_ip'] = self.get_ip_address_from_peer_service_instance(
165 's11_network', "VMMETenant", o, 's11_mme_ip')
166
167 # for rules setup in ONOS
Woojoong Kim103fba02018-01-18 20:01:06 -0800168 internetemulator_flag = self.has_instance("InternetEmulatorServiceInstance", o)
169 if (internetemulator_flag):
170 fields['sgi_as_ip'] = self.get_ip_address_from_peer_service_instance(
171 'sgi_network', "InternetEmulatorServiceInstance", o, 'sgi_as_ip')
172 else:
173 fields['sgi_as_ip'] = o.appserver_ip_addr
Woojoong Kim313d35c2017-12-18 17:15:46 -0800174 fields['sgi_spgwu_ip'] = self.get_ip_address_from_peer_service_instance(
175 'sgi_network', "VSPGWUTenant", o, 'sgi_spgwu_ip')
176
177 return fields
Sapan Bhatia0c7f2602018-01-23 23:53:43 -0500178
179 def find_first_blueprint_subgraph(self, blueprints, adj_set):
180 found_blueprint = None
181 for blueprint in blueprints:
182 found = True
Woojoong Kim313d35c2017-12-18 17:15:46 -0800183
Sapan Bhatia0c7f2602018-01-23 23:53:43 -0500184 for node in blueprint['graph']:
185 if node['name'] not in adj_set:
186 found = False
187 break
188 try:
189 links = node['links']
190 except KeyError:
191 links = []
Woojoong Kim313d35c2017-12-18 17:15:46 -0800192
Sapan Bhatia0c7f2602018-01-23 23:53:43 -0500193 for link in links:
194 if link['name'] not in adj_set[node['name']]:
195 found = False
196 break
197 if not found:
198 break
Woojoong Kim4f09cbf2017-11-19 21:25:37 -0800199
Sapan Bhatia0c7f2602018-01-23 23:53:43 -0500200 if found:
201 found_blueprint = blueprint['name']
202 break
Woojoong Kimf000eda2017-10-20 15:00:43 -0700203
Sapan Bhatia0c7f2602018-01-23 23:53:43 -0500204 return found_blueprint
Woojoong Kim313d35c2017-12-18 17:15:46 -0800205
Sapan Bhatia0c7f2602018-01-23 23:53:43 -0500206 def check_instance_dependencies(self, blueprints, blueprint_name, o):
207 blueprint = next(
208 b for b in blueprints if b['name'] == blueprint_name)
209 node = next(n for n in blueprint['graph'] if n['name'] == o.leaf_model_name)
210 for link in node['links']:
211 flag = self.has_instance(link['name'], o)
212 if not flag:
213 self.defer_sync('%s does not have an instance. Deferring synchronization.'%link['name'])
214
215 def get_blueprint_and_check_dependencies(self, o):
216 adj_set = self.adj_set_of_service_graph(o)
217 blueprint_name = self.find_first_blueprint_subgraph(blueprints, adj_set)
218 if blueprint_name:
219 self.check_instance_dependencies(blueprints, blueprint_name, o)
220
221 ret_blueprint = 'manual' if not blueprint_name else blueprint_name
222 return ret_blueprint
Woojoong Kim1a1e3702017-10-27 13:26:34 -0700223
Sapan Bhatiaa1fbd382017-11-22 13:18:11 -0500224 def get_ip_address_from_peer_service_instance(self, network_name, sitype, o, parameter=None):
225 peer_si = self.get_peer_serviceinstance_of_type(sitype, o)
Sapan Bhatia97536292017-11-27 21:35:34 -0500226 return self.get_ip_address_from_peer_service_instance_instance(network_name, peer_si, o, parameter)
Woojoong Kimf000eda2017-10-20 15:00:43 -0700227
Sapan Bhatia97536292017-11-27 21:35:34 -0500228 def get_ip_address_from_peer_service_instance_instance(self, network_name, peer_si, o, parameter=None):
Sapan Bhatiaa1fbd382017-11-22 13:18:11 -0500229 try:
230 net_id = self.get_network_id(network_name)
Sapan Bhatia97536292017-11-27 21:35:34 -0500231 ins_id = peer_si.leaf_model.instance_id
Sapan Bhatiaa1fbd382017-11-22 13:18:11 -0500232 ip_address = Port.objects.get(
233 network_id=net_id, instance_id=ins_id).ip
234 except Exception:
235 self.log.error("Failed to fetch parameter",
236 parameter=parameter,
237 network_name=network_name)
Sapan Bhatia97536292017-11-27 21:35:34 -0500238 self.defer_sync(o, "Waiting for parameters to become available")
Sapan Bhatiaa1fbd382017-11-22 13:18:11 -0500239
240 return ip_address
241
242 def get_peer_serviceinstance_of_type(self, sitype, o):
Woojoong Kimc96c24f2018-01-22 17:37:05 -0800243
244 global_list = self.get_all_instances_in_graph(o)
Sapan Bhatiaa1fbd382017-11-22 13:18:11 -0500245
246 try:
Woojoong Kimc96c24f2018-01-22 17:37:05 -0800247 peer_service = next(p for p in global_list if p.leaf_model_name == sitype)
Sapan Bhatia97536292017-11-27 21:35:34 -0500248
Woojoong Kimc96c24f2018-01-22 17:37:05 -0800249 except StopIteration:
250 self.log.error(
251 'Could not find service type in service graph', service_type=sitype, object=o)
252 raise ServiceGraphException(
253 "Synchronization failed due to incomplete service graph")
254
255 return peer_service
256
257 def has_instance_in_list(self, list, o):
258 for instance in list:
259 if instance.leaf_model_name == o.leaf_model_name:
260 return True
261
262 return False
263
264 def get_all_instances_in_graph(self, o):
265
266 to_search_list = self.get_one_hop_instances_in_graph(o)
267 result_list = []
268
269 while len(to_search_list) > 0:
270 tmp_obj = to_search_list[0]
271 to_search_list.remove(tmp_obj)
272 tmp_list = self.get_one_hop_instances_in_graph(tmp_obj)
273
274 for index_obj in tmp_list:
275 if (not self.has_instance_in_list(to_search_list, index_obj)) and (
276 not self.has_instance_in_list(result_list, index_obj)):
277 to_search_list.append(index_obj)
278
279 result_list.append(tmp_obj)
280 return result_list
281
282 def get_one_hop_instances_in_graph(self, o):
283 instance_list = []
284
285 # 1 hop forward and backward
286 prov_links = ServiceInstanceLink.objects.filter(subscriber_service_instance_id=o.id)
287 subs_links = ServiceInstanceLink.objects.filter(provider_service_instance_id=o.id)
288
289 # add instances located in 1 hop into instance_list
290 for tmp_link1 in prov_links:
291 if not self.has_instance_in_list(instance_list, tmp_link1.provider_service_instance):
292 instance_list.append(tmp_link1.provider_service_instance)
293
294 for tmp_link1 in subs_links:
295 if not self.has_instance_in_list(instance_list, tmp_link1.subscriber_service_instance):
296 instance_list.append(tmp_link1.subscriber_service_instance)
297
298 return instance_list
Sapan Bhatiaa1fbd382017-11-22 13:18:11 -0500299
Woojoong Kimf000eda2017-10-20 15:00:43 -0700300 # To get each network id
301 def get_network_id(self, network_name):
302 return Network.objects.get(name=network_name).id
303
304 # To get service_instance (assumption: there is a single instance for each service)
305 def get_instance_id(self, serviceinstance):
306 instances = serviceinstance.objects.all()
307 instance_id = instances[0].instance_id
308 return instance_id
Sapan Bhatiaa1fbd382017-11-22 13:18:11 -0500309
310 def has_instance(self, sitype, o):
Sapan Bhatia28b75602017-11-28 14:18:21 -0500311 try:
312 i = self.get_peer_serviceinstance_of_type(sitype, o)
313 except ServiceGraphException:
Sapan Bhatiaa1fbd382017-11-22 13:18:11 -0500314 self.log.info("Missing in ServiceInstance graph",
315 serviceinstance=sitype)
316 return False
317
Woojoong Kim38d84882017-11-28 15:38:39 -0800318 return i.leaf_model.instance_id