[SEBA-694]Add a rest endpoint to the Sadis application in order to flush the cache for a single subscriber

Change-Id: I2c540d743479c616b7000954c4aa36fa8058f423
diff --git a/docs/README.md b/docs/README.md
index 8ada62f..cdc1ef5 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -95,14 +95,15 @@
 
 If the R-CORD Service is configured with `access=voltha`, the following requirements apply:
 
-- There is only one `provider_service` linked to the R-CORD Servioce.
-- The `provider_service` exposes an API called `has_access_device(onu_serial_number)`
+- There are two `provider_service` linked to the R-CORD Servioce.
+- First one is `VOLT_SERVICE` which exposes an API called `has_access_device(onu_serial_number)`
   that returns a boolean. This is used to validate that the ONU the subscriber
   is pointing to really exists.
-- The `provider_service` exposes API called `get_olt_technology_from_unu_sn(onu_serial_number)` and `get_tech_profile(technology, tech_profile_id)`
+- The `VOLT_SERVICE` also exposes API called `get_olt_technology_from_unu_sn(onu_serial_number)` and `get_tech_profile(technology, tech_profile_id)`
   that returns a boolean. This is used to validate that the Technology Profile the subscriber
   is pointing to really exists. See [Technology Profile Management](https://github.com/opencord/voltha/tree/master/common/tech_profile) for more informations.
-
+- Second service is `ONOS_SERVICE` which adds a rest endpoint to the Sadis application in order to flush the cache for a single subscriber.This provides an endpoint
+  to flush the cache for a single subscriber as well as flush the entire cache.
 ## Synchronizer workflow
 
 The R-CORD Service synchronizer implements no sync steps as it does not directly interact with any external components. It does implement one model policy.
diff --git a/xos/synchronizer/models/models.py b/xos/synchronizer/models/models.py
old mode 100755
new mode 100644
index fd25d01..94f96fa
--- a/xos/synchronizer/models/models.py
+++ b/xos/synchronizer/models/models.py
@@ -246,10 +246,12 @@
 
             # if the access network is managed by voltha, validate that onu_device actually exist
             # we assume RCORDService is connected only to the vOLTService
-            volt_service = self.owner.provider_services[0].leaf_model
-
-            if not volt_service.has_access_device(self.onu_device):
-                raise XOSValidationError("The onu_device you specified (%s) does not exists" % self.onu_device)
+            for ps in self.owner.provider_services:
+                provider_service = ps.leaf_model
+                if provider_service.name.lower() == "volt":
+                    volt_service = provider_service
+                    if not volt_service.has_access_device(self.onu_device):
+                       raise XOSValidationError("The onu_device you specified (%s) does not exists" % self.onu_device)
 
             # if the access network is managed by voltha, validate that the tech_profile_id actually exists
             if not self.validate_tech_profile_id():
diff --git a/xos/synchronizer/steps/sync_rcordsubscriber.py b/xos/synchronizer/steps/sync_rcordsubscriber.py
index a25ca43..f980421 100644
--- a/xos/synchronizer/steps/sync_rcordsubscriber.py
+++ b/xos/synchronizer/steps/sync_rcordsubscriber.py
@@ -13,12 +13,14 @@
 # limitations under the License.
 
 import os, sys
+import requests
 sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
 from multistructlog import create_logger
 from xossynchronizer.modelaccessor import RCORDSubscriber, model_accessor
 from xossynchronizer.steps.syncstep import SyncStep
 from xosconfig import Config
+from requests.auth import HTTPBasicAuth
 
 log = create_logger(Config().get("logging"))
 
@@ -27,10 +29,46 @@
 
     observes = RCORDSubscriber
 
-    #TODO: (Blocked by SEBA-694) : Add API calls that will be implemented by SEBA-694 to flush the Sadis cache when a subscriber changes or is removed.
-
     def sync_record(self, model):
         log.info('Synching RCORDSubscriber', object=str(model), **model.tologdict())
+        self.delete_sadis_subscriber( self , model)
 
     def delete_record(self, model):
         log.info('Deleting RCORDSubscriber', object=str(model), **model.tologdict())
+        self.delete_sadis_subscriber( self , model)
+
+    @staticmethod
+    def delete_sadis_subscriber( self,  model):
+        log.info('Deleting sadis subscriber cache', object=str(model), **model.tologdict())
+        onos = self.get_rcord_onos_info( self , model )
+        url = onos['url'] + '/onos/sadis/cache/subscriber/' + str(model.onu_device)
+        r = requests.delete(url, auth=HTTPBasicAuth(onos['user'], onos['pass']))
+        if r.status_code != 204:
+            self.log.info("Failed to remove sadis subscriber in ONOS")
+        log.info("ONOS response", res=r.text)
+
+    @staticmethod
+    def get_rcord_onos_info( self, model ):
+        # get rcord service
+        rcord = model.owner
+
+        # get the rcord onos service
+        rcord_onos = [s.leaf_model for s in rcord.provider_services if "onos" in s.name.lower()]
+
+        if len(rcord_onos) == 0:
+            raise Exception('Cannot find ONOS service in provider_services of rcord')
+
+        rcord_onos = rcord_onos[0]
+        return {
+            'url': SyncRCORDSubscriber.format_url( "%s:%s" % (rcord_onos.rest_hostname, rcord_onos.rest_port)),
+            'user': rcord_onos.rest_username,
+            'pass': rcord_onos.rest_password
+        }
+
+    @staticmethod
+    def format_url(url):
+        if 'http' in url:
+            return url
+        else:
+            return 'http://%s' % url
+