Adding UNI to be onboarded via Tosca

Change-Id: Ib1f38203372575c1e2638fd1d961221972f4f1f7
diff --git a/xos/api/service/metronetworkservice/metronetworkservice.py b/xos/api/service/metronetworkservice/metronetworkservice.py
index 764205d..cf6623d 100644
--- a/xos/api/service/metronetworkservice/metronetworkservice.py
+++ b/xos/api/service/metronetworkservice/metronetworkservice.py
@@ -397,6 +397,7 @@
     class Meta:
         model = BandwidthProfile
 
+
         fields = ('humanReadableName',
                   'id',
                   'bwpcfgcbs',
@@ -451,6 +452,71 @@
 
         return Response(response_data)
 
+class UserNetworkInterfaceSerializer(PlusModelSerializer):
+    humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
+
+    class Meta:
+        model = UserNetworkInterface
+
+        fields = ('humanReadableName',
+                  'id',
+                  'bwpcfgcbs',
+                  'bwpcfgebs',
+                  'bwpcfgcir',
+                  'bwpcfgeir',
+                  'name'
+                  )
+
+    def getHumanReadableName(self, obj):
+        return obj.name
+
+class UserNetworkInterfaceViewSet(XOSViewSet):
+    base_name = "USER_NETWORK_INTERFACE"
+    method_name = "USER_NETWORK_INTERFACE"
+    method_kind = "viewset"
+    queryset = UserNetworkInterface.objects.all()
+    serializer_class = UserNetworkInterfaceSerializer
+
+    @classmethod
+    def get_urlpatterns(self, api_path="^"):
+        patterns = super(UserNetworkInterfaceViewSet, 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):
+
+        userNetworkInterface = UserNetworkInterface()
+
+        userNetworkInterface.name = validated_data.data.get('name')
+        userNetworkInterface.capacity = validated_data.data.get('capacity')
+        userNetworkInterface.bw_used = validated_data.data.get('bw_used')
+        userNetworkInterface.vlanIds = validated_data.data.get('vlanIds')
+        userNetworkInterface.location = validated_data.data.get('location')
+        userNetworkInterface.latlng = validated_data.data.get('latlng')
+
+        copyin_props = ['enabled', 'capacity', 'bw_used', 'vlanIds', 'location', 'latlng', 'name']
+
+        userNetworkInterface.save()
+
+        response_data = {}
+        response_data['name'] = userNetworkInterface.name
+        response_data['capacity'] = userNetworkInterface.capacity
+        response_data['bw_used'] = userNetworkInterface.bw_used
+        response_data['vlanIds'] = userNetworkInterface.vlanIds
+        response_data['location'] = userNetworkInterface.location
+        response_data['latlng'] = userNetworkInterface.latlng
+        response_data['id'] = userNetworkInterface.id
+
+        return Response(response_data)
+
 class VnodSiteSerializer(PlusModelSerializer):
     humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
 
diff --git a/xos/metronet.m4 b/xos/metronet.m4
index 7fcc6b4..c9e6eb8 100644
--- a/xos/metronet.m4
+++ b/xos/metronet.m4
@@ -64,7 +64,6 @@
         description: >
             CORD: The ecord bandwith profile.
         capabilities:
-            xos_base_service_caps
         properties:
             xos_base_props
             bwpcfgcbs:
@@ -83,6 +82,35 @@
                 type: string
                 required: true
 
+   tosca.nodes.EcordUserNetworkInterface:
+        derived_from: tosca.nodes.Root
+        description: >
+            CORD: The ecord user netowrk interface
+        capabilities:
+        properties:
+            xos_base_props
+            enabled:
+                type: boolean
+                required: false
+            capacity:
+                type: integer
+                required: false
+            bw_used:
+                type: integer
+                required: false
+            vlanIds:
+                type: string
+                required: false
+            name:
+                type: string
+                required: true
+            location:
+                type: string
+                required: false
+            latlng:
+                type: string
+                required: false
+
    tosca.relationships.UsesBandwidthProfile:
         derived_from: tosca.relationships.Root
         valid_target_types: [ tosca.capabilities.xos.EcordBandwidthProfile ]
\ No newline at end of file
diff --git a/xos/metronet.yaml b/xos/metronet.yaml
index c0eb018..6a700fa 100644
--- a/xos/metronet.yaml
+++ b/xos/metronet.yaml
@@ -190,10 +190,6 @@
         description: >
             CORD: The ecord bandwith profile.
         capabilities:
-            scalable:
-                type: tosca.capabilities.Scalable
-            service:
-                type: tosca.capabilities.xos.Service
         properties:
             no-delete:
                 type: boolean
@@ -227,6 +223,50 @@
                 type: string
                 required: true
 
+   tosca.nodes.EcordUserNetworkInterface:
+        derived_from: tosca.nodes.Root
+        description: >
+            CORD: The ecord user netowrk interface
+        capabilities:
+        properties:
+            no-delete:
+                type: boolean
+                default: false
+                description: Do not allow Tosca to delete this object
+            no-create:
+                type: boolean
+                default: false
+                description: Do not allow Tosca to create this object
+            no-update:
+                type: boolean
+                default: false
+                description: Do not allow Tosca to update this object
+            replaces:
+                type: string
+                required: false
+                descrption: Replaces/renames this object
+            enabled:
+                type: boolean
+                required: false
+            capacity:
+                type: integer
+                required: false
+            bw_used:
+                type: integer
+                required: false
+            vlanIds:
+                type: string
+                required: false
+            name:
+                type: string
+                required: true
+            location:
+                type: string
+                required: false
+            latlng:
+                type: string
+                required: false
+
    tosca.relationships.UsesBandwidthProfile:
         derived_from: tosca.relationships.Root
         valid_target_types: [ tosca.capabilities.xos.EcordBandwidthProfile ]
\ No newline at end of file
diff --git a/xos/models.py b/xos/models.py
index 4ebda3b..580bb4f 100644
--- a/xos/models.py
+++ b/xos/models.py
@@ -461,3 +461,43 @@
 
     def __init__(self, *args, **kwargs):
         super(VnodGlobalService, self).__init__(*args, **kwargs)
+
+
+class UserNetworkInterface(PlCoreBase):
+
+    class Meta:
+        app_label = METRONETWORK_KIND
+        verbose_name = "User Network Interface"
+
+    id = models.AutoField(verbose_name="id", primary_key=True, editable=False)
+    enabled = models.IntegerField(verbose_name="State of UNI", editable=True)
+    capacity = models.IntegerField(verbose_name="UNI Capacity", editable=True)
+    bw_used = models.IntegerField(verbose_name="UNI bandwidth used", editable=True)
+    vlanIds = models.CharField(verbose_name="VlanIds in this UNI", max_length=256, editable=True)
+    location = models.CharField(verbose_name="Location", max_length=256, editable=True, blank=True)
+    latlng = models.CharField(verbose_name="Latitude/Longitude", max_length=50, editable=True, blank=True)
+    name = models.CharField(unique=True, verbose_name="Name", max_length=256, editable=True)
+
+    def __init__(self, *args, **kwargs):
+        super(UserNetworkInterface, self).__init__(*args, **kwargs)
+
+    def __unicode__(self):  return u'%s' % (self.name)
+
+    def save(self, *args, **kwargs):
+
+        if self.latlng:
+            try:
+                latlng_value = getattr(self, 'latlng').strip()
+                if (latlng_value.startswith('[') and latlng_value.endswith(']') and latlng_value.index(',') > 0):
+                    lat = latlng_value[1: latlng_value.index(',')].strip()
+                    lng = latlng_value[latlng_value.index(',') + 1: len(latlng_value) - 1].strip()
+
+                    # If lat and lng are not floats, the code below should result in an error.
+                    lat_validation = float(lat)
+                    lng_validation = float(lng)
+                else:
+                    raise ValueError("The lat/lng value is not formatted correctly.")
+            except:
+                raise ValueError("The lat/lng value is not formatted correctly.")
+
+        super(UserNetworkInterface, self).save(*args, **kwargs)
\ No newline at end of file
diff --git a/xos/tosca/resources/metronetservice.py b/xos/tosca/resources/metronetservice.py
index 3ed5e59..372337f 100644
--- a/xos/tosca/resources/metronetservice.py
+++ b/xos/tosca/resources/metronetservice.py
@@ -29,4 +29,9 @@
 class XOSMetronetBandwithProficle(XOSResource):
     provides = "tosca.nodes.EcordBandwidthProfile"
     xos_model = BandwidthProfile
-    copyin_props = ['bwpcfgcbs','bwpcfgebs','bwpcfgcir','bwpcfgeir','name']
\ No newline at end of file
+    copyin_props = ['bwpcfgcbs','bwpcfgebs','bwpcfgcir','bwpcfgeir','name']
+
+class XOSMetronetUNI(XOSResource):
+    provides = "tosca.nodes.EcordUserNetworkInterface"
+    xos_model = UserNetworkInterface
+    copyin_props = ['enabled','capacity','bw_used','vlanIds', 'location', 'latlng', 'name']
\ No newline at end of file