[CORD-3091] Pulling NNI and PON ports
Change-Id: I001782ffd8a092371f4939869c9c6dda2360bf98
diff --git a/xos/synchronizer/pull_steps/pull_olts.py b/xos/synchronizer/pull_steps/pull_olts.py
index 36cac45..370250d 100644
--- a/xos/synchronizer/pull_steps/pull_olts.py
+++ b/xos/synchronizer/pull_steps/pull_olts.py
@@ -13,7 +13,7 @@
# limitations under the License.
from synchronizers.new_base.pullstep import PullStep
-from synchronizers.new_base.modelaccessor import model_accessor, OLTDevice, VOLTService
+from synchronizers.new_base.modelaccessor import model_accessor, OLTDevice, VOLTService, PONPort, NNIPort
from xosconfig import Config
from multistructlog import create_logger
@@ -79,9 +79,6 @@
# TODO
# [ ] delete OLTS as OLTDevice.objects.all() - updated OLTs
- if r.status_code != 200:
- log.info("It was not possible to fetch devices from VOLTHA")
-
olts_in_voltha = self.create_or_update_olts(devices)
except ConnectionError, e:
@@ -102,10 +99,13 @@
else:
[host, port] = olt["host_and_port"].split(":")
model = OLTDevice.objects.filter(device_type=olt["type"], host=host, port=port)[0]
+
log.debug("OLTDevice already exists, updating it", device_type=olt["type"], host=host, port=port)
if model.enacted < model.updated:
log.info("Skipping pull on OLTDevice %s as enacted < updated" % model.name, name=model.name, id=model.id, enacted=model.enacted, updated=model.updated)
+ # if we are not updating the device we still need to pull ports
+ self.fetch_olt_ports(model)
return
except IndexError:
@@ -115,6 +115,10 @@
if olt["type"] == "simulated_olt":
model.host = "172.17.0.1"
model.port = 50060
+ else:
+ [host, port] = olt["host_and_port"].split(":")
+ model.host = host
+ model.port = int(port)
log.debug("OLTDevice is new, creating it", device_type=olt["type"], host=host, port=port)
@@ -131,10 +135,85 @@
model.save()
+ self.fetch_olt_ports(model)
+
updated_olts.append(model)
return updated_olts
+ def fetch_olt_ports(self, olt):
+ voltha_url = Helpers.get_voltha_info(self.volt_service)['url']
+ voltha_port = Helpers.get_voltha_info(self.volt_service)['port']
+
+ try:
+ r = requests.get("%s:%s/api/v1/devices/%s/ports" % (voltha_url, voltha_port, olt.device_id))
+
+ if r.status_code != 200:
+ log.info("It was not possible to fetch ports from VOLTHA for device %s" % olt.device_id)
+
+ ports = r.json()['items']
+
+ log.debug("received ports", ports=ports, olt=olt.device_id)
+
+ self.create_or_update_ports(ports, olt)
+
+ except ConnectionError, e:
+ log.warn("It was not possible to connect to VOLTHA", reason=e)
+ return
+ except InvalidURL, e:
+ log.warn("VOLTHA url is invalid, is it configured in the VOLTService?", reason=e)
+ return
+ return
+
+ def create_or_update_ports(self, ports, olt):
+ nni_ports = [p for p in ports if "ETHERNET_NNI" in p["type"]]
+ pon_ports = [p for p in ports if "PON_OLT" in p["type"]]
+
+ self.create_or_update_nni_port(nni_ports, olt)
+ self.create_or_update_pon_port(pon_ports, olt)
+
+ def create_or_update_pon_port(self, pon_ports, olt):
+
+ update_ports = []
+
+ for port in pon_ports:
+ try:
+ model = PONPort.objects.filter(port_no=port["port_no"], olt_device_id=olt.id)[0]
+ log.debug("PONPort is new, creating it", port_no=port["port_no"], olt_device_id=olt.id)
+ except IndexError:
+ model = PONPort()
+ model.port_no = port["port_no"]
+ model.olt_device_id = olt.id
+ model.name = port["label"]
+ log.debug("PONPort already exists, updating it", port_no=port["port_no"], olt_device_id=olt.id)
+
+ model.admin_state = port["admin_state"]
+ model.oper_status = port["oper_status"]
+ model.save()
+ update_ports.append(model)
+ return update_ports
+
+ def create_or_update_nni_port(self, nni_ports, olt):
+ update_ports = []
+
+ for port in nni_ports:
+ try:
+ model = NNIPort.objects.filter(port_no=port["port_no"], olt_device_id=olt.id)[0]
+ model.xos_managed = False
+ log.debug("NNIPort is new, creating it", port_no=port["port_no"], olt_device_id=olt.id)
+ except IndexError:
+ model = NNIPort()
+ model.port_no = port["port_no"]
+ model.olt_device_id = olt.id
+ model.name = port["label"]
+ model.xos_managed = False
+ log.debug("NNIPort already exists, updating it", port_no=port["port_no"], olt_device_id=olt.id)
+
+ model.admin_state = port["admin_state"]
+ model.oper_status = port["oper_status"]
+ model.save()
+ update_ports.append(model)
+ return update_ports
diff --git a/xos/synchronizer/pull_steps/pull_onus.py b/xos/synchronizer/pull_steps/pull_onus.py
index cc60ca3..b762297 100644
--- a/xos/synchronizer/pull_steps/pull_onus.py
+++ b/xos/synchronizer/pull_steps/pull_onus.py
@@ -13,7 +13,7 @@
# limitations under the License.
from synchronizers.new_base.pullstep import PullStep
-from synchronizers.new_base.modelaccessor import model_accessor, ONUDevice, VOLTService, OLTDevice
+from synchronizers.new_base.modelaccessor import model_accessor, ONUDevice, VOLTService, OLTDevice, PONPort
from xosconfig import Config
from multistructlog import create_logger
@@ -34,8 +34,6 @@
super(ONUDevicePullStep, self).__init__(observed_model=ONUDevice)
def pull_records(self):
- return
- # FIXME we need to pull PON Ports before
log.info("pulling ONU devices from VOLTHA")
try:
@@ -84,7 +82,7 @@
log.debug("ONUDevice already exists, updating it", serial_number=onu["serial_number"])
if model.enacted < model.updated:
- log.info("Skipping pull on ONUDevice %s as enacted < updated" % model.name, name=model.name, id=model.id, enacted=model.enacted, updated=model.updated)
+ log.info("Skipping pull on ONUDevice %s as enacted < updated" % model.serial_number, serial_number=model.serial_number, id=model.id, enacted=model.enacted, updated=model.updated)
return
except IndexError:
@@ -101,11 +99,13 @@
model.admin_state = onu["admin_state"]
model.oper_status = onu["oper_status"]
model.connect_status = onu["connect_status"]
+ model.xos_managed = False
- # olt = OLTDevice.objects.get(device_id=onu["proxy_address"]["device_id"])
- #
- # model.olt_device = olt
- # model.olt_device_id = olt.id
+ olt = OLTDevice.objects.get(device_id=onu["parent_id"])
+ pon_port = PONPort.objects.get(port_no=onu["parent_port_no"], olt_device_id=olt.id)
+
+ model.pon_port = pon_port
+ model.pon_port_id = pon_port.id
model.save()
diff --git a/xos/synchronizer/pull_steps/test_pull_olts.py b/xos/synchronizer/pull_steps/test_pull_olts.py
index a0ef017..91b64e3 100644
--- a/xos/synchronizer/pull_steps/test_pull_olts.py
+++ b/xos/synchronizer/pull_steps/test_pull_olts.py
@@ -104,6 +104,25 @@
]
}
+ self.ports = {
+ "items": [
+ {
+ "label": "PON port",
+ "port_no": 1,
+ "type": "PON_OLT",
+ "admin_state": "ENABLED",
+ "oper_status": "ACTIVE"
+ },
+ {
+ "label": "NNI facing Ethernet port",
+ "port_no": 2,
+ "type": "ETHERNET_NNI",
+ "admin_state": "ENABLED",
+ "oper_status": "ACTIVE"
+ }
+ ]
+ }
+
def tearDown(self):
sys.path = self.sys_path_save
@@ -115,10 +134,13 @@
def test_pull(self, m):
with patch.object(VOLTService.objects, "all") as olt_service_mock, \
- patch.object(OLTDevice, "save") as mock_save:
+ patch.object(OLTDevice, "save") as mock_olt_save, \
+ patch.object(PONPort, "save") as mock_pon_save, \
+ patch.object(NNIPort, "save") as mock_nni_save:
olt_service_mock.return_value = [self.volt_service]
m.get("http://voltha_url:1234/api/v1/devices", status_code=200, json=self.devices)
+ m.get("http://voltha_url:1234/api/v1/devices/test_id/ports", status_code=200, json=self.ports)
m.get("http://voltha_url:1234/api/v1/logical_devices", status_code=200, json=self.logical_devices)
self.sync_step().pull_records()
@@ -131,7 +153,9 @@
# self.assertEqual(existing_olt.of_id, "of_id")
# self.assertEqual(existing_olt.dp_id, "of:0000000ce2314000")
- mock_save.assert_called()
+ mock_olt_save.assert_called()
+ mock_pon_save.assert_called()
+ mock_nni_save.assert_called()
@requests_mock.Mocker()
def test_pull_existing(self, m):
@@ -141,12 +165,15 @@
existing_olt.updated = 1
with patch.object(VOLTService.objects, "all") as olt_service_mock, \
- patch.object(OLTDevice.objects, "filter") as mock_get, \
- patch.object(existing_olt, "save") as mock_save:
+ patch.object(OLTDevice.objects, "filter") as mock_get, \
+ patch.object(PONPort, "save") as mock_pon_save, \
+ patch.object(NNIPort, "save") as mock_nni_save, \
+ patch.object(existing_olt, "save") as mock_olt_save:
olt_service_mock.return_value = [self.volt_service]
mock_get.return_value = [existing_olt]
m.get("http://voltha_url:1234/api/v1/devices", status_code=200, json=self.devices)
+ m.get("http://voltha_url:1234/api/v1/devices/test_id/ports", status_code=200, json=self.ports)
m.get("http://voltha_url:1234/api/v1/logical_devices", status_code=200, json=self.logical_devices)
self.sync_step().pull_records()
@@ -158,26 +185,35 @@
self.assertEqual(existing_olt.of_id, "of_id")
self.assertEqual(existing_olt.dp_id, "of:0000000ce2314000")
- mock_save.assert_called()
+ mock_olt_save.assert_called()
+ mock_pon_save.assert_called()
+ mock_nni_save.assert_called()
@requests_mock.Mocker()
def test_pull_existing_do_not_sync(self, m):
existing_olt = Mock()
existing_olt.enacted = 1
existing_olt.updated = 2
+ existing_olt.device_id = "test_id"
with patch.object(VOLTService.objects, "all") as olt_service_mock, \
- patch.object(OLTDevice.objects, "get") as mock_get, \
- patch.object(existing_olt, "save") as mock_save:
+ patch.object(OLTDevice.objects, "filter") as mock_get, \
+ patch.object(PONPort, "save") as mock_pon_save, \
+ patch.object(NNIPort, "save") as mock_nni_save, \
+ patch.object(existing_olt, "save") as mock_olt_save:
+
olt_service_mock.return_value = [self.volt_service]
- mock_get.return_value = existing_olt
+ mock_get.return_value = [existing_olt]
m.get("http://voltha_url:1234/api/v1/devices", status_code=200, json=self.devices)
+ m.get("http://voltha_url:1234/api/v1/devices/test_id/ports", status_code=200, json=self.ports)
m.get("http://voltha_url:1234/api/v1/logical_devices", status_code=200, json=self.logical_devices)
self.sync_step().pull_records()
- mock_save.assert_not_called()
+ mock_olt_save.assert_not_called()
+ mock_pon_save.assert_called()
+ mock_nni_save.assert_called()
if __name__ == "__main__":
unittest.main()
\ No newline at end of file
diff --git a/xos/synchronizer/pull_steps/test_pull_onus.py b/xos/synchronizer/pull_steps/test_pull_onus.py
index b8ffa5f..a2b948b 100644
--- a/xos/synchronizer/pull_steps/test_pull_onus.py
+++ b/xos/synchronizer/pull_steps/test_pull_onus.py
@@ -85,6 +85,10 @@
self.olt = Mock()
self.olt.id = 1
+ # mock pon port
+ self.pon_port = Mock()
+ self.pon_port.id = 1
+
# mock voltha responses
self.devices = {
"items": [
@@ -99,9 +103,8 @@
"admin_state": "ENABLED",
"oper_status": "ACTIVE",
"connect_status": "REACHABLE",
- "proxy_address": {
- "device_id": "00010fc93996afea"
- }
+ "parent_id": "00010fc93996afea",
+ "parent_port_no": 1
}
]
}
@@ -114,12 +117,14 @@
self.assertFalse(m.called)
@requests_mock.Mocker()
- def _test_pull(self, m):
+ def test_pull(self, m):
with patch.object(VOLTService.objects, "all") as olt_service_mock, \
patch.object(OLTDevice.objects, "get") as mock_olt_device, \
+ patch.object(PONPort.objects, "get") as mock_pon_port, \
patch.object(ONUDevice, "save") as mock_save:
olt_service_mock.return_value = [self.volt_service]
+ mock_pon_port.return_value = self.pon_port
mock_olt_device.return_value = self.olt
m.get("http://voltha_url:1234/api/v1/devices", status_code=200, json=self.devices)
@@ -134,7 +139,7 @@
# self.assertEqual(existing_olt.of_id, "of_id")
# self.assertEqual(existing_olt.dp_id, "of:0000000ce2314000")
- mock_save.assert_called()
+ mock_save.assert_called_with()
@requests_mock.Mocker()
def _test_pull_existing(self, m):