blob: 7194f456fe615b33a990e429d2816a03495c3f4b [file] [log] [blame]
Andy Bavier7b321c52017-08-30 15:33:59 -07001
2# Copyright 2017-present Open Networking Foundation
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16
17from synchronizers.new_base.modelaccessor import *
18in_synchronizer = True
19
20class VTNNetwork(object):
21 def __init__(self, xos_network=None):
22 self.xos_network = xos_network
23
24 def get_controller_network(self):
25 for cn in self.xos_network.controllernetworks.all():
26 # TODO: find the right one
27 return cn
28 return None
29
30 def get_cn_field(self, fieldname):
31 cn=self.get_controller_network()
32 if not cn:
33 return None
34 return getattr(cn, fieldname)
35
36 @property
37 def id(self):
38 return self.get_cn_field("net_id")
39
40 @property
41 def name(self):
42 return self.xos_network.name
43
44 @property
45 def subnet(self):
46 return self.get_cn_field("subnet")
47
48 @property
49 def gateway(self):
50 return self.get_cn_field("gateway")
51
52 @property
53 def segmentation_id(self):
54 return self.get_cn_field("segmentation_id")
55
56 @property
57 def type(self):
58 return self.xos_network.template.vtn_kind
59
60 @property
61 def providerNetworks(self):
62 slice = self.xos_network.owner
63 service = slice.service
64 if not service:
65 return []
66
67 nets=[]
68 for dep in service.subscribed_dependencies.all():
69 if dep.provider_service:
70 bidirectional = dep.connect_method!="private-unidirectional"
71 for net in dep.provider_service.get_composable_networks():
72 if not net.controllernetworks.exists():
73 continue
74
75 cn = net.controllernetworks.all()[0]
76
77 if not cn.net_id:
78 continue
79
80 nets.append({"id": cn.net_id,
81 "name": net.name,
82 "bidirectional": bidirectional})
83 return nets
84
85 @property
86 def subscriberNetworks(self):
87 slice = self.xos_network.owner
88 service = slice.service
89 if not service:
90 return []
91
92 nets=[]
93 for dep in service.provided_dependencies.all():
94 if dep.subscriber_service:
95 bidirectional = dep.connect_method!="private-unidirectional"
96 for net in dep.subscriber_service.get_composable_networks():
97 if not net.controllernetworks.exists():
98 continue
99
100 cn = net.controllernetworks.all()[0]
101
102 if not cn.net_id:
103 continue
104
105 nets.append({"id": cn.net_id,
106 "name": net.name,
107 "bidirectional": bidirectional})
108 return nets
109
110 @property
111 def ownerSliceName(self):
112 if self.xos_network.owner:
113 return self.xos_network.owner.name
114 return None
115
116 @property
117 def ownerServiceName(self):
118 if self.xos_network.owner and self.xos_network.owner.service:
119 return self.xos_network.owner.service.name
120 return None
121
122 def to_dict(self):
123 return {"id": self.id,
124 "name": self.name,
125 "subnet": self.subnet,
126 "gateway": self.gateway,
127 "segmentation_id": self.segmentation_id,
128 "type": self.type,
129 "providerNetworks": self.providerNetworks,
130 "subscriberNetworks": self.subscriberNetworks,
131 "ownerSliceName": self.ownerSliceName,
132 "ownerServiceName": self.ownerServiceName}
133
134 def __eq__(self, other):
135 return self.to_dict() == other.to_dict()
136
137class VTNPort(object):
138 def __init__(self, xos_port=None):
139 self.xos_port = xos_port
140
141 def get_controller_network(self):
142 for cn in self.xos_port.network.controllernetworks.all():
143 # TODO: find the right one
144 return cn
145 return None
146
147 def is_access_network(self):
148 """ Determines whether this port is attached to an access network. Currently we do this by examining the
149 network template's vtn_kind field. See if there is a better way...
150 """
151 return self.xos_port.network.template.vtn_kind in ["VSG", ]
152
153 def get_vm_addresses(self):
154 if not self.is_access_network():
155 # If not an access network, do not apply any addresses
156 return []
157
158 if not self.xos_port.instance:
159 return []
160
161 # See if the Instance has any public address (aka "VrouterTenant) service instances associated with it.
162 # If so, then add each of those to the set of address pairs.
163
164 # TODO: Perhaps this should be implemented as a link instead of a tag...
165
166 tags = Tag.objects.filter(name="vm_public_service_instance", object_id=self.xos_port.instance.id,
167 content_type=self.xos_port.instance.self_content_type_id)
168
169 if not tags:
170 # DEPRECATED
171 # Historically, VSG instances are tagged with "vm_vrouter_tenant" instead of "vm_public_service_instance"
172 tags = Tag.objects.filter(name="vm_vrouter_tenant", object_id=self.xos_port.instance.id,
173 content_type=self.xos_port.instance.self_content_type_id)
174
175 address_pairs = []
176 for tag in tags:
177 si = ServiceInstance.objects.get(id = int(tag.value))
178
179 # cast from Tenant to descendant class (VRouterTenant, etc)
180 si = si.leaf_model
181
182 if (not hasattr(si, "public_ip")) or (not hasattr(si, "public_mac")):
183 raise Exception("Object %s does not have public_ip and/or public_mac fields" % si)
184 address_pairs.append({"ip_address": si.public_ip,
185 "mac_address": si.public_mac})
186
187 return address_pairs
188
189 def get_container_addresses(self):
190 if not self.is_access_network():
191 # If not an access network, do not apply any addresses
192 return []
193
194 if not self.xos_port.instance:
195 return []
196
197 addrs = []
198 for si in ServiceInstance.objects.all():
199 # cast from tenant to its descendant class (VSGTenant, etc)
200 si = si.leaf_model
201
202 if not hasattr(si, "instance_id"):
203 # ignore ServiceInstance that don't have instances
204 continue
205
206 if si.instance_id != self.xos_port.instance.id:
207 # ignore ServiceInstances that don't relate to our instance
208 continue
209
210 # Check to see if there is a link public address (aka VRouterTenant)
211 links = si.subscribed_links.all()
212 for link in links:
213 # cast from ServiceInstance to descendant class (VRouterTenant, etc)
214 pubaddr_si = link.provider_service_instance.leaf_model
215 if hasattr(pubaddr_si, "public_ip") and hasattr(pubaddr_si, "public_mac"):
216 addrs.append({"ip_address": pubaddr_si.public_ip,
217 "mac_address": pubaddr_si.public_mac})
218 return addrs
219
220 @property
221 def vlan_id(self):
222 """ Return the vlan_id associated with this instance. This assumes the instance was tagged with either a
223 vlan_id or s_tag tag.
224 """
225
226 if not self.is_access_network():
227 # If not an access network, do not apply any tags
Scott Bakerf6cfb382018-04-03 09:48:01 -0700228 return None
Andy Bavier7b321c52017-08-30 15:33:59 -0700229
230 if not self.xos_port.instance:
231 return None
232
233 tags = Tag.objects.filter(content_type=model_accessor.get_content_type_id(self.xos_port.instance),
234 object_id=self.xos_port.instance.id,
235 name="vlan_id")
236
237 if not tags:
238 # DEPRECATED
239 # Historically, VSG instances are tagged with "s_tag" instead of "vlan_id"
240 tags = Tag.objects.filter(content_type=model_accessor.get_content_type_id(self.xos_port.instance),
241 object_id=self.xos_port.instance.id,
242 name="s_tag")
243
244 if not tags:
245 return None
246
247 return tags[0].value
248
249 @property
250 def floating_address_pairs(self):
251 # Floating_address_pairs is the set of WAN addresses that should be
252 # applied to this port.
253
254 # We only want to apply these addresses to an "access" network.
255
256
257 address_pairs = self.get_vm_addresses() + self.get_container_addresses()
258
259 return address_pairs
260
261 @property
262 def id(self):
263 return self.xos_port.port_id
264
265 @property
266 def name(self):
Scott Bakerf6cfb382018-04-03 09:48:01 -0700267 # In OpenStack Kilo, the tap name uses the first 11 characters of the port id. Unverified if this is true for
268 # any other OpenStack.
269 return "tap" + self.xos_port.port_id[:11]
270 #return self.xos_port.name
Andy Bavier7b321c52017-08-30 15:33:59 -0700271
272 @property
273 def network_id(self):
274 cn = self.get_controller_network()
275 if not cn:
276 return None
277 return cn.net_id
278
279 @property
280 def network_name(self):
281 return self.xos_port.network.name
282
283 @property
284 def mac_address(self):
285 return self.xos_port.mac
286
287 @property
288 def ip_address(self):
289 return self.xos_port.ip
290
291 def to_dict(self):
292 return {"id": self.id,
293 "name": self.name,
294 "network_id": self.network_id,
295 "mac_address": self.mac_address,
296 "ip_address": self.ip_address,
297 "floating_address_pairs": self.floating_address_pairs,
298 "vlan_id": self.vlan_id}
299
300 def __eq__(self, other):
301 return self.to_dict() == other.to_dict()
302