Matteo Scandolo | 0e7912c | 2017-08-08 13:05:24 -0700 | [diff] [blame] | 1 | |
| 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 | |
Scott Baker | c3ce3e7 | 2016-06-20 17:35:19 -0700 | [diff] [blame] | 17 | from rest_framework.decorators import api_view |
| 18 | from rest_framework.response import Response |
| 19 | from rest_framework.reverse import reverse |
| 20 | from rest_framework import serializers |
| 21 | from rest_framework import generics |
| 22 | from rest_framework import viewsets |
| 23 | from rest_framework.decorators import detail_route, list_route |
| 24 | from rest_framework.views import APIView |
Scott Baker | c3800fa | 2016-08-25 15:30:43 -0700 | [diff] [blame] | 25 | from rest_framework import status |
Scott Baker | c3ce3e7 | 2016-06-20 17:35:19 -0700 | [diff] [blame] | 26 | from core.models import * |
| 27 | from services.vtn.models import VTNService |
Scott Baker | 2342903 | 2016-09-06 12:02:39 -0700 | [diff] [blame] | 28 | from services.vtn.vtnnetport import VTNNetwork, VTNPort |
Scott Baker | c3ce3e7 | 2016-06-20 17:35:19 -0700 | [diff] [blame] | 29 | from django.forms import widgets |
| 30 | from django.conf.urls import patterns, url |
| 31 | from api.xosapi_helpers import PlusModelSerializer, XOSViewSet, ReadOnlyField |
| 32 | from django.shortcuts import get_object_or_404 |
| 33 | from xos.apibase import XOSListCreateAPIView, XOSRetrieveUpdateDestroyAPIView, XOSPermissionDenied |
| 34 | from xos.exceptions import * |
| 35 | import json |
| 36 | import subprocess |
| 37 | |
| 38 | class VTNServiceSerializer(PlusModelSerializer): |
| 39 | id = ReadOnlyField() |
| 40 | |
| 41 | privateGatewayMac = serializers.CharField(required=False) |
| 42 | localManagementIp = serializers.CharField(required=False) |
| 43 | ovsdbPort = serializers.IntegerField(required=False) |
| 44 | sshPort = serializers.IntegerField(required=False) |
| 45 | sshUser = serializers.CharField(required=False) |
| 46 | sshKeyFile = serializers.CharField(required=False) |
| 47 | mgmtSubnetBits = serializers.IntegerField(required=False) |
| 48 | xosEndpoint = serializers.CharField(required=False) |
| 49 | xosUser = serializers.CharField(required=False) |
| 50 | xosPassword = serializers.CharField(required=False) |
| 51 | |
Scott Baker | c3ce3e7 | 2016-06-20 17:35:19 -0700 | [diff] [blame] | 52 | humanReadableName = serializers.SerializerMethodField("getHumanReadableName") |
| 53 | class Meta: |
| 54 | model = VTNService |
| 55 | fields = ('humanReadableName', 'id', 'privateGatewayMac', 'localManagementIp', 'ovsdbPort', 'sshPort', 'sshUser', 'sshKeyFile', |
| 56 | 'mgmtSubnetBits', 'xosEndpoint', 'xosUser', 'xosPassword') |
| 57 | |
| 58 | def getHumanReadableName(self, obj): |
| 59 | return obj.__unicode__() |
| 60 | |
Scott Baker | c3800fa | 2016-08-25 15:30:43 -0700 | [diff] [blame] | 61 | class VTNNetworkSerializer(serializers.Serializer): |
| 62 | id = ReadOnlyField() |
| 63 | name = serializers.CharField(required=False) |
| 64 | subnet = serializers.CharField(required=False) |
| 65 | gateway = serializers.CharField(required=False) |
| 66 | segmentation_id = serializers.CharField(required=False) |
| 67 | |
| 68 | class Meta: |
| 69 | fields = ('id', 'name', 'subnet', 'gateway', 'segmentation_id') |
| 70 | |
| 71 | class VTNServiceNetworkSerializer(serializers.Serializer): |
| 72 | id = ReadOnlyField() |
| 73 | type = serializers.CharField(required=False) |
| 74 | subscriberNetworks = serializers.SerializerMethodField("getSubscriberNetworks") |
| 75 | providerNetworks = serializers.SerializerMethodField("getProviderNetworks") |
| 76 | ownerSliceName = ReadOnlyField() |
| 77 | ownerServiceName = ReadOnlyField() |
| 78 | |
| 79 | class Meta: |
| 80 | fields = ('id', 'type', "subscriberNetworks", "providerNetworks", "ownerSliceName", "ownerServiceName") |
| 81 | |
| 82 | def getSubscriberNetworks(self, obj): |
| 83 | return obj.subscriberNetworks |
| 84 | |
| 85 | def getProviderNetworks(self, obj): |
| 86 | return obj.providerNetworks |
| 87 | |
Scott Baker | c3800fa | 2016-08-25 15:30:43 -0700 | [diff] [blame] | 88 | class VTNPortSerializer(serializers.Serializer): |
| 89 | id = ReadOnlyField() |
| 90 | name = serializers.CharField(required=False) |
| 91 | network_id = serializers.CharField(required=False) |
Scott Baker | 9837fb8 | 2016-09-26 13:43:57 -0700 | [diff] [blame] | 92 | network_name = serializers.CharField(required=False) |
Scott Baker | c3800fa | 2016-08-25 15:30:43 -0700 | [diff] [blame] | 93 | mac_address = serializers.CharField(required=False) |
| 94 | ip_address = serializers.CharField(required=False) |
| 95 | |
| 96 | class Meta: |
Scott Baker | 9837fb8 | 2016-09-26 13:43:57 -0700 | [diff] [blame] | 97 | fields = ('id', 'name', 'network_id', 'network_name', 'mac_address', 'ip_address') |
Scott Baker | c3800fa | 2016-08-25 15:30:43 -0700 | [diff] [blame] | 98 | |
| 99 | class FloatingAddressPairSerializer(serializers.Serializer): |
| 100 | ip_address = ReadOnlyField() |
| 101 | mac_address = ReadOnlyField() |
| 102 | |
| 103 | class VTNServicePortSerializer(serializers.Serializer): |
| 104 | id = ReadOnlyField() |
| 105 | vlan_id = serializers.IntegerField(required=False) |
Scott Baker | 9837fb8 | 2016-09-26 13:43:57 -0700 | [diff] [blame] | 106 | network_name = serializers.CharField(required=False) |
Scott Baker | c3800fa | 2016-08-25 15:30:43 -0700 | [diff] [blame] | 107 | |
| 108 | # TODO: structure this better |
| 109 | floating_address_pairs = serializers.SerializerMethodField("getFloatingAddressPairs") |
| 110 | |
| 111 | class Meta: |
Scott Baker | 9837fb8 | 2016-09-26 13:43:57 -0700 | [diff] [blame] | 112 | fields = ('id', 'vlan_id', 'network_name') |
Scott Baker | c3800fa | 2016-08-25 15:30:43 -0700 | [diff] [blame] | 113 | |
| 114 | def getFloatingAddressPairs(self, obj): |
| 115 | return obj.floating_address_pairs |
| 116 | |
Scott Baker | c3ce3e7 | 2016-06-20 17:35:19 -0700 | [diff] [blame] | 117 | class VTNViewSet(XOSViewSet): |
| 118 | base_name = "vtn" |
| 119 | method_name = "vtn" |
| 120 | method_kind = "viewset" |
| 121 | |
| 122 | # these are just because ViewSet needs some queryset and model, even if we don't use the |
| 123 | # default endpoints |
Scott Baker | cd2db8c | 2017-05-25 09:07:19 -0700 | [diff] [blame] | 124 | queryset = VTNService.objects.all() |
Scott Baker | c3ce3e7 | 2016-06-20 17:35:19 -0700 | [diff] [blame] | 125 | model = VTNService |
| 126 | serializer_class = VTNServiceSerializer |
| 127 | |
Scott Baker | c3800fa | 2016-08-25 15:30:43 -0700 | [diff] [blame] | 128 | custom_serializers = {"get_port": VTNPortSerializer, |
| 129 | "get_ports": VTNPortSerializer, |
| 130 | "get_network": VTNNetworkSerializer, |
| 131 | "get_networks": VTNNetworkSerializer} |
| 132 | |
Scott Baker | c3ce3e7 | 2016-06-20 17:35:19 -0700 | [diff] [blame] | 133 | @classmethod |
| 134 | def get_urlpatterns(self, api_path="^"): |
| 135 | patterns = [] |
| 136 | |
| 137 | patterns.append( self.detail_url("services/$", {"get": "get_services"}, "services") ) |
| 138 | patterns.append( self.detail_url("services_names/$", {"get": "get_services_names"}, "services") ) |
| 139 | patterns.append( self.detail_url("services/(?P<service>[a-zA-Z0-9\-_]+)/$", {"get": "get_service"}, "get_service") ) |
| 140 | |
| 141 | # Not as RESTful as it could be, but maintain these endpoints for compability |
| 142 | patterns.append( self.list_url("services/$", {"get": "get_services"}, "rootvtn_services") ) |
| 143 | patterns.append( self.list_url("services_names/$", {"get": "get_services_names"}, "rootvtn_services") ) |
| 144 | patterns.append( self.list_url("services/(?P<service>[a-zA-Z0-9\-_]+)/$", {"get": "get_service"}, "rootvtn_get_service") ) |
| 145 | |
Scott Baker | c3800fa | 2016-08-25 15:30:43 -0700 | [diff] [blame] | 146 | # Neutron-replacement APIs |
| 147 | patterns.append( self.list_url("ports/$", {"get": "get_ports"}, "vtn_ports") ) |
| 148 | patterns.append( self.list_url("ports/(?P<port_id>[a-zA-Z0-9\-_]+)/$", {"get": "get_port"}, "vtn_port") ) |
| 149 | patterns.append( self.list_url("networks/$", {"get": "get_networks"}, "vtn_networks") ) |
| 150 | patterns.append( self.list_url("networks/(?P<network_id>[a-zA-Z0-9\-_]+)/$", {"get": "get_network"}, "vtn_network") ) |
| 151 | |
| 152 | patterns.append( self.list_url("servicePorts/$", {"get": "get_service_ports"}, "vtn_service_ports") ) |
| 153 | patterns.append( self.list_url("servicePorts/(?P<port_id>[a-zA-Z0-9\-_]+)/$", {"get": "get_service_port"}, "vtn_service_port") ) |
| 154 | patterns.append( self.list_url("serviceNetworks/$", {"get": "get_service_networks"}, "vtn_service_networks") ) |
| 155 | patterns.append( self.list_url("serviceNetworks/(?P<network_id>[a-zA-Z0-9\-_]+)/$", {"get": "get_service_network"}, "vtn_service_network") ) |
| 156 | |
Scott Baker | c3ce3e7 | 2016-06-20 17:35:19 -0700 | [diff] [blame] | 157 | patterns = patterns + super(VTNViewSet,self).get_urlpatterns(api_path) |
| 158 | |
| 159 | return patterns |
| 160 | |
| 161 | def get_services_names(self, request, pk=None): |
| 162 | result = {} |
| 163 | for service in Service.objects.all(): |
| 164 | for id in service.get_vtn_src_names(): |
| 165 | dependencies = service.get_vtn_dependencies_names() |
| 166 | if dependencies: |
| 167 | result[id] = dependencies |
| 168 | return Response(result) |
| 169 | |
| 170 | def get_services(self, request, pk=None): |
| 171 | result = {} |
| 172 | for service in Service.objects.all(): |
| 173 | for id in service.get_vtn_src_ids(): |
| 174 | dependencies = service.get_vtn_dependencies_ids() |
| 175 | if dependencies: |
| 176 | result[id] = dependencies |
| 177 | return Response(result) |
| 178 | |
| 179 | def get_service(self, request, pk=None, service=None): |
| 180 | for xos_service in Service.objects.all(): |
| 181 | if service in xos_service.get_vtn_src_ids(): |
| 182 | return Response(xos_service.get_vtn_dependencies_ids()) |
| 183 | return Response([]) |
| 184 | |
Scott Baker | c3800fa | 2016-08-25 15:30:43 -0700 | [diff] [blame] | 185 | def get_ports(self, request): |
| 186 | result=[] |
| 187 | for port in Port.objects.all(): |
| 188 | result.append(VTNPortSerializer(VTNPort(port)).data) |
Scott Baker | cb25cd5 | 2016-09-09 12:28:10 -0700 | [diff] [blame] | 189 | return Response({"ports": result}) |
Scott Baker | c3800fa | 2016-08-25 15:30:43 -0700 | [diff] [blame] | 190 | |
| 191 | def get_port(self, request, port_id=None): |
| 192 | port = Port.objects.filter(port_id = port_id) |
| 193 | if port: |
| 194 | port=port[0] |
| 195 | else: |
| 196 | return Response("Failed to find port %s" % port_id, status=status.HTTP_404_NOT_FOUND) |
Scott Baker | cb25cd5 | 2016-09-09 12:28:10 -0700 | [diff] [blame] | 197 | return Response({"port": VTNPortSerializer(VTNPort(port)).data}) |
Scott Baker | c3800fa | 2016-08-25 15:30:43 -0700 | [diff] [blame] | 198 | |
| 199 | def get_service_ports(self, request): |
| 200 | result=[] |
| 201 | for port in Port.objects.all(): |
| 202 | result.append(VTNServicePortSerializer(VTNPort(port)).data) |
Scott Baker | cb25cd5 | 2016-09-09 12:28:10 -0700 | [diff] [blame] | 203 | return Response({"servicePorts": result}) |
Scott Baker | c3800fa | 2016-08-25 15:30:43 -0700 | [diff] [blame] | 204 | |
| 205 | def get_service_port(self, request, port_id=None): |
| 206 | port = Port.objects.filter(port_id = port_id) |
| 207 | if port: |
| 208 | port=port[0] |
| 209 | else: |
| 210 | return Response("Failed to find port %s" % port_id, status=status.HTTP_404_NOT_FOUND) |
Scott Baker | cb25cd5 | 2016-09-09 12:28:10 -0700 | [diff] [blame] | 211 | return Response({"servicePort": VTNServicePortSerializer(VTNPort(port)).data}) |
Scott Baker | c3800fa | 2016-08-25 15:30:43 -0700 | [diff] [blame] | 212 | |
| 213 | def get_networks(self, request): |
| 214 | result=[] |
| 215 | for network in Network.objects.all(): |
Scott Baker | f489374 | 2016-11-23 12:31:20 -0800 | [diff] [blame] | 216 | network = VTNNetwork(network) |
| 217 | if network.id is not None: |
| 218 | result.append(VTNNetworkSerializer(network).data) |
Scott Baker | cb25cd5 | 2016-09-09 12:28:10 -0700 | [diff] [blame] | 219 | return Response({"networks": result}) |
Scott Baker | c3800fa | 2016-08-25 15:30:43 -0700 | [diff] [blame] | 220 | |
| 221 | def get_network(self, request, network_id=None): |
Scott Baker | cb25cd5 | 2016-09-09 12:28:10 -0700 | [diff] [blame] | 222 | network = [x for x in Network.objects.all() if VTNNetwork(x).id == network_id] |
Scott Baker | c3800fa | 2016-08-25 15:30:43 -0700 | [diff] [blame] | 223 | if network: |
| 224 | network=network[0] |
| 225 | else: |
| 226 | return Response("Failed to find network %s" % network_id, status=status.HTTP_404_NOT_FOUND) |
Scott Baker | cb25cd5 | 2016-09-09 12:28:10 -0700 | [diff] [blame] | 227 | return Response({"network": VTNNetworkSerializer(VTNNetwork(network)).data}) |
Scott Baker | c3800fa | 2016-08-25 15:30:43 -0700 | [diff] [blame] | 228 | |
| 229 | def get_service_networks(self, request): |
| 230 | result=[] |
| 231 | for network in Network.objects.all(): |
Scott Baker | f489374 | 2016-11-23 12:31:20 -0800 | [diff] [blame] | 232 | network = VTNNetwork(network) |
| 233 | if network.id is not None: |
| 234 | result.append(VTNServiceNetworkSerializer(network).data) |
Scott Baker | cb25cd5 | 2016-09-09 12:28:10 -0700 | [diff] [blame] | 235 | return Response({"serviceNetworks": result}) |
Scott Baker | c3800fa | 2016-08-25 15:30:43 -0700 | [diff] [blame] | 236 | |
| 237 | def get_service_network(self, request, network_id=None): |
Scott Baker | cb25cd5 | 2016-09-09 12:28:10 -0700 | [diff] [blame] | 238 | network = [x for x in Network.objects.all() if VTNNetwork(x).id == network_id] |
Scott Baker | c3800fa | 2016-08-25 15:30:43 -0700 | [diff] [blame] | 239 | if network: |
| 240 | network=network[0] |
| 241 | else: |
| 242 | return Response("Failed to find network %s" % network_id, status=status.HTTP_404_NOT_FOUND) |
Scott Baker | cb25cd5 | 2016-09-09 12:28:10 -0700 | [diff] [blame] | 243 | return Response({"serviceNetwork": VTNServiceNetworkSerializer(VTNNetwork(network)).data}) |
Scott Baker | c3800fa | 2016-08-25 15:30:43 -0700 | [diff] [blame] | 244 | |
| 245 | |
Scott Baker | c3ce3e7 | 2016-06-20 17:35:19 -0700 | [diff] [blame] | 246 | |