[CORD-3168] Removing subscriber termination when the subscriber status change
Change-Id: I3b4494539d12f577e7d093cce01317e759e6a40c
diff --git a/.gitignore b/.gitignore
index 1163cb2..9a8876a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,4 @@
.idea
-*.pyc
\ No newline at end of file
+*.pyc
+.coverage
+xos/htmlcov
\ No newline at end of file
diff --git a/xos/synchronizer/steps/sync_vsg_hw_service_instance.py b/xos/synchronizer/steps/sync_vsg_hw_service_instance.py
index 05b16cb..6f79ca2 100644
--- a/xos/synchronizer/steps/sync_vsg_hw_service_instance.py
+++ b/xos/synchronizer/steps/sync_vsg_hw_service_instance.py
@@ -17,6 +17,7 @@
from xosconfig import Config
from multistructlog import create_logger
+import urllib
import requests
from requests.auth import HTTPBasicAuth
@@ -83,7 +84,15 @@
if not port:
raise ValueError("switch_port")
except ValueError as e:
- raise DeferredException("Skipping synchronization for VSG-HW Service Instance with id %s as %s is not available" % (o.id, e.message))
+ raise Exception("Skipping synchronization for VSG-HW Service Instance with id %s as westbound value %s is not available" % (o.id, e.message))
+
+ subscriber_status = si.get_westbound_service_instance_properties("status")
+
+ if subscriber_status != "enabled":
+ if o.enacted:
+ return self.delete_record(o)
+ else:
+ raise DeferredException("Deferring synchronization for VSG-HW Service Instance with id %s as subscriber is not enabled" % o.id)
data = {
'hosts': {
@@ -115,4 +124,23 @@
def delete_record(self, o):
self.log.info("Deleting VSG-HW Service Instance", service_instance=o)
+ if o.enacted:
+ onos = SyncVSGHWServiceInstance.get_fabric_onos_info(o)
+
+ si = ServiceInstance.objects.get(id=o.id)
+
+ mac_address = si.get_westbound_service_instance_properties("mac_address")
+ s_tag = si.get_westbound_service_instance_properties("s_tag")
+
+ key = "%s/%s" % (mac_address, str(s_tag))
+ key = urllib.quote(key, safe='')
+
+ url = onos['url'] + '/onos/v1/network/configuration/hosts/%s' % key
+
+ r = requests.delete(url, auth=HTTPBasicAuth(onos['user'], onos['pass']))
+
+ if r.status_code != 200:
+ raise Exception("Failed to remove subscriber termination in ONOS: %s" % r.text)
+
+ self.log.info("ONOS response", res=r.text)
pass
\ No newline at end of file
diff --git a/xos/synchronizer/steps/test_sync_vsg_hw_service_instance.py b/xos/synchronizer/steps/test_sync_vsg_hw_service_instance.py
index 680fc86..b1bddf4 100644
--- a/xos/synchronizer/steps/test_sync_vsg_hw_service_instance.py
+++ b/xos/synchronizer/steps/test_sync_vsg_hw_service_instance.py
@@ -45,6 +45,8 @@
# END generate model from xproto
def mock_get_westbound_service_instance_properties(prop):
+ if prop == "status":
+ return "enabled"
return prop
def match_json(desired, req):
@@ -120,9 +122,9 @@
sys.path = self.sys_path_save
@requests_mock.Mocker()
- def test_hold_sync(self, m):
+ def test_fail_sync(self, m):
"""
- If we don't have all the data we need, wait to synchronize
+ If we don't have all the data we need, do not synchronize
"""
for i in ["mac_address", "ip_address", "s_tag", "c_tag", "switch_datapath_id", "switch_port"]:
@@ -138,13 +140,34 @@
with patch.object(ServiceInstance.objects, "get") as service_instance_mock:
service_instance_mock.return_value = self.si
- with self.assertRaises(DeferredException) as e:
+ with self.assertRaises(Exception) as e:
self.sync_step().sync_record(self.o)
- self.assertEqual(e.exception.message, "Skipping synchronization for VSG-HW Service Instance with id 1 as %s is not available" % i)
+ self.assertEqual(e.exception.message, "Skipping synchronization for VSG-HW Service Instance with id 1 as westbound value %s is not available" % i)
self.assertFalse(m.called)
@requests_mock.Mocker()
+ def test_hold_sync(self, m):
+ with patch.object(ServiceInstance.objects, "get") as service_instance_mock:
+ service_instance_mock.return_value = self.si
+
+ def wb_si_prop(prop):
+ # fake prop not present
+ if prop == "status":
+ return "suspended"
+ return prop
+
+ self.si.get_westbound_service_instance_properties = wb_si_prop
+
+ self.o.enacted = None
+
+ with self.assertRaises(DeferredException) as e:
+ self.sync_step().sync_record(self.o)
+
+ self.assertEqual(e.exception.message, "Deferring synchronization for VSG-HW Service Instance with id 1 as subscriber is not enabled")
+ self.assertFalse(m.called)
+
+ @requests_mock.Mocker()
def test_sync_success(self, m):
expected_conf = {
'hosts': {
@@ -166,6 +189,8 @@
def wb_si_prop(prop):
if prop == "outer_tpid":
return None
+ if prop == "status":
+ return "enabled"
return prop
self.si.get_westbound_service_instance_properties = wb_si_prop
@@ -201,4 +226,42 @@
self.sync_step().sync_record(self.o)
+ self.assertTrue(m.called)
+
+ @requests_mock.Mocker()
+ def test_delete(self, m):
+ self.o.enacted = True
+ m.delete("http://onos-fabric:8181/onos/v1/network/configuration/hosts/mac_address%2Fs_tag",
+ status_code=200)
+
+ with patch.object(ServiceInstance.objects, "get") as service_instance_mock:
+ service_instance_mock.return_value = self.si
+
+ self.sync_step().delete_record(self.o)
+
+ self.assertTrue(m.called)
+
+ @requests_mock.Mocker()
+ def test_disable(self, m):
+
+ # if a subscriber was enabled and now is suspended, remove subscriber termination
+
+ m.delete("http://onos-fabric:8181/onos/v1/network/configuration/hosts/mac_address%2Fs_tag",
+ status_code=200)
+
+ with patch.object(ServiceInstance.objects, "get") as service_instance_mock:
+ service_instance_mock.return_value = self.si
+
+ def wb_si_prop(prop):
+ # fake prop not present
+ if prop == "status":
+ return "suspended"
+ return prop
+
+ self.si.get_westbound_service_instance_properties = wb_si_prop
+
+ self.o.enacted = True
+
+ self.sync_step().sync_record(self.o)
+
self.assertTrue(m.called)
\ No newline at end of file
diff --git a/xos/unittest.cfg b/xos/unittest.cfg
index 71be7ca..9679a47 100644
--- a/xos/unittest.cfg
+++ b/xos/unittest.cfg
@@ -3,3 +3,9 @@
code-directories=synchronizer
model_policies
steps
+
+[coverage]
+always-on = True
+coverage = synchronizer
+coverage-report = term
+coverage-report = html
\ No newline at end of file