Support for ELAN, ETREE, and VNoD Global Service
Change-Id: Iea1ee5b5b9224404a16bc9b88bc082719f75d10f
diff --git a/xos/api/service/metronetworkservice/metronetworkservice.py b/xos/api/service/metronetworkservice/metronetworkservice.py
index 8e200ce..764205d 100644
--- a/xos/api/service/metronetworkservice/metronetworkservice.py
+++ b/xos/api/service/metronetworkservice/metronetworkservice.py
@@ -1,7 +1,11 @@
+from django.http import HttpResponseBadRequest
from rest_framework.response import Response
+from rest_framework.views import APIView
from rest_framework import serializers, filters, status
from api.xosapi_helpers import PlusModelSerializer, XOSViewSet, ReadOnlyField
from services.metronetwork.models import *
+from random import randint
+import json
from django.core.exceptions import ObjectDoesNotExist
from django.core import serializers as jsonserializer
@@ -18,7 +22,7 @@
'operationalState')
def getHumanReadableName(self, obj):
- return obj.__unicode__()
+ return obj.name
class MetroNetworkSystemViewSet(XOSViewSet):
base_name = "metronetworksystem"
@@ -143,7 +147,8 @@
ELineConnection.sid = validated_data.data.get('sid')
ELineConnection.adminstate = validated_data.data.get('adminstate')
ELineConnection.operstate = validated_data.data.get('operstate')
- ELineConnection.type = validated_data.data.get('type')
+ ELineConnection.sid = validated_data.data.get('sid')
+ ELineConnection.type = 'Point_To_Point'
uni1 = validated_data.data.get('uni1')
uni2 = validated_data.data.get('uni2')
@@ -244,7 +249,8 @@
ETreeConnection.sid = validated_data.data.get('sid')
ETreeConnection.adminstate = validated_data.data.get('adminstate')
ETreeConnection.operstate = validated_data.data.get('operstate')
- ETreeConnection.type = validated_data.data.get('type')
+ ETreeConnection.sid = validated_data.data.get('sid')
+ ETreeConnection.type = 'Root_Multipoint'
root_id = validated_data.data.get('root')
eps_list = validated_data.data.get('eps')
@@ -349,7 +355,8 @@
ELanConnection.sid = validated_data.data.get('sid')
ELanConnection.adminstate = validated_data.data.get('adminstate')
ELanConnection.operstate = validated_data.data.get('operstate')
- ELanConnection.type = validated_data.data.get('type')
+ ELanConnection.sid = validated_data.data.get('sid')
+ ELanConnection.type = 'Multipoint_To_Multipoint'
eps_list = validated_data.data.get('eps')
ELanConnection.save()
@@ -381,3 +388,455 @@
response_data['eps'] = eps_data
return Response(response_data)
+
+############################
+
+class BandwidthProfileSerializer(PlusModelSerializer):
+ humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
+
+ class Meta:
+ model = BandwidthProfile
+
+ fields = ('humanReadableName',
+ 'id',
+ 'bwpcfgcbs',
+ 'bwpcfgebs',
+ 'bwpcfgcir',
+ 'bwpcfgeir',
+ 'name'
+ )
+
+ def getHumanReadableName(self, obj):
+ return obj.name
+
+class BandwidthProfileViewSet(XOSViewSet):
+ base_name = "BANDWIDTH_PROFILE"
+ method_name = "BANDWIDTH_PROFILE"
+ method_kind = "viewset"
+ queryset = BandwidthProfile.objects.all()
+ serializer_class = BandwidthProfileSerializer
+
+ @classmethod
+ def get_urlpatterns(self, api_path="^"):
+ patterns = super(BandwidthProfileViewSet, self).get_urlpatterns(api_path=api_path)
+
+ return patterns
+
+ def list(self, request):
+
+ object_list = self.filter_queryset(self.get_queryset())
+
+ serializer = self.get_serializer(object_list, many=True)
+
+ return Response(serializer.data)
+
+ def create(self, validated_data):
+
+ bandwidthProfile = BandwidthProfile()
+ bandwidthProfile.name = validated_data.data.get('name')
+ bandwidthProfile.bwpcfgcbs = validated_data.data.get('bwpcfgcbs')
+ bandwidthProfile.bwpcfgebs = validated_data.data.get('bwpcfgebs')
+ bandwidthProfile.bwpcfgcir = validated_data.data.get('bwpcfgcir')
+ bandwidthProfile.bwpcfgeir = validated_data.data.get('bwpcfgeir')
+
+ bandwidthProfile.save()
+
+ response_data = {}
+ response_data['name'] = bandwidthProfile.name
+ response_data['bwpcfgcbs'] = bandwidthProfile.bwpcfgcbs
+ response_data['bwpcfgebs'] = bandwidthProfile.bwpcfgebs
+ response_data['bwpcfgcir'] = bandwidthProfile.bwpcfgeir
+ response_data['bwpcfgcir'] = bandwidthProfile.bwpcfgcir
+ response_data['id'] = bandwidthProfile.id
+
+ return Response(response_data)
+
+class VnodSiteSerializer(PlusModelSerializer):
+ humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
+
+ class Meta:
+ model = Site
+
+ fields = ('humanReadableName',
+ 'site_url',
+ 'enabled',
+ 'longitude',
+ 'latitude',
+ 'name'
+ )
+
+ def getHumanReadableName(self, obj):
+ return obj.name
+
+class RemotePortSerializer(PlusModelSerializer):
+ humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
+ edgeport = NetworkEdgePortSerializer(read_only=True)
+ remoteportsite = VnodSiteSerializer(read_only=True)
+
+ class Meta:
+ model = RemotePort
+
+ fields = ('humanReadableName',
+ 'name',
+ 'edgeport',
+ 'id',
+ 'remoteportsite'
+ )
+
+ def getHumanReadableName(self, obj):
+ return obj.name
+
+class ServiceSpokeSerializer(PlusModelSerializer):
+ humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
+ vnodlocalsite = VnodSiteSerializer(read_only=True)
+ vnodlocalport = RemotePortSerializer(read_only=True)
+
+ class Meta:
+ model = ServiceSpoke
+
+ fields = ('humanReadableName',
+ 'id',
+ 'name',
+ 'remotesubscriber',
+ 'remotevnodid',
+ 'autoattached',
+ 'operstate',
+ 'vnodlocalsite',
+ 'vnodlocalport'
+ )
+
+ def getHumanReadableName(self, obj):
+ return obj.name
+
+class VnodGlobalServiceSerializer(PlusModelSerializer):
+ humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
+ metronetworkroottomultipoint = NetworkEdgeToMultipointConnectionSerializer(read_only=True)
+ metronetworkmultipoint = NetworkMultipointToMultipointConnectionSerializer(read_only=True)
+ metronetworkpointtopoint = NetworkEdgeToEdgePointConnectionSerializer(read_only=True)
+ spokes = ServiceSpokeSerializer(read_only=True, many=True)
+ bandwidthProfile = BandwidthProfileSerializer(read_only=True)
+
+ class Meta:
+ model = VnodGlobalService
+
+ fields = ('humanReadableName',
+ 'servicehandle',
+ 'vlanid',
+ 'id',
+ 'type',
+ 'operstate',
+ 'adminstate',
+ 'metronetworkroottomultipoint',
+ 'metronetworkmultipoint',
+ 'metronetworkpointtopoint',
+ 'spokes',
+ 'bandwidthProfile',
+ 'name'
+ )
+
+ def getHumanReadableName(self, obj):
+ return obj.name
+
+class VnodGlobalServiceViewSet(XOSViewSet):
+ base_name = "VNOD_GLOBAL_SERVICE"
+ method_name = "VNOD_GLOBAL_SERVICE"
+ method_kind = "viewset"
+ queryset = VnodGlobalService.get_service_objects().all()
+ serializer_class = VnodGlobalServiceSerializer
+
+ @classmethod
+ def get_urlpatterns(self, api_path="^"):
+ patterns = super(VnodGlobalServiceViewSet, self).get_urlpatterns(api_path=api_path)
+
+ return patterns
+
+ def list(self, request):
+
+ object_list = self.filter_queryset(self.get_queryset())
+
+ serializer = self.get_serializer(object_list, many=True)
+
+ return Response(serializer.data)
+
+ def destroy(self, request, pk=None):
+ VnodGlobalServiceToDelete = VnodGlobalService.objects.get(pk=pk)
+
+ if (VnodGlobalServiceToDelete):
+ VnodGlobalServiceToDelete.adminstate = 'deactivationrequested'
+ VnodGlobalServiceToDelete.save()
+ else:
+ return Response(status=status.HTTP_400_BAD_REQUEST)
+
+ return Response(status=status.HTTP_200_OK)
+
+ def create(self, validated_data):
+
+ vnodGlobalService = VnodGlobalService()
+
+ vnodGlobalService.name = validated_data.data.get('name')
+
+ if VnodGlobalService.objects.filter(
+ name=vnodGlobalService.name).exists():
+ return HttpResponseBadRequest('Error: VnodGlobalService name \'' + vnodGlobalService.name
+ + '\' already exists.')
+
+ vnodGlobalService.servicehandle = validated_data.data.get('servicehandle')
+ vnodGlobalService.adminstate = 'enabled'
+ vnodGlobalService.operstate = 'inactive'
+ vnodGlobalService.type = validated_data.data.get('type')
+
+ vnodGlobalService.vlanid = self.getUniqueVlandId()
+
+ bandwidth_profile = validated_data.data.get('bandwidthProfile')
+ bandwidthprofile = BandwidthProfile.objects.get(pk=bandwidth_profile['id'])
+ if (bandwidth_profile):
+ vnodGlobalService.bandwidthProfile = bandwidthprofile
+
+ vnodGlobalService.save()
+
+ spokes_list = validated_data.data.get('spokes')
+ if (spokes_list is None):
+ vnodGlobalService.delete()
+ return HttpResponseBadRequest('Error: No spokes found in request.')
+
+ for spoke in spokes_list:
+ vnodlocalsite = Site.objects.get(pk=spoke['vnodlocalsite']['id'])
+ servicespoke = ServiceSpoke()
+ servicespoke.vnodlocalsite = vnodlocalsite
+ servicespoke.vnodlocalport = self.getRandomRemotePort(vnodlocalsite)
+ servicespoke.name = spoke['name']
+ if (spoke.get('autoattached')):
+ servicespoke.autoattached = spoke['autoattached']
+ servicespoke.operstate = 'inactive'
+ servicespoke.adminstate = 'disabled'
+ servicespoke.save()
+ vnodGlobalService.spokes.add(servicespoke)
+
+ serializer = self.get_serializer(vnodGlobalService)
+ return Response(serializer.data)
+
+ def getUniqueVlandId(self):
+ unique = False
+ while not unique:
+ vlanid = randint(1, 4095)
+ vnodglobalservice = VnodGlobalService.get_service_objects().filter(vlanid=vlanid)
+ if (not vnodglobalservice):
+ unique = True
+ return vlanid
+
+ def getRandomRemotePort(self, site):
+ remotePort = RemotePort.objects.get(remoteportsite__name=site.name)
+ if (remotePort):
+ return remotePort
+ return None
+
+ @classmethod
+ def calculateVnodGlobalOperState(self, servicehandle):
+ vnodglobalservice = VnodGlobalService.get_service_objects().filter(servicehandle=servicehandle)
+ if (not vnodglobalservice):
+ HttpResponseBadRequest('Error: Could not find VnodGlobalObject with servicehandle=' + servicehandle)
+
+ vnodglobalservice = vnodglobalservice[0]
+ all_spokes_active_and_enabled = True
+
+ for spoke in vnodglobalservice.spokes.all():
+ if (spoke.operstate != 'active' or spoke.adminstate != 'enabled'):
+ all_spokes_active_and_enabled = False
+ break;
+
+ if (all_spokes_active_and_enabled):
+ vnodglobalservice.operstate = 'active'
+ else:
+ vnodglobalservice.operstate = 'inactive'
+
+ vnodglobalservice.save()
+ return all_spokes_active_and_enabled
+
+ @classmethod
+ def createService(self, servicehandle):
+ vnodglobalservice = VnodGlobalService.get_service_objects().filter(servicehandle=servicehandle)
+ if (not vnodglobalservice):
+ HttpResponseBadRequest('Error: Could not find VnodGlobalObject with servicehandle=' + servicehandle)
+
+ vnodglobalservice = vnodglobalservice[0]
+ if (vnodglobalservice.type == 'eline'):
+
+ spokes = vnodglobalservice.spokes.all()
+ uni1 = spokes[0].vnodlocalport.edgeport
+ uni2 = spokes[1].vnodlocalport.edgeport
+ name = 'ELine-' + str(vnodglobalservice.id)
+ type = 'Point_To_Point'
+ operstate = 'active'
+ adminstate = 'activationrequested'
+
+ eline = NetworkEdgeToEdgePointConnection()
+ eline.name = name
+ eline.type = type
+ eline.operstate = operstate
+ eline.adminstate = adminstate
+ eline.vlanid = vnodglobalservice.vlanid
+ eline.sid = name
+ eline.uni1 = NetworkEdgePort.objects.get(pid=uni1.pid)
+ eline.uni2 = NetworkEdgePort.objects.get(pid=uni2.pid)
+
+ eline.save()
+ vnodglobalservice.metronetworkpointtopoint = eline
+ vnodglobalservice.save()
+
+ elif (vnodglobalservice.type == 'elan'):
+
+ spokes = vnodglobalservice.spokes.all()
+
+ name = 'ELAN-' + str(vnodglobalservice.id)
+ type = 'Multipoint_To_Multipoint'
+ operstate = 'active'
+ adminstate = 'activationrequested'
+
+ elan = NetworkMultipointToMultipointConnection()
+ elan.name = name
+ elan.type = type
+ elan.operstate = 'inactive'
+ elan.adminstate = 'disabled'
+ elan.vlanid = vnodglobalservice.vlanid
+ elan.save()
+
+ for spoke in spokes:
+ uni = NetworkEdgePort.objects.get(pid=spoke.vnodlocalport.edgeport.pid)
+ elan.eps.add(uni)
+
+ elan.operstate = operstate
+ elan.adminstate = adminstate
+ elan.save()
+
+ vnodglobalservice.metronetworkmultipoint = elan
+ vnodglobalservice.save()
+
+ # TODO: elif (vnodglobalservice.type == 'etree'):
+
+class VnodGlobalServiceAutoAttachmentView(APIView):
+ method_kind = "list"
+ method_name = "vnodglobal_api_autoattach"
+
+ def get(self, request, format=None):
+ params = request.query_params
+ sitename = params.get('sitename')
+
+ if ( sitename is None):
+ HttpResponseBadRequest("Error: Request requires] 'sitename' as a query param.")
+
+ vnodglobalservices = VnodGlobalService.get_service_objects().filter(spokes__autoattached=True,
+ spokes__operstate='inactive',
+ spokes__vnodlocalsite__name=sitename)
+
+ if (not vnodglobalservices):
+ HttpResponseBadRequest({"handles" : []})
+
+ handles = []
+ for vnodglobalservice in vnodglobalservices:
+ if (vnodglobalservice.adminstate != 'disabled'):
+ handles.append(vnodglobalservice.servicehandle)
+
+ response_data = {'servicehandles' : handles}
+ return Response(response_data)
+
+class VnodGlobalServiceConfigurationView(APIView):
+ method_kind = "list"
+ method_name = "vnodglobal_api_configuration"
+
+ def get(self, request, format=None):
+ params = request.query_params
+ servicehandle = params.get('servicehandle')
+ sitename = params.get('sitename')
+
+ if (servicehandle is None or sitename is None):
+ HttpResponseBadRequest("Error: Request requires 'servicehandle' and 'sitename' as query params.")
+
+ vnodglobalservice = VnodGlobalService.get_service_objects().filter(servicehandle=servicehandle)
+ if (not vnodglobalservice):
+ HttpResponseBadRequest('Error: Could not find VnodGlobalObject with servicehandle=' + servicehandle)
+
+ vnodglobalservice = vnodglobalservice[0]
+ response_data = {}
+ response_data['vlanid'] = vnodglobalservice.vlanid
+
+ for spoke in vnodglobalservice.spokes.all():
+ if (spoke.vnodlocalsite.name == sitename and spoke.adminstate != 'configured'):
+ response_data['port'] = {}
+ response_data['port']['name'] = spoke.vnodlocalport.name
+ break;
+
+ return Response(response_data)
+
+class VnodGlobalServiceActivationView(APIView):
+ method_kind = "list"
+ method_name = "vnodglobal_api_activation"
+
+ def post(self, request, format=None):
+ body_json = request.body
+ body = json.loads(body_json)
+
+ servicehandle=body['servicehandle']
+ sitename=body['sitename']
+ activate = body['activate']
+ vnodlocalid = body['vnodlocalid']
+ portid = body.get('portid')
+
+ if (activate == 'true' or activate == 'True'):
+ isActivate = True
+ else:
+ isActivate = False
+
+ vnodglobalservice = VnodGlobalService.get_service_objects().filter(servicehandle=servicehandle)
+ if (not vnodglobalservice):
+ HttpResponseBadRequest('Error: Could not find VnodGlobalObject with servicehandle=' + servicehandle)
+
+ vnodglobalservice = vnodglobalservice[0]
+
+ for spoke in vnodglobalservice.spokes.all():
+ if (spoke.vnodlocalsite.name == sitename and spoke.vnodlocalport.name == portid):
+ spoke_id = spoke.id
+ servicespoke = ServiceSpoke.objects.get(id=spoke_id)
+ servicespoke.remotevnodid = vnodlocalid
+ servicespoke.save()
+ break;
+
+ return Response()
+
+class VnodGlobalServiceAdminOperationalStateView(APIView):
+ method_kind = "list"
+ method_name = "vnodglobal_api_status"
+
+ def post(self, request, format=None):
+ body_json = request.body
+ body = json.loads(body_json)
+
+ servicehandle = body['servicehandle']
+ sitename = body['sitename']
+ operstate = body.get('operstate')
+ adminstate = body.get('adminstate')
+ portid = body.get('portid')
+
+ vnodglobalservice = VnodGlobalService.get_service_objects().filter(servicehandle=servicehandle)
+ if (not vnodglobalservice):
+ HttpResponseBadRequest('Error: Could not find VnodGlobalObject with servicehandle=' + servicehandle)
+
+ vnodglobalservice = vnodglobalservice[0]
+
+ for spoke in vnodglobalservice.spokes.all():
+ if (spoke.vnodlocalsite.name == sitename and spoke.vnodlocalport.name == portid):
+ spoke_id = spoke.id
+ servicespoke = ServiceSpoke.objects.get(id=spoke_id)
+ if (operstate):
+ servicespoke.operstate = operstate
+ if (adminstate):
+ servicespoke.adminstate = adminstate
+ servicespoke.save()
+ break;
+
+ isGlobalActive = VnodGlobalServiceViewSet.calculateVnodGlobalOperState(servicehandle=servicehandle)
+
+ if (vnodglobalservice.metronetworkmultipoint is None and vnodglobalservice.metronetworkpointtopoint is None and
+ vnodglobalservice.metronetworkroottomultipoint is None and isGlobalActive):
+ VnodGlobalServiceViewSet.createService(servicehandle=servicehandle)
+
+ return Response()