blob: 5e7bdd575e9b09dfbf2d0613f1c13bc34530de15 [file] [log] [blame]
Scott Baker1b241612015-04-14 17:19:16 -07001from django.db import models
Scott Bakerf08823d2015-07-06 16:50:30 -07002from core.models import Service, PlCoreBase, Slice, Sliver, Tenant, Node, Image, User, Flavor, Subscriber
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 Baker2b29a312015-05-11 08:31:24 -070027for v in VOLTTenant.get_tenant_objects().all():
Scott Baker39b0d892015-04-15 20:59:15 -070028 v.caller = User.objects.all()[0]
29 v.delete()
30
Scott Baker2b29a312015-05-11 08:31:24 -070031for v in VCPETenant.get_tenant_objects().all():
Scott Baker1b241612015-04-14 17:19:16 -070032 v.caller = User.objects.all()[0]
33 v.delete()
Scott Baker697fb0b2015-04-20 09:16:17 -070034
Scott Baker2b29a312015-05-11 08:31:24 -070035for v in VOLTTenant.get_tenant_objects().all():
Scott Baker697fb0b2015-04-20 09:16:17 -070036 v.caller = User.objects.all()[0]
37 v.delete()
Scott Baker9c8a2c72015-05-05 17:49:46 -070038
Scott Baker2b29a312015-05-11 08:31:24 -070039for v in VOLTTenant.get_tenant_objects().all():
Scott Baker9c8a2c72015-05-05 17:49:46 -070040 if not v.creator:
41 v.creator= User.objects.all()[0]
42 v.save()
43
Scott Baker2b29a312015-05-11 08:31:24 -070044for v in VCPETenant.get_tenant_objects().all():
Scott Baker9c8a2c72015-05-05 17:49:46 -070045 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 Baker361c86c2015-07-06 14:38:02 -070053VOLT_KIND = "vOLT"
54VCPE_KIND = "vCPE"
55VBNG_KIND = "vBNG"
Scott Bakerf08823d2015-07-06 16:50:30 -070056CORD_SUBSCRIBER_KIND = "CordSubscriberRoot"
57
58# -------------------------------------------
59# CordSubscriberRoot
60# -------------------------------------------
61
62class CordSubscriberRoot(Subscriber):
63 KIND = CORD_SUBSCRIBER_KIND
64
65 default_attributes = {"firewall_enable": False,
66 "firewall_rules": "accept all anywhere anywhere",
67 "url_filter_enable": False,
68 "url_filter_rules": "allow all",
69 "url_filter_level": "PG",
70 "cdn_enable": False,
71 "users": [] }
72
73 def __init__(self, *args, **kwargs):
74 super(CordSubscriberRoot, self).__init__(*args, **kwargs)
75 self.cached_volt = None
76
77 @property
78 def volt(self):
79 volt = self.get_newest_subscribed_tenant(VOLTTenant)
80 if not volt:
81 return None
82
83 # always return the same object when possible
84 if (self.cached_volt) and (self.cached_volt.id == volt.id):
85 return self.cached_vcpe
86
87 vcpe.caller = self.creator
88 self.cached_volt = volt
89 return volt
90
91 @property
92 def firewall_enable(self):
93 return self.get_attribute("firewall_enable", self.default_attributes["firewall_enable"])
94
95 @firewall_enable.setter
96 def firewall_enable(self, value):
97 self.set_attribute("firewall_enable", value)
98
99 @property
100 def firewall_rules(self):
101 return self.get_attribute("firewall_rules", self.default_attributes["firewall_rules"])
102
103 @firewall_rules.setter
104 def firewall_rules(self, value):
105 self.set_attribute("firewall_rules", value)
106
107 @property
108 def url_filter_enable(self):
109 return self.get_attribute("url_filter_enable", self.default_attributes["url_filter_enable"])
110
111 @url_filter_enable.setter
112 def url_filter_enable(self, value):
113 self.set_attribute("url_filter_enable", value)
114
115 @property
116 def url_filter_level(self):
117 return self.get_attribute("url_filter_level", self.default_attributes["url_filter_level"])
118
119 @url_filter_level.setter
120 def url_filter_level(self, value):
121 self.set_attribute("url_filter_level", value)
122
123 @property
124 def url_filter_rules(self):
125 return self.get_attribute("url_filter_rules", self.default_attributes["url_filter_rules"])
126
127 @url_filter_rules.setter
128 def url_filter_rules(self, value):
129 self.set_attribute("url_filter_rules", value)
130
131 @property
132 def cdn_enable(self):
133 return self.get_attribute("cdn_enable", self.default_attributes["cdn_enable"])
134
135 @cdn_enable.setter
136 def cdn_enable(self, value):
137 self.set_attribute("cdn_enable", value)
138
139 @property
140 def users(self):
141 return self.get_attribute("users", self.default_attributes["users"])
142
143 @users.setter
144 def users(self, value):
145 self.set_attribute("users", value)
146
147 def find_user(self, uid):
148 uid = int(uid)
149 for user in self.users:
150 if user["id"] == uid:
151 return user
152 return None
153
154 def update_user(self, uid, **kwargs):
155 # kwargs may be "level" or "mac"
156 # Setting one of these to None will cause None to be stored in the db
157 uid = int(uid)
158 users = self.users
159 for user in users:
160 if user["id"] == uid:
161 for arg in kwargs.keys():
162 user[arg] = kwargs[arg]
163 self.users = users
164 return user
165 raise ValueError("User %d not found" % uid)
166
167 def create_user(self, **kwargs):
168 if "name" not in kwargs:
169 raise XOSMissingField("The name field is required")
170
171 for user in self.users:
172 if kwargs["name"] == user["name"]:
173 raise XOSDuplicateKey("User %s already exists" % kwargs["name"])
174
175 uids = [x["id"] for x in self.users]
176 if uids:
177 uid = max(uids)+1
178 else:
179 uid = 0
180 newuser = kwargs.copy()
181 newuser["id"] = uid
182
183 users = self.users
184 users.append(newuser)
185 self.users = users
186
187 return newuser
188
189 def delete_user(self, uid):
190 uid = int(uid)
191 users = self.users
192 for user in users:
193 if user["id"]==uid:
194 users.remove(user)
195 self.users = users
196 return
197
198 raise ValueError("Users %d not found" % uid)
199
200 @property
201 def services(self):
202 return {"cdn": self.cdn_enable,
203 "url_filter": self.url_filter_enable,
204 "firewall": self.firewall_enable}
205
206 @services.setter
207 def services(self, value):
208 pass
Scott Baker361c86c2015-07-06 14:38:02 -0700209
Scott Baker39b0d892015-04-15 20:59:15 -0700210# -------------------------------------------
211# VOLT
212# -------------------------------------------
213
214class VOLTService(Service):
Scott Baker361c86c2015-07-06 14:38:02 -0700215 KIND = VOLT_KIND
Scott Baker39b0d892015-04-15 20:59:15 -0700216
Scott Baker1b241612015-04-14 17:19:16 -0700217 class Meta:
Scott Baker39b0d892015-04-15 20:59:15 -0700218 app_label = "cord"
219 verbose_name = "vOLT Service"
220 proxy = True
221
222class VOLTTenant(Tenant):
223 class Meta:
224 proxy = True
225
Scott Baker361c86c2015-07-06 14:38:02 -0700226 KIND = VOLT_KIND
Scott Baker39b0d892015-04-15 20:59:15 -0700227
Scott Baker664c4282015-05-28 17:12:00 -0700228 default_attributes = {"vlan_id": None,
229 "is_demo_user": False }
Scott Bakere744c7b2015-04-20 11:50:09 -0700230
Scott Baker557aada2015-04-20 09:48:34 -0700231 def __init__(self, *args, **kwargs):
232 volt_services = VOLTService.get_service_objects().all()
233 if volt_services:
234 self._meta.get_field("provider_service").default = volt_services[0].id
235 super(VOLTTenant, self).__init__(*args, **kwargs)
Scott Baker361c86c2015-07-06 14:38:02 -0700236 self.cached_vcpe = None
Scott Baker5e76f802015-06-24 12:54:24 -0700237
Scott Baker39b0d892015-04-15 20:59:15 -0700238 @property
Scott Bakere744c7b2015-04-20 11:50:09 -0700239 def vlan_id(self):
240 return self.get_attribute("vlan_id", self.default_attributes["vlan_id"])
241
242 @vlan_id.setter
243 def vlan_id(self, value):
244 self.set_attribute("vlan_id", value)
245
246 @property
Scott Baker39b0d892015-04-15 20:59:15 -0700247 def vcpe(self):
Scott Baker361c86c2015-07-06 14:38:02 -0700248 vcpe = self.get_newest_subscribed_tenant(VCPETenant)
249 if not vcpe:
250 return None
251
252 # always return the same object when possible
253 if (self.cached_vcpe) and (self.cached_vcpe.id == vcpe.id):
Scott Baker697fb0b2015-04-20 09:16:17 -0700254 return self.cached_vcpe
Scott Baker361c86c2015-07-06 14:38:02 -0700255
Scott Baker9c8a2c72015-05-05 17:49:46 -0700256 vcpe.caller = self.creator
Scott Baker697fb0b2015-04-20 09:16:17 -0700257 self.cached_vcpe = vcpe
258 return vcpe
Scott Baker39b0d892015-04-15 20:59:15 -0700259
260 @vcpe.setter
261 def vcpe(self, value):
Scott Baker361c86c2015-07-06 14:38:02 -0700262 raise XOSConfigurationError("vOLT.vCPE cannot be set this way -- create a new vCPE object and set it's subscriber_tenant instead")
Scott Baker39b0d892015-04-15 20:59:15 -0700263
Scott Baker9c8a2c72015-05-05 17:49:46 -0700264 @property
265 def creator(self):
266 if getattr(self, "cached_creator", None):
267 return self.cached_creator
268 creator_id=self.get_attribute("creator_id")
269 if not creator_id:
270 return None
271 users=User.objects.filter(id=creator_id)
272 if not users:
273 return None
274 user=users[0]
275 self.cached_creator = users[0]
276 return user
277
278 @creator.setter
279 def creator(self, value):
280 if value:
281 value = value.id
282 if (value != self.get_attribute("creator_id", None)):
283 self.cached_creator=None
284 self.set_attribute("creator_id", value)
285
Scott Baker664c4282015-05-28 17:12:00 -0700286 @property
287 def is_demo_user(self):
288 return self.get_attribute("is_demo_user", self.default_attributes["is_demo_user"])
289
290 @is_demo_user.setter
291 def is_demo_user(self, value):
292 self.set_attribute("is_demo_user", value)
293
Scott Baker39b0d892015-04-15 20:59:15 -0700294 def manage_vcpe(self):
295 # Each VOLT object owns exactly one VCPE object
296
297 if self.deleted:
298 return
299
300 if self.vcpe is None:
301 vcpeServices = VCPEService.get_service_objects().all()
302 if not vcpeServices:
Scott Bakerd921e1c2015-04-20 14:24:29 -0700303 raise XOSConfigurationError("No VCPE Services available")
Scott Baker39b0d892015-04-15 20:59:15 -0700304
305 vcpe = VCPETenant(provider_service = vcpeServices[0],
306 subscriber_tenant = self)
Scott Baker9c8a2c72015-05-05 17:49:46 -0700307 vcpe.caller = self.creator
Scott Baker39b0d892015-04-15 20:59:15 -0700308 vcpe.save()
309
Scott Baker39b0d892015-04-15 20:59:15 -0700310 def cleanup_vcpe(self):
311 if self.vcpe:
Scott Baker361c86c2015-07-06 14:38:02 -0700312 # print "XXX cleanup vcpe", self.vcpe
Scott Baker39b0d892015-04-15 20:59:15 -0700313 self.vcpe.delete()
Scott Baker39b0d892015-04-15 20:59:15 -0700314
Scott Baker5e76f802015-06-24 12:54:24 -0700315 def cleanup_orphans(self):
Scott Baker361c86c2015-07-06 14:38:02 -0700316 # ensure vOLT only has one vCPE
317 cur_vcpe = self.vcpe
318 for vcpe in list(self.get_subscribed_tenants(VCPETenant)):
319 if (not cur_vcpe) or (vcpe.id != cur_vcpe.id):
320 # print "XXX clean up orphaned vcpe", vcpe
321 vcpe.delete()
Scott Baker5e76f802015-06-24 12:54:24 -0700322
Scott Baker39b0d892015-04-15 20:59:15 -0700323 def save(self, *args, **kwargs):
Scott Bakerd921e1c2015-04-20 14:24:29 -0700324 self.validate_unique_service_specific_id()
325
Scott Baker9c8a2c72015-05-05 17:49:46 -0700326 if not self.creator:
327 if not getattr(self, "caller", None):
328 # caller must be set when creating a vCPE since it creates a slice
329 raise XOSProgrammingError("VOLTTenant's self.caller was not set")
330 self.creator = self.caller
331 if not self.creator:
332 raise XOSProgrammingError("VOLTTenant's self.creator was not set")
333
Scott Baker39b0d892015-04-15 20:59:15 -0700334 super(VOLTTenant, self).save(*args, **kwargs)
335 self.manage_vcpe()
Scott Baker5e76f802015-06-24 12:54:24 -0700336 self.cleanup_orphans()
Scott Baker39b0d892015-04-15 20:59:15 -0700337
338 def delete(self, *args, **kwargs):
339 self.cleanup_vcpe()
340 super(VOLTTenant, self).delete(*args, **kwargs)
341
342# -------------------------------------------
343# VCPE
344# -------------------------------------------
345
346class VCPEService(Service):
Scott Baker361c86c2015-07-06 14:38:02 -0700347 KIND = VCPE_KIND
Scott Baker39b0d892015-04-15 20:59:15 -0700348
349 class Meta:
350 app_label = "cord"
Scott Baker1b241612015-04-14 17:19:16 -0700351 verbose_name = "vCPE Service"
Scott Baker39b0d892015-04-15 20:59:15 -0700352 proxy = True
Scott Baker1b241612015-04-14 17:19:16 -0700353
Scott Baker5c8abf82015-05-20 20:45:11 -0700354 def allocate_bbs_account(self):
355 vcpes = VCPETenant.get_tenant_objects().all()
356 bbs_accounts = [vcpe.bbs_account for vcpe in vcpes]
357
358 # There's a bit of a race here; some other user could be trying to
359 # allocate a bbs_account at the same time we are.
360
Scott Bakerf4f61ca2015-06-09 12:03:56 -0700361 for i in range(2,21):
Scott Baker5c8abf82015-05-20 20:45:11 -0700362 account_name = "bbs%02d@onlab.us" % i
363 if (account_name not in bbs_accounts):
364 return account_name
365
366 raise XOSConfigurationError("We've run out of available broadbandshield accounts. Delete some vcpe and try again.")
367
Scott Baker1b241612015-04-14 17:19:16 -0700368class VCPETenant(Tenant):
369 class Meta:
370 proxy = True
371
Scott Baker361c86c2015-07-06 14:38:02 -0700372 KIND = VCPE_KIND
Scott Baker39b0d892015-04-15 20:59:15 -0700373
Scott Baker9c8a2c72015-05-05 17:49:46 -0700374 sync_attributes = ("firewall_enable",
375 "firewall_rules",
376 "url_filter_enable",
377 "url_filter_rules",
Scott Bakerc7a96c82015-05-20 08:41:38 -0700378 "cdn_enable",
379 "nat_ip",
380 "lan_ip",
381 "wan_ip",
Scott Baker710ad052015-06-04 10:26:44 -0700382 "private_ip",
Scott Baker3f4fe402015-06-05 12:08:34 -0700383 "hpc_client_ip",
384 "wan_mac")
Scott Baker9c8a2c72015-05-05 17:49:46 -0700385
Scott Baker1b241612015-04-14 17:19:16 -0700386 default_attributes = {"firewall_enable": False,
Scott Baker0bcbb962015-04-16 21:54:50 -0700387 "firewall_rules": "accept all anywhere anywhere",
388 "url_filter_enable": False,
389 "url_filter_rules": "allow all",
Scott Baker8d13a982015-05-14 20:29:04 -0700390 "url_filter_level": "PG",
Scott Baker0bcbb962015-04-16 21:54:50 -0700391 "cdn_enable": False,
Scott Bakera0cf9612015-05-20 16:31:58 -0700392 "sliver_id": None,
Scott Baker5c8abf82015-05-20 20:45:11 -0700393 "users": [],
Scott Bakerd40a42d2015-06-09 12:22:29 -0700394 "bbs_account": None,
395 "last_ansible_hash": None}
Scott Baker1b241612015-04-14 17:19:16 -0700396
Scott Baker697fb0b2015-04-20 09:16:17 -0700397 def __init__(self, *args, **kwargs):
398 super(VCPETenant, self).__init__(*args, **kwargs)
399 self.cached_vbng=None
400 self.cached_sliver=None
Scott Baker5e76f802015-06-24 12:54:24 -0700401 self.orig_sliver_id = self.get_initial_attribute("sliver_id")
Scott Baker697fb0b2015-04-20 09:16:17 -0700402
Scott Baker1b241612015-04-14 17:19:16 -0700403 @property
404 def image(self):
Andy Bavieracf02052015-06-10 15:59:04 -0400405 LOOK_FOR_IMAGES=["ubuntu-vcpe3", # ONOS demo machine -- preferred vcpe image
Scott Baker2c4f1eb2015-06-02 16:03:30 -0700406 "Ubuntu 14.04 LTS", # portal
Scott Baker4f751bd2015-04-20 20:12:59 -0700407 "Ubuntu-14.04-LTS", # ONOS demo machine
408 ]
409 for image_name in LOOK_FOR_IMAGES:
410 images = Image.objects.filter(name = image_name)
411 if images:
412 return images[0]
413
414 raise XOSProgrammingError("No VPCE image (looked for %s)" % str(LOOK_FOR_IMAGES))
Scott Baker1b241612015-04-14 17:19:16 -0700415
416 @property
417 def sliver(self):
Scott Baker697fb0b2015-04-20 09:16:17 -0700418 if getattr(self, "cached_sliver", None):
419 return self.cached_sliver
Scott Baker1b241612015-04-14 17:19:16 -0700420 sliver_id=self.get_attribute("sliver_id")
421 if not sliver_id:
422 return None
423 slivers=Sliver.objects.filter(id=sliver_id)
424 if not slivers:
425 return None
Scott Baker697fb0b2015-04-20 09:16:17 -0700426 sliver=slivers[0]
Scott Baker9c8a2c72015-05-05 17:49:46 -0700427 sliver.caller = self.creator
Scott Baker697fb0b2015-04-20 09:16:17 -0700428 self.cached_sliver = sliver
429 return sliver
Scott Baker1b241612015-04-14 17:19:16 -0700430
431 @sliver.setter
432 def sliver(self, value):
433 if value:
Scott Baker697fb0b2015-04-20 09:16:17 -0700434 value = value.id
435 if (value != self.get_attribute("sliver_id", None)):
436 self.cached_sliver=None
437 self.set_attribute("sliver_id", value)
438
439 @property
Scott Baker9c8a2c72015-05-05 17:49:46 -0700440 def creator(self):
441 if getattr(self, "cached_creator", None):
442 return self.cached_creator
443 creator_id=self.get_attribute("creator_id")
444 if not creator_id:
445 return None
446 users=User.objects.filter(id=creator_id)
447 if not users:
448 return None
449 user=users[0]
450 self.cached_creator = users[0]
451 return user
452
453 @creator.setter
454 def creator(self, value):
455 if value:
456 value = value.id
457 if (value != self.get_attribute("creator_id", None)):
458 self.cached_creator=None
459 self.set_attribute("creator_id", value)
460
461 @property
Scott Baker697fb0b2015-04-20 09:16:17 -0700462 def vbng(self):
Scott Baker361c86c2015-07-06 14:38:02 -0700463 vbng = self.get_newest_subscribed_tenant(VBNGTenant)
464 if not vbng:
465 return None
466
467 # always return the same object when possible
468 if (self.cached_vbng) and (self.cached_vbng.id == vbng.id):
Scott Baker697fb0b2015-04-20 09:16:17 -0700469 return self.cached_vbng
Scott Baker361c86c2015-07-06 14:38:02 -0700470
Scott Baker9c8a2c72015-05-05 17:49:46 -0700471 vbng.caller = self.creator
Scott Baker697fb0b2015-04-20 09:16:17 -0700472 self.cached_vbng = vbng
473 return vbng
474
475 @vbng.setter
476 def vbng(self, value):
Scott Baker361c86c2015-07-06 14:38:02 -0700477 raise XOSConfigurationError("vCPE.vBNG cannot be set this way -- create a new vBNG object and set it's subscriber_tenant instead")
Scott Baker1b241612015-04-14 17:19:16 -0700478
Scott Bakerf08823d2015-07-06 16:50:30 -0700479 # *** to be moved to CordSubscriberRoot
480
Scott Baker1b241612015-04-14 17:19:16 -0700481 @property
482 def firewall_enable(self):
483 return self.get_attribute("firewall_enable", self.default_attributes["firewall_enable"])
484
485 @firewall_enable.setter
486 def firewall_enable(self, value):
487 self.set_attribute("firewall_enable", value)
488
Scott Baker0bcbb962015-04-16 21:54:50 -0700489 @property
490 def firewall_rules(self):
491 return self.get_attribute("firewall_rules", self.default_attributes["firewall_rules"])
492
493 @firewall_rules.setter
494 def firewall_rules(self, value):
495 self.set_attribute("firewall_rules", value)
496
497 @property
498 def url_filter_enable(self):
499 return self.get_attribute("url_filter_enable", self.default_attributes["url_filter_enable"])
500
501 @url_filter_enable.setter
502 def url_filter_enable(self, value):
503 self.set_attribute("url_filter_enable", value)
504
505 @property
Scott Baker8d13a982015-05-14 20:29:04 -0700506 def url_filter_level(self):
507 return self.get_attribute("url_filter_level", self.default_attributes["url_filter_level"])
508
509 @url_filter_level.setter
510 def url_filter_level(self, value):
511 self.set_attribute("url_filter_level", value)
512
513 @property
Scott Baker0bcbb962015-04-16 21:54:50 -0700514 def url_filter_rules(self):
515 return self.get_attribute("url_filter_rules", self.default_attributes["url_filter_rules"])
516
517 @url_filter_rules.setter
518 def url_filter_rules(self, value):
519 self.set_attribute("url_filter_rules", value)
520
521 @property
522 def cdn_enable(self):
523 return self.get_attribute("cdn_enable", self.default_attributes["cdn_enable"])
524
525 @cdn_enable.setter
526 def cdn_enable(self, value):
527 self.set_attribute("cdn_enable", value)
528
Scott Baker8d13a982015-05-14 20:29:04 -0700529 @property
530 def users(self):
Scott Bakera0cf9612015-05-20 16:31:58 -0700531 return self.get_attribute("users", self.default_attributes["users"])
Scott Baker8d13a982015-05-14 20:29:04 -0700532
533 @users.setter
534 def users(self, value):
Scott Bakera0cf9612015-05-20 16:31:58 -0700535 self.set_attribute("users", value)
536
537 def find_user(self, uid):
538 uid = int(uid)
539 for user in self.users:
540 if user["id"] == uid:
541 return user
542 return None
543
544 def update_user(self, uid, **kwargs):
545 # kwargs may be "level" or "mac"
546 # Setting one of these to None will cause None to be stored in the db
547 uid = int(uid)
548 users = self.users
549 for user in users:
550 if user["id"] == uid:
551 for arg in kwargs.keys():
552 user[arg] = kwargs[arg]
553 self.users = users
Scott Bakerac731702015-06-01 20:34:03 -0700554 return user
Scott Bakera0cf9612015-05-20 16:31:58 -0700555 raise ValueError("User %d not found" % uid)
556
557 def create_user(self, **kwargs):
Scott Baker7c796302015-05-28 19:44:20 -0700558 if "name" not in kwargs:
559 raise XOSMissingField("The name field is required")
560
561 for user in self.users:
562 if kwargs["name"] == user["name"]:
563 raise XOSDuplicateKey("User %s already exists" % kwargs["name"])
564
Scott Bakera0cf9612015-05-20 16:31:58 -0700565 uids = [x["id"] for x in self.users]
566 if uids:
567 uid = max(uids)+1
568 else:
569 uid = 0
570 newuser = kwargs.copy()
571 newuser["id"] = uid
572
573 users = self.users
574 users.append(newuser)
575 self.users = users
576
577 return newuser
578
579 def delete_user(self, uid):
580 uid = int(uid)
581 users = self.users
582 for user in users:
583 if user["id"]==uid:
584 users.remove(user)
585 self.users = users
586 return
587
588 raise ValueError("Users %d not found" % uid)
Scott Baker8d13a982015-05-14 20:29:04 -0700589
590 @property
591 def services(self):
Scott Bakerf4c3ad42015-05-15 14:59:47 -0700592 return {"cdn": self.cdn_enable,
593 "url_filter": self.url_filter_enable,
594 "firewall": self.firewall_enable}
Scott Baker8d13a982015-05-14 20:29:04 -0700595
596 @services.setter
597 def services(self, value):
598 pass
599
Scott Bakerf08823d2015-07-06 16:50:30 -0700600 # *** end of stuff to be moved to CordSubscriberRoot
601
602 @property
603 def bbs_account(self):
604 return self.get_attribute("bbs_account", self.default_attributes["bbs_account"])
605
606 @bbs_account.setter
607 def bbs_account(self, value):
608 return self.set_attribute("bbs_account", value)
609
610 @property
611 def last_ansible_hash(self):
612 return self.get_attribute("last_ansible_hash", self.default_attributes["last_ansible_hash"])
613
614 @last_ansible_hash.setter
615 def last_ansible_hash(self, value):
616 return self.set_attribute("last_ansible_hash", value)
617
618 @property
619 def ssh_command(self):
620 if self.sliver:
621 return self.sliver.get_ssh_command()
622 else:
623 return "no-sliver"
624
625 @ssh_command.setter
626 def ssh_command(self, value):
627 pass
628
Scott Baker706bf972015-05-20 08:19:25 -0700629 @property
630 def addresses(self):
631 if not self.sliver:
632 return {}
633
634 addresses = {}
635 for ns in self.sliver.networkslivers.all():
636 if "lan" in ns.network.name.lower():
637 addresses["lan"] = ns.ip
638 elif "wan" in ns.network.name.lower():
639 addresses["wan"] = ns.ip
640 elif "private" in ns.network.name.lower():
641 addresses["private"] = ns.ip
642 elif "nat" in ns.network.name.lower():
643 addresses["nat"] = ns.ip
Scott Baker710ad052015-06-04 10:26:44 -0700644 elif "hpc_client" in ns.network.name.lower():
645 addresses["hpc_client"] = ns.ip
Scott Baker706bf972015-05-20 08:19:25 -0700646 return addresses
647
Scott Bakera6a7e032015-05-20 08:25:29 -0700648 @property
649 def nat_ip(self):
650 return self.addresses.get("nat",None)
651
652 @property
653 def lan_ip(self):
654 return self.addresses.get("lan",None)
655
656 @property
657 def wan_ip(self):
658 return self.addresses.get("wan",None)
659
660 @property
Scott Baker3f4fe402015-06-05 12:08:34 -0700661 def wan_mac(self):
662 ip = self.wan_ip
663 if not ip:
664 return None
665 try:
666 (a,b,c,d) = ip.split('.')
667 wan_mac = "02:42:%2x:%2x:%2x:%2x" % (int(a), int(b), int(c), int(d))
668 except:
669 wan_mac = "Exception"
670 return wan_mac
671
672 @property
Scott Bakera6a7e032015-05-20 08:25:29 -0700673 def private_ip(self):
674 return self.addresses.get("private",None)
675
Scott Baker710ad052015-06-04 10:26:44 -0700676 @property
677 def hpc_client_ip(self):
678 return self.addresses.get("hpc_client",None)
679
Scott Baker7bbdd2f2015-06-09 12:30:30 -0700680 @property
681 def is_synced(self):
682 return (self.enacted is not None) and (self.enacted >= self.updated)
683
684 @is_synced.setter
685 def is_synced(self, value):
686 pass
687
Scott Baker1b241612015-04-14 17:19:16 -0700688 def pick_node(self):
689 nodes = list(Node.objects.all())
690 # TODO: logic to filter nodes by which nodes are up, and which
691 # nodes the slice can instantiate on.
692 nodes = sorted(nodes, key=lambda node: node.slivers.all().count())
693 return nodes[0]
694
695 def manage_sliver(self):
Scott Baker39b0d892015-04-15 20:59:15 -0700696 # Each VCPE object owns exactly one sliver.
697
Scott Baker1b241612015-04-14 17:19:16 -0700698 if self.deleted:
699 return
700
Scott Baker1b241612015-04-14 17:19:16 -0700701 if (self.sliver is not None) and (self.sliver.image != self.image):
702 self.sliver.delete()
703 self.sliver = None
Scott Baker9c8a2c72015-05-05 17:49:46 -0700704
Scott Baker1b241612015-04-14 17:19:16 -0700705 if self.sliver is None:
706 if not self.provider_service.slices.count():
Scott Bakeree0c2802015-05-06 15:46:34 -0700707 raise XOSConfigurationError("The VCPE service has no slices")
Scott Baker1b241612015-04-14 17:19:16 -0700708
Scott Bakerac60d5f2015-05-14 21:48:53 -0700709 flavors = Flavor.objects.filter(name="m1.small")
710 if not flavors:
711 raise XOSConfigurationError("No m1.small flavor")
712
Scott Baker1b241612015-04-14 17:19:16 -0700713 node =self.pick_node()
714 sliver = Sliver(slice = self.provider_service.slices.all()[0],
715 node = node,
716 image = self.image,
Scott Baker9c8a2c72015-05-05 17:49:46 -0700717 creator = self.creator,
Scott Bakerac60d5f2015-05-14 21:48:53 -0700718 deployment = node.site_deployment.deployment,
719 flavor = flavors[0])
Scott Baker1b241612015-04-14 17:19:16 -0700720 sliver.save()
721
Scott Baker39b0d892015-04-15 20:59:15 -0700722 try:
723 self.sliver = sliver
Scott Baker697fb0b2015-04-20 09:16:17 -0700724 super(VCPETenant, self).save()
Scott Baker39b0d892015-04-15 20:59:15 -0700725 except:
726 sliver.delete()
727 raise
Scott Baker1b241612015-04-14 17:19:16 -0700728
729 def cleanup_sliver(self):
730 if self.sliver:
Scott Baker361c86c2015-07-06 14:38:02 -0700731 # print "XXX cleanup sliver", self.sliver
Scott Baker1b241612015-04-14 17:19:16 -0700732 self.sliver.delete()
733 self.sliver = None
734
Scott Baker697fb0b2015-04-20 09:16:17 -0700735 def manage_vbng(self):
736 # Each vCPE object owns exactly one vBNG object
737
738 if self.deleted:
739 return
740
741 if self.vbng is None:
742 vbngServices = VBNGService.get_service_objects().all()
743 if not vbngServices:
Scott Bakerd921e1c2015-04-20 14:24:29 -0700744 raise XOSConfigurationError("No VBNG Services available")
Scott Baker697fb0b2015-04-20 09:16:17 -0700745
746 vbng = VBNGTenant(provider_service = vbngServices[0],
747 subscriber_tenant = self)
Scott Baker9c8a2c72015-05-05 17:49:46 -0700748 vbng.caller = self.creator
Scott Baker697fb0b2015-04-20 09:16:17 -0700749 vbng.save()
750
Scott Baker697fb0b2015-04-20 09:16:17 -0700751 def cleanup_vbng(self):
752 if self.vbng:
Scott Baker361c86c2015-07-06 14:38:02 -0700753 # print "XXX cleanup vnbg", self.vbng
Scott Baker697fb0b2015-04-20 09:16:17 -0700754 self.vbng.delete()
Scott Baker697fb0b2015-04-20 09:16:17 -0700755
Scott Baker5e76f802015-06-24 12:54:24 -0700756 def cleanup_orphans(self):
Scott Baker361c86c2015-07-06 14:38:02 -0700757 # ensure vCPE only has one vBNG
758 cur_vbng = self.vbng
759 for vbng in list(self.get_subscribed_tenants(VBNGTenant)):
760 if (not cur_vbng) or (vbng.id != cur_vbng.id):
761 # print "XXX clean up orphaned vbng", vbng
762 vbng.delete()
Scott Baker5e76f802015-06-24 12:54:24 -0700763
764 if self.orig_sliver_id and (self.orig_sliver_id != self.get_attribute("sliver_id")):
765 slivers=Sliver.objects.filter(id=self.orig_sliver_id)
766 if slivers:
767 # print "XXX clean up orphaned sliver", slivers[0]
768 slivers[0].delete()
769
Scott Baker5c8abf82015-05-20 20:45:11 -0700770 def manage_bbs_account(self):
771 if self.deleted:
772 return
773
Scott Bakere2570112015-05-20 20:57:28 -0700774 if self.url_filter_enable:
775 if not self.bbs_account:
776 # make sure we use the proxied VCPEService object, not the generic Service object
777 vcpe_service = VCPEService.objects.get(id=self.provider_service.id)
Scott Bakerf4f61ca2015-06-09 12:03:56 -0700778 if self.service_specific_id=="SYNCME":
779 self.bbs_account = "bbs01@onlab.us"
780 else:
781 self.bbs_account = vcpe_service.allocate_bbs_account()
Scott Bakere2570112015-05-20 20:57:28 -0700782 super(VCPETenant, self).save()
783 else:
784 if self.bbs_account:
785 self.bbs_account = None
786 super(VCPETenant, self).save()
Scott Baker5c8abf82015-05-20 20:45:11 -0700787
Scott Baker1b241612015-04-14 17:19:16 -0700788 def save(self, *args, **kwargs):
Scott Baker9c8a2c72015-05-05 17:49:46 -0700789 if not self.creator:
790 if not getattr(self, "caller", None):
791 # caller must be set when creating a vCPE since it creates a slice
Scott Bakeree0c2802015-05-06 15:46:34 -0700792 raise XOSProgrammingError("VCPETenant's self.caller was not set")
Scott Baker9c8a2c72015-05-05 17:49:46 -0700793 self.creator = self.caller
794 if not self.creator:
Scott Bakeree0c2802015-05-06 15:46:34 -0700795 raise XOSProgrammingError("VCPETenant's self.creator was not set")
Scott Baker9c8a2c72015-05-05 17:49:46 -0700796
Scott Baker1b241612015-04-14 17:19:16 -0700797 super(VCPETenant, self).save(*args, **kwargs)
Scott Baker39b0d892015-04-15 20:59:15 -0700798 self.manage_sliver()
Scott Baker697fb0b2015-04-20 09:16:17 -0700799 self.manage_vbng()
Scott Baker5c8abf82015-05-20 20:45:11 -0700800 self.manage_bbs_account()
Scott Baker5e76f802015-06-24 12:54:24 -0700801 self.cleanup_orphans()
Scott Baker1b241612015-04-14 17:19:16 -0700802
803 def delete(self, *args, **kwargs):
Scott Baker697fb0b2015-04-20 09:16:17 -0700804 self.cleanup_vbng()
Scott Baker1b241612015-04-14 17:19:16 -0700805 self.cleanup_sliver()
806 super(VCPETenant, self).delete(*args, **kwargs)
807
Scott Baker697fb0b2015-04-20 09:16:17 -0700808#----------------------------------------------------------------------------
809# vBNG
810#----------------------------------------------------------------------------
811
812class VBNGService(Service):
Scott Baker361c86c2015-07-06 14:38:02 -0700813 KIND = VBNG_KIND
Scott Baker697fb0b2015-04-20 09:16:17 -0700814
815 class Meta:
816 app_label = "cord"
817 verbose_name = "vBNG Service"
818 proxy = True
819
820class VBNGTenant(Tenant):
821 class Meta:
822 proxy = True
823
Scott Baker361c86c2015-07-06 14:38:02 -0700824 KIND = VBNG_KIND
Scott Baker697fb0b2015-04-20 09:16:17 -0700825
Scott Baker99ff5512015-06-02 14:34:04 -0700826 default_attributes = {"routeable_subnet": "",
Scott Baker790613c2015-06-08 19:09:53 -0700827 "mapped_ip": "",
828 "mapped_mac": "",
829 "mapped_hostname": ""}
Scott Baker697fb0b2015-04-20 09:16:17 -0700830
831 @property
832 def routeable_subnet(self):
833 return self.get_attribute("routeable_subnet", self.default_attributes["routeable_subnet"])
834
835 @routeable_subnet.setter
836 def routeable_subnet(self, value):
837 self.set_attribute("routeable_subnet", value)
Scott Baker99ff5512015-06-02 14:34:04 -0700838
839 @property
840 def mapped_ip(self):
841 return self.get_attribute("mapped_ip", self.default_attributes["mapped_ip"])
842
843 @mapped_ip.setter
844 def mapped_ip(self, value):
845 self.set_attribute("mapped_ip", value)
Scott Baker790613c2015-06-08 19:09:53 -0700846
847 @property
848 def mapped_mac(self):
849 return self.get_attribute("mapped_mac", self.default_attributes["mapped_mac"])
850
851 @mapped_mac.setter
852 def mapped_mac(self, value):
853 self.set_attribute("mapped_mac", value)
854
855 @property
856 def mapped_hostname(self):
857 return self.get_attribute("mapped_hostname", self.default_attributes["mapped_hostname"])
858
859 @mapped_hostname.setter
860 def mapped_hostname(self, value):
861 self.set_attribute("mapped_hostname", value)