blob: 2460ec703d31935b6075985ea0c02ee3ecec0a67 [file] [log] [blame]
Scott Bakere9ff7ce2015-04-14 17:19:16 -07001from django.db import models
Scott Bakere6780e92016-02-13 14:38:43 -08002from core.models import Service, PlCoreBase, Slice, Instance, Tenant, TenantWithContainer, Node, Image, User, Flavor, Subscriber, NetworkParameter, NetworkParameterType, Port, AddressPool
Scott Bakere9ff7ce2015-04-14 17:19:16 -07003from core.models.plcorebase import StrippedCharField
4import os
Scott Baker192da222015-07-08 19:01:56 -07005from django.db import models, transaction
Scott Bakere9ff7ce2015-04-14 17:19:16 -07006from django.forms.models import model_to_dict
7from django.db.models import Q
8from operator import itemgetter, attrgetter, methodcaller
Scott Baker5b8eb412016-02-02 16:56:18 -08009from core.models import Tag
10from core.models.service import LeastLoadedNodeScheduler
Scott Bakerdf6375e2016-04-13 11:25:52 -070011from services.vrouter.models import VRouterService, VRouterTenant
Scott Bakerfa5cdd62015-04-20 09:16:17 -070012import traceback
Scott Baker7f8ef8f2015-04-20 14:24:29 -070013from xos.exceptions import *
Scott Bakere6780e92016-02-13 14:38:43 -080014from xos.config import Config
Scott Bakere9ff7ce2015-04-14 17:19:16 -070015
Scott Bakere9ff7ce2015-04-14 17:19:16 -070016class ConfigurationError(Exception):
17 pass
18
Scott Bakerd9133342015-07-06 14:38:02 -070019VOLT_KIND = "vOLT"
20VCPE_KIND = "vCPE"
21VBNG_KIND = "vBNG"
Scott Baker81de6402015-07-06 16:50:30 -070022CORD_SUBSCRIBER_KIND = "CordSubscriberRoot"
23
Scott Bakere6780e92016-02-13 14:38:43 -080024CORD_USE_VTN = getattr(Config(), "networking_use_vtn", False)
25
Scott Baker81de6402015-07-06 16:50:30 -070026# -------------------------------------------
27# CordSubscriberRoot
28# -------------------------------------------
29
30class CordSubscriberRoot(Subscriber):
Scott Bakere4364d12015-07-06 17:21:21 -070031 class Meta:
32 proxy = True
33
Scott Baker81de6402015-07-06 16:50:30 -070034 KIND = CORD_SUBSCRIBER_KIND
35
Scott Baker669212f2016-03-01 20:14:35 -080036 status_choices = (("enabled", "Enabled"),
37 ("suspended", "Suspended"),
38 ("delinquent", "Delinquent"),
39 ("copyrightviolation", "Copyright Violation"))
40
41 # 'simple_attributes' will be expanded into properties and setters that
42 # store the attribute using self.set_attribute / self.get_attribute.
43
44 simple_attributes = ( ("firewall_enable", False),
45 ("firewall_rules", "accept all anywhere anywhere"),
46 ("url_filter_enable", False),
47 ("url_filter_rules", "allow all"),
48 ("url_filter_level", "PG"),
49 ("cdn_enable", False),
50 ("users", []),
51 ("is_demo_user", False),
52
Matteoc1018542016-03-02 09:33:20 -080053 ("uplink_speed", 1000000000), # 1 gigabit, a reasonable default?
54 ("downlink_speed", 1000000000),
Scott Baker669212f2016-03-01 20:14:35 -080055 ("enable_uverse", True) )
56
57 default_attributes = {"status": "enabled"}
Scott Baker81de6402015-07-06 16:50:30 -070058
Scott Baker050f8b32015-07-07 12:15:03 -070059 sync_attributes = ("firewall_enable",
60 "firewall_rules",
61 "url_filter_enable",
62 "url_filter_rules",
Scott Bakere98eea82016-03-01 20:44:40 -080063 "cdn_enable",
64 "uplink_speed",
65 "downlink_speed",
66 "enable_uverse",
67 "status")
Scott Baker050f8b32015-07-07 12:15:03 -070068
Scott Baker81de6402015-07-06 16:50:30 -070069 def __init__(self, *args, **kwargs):
70 super(CordSubscriberRoot, self).__init__(*args, **kwargs)
71 self.cached_volt = None
Scott Baker050f8b32015-07-07 12:15:03 -070072 self._initial_url_filter_enable = self.url_filter_enable
Scott Baker81de6402015-07-06 16:50:30 -070073
74 @property
75 def volt(self):
76 volt = self.get_newest_subscribed_tenant(VOLTTenant)
77 if not volt:
78 return None
79
80 # always return the same object when possible
81 if (self.cached_volt) and (self.cached_volt.id == volt.id):
Scott Baker126ad472015-07-07 17:59:44 -070082 return self.cached_volt
Scott Baker81de6402015-07-06 16:50:30 -070083
Scott Bakere4364d12015-07-06 17:21:21 -070084 #volt.caller = self.creator
Scott Baker81de6402015-07-06 16:50:30 -070085 self.cached_volt = volt
86 return volt
87
88 @property
Scott Baker669212f2016-03-01 20:14:35 -080089 def status(self):
90 return self.get_attribute("status", self.default_attributes["status"])
Scott Baker81de6402015-07-06 16:50:30 -070091
Scott Baker669212f2016-03-01 20:14:35 -080092 @status.setter
93 def status(self, value):
94 if not value in [x[0] for x in self.status_choices]:
95 raise Exception("invalid status %s" % value)
96 self.set_attribute("status", value)
Scott Baker81de6402015-07-06 16:50:30 -070097
98 def find_user(self, uid):
99 uid = int(uid)
100 for user in self.users:
101 if user["id"] == uid:
102 return user
103 return None
104
105 def update_user(self, uid, **kwargs):
106 # kwargs may be "level" or "mac"
107 # Setting one of these to None will cause None to be stored in the db
108 uid = int(uid)
109 users = self.users
110 for user in users:
111 if user["id"] == uid:
112 for arg in kwargs.keys():
113 user[arg] = kwargs[arg]
114 self.users = users
115 return user
116 raise ValueError("User %d not found" % uid)
117
118 def create_user(self, **kwargs):
119 if "name" not in kwargs:
120 raise XOSMissingField("The name field is required")
121
122 for user in self.users:
123 if kwargs["name"] == user["name"]:
124 raise XOSDuplicateKey("User %s already exists" % kwargs["name"])
125
126 uids = [x["id"] for x in self.users]
127 if uids:
128 uid = max(uids)+1
129 else:
130 uid = 0
131 newuser = kwargs.copy()
132 newuser["id"] = uid
133
134 users = self.users
135 users.append(newuser)
136 self.users = users
137
138 return newuser
139
140 def delete_user(self, uid):
141 uid = int(uid)
142 users = self.users
143 for user in users:
144 if user["id"]==uid:
145 users.remove(user)
146 self.users = users
147 return
148
149 raise ValueError("Users %d not found" % uid)
150
151 @property
152 def services(self):
153 return {"cdn": self.cdn_enable,
154 "url_filter": self.url_filter_enable,
155 "firewall": self.firewall_enable}
156
157 @services.setter
158 def services(self, value):
159 pass
Scott Bakerd9133342015-07-06 14:38:02 -0700160
Scott Baker050f8b32015-07-07 12:15:03 -0700161 def save(self, *args, **kwargs):
Scott Bakerf3735762016-03-31 14:45:31 -0700162 self.validate_unique_service_specific_id(none_okay=True)
Scott Bakerfe38c2a2015-07-24 18:56:57 -0700163 if (not hasattr(self, 'caller') or not self.caller.is_admin):
164 if (self.has_field_changed("service_specific_id")):
165 raise XOSPermissionDenied("You do not have permission to change service_specific_id")
Scott Baker050f8b32015-07-07 12:15:03 -0700166 super(CordSubscriberRoot, self).save(*args, **kwargs)
167 if (self.volt) and (self.volt.vcpe): # and (self._initial_url_filter_enabled != self.url_filter_enable):
168 # 1) trigger manage_bbs_account to run
169 # 2) trigger vcpe observer to wake up
170 self.volt.vcpe.save()
171
Scott Baker669212f2016-03-01 20:14:35 -0800172CordSubscriberRoot.setup_simple_attributes()
Scott Baker126ad472015-07-07 17:59:44 -0700173
Scott Bakerd4b48c02015-04-15 20:59:15 -0700174# -------------------------------------------
175# VOLT
176# -------------------------------------------
177
178class VOLTService(Service):
Scott Bakerd9133342015-07-06 14:38:02 -0700179 KIND = VOLT_KIND
Scott Bakerd4b48c02015-04-15 20:59:15 -0700180
Scott Bakere9ff7ce2015-04-14 17:19:16 -0700181 class Meta:
Scott Bakerd4b48c02015-04-15 20:59:15 -0700182 app_label = "cord"
183 verbose_name = "vOLT Service"
184 proxy = True
185
186class VOLTTenant(Tenant):
187 class Meta:
188 proxy = True
189
Scott Bakerd9133342015-07-06 14:38:02 -0700190 KIND = VOLT_KIND
Scott Bakerd4b48c02015-04-15 20:59:15 -0700191
Scott Bakerf1527cd2015-11-09 20:25:21 -0800192 default_attributes = {"vlan_id": None, "s_tag": None, "c_tag": None}
Scott Baker323eca92015-04-20 09:48:34 -0700193 def __init__(self, *args, **kwargs):
194 volt_services = VOLTService.get_service_objects().all()
195 if volt_services:
196 self._meta.get_field("provider_service").default = volt_services[0].id
197 super(VOLTTenant, self).__init__(*args, **kwargs)
Scott Bakerd9133342015-07-06 14:38:02 -0700198 self.cached_vcpe = None
Scott Baker868dabf2015-06-24 12:54:24 -0700199
Scott Bakerd4b48c02015-04-15 20:59:15 -0700200 @property
Scott Bakerf1527cd2015-11-09 20:25:21 -0800201 def s_tag(self):
202 return self.get_attribute("s_tag", self.default_attributes["s_tag"])
203
204 @s_tag.setter
205 def s_tag(self, value):
206 self.set_attribute("s_tag", value)
207
208 @property
209 def c_tag(self):
210 return self.get_attribute("c_tag", self.default_attributes["c_tag"])
211
212 @c_tag.setter
213 def c_tag(self, value):
214 self.set_attribute("c_tag", value)
215
216 # for now, vlan_id is a synonym for c_tag
217
218 @property
Scott Baker679f7022015-04-20 11:50:09 -0700219 def vlan_id(self):
Scott Bakerf1527cd2015-11-09 20:25:21 -0800220 return self.c_tag
Scott Baker679f7022015-04-20 11:50:09 -0700221
222 @vlan_id.setter
223 def vlan_id(self, value):
Scott Bakerf1527cd2015-11-09 20:25:21 -0800224 self.c_tag = value
Scott Baker679f7022015-04-20 11:50:09 -0700225
226 @property
Scott Bakerd4b48c02015-04-15 20:59:15 -0700227 def vcpe(self):
Scott Baker4c052b22016-02-11 11:08:42 -0800228 vcpe = self.get_newest_subscribed_tenant(VSGTenant)
Scott Bakerd9133342015-07-06 14:38:02 -0700229 if not vcpe:
230 return None
231
232 # always return the same object when possible
233 if (self.cached_vcpe) and (self.cached_vcpe.id == vcpe.id):
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700234 return self.cached_vcpe
Scott Bakerd9133342015-07-06 14:38:02 -0700235
Scott Bakerc633dc92015-05-05 17:49:46 -0700236 vcpe.caller = self.creator
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700237 self.cached_vcpe = vcpe
238 return vcpe
Scott Bakerd4b48c02015-04-15 20:59:15 -0700239
240 @vcpe.setter
241 def vcpe(self, value):
Scott Bakere4364d12015-07-06 17:21:21 -0700242 raise XOSConfigurationError("vOLT.vCPE cannot be set this way -- create a new vCPE object and set its subscriber_tenant instead")
243
244 @property
245 def subscriber(self):
246 if not self.subscriber_root:
247 return None
248 subs = CordSubscriberRoot.objects.filter(id=self.subscriber_root.id)
249 if not subs:
250 return None
251 return subs[0]
Scott Bakerd4b48c02015-04-15 20:59:15 -0700252
Scott Bakerc633dc92015-05-05 17:49:46 -0700253 @property
254 def creator(self):
255 if getattr(self, "cached_creator", None):
256 return self.cached_creator
257 creator_id=self.get_attribute("creator_id")
258 if not creator_id:
259 return None
260 users=User.objects.filter(id=creator_id)
261 if not users:
262 return None
263 user=users[0]
264 self.cached_creator = users[0]
265 return user
266
267 @creator.setter
268 def creator(self, value):
269 if value:
270 value = value.id
271 if (value != self.get_attribute("creator_id", None)):
272 self.cached_creator=None
273 self.set_attribute("creator_id", value)
274
Scott Bakerd4b48c02015-04-15 20:59:15 -0700275 def manage_vcpe(self):
276 # Each VOLT object owns exactly one VCPE object
277
278 if self.deleted:
279 return
280
281 if self.vcpe is None:
Scott Bakerf91e6152016-02-11 12:07:10 -0800282 vsgServices = VSGService.get_service_objects().all()
283 if not vsgServices:
284 raise XOSConfigurationError("No VSG Services available")
Scott Bakerd4b48c02015-04-15 20:59:15 -0700285
Scott Bakerf91e6152016-02-11 12:07:10 -0800286 vcpe = VSGTenant(provider_service = vsgServices[0],
Scott Bakerd4b48c02015-04-15 20:59:15 -0700287 subscriber_tenant = self)
Scott Bakerc633dc92015-05-05 17:49:46 -0700288 vcpe.caller = self.creator
Scott Bakerd4b48c02015-04-15 20:59:15 -0700289 vcpe.save()
290
Scott Baker050f8b32015-07-07 12:15:03 -0700291 def manage_subscriber(self):
292 if (self.subscriber_root is None):
293 # The vOLT is not connected to a Subscriber, so either find an
294 # existing subscriber with the same SSID, or autogenerate a new
295 # subscriber.
296 #
297 # TODO: This probably goes away when we rethink the ONOS-to-XOS
298 # vOLT API.
299
300 subs = CordSubscriberRoot.get_tenant_objects().filter(service_specific_id = self.service_specific_id)
301 if subs:
302 sub = subs[0]
303 else:
304 sub = CordSubscriberRoot(service_specific_id = self.service_specific_id,
305 name = "autogenerated-for-vOLT-%s" % self.id)
306 sub.save()
307 self.subscriber_root = sub
308 self.save()
309
Scott Bakerd4b48c02015-04-15 20:59:15 -0700310 def cleanup_vcpe(self):
311 if self.vcpe:
Scott Bakerd9133342015-07-06 14:38:02 -0700312 # print "XXX cleanup vcpe", self.vcpe
Scott Bakerd4b48c02015-04-15 20:59:15 -0700313 self.vcpe.delete()
Scott Bakerd4b48c02015-04-15 20:59:15 -0700314
Scott Baker868dabf2015-06-24 12:54:24 -0700315 def cleanup_orphans(self):
Scott Bakerd9133342015-07-06 14:38:02 -0700316 # ensure vOLT only has one vCPE
317 cur_vcpe = self.vcpe
Scott Baker4c052b22016-02-11 11:08:42 -0800318 for vcpe in list(self.get_subscribed_tenants(VSGTenant)):
Scott Bakerd9133342015-07-06 14:38:02 -0700319 if (not cur_vcpe) or (vcpe.id != cur_vcpe.id):
320 # print "XXX clean up orphaned vcpe", vcpe
321 vcpe.delete()
Scott Baker868dabf2015-06-24 12:54:24 -0700322
Scott Bakerd4b48c02015-04-15 20:59:15 -0700323 def save(self, *args, **kwargs):
Scott Baker6292f342016-03-30 09:39:59 -0700324 # VOLTTenant probably doesn't need a SSID anymore; that will be handled
325 # by CORDSubscriberRoot...
326 # self.validate_unique_service_specific_id()
Scott Baker7f8ef8f2015-04-20 14:24:29 -0700327
Scott Baker050f8b32015-07-07 12:15:03 -0700328 if (self.subscriber_root is not None):
329 subs = self.subscriber_root.get_subscribed_tenants(VOLTTenant)
330 if (subs) and (self not in subs):
331 raise XOSDuplicateKey("Subscriber should only be linked to one vOLT")
332
Scott Bakerc633dc92015-05-05 17:49:46 -0700333 if not self.creator:
334 if not getattr(self, "caller", None):
335 # caller must be set when creating a vCPE since it creates a slice
336 raise XOSProgrammingError("VOLTTenant's self.caller was not set")
337 self.creator = self.caller
338 if not self.creator:
339 raise XOSProgrammingError("VOLTTenant's self.creator was not set")
340
Scott Bakerd4b48c02015-04-15 20:59:15 -0700341 super(VOLTTenant, self).save(*args, **kwargs)
Scott Baker192da222015-07-08 19:01:56 -0700342 model_policy_volt(self.pk)
343 #self.manage_vcpe()
344 #self.manage_subscriber()
345 #self.cleanup_orphans()
Scott Bakerd4b48c02015-04-15 20:59:15 -0700346
347 def delete(self, *args, **kwargs):
348 self.cleanup_vcpe()
349 super(VOLTTenant, self).delete(*args, **kwargs)
350
Scott Baker192da222015-07-08 19:01:56 -0700351def model_policy_volt(pk):
352 # TODO: this should be made in to a real model_policy
353 with transaction.atomic():
354 volt = VOLTTenant.objects.select_for_update().filter(pk=pk)
355 if not volt:
356 return
357 volt = volt[0]
358 volt.manage_vcpe()
359 volt.manage_subscriber()
360 volt.cleanup_orphans()
361
Scott Bakerd4b48c02015-04-15 20:59:15 -0700362# -------------------------------------------
363# VCPE
364# -------------------------------------------
365
Scott Bakerf91e6152016-02-11 12:07:10 -0800366class VSGService(Service):
Scott Bakerd9133342015-07-06 14:38:02 -0700367 KIND = VCPE_KIND
Scott Bakerd4b48c02015-04-15 20:59:15 -0700368
Scott Bakerbe2bc9a2016-03-10 20:12:15 -0800369 URL_FILTER_KIND_CHOICES = ( (None, "None"), ("safebrowsing", "Safe Browsing"), ("answerx", "AnswerX") )
Scott Baker9b870572016-03-10 19:23:10 -0800370
Scott Baker2b56cf42015-07-15 18:08:06 -0700371 simple_attributes = ( ("bbs_api_hostname", None),
372 ("bbs_api_port", None),
Scott Baker80157da2015-07-15 17:42:43 -0700373 ("bbs_server", None),
Scott Bakercf6eb992016-02-18 06:43:02 -0800374 ("backend_network_label", "hpc_client"),
375 ("wan_container_gateway_ip", ""),
376 ("wan_container_gateway_mac", ""),
Scott Bakerae6187c2016-02-23 14:58:49 -0800377 ("wan_container_netbits", "24"),
Scott Baker67074ab2016-03-04 11:29:02 -0800378 ("dns_servers", "8.8.8.8"),
Scott Baker9b870572016-03-10 19:23:10 -0800379 ("url_filter_kind", None),
Scott Baker67074ab2016-03-04 11:29:02 -0800380 ("node_label", None) )
Scott Baker62312972015-07-13 14:30:25 -0700381
382 def __init__(self, *args, **kwargs):
Scott Bakerf91e6152016-02-11 12:07:10 -0800383 super(VSGService, self).__init__(*args, **kwargs)
Scott Baker62312972015-07-13 14:30:25 -0700384
Scott Bakerd4b48c02015-04-15 20:59:15 -0700385 class Meta:
386 app_label = "cord"
Scott Baker2516ce32016-02-11 16:56:34 -0800387 verbose_name = "vSG Service"
Scott Bakerd4b48c02015-04-15 20:59:15 -0700388 proxy = True
Scott Bakere9ff7ce2015-04-14 17:19:16 -0700389
Scott Baker4e6d60d2015-05-20 20:45:11 -0700390 def allocate_bbs_account(self):
Scott Baker4c052b22016-02-11 11:08:42 -0800391 vcpes = VSGTenant.get_tenant_objects().all()
Scott Baker4e6d60d2015-05-20 20:45:11 -0700392 bbs_accounts = [vcpe.bbs_account for vcpe in vcpes]
393
394 # There's a bit of a race here; some other user could be trying to
395 # allocate a bbs_account at the same time we are.
396
Scott Baker2f0b3462015-06-09 12:03:56 -0700397 for i in range(2,21):
Scott Baker4e6d60d2015-05-20 20:45:11 -0700398 account_name = "bbs%02d@onlab.us" % i
399 if (account_name not in bbs_accounts):
400 return account_name
401
402 raise XOSConfigurationError("We've run out of available broadbandshield accounts. Delete some vcpe and try again.")
403
Scott Baker80157da2015-07-15 17:42:43 -0700404 @property
405 def bbs_slice(self):
406 bbs_slice_id=self.get_attribute("bbs_slice_id")
407 if not bbs_slice_id:
408 return None
409 bbs_slices=Slice.objects.filter(id=bbs_slice_id)
410 if not bbs_slices:
411 return None
412 return bbs_slices[0]
413
414 @bbs_slice.setter
415 def bbs_slice(self, value):
416 if value:
417 value = value.id
418 self.set_attribute("bbs_slice_id", value)
419
Scott Bakerf91e6152016-02-11 12:07:10 -0800420VSGService.setup_simple_attributes()
Scott Baker62312972015-07-13 14:30:25 -0700421
Scott Baker5b8eb412016-02-02 16:56:18 -0800422#class STagBlock(PlCoreBase):
423# instance = models.ForeignKey(Instance, related_name="s_tags")
424# s_tag = models.CharField(null=false, blank=false, unique=true, max_length=10)
425# #c_tags = models.TextField(null=true, blank=true)
426#
427# def __unicode__(self): return u'%s' % (self.s_tag)
Scott Baker62312972015-07-13 14:30:25 -0700428
Scott Baker4c052b22016-02-11 11:08:42 -0800429class VSGTenant(TenantWithContainer):
Scott Bakere9ff7ce2015-04-14 17:19:16 -0700430 class Meta:
431 proxy = True
432
Scott Bakerd9133342015-07-06 14:38:02 -0700433 KIND = VCPE_KIND
Scott Bakerd4b48c02015-04-15 20:59:15 -0700434
Scott Baker92a81d42015-09-09 10:57:16 -0700435 sync_attributes = ("nat_ip", "nat_mac",
436 "lan_ip", "lan_mac",
Scott Bakere6780e92016-02-13 14:38:43 -0800437 "wan_ip", "wan_mac",
438 "wan_container_ip", "wan_container_mac",
Scott Baker92a81d42015-09-09 10:57:16 -0700439 "private_ip", "private_mac",
440 "hpc_client_ip", "hpc_client_mac")
Scott Bakerc633dc92015-05-05 17:49:46 -0700441
Tony Mackd8515472015-08-19 11:58:18 -0400442 default_attributes = {"instance_id": None,
Scott Baker4b206972015-11-02 20:55:07 -0800443 "container_id": None,
Scott Baker4e6d60d2015-05-20 20:45:11 -0700444 "users": [],
Scott Baker4aa660e2015-06-09 12:22:29 -0700445 "bbs_account": None,
Scott Bakere6780e92016-02-13 14:38:43 -0800446 "last_ansible_hash": None,
447 "wan_container_ip": None}
Scott Bakere9ff7ce2015-04-14 17:19:16 -0700448
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700449 def __init__(self, *args, **kwargs):
Scott Baker4c052b22016-02-11 11:08:42 -0800450 super(VSGTenant, self).__init__(*args, **kwargs)
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700451 self.cached_vbng=None
Scott Baker47075932016-04-13 09:12:45 -0700452 self.cached_vrouter=None
Scott Bakerc633dc92015-05-05 17:49:46 -0700453
454 @property
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700455 def vbng(self):
Scott Bakerd9133342015-07-06 14:38:02 -0700456 vbng = self.get_newest_subscribed_tenant(VBNGTenant)
457 if not vbng:
458 return None
459
460 # always return the same object when possible
461 if (self.cached_vbng) and (self.cached_vbng.id == vbng.id):
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700462 return self.cached_vbng
Scott Bakerd9133342015-07-06 14:38:02 -0700463
Scott Bakerc633dc92015-05-05 17:49:46 -0700464 vbng.caller = self.creator
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700465 self.cached_vbng = vbng
466 return vbng
467
468 @vbng.setter
469 def vbng(self, value):
Scott Bakerd9133342015-07-06 14:38:02 -0700470 raise XOSConfigurationError("vCPE.vBNG cannot be set this way -- create a new vBNG object and set it's subscriber_tenant instead")
Scott Bakere9ff7ce2015-04-14 17:19:16 -0700471
Scott Bakere4364d12015-07-06 17:21:21 -0700472 @property
Scott Baker47075932016-04-13 09:12:45 -0700473 def vrouter(self):
474 vrouter = self.get_newest_subscribed_tenant(VRouterTenant)
475 if not vrouter:
476 return None
477
478 # always return the same object when possible
479 if (self.cached_vrouter) and (self.cached_vrouter.id == vrouter.id):
480 return self.cached_vrouter
481
482 vrouter.caller = self.creator
483 self.cached_vrouter = vrouter
484 return vrouter
485
486 @vrouter.setter
487 def vrouter(self, value):
488 raise XOSConfigurationError("vCPE.vRouter cannot be set this way -- create a new vRuter object and set its subscriber_tenant instead")
489
490 @property
Scott Bakere4364d12015-07-06 17:21:21 -0700491 def volt(self):
492 if not self.subscriber_tenant:
493 return None
494 volts = VOLTTenant.objects.filter(id=self.subscriber_tenant.id)
495 if not volts:
496 return None
497 return volts[0]
498
Scott Baker81de6402015-07-06 16:50:30 -0700499 @property
500 def bbs_account(self):
501 return self.get_attribute("bbs_account", self.default_attributes["bbs_account"])
502
503 @bbs_account.setter
504 def bbs_account(self, value):
505 return self.set_attribute("bbs_account", value)
506
507 @property
508 def last_ansible_hash(self):
509 return self.get_attribute("last_ansible_hash", self.default_attributes["last_ansible_hash"])
510
511 @last_ansible_hash.setter
512 def last_ansible_hash(self, value):
513 return self.set_attribute("last_ansible_hash", value)
514
515 @property
516 def ssh_command(self):
Tony Mackd8515472015-08-19 11:58:18 -0400517 if self.instance:
518 return self.instance.get_ssh_command()
Scott Baker81de6402015-07-06 16:50:30 -0700519 else:
Tony Mackd8515472015-08-19 11:58:18 -0400520 return "no-instance"
Scott Baker81de6402015-07-06 16:50:30 -0700521
522 @ssh_command.setter
523 def ssh_command(self, value):
524 pass
525
Scott Baker5571c692015-05-20 08:19:25 -0700526 @property
527 def addresses(self):
Scott Baker4b206972015-11-02 20:55:07 -0800528 if self.instance:
529 ports = self.instance.ports.all()
530 elif self.container:
531 ports = self.container.ports.all()
532 else:
Scott Baker5571c692015-05-20 08:19:25 -0700533 return {}
534
535 addresses = {}
Scott Baker4b206972015-11-02 20:55:07 -0800536 for ns in ports:
Scott Baker5571c692015-05-20 08:19:25 -0700537 if "lan" in ns.network.name.lower():
Scott Baker92a81d42015-09-09 10:57:16 -0700538 addresses["lan"] = (ns.ip, ns.mac)
Scott Baker5571c692015-05-20 08:19:25 -0700539 elif "wan" in ns.network.name.lower():
Scott Baker92a81d42015-09-09 10:57:16 -0700540 addresses["wan"] = (ns.ip, ns.mac)
Scott Baker5571c692015-05-20 08:19:25 -0700541 elif "private" in ns.network.name.lower():
Scott Baker92a81d42015-09-09 10:57:16 -0700542 addresses["private"] = (ns.ip, ns.mac)
Scott Baker5571c692015-05-20 08:19:25 -0700543 elif "nat" in ns.network.name.lower():
Scott Baker92a81d42015-09-09 10:57:16 -0700544 addresses["nat"] = (ns.ip, ns.mac)
Scott Baker281b1af2015-06-04 10:26:44 -0700545 elif "hpc_client" in ns.network.name.lower():
Scott Baker92a81d42015-09-09 10:57:16 -0700546 addresses["hpc_client"] = (ns.ip, ns.mac)
Scott Baker5571c692015-05-20 08:19:25 -0700547 return addresses
548
Scott Bakere6780e92016-02-13 14:38:43 -0800549 # ------------------------------------------------------------------------
550 # The following IP addresses all come from the VM
551 # Note: They might not be useful for the VTN-vSG
552
Scott Baker432d1402015-05-20 08:25:29 -0700553 @property
554 def nat_ip(self):
Scott Baker92a81d42015-09-09 10:57:16 -0700555 return self.addresses.get("nat", (None,None) )[0]
556
557 @property
558 def nat_mac(self):
559 return self.addresses.get("nat", (None,None) )[1]
Scott Baker432d1402015-05-20 08:25:29 -0700560
561 @property
562 def lan_ip(self):
Scott Baker92a81d42015-09-09 10:57:16 -0700563 return self.addresses.get("lan", (None, None) )[0]
564
565 @property
566 def lan_mac(self):
567 return self.addresses.get("lan", (None, None) )[1]
Scott Baker432d1402015-05-20 08:25:29 -0700568
569 @property
570 def wan_ip(self):
Scott Baker92a81d42015-09-09 10:57:16 -0700571 return self.addresses.get("wan", (None, None) )[0]
Scott Baker432d1402015-05-20 08:25:29 -0700572
573 @property
Scott Baker4f972592015-06-05 12:08:34 -0700574 def wan_mac(self):
Andy Bavier4c7e76d2015-09-09 18:06:30 -0400575 return self.addresses.get("wan", (None, None) )[1]
Scott Baker4f972592015-06-05 12:08:34 -0700576
Scott Bakere6780e92016-02-13 14:38:43 -0800577 # end of VM IP address stubs
578 # ------------------------------------------------------------------------
579
580 @property
581 def wan_container_ip(self):
582 if CORD_USE_VTN:
583 # When using VTN, wan_container_ip is stored and maintained inside
584 # of the vSG object.
585 return self.get_attribute("wan_container_ip", self.default_attributes["wan_container_ip"])
586 else:
587 # When not using VTN, wan_container_ip is the same as wan_ip.
588 # XXX Is this broken for multiple-containers-per-VM?
589 return self.wan_ip
590
591 @wan_container_ip.setter
592 def wan_container_ip(self, value):
593 if CORD_USE_VTN:
594 self.set_attribute("wan_container_ip", value)
595 else:
596 raise Exception("wan_container_ip.setter called on non-VTN CORD")
597
Scott Baker6fd78342016-02-18 15:18:47 -0800598 def ip_to_mac(self, ip):
599 (a, b, c, d) = ip.split('.')
600 return "02:42:%02x:%02x:%02x:%02x" % (int(a), int(b), int(c), int(d))
601
Andy Bavier733733d2015-10-29 14:01:47 -0400602 # Generate the MAC for the container interface connected to WAN
603 @property
604 def wan_container_mac(self):
Scott Bakere6780e92016-02-13 14:38:43 -0800605 if not self.wan_container_ip:
606 return None
Scott Baker6fd78342016-02-18 15:18:47 -0800607 return self.ip_to_mac(self.wan_container_ip)
Andy Bavier733733d2015-10-29 14:01:47 -0400608
Scott Baker4f972592015-06-05 12:08:34 -0700609 @property
Scott Baker432d1402015-05-20 08:25:29 -0700610 def private_ip(self):
Scott Baker92a81d42015-09-09 10:57:16 -0700611 return self.addresses.get("private", (None, None) )[0]
612
613 @property
614 def private_mac(self):
615 return self.addresses.get("private", (None, None) )[1]
Scott Baker432d1402015-05-20 08:25:29 -0700616
Scott Baker281b1af2015-06-04 10:26:44 -0700617 @property
618 def hpc_client_ip(self):
Scott Baker92a81d42015-09-09 10:57:16 -0700619 return self.addresses.get("hpc_client", (None, None) )[0]
620
621 @property
622 def hpc_client_mac(self):
623 return self.addresses.get("hpc_client", (None, None) )[1]
Scott Baker281b1af2015-06-04 10:26:44 -0700624
Scott Bakerd517a102015-06-09 12:30:30 -0700625 @property
626 def is_synced(self):
627 return (self.enacted is not None) and (self.enacted >= self.updated)
628
629 @is_synced.setter
630 def is_synced(self, value):
631 pass
632
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700633 def manage_vbng(self):
634 # Each vCPE object owns exactly one vBNG object
635
636 if self.deleted:
637 return
638
639 if self.vbng is None:
640 vbngServices = VBNGService.get_service_objects().all()
641 if not vbngServices:
Scott Baker7f8ef8f2015-04-20 14:24:29 -0700642 raise XOSConfigurationError("No VBNG Services available")
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700643
644 vbng = VBNGTenant(provider_service = vbngServices[0],
645 subscriber_tenant = self)
Scott Bakerc633dc92015-05-05 17:49:46 -0700646 vbng.caller = self.creator
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700647 vbng.save()
648
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700649 def cleanup_vbng(self):
650 if self.vbng:
Scott Bakerd9133342015-07-06 14:38:02 -0700651 # print "XXX cleanup vnbg", self.vbng
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700652 self.vbng.delete()
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700653
Scott Baker47075932016-04-13 09:12:45 -0700654 def manage_vrouter(self):
655 # Each vCPE object owns exactly one vRouterTenant object
656
657 if self.deleted:
658 return
659
660 if self.vrouter is None:
661 vrouterServices = VRouterService.get_service_objects().all()
662 if not vrouterServices:
663 raise XOSConfigurationError("No VROUTER Services available")
664
665 vrouter = vrouterService.get_tenant(name="addresses_vsg", subscriber_tenant = self)
666 vrouter.caller = self.creator
667 vrouter.save()
668
669 def cleanup_vrouter(self):
670 if self.vrouter:
671 # print "XXX cleanup vrouter", self.vrouter
672 self.vrouter.delete()
673
Scott Baker868dabf2015-06-24 12:54:24 -0700674 def cleanup_orphans(self):
Scott Bakerd9133342015-07-06 14:38:02 -0700675 # ensure vCPE only has one vBNG
676 cur_vbng = self.vbng
677 for vbng in list(self.get_subscribed_tenants(VBNGTenant)):
678 if (not cur_vbng) or (vbng.id != cur_vbng.id):
679 # print "XXX clean up orphaned vbng", vbng
680 vbng.delete()
Scott Baker868dabf2015-06-24 12:54:24 -0700681
Scott Baker47075932016-04-13 09:12:45 -0700682 # ensure vCPE only has one vRouter
683 cur_vrouter = self.vrouter
684 for vrouter in list(self.get_subscribed_tenants(VRouterTenant)):
685 if (not cur_vrouter) or (vrouter.id != cur_vrouter.id):
686 # print "XXX clean up orphaned vrouter", vrouter
687 vrouter.delete()
688
Tony Mackd8515472015-08-19 11:58:18 -0400689 if self.orig_instance_id and (self.orig_instance_id != self.get_attribute("instance_id")):
690 instances=Instance.objects.filter(id=self.orig_instance_id)
691 if instances:
692 # print "XXX clean up orphaned instance", instances[0]
693 instances[0].delete()
Scott Baker868dabf2015-06-24 12:54:24 -0700694
Scott Baker5b8eb412016-02-02 16:56:18 -0800695 def get_slice(self):
696 if not self.provider_service.slices.count():
Matteo Scandoloc6103aa2016-04-07 14:38:54 -0700697 print self, "dio porco"
Scott Baker5b8eb412016-02-02 16:56:18 -0800698 raise XOSConfigurationError("The service has no slices")
699 slice = self.provider_service.slices.all()[0]
700 return slice
701
Scott Baker67074ab2016-03-04 11:29:02 -0800702 def get_vsg_service(self):
703 return VSGService.get_service_objects().get(id=self.provider_service.id)
704
Scott Baker5b8eb412016-02-02 16:56:18 -0800705 def find_instance_for_s_tag(self, s_tag):
706 #s_tags = STagBlock.objects.find(s_s_tag)
707 #if s_tags:
708 # return s_tags[0].instance
709
710 tags = Tag.objects.filter(name="s_tag", value=s_tag)
711 if tags:
712 return tags[0].content_object
713
714 return None
715
716 def find_or_make_instance_for_s_tag(self, s_tag):
717 instance = self.find_instance_for_s_tag(self.volt.s_tag)
718 if instance:
719 return instance
720
721 flavors = Flavor.objects.filter(name="m1.small")
722 if not flavors:
723 raise XOSConfigurationError("No m1.small flavor")
724
725 slice = self.provider_service.slices.all()[0]
726
727 if slice.default_isolation == "container_vm":
728 (node, parent) = ContainerVmScheduler(slice).pick()
729 else:
Scott Baker67074ab2016-03-04 11:29:02 -0800730 (node, parent) = LeastLoadedNodeScheduler(slice, label=self.get_vsg_service().node_label).pick()
Scott Baker5b8eb412016-02-02 16:56:18 -0800731
732 instance = Instance(slice = slice,
733 node = node,
734 image = self.image,
735 creator = self.creator,
736 deployment = node.site_deployment.deployment,
737 flavor = flavors[0],
738 isolation = slice.default_isolation,
739 parent = parent)
Scott Baker63c8b372016-02-12 16:17:04 -0800740
Scott Baker5b8eb412016-02-02 16:56:18 -0800741 self.save_instance(instance)
742
743 return instance
744
745 def manage_container(self):
746 from core.models import Instance, Flavor
747
748 if self.deleted:
749 return
750
751 # For container or container_vm isolation, use what TenantWithCotnainer
752 # provides us
753 slice = self.get_slice()
754 if slice.default_isolation in ["container_vm", "container"]:
Scott Baker4c052b22016-02-11 11:08:42 -0800755 super(VSGTenant,self).manage_container()
Scott Baker5b8eb412016-02-02 16:56:18 -0800756 return
757
758 if not self.volt:
759 raise XOSConfigurationError("This vCPE container has no volt")
760
Scott Bakercf6eb992016-02-18 06:43:02 -0800761 if self.instance:
762 # We're good.
763 return
764
Scott Baker5b8eb412016-02-02 16:56:18 -0800765 instance = self.find_or_make_instance_for_s_tag(self.volt.s_tag)
766 self.instance = instance
767 super(TenantWithContainer, self).save()
768
769 def cleanup_container(self):
770 if self.get_slice().default_isolation in ["container_vm", "container"]:
Scott Baker4c052b22016-02-11 11:08:42 -0800771 super(VSGTenant,self).cleanup_container()
Scott Baker5b8eb412016-02-02 16:56:18 -0800772
773 # To-do: cleanup unused instances
774 pass
775
Scott Baker4e6d60d2015-05-20 20:45:11 -0700776 def manage_bbs_account(self):
777 if self.deleted:
778 return
779
Scott Baker126ad472015-07-07 17:59:44 -0700780 if self.volt and self.volt.subscriber and self.volt.subscriber.url_filter_enable:
Scott Baker642126f2015-05-20 20:57:28 -0700781 if not self.bbs_account:
Scott Bakerf91e6152016-02-11 12:07:10 -0800782 # make sure we use the proxied VSGService object, not the generic Service object
783 vcpe_service = VSGService.objects.get(id=self.provider_service.id)
Scott Baker050f8b32015-07-07 12:15:03 -0700784 self.bbs_account = vcpe_service.allocate_bbs_account()
Scott Baker4c052b22016-02-11 11:08:42 -0800785 super(VSGTenant, self).save()
Scott Baker642126f2015-05-20 20:57:28 -0700786 else:
787 if self.bbs_account:
788 self.bbs_account = None
Scott Baker4c052b22016-02-11 11:08:42 -0800789 super(VSGTenant, self).save()
Scott Baker4e6d60d2015-05-20 20:45:11 -0700790
Scott Baker6fd78342016-02-18 15:18:47 -0800791 def get_wan_address_from_pool(self):
792 ap = AddressPool.objects.filter(name="public_addresses")
793 if not ap:
794 raise Exception("AddressPool 'public_addresses' does not exist. Please configure it.")
795 ap = ap[0]
796
797 addr = ap.get_address()
798 if not addr:
799 raise Exception("AddressPool 'public_addresses' has run out of addresses.")
800 return addr
801
802 def put_wan_address_to_pool(self, addr):
803 AddressPool.objects.filter(name="public_addresses")[0].put_address(addr)
804
Scott Bakere6780e92016-02-13 14:38:43 -0800805 def manage_wan_container_ip(self):
806 if CORD_USE_VTN:
807 if not self.wan_container_ip:
Scott Baker6fd78342016-02-18 15:18:47 -0800808 addr = self.get_wan_address_from_pool()
Scott Bakere6780e92016-02-13 14:38:43 -0800809
810 self.wan_container_ip = addr
Scott Bakercf6eb992016-02-18 06:43:02 -0800811 super(TenantWithContainer, self).save()
Scott Bakere6780e92016-02-13 14:38:43 -0800812
813 def cleanup_wan_container_ip(self):
814 if CORD_USE_VTN and self.wan_container_ip:
Scott Baker6fd78342016-02-18 15:18:47 -0800815 self.put_wan_address_to_pool(self.wan_container_ip)
Scott Bakere6780e92016-02-13 14:38:43 -0800816 self.wan_container_ip = None
817
Scott Baker839daa82015-11-16 22:53:49 -0800818 def find_or_make_port(self, instance, network, **kwargs):
819 port = Port.objects.filter(instance=instance, network=network)
820 if port:
821 port = port[0]
822 else:
823 port = Port(instance=instance, network=network, **kwargs)
824 port.save()
825 return port
826
Scott Baker63c8b372016-02-12 16:17:04 -0800827 def get_lan_network(self, instance):
Scott Baker63c8b372016-02-12 16:17:04 -0800828 slice = self.provider_service.slices.all()[0]
Scott Bakere6780e92016-02-13 14:38:43 -0800829 if CORD_USE_VTN:
830 # there should only be one network private network, and its template should not be the management template
831 lan_networks = [x for x in slice.networks.all() if x.template.visibility=="private" and (not "management" in x.template.name)]
832 if len(lan_networks)>1:
833 raise XOSProgrammingError("The vSG slice should only have one non-management private network")
834 else:
835 lan_networks = [x for x in slice.networks.all() if "lan" in x.name]
Scott Baker63c8b372016-02-12 16:17:04 -0800836 if not lan_networks:
837 raise XOSProgrammingError("No lan_network")
838 return lan_networks[0]
839
Scott Baker839daa82015-11-16 22:53:49 -0800840 def save_instance(self, instance):
841 with transaction.atomic():
Andy Bavier1aa49af2015-12-16 14:10:01 -0500842 instance.volumes = "/etc/dnsmasq.d,/etc/ufw"
Scott Baker4c052b22016-02-11 11:08:42 -0800843 super(VSGTenant, self).save_instance(instance)
Scott Baker839daa82015-11-16 22:53:49 -0800844
845 if instance.isolation in ["container", "container_vm"]:
Scott Baker63c8b372016-02-12 16:17:04 -0800846 lan_network = self.get_lan_network(instance)
847 port = self.find_or_make_port(instance, lan_network, ip="192.168.0.1", port_id="unmanaged")
Scott Baker839daa82015-11-16 22:53:49 -0800848 port.set_parameter("c_tag", self.volt.c_tag)
849 port.set_parameter("s_tag", self.volt.s_tag)
850 port.set_parameter("device", "eth1")
Scott Bakere2920b22015-11-19 16:51:27 -0800851 port.set_parameter("bridge", "br-lan")
Scott Baker839daa82015-11-16 22:53:49 -0800852
853 wan_networks = [x for x in instance.slice.networks.all() if "wan" in x.name]
854 if not wan_networks:
855 raise XOSProgrammingError("No wan_network")
856 port = self.find_or_make_port(instance, wan_networks[0])
857 port.set_parameter("next_hop", value="10.0.1.253") # FIX ME
858 port.set_parameter("device", "eth0")
859
Scott Baker63c8b372016-02-12 16:17:04 -0800860 if instance.isolation in ["vm"]:
861 lan_network = self.get_lan_network(instance)
862 port = self.find_or_make_port(instance, lan_network)
863 port.set_parameter("c_tag", self.volt.c_tag)
864 port.set_parameter("s_tag", self.volt.s_tag)
865 port.set_parameter("neutron_port_name", "stag-%s" % self.volt.s_tag)
866 port.save()
867
Scott Baker5b8eb412016-02-02 16:56:18 -0800868 # tag the instance with the s-tag, so we can easily find the
869 # instance later
870 if self.volt and self.volt.s_tag:
871 tags = Tag.objects.filter(name="s_tag", value=self.volt.s_tag)
872 if not tags:
873 tag = Tag(service=self.provider_service, content_object=instance, name="s_tag", value=self.volt.s_tag)
874 tag.save()
875
Scott Baker6fd78342016-02-18 15:18:47 -0800876 # VTN-CORD needs a WAN address for the VM, so that the VM can
877 # be configured.
878 if CORD_USE_VTN:
879 tags = Tag.select_by_content_object(instance).filter(name="vm_wan_addr")
880 if not tags:
881 address = self.get_wan_address_from_pool()
882 tag = Tag(service=self.provider_service, content_object=instance, name="vm_wan_addr", value="%s,%s,%s" % ("public_addresses", address, self.ip_to_mac(address)))
883 tag.save()
884
Scott Bakere9ff7ce2015-04-14 17:19:16 -0700885 def save(self, *args, **kwargs):
Scott Bakerc633dc92015-05-05 17:49:46 -0700886 if not self.creator:
887 if not getattr(self, "caller", None):
888 # caller must be set when creating a vCPE since it creates a slice
Scott Baker4c052b22016-02-11 11:08:42 -0800889 raise XOSProgrammingError("VSGTenant's self.caller was not set")
Scott Bakerc633dc92015-05-05 17:49:46 -0700890 self.creator = self.caller
891 if not self.creator:
Scott Baker4c052b22016-02-11 11:08:42 -0800892 raise XOSProgrammingError("VSGTenant's self.creator was not set")
Scott Bakerc633dc92015-05-05 17:49:46 -0700893
Scott Baker4c052b22016-02-11 11:08:42 -0800894 super(VSGTenant, self).save(*args, **kwargs)
Scott Baker192da222015-07-08 19:01:56 -0700895 model_policy_vcpe(self.pk)
Scott Bakere9ff7ce2015-04-14 17:19:16 -0700896
897 def delete(self, *args, **kwargs):
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700898 self.cleanup_vbng()
Scott Bakerc1584b82015-09-09 16:36:06 -0700899 self.cleanup_container()
Scott Bakere6780e92016-02-13 14:38:43 -0800900 self.cleanup_wan_container_ip()
Scott Baker4c052b22016-02-11 11:08:42 -0800901 super(VSGTenant, self).delete(*args, **kwargs)
Scott Bakere9ff7ce2015-04-14 17:19:16 -0700902
Scott Baker192da222015-07-08 19:01:56 -0700903def model_policy_vcpe(pk):
904 # TODO: this should be made in to a real model_policy
905 with transaction.atomic():
Scott Baker4c052b22016-02-11 11:08:42 -0800906 vcpe = VSGTenant.objects.select_for_update().filter(pk=pk)
Scott Baker192da222015-07-08 19:01:56 -0700907 if not vcpe:
908 return
909 vcpe = vcpe[0]
Scott Bakere6780e92016-02-13 14:38:43 -0800910 vcpe.manage_wan_container_ip()
Scott Bakerc1584b82015-09-09 16:36:06 -0700911 vcpe.manage_container()
Scott Baker47075932016-04-13 09:12:45 -0700912 vcpe.manage_vrouter()
913 #vcpe.manage_vbng()
Scott Baker192da222015-07-08 19:01:56 -0700914 vcpe.manage_bbs_account()
915 vcpe.cleanup_orphans()
916
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700917#----------------------------------------------------------------------------
918# vBNG
919#----------------------------------------------------------------------------
920
921class VBNGService(Service):
Scott Bakerd9133342015-07-06 14:38:02 -0700922 KIND = VBNG_KIND
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700923
Scott Baker6667ddc2015-10-20 22:12:51 -0700924 simple_attributes = ( ("vbng_url", ""), ) # "http://10.0.3.136:8181/onos/virtualbng/"
Scott Baker21d18932015-07-21 18:24:21 -0700925
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700926 class Meta:
927 app_label = "cord"
928 verbose_name = "vBNG Service"
929 proxy = True
930
Scott Baker21d18932015-07-21 18:24:21 -0700931VBNGService.setup_simple_attributes()
932
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700933class VBNGTenant(Tenant):
934 class Meta:
935 proxy = True
936
Scott Bakerd9133342015-07-06 14:38:02 -0700937 KIND = VBNG_KIND
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700938
Scott Baker61c8e8d2015-06-02 14:34:04 -0700939 default_attributes = {"routeable_subnet": "",
Scott Bakercf155f42015-06-08 19:09:53 -0700940 "mapped_ip": "",
941 "mapped_mac": "",
942 "mapped_hostname": ""}
Scott Bakerfa5cdd62015-04-20 09:16:17 -0700943
944 @property
945 def routeable_subnet(self):
946 return self.get_attribute("routeable_subnet", self.default_attributes["routeable_subnet"])
947
948 @routeable_subnet.setter
949 def routeable_subnet(self, value):
950 self.set_attribute("routeable_subnet", value)
Scott Baker61c8e8d2015-06-02 14:34:04 -0700951
952 @property
953 def mapped_ip(self):
954 return self.get_attribute("mapped_ip", self.default_attributes["mapped_ip"])
955
956 @mapped_ip.setter
957 def mapped_ip(self, value):
958 self.set_attribute("mapped_ip", value)
Scott Bakercf155f42015-06-08 19:09:53 -0700959
960 @property
961 def mapped_mac(self):
962 return self.get_attribute("mapped_mac", self.default_attributes["mapped_mac"])
963
964 @mapped_mac.setter
965 def mapped_mac(self, value):
966 self.set_attribute("mapped_mac", value)
967
968 @property
969 def mapped_hostname(self):
970 return self.get_attribute("mapped_hostname", self.default_attributes["mapped_hostname"])
971
972 @mapped_hostname.setter
973 def mapped_hostname(self, value):
974 self.set_attribute("mapped_hostname", value)