blob: 3344a2d79c41185300db1316426560d7ba0ecc7f [file] [log] [blame]
Sapan Bhatia2810e032017-11-03 00:31:00 -04001# 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
15from synchronizers.new_base.modelaccessor import *
Sapan Bhatia503ad902017-11-13 13:06:17 -050016from synchronizers.new_base.model_policies.model_policy_tenantwithcontainer import Policy
Sapan Bhatia2810e032017-11-03 00:31:00 -040017from synchronizers.new_base.exceptions import *
18
19from xosconfig import Config
20from multistructlog import create_logger
21
22log = create_logger(Config().get('logging'))
23blueprints = Config().get('blueprints')
24
Sapan Bhatia6eeb6942017-11-27 00:27:56 -050025
Sapan Bhatia503ad902017-11-13 13:06:17 -050026class VEPCServiceInstancePolicy(Policy):
Sapan Bhatia2810e032017-11-03 00:31:00 -040027 model_name = "VEPCServiceInstance"
28
Wei-Yu Chen3d6939a2018-06-22 16:44:08 +080029 def get_service_object(self, name):
30 """ return: First Service object """
31 if any(map(lambda x: x in name, ["ServiceInstance", "Tenant"])):
32 name = name.replace("ServiceInstance", "Service")
33 name = name.replace("Tenant", "Service")
Sapan Bhatia491a0802017-11-22 19:37:28 -050034
Wei-Yu Chen3d6939a2018-06-22 16:44:08 +080035 service_obj = getattr(Slice().stub, name).objects.first()
Sapan Bhatia503ad902017-11-13 13:06:17 -050036
Wei-Yu Chen3d6939a2018-06-22 16:44:08 +080037 if not service_obj:
38 raise Exception("No %s object existed." % name)
Sapan Bhatia6eeb6942017-11-27 00:27:56 -050039
Sapan Bhatia2810e032017-11-03 00:31:00 -040040 return service_obj
41
Wei-Yu Chen3d6939a2018-06-22 16:44:08 +080042 def get_tenant_class(self, name):
43 """
44 return: Tenant class
45 We need to claim new Tenant instance(object) by this class
46 """
47 if not name.endswith("Service"):
48 raise Exception("Tenant object needs to find with Service name.")
Sapan Bhatia2810e032017-11-03 00:31:00 -040049
Wei-Yu Chen3d6939a2018-06-22 16:44:08 +080050 if hasattr(Slice().stub, name + "Instance"):
51 tenant_class = getattr(Slice().stub, name + "Instance")
52 elif hasattr(Slice().stub, name.replace("Service", "Tenant")):
53 tenant_class = getattr(Slice().stub, name.replace("Service", "Tenant"))
54 else:
55 raise Exception("No %s class existed." % name)
56
57 return tenant_class
58
59 def get_vendor_object(self, name):
60 postfixs = ["Service", "ServiceInstance", "Tenant"]
61 if not any(map(lambda x: name.endswith(x), postfixs)):
62 raise Exception("Vendor object need to find with Service or Tenant name.")
63
64 for postfix in postfixs:
65 name = name.replace(postfix, "Vendor")
66
67 vendor_obj = getattr(Slice().stub, name).objects.first()
68
69 if not vendor_obj:
70 raise Exception("No %s object existed." % name)
71
72 return vendor_obj
73
74 def create_service_instance(self, service_obj, node_label=None):
75 tenant_class = self.get_tenant_class(service_obj.leaf_model_name)
76 vendor_obj = self.get_vendor_object(service_obj.leaf_model_name)
77
78 vendor_name = "%s_vendor" % service_obj.name.lower()
79 name = "epc-%s-%d" % (tenant_class.__name__.lower(), self.obj.id)
80
81 instance = tenant_class.objects.filter(owner=service_obj.id, name=name).first()
82
83 if instance:
84 return instance
85
86 instance = tenant_class(owner=service_obj, name=name)
87 instance.master_serviceinstance = self.obj
88 instance.__setattr__(vendor_name, vendor_obj)
Sapan Bhatia11d0c9a2017-12-10 21:16:34 -050089
90 if node_label:
Wei-Yu Chen3d6939a2018-06-22 16:44:08 +080091 instance.node_label = "%s-%d" % (node_label, self.obj.id)
Sapan Bhatia11d0c9a2017-12-10 21:16:34 -050092
Wei-Yu Chen3d6939a2018-06-22 16:44:08 +080093 # Assign custom parameter to child tenant
94 if name in ["vspgwc", "vspgwu"]:
95 instance.enodeb_ip_addr = self.obj.enodeb_ip_addr_s1u
96 instance.enodeb_mac_addr = self.obj.enodeb_mac_addr_s1u
97 instance.appserver_ip_addr = self.obj.appserver_ip_addr
98 instance.appserver_mac_addr = self.obj.appserver_mac_addr
99 elif name in ["vmme"]:
100 instance.enodeb_ip_addr = self.obj.enodeb_ip_addr_s1mme
Sapan Bhatia2810e032017-11-03 00:31:00 -0400101
Wei-Yu Chen3d6939a2018-06-22 16:44:08 +0800102 instance.no_sync = True
103 instance.no_policy = True
104 instance.invalidate_cache(vendor_name)
Sapan Bhatia503ad902017-11-13 13:06:17 -0500105
Wei-Yu Chen3d6939a2018-06-22 16:44:08 +0800106 instance.save()
Sapan Bhatia2810e032017-11-03 00:31:00 -0400107
Wei-Yu Chen3d6939a2018-06-22 16:44:08 +0800108 log.info("Instance %s was created." % instance)
Sapan Bhatia2810e032017-11-03 00:31:00 -0400109
Sapan Bhatia491a0802017-11-22 19:37:28 -0500110 return instance
111
Wei-Yu Chen3d6939a2018-06-22 16:44:08 +0800112 def create_network(self, network):
113 name = network.get("name", "")
114 owner = network.get("owner", "")
Andy Bavier52b5e0f2017-11-27 15:58:21 -0700115 site_name = self.obj.site.login_base
Wei-Yu Chen3d6939a2018-06-22 16:44:08 +0800116 template_name = network.get("template", "public")
117 subnet = network.get("subnet", "")
118 permit_all_slices = network.get("permit_all_slices", False)
Sapan Bhatia491a0802017-11-22 19:37:28 -0500119
Wei-Yu Chen3d6939a2018-06-22 16:44:08 +0800120 # Get Network, If Network subnet mismatch, then update
121 # If Network existed, then early return.
122 network_obj = Network.objects.filter(name=name).first()
123 if network_obj:
124 if network_obj.subnet != subnet:
125 network_obj.subnet = subnet
126 network_obj.save()
127 return network_obj
Andy Bavier8721f5e2018-01-02 14:36:23 -0700128
Wei-Yu Chen3d6939a2018-06-22 16:44:08 +0800129 # Get Network Template by assigned name.
130 template = NetworkTemplate.objects.filter(name=template_name).first()
131 if not template:
132 raise Exception("Template %s for network %s is not exist." % (template_name, name))
Andy Bavier8721f5e2018-01-02 14:36:23 -0700133
Wei-Yu Chen3d6939a2018-06-22 16:44:08 +0800134 # Get Network owner slice by assigned name.
135 slice_name = "%s_%s" % (site_name, owner)
136 owner_slice = Slice.objects.filter(name=slice_name).first()
137 if not owner_slice:
138 raise Exception("Owner Slice %s for network %s is not exist." % (owner, name))
Sapan Bhatia6eeb6942017-11-27 00:27:56 -0500139
Wei-Yu Chen3d6939a2018-06-22 16:44:08 +0800140 # Create Network Instance and save.
141 network = Network(name=name, subnet=subnet, template=template,
142 permit_all_slices=permit_all_slices, owner=owner_slice)
143 network.save()
Sapan Bhatia491a0802017-11-22 19:37:28 -0500144
Wei-Yu Chen3d6939a2018-06-22 16:44:08 +0800145 log.info("Network %s was created." % network)
Sapan Bhatia491a0802017-11-22 19:37:28 -0500146
Wei-Yu Chen3d6939a2018-06-22 16:44:08 +0800147 return network
Sapan Bhatia491a0802017-11-22 19:37:28 -0500148
Wei-Yu Chen3d6939a2018-06-22 16:44:08 +0800149 def create_service_dependency(self, source, target):
150 """
151 Create Service Dependency object for Connectivity between service
152 source: source service object
153 target: target service object
154 """
Sapan Bhatia2810e032017-11-03 00:31:00 -0400155
Wei-Yu Chen3d6939a2018-06-22 16:44:08 +0800156 # Use Subscriber and Provider's ID to get Dependency
157 dependency = ServiceDependency.objects.filter(
158 subscriber_service_id=source.id, provider_service_id=target.id
159 ).first()
Sapan Bhatia8af7b882017-12-08 15:46:07 -0500160
Wei-Yu Chen3d6939a2018-06-22 16:44:08 +0800161 if not dependency:
162 # If no dependency existed, then create dependency
163 dependency = ServiceDependency(
164 subscriber_service=source, provider_service=target
165 )
166 dependency.save()
Sapan Bhatia8af7b882017-12-08 15:46:07 -0500167
Wei-Yu Chen3d6939a2018-06-22 16:44:08 +0800168 log.info("Service dependency %s was created, %s->%s" % (dependency, source, target))
169
170 # Get subscriber and provider's Service Instance
171 source_tenant_class = self.get_tenant_class(source.leaf_model_name)
172 target_tenant_class = self.get_tenant_class(target.leaf_model_name)
173 source_tenants = source_tenant_class.objects.all()
174 target_tenants = target_tenant_class.objects.all()
175
176 # Use cross product to create ServiceInstance Link
177 for source_tenant in source_tenants:
178 for target_tenant in target_tenants:
179 link = ServiceInstanceLink.objects.filter(
180 subscriber_service_instance_id=source_tenant.id,
181 provider_service_instance_id=target_tenant.id
182 )
183
184 if not link:
185 link = ServiceInstanceLink(
186 subscriber_service_instance=source_tenant,
187 provider_service_instance=target_tenant
188 )
189
190 link.save()
191
192 log.info("Service instance link %s was created" % link)
193
194 return dependency
195
196 def assign_network_to_service(self, service, network):
197 service_slice = service.slices.first()
198 network_slice = NetworkSlice.objects.filter(
199 network=network.id, slice=service_slice.id
200 )
201
202 if not network_slice:
203 network_slice = NetworkSlice(
204 network=network, slice=service_slice
205 )
206 network_slice.save()
207
208 return network_slice
209
210 def create_services_from_blueprint(self, blueprint):
211 dependencies = list()
212 instances = list()
213
214 for network in blueprint["networks"]:
215 network_instance = self.create_network(network)
216
217 for node in blueprint["graph"]:
218 # Get Service's Name, Network, Link attribute from blueprint node
219 # If value is not set, return empty data struct instead.
220 tenant_str = node.get("name", "")
221 networks = node.get("networks", list())
222 links = node.get("links", list())
223 node_label = node.get("node_label", None)
224
225 # Get Service Class by Defined Service Instance Name
226 # service_obj: Service Object in XOS core
227 # tenant_obj: Tenant Object in XOS core
228 service_obj = self.get_service_object(tenant_str)
229
230 for network in networks:
231 network_obj = Network.objects.filter(name=network).first()
232 self.assign_network_to_service(service_obj, network_obj)
233
234 instance = self.create_service_instance(service_obj, node_label=node_label)
235 instances.append(instance)
236
237 # Collect Service Dependencies relationship from links
238 for provider in links:
239 provider_str = provider.get("name", "")
240 provider_service_obj = self.get_service_object(provider_str)
241 dependencies.append((service_obj, provider_service_obj))
242
243 log.info("Dependency Pair: %s" % dependencies)
244
245 # Create Service Dependency between subscriber and provider
246 for subscriber, provider in dependencies:
247 self.create_service_dependency(subscriber, provider)
248
249 for instance in instances:
250 instance.no_policy = False
251 instance.no_sync = False
252 instance.save()
Sapan Bhatia2810e032017-11-03 00:31:00 -0400253
Sapan Bhatia503ad902017-11-13 13:06:17 -0500254 def handle_create(self, service_instance):
255 self.handle_update(service_instance)
256
Sapan Bhatia2810e032017-11-03 00:31:00 -0400257 def handle_update(self, service_instance):
Wei-Yu Chen3d6939a2018-06-22 16:44:08 +0800258 # Register EPC-Service's service_instance as self.obj
259 self.obj = service_instance
260
261 blueprint_name = service_instance.blueprint
262 try:
263 blueprint = filter(lambda x: x["name"] == blueprint_name, blueprints)[0]
264 except StopIteration:
265 log.error("Chosen blueprint: %s not defined" % blueprint_name)
266
267 self.create_services_from_blueprint(blueprint)