SEBA-54 implement create policy

Change-Id: Ie8457055b03cc38eff1d85b6fa16bcb95a7416c9
diff --git a/xos/synchronizer/model_policies/model_policy_hippieossserviceinstance.py b/xos/synchronizer/model_policies/model_policy_hippieossserviceinstance.py
index 5a380dd..5dc7221 100644
--- a/xos/synchronizer/model_policies/model_policy_hippieossserviceinstance.py
+++ b/xos/synchronizer/model_policies/model_policy_hippieossserviceinstance.py
@@ -20,8 +20,18 @@
 class OSSServiceInstancePolicy(Policy):
     model_name = "HippieOSSServiceInstance"
 
+    def handle_create(self, si):
+        self.logger.debug("MODEL_POLICY: handle_create for HippieOSSServiceInstance %s " % si.id)
+        self.handle_update(si)
+
     def handle_update(self, si):
-        self.logger.debug("MODEL_POLICY: handle_update for HippieOSSServiceInstance %s " % si.id)
+        self.logger.debug("MODEL_POLICY: handle_update for HippieOSSServiceInstance %s, valid=%s " % (si.id, si.valid))
+
+        # Check to make sure the object has been synced. This is to cover a race condition where the model_policy
+        # runs, is interrupted by the sync step, the sync step completes, and then the model policy ends up saving
+        # a policed_timestamp that is later the updated timestamp set by the sync_step.
+        if (si.backend_code!=1):
+            raise Exception("MODEL_POLICY: HippieOSSServiceInstance %s has not been synced yet" % si.id)
 
         if not hasattr(si, 'valid') or si.valid is "awaiting":
             self.logger.debug("MODEL_POLICY: skipping handle_update for HippieOSSServiceInstance %s as not validated yet" % si.id)
diff --git a/xos/synchronizer/model_policies/test_model_policy_hippieossserviceinstance.py b/xos/synchronizer/model_policies/test_model_policy_hippieossserviceinstance.py
index 65a740f..6140712 100644
--- a/xos/synchronizer/model_policies/test_model_policy_hippieossserviceinstance.py
+++ b/xos/synchronizer/model_policies/test_model_policy_hippieossserviceinstance.py
@@ -72,8 +72,21 @@
         sys.path = self.sys_path_save
         self.si = None
 
+    def test_not_synced(self):
+        self.si.valid = "awaiting"
+        self.si.backend_code = 0
+
+        with patch.object(RCORDSubscriber, "save") as subscriber_save, \
+            patch.object(ONUDevice, "save") as onu_save:
+
+            with self.assertRaises(Exception) as e:
+               self.policy.handle_update(self.si)
+
+            self.assertIn("has not been synced yet", e.exception.message)
+
     def test_skip_update(self):
         self.si.valid = "awaiting"
+        self.si.backend_code = 1
 
         with patch.object(RCORDSubscriber, "save") as subscriber_save, \
             patch.object(ONUDevice, "save") as onu_save:
@@ -85,6 +98,7 @@
     def test_disable_onu(self):
         self.si.valid = "invalid"
         self.si.serial_number = "BRCM1234"
+        self.si.backend_code = 1
 
         onu = ONUDevice(
             serial_number=self.si.serial_number
@@ -105,6 +119,7 @@
         self.si.valid = "valid"
         self.si.serial_number = "BRCM1234"
         self.si.c_tag = None
+        self.si.backend_code = 1
 
         onu = ONUDevice(
             serial_number=self.si.serial_number,
@@ -131,6 +146,7 @@
     def test_create_subscriber(self):
         self.si.valid = "valid"
         self.si.serial_number = "BRCM1234"
+        self.si.backend_code = 1
 
         onu = ONUDevice(
             serial_number=self.si.serial_number,
@@ -155,6 +171,7 @@
         self.si.valid = "valid"
         self.si.serial_number = "BRCM1234"
         self.si.c_tag = 111
+        self.si.backend_code = 1
 
         onu = ONUDevice(
             serial_number=self.si.serial_number,
@@ -180,6 +197,7 @@
         self.si.valid = "valid"
         self.si.serial_number = "BRCM1234"
         self.si.c_tag = 111
+        self.si.backend_code = 1
 
         onu = ONUDevice(
             serial_number=self.si.serial_number,
diff --git a/xos/synchronizer/steps/sync_hippie_oss_service_instance.py b/xos/synchronizer/steps/sync_hippie_oss_service_instance.py
index bc64f3b..9ca7678 100644
--- a/xos/synchronizer/steps/sync_hippie_oss_service_instance.py
+++ b/xos/synchronizer/steps/sync_hippie_oss_service_instance.py
@@ -53,10 +53,11 @@
 
             o.valid = "valid"
 
-        # we need to update the timestamp to run model_policies again, but we don't want to loop over the sync_steps
-        # maybe we need an "after_sync" model policy method?
+        # Set no_sync=True to prevent the syncstep from running again, and set alway_update_timestamp=True to cause
+        # the model_policy to run again.
+        # TODO(smbaker): Revisit this after fixing this issue in the core.
         o.no_sync = True
-        o.save(always_update_timestamp=True)
+        o.save(update_fields=["valid", "no_sync", "updated"], always_update_timestamp=True)
 
     def delete_record(self, o):
         pass