blob: 5ab5223da3181191bd19ec4f1bb3fe69c0116819 [file] [log] [blame]
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.reverse import reverse
from rest_framework import serializers
from rest_framework import generics
from rest_framework import viewsets
from rest_framework.decorators import detail_route, list_route
from rest_framework.views import APIView
from rest_framework import status
from core.models import *
from services.vtn.models import VTNService
from django.forms import widgets
from django.conf.urls import patterns, url
from api.xosapi_helpers import PlusModelSerializer, XOSViewSet, ReadOnlyField
from django.shortcuts import get_object_or_404
from xos.apibase import XOSListCreateAPIView, XOSRetrieveUpdateDestroyAPIView, XOSPermissionDenied
from xos.exceptions import *
import json
import subprocess
VTN_SERVCOMP_KINDS=["PRIVATE","VSG"]
class VTNServiceSerializer(PlusModelSerializer):
id = ReadOnlyField()
privateGatewayMac = serializers.CharField(required=False)
localManagementIp = serializers.CharField(required=False)
ovsdbPort = serializers.IntegerField(required=False)
sshPort = serializers.IntegerField(required=False)
sshUser = serializers.CharField(required=False)
sshKeyFile = serializers.CharField(required=False)
mgmtSubnetBits = serializers.IntegerField(required=False)
xosEndpoint = serializers.CharField(required=False)
xosUser = serializers.CharField(required=False)
xosPassword = serializers.CharField(required=False)
humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
class Meta:
model = VTNService
fields = ('humanReadableName', 'id', 'privateGatewayMac', 'localManagementIp', 'ovsdbPort', 'sshPort', 'sshUser', 'sshKeyFile',
'mgmtSubnetBits', 'xosEndpoint', 'xosUser', 'xosPassword')
def getHumanReadableName(self, obj):
return obj.__unicode__()
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 tenant in service.subscribed_tenants.all():
if tenant.provider_service:
bidirectional = tenant.connect_method!="private-unidirectional"
for slice in tenant.provider_service.slices.all():
for net in slice.networks.all():
if net.template.vtn_kind not in VTN_SERVCOMP_KINDS:
continue
if not net.controllernetworks.exists():
continue
cn = net.controllernetworks.all()[0]
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 tenant in service.provided_tenants.all():
if tenant.subscriber_service:
bidirectional = tenant.connect_method!="private-unidirectional"
for slice in tenant.subscriber_service.slices.all():
for net in slice.networks.all():
if net.template.vtn_kind not in VTN_SERVCOMP_KINDS:
continue
if not net.controllernetworks.exists():
continue
cn = net.controllernetworks.all()[0]
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
class VTNNetworkSerializer(serializers.Serializer):
id = ReadOnlyField()
name = serializers.CharField(required=False)
subnet = serializers.CharField(required=False)
gateway = serializers.CharField(required=False)
segmentation_id = serializers.CharField(required=False)
class Meta:
fields = ('id', 'name', 'subnet', 'gateway', 'segmentation_id')
class VTNServiceNetworkSerializer(serializers.Serializer):
id = ReadOnlyField()
type = serializers.CharField(required=False)
subscriberNetworks = serializers.SerializerMethodField("getSubscriberNetworks")
providerNetworks = serializers.SerializerMethodField("getProviderNetworks")
ownerSliceName = ReadOnlyField()
ownerServiceName = ReadOnlyField()
class Meta:
fields = ('id', 'type', "subscriberNetworks", "providerNetworks", "ownerSliceName", "ownerServiceName")
def getSubscriberNetworks(self, obj):
return obj.subscriberNetworks
def getProviderNetworks(self, obj):
return obj.providerNetworks
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 get_vsg_tenant(self):
from services.vsg.models import VSGTenant
for tenant in VSGTenant.get_tenant_objects().all():
if tenant.instance == self.xos_port.instance:
return tenant
return None
@property
def vlan_id(self):
if not self.xos_port.instance:
return None
tags = Tag.select_by_content_object(self.xos_port.instance).filter(name="s_tag")
if not tags:
return None
return tags[0].value
@property
def floating_address_pairs(self):
address_pairs = []
vsg = self.get_vsg_tenant()
if vsg:
if vsg.wan_container_ip and vsg.wan_container_mac:
address_pairs.append({"ip_address": vsg.wan_container_ip,
"mac_address": vsg.wan_container_mac})
if vsg.wan_vm_ip and vsg.wan_vm_mac:
address_pairs.append({"ip_address": vsg.wan_vm_ip,
"mac_address": vsg.wan_vm_mac})
return address_pairs
@property
def id(self):
return self.xos_port.port_id
@property
def name(self):
return "port-%s" % self.xos_port.id
@property
def network_id(self):
cn = self.get_controller_network()
if not cn:
return None
return cn.net_id
@property
def mac_address(self):
return self.xos_port.mac
@property
def ip_address(self):
return self.xos_port.ip
class VTNPortSerializer(serializers.Serializer):
id = ReadOnlyField()
name = serializers.CharField(required=False)
network_id = serializers.CharField(required=False)
mac_address = serializers.CharField(required=False)
ip_address = serializers.CharField(required=False)
class Meta:
fields = ('id', 'name', 'network_id', 'mac_address', 'ip_address')
class FloatingAddressPairSerializer(serializers.Serializer):
ip_address = ReadOnlyField()
mac_address = ReadOnlyField()
class VTNServicePortSerializer(serializers.Serializer):
id = ReadOnlyField()
vlan_id = serializers.IntegerField(required=False)
# TODO: structure this better
floating_address_pairs = serializers.SerializerMethodField("getFloatingAddressPairs")
class Meta:
fields = ('id', 'vlan_id')
def getFloatingAddressPairs(self, obj):
return obj.floating_address_pairs
class VTNViewSet(XOSViewSet):
base_name = "vtn"
method_name = "vtn"
method_kind = "viewset"
# these are just because ViewSet needs some queryset and model, even if we don't use the
# default endpoints
queryset = VTNService.get_service_objects().all()
model = VTNService
serializer_class = VTNServiceSerializer
custom_serializers = {"get_port": VTNPortSerializer,
"get_ports": VTNPortSerializer,
"get_network": VTNNetworkSerializer,
"get_networks": VTNNetworkSerializer}
@classmethod
def get_urlpatterns(self, api_path="^"):
patterns = []
patterns.append( self.detail_url("services/$", {"get": "get_services"}, "services") )
patterns.append( self.detail_url("services_names/$", {"get": "get_services_names"}, "services") )
patterns.append( self.detail_url("services/(?P<service>[a-zA-Z0-9\-_]+)/$", {"get": "get_service"}, "get_service") )
# Not as RESTful as it could be, but maintain these endpoints for compability
patterns.append( self.list_url("services/$", {"get": "get_services"}, "rootvtn_services") )
patterns.append( self.list_url("services_names/$", {"get": "get_services_names"}, "rootvtn_services") )
patterns.append( self.list_url("services/(?P<service>[a-zA-Z0-9\-_]+)/$", {"get": "get_service"}, "rootvtn_get_service") )
# Neutron-replacement APIs
patterns.append( self.list_url("ports/$", {"get": "get_ports"}, "vtn_ports") )
patterns.append( self.list_url("ports/(?P<port_id>[a-zA-Z0-9\-_]+)/$", {"get": "get_port"}, "vtn_port") )
patterns.append( self.list_url("networks/$", {"get": "get_networks"}, "vtn_networks") )
patterns.append( self.list_url("networks/(?P<network_id>[a-zA-Z0-9\-_]+)/$", {"get": "get_network"}, "vtn_network") )
patterns.append( self.list_url("servicePorts/$", {"get": "get_service_ports"}, "vtn_service_ports") )
patterns.append( self.list_url("servicePorts/(?P<port_id>[a-zA-Z0-9\-_]+)/$", {"get": "get_service_port"}, "vtn_service_port") )
patterns.append( self.list_url("serviceNetworks/$", {"get": "get_service_networks"}, "vtn_service_networks") )
patterns.append( self.list_url("serviceNetworks/(?P<network_id>[a-zA-Z0-9\-_]+)/$", {"get": "get_service_network"}, "vtn_service_network") )
patterns = patterns + super(VTNViewSet,self).get_urlpatterns(api_path)
return patterns
def get_services_names(self, request, pk=None):
result = {}
for service in Service.objects.all():
for id in service.get_vtn_src_names():
dependencies = service.get_vtn_dependencies_names()
if dependencies:
result[id] = dependencies
return Response(result)
def get_services(self, request, pk=None):
result = {}
for service in Service.objects.all():
for id in service.get_vtn_src_ids():
dependencies = service.get_vtn_dependencies_ids()
if dependencies:
result[id] = dependencies
return Response(result)
def get_service(self, request, pk=None, service=None):
for xos_service in Service.objects.all():
if service in xos_service.get_vtn_src_ids():
return Response(xos_service.get_vtn_dependencies_ids())
return Response([])
def get_ports(self, request):
result=[]
for port in Port.objects.all():
result.append(VTNPortSerializer(VTNPort(port)).data)
return Response(result)
def get_port(self, request, port_id=None):
port = Port.objects.filter(port_id = port_id)
if port:
port=port[0]
else:
return Response("Failed to find port %s" % port_id, status=status.HTTP_404_NOT_FOUND)
return Response(VTNPortSerializer(VTNPort(port)).data)
def get_service_ports(self, request):
result=[]
for port in Port.objects.all():
result.append(VTNServicePortSerializer(VTNPort(port)).data)
return Response(result)
def get_service_port(self, request, port_id=None):
port = Port.objects.filter(port_id = port_id)
if port:
port=port[0]
else:
return Response("Failed to find port %s" % port_id, status=status.HTTP_404_NOT_FOUND)
return Response(VTNServicePortSerializer(VTNPort(port)).data)
def get_networks(self, request):
result=[]
for network in Network.objects.all():
result.append(VTNNetworkSerializer(VTNNetwork(network)).data)
return Response(result)
def get_network(self, request, network_id=None):
network = Network.objects.filter(network_id = network_id)
if network:
network=network[0]
else:
return Response("Failed to find network %s" % network_id, status=status.HTTP_404_NOT_FOUND)
return Response(VTNNetworkSerializer(VTNNetwork(network)).data)
def get_service_networks(self, request):
result=[]
for network in Network.objects.all():
result.append(VTNServiceNetworkSerializer(VTNNetwork(network)).data)
return Response(result)
def get_service_network(self, request, network_id=None):
network = Network.objects.filter(network_id = network_id)
if network:
network=network[0]
else:
return Response("Failed to find network %s" % network_id, status=status.HTTP_404_NOT_FOUND)
return Response(VTNServiceNetworkSerializer(VTNNetwork(network)).data)