blob: 8396d3e2d347b566905efd2c19a5567dc9eb9f2b [file] [log] [blame]
Scott Baker87eb7402016-06-20 17:21:50 -07001from django.db import models
2from core.models import Service, PlCoreBase, Slice, Instance, Tenant, TenantWithContainer, Node, Image, User, Flavor, Subscriber, NetworkParameter, NetworkParameterType, Port, AddressPool
3from core.models.plcorebase import StrippedCharField
4import os
5from django.db import models, transaction
6from django.forms.models import model_to_dict
7from django.db.models import Q
8from operator import itemgetter, attrgetter, methodcaller
9from core.models import Tag
10from core.models.service import LeastLoadedNodeScheduler
11import traceback
12from xos.exceptions import *
13from xos.config import Config
14
Matteo Scandoloa4e6e9a2016-08-23 12:04:45 -070015
Scott Baker87eb7402016-06-20 17:21:50 -070016class ConfigurationError(Exception):
17 pass
18
19
20VROUTER_KIND = "vROUTER"
Matteo Scandoloa4e6e9a2016-08-23 12:04:45 -070021APP_LABEL = "vrouter"
Scott Baker87eb7402016-06-20 17:21:50 -070022
23# NOTE: don't change VROUTER_KIND unless you also change the reference to it
24# in tosca/resources/network.py
25
26CORD_USE_VTN = getattr(Config(), "networking_use_vtn", False)
27
Matteo Scandoloa4e6e9a2016-08-23 12:04:45 -070028
Scott Baker87eb7402016-06-20 17:21:50 -070029class VRouterService(Service):
30 KIND = VROUTER_KIND
31
32 class Meta:
Matteo Scandoloa4e6e9a2016-08-23 12:04:45 -070033 app_label = APP_LABEL
Scott Baker87eb7402016-06-20 17:21:50 -070034 verbose_name = "vRouter Service"
35 proxy = True
36
Matteo Scandoloa4e6e9a2016-08-23 12:04:45 -070037 default_attributes = {
38 "rest_hostname": "",
39 "rest_port": "8181",
40 "rest_user": "onos",
41 "rest_pass": "rocks"
42 }
43
44 @property
45 def rest_hostname(self):
46 return self.get_attribute("rest_hostname", self.default_attributes["rest_hostname"])
47
48 @rest_hostname.setter
49 def rest_hostname(self, value):
50 self.set_attribute("rest_hostname", value)
51
52 @property
53 def rest_port(self):
54 return self.get_attribute("rest_port", self.default_attributes["rest_port"])
55
56 @rest_port.setter
57 def rest_port(self, value):
58 self.set_attribute("rest_port", value)
59
60 @property
61 def rest_user(self):
62 return self.get_attribute("rest_user", self.default_attributes["rest_user"])
63
64 @rest_user.setter
65 def rest_user(self, value):
66 self.set_attribute("rest_user", value)
67
68 @property
69 def rest_pass(self):
70 return self.get_attribute("rest_pass", self.default_attributes["rest_pass"])
71
72 @rest_pass.setter
73 def rest_pass(self, value):
74 self.set_attribute("rest_pass", value)
75
Scott Baker87eb7402016-06-20 17:21:50 -070076 def ip_to_mac(self, ip):
77 (a, b, c, d) = ip.split('.')
78 return "02:42:%02x:%02x:%02x:%02x" % (int(a), int(b), int(c), int(d))
79
80 def get_gateways(self):
Matteo Scandoloa4e6e9a2016-08-23 12:04:45 -070081 gateways = []
Scott Baker87eb7402016-06-20 17:21:50 -070082
83 aps = self.addresspools.all()
84 for ap in aps:
Matteo Scandoloa4e6e9a2016-08-23 12:04:45 -070085 gateways.append({"gateway_ip": ap.gateway_ip, "gateway_mac": ap.gateway_mac})
Scott Baker87eb7402016-06-20 17:21:50 -070086
87 return gateways
88
89 def get_address_pool(self, name):
90 ap = AddressPool.objects.filter(name=name, service=self)
91 if not ap:
92 raise Exception("vRouter unable to find addresspool %s" % name)
93 return ap[0]
94
95 def get_tenant(self, **kwargs):
96 address_pool_name = kwargs.pop("address_pool_name")
97
98 ap = self.get_address_pool(address_pool_name)
99
100 ip = ap.get_address()
101 if not ip:
102 raise Exception("AddressPool '%s' has run out of addresses." % ap.name)
103
104 t = VRouterTenant(provider_service=self, **kwargs)
105 t.public_ip = ip
106 t.public_mac = self.ip_to_mac(ip)
107 t.address_pool_id = ap.id
108 t.save()
109
110 return t
111
Scott Baker87eb7402016-06-20 17:21:50 -0700112
113class VRouterTenant(Tenant):
114 class Meta:
115 proxy = True
Matteo Scandoloa4e6e9a2016-08-23 12:04:45 -0700116 verbose_name = "vRouter Tenant"
Scott Baker87eb7402016-06-20 17:21:50 -0700117
118 KIND = VROUTER_KIND
119
Matteo Scandoloa4e6e9a2016-08-23 12:04:45 -0700120 simple_attributes = (
121 ("public_ip", None),
122 ("public_mac", None),
123 ("address_pool_id", None),
124 )
Scott Baker87eb7402016-06-20 17:21:50 -0700125
126 @property
127 def gateway_ip(self):
128 if not self.address_pool:
129 return None
130 return self.address_pool.gateway_ip
131
132 @property
133 def gateway_mac(self):
134 if not self.address_pool:
135 return None
136 return self.address_pool.gateway_mac
137
138 @property
139 def cidr(self):
140 if not self.address_pool:
141 return None
142 return self.address_pool.cidr
143
144 @property
145 def netbits(self):
146 # return number of bits in the network portion of the cidr
147 if self.cidr:
148 parts = self.cidr.split("/")
Matteo Scandoloa4e6e9a2016-08-23 12:04:45 -0700149 if len(parts) == 2:
Scott Baker87eb7402016-06-20 17:21:50 -0700150 return int(parts[1].strip())
151 return None
152
153 @property
154 def address_pool(self):
155 if getattr(self, "cached_address_pool", None):
156 return self.cached_address_pool
157 if not self.address_pool_id:
158 return None
Matteo Scandoloa4e6e9a2016-08-23 12:04:45 -0700159 aps = AddressPool.objects.filter(id=self.address_pool_id)
Scott Baker87eb7402016-06-20 17:21:50 -0700160 if not aps:
161 return None
Matteo Scandoloa4e6e9a2016-08-23 12:04:45 -0700162 ap = aps[0]
Scott Baker87eb7402016-06-20 17:21:50 -0700163 self.cached_address_pool = ap
164 return ap
165
166 @address_pool.setter
167 def address_pool(self, value):
168 if value:
169 value = value.id
170 if (value != self.get_attribute("address_pool_id", None)):
Matteo Scandoloa4e6e9a2016-08-23 12:04:45 -0700171 self.cached_address_pool = None
Scott Baker87eb7402016-06-20 17:21:50 -0700172 self.set_attribute("address_pool_id", value)
173
174 def cleanup_addresspool(self):
175 if self.address_pool_id:
176 ap = AddressPool.objects.filter(id=self.address_pool_id)
177 if ap:
178 ap[0].put_address(self.public_ip)
179 self.public_ip = None
180
181 def delete(self, *args, **kwargs):
182 self.cleanup_addresspool()
183 super(VRouterTenant, self).delete(*args, **kwargs)
184
185VRouterTenant.setup_simple_attributes()
186
Matteo Scandoloa4e6e9a2016-08-23 12:04:45 -0700187
188# DEVICES
189class VRouterDevice(PlCoreBase):
190 """define the information related to an device used by vRouter"""
191 class Meta:
192 app_label = APP_LABEL
193 verbose_name = "vRouter Device"
194
195 name = models.CharField(max_length=20, help_text="device friendly name", null=True, blank=True)
196 openflow_id = models.CharField(max_length=20, help_text="device identifier in ONOS", null=False, blank=False)
197 config_key = models.CharField(max_length=32, help_text="configuration key", null=False, blank=False, default="basic")
198 driver = models.CharField(max_length=32, help_text="driver type", null=False, blank=False)
199 vrouter_service = models.ForeignKey(VRouterService, related_name='devices')
200
201
202# PORTS
203class VRouterPort(PlCoreBase):
204 class Meta:
205 app_label = APP_LABEL
206 verbose_name = "vRouter Port"
207
208 name = models.CharField(max_length=20, help_text="port friendly name", null=True, blank=True)
209 openflow_id = models.CharField(max_length=21, help_text="port identifier in ONOS", null=False, blank=False)
210 vrouter_device = models.ForeignKey(VRouterDevice, related_name='ports')
211 # NOTE probably is not meaningful to relate a port to a service
212 vrouter_service = models.ForeignKey(VRouterService, related_name='device_ports')
213
214
215class VRouterInterface(PlCoreBase):
216 class Meta:
217 app_label = APP_LABEL
218 verbose_name = "vRouter Interface"
219
220 name = models.CharField(max_length=20, help_text="interface friendly name", null=True, blank=True)
221 vrouter_port = models.ForeignKey(VRouterPort, related_name='interfaces')
222 name = models.CharField(max_length=10, help_text="interface name", null=False, blank=False)
223 mac = models.CharField(max_length=17, help_text="interface mac", null=False, blank=False)
224 vlan = models.CharField(max_length=10, help_text="interface vlan id", null=True, blank=True)
225
226
227class VRouterIp(PlCoreBase):
228 class Meta:
229 app_label = APP_LABEL
230 verbose_name = "vRouter Ip"
231
232 name = models.CharField(max_length=20, help_text="ip friendly name", null=True, blank=True)
233 vrouter_interface = models.ForeignKey(VRouterInterface, related_name='ips')
234 ip = models.CharField(max_length=19, help_text="interface ips", null=False, blank=False)
235
236
237# APPS
238class VRouterApp(PlCoreBase):
239 class Meta:
240 app_label = "vrouter"
241 verbose_name = "vRouter App"
242
243 def _get_interfaces(self):
244 app_interfaces = []
245 devices = VRouterDevice.objects.filter(vrouter_service=self.vrouter_service)
246 for device in devices:
247 ports = VRouterPort.objects.filter(vrouter_device=device.id)
248 for port in ports:
249 interfaces = VRouterInterface.objects.filter(vrouter_port=port.id)
250 for iface in interfaces:
251 app_interfaces.append(iface.name)
252 return app_interfaces
253
254 vrouter_service = models.ForeignKey(VRouterService, related_name='apps')
255 name = models.CharField(max_length=50, help_text="application name", null=False, blank=False)
256 control_plane_connect_point = models.CharField(max_length=21, help_text="port identifier in ONOS", null=False, blank=False)
257 ospf_enabled = models.BooleanField(default=True, help_text="ospf enabled")
258 interfaces = property(_get_interfaces)