blob: 98faaadffe27a24dbdd16ad3c47ba76dc36f7759 [file] [log] [blame]
Scott Baker87eb7402016-06-20 17:21:50 -07001from django.db import models
Scott Bakere28aa452017-03-20 18:48:44 -07002from core.models import Service, PlCoreBase, Slice, Instance, Tenant, TenantWithContainer, Node, Image, User, Flavor, NetworkParameter, NetworkParameterType, Port, AddressPool
Scott Baker87eb7402016-06-20 17:21:50 -07003from 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"
Scott Baker87eb7402016-06-20 17:21:50 -070035
Scott Bakerd94cbfc2017-03-13 11:40:46 -070036 # Are rest_hostname and rest_port redundant with ONOS service?
37 # Should ONOSService be augmented with rest_user and rest_pass?
Matteo Scandoloa4e6e9a2016-08-23 12:04:45 -070038
Scott Bakerd94cbfc2017-03-13 11:40:46 -070039 rest_hostname = StrippedCharField(max_length=255, null=True, blank=True)
40 rest_port = models.IntegerField(default=8181)
41 rest_user = StrippedCharField(max_length=255, default="onos")
42 rest_pass = StrippedCharField(max_length=255, default="rocks")
Matteo Scandoloa4e6e9a2016-08-23 12:04:45 -070043
Scott Baker87eb7402016-06-20 17:21:50 -070044 def ip_to_mac(self, ip):
45 (a, b, c, d) = ip.split('.')
46 return "02:42:%02x:%02x:%02x:%02x" % (int(a), int(b), int(c), int(d))
47
48 def get_gateways(self):
Matteo Scandoloa4e6e9a2016-08-23 12:04:45 -070049 gateways = []
Scott Baker87eb7402016-06-20 17:21:50 -070050
51 aps = self.addresspools.all()
52 for ap in aps:
Matteo Scandoloa4e6e9a2016-08-23 12:04:45 -070053 gateways.append({"gateway_ip": ap.gateway_ip, "gateway_mac": ap.gateway_mac})
Scott Baker87eb7402016-06-20 17:21:50 -070054
55 return gateways
56
57 def get_address_pool(self, name):
58 ap = AddressPool.objects.filter(name=name, service=self)
59 if not ap:
60 raise Exception("vRouter unable to find addresspool %s" % name)
61 return ap[0]
62
63 def get_tenant(self, **kwargs):
64 address_pool_name = kwargs.pop("address_pool_name")
65
66 ap = self.get_address_pool(address_pool_name)
67
68 ip = ap.get_address()
69 if not ip:
70 raise Exception("AddressPool '%s' has run out of addresses." % ap.name)
71
72 t = VRouterTenant(provider_service=self, **kwargs)
73 t.public_ip = ip
74 t.public_mac = self.ip_to_mac(ip)
75 t.address_pool_id = ap.id
76 t.save()
77
78 return t
79
Scott Baker87eb7402016-06-20 17:21:50 -070080
81class VRouterTenant(Tenant):
82 class Meta:
Matteo Scandoloa4e6e9a2016-08-23 12:04:45 -070083 verbose_name = "vRouter Tenant"
Scott Baker87eb7402016-06-20 17:21:50 -070084
85 KIND = VROUTER_KIND
86
Scott Bakerd94cbfc2017-03-13 11:40:46 -070087 public_ip = StrippedCharField(max_length = 30, null=True, blank=True)
88 public_mac = StrippedCharField(max_length = 30, null=True, blank=True)
89 address_pool = models.ForeignKey(AddressPool, related_name='vrouter_tenants', blank=True, null=True)
Scott Baker87eb7402016-06-20 17:21:50 -070090
91 @property
92 def gateway_ip(self):
93 if not self.address_pool:
94 return None
95 return self.address_pool.gateway_ip
96
97 @property
98 def gateway_mac(self):
99 if not self.address_pool:
100 return None
101 return self.address_pool.gateway_mac
102
103 @property
104 def cidr(self):
105 if not self.address_pool:
106 return None
107 return self.address_pool.cidr
108
109 @property
110 def netbits(self):
111 # return number of bits in the network portion of the cidr
112 if self.cidr:
113 parts = self.cidr.split("/")
Matteo Scandoloa4e6e9a2016-08-23 12:04:45 -0700114 if len(parts) == 2:
Scott Baker87eb7402016-06-20 17:21:50 -0700115 return int(parts[1].strip())
116 return None
117
Scott Baker87eb7402016-06-20 17:21:50 -0700118 def cleanup_addresspool(self):
Scott Bakerd94cbfc2017-03-13 11:40:46 -0700119 if self.address_pool:
120 ap = self.address_pool
Scott Baker87eb7402016-06-20 17:21:50 -0700121 if ap:
122 ap[0].put_address(self.public_ip)
123 self.public_ip = None
124
125 def delete(self, *args, **kwargs):
126 self.cleanup_addresspool()
127 super(VRouterTenant, self).delete(*args, **kwargs)
128
Matteo Scandoloa4e6e9a2016-08-23 12:04:45 -0700129
130# DEVICES
131class VRouterDevice(PlCoreBase):
132 """define the information related to an device used by vRouter"""
133 class Meta:
134 app_label = APP_LABEL
135 verbose_name = "vRouter Device"
136
137 name = models.CharField(max_length=20, help_text="device friendly name", null=True, blank=True)
138 openflow_id = models.CharField(max_length=20, help_text="device identifier in ONOS", null=False, blank=False)
139 config_key = models.CharField(max_length=32, help_text="configuration key", null=False, blank=False, default="basic")
140 driver = models.CharField(max_length=32, help_text="driver type", null=False, blank=False)
141 vrouter_service = models.ForeignKey(VRouterService, related_name='devices')
142
143
144# PORTS
145class VRouterPort(PlCoreBase):
146 class Meta:
147 app_label = APP_LABEL
148 verbose_name = "vRouter Port"
149
150 name = models.CharField(max_length=20, help_text="port friendly name", null=True, blank=True)
151 openflow_id = models.CharField(max_length=21, help_text="port identifier in ONOS", null=False, blank=False)
152 vrouter_device = models.ForeignKey(VRouterDevice, related_name='ports')
153 # NOTE probably is not meaningful to relate a port to a service
154 vrouter_service = models.ForeignKey(VRouterService, related_name='device_ports')
155
156
157class VRouterInterface(PlCoreBase):
158 class Meta:
159 app_label = APP_LABEL
160 verbose_name = "vRouter Interface"
161
162 name = models.CharField(max_length=20, help_text="interface friendly name", null=True, blank=True)
163 vrouter_port = models.ForeignKey(VRouterPort, related_name='interfaces')
164 name = models.CharField(max_length=10, help_text="interface name", null=False, blank=False)
165 mac = models.CharField(max_length=17, help_text="interface mac", null=False, blank=False)
166 vlan = models.CharField(max_length=10, help_text="interface vlan id", null=True, blank=True)
167
168
169class VRouterIp(PlCoreBase):
170 class Meta:
171 app_label = APP_LABEL
172 verbose_name = "vRouter Ip"
173
174 name = models.CharField(max_length=20, help_text="ip friendly name", null=True, blank=True)
175 vrouter_interface = models.ForeignKey(VRouterInterface, related_name='ips')
176 ip = models.CharField(max_length=19, help_text="interface ips", null=False, blank=False)
177
178
179# APPS
180class VRouterApp(PlCoreBase):
181 class Meta:
182 app_label = "vrouter"
183 verbose_name = "vRouter App"
184
185 def _get_interfaces(self):
186 app_interfaces = []
187 devices = VRouterDevice.objects.filter(vrouter_service=self.vrouter_service)
188 for device in devices:
189 ports = VRouterPort.objects.filter(vrouter_device=device.id)
190 for port in ports:
191 interfaces = VRouterInterface.objects.filter(vrouter_port=port.id)
192 for iface in interfaces:
193 app_interfaces.append(iface.name)
194 return app_interfaces
195
196 vrouter_service = models.ForeignKey(VRouterService, related_name='apps')
197 name = models.CharField(max_length=50, help_text="application name", null=False, blank=False)
198 control_plane_connect_point = models.CharField(max_length=21, help_text="port identifier in ONOS", null=False, blank=False)
199 ospf_enabled = models.BooleanField(default=True, help_text="ospf enabled")
200 interfaces = property(_get_interfaces)