SEBA-353 Pull step should be resilient to missing PonPorts;
Delete OLTDevice if Voltha unreachable

Change-Id: I806eaa9f3bdd281ef3184ec5d6e76177199d5cad
diff --git a/xos/synchronizer/steps/sync_olt_device.py b/xos/synchronizer/steps/sync_olt_device.py
index 4646dbd..40f884e 100644
--- a/xos/synchronizer/steps/sync_olt_device.py
+++ b/xos/synchronizer/steps/sync_olt_device.py
@@ -185,22 +185,25 @@
             log.warning("OLTDevice %s has no device_id, it was never saved in VOLTHA" % model.name)
             return
         else:
-            # Disable the OLT device
-            request = requests.post("%s:%d/api/v1/devices/%s/disable" % (voltha['url'], voltha['port'], model.device_id))
+            try:
+                # Disable the OLT device
+                request = requests.post("%s:%d/api/v1/devices/%s/disable" % (voltha['url'], voltha['port'], model.device_id))
 
-            if request.status_code != 200:
-                log.error("Failed to disable OLT device in VOLTHA: %s - %s" % (model.name, model.device_id), rest_response=request.text, rest_status_code=request.status_code)
-                raise Exception("Failed to disable OLT device in VOLTHA")
+                if request.status_code != 200:
+                    log.error("Failed to disable OLT device in VOLTHA: %s - %s" % (model.name, model.device_id), rest_response=request.text, rest_status_code=request.status_code)
+                    raise Exception("Failed to disable OLT device in VOLTHA")
 
-            # NOTE [teo] wait some time after the disable to let VOLTHA doing its things
-            i = 0
-            for i in list(reversed(range(10))):
-                sleep(1)
-                log.info("Deleting the OLT in %s seconds" % i)
+                # NOTE [teo] wait some time after the disable to let VOLTHA doing its things
+                i = 0
+                for i in list(reversed(range(10))):
+                    sleep(1)
+                    log.info("Deleting the OLT in %s seconds" % i)
 
-            # Delete the OLT device
-            request = requests.delete("%s:%d/api/v1/devices/%s/delete" % (voltha['url'], voltha['port'], model.device_id))
+                # Delete the OLT device
+                request = requests.delete("%s:%d/api/v1/devices/%s/delete" % (voltha['url'], voltha['port'], model.device_id))
 
-            if request.status_code != 200:
-                log.error("Failed to delete OLT device from VOLTHA: %s - %s" % (model.name, model.device_id), rest_response=request.text, rest_status_code=request.status_code)
-                raise Exception("Failed to delete OLT device from VOLTHA")
+                if request.status_code != 200:
+                    log.error("Failed to delete OLT device from VOLTHA: %s - %s" % (model.name, model.device_id), rest_response=request.text, rest_status_code=request.status_code)
+                    raise Exception("Failed to delete OLT device from VOLTHA")
+            except requests.ConnectionError:
+                log.warning("ConnectionError when contacting Voltha in OLT delete step", name=model.name, device_id=model.device_id)
diff --git a/xos/synchronizer/steps/test_sync_olt_device.py b/xos/synchronizer/steps/test_sync_olt_device.py
index 18ed99b..38da1a1 100644
--- a/xos/synchronizer/steps/test_sync_olt_device.py
+++ b/xos/synchronizer/steps/test_sync_olt_device.py
@@ -12,6 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from requests import ConnectionError
 import unittest
 import functools
 from mock import patch, call, Mock, PropertyMock
@@ -339,6 +340,18 @@
 
         self.assertEqual(m.call_count, 2)
 
+    @patch('requests.post')
+    def test_delete_record_connectionerror(self, m):
+        self.o.of_id = "0001000ce2314000"
+        self.o.device_id = "123"
+
+        m.side_effect = ConnectionError()
+
+        self.sync_step().delete_record(self.o)
+
+        # No exception thrown, as ConnectionError will be caught
+
+
     @requests_mock.Mocker()
     def test_delete_unsynced_record(self, m):