Prevent synchronizer to push OLTs to VOLTHA if they have feedback state
Moved the s_tag in the PONPort Model
Change-Id: I8e6b07ff925f0df7772a66425e9ddaa944cfe9fb
diff --git a/samples/olt_device.yaml b/samples/olt_device.yaml
index e5e898c..c8a1485 100644
--- a/samples/olt_device.yaml
+++ b/samples/olt_device.yaml
@@ -17,6 +17,7 @@
tosca_definitions_version: tosca_simple_yaml_1_0
imports:
- custom_types/oltdevice.yaml
+ - custom_types/ponport.yaml
- custom_types/voltservice.yaml
description: Create a simulated OLT Device in VOLTHA
topology_template:
@@ -39,3 +40,14 @@
- volt_service:
node: service#volt
relationship: tosca.relationships.BelongsToOne
+
+ pon_port:
+ type: tosca.nodes.PONPort
+ properties:
+ name: test_olt_port_1
+ port_id: ff00ff
+ s_tag: 111
+ requirements:
+ - olt_device:
+ node: device#olt
+ relationship: tosca.relationships.BelongsToOne
diff --git a/xos/synchronizer/models/volt.xproto b/xos/synchronizer/models/volt.xproto
index a58b696..b66bddc 100644
--- a/xos/synchronizer/models/volt.xproto
+++ b/xos/synchronizer/models/volt.xproto
@@ -39,7 +39,6 @@
optional string of_id = 13 [help_text = "openflow id", null = True, db_index = False, blank = False, feedback_state = True];
required string uplink = 14 [default="129", help_text = "uplink port", null = False, db_index = False, blank = False];
- required string vlan = 15 [default="3", help_text = "same as S-Tag", null = True, db_index = False, blank = False];
required string driver = 16 [default="pmc-olt", help_text = "Olt driver", null = True, db_index = False, blank = False];
}
@@ -55,7 +54,7 @@
option verbose_name = "PON Port";
required string name = 1 [db_index = True, null = False, blank = False];
- required manytoone volt_device->OLTDevice:ports = 2 [db_index = True, null = False, blank = False];
- required string port_id = 3 [help_text = "Port ID (Feedback State)", max_length = 254, null = False, db_index = False, blank = False];
+ required manytoone olt_device->OLTDevice:ports = 2 [db_index = True, null = False, blank = False];
+ required string port_id = 3 [help_text = "Port ID", max_length = 254, null = False, db_index = False, blank = False];
required int32 s_tag = 4 [help_text = "S Tag", null = False, db_index = False, blank = False];
}
diff --git a/xos/synchronizer/steps/sync_olt_device.py b/xos/synchronizer/steps/sync_olt_device.py
index 591f7f9..74da3b0 100644
--- a/xos/synchronizer/steps/sync_olt_device.py
+++ b/xos/synchronizer/steps/sync_olt_device.py
@@ -72,56 +72,66 @@
def sync_record(self, o):
log.info("sync'ing device", object=str(o), **o.tologdict())
- voltha_url = self.get_voltha_info(o)['url']
+ # If the device has feedback_state is already present in voltha
+ if not o.device_id and not o.admin_state and not o.oper_status and not o.of_id:
+ log.info("Pushing device to VOLTHA", object=str(o), **o.tologdict())
+ voltha_url = self.get_voltha_info(o)['url']
- data = {
- "type": o.device_type,
- "host_and_port": "%s:%s" % (o.host, o.port)
- }
+ data = {
+ "type": o.device_type,
+ "host_and_port": "%s:%s" % (o.host, o.port)
+ }
- if o.device_type == 'simulated_olt':
- # simulated devices won't accept host and port, for testing only
- data.pop('host_and_port')
- data['mac_address'] = "00:0c:e2:31:40:00"
+ if o.device_type == 'simulated_olt':
+ # simulated devices won't accept host and port, for testing only
+ data.pop('host_and_port')
+ data['mac_address'] = "00:0c:e2:31:40:00"
- log.info("pushing olt to voltha", data=data)
+ log.info("pushing olt to voltha", data=data)
- r = requests.post(voltha_url + "/api/v1/devices", json=data)
+ r = requests.post(voltha_url + "/api/v1/devices", json=data)
- if r.status_code != 200:
- raise Exception("Failed to add device: %s" % r.text)
+ if r.status_code != 200:
+ raise Exception("Failed to add device: %s" % r.text)
- log.info("add device response", text=r.text)
+ log.info("add device response", text=r.text)
- res = r.json()
+ res = r.json()
- print log.info("add device json res", res=res)
+ log.info("add device json res", res=res)
- if not res['id']:
- raise Exception('VOLTHA Device Id is empty, this probably means that the device is already provisioned in VOLTHA')
- else:
- o.device_id = res['id'];
+ if not res['id']:
+ raise Exception('VOLTHA Device Id is empty, this probably means that the device is already provisioned in VOLTHA')
+ else:
+ o.device_id = res['id'];
- # enable device
+ # enable device
- r = requests.post(voltha_url + "/api/v1/devices/" + o.device_id + "/enable")
+ r = requests.post(voltha_url + "/api/v1/devices/" + o.device_id + "/enable")
- if r.status_code != 200:
- raise Exception("Failed to enable device: %s" % r.text)
+ if r.status_code != 200:
+ raise Exception("Failed to enable device: %s" % r.text)
- # read state
- r = requests.get(voltha_url + "/api/v1/devices/" + o.device_id).json()
- while r['oper_status'] == "ACTIVATING":
- log.info("Waiting for device %s (%s) to activate" % (o.name, o.device_id))
- sleep(5)
+ # read state
r = requests.get(voltha_url + "/api/v1/devices/" + o.device_id).json()
+ while r['oper_status'] == "ACTIVATING":
+ log.info("Waiting for device %s (%s) to activate" % (o.name, o.device_id))
+ sleep(5)
+ r = requests.get(voltha_url + "/api/v1/devices/" + o.device_id).json()
- o.admin_state = r['admin_state']
- o.oper_status = r['oper_status']
+ o.admin_state = r['admin_state']
+ o.oper_status = r['oper_status']
- # find of_id of device
- o.of_id = self.get_of_id_from_device(o)
- o.save()
+ # find of_id of device
+ o.of_id = self.get_of_id_from_device(o)
+ o.save()
+ else:
+ log.info("Device already exists in VOLTHA", object=str(o), **o.tologdict())
+
+
+ # NOTE do we need to move this synchronization in a PON_PORT specific step?
+ # for now we assume that each OLT has only one Port
+ vlan = o.ports.all()[0].s_tag
# add device info to P-ONOS
data = {
@@ -132,7 +142,7 @@
},
"accessDevice": {
"uplink": o.uplink,
- "vlan": o.vlan
+ "vlan": vlan
}
}
}
diff --git a/xos/synchronizer/steps/test_sync_olt_device.py b/xos/synchronizer/steps/test_sync_olt_device.py
index cac697d..cd4906f 100644
--- a/xos/synchronizer/steps/test_sync_olt_device.py
+++ b/xos/synchronizer/steps/test_sync_olt_device.py
@@ -40,6 +40,17 @@
raise Exception("Unable to find service=%s xproto=%s" % (service_name, xproto_name))
# END generate model from xproto
+def match_onos_req(req):
+ r = req.json()['devices']
+ if not r['abc']:
+ return False
+ else:
+ if not r['abc']['basic']['driver'] == 'pmc-olt':
+ return False
+ if not r['abc']['accessDevice']['vlan'] == "s_tag" or not r['abc']['accessDevice']['uplink'] == "129":
+ return False
+ return True
+
class TestSyncOLTDevice(unittest.TestCase):
def setUp(self):
@@ -61,6 +72,10 @@
from sync_olt_device import SyncOLTDevice
self.sync_step = SyncOLTDevice
+ pon_port = Mock()
+ pon_port.port_id = "00ff00"
+ pon_port.s_tag = "s_tag"
+
# create a mock service instance
o = Mock()
o.volt_service.voltha_url = "voltha_url"
@@ -74,13 +89,20 @@
o.host = "172.17.0.1"
o.port = "50060"
o.uplink = "129"
- o.vlan = "3"
o.driver = "pmc-olt"
+ # feedback state
+ o.device_id = None
+ o.admin_state = None
+ o.oper_status = None
+ o.of_id = None
+
o.tologdict.return_value = {'name': "Mock VOLTServiceInstance"}
o.save.return_value = "Saved"
+ o.ports.all.return_value = [pon_port]
+
self.o = o
def tearDown(self):
@@ -175,17 +197,6 @@
}
m.get("http://voltha_url/api/v1/logical_devices", status_code=200, json=logical_devices)
- def match_onos_req(req):
- r = req.json()['devices']
- if not r['abc']:
- return False
- else:
- if not r['abc']['basic']['driver'] == 'pmc-olt':
- return False
- if not r['abc']['accessDevice']['vlan'] == "3" or not r['abc']['accessDevice']['uplink'] == "129":
- return False
- return True
-
m.post("http://p_onos_url/onos/v1/network/configuration/", status_code=200, additional_matcher=match_onos_req, json={})
self.sync_step().sync_record(self.o)
@@ -195,6 +206,21 @@
self.o.save.assert_called_once()
@requests_mock.Mocker()
+ def test_sync_record_already_existing_in_voltha(self, m):
+
+ # mock device feedback state
+ self.o.device_id = "123"
+ self.o.admin_state = "ACTIVE"
+ self.o.oper_status = "ENABLED"
+ self.o.of_id = "abc"
+
+ m.post("http://p_onos_url/onos/v1/network/configuration/", status_code=200, additional_matcher=match_onos_req, json={})
+
+ self.sync_step().sync_record(self.o)
+ self.o.save.assert_not_called()
+
+
+ @requests_mock.Mocker()
def test_delete_record(self, m):
self.o.of_id = "abc"
self.o.device_id = "123"