blob: 7194f456fe615b33a990e429d2816a03495c3f4b [file] [log] [blame]
# Copyright 2017-present Open Networking Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from synchronizers.new_base.modelaccessor import *
in_synchronizer = True
class VTNNetwork(object):
def __init__(self, xos_network=None):
self.xos_network = xos_network
def get_controller_network(self):
for cn in self.xos_network.controllernetworks.all():
# TODO: find the right one
return cn
return None
def get_cn_field(self, fieldname):
cn=self.get_controller_network()
if not cn:
return None
return getattr(cn, fieldname)
@property
def id(self):
return self.get_cn_field("net_id")
@property
def name(self):
return self.xos_network.name
@property
def subnet(self):
return self.get_cn_field("subnet")
@property
def gateway(self):
return self.get_cn_field("gateway")
@property
def segmentation_id(self):
return self.get_cn_field("segmentation_id")
@property
def type(self):
return self.xos_network.template.vtn_kind
@property
def providerNetworks(self):
slice = self.xos_network.owner
service = slice.service
if not service:
return []
nets=[]
for dep in service.subscribed_dependencies.all():
if dep.provider_service:
bidirectional = dep.connect_method!="private-unidirectional"
for net in dep.provider_service.get_composable_networks():
if not net.controllernetworks.exists():
continue
cn = net.controllernetworks.all()[0]
if not cn.net_id:
continue
nets.append({"id": cn.net_id,
"name": net.name,
"bidirectional": bidirectional})
return nets
@property
def subscriberNetworks(self):
slice = self.xos_network.owner
service = slice.service
if not service:
return []
nets=[]
for dep in service.provided_dependencies.all():
if dep.subscriber_service:
bidirectional = dep.connect_method!="private-unidirectional"
for net in dep.subscriber_service.get_composable_networks():
if not net.controllernetworks.exists():
continue
cn = net.controllernetworks.all()[0]
if not cn.net_id:
continue
nets.append({"id": cn.net_id,
"name": net.name,
"bidirectional": bidirectional})
return nets
@property
def ownerSliceName(self):
if self.xos_network.owner:
return self.xos_network.owner.name
return None
@property
def ownerServiceName(self):
if self.xos_network.owner and self.xos_network.owner.service:
return self.xos_network.owner.service.name
return None
def to_dict(self):
return {"id": self.id,
"name": self.name,
"subnet": self.subnet,
"gateway": self.gateway,
"segmentation_id": self.segmentation_id,
"type": self.type,
"providerNetworks": self.providerNetworks,
"subscriberNetworks": self.subscriberNetworks,
"ownerSliceName": self.ownerSliceName,
"ownerServiceName": self.ownerServiceName}
def __eq__(self, other):
return self.to_dict() == other.to_dict()
class VTNPort(object):
def __init__(self, xos_port=None):
self.xos_port = xos_port
def get_controller_network(self):
for cn in self.xos_port.network.controllernetworks.all():
# TODO: find the right one
return cn
return None
def is_access_network(self):
""" Determines whether this port is attached to an access network. Currently we do this by examining the
network template's vtn_kind field. See if there is a better way...
"""
return self.xos_port.network.template.vtn_kind in ["VSG", ]
def get_vm_addresses(self):
if not self.is_access_network():
# If not an access network, do not apply any addresses
return []
if not self.xos_port.instance:
return []
# See if the Instance has any public address (aka "VrouterTenant) service instances associated with it.
# If so, then add each of those to the set of address pairs.
# TODO: Perhaps this should be implemented as a link instead of a tag...
tags = Tag.objects.filter(name="vm_public_service_instance", object_id=self.xos_port.instance.id,
content_type=self.xos_port.instance.self_content_type_id)
if not tags:
# DEPRECATED
# Historically, VSG instances are tagged with "vm_vrouter_tenant" instead of "vm_public_service_instance"
tags = Tag.objects.filter(name="vm_vrouter_tenant", object_id=self.xos_port.instance.id,
content_type=self.xos_port.instance.self_content_type_id)
address_pairs = []
for tag in tags:
si = ServiceInstance.objects.get(id = int(tag.value))
# cast from Tenant to descendant class (VRouterTenant, etc)
si = si.leaf_model
if (not hasattr(si, "public_ip")) or (not hasattr(si, "public_mac")):
raise Exception("Object %s does not have public_ip and/or public_mac fields" % si)
address_pairs.append({"ip_address": si.public_ip,
"mac_address": si.public_mac})
return address_pairs
def get_container_addresses(self):
if not self.is_access_network():
# If not an access network, do not apply any addresses
return []
if not self.xos_port.instance:
return []
addrs = []
for si in ServiceInstance.objects.all():
# cast from tenant to its descendant class (VSGTenant, etc)
si = si.leaf_model
if not hasattr(si, "instance_id"):
# ignore ServiceInstance that don't have instances
continue
if si.instance_id != self.xos_port.instance.id:
# ignore ServiceInstances that don't relate to our instance
continue
# Check to see if there is a link public address (aka VRouterTenant)
links = si.subscribed_links.all()
for link in links:
# cast from ServiceInstance to descendant class (VRouterTenant, etc)
pubaddr_si = link.provider_service_instance.leaf_model
if hasattr(pubaddr_si, "public_ip") and hasattr(pubaddr_si, "public_mac"):
addrs.append({"ip_address": pubaddr_si.public_ip,
"mac_address": pubaddr_si.public_mac})
return addrs
@property
def vlan_id(self):
""" Return the vlan_id associated with this instance. This assumes the instance was tagged with either a
vlan_id or s_tag tag.
"""
if not self.is_access_network():
# If not an access network, do not apply any tags
return None
if not self.xos_port.instance:
return None
tags = Tag.objects.filter(content_type=model_accessor.get_content_type_id(self.xos_port.instance),
object_id=self.xos_port.instance.id,
name="vlan_id")
if not tags:
# DEPRECATED
# Historically, VSG instances are tagged with "s_tag" instead of "vlan_id"
tags = Tag.objects.filter(content_type=model_accessor.get_content_type_id(self.xos_port.instance),
object_id=self.xos_port.instance.id,
name="s_tag")
if not tags:
return None
return tags[0].value
@property
def floating_address_pairs(self):
# Floating_address_pairs is the set of WAN addresses that should be
# applied to this port.
# We only want to apply these addresses to an "access" network.
address_pairs = self.get_vm_addresses() + self.get_container_addresses()
return address_pairs
@property
def id(self):
return self.xos_port.port_id
@property
def name(self):
# In OpenStack Kilo, the tap name uses the first 11 characters of the port id. Unverified if this is true for
# any other OpenStack.
return "tap" + self.xos_port.port_id[:11]
#return self.xos_port.name
@property
def network_id(self):
cn = self.get_controller_network()
if not cn:
return None
return cn.net_id
@property
def network_name(self):
return self.xos_port.network.name
@property
def mac_address(self):
return self.xos_port.mac
@property
def ip_address(self):
return self.xos_port.ip
def to_dict(self):
return {"id": self.id,
"name": self.name,
"network_id": self.network_id,
"mac_address": self.mac_address,
"ip_address": self.ip_address,
"floating_address_pairs": self.floating_address_pairs,
"vlan_id": self.vlan_id}
def __eq__(self, other):
return self.to_dict() == other.to_dict()