[SEBA-742] Adding methods to validate subscriber tech_profile association

Change-Id: I4287f7021fa2c3cac6f025ac829ab280bf09e8ba
diff --git a/Makefile b/Makefile
index 33abf12..9a1b268 100644
--- a/Makefile
+++ b/Makefile
@@ -60,7 +60,7 @@
 venv-service:
 	virtualenv $@;\
     source ./$@/bin/activate ; set -u ;\
-    pip install -r requirements.txt xosmigrate~=3.2.6
+    pip install -r requirements.txt xosmigrate~=3.2.6 django
 
 create-migration: venv-service
 	source ./venv-service/bin/activate; set -u;\
diff --git a/tox.ini b/tox.ini
index 9064a11..73c1e23 100644
--- a/tox.ini
+++ b/tox.ini
@@ -23,6 +23,7 @@
   -r requirements.txt
   requests_mock
   nose2
+  django
 ;  flake8
 
 changedir = xos
diff --git a/xos/synchronizer/migrations/0010_auto_20190620_1906.py b/xos/synchronizer/migrations/0010_auto_20190620_1906.py
new file mode 100644
index 0000000..4588258
--- /dev/null
+++ b/xos/synchronizer/migrations/0010_auto_20190620_1906.py
@@ -0,0 +1,38 @@
+# 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.
+
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.21 on 2019-06-20 23:06
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('volt', '0009_auto_20190610_1723'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='oltdevice_decl',
+            name='technology',
+            field=models.CharField(choices=[(b'gpon', b'gpon'), (b'xgspon', b'xgspon')], db_index=True, default=b'xgspon', help_text=b'The technology being utilized by the adapter', max_length=16),
+        ),
+        migrations.AlterUniqueTogether(
+            name='technologyprofile_decl',
+            unique_together=set([('profile_id', 'technology')]),
+        ),
+    ]
diff --git a/xos/synchronizer/models/models.py b/xos/synchronizer/models/models.py
index 643b5d3..5114871 100644
--- a/xos/synchronizer/models/models.py
+++ b/xos/synchronizer/models/models.py
@@ -26,6 +26,7 @@
 from models_decl import ANIPort_decl, ANIPort
 from models_decl import UNIPort_decl, UNIPort
 from models_decl import TechnologyProfile_decl
+from django.core.exceptions import ObjectDoesNotExist
 
 import json
 
@@ -41,6 +42,36 @@
         except IndexError, e:
             return False
 
+    def get_olt_technology_from_unu_sn(self, onu_sn):
+        """
+        Return the technology assigned to an OLT Device given and ONU Serial Number
+        example usage:
+            volt = VOLTService.objects.first()
+            sn = volt.get_olt_technology_from_unu_sn("BRCM12345678")
+            # "XGSPON"
+
+        Arguments:
+            onu_sn {string} -- The ONU Serial Number
+
+        Returns:
+            string -- Technology
+        """
+        try:
+            onu = ONUDevice.objects.get(serial_number=onu_sn)
+            olt = onu.pon_port.olt_device
+            return olt.technology
+        except ObjectDoesNotExist:
+            raise XOSNotFound("Can't find OLT for %s" % onu_sn, serial_number=onu_sn)
+
+    def get_tech_profile(self, technology, profile_id):
+        """
+        Returns a Technology profiles or raise an Exception (DoesNotExist)
+        :param technology: string
+        :param profile_id: int
+        :return: TechnologyProfile
+        """
+        return TechnologyProfile.objects.get(technology=technology, profile_id=profile_id)
+
 class OLTDevice(OLTDevice_decl):
     class Meta:
         proxy = True
diff --git a/xos/synchronizer/models/volt.xproto b/xos/synchronizer/models/volt.xproto
index 5abdf6f..cabf0c2 100644
--- a/xos/synchronizer/models/volt.xproto
+++ b/xos/synchronizer/models/volt.xproto
@@ -101,6 +101,14 @@
     optional string nas_id = 20 [
         help_text = "Authentication ID (propagated to the free-radius server via sadis)",
         max_length = 256];
+
+    required string technology = 22 [
+        help_text = "The technology being utilized by the adapter",
+        db_index = True,
+        tosca_key = True,
+        max_length = 16,
+        choices = "(('gpon', 'gpon'), ('xgspon', 'xgspon'))",
+        default = "xgspon"];
 }
 
 message PortBase (XOSBase){
@@ -116,12 +124,10 @@
 
     optional string admin_state = 4 [
         help_text = "admin state, whether port should be enabled",
-        // TODO: Should specify "choices"
         feedback_state = True,
         max_length = 32];
     optional string oper_status = 5 [
         help_text = "operational status, whether port is active",
-        // TODO: Should specify "choices"
         feedback_state = True,
         max_length = 32];
 }
@@ -237,7 +243,9 @@
         db_index = True,
         tosca_key = True,
         min_value = 64,
-        max_value = 255];
+        max_value = 255,
+        unique_with = "technology"];
+
     required string profile_value = 3 [
         help_text = "The technology profile value in JSON format",
         max_length = 4096];