blob: 86beba1bbb18760fb0014e7d4f682003c4ac405c [file] [log] [blame]
Scott Baker1b241612015-04-14 17:19:16 -07001from django.db import models
Scott Baker9c8a2c72015-05-05 17:49:46 -07002from core.models import Service, PlCoreBase, Slice, Sliver, Tenant, Node, Image, User
Scott Baker1b241612015-04-14 17:19:16 -07003from core.models.plcorebase import StrippedCharField
4import os
5from django.db import models
6from django.forms.models import model_to_dict
7from django.db.models import Q
8from operator import itemgetter, attrgetter, methodcaller
Scott Baker697fb0b2015-04-20 09:16:17 -07009import traceback
Scott Bakerd921e1c2015-04-20 14:24:29 -070010from xos.exceptions import *
Scott Baker1b241612015-04-14 17:19:16 -070011
12"""
13import os
14import sys
15sys.path.append("/opt/xos")
16os.environ.setdefault("DJANGO_SETTINGS_MODULE", "xos.settings")
17import django
18from core.models import *
19from hpc.models import *
20from cord.models import *
21django.setup()
Scott Baker1b241612015-04-14 17:19:16 -070022
Scott Baker557aada2015-04-20 09:48:34 -070023t = VOLTTenant()
Scott Baker1b241612015-04-14 17:19:16 -070024t.caller = User.objects.all()[0]
25t.save()
26
Scott Baker39b0d892015-04-15 20:59:15 -070027for v in VOLTTenant.objects.all():
28 v.caller = User.objects.all()[0]
29 v.delete()
30
Scott Baker1b241612015-04-14 17:19:16 -070031for v in VCPETenant.objects.all():
32 v.caller = User.objects.all()[0]
33 v.delete()
Scott Baker697fb0b2015-04-20 09:16:17 -070034
35for v in VOLTTenant.objects.all():
36 v.caller = User.objects.all()[0]
37 v.delete()
Scott Baker9c8a2c72015-05-05 17:49:46 -070038
39for v in VOLTTenant.objects.all():
40 if not v.creator:
41 v.creator= User.objects.all()[0]
42 v.save()
43
44for v in VCPETenant.objects.all():
45 if not v.creator:
46 v.creator= User.objects.all()[0]
47 v.save()
Scott Baker1b241612015-04-14 17:19:16 -070048"""
49
50class ConfigurationError(Exception):
51 pass
52
Scott Baker39b0d892015-04-15 20:59:15 -070053# -------------------------------------------
54# VOLT
55# -------------------------------------------
56
57class VOLTService(Service):
58 KIND = "vOLT"
59
Scott Baker1b241612015-04-14 17:19:16 -070060 class Meta:
Scott Baker39b0d892015-04-15 20:59:15 -070061 app_label = "cord"
62 verbose_name = "vOLT Service"
63 proxy = True
64
65class VOLTTenant(Tenant):
66 class Meta:
67 proxy = True
68
69 KIND = "vOLT"
70
Scott Bakere744c7b2015-04-20 11:50:09 -070071 default_attributes = {"vlan_id": None, }
72
Scott Baker557aada2015-04-20 09:48:34 -070073 def __init__(self, *args, **kwargs):
74 volt_services = VOLTService.get_service_objects().all()
75 if volt_services:
76 self._meta.get_field("provider_service").default = volt_services[0].id
77 super(VOLTTenant, self).__init__(*args, **kwargs)
78
Scott Baker39b0d892015-04-15 20:59:15 -070079 @property
Scott Bakere744c7b2015-04-20 11:50:09 -070080 def vlan_id(self):
81 return self.get_attribute("vlan_id", self.default_attributes["vlan_id"])
82
83 @vlan_id.setter
84 def vlan_id(self, value):
85 self.set_attribute("vlan_id", value)
86
87 @property
Scott Baker39b0d892015-04-15 20:59:15 -070088 def vcpe(self):
Scott Baker697fb0b2015-04-20 09:16:17 -070089 if getattr(self, "cached_vcpe", None):
90 return self.cached_vcpe
Scott Baker39b0d892015-04-15 20:59:15 -070091 vcpe_id=self.get_attribute("vcpe_id")
92 if not vcpe_id:
93 return None
94 vcpes=VCPETenant.objects.filter(id=vcpe_id)
95 if not vcpes:
96 return None
Scott Baker697fb0b2015-04-20 09:16:17 -070097 vcpe=vcpes[0]
Scott Baker9c8a2c72015-05-05 17:49:46 -070098 vcpe.caller = self.creator
Scott Baker697fb0b2015-04-20 09:16:17 -070099 self.cached_vcpe = vcpe
100 return vcpe
Scott Baker39b0d892015-04-15 20:59:15 -0700101
102 @vcpe.setter
103 def vcpe(self, value):
104 if value:
Scott Baker697fb0b2015-04-20 09:16:17 -0700105 value = value.id
106 if (value != self.get_attribute("vcpe_id", None)):
107 self.cached_vcpe=None
108 self.set_attribute("vcpe_id", value)
Scott Baker39b0d892015-04-15 20:59:15 -0700109
Scott Baker9c8a2c72015-05-05 17:49:46 -0700110 @property
111 def creator(self):
112 if getattr(self, "cached_creator", None):
113 return self.cached_creator
114 creator_id=self.get_attribute("creator_id")
115 if not creator_id:
116 return None
117 users=User.objects.filter(id=creator_id)
118 if not users:
119 return None
120 user=users[0]
121 self.cached_creator = users[0]
122 return user
123
124 @creator.setter
125 def creator(self, value):
126 if value:
127 value = value.id
128 if (value != self.get_attribute("creator_id", None)):
129 self.cached_creator=None
130 self.set_attribute("creator_id", value)
131
Scott Baker39b0d892015-04-15 20:59:15 -0700132 def manage_vcpe(self):
133 # Each VOLT object owns exactly one VCPE object
134
135 if self.deleted:
136 return
137
138 if self.vcpe is None:
139 vcpeServices = VCPEService.get_service_objects().all()
140 if not vcpeServices:
Scott Bakerd921e1c2015-04-20 14:24:29 -0700141 raise XOSConfigurationError("No VCPE Services available")
Scott Baker39b0d892015-04-15 20:59:15 -0700142
143 vcpe = VCPETenant(provider_service = vcpeServices[0],
144 subscriber_tenant = self)
Scott Baker9c8a2c72015-05-05 17:49:46 -0700145 vcpe.caller = self.creator
Scott Baker39b0d892015-04-15 20:59:15 -0700146 vcpe.save()
147
148 try:
149 self.vcpe = vcpe
Scott Baker697fb0b2015-04-20 09:16:17 -0700150 super(VOLTTenant, self).save()
Scott Baker39b0d892015-04-15 20:59:15 -0700151 except:
152 vcpe.delete()
153 raise
154
155 def cleanup_vcpe(self):
156 if self.vcpe:
157 self.vcpe.delete()
158 self.vcpe = None
159
160 def save(self, *args, **kwargs):
Scott Bakerd921e1c2015-04-20 14:24:29 -0700161 self.validate_unique_service_specific_id()
162
Scott Baker9c8a2c72015-05-05 17:49:46 -0700163 if not self.creator:
164 if not getattr(self, "caller", None):
165 # caller must be set when creating a vCPE since it creates a slice
166 raise XOSProgrammingError("VOLTTenant's self.caller was not set")
167 self.creator = self.caller
168 if not self.creator:
169 raise XOSProgrammingError("VOLTTenant's self.creator was not set")
170
Scott Baker39b0d892015-04-15 20:59:15 -0700171 super(VOLTTenant, self).save(*args, **kwargs)
172 self.manage_vcpe()
173
174 def delete(self, *args, **kwargs):
175 self.cleanup_vcpe()
176 super(VOLTTenant, self).delete(*args, **kwargs)
177
178# -------------------------------------------
179# VCPE
180# -------------------------------------------
181
182class VCPEService(Service):
183 KIND = "vCPE"
184
185 class Meta:
186 app_label = "cord"
Scott Baker1b241612015-04-14 17:19:16 -0700187 verbose_name = "vCPE Service"
Scott Baker39b0d892015-04-15 20:59:15 -0700188 proxy = True
Scott Baker1b241612015-04-14 17:19:16 -0700189
190class VCPETenant(Tenant):
191 class Meta:
192 proxy = True
193
Scott Baker39b0d892015-04-15 20:59:15 -0700194 KIND = "vCPE"
195
Scott Baker9c8a2c72015-05-05 17:49:46 -0700196 sync_attributes = ("firewall_enable",
197 "firewall_rules",
198 "url_filter_enable",
199 "url_filter_rules",
200 "cdn_enable")
201
Scott Baker1b241612015-04-14 17:19:16 -0700202 default_attributes = {"firewall_enable": False,
Scott Baker0bcbb962015-04-16 21:54:50 -0700203 "firewall_rules": "accept all anywhere anywhere",
204 "url_filter_enable": False,
205 "url_filter_rules": "allow all",
206 "cdn_enable": False,
Scott Baker1b241612015-04-14 17:19:16 -0700207 "sliver_id": None}
208
Scott Baker697fb0b2015-04-20 09:16:17 -0700209 def __init__(self, *args, **kwargs):
210 super(VCPETenant, self).__init__(*args, **kwargs)
211 self.cached_vbng=None
212 self.cached_sliver=None
213
Scott Baker1b241612015-04-14 17:19:16 -0700214 @property
215 def image(self):
Scott Baker4f751bd2015-04-20 20:12:59 -0700216 LOOK_FOR_IMAGES=["Ubuntu 14.04 LTS", # portal
217 "Ubuntu-14.04-LTS", # ONOS demo machine
218 ]
219 for image_name in LOOK_FOR_IMAGES:
220 images = Image.objects.filter(name = image_name)
221 if images:
222 return images[0]
223
224 raise XOSProgrammingError("No VPCE image (looked for %s)" % str(LOOK_FOR_IMAGES))
Scott Baker1b241612015-04-14 17:19:16 -0700225
226 @property
227 def sliver(self):
Scott Baker697fb0b2015-04-20 09:16:17 -0700228 if getattr(self, "cached_sliver", None):
229 return self.cached_sliver
Scott Baker1b241612015-04-14 17:19:16 -0700230 sliver_id=self.get_attribute("sliver_id")
231 if not sliver_id:
232 return None
233 slivers=Sliver.objects.filter(id=sliver_id)
234 if not slivers:
235 return None
Scott Baker697fb0b2015-04-20 09:16:17 -0700236 sliver=slivers[0]
Scott Baker9c8a2c72015-05-05 17:49:46 -0700237 sliver.caller = self.creator
Scott Baker697fb0b2015-04-20 09:16:17 -0700238 self.cached_sliver = sliver
239 return sliver
Scott Baker1b241612015-04-14 17:19:16 -0700240
241 @sliver.setter
242 def sliver(self, value):
243 if value:
Scott Baker697fb0b2015-04-20 09:16:17 -0700244 value = value.id
245 if (value != self.get_attribute("sliver_id", None)):
246 self.cached_sliver=None
247 self.set_attribute("sliver_id", value)
248
249 @property
Scott Baker9c8a2c72015-05-05 17:49:46 -0700250 def creator(self):
251 if getattr(self, "cached_creator", None):
252 return self.cached_creator
253 creator_id=self.get_attribute("creator_id")
254 if not creator_id:
255 return None
256 users=User.objects.filter(id=creator_id)
257 if not users:
258 return None
259 user=users[0]
260 self.cached_creator = users[0]
261 return user
262
263 @creator.setter
264 def creator(self, value):
265 if value:
266 value = value.id
267 if (value != self.get_attribute("creator_id", None)):
268 self.cached_creator=None
269 self.set_attribute("creator_id", value)
270
271 @property
Scott Baker697fb0b2015-04-20 09:16:17 -0700272 def vbng(self):
273 if getattr(self, "cached_vbng", None):
274 return self.cached_vbng
275 vbng_id=self.get_attribute("vbng_id")
276 if not vbng_id:
277 return None
278 vbngs=VBNGTenant.objects.filter(id=vbng_id)
279 if not vbngs:
280 return None
281 vbng=vbngs[0]
Scott Baker9c8a2c72015-05-05 17:49:46 -0700282 vbng.caller = self.creator
Scott Baker697fb0b2015-04-20 09:16:17 -0700283 self.cached_vbng = vbng
284 return vbng
285
286 @vbng.setter
287 def vbng(self, value):
288 if value:
289 value = value.id
290 if (value != self.get_attribute("vbng_id", None)):
291 self.cached_vbng=None
292 self.set_attribute("vbng_id", value)
Scott Baker1b241612015-04-14 17:19:16 -0700293
294 @property
295 def firewall_enable(self):
296 return self.get_attribute("firewall_enable", self.default_attributes["firewall_enable"])
297
298 @firewall_enable.setter
299 def firewall_enable(self, value):
300 self.set_attribute("firewall_enable", value)
301
Scott Baker0bcbb962015-04-16 21:54:50 -0700302 @property
303 def firewall_rules(self):
304 return self.get_attribute("firewall_rules", self.default_attributes["firewall_rules"])
305
306 @firewall_rules.setter
307 def firewall_rules(self, value):
308 self.set_attribute("firewall_rules", value)
309
310 @property
311 def url_filter_enable(self):
312 return self.get_attribute("url_filter_enable", self.default_attributes["url_filter_enable"])
313
314 @url_filter_enable.setter
315 def url_filter_enable(self, value):
316 self.set_attribute("url_filter_enable", value)
317
318 @property
319 def url_filter_rules(self):
320 return self.get_attribute("url_filter_rules", self.default_attributes["url_filter_rules"])
321
322 @url_filter_rules.setter
323 def url_filter_rules(self, value):
324 self.set_attribute("url_filter_rules", value)
325
326 @property
327 def cdn_enable(self):
328 return self.get_attribute("cdn_enable", self.default_attributes["cdn_enable"])
329
330 @cdn_enable.setter
331 def cdn_enable(self, value):
332 self.set_attribute("cdn_enable", value)
333
Scott Baker1b241612015-04-14 17:19:16 -0700334 def pick_node(self):
335 nodes = list(Node.objects.all())
336 # TODO: logic to filter nodes by which nodes are up, and which
337 # nodes the slice can instantiate on.
338 nodes = sorted(nodes, key=lambda node: node.slivers.all().count())
339 return nodes[0]
340
341 def manage_sliver(self):
Scott Baker39b0d892015-04-15 20:59:15 -0700342 # Each VCPE object owns exactly one sliver.
343
Scott Baker1b241612015-04-14 17:19:16 -0700344 if self.deleted:
345 return
346
Scott Baker1b241612015-04-14 17:19:16 -0700347 if (self.sliver is not None) and (self.sliver.image != self.image):
348 self.sliver.delete()
349 self.sliver = None
Scott Baker9c8a2c72015-05-05 17:49:46 -0700350
Scott Baker1b241612015-04-14 17:19:16 -0700351 if self.sliver is None:
352 if not self.provider_service.slices.count():
Scott Bakerd921e1c2015-04-20 14:24:29 -0700353 raise XOSConfigurationError("The VCPE service has no slicers")
Scott Baker1b241612015-04-14 17:19:16 -0700354
355 node =self.pick_node()
356 sliver = Sliver(slice = self.provider_service.slices.all()[0],
357 node = node,
358 image = self.image,
Scott Baker9c8a2c72015-05-05 17:49:46 -0700359 creator = self.creator,
Scott Baker1b241612015-04-14 17:19:16 -0700360 deployment = node.site_deployment.deployment)
361 sliver.save()
362
Scott Baker39b0d892015-04-15 20:59:15 -0700363 try:
364 self.sliver = sliver
Scott Baker697fb0b2015-04-20 09:16:17 -0700365 super(VCPETenant, self).save()
Scott Baker39b0d892015-04-15 20:59:15 -0700366 except:
367 sliver.delete()
368 raise
Scott Baker1b241612015-04-14 17:19:16 -0700369
370 def cleanup_sliver(self):
371 if self.sliver:
372 self.sliver.delete()
373 self.sliver = None
374
Scott Baker697fb0b2015-04-20 09:16:17 -0700375 def manage_vbng(self):
376 # Each vCPE object owns exactly one vBNG object
377
378 if self.deleted:
379 return
380
381 if self.vbng is None:
382 vbngServices = VBNGService.get_service_objects().all()
383 if not vbngServices:
Scott Bakerd921e1c2015-04-20 14:24:29 -0700384 raise XOSConfigurationError("No VBNG Services available")
Scott Baker697fb0b2015-04-20 09:16:17 -0700385
386 vbng = VBNGTenant(provider_service = vbngServices[0],
387 subscriber_tenant = self)
Scott Baker9c8a2c72015-05-05 17:49:46 -0700388 vbng.caller = self.creator
Scott Baker697fb0b2015-04-20 09:16:17 -0700389 vbng.save()
390
391 try:
392 self.vbng = vbng
393 super(VCPETenant, self).save()
394 except:
395 vbng.delete()
396 raise
397
398 def cleanup_vbng(self):
399 if self.vbng:
400 self.vbng.delete()
401 self.vbng = None
402
Scott Baker1b241612015-04-14 17:19:16 -0700403 def save(self, *args, **kwargs):
Scott Baker9c8a2c72015-05-05 17:49:46 -0700404 if not self.creator:
405 if not getattr(self, "caller", None):
406 # caller must be set when creating a vCPE since it creates a slice
407 raise XOSProgrammingError("VBNGTenant's self.caller was not set")
408 self.creator = self.caller
409 if not self.creator:
410 raise XOSProgrammingError("VCPETenant's self.caller was not set")
411
Scott Baker1b241612015-04-14 17:19:16 -0700412 super(VCPETenant, self).save(*args, **kwargs)
Scott Baker39b0d892015-04-15 20:59:15 -0700413 self.manage_sliver()
Scott Baker697fb0b2015-04-20 09:16:17 -0700414 self.manage_vbng()
Scott Baker1b241612015-04-14 17:19:16 -0700415
416 def delete(self, *args, **kwargs):
Scott Baker697fb0b2015-04-20 09:16:17 -0700417 self.cleanup_vbng()
Scott Baker1b241612015-04-14 17:19:16 -0700418 self.cleanup_sliver()
419 super(VCPETenant, self).delete(*args, **kwargs)
420
Scott Baker697fb0b2015-04-20 09:16:17 -0700421#----------------------------------------------------------------------------
422# vBNG
423#----------------------------------------------------------------------------
424
425class VBNGService(Service):
426 KIND = "vBNG"
427
428 class Meta:
429 app_label = "cord"
430 verbose_name = "vBNG Service"
431 proxy = True
432
433class VBNGTenant(Tenant):
434 class Meta:
435 proxy = True
436
437 KIND = "vBNG"
438
439 default_attributes = {"routeable_subnet": ""}
440
441 @property
442 def routeable_subnet(self):
443 return self.get_attribute("routeable_subnet", self.default_attributes["routeable_subnet"])
444
445 @routeable_subnet.setter
446 def routeable_subnet(self, value):
447 self.set_attribute("routeable_subnet", value)