blob: 016cb3d6ee6fe5ef40f04c164497babb09197f4b [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"
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)