[SEBA-179] Fabric-crossconnect service should react to changes in BNGPortMapping
Change-Id: Ie7174ac31af300dabb50e0d850fff0c474e5366a
diff --git a/xos/synchronizer/steps/sync_bng_port_mapping.py b/xos/synchronizer/steps/sync_bng_port_mapping.py
new file mode 100644
index 0000000..c704e6d
--- /dev/null
+++ b/xos/synchronizer/steps/sync_bng_port_mapping.py
@@ -0,0 +1,125 @@
+# 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.
+
+import os, sys
+import json
+from xossynchronizer.steps.syncstep import SyncStep, DeferredException
+from xossynchronizer.modelaccessor import model_accessor, FabricCrossconnectServiceInstance, ServiceInstance, BNGPortMapping
+
+import requests
+from requests import ConnectionError
+from requests.auth import HTTPBasicAuth
+from requests.models import InvalidURL
+
+from xosconfig import Config
+from multistructlog import create_logger
+
+from helpers import Helpers
+log = create_logger(Config().get('logging'))
+
+
+class SyncBNGPortMapping(SyncStep):
+ provides = [BNGPortMapping]
+ observes = BNGPortMapping
+
+ def remove_crossconnect(self, fcsis):
+ for fcsi in fcsis:
+ onos = Helpers.get_fabric_onos_info(self.model_accessor, fcsi.owner)
+
+ url = onos['url'] + '/onos/segmentrouting/xconnect'
+ data = {"deviceId": fcsi.switch_datapath_id,
+ "vlanId": fcsi.s_tag}
+ log.info("Sending request to ONOS", url=url)
+ r = requests.delete(url, json=data, auth=HTTPBasicAuth(onos['user'], onos['pass']))
+ if r.status_code != 204:
+ raise Exception("Failed to remove fabric crossconnect in ONOS: %s" % r.text)
+ fcsi.save(always_update_timestamp = True)
+
+ def find_crossconnect(self, bng_s_tag):
+ if(bng_s_tag.isnumeric()):
+ xconnect_si = self.model_accessor.FabricCrossconnectServiceInstance.objects.filter(s_tag=int(bng_s_tag))
+ if xconnect_si:
+ log.info("Crossconnects belonging having s-tag equal to s-tags: %s" % xconnect_si)
+ return xconnect_si
+ else:
+ [fcsis_range, fcsis_any] = [[], []]
+ for fcsi in self.model_accessor.FabricCrossconnectServiceInstance.objects.all():
+ if Helpers.range_matches(fcsi.s_tag, bng_s_tag):
+ fcsis_range.append(fcsi)
+ else:
+ fcsis_any.append(fcsi)
+ if fcsis_range:
+ log.info("Crossconnects belonging to bng range s-tags: %s" % fcsis_range)
+ return fcsis_range
+ else:
+ log.info("Crossconnects belonging to bng any s-tags: %s" % fcsis_any)
+ return fcsis_any
+
+ def check_switch_port_change(self, model):
+ fcsis = self.find_crossconnect(model.s_tag)
+ isChanged = False
+ remove_xconnect = []
+ if fcsis:
+ for fcsi in fcsis:
+ onos = Helpers.get_fabric_onos_info(self.model_accessor, fcsi.owner)
+ log.info("ONOS belonging to fabric crossconnect instance: %s" % onos)
+
+ url = onos['url'] + '/onos/segmentrouting/xconnect'
+ log.info("Sending request to ONOS", url=url)
+ r = requests.get(url, auth=HTTPBasicAuth(onos['user'], onos['pass']))
+ if r.status_code != 200:
+ log.error(r.text)
+ raise Exception("Failed to get onos devices")
+ else:
+ try:
+ log.info("Get devices response", json=r.json())
+ except Exception:
+ log.info("Get devices exception response", text=r.text)
+ xconnects = r.json()["xconnects"]
+ for xconn in xconnects:
+ val = xconn['deviceId']
+ if(str(fcsi.switch_datapath_id) == str(val)):
+ if model.switch_port not in xconn['endpoints']:
+ remove_xconnect.append(fcsi)
+ self.remove_crossconnect(remove_xconnect)
+ isChanged = True
+ else:
+ log.info("No Fabric-xconnect-si found & saving bng instance.")
+ return isChanged
+
+ def sync_record(self, model):
+ log.info("Sync started for BNGPortMapping instance: %s" % model.id)
+ log.info('Syncing BNGPortMapping instance', object=str(model), **model.tologdict())
+ if model.old_s_tag:
+ if (model.old_s_tag != model.s_tag):
+ fcsis = self.find_crossconnect(model.old_s_tag)
+ if fcsis:
+ log.info("Xconnect-instance linked to bng : %s" % fcsis)
+ self.remove_crossconnect(fcsis)
+ else:
+ log.info("No crossconnect is found for current bng instance")
+ else:
+ self.check_switch_port_change(model)
+ else:
+ if self.check_switch_port_change(model):
+ log.info("Changed bng switch port is repushed to ONOS")
+ log.info("Completing Synchronization for BNGPortMapping instance: %s" % model.id)
+
+ def delete_record(self,model):
+ log.info('Deleting BNGPortMapping instance', object=str(model), **model.tologdict())
+ fcsis = self.find_crossconnect(model.s_tag)
+ if fcsis:
+ log.info("Xconnect-instance linked to bng : %s" % fcsis)
+ self.remove_crossconnect(fcsis)
+ log.info("Completing deletion of bng instance")