blob: 58d1a974ff7968532e4a75941b7c458eba0e0054 [file] [log] [blame]
Scott Bakere9ff7ce2015-04-14 17:19:16 -07001from django.db import models
Scott Bakere1f72d12015-05-14 21:48:53 -07002from core.models import Service, PlCoreBase, Slice, Sliver, Tenant, Node, Image, User, Flavor
Scott Bakere9ff7ce2015-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 Bakerfa5cdd62015-04-20 09:16:17 -07009import traceback
Scott Baker7f8ef8f2015-04-20 14:24:29 -070010from xos.exceptions import *
Scott Bakere9ff7ce2015-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 Bakere9ff7ce2015-04-14 17:19:16 -070022
Scott Baker323eca92015-04-20 09:48:34 -070023t = VOLTTenant()
Scott Bakere9ff7ce2015-04-14 17:19:16 -070024t.caller = User.objects.all()[0]
25t.save()
26
Scott Bakerdfc0bef2015-05-11 08:31:24 -070027for v in VOLTTenant.get_tenant_objects().all():
Scott Bakerd4b48c02015-04-15 20:59:15 -070028 v.caller = User.objects.all()[0]
29 v.delete()
30
Scott Bakerdfc0bef2015-05-11 08:31:24 -070031for v in VCPETenant.get_tenant_objects().all():
Scott Bakere9ff7ce2015-04-14 17:19:16 -070032 v.caller = User.objects.all()[0]
33 v.delete()
Scott Bakerfa5cdd62015-04-20 09:16:17 -070034
Scott Bakerdfc0bef2015-05-11 08:31:24 -070035for v in VOLTTenant.get_tenant_objects().all():
Scott Bakerfa5cdd62015-04-20 09:16:17 -070036 v.caller = User.objects.all()[0]
37 v.delete()
Scott Bakerc633dc92015-05-05 17:49:46 -070038
Scott Bakerdfc0bef2015-05-11 08:31:24 -070039for v in VOLTTenant.get_tenant_objects().all():
Scott Bakerc633dc92015-05-05 17:49:46 -070040 if not v.creator:
41 v.creator= User.objects.all()[0]
42 v.save()
43
Scott Bakerdfc0bef2015-05-11 08:31:24 -070044for v in VCPETenant.get_tenant_objects().all():
Scott Bakerc633dc92015-05-05 17:49:46 -070045 if not v.creator:
46 v.creator= User.objects.all()[0]
47 v.save()
Scott Bakere9ff7ce2015-04-14 17:19:16 -070048"""
49
50class ConfigurationError(Exception):
51 pass
52
Scott Bakerd4b48c02015-04-15 20:59:15 -070053# -------------------------------------------
54# VOLT
55# -------------------------------------------
56
57class VOLTService(Service):
58 KIND = "vOLT"
59
Scott Bakere9ff7ce2015-04-14 17:19:16 -070060 class Meta:
Scott Bakerd4b48c02015-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 Baker1f050df2015-05-28 17:12:00 -070071 default_attributes = {"vlan_id": None,
72 "is_demo_user": False }
Scott Baker679f7022015-04-20 11:50:09 -070073
Scott Baker323eca92015-04-20 09:48:34 -070074 def __init__(self, *args, **kwargs):
75 volt_services = VOLTService.get_service_objects().all()
76 if volt_services:
77 self._meta.get_field("provider_service").default = volt_services[0].id
78 super(VOLTTenant, self).__init__(*args, **kwargs)
79
Scott Bakerd4b48c02015-04-15 20:59:15 -070080 @property
Scott Baker679f7022015-04-20 11:50:09 -070081 def vlan_id(self):
82 return self.get_attribute("vlan_id", self.default_attributes["vlan_id"])
83
84 @vlan_id.setter
85 def vlan_id(self, value):
86 self.set_attribute("vlan_id", value)
87
88 @property
Scott Bakerd4b48c02015-04-15 20:59:15 -070089 def vcpe(self):
Scott Bakerfa5cdd62015-04-20 09:16:17 -070090 if getattr(self, "cached_vcpe", None):
91 return self.cached_vcpe
Scott Bakerd4b48c02015-04-15 20:59:15 -070092 vcpe_id=self.get_attribute("vcpe_id")
93 if not vcpe_id:
94 return None
95 vcpes=VCPETenant.objects.filter(id=vcpe_id)
96 if not vcpes:
97 return None
Scott Bakerfa5cdd62015-04-20 09:16:17 -070098 vcpe=vcpes[0]
Scott Bakerc633dc92015-05-05 17:49:46 -070099 vcpe.caller = self.creator
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700100 self.cached_vcpe = vcpe
101 return vcpe
Scott Bakerd4b48c02015-04-15 20:59:15 -0700102
103 @vcpe.setter
104 def vcpe(self, value):
105 if value:
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700106 value = value.id
107 if (value != self.get_attribute("vcpe_id", None)):
108 self.cached_vcpe=None
109 self.set_attribute("vcpe_id", value)
Scott Bakerd4b48c02015-04-15 20:59:15 -0700110
Scott Bakerc633dc92015-05-05 17:49:46 -0700111 @property
112 def creator(self):
113 if getattr(self, "cached_creator", None):
114 return self.cached_creator
115 creator_id=self.get_attribute("creator_id")
116 if not creator_id:
117 return None
118 users=User.objects.filter(id=creator_id)
119 if not users:
120 return None
121 user=users[0]
122 self.cached_creator = users[0]
123 return user
124
125 @creator.setter
126 def creator(self, value):
127 if value:
128 value = value.id
129 if (value != self.get_attribute("creator_id", None)):
130 self.cached_creator=None
131 self.set_attribute("creator_id", value)
132
Scott Baker1f050df2015-05-28 17:12:00 -0700133 @property
134 def is_demo_user(self):
135 return self.get_attribute("is_demo_user", self.default_attributes["is_demo_user"])
136
137 @is_demo_user.setter
138 def is_demo_user(self, value):
139 self.set_attribute("is_demo_user", value)
140
Scott Bakerd4b48c02015-04-15 20:59:15 -0700141 def manage_vcpe(self):
142 # Each VOLT object owns exactly one VCPE object
143
144 if self.deleted:
145 return
146
147 if self.vcpe is None:
148 vcpeServices = VCPEService.get_service_objects().all()
149 if not vcpeServices:
Scott Baker7f8ef8f2015-04-20 14:24:29 -0700150 raise XOSConfigurationError("No VCPE Services available")
Scott Bakerd4b48c02015-04-15 20:59:15 -0700151
152 vcpe = VCPETenant(provider_service = vcpeServices[0],
153 subscriber_tenant = self)
Scott Bakerc633dc92015-05-05 17:49:46 -0700154 vcpe.caller = self.creator
Scott Bakerd4b48c02015-04-15 20:59:15 -0700155 vcpe.save()
156
157 try:
158 self.vcpe = vcpe
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700159 super(VOLTTenant, self).save()
Scott Bakerd4b48c02015-04-15 20:59:15 -0700160 except:
161 vcpe.delete()
162 raise
163
164 def cleanup_vcpe(self):
165 if self.vcpe:
166 self.vcpe.delete()
167 self.vcpe = None
168
169 def save(self, *args, **kwargs):
Scott Baker7f8ef8f2015-04-20 14:24:29 -0700170 self.validate_unique_service_specific_id()
171
Scott Bakerc633dc92015-05-05 17:49:46 -0700172 if not self.creator:
173 if not getattr(self, "caller", None):
174 # caller must be set when creating a vCPE since it creates a slice
175 raise XOSProgrammingError("VOLTTenant's self.caller was not set")
176 self.creator = self.caller
177 if not self.creator:
178 raise XOSProgrammingError("VOLTTenant's self.creator was not set")
179
Scott Bakerd4b48c02015-04-15 20:59:15 -0700180 super(VOLTTenant, self).save(*args, **kwargs)
181 self.manage_vcpe()
182
183 def delete(self, *args, **kwargs):
184 self.cleanup_vcpe()
185 super(VOLTTenant, self).delete(*args, **kwargs)
186
187# -------------------------------------------
188# VCPE
189# -------------------------------------------
190
191class VCPEService(Service):
192 KIND = "vCPE"
193
194 class Meta:
195 app_label = "cord"
Scott Bakere9ff7ce2015-04-14 17:19:16 -0700196 verbose_name = "vCPE Service"
Scott Bakerd4b48c02015-04-15 20:59:15 -0700197 proxy = True
Scott Bakere9ff7ce2015-04-14 17:19:16 -0700198
Scott Baker4e6d60d2015-05-20 20:45:11 -0700199 def allocate_bbs_account(self):
200 vcpes = VCPETenant.get_tenant_objects().all()
201 bbs_accounts = [vcpe.bbs_account for vcpe in vcpes]
202
203 # There's a bit of a race here; some other user could be trying to
204 # allocate a bbs_account at the same time we are.
205
206 for i in range(1,21):
207 account_name = "bbs%02d@onlab.us" % i
208 if (account_name not in bbs_accounts):
209 return account_name
210
211 raise XOSConfigurationError("We've run out of available broadbandshield accounts. Delete some vcpe and try again.")
212
Scott Bakere9ff7ce2015-04-14 17:19:16 -0700213class VCPETenant(Tenant):
214 class Meta:
215 proxy = True
216
Scott Bakerd4b48c02015-04-15 20:59:15 -0700217 KIND = "vCPE"
218
Scott Bakerc633dc92015-05-05 17:49:46 -0700219 sync_attributes = ("firewall_enable",
220 "firewall_rules",
221 "url_filter_enable",
222 "url_filter_rules",
Scott Baker0c8512b2015-05-20 08:41:38 -0700223 "cdn_enable",
224 "nat_ip",
225 "lan_ip",
226 "wan_ip",
227 "private_ip")
Scott Bakerc633dc92015-05-05 17:49:46 -0700228
Scott Bakere9ff7ce2015-04-14 17:19:16 -0700229 default_attributes = {"firewall_enable": False,
Scott Baker05eb4972015-04-16 21:54:50 -0700230 "firewall_rules": "accept all anywhere anywhere",
231 "url_filter_enable": False,
232 "url_filter_rules": "allow all",
Scott Baker647d45d2015-05-14 20:29:04 -0700233 "url_filter_level": "PG",
Scott Baker05eb4972015-04-16 21:54:50 -0700234 "cdn_enable": False,
Scott Baker20952552015-05-20 16:31:58 -0700235 "sliver_id": None,
Scott Baker4e6d60d2015-05-20 20:45:11 -0700236 "users": [],
237 "bbs_account": None}
Scott Bakere9ff7ce2015-04-14 17:19:16 -0700238
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700239 def __init__(self, *args, **kwargs):
240 super(VCPETenant, self).__init__(*args, **kwargs)
241 self.cached_vbng=None
242 self.cached_sliver=None
243
Scott Bakere9ff7ce2015-04-14 17:19:16 -0700244 @property
245 def image(self):
Scott Baker8c0ae622015-04-20 20:12:59 -0700246 LOOK_FOR_IMAGES=["Ubuntu 14.04 LTS", # portal
247 "Ubuntu-14.04-LTS", # ONOS demo machine
248 ]
249 for image_name in LOOK_FOR_IMAGES:
250 images = Image.objects.filter(name = image_name)
251 if images:
252 return images[0]
253
254 raise XOSProgrammingError("No VPCE image (looked for %s)" % str(LOOK_FOR_IMAGES))
Scott Bakere9ff7ce2015-04-14 17:19:16 -0700255
256 @property
257 def sliver(self):
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700258 if getattr(self, "cached_sliver", None):
259 return self.cached_sliver
Scott Bakere9ff7ce2015-04-14 17:19:16 -0700260 sliver_id=self.get_attribute("sliver_id")
261 if not sliver_id:
262 return None
263 slivers=Sliver.objects.filter(id=sliver_id)
264 if not slivers:
265 return None
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700266 sliver=slivers[0]
Scott Bakerc633dc92015-05-05 17:49:46 -0700267 sliver.caller = self.creator
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700268 self.cached_sliver = sliver
269 return sliver
Scott Bakere9ff7ce2015-04-14 17:19:16 -0700270
271 @sliver.setter
272 def sliver(self, value):
273 if value:
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700274 value = value.id
275 if (value != self.get_attribute("sliver_id", None)):
276 self.cached_sliver=None
277 self.set_attribute("sliver_id", value)
278
279 @property
Scott Bakerc633dc92015-05-05 17:49:46 -0700280 def creator(self):
281 if getattr(self, "cached_creator", None):
282 return self.cached_creator
283 creator_id=self.get_attribute("creator_id")
284 if not creator_id:
285 return None
286 users=User.objects.filter(id=creator_id)
287 if not users:
288 return None
289 user=users[0]
290 self.cached_creator = users[0]
291 return user
292
293 @creator.setter
294 def creator(self, value):
295 if value:
296 value = value.id
297 if (value != self.get_attribute("creator_id", None)):
298 self.cached_creator=None
299 self.set_attribute("creator_id", value)
300
301 @property
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700302 def vbng(self):
303 if getattr(self, "cached_vbng", None):
304 return self.cached_vbng
305 vbng_id=self.get_attribute("vbng_id")
306 if not vbng_id:
307 return None
308 vbngs=VBNGTenant.objects.filter(id=vbng_id)
309 if not vbngs:
310 return None
311 vbng=vbngs[0]
Scott Bakerc633dc92015-05-05 17:49:46 -0700312 vbng.caller = self.creator
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700313 self.cached_vbng = vbng
314 return vbng
315
316 @vbng.setter
317 def vbng(self, value):
318 if value:
319 value = value.id
320 if (value != self.get_attribute("vbng_id", None)):
321 self.cached_vbng=None
322 self.set_attribute("vbng_id", value)
Scott Bakere9ff7ce2015-04-14 17:19:16 -0700323
324 @property
325 def firewall_enable(self):
326 return self.get_attribute("firewall_enable", self.default_attributes["firewall_enable"])
327
328 @firewall_enable.setter
329 def firewall_enable(self, value):
330 self.set_attribute("firewall_enable", value)
331
Scott Baker05eb4972015-04-16 21:54:50 -0700332 @property
333 def firewall_rules(self):
334 return self.get_attribute("firewall_rules", self.default_attributes["firewall_rules"])
335
336 @firewall_rules.setter
337 def firewall_rules(self, value):
338 self.set_attribute("firewall_rules", value)
339
340 @property
341 def url_filter_enable(self):
342 return self.get_attribute("url_filter_enable", self.default_attributes["url_filter_enable"])
343
344 @url_filter_enable.setter
345 def url_filter_enable(self, value):
346 self.set_attribute("url_filter_enable", value)
347
348 @property
Scott Baker647d45d2015-05-14 20:29:04 -0700349 def url_filter_level(self):
350 return self.get_attribute("url_filter_level", self.default_attributes["url_filter_level"])
351
352 @url_filter_level.setter
353 def url_filter_level(self, value):
354 self.set_attribute("url_filter_level", value)
355
356 @property
Scott Baker05eb4972015-04-16 21:54:50 -0700357 def url_filter_rules(self):
358 return self.get_attribute("url_filter_rules", self.default_attributes["url_filter_rules"])
359
360 @url_filter_rules.setter
361 def url_filter_rules(self, value):
362 self.set_attribute("url_filter_rules", value)
363
364 @property
365 def cdn_enable(self):
366 return self.get_attribute("cdn_enable", self.default_attributes["cdn_enable"])
367
368 @cdn_enable.setter
369 def cdn_enable(self, value):
370 self.set_attribute("cdn_enable", value)
371
Scott Baker647d45d2015-05-14 20:29:04 -0700372 @property
373 def users(self):
Scott Baker20952552015-05-20 16:31:58 -0700374 return self.get_attribute("users", self.default_attributes["users"])
Scott Baker647d45d2015-05-14 20:29:04 -0700375
376 @users.setter
377 def users(self, value):
Scott Baker20952552015-05-20 16:31:58 -0700378 self.set_attribute("users", value)
379
Scott Baker4e6d60d2015-05-20 20:45:11 -0700380 @property
381 def bbs_account(self):
382 return self.get_attribute("bbs_account", self.default_attributes["bbs_account"])
383
384 @bbs_account.setter
385 def bbs_account(self, value):
386 return self.set_attribute("bbs_account", value)
387
Scott Baker20952552015-05-20 16:31:58 -0700388 def find_user(self, uid):
389 uid = int(uid)
390 for user in self.users:
391 if user["id"] == uid:
392 return user
393 return None
394
395 def update_user(self, uid, **kwargs):
396 # kwargs may be "level" or "mac"
397 # Setting one of these to None will cause None to be stored in the db
398 uid = int(uid)
399 users = self.users
400 for user in users:
401 if user["id"] == uid:
402 for arg in kwargs.keys():
403 user[arg] = kwargs[arg]
404 self.users = users
405 return
406 raise ValueError("User %d not found" % uid)
407
408 def create_user(self, **kwargs):
Scott Bakerf1e80042015-05-28 19:44:20 -0700409 if "name" not in kwargs:
410 raise XOSMissingField("The name field is required")
411
412 for user in self.users:
413 if kwargs["name"] == user["name"]:
414 raise XOSDuplicateKey("User %s already exists" % kwargs["name"])
415
Scott Baker20952552015-05-20 16:31:58 -0700416 uids = [x["id"] for x in self.users]
417 if uids:
418 uid = max(uids)+1
419 else:
420 uid = 0
421 newuser = kwargs.copy()
422 newuser["id"] = uid
423
424 users = self.users
425 users.append(newuser)
426 self.users = users
427
428 return newuser
429
430 def delete_user(self, uid):
431 uid = int(uid)
432 users = self.users
433 for user in users:
434 if user["id"]==uid:
435 users.remove(user)
436 self.users = users
437 return
438
439 raise ValueError("Users %d not found" % uid)
Scott Baker647d45d2015-05-14 20:29:04 -0700440
441 @property
442 def services(self):
Scott Bakeraa1e96d2015-05-15 14:59:47 -0700443 return {"cdn": self.cdn_enable,
444 "url_filter": self.url_filter_enable,
445 "firewall": self.firewall_enable}
Scott Baker647d45d2015-05-14 20:29:04 -0700446
447 @services.setter
448 def services(self, value):
449 pass
450
Scott Baker5571c692015-05-20 08:19:25 -0700451 @property
452 def addresses(self):
453 if not self.sliver:
454 return {}
455
456 addresses = {}
457 for ns in self.sliver.networkslivers.all():
458 if "lan" in ns.network.name.lower():
459 addresses["lan"] = ns.ip
460 elif "wan" in ns.network.name.lower():
461 addresses["wan"] = ns.ip
462 elif "private" in ns.network.name.lower():
463 addresses["private"] = ns.ip
464 elif "nat" in ns.network.name.lower():
465 addresses["nat"] = ns.ip
466 return addresses
467
Scott Baker432d1402015-05-20 08:25:29 -0700468 @property
469 def nat_ip(self):
470 return self.addresses.get("nat",None)
471
472 @property
473 def lan_ip(self):
474 return self.addresses.get("lan",None)
475
476 @property
477 def wan_ip(self):
478 return self.addresses.get("wan",None)
479
480 @property
481 def private_ip(self):
482 return self.addresses.get("private",None)
483
Scott Bakere9ff7ce2015-04-14 17:19:16 -0700484 def pick_node(self):
485 nodes = list(Node.objects.all())
486 # TODO: logic to filter nodes by which nodes are up, and which
487 # nodes the slice can instantiate on.
488 nodes = sorted(nodes, key=lambda node: node.slivers.all().count())
489 return nodes[0]
490
491 def manage_sliver(self):
Scott Bakerd4b48c02015-04-15 20:59:15 -0700492 # Each VCPE object owns exactly one sliver.
493
Scott Bakere9ff7ce2015-04-14 17:19:16 -0700494 if self.deleted:
495 return
496
Scott Bakere9ff7ce2015-04-14 17:19:16 -0700497 if (self.sliver is not None) and (self.sliver.image != self.image):
498 self.sliver.delete()
499 self.sliver = None
Scott Bakerc633dc92015-05-05 17:49:46 -0700500
Scott Bakere9ff7ce2015-04-14 17:19:16 -0700501 if self.sliver is None:
502 if not self.provider_service.slices.count():
Scott Bakerf6790db2015-05-06 15:46:34 -0700503 raise XOSConfigurationError("The VCPE service has no slices")
Scott Bakere9ff7ce2015-04-14 17:19:16 -0700504
Scott Bakere1f72d12015-05-14 21:48:53 -0700505 flavors = Flavor.objects.filter(name="m1.small")
506 if not flavors:
507 raise XOSConfigurationError("No m1.small flavor")
508
Scott Bakere9ff7ce2015-04-14 17:19:16 -0700509 node =self.pick_node()
510 sliver = Sliver(slice = self.provider_service.slices.all()[0],
511 node = node,
512 image = self.image,
Scott Bakerc633dc92015-05-05 17:49:46 -0700513 creator = self.creator,
Scott Bakere1f72d12015-05-14 21:48:53 -0700514 deployment = node.site_deployment.deployment,
515 flavor = flavors[0])
Scott Bakere9ff7ce2015-04-14 17:19:16 -0700516 sliver.save()
517
Scott Bakerd4b48c02015-04-15 20:59:15 -0700518 try:
519 self.sliver = sliver
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700520 super(VCPETenant, self).save()
Scott Bakerd4b48c02015-04-15 20:59:15 -0700521 except:
522 sliver.delete()
523 raise
Scott Bakere9ff7ce2015-04-14 17:19:16 -0700524
525 def cleanup_sliver(self):
526 if self.sliver:
527 self.sliver.delete()
528 self.sliver = None
529
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700530 def manage_vbng(self):
531 # Each vCPE object owns exactly one vBNG object
532
533 if self.deleted:
534 return
535
536 if self.vbng is None:
537 vbngServices = VBNGService.get_service_objects().all()
538 if not vbngServices:
Scott Baker7f8ef8f2015-04-20 14:24:29 -0700539 raise XOSConfigurationError("No VBNG Services available")
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700540
541 vbng = VBNGTenant(provider_service = vbngServices[0],
542 subscriber_tenant = self)
Scott Bakerc633dc92015-05-05 17:49:46 -0700543 vbng.caller = self.creator
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700544 vbng.save()
545
546 try:
547 self.vbng = vbng
548 super(VCPETenant, self).save()
549 except:
550 vbng.delete()
551 raise
552
553 def cleanup_vbng(self):
554 if self.vbng:
555 self.vbng.delete()
556 self.vbng = None
557
Scott Baker4e6d60d2015-05-20 20:45:11 -0700558 def manage_bbs_account(self):
559 if self.deleted:
560 return
561
Scott Baker642126f2015-05-20 20:57:28 -0700562 if self.url_filter_enable:
563 if not self.bbs_account:
564 # make sure we use the proxied VCPEService object, not the generic Service object
565 vcpe_service = VCPEService.objects.get(id=self.provider_service.id)
566 self.bbs_account = vcpe_service.allocate_bbs_account()
567 super(VCPETenant, self).save()
568 else:
569 if self.bbs_account:
570 self.bbs_account = None
571 super(VCPETenant, self).save()
Scott Baker4e6d60d2015-05-20 20:45:11 -0700572
Scott Bakere9ff7ce2015-04-14 17:19:16 -0700573 def save(self, *args, **kwargs):
Scott Bakerc633dc92015-05-05 17:49:46 -0700574 if not self.creator:
575 if not getattr(self, "caller", None):
576 # caller must be set when creating a vCPE since it creates a slice
Scott Bakerf6790db2015-05-06 15:46:34 -0700577 raise XOSProgrammingError("VCPETenant's self.caller was not set")
Scott Bakerc633dc92015-05-05 17:49:46 -0700578 self.creator = self.caller
579 if not self.creator:
Scott Bakerf6790db2015-05-06 15:46:34 -0700580 raise XOSProgrammingError("VCPETenant's self.creator was not set")
Scott Bakerc633dc92015-05-05 17:49:46 -0700581
Scott Bakere9ff7ce2015-04-14 17:19:16 -0700582 super(VCPETenant, self).save(*args, **kwargs)
Scott Bakerd4b48c02015-04-15 20:59:15 -0700583 self.manage_sliver()
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700584 self.manage_vbng()
Scott Baker4e6d60d2015-05-20 20:45:11 -0700585 self.manage_bbs_account()
Scott Bakere9ff7ce2015-04-14 17:19:16 -0700586
587 def delete(self, *args, **kwargs):
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700588 self.cleanup_vbng()
Scott Bakere9ff7ce2015-04-14 17:19:16 -0700589 self.cleanup_sliver()
590 super(VCPETenant, self).delete(*args, **kwargs)
591
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700592#----------------------------------------------------------------------------
593# vBNG
594#----------------------------------------------------------------------------
595
596class VBNGService(Service):
597 KIND = "vBNG"
598
599 class Meta:
600 app_label = "cord"
601 verbose_name = "vBNG Service"
602 proxy = True
603
604class VBNGTenant(Tenant):
605 class Meta:
606 proxy = True
607
608 KIND = "vBNG"
609
610 default_attributes = {"routeable_subnet": ""}
611
612 @property
613 def routeable_subnet(self):
614 return self.get_attribute("routeable_subnet", self.default_attributes["routeable_subnet"])
615
616 @routeable_subnet.setter
617 def routeable_subnet(self, value):
618 self.set_attribute("routeable_subnet", value)