Scott Baker | 1b24161 | 2015-04-14 17:19:16 -0700 | [diff] [blame] | 1 | from django.db import models |
Scott Baker | 9c8a2c7 | 2015-05-05 17:49:46 -0700 | [diff] [blame^] | 2 | from core.models import Service, PlCoreBase, Slice, Sliver, Tenant, Node, Image, User |
Scott Baker | 1b24161 | 2015-04-14 17:19:16 -0700 | [diff] [blame] | 3 | from core.models.plcorebase import StrippedCharField |
| 4 | import os |
| 5 | from django.db import models |
| 6 | from django.forms.models import model_to_dict |
| 7 | from django.db.models import Q |
| 8 | from operator import itemgetter, attrgetter, methodcaller |
Scott Baker | 697fb0b | 2015-04-20 09:16:17 -0700 | [diff] [blame] | 9 | import traceback |
Scott Baker | d921e1c | 2015-04-20 14:24:29 -0700 | [diff] [blame] | 10 | from xos.exceptions import * |
Scott Baker | 1b24161 | 2015-04-14 17:19:16 -0700 | [diff] [blame] | 11 | |
| 12 | """ |
| 13 | import os |
| 14 | import sys |
| 15 | sys.path.append("/opt/xos") |
| 16 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "xos.settings") |
| 17 | import django |
| 18 | from core.models import *
|
| 19 | from hpc.models import *
|
| 20 | from cord.models import *
|
| 21 | django.setup() |
Scott Baker | 1b24161 | 2015-04-14 17:19:16 -0700 | [diff] [blame] | 22 | |
Scott Baker | 557aada | 2015-04-20 09:48:34 -0700 | [diff] [blame] | 23 | t = VOLTTenant() |
Scott Baker | 1b24161 | 2015-04-14 17:19:16 -0700 | [diff] [blame] | 24 | t.caller = User.objects.all()[0] |
| 25 | t.save() |
| 26 | |
Scott Baker | 39b0d89 | 2015-04-15 20:59:15 -0700 | [diff] [blame] | 27 | for v in VOLTTenant.objects.all(): |
| 28 | v.caller = User.objects.all()[0] |
| 29 | v.delete() |
| 30 | |
Scott Baker | 1b24161 | 2015-04-14 17:19:16 -0700 | [diff] [blame] | 31 | for v in VCPETenant.objects.all(): |
| 32 | v.caller = User.objects.all()[0] |
| 33 | v.delete() |
Scott Baker | 697fb0b | 2015-04-20 09:16:17 -0700 | [diff] [blame] | 34 | |
| 35 | for v in VOLTTenant.objects.all(): |
| 36 | v.caller = User.objects.all()[0] |
| 37 | v.delete() |
Scott Baker | 9c8a2c7 | 2015-05-05 17:49:46 -0700 | [diff] [blame^] | 38 | |
| 39 | for v in VOLTTenant.objects.all(): |
| 40 | if not v.creator: |
| 41 | v.creator= User.objects.all()[0] |
| 42 | v.save() |
| 43 | |
| 44 | for v in VCPETenant.objects.all(): |
| 45 | if not v.creator: |
| 46 | v.creator= User.objects.all()[0] |
| 47 | v.save() |
Scott Baker | 1b24161 | 2015-04-14 17:19:16 -0700 | [diff] [blame] | 48 | """ |
| 49 | |
| 50 | class ConfigurationError(Exception): |
| 51 | pass |
| 52 | |
Scott Baker | 39b0d89 | 2015-04-15 20:59:15 -0700 | [diff] [blame] | 53 | # ------------------------------------------- |
| 54 | # VOLT |
| 55 | # ------------------------------------------- |
| 56 | |
| 57 | class VOLTService(Service): |
| 58 | KIND = "vOLT" |
| 59 | |
Scott Baker | 1b24161 | 2015-04-14 17:19:16 -0700 | [diff] [blame] | 60 | class Meta: |
Scott Baker | 39b0d89 | 2015-04-15 20:59:15 -0700 | [diff] [blame] | 61 | app_label = "cord" |
| 62 | verbose_name = "vOLT Service" |
| 63 | proxy = True |
| 64 | |
| 65 | class VOLTTenant(Tenant): |
| 66 | class Meta: |
| 67 | proxy = True |
| 68 | |
| 69 | KIND = "vOLT" |
| 70 | |
Scott Baker | e744c7b | 2015-04-20 11:50:09 -0700 | [diff] [blame] | 71 | default_attributes = {"vlan_id": None, } |
| 72 | |
Scott Baker | 557aada | 2015-04-20 09:48:34 -0700 | [diff] [blame] | 73 | 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 Baker | 39b0d89 | 2015-04-15 20:59:15 -0700 | [diff] [blame] | 79 | @property |
Scott Baker | e744c7b | 2015-04-20 11:50:09 -0700 | [diff] [blame] | 80 | 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 Baker | 39b0d89 | 2015-04-15 20:59:15 -0700 | [diff] [blame] | 88 | def vcpe(self): |
Scott Baker | 697fb0b | 2015-04-20 09:16:17 -0700 | [diff] [blame] | 89 | if getattr(self, "cached_vcpe", None): |
| 90 | return self.cached_vcpe |
Scott Baker | 39b0d89 | 2015-04-15 20:59:15 -0700 | [diff] [blame] | 91 | 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 Baker | 697fb0b | 2015-04-20 09:16:17 -0700 | [diff] [blame] | 97 | vcpe=vcpes[0] |
Scott Baker | 9c8a2c7 | 2015-05-05 17:49:46 -0700 | [diff] [blame^] | 98 | vcpe.caller = self.creator |
Scott Baker | 697fb0b | 2015-04-20 09:16:17 -0700 | [diff] [blame] | 99 | self.cached_vcpe = vcpe |
| 100 | return vcpe |
Scott Baker | 39b0d89 | 2015-04-15 20:59:15 -0700 | [diff] [blame] | 101 | |
| 102 | @vcpe.setter |
| 103 | def vcpe(self, value): |
| 104 | if value: |
Scott Baker | 697fb0b | 2015-04-20 09:16:17 -0700 | [diff] [blame] | 105 | 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 Baker | 39b0d89 | 2015-04-15 20:59:15 -0700 | [diff] [blame] | 109 | |
Scott Baker | 9c8a2c7 | 2015-05-05 17:49:46 -0700 | [diff] [blame^] | 110 | @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 Baker | 39b0d89 | 2015-04-15 20:59:15 -0700 | [diff] [blame] | 132 | 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 Baker | d921e1c | 2015-04-20 14:24:29 -0700 | [diff] [blame] | 141 | raise XOSConfigurationError("No VCPE Services available") |
Scott Baker | 39b0d89 | 2015-04-15 20:59:15 -0700 | [diff] [blame] | 142 | |
| 143 | vcpe = VCPETenant(provider_service = vcpeServices[0], |
| 144 | subscriber_tenant = self) |
Scott Baker | 9c8a2c7 | 2015-05-05 17:49:46 -0700 | [diff] [blame^] | 145 | vcpe.caller = self.creator |
Scott Baker | 39b0d89 | 2015-04-15 20:59:15 -0700 | [diff] [blame] | 146 | vcpe.save() |
| 147 | |
| 148 | try: |
| 149 | self.vcpe = vcpe |
Scott Baker | 697fb0b | 2015-04-20 09:16:17 -0700 | [diff] [blame] | 150 | super(VOLTTenant, self).save() |
Scott Baker | 39b0d89 | 2015-04-15 20:59:15 -0700 | [diff] [blame] | 151 | 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 Baker | d921e1c | 2015-04-20 14:24:29 -0700 | [diff] [blame] | 161 | self.validate_unique_service_specific_id() |
| 162 | |
Scott Baker | 9c8a2c7 | 2015-05-05 17:49:46 -0700 | [diff] [blame^] | 163 | 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 Baker | 39b0d89 | 2015-04-15 20:59:15 -0700 | [diff] [blame] | 171 | 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 | |
| 182 | class VCPEService(Service): |
| 183 | KIND = "vCPE" |
| 184 | |
| 185 | class Meta: |
| 186 | app_label = "cord" |
Scott Baker | 1b24161 | 2015-04-14 17:19:16 -0700 | [diff] [blame] | 187 | verbose_name = "vCPE Service" |
Scott Baker | 39b0d89 | 2015-04-15 20:59:15 -0700 | [diff] [blame] | 188 | proxy = True |
Scott Baker | 1b24161 | 2015-04-14 17:19:16 -0700 | [diff] [blame] | 189 | |
| 190 | class VCPETenant(Tenant): |
| 191 | class Meta: |
| 192 | proxy = True |
| 193 | |
Scott Baker | 39b0d89 | 2015-04-15 20:59:15 -0700 | [diff] [blame] | 194 | KIND = "vCPE" |
| 195 | |
Scott Baker | 9c8a2c7 | 2015-05-05 17:49:46 -0700 | [diff] [blame^] | 196 | sync_attributes = ("firewall_enable", |
| 197 | "firewall_rules", |
| 198 | "url_filter_enable", |
| 199 | "url_filter_rules", |
| 200 | "cdn_enable") |
| 201 | |
Scott Baker | 1b24161 | 2015-04-14 17:19:16 -0700 | [diff] [blame] | 202 | default_attributes = {"firewall_enable": False, |
Scott Baker | 0bcbb96 | 2015-04-16 21:54:50 -0700 | [diff] [blame] | 203 | "firewall_rules": "accept all anywhere anywhere", |
| 204 | "url_filter_enable": False, |
| 205 | "url_filter_rules": "allow all", |
| 206 | "cdn_enable": False, |
Scott Baker | 1b24161 | 2015-04-14 17:19:16 -0700 | [diff] [blame] | 207 | "sliver_id": None} |
| 208 | |
Scott Baker | 697fb0b | 2015-04-20 09:16:17 -0700 | [diff] [blame] | 209 | def __init__(self, *args, **kwargs): |
| 210 | super(VCPETenant, self).__init__(*args, **kwargs) |
| 211 | self.cached_vbng=None |
| 212 | self.cached_sliver=None |
| 213 | |
Scott Baker | 1b24161 | 2015-04-14 17:19:16 -0700 | [diff] [blame] | 214 | @property |
| 215 | def image(self): |
Scott Baker | 4f751bd | 2015-04-20 20:12:59 -0700 | [diff] [blame] | 216 | 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 Baker | 1b24161 | 2015-04-14 17:19:16 -0700 | [diff] [blame] | 225 | |
| 226 | @property |
| 227 | def sliver(self): |
Scott Baker | 697fb0b | 2015-04-20 09:16:17 -0700 | [diff] [blame] | 228 | if getattr(self, "cached_sliver", None): |
| 229 | return self.cached_sliver |
Scott Baker | 1b24161 | 2015-04-14 17:19:16 -0700 | [diff] [blame] | 230 | 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 Baker | 697fb0b | 2015-04-20 09:16:17 -0700 | [diff] [blame] | 236 | sliver=slivers[0] |
Scott Baker | 9c8a2c7 | 2015-05-05 17:49:46 -0700 | [diff] [blame^] | 237 | sliver.caller = self.creator |
Scott Baker | 697fb0b | 2015-04-20 09:16:17 -0700 | [diff] [blame] | 238 | self.cached_sliver = sliver |
| 239 | return sliver |
Scott Baker | 1b24161 | 2015-04-14 17:19:16 -0700 | [diff] [blame] | 240 | |
| 241 | @sliver.setter |
| 242 | def sliver(self, value): |
| 243 | if value: |
Scott Baker | 697fb0b | 2015-04-20 09:16:17 -0700 | [diff] [blame] | 244 | 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 Baker | 9c8a2c7 | 2015-05-05 17:49:46 -0700 | [diff] [blame^] | 250 | 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 Baker | 697fb0b | 2015-04-20 09:16:17 -0700 | [diff] [blame] | 272 | 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 Baker | 9c8a2c7 | 2015-05-05 17:49:46 -0700 | [diff] [blame^] | 282 | vbng.caller = self.creator |
Scott Baker | 697fb0b | 2015-04-20 09:16:17 -0700 | [diff] [blame] | 283 | 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 Baker | 1b24161 | 2015-04-14 17:19:16 -0700 | [diff] [blame] | 293 | |
| 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 Baker | 0bcbb96 | 2015-04-16 21:54:50 -0700 | [diff] [blame] | 302 | @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 Baker | 1b24161 | 2015-04-14 17:19:16 -0700 | [diff] [blame] | 334 | 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 Baker | 39b0d89 | 2015-04-15 20:59:15 -0700 | [diff] [blame] | 342 | # Each VCPE object owns exactly one sliver. |
| 343 | |
Scott Baker | 1b24161 | 2015-04-14 17:19:16 -0700 | [diff] [blame] | 344 | if self.deleted: |
| 345 | return |
| 346 | |
Scott Baker | 1b24161 | 2015-04-14 17:19:16 -0700 | [diff] [blame] | 347 | if (self.sliver is not None) and (self.sliver.image != self.image): |
| 348 | self.sliver.delete() |
| 349 | self.sliver = None |
Scott Baker | 9c8a2c7 | 2015-05-05 17:49:46 -0700 | [diff] [blame^] | 350 | |
Scott Baker | 1b24161 | 2015-04-14 17:19:16 -0700 | [diff] [blame] | 351 | if self.sliver is None: |
| 352 | if not self.provider_service.slices.count(): |
Scott Baker | d921e1c | 2015-04-20 14:24:29 -0700 | [diff] [blame] | 353 | raise XOSConfigurationError("The VCPE service has no slicers") |
Scott Baker | 1b24161 | 2015-04-14 17:19:16 -0700 | [diff] [blame] | 354 | |
| 355 | node =self.pick_node() |
| 356 | sliver = Sliver(slice = self.provider_service.slices.all()[0], |
| 357 | node = node, |
| 358 | image = self.image, |
Scott Baker | 9c8a2c7 | 2015-05-05 17:49:46 -0700 | [diff] [blame^] | 359 | creator = self.creator, |
Scott Baker | 1b24161 | 2015-04-14 17:19:16 -0700 | [diff] [blame] | 360 | deployment = node.site_deployment.deployment) |
| 361 | sliver.save() |
| 362 | |
Scott Baker | 39b0d89 | 2015-04-15 20:59:15 -0700 | [diff] [blame] | 363 | try: |
| 364 | self.sliver = sliver |
Scott Baker | 697fb0b | 2015-04-20 09:16:17 -0700 | [diff] [blame] | 365 | super(VCPETenant, self).save() |
Scott Baker | 39b0d89 | 2015-04-15 20:59:15 -0700 | [diff] [blame] | 366 | except: |
| 367 | sliver.delete() |
| 368 | raise |
Scott Baker | 1b24161 | 2015-04-14 17:19:16 -0700 | [diff] [blame] | 369 | |
| 370 | def cleanup_sliver(self): |
| 371 | if self.sliver: |
| 372 | self.sliver.delete() |
| 373 | self.sliver = None |
| 374 | |
Scott Baker | 697fb0b | 2015-04-20 09:16:17 -0700 | [diff] [blame] | 375 | 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 Baker | d921e1c | 2015-04-20 14:24:29 -0700 | [diff] [blame] | 384 | raise XOSConfigurationError("No VBNG Services available") |
Scott Baker | 697fb0b | 2015-04-20 09:16:17 -0700 | [diff] [blame] | 385 | |
| 386 | vbng = VBNGTenant(provider_service = vbngServices[0], |
| 387 | subscriber_tenant = self) |
Scott Baker | 9c8a2c7 | 2015-05-05 17:49:46 -0700 | [diff] [blame^] | 388 | vbng.caller = self.creator |
Scott Baker | 697fb0b | 2015-04-20 09:16:17 -0700 | [diff] [blame] | 389 | 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 Baker | 1b24161 | 2015-04-14 17:19:16 -0700 | [diff] [blame] | 403 | def save(self, *args, **kwargs): |
Scott Baker | 9c8a2c7 | 2015-05-05 17:49:46 -0700 | [diff] [blame^] | 404 | 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 Baker | 1b24161 | 2015-04-14 17:19:16 -0700 | [diff] [blame] | 412 | super(VCPETenant, self).save(*args, **kwargs) |
Scott Baker | 39b0d89 | 2015-04-15 20:59:15 -0700 | [diff] [blame] | 413 | self.manage_sliver() |
Scott Baker | 697fb0b | 2015-04-20 09:16:17 -0700 | [diff] [blame] | 414 | self.manage_vbng() |
Scott Baker | 1b24161 | 2015-04-14 17:19:16 -0700 | [diff] [blame] | 415 | |
| 416 | def delete(self, *args, **kwargs): |
Scott Baker | 697fb0b | 2015-04-20 09:16:17 -0700 | [diff] [blame] | 417 | self.cleanup_vbng() |
Scott Baker | 1b24161 | 2015-04-14 17:19:16 -0700 | [diff] [blame] | 418 | self.cleanup_sliver() |
| 419 | super(VCPETenant, self).delete(*args, **kwargs) |
| 420 | |
Scott Baker | 697fb0b | 2015-04-20 09:16:17 -0700 | [diff] [blame] | 421 | #---------------------------------------------------------------------------- |
| 422 | # vBNG |
| 423 | #---------------------------------------------------------------------------- |
| 424 | |
| 425 | class VBNGService(Service): |
| 426 | KIND = "vBNG" |
| 427 | |
| 428 | class Meta: |
| 429 | app_label = "cord" |
| 430 | verbose_name = "vBNG Service" |
| 431 | proxy = True |
| 432 | |
| 433 | class 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) |