SEBA-108 base methods for acquire_service_instance and validate_links

Change-Id: I162fb34dd8c18a3409d4bbdde6cc4bf275e16414
diff --git a/VERSION b/VERSION
index ac2cdeb..7d2ed7c 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.1.3
+2.1.4
diff --git a/containers/chameleon/Dockerfile.chameleon b/containers/chameleon/Dockerfile.chameleon
index 116fb2d..f7ba11b 100644
--- a/containers/chameleon/Dockerfile.chameleon
+++ b/containers/chameleon/Dockerfile.chameleon
@@ -13,7 +13,7 @@
 # limitations under the License.
 
 # xosproject/chameleon
-FROM xosproject/xos-base:2.1.3
+FROM xosproject/xos-base:2.1.4
 
 # xos-base already has protoc and dependencies installed
 
diff --git a/containers/xos/Dockerfile.client b/containers/xos/Dockerfile.client
index 9210f39..9aa9f1b 100644
--- a/containers/xos/Dockerfile.client
+++ b/containers/xos/Dockerfile.client
@@ -13,7 +13,7 @@
 # limitations under the License.
 
 # xosproject/xos-client
-FROM xosproject/xos-libraries:2.1.3
+FROM xosproject/xos-libraries:2.1.4
 
 # Install XOS client
 COPY xos/xos_client /tmp/xos_client
diff --git a/containers/xos/Dockerfile.libraries b/containers/xos/Dockerfile.libraries
index 8ead8ef..dfe651b 100644
--- a/containers/xos/Dockerfile.libraries
+++ b/containers/xos/Dockerfile.libraries
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-FROM xosproject/xos-base:2.1.3
+FROM xosproject/xos-base:2.1.4
 
 # Add libraries
 COPY lib /opt/xos/lib
diff --git a/containers/xos/Dockerfile.synchronizer-base b/containers/xos/Dockerfile.synchronizer-base
index 3f63f83..fad65c4 100644
--- a/containers/xos/Dockerfile.synchronizer-base
+++ b/containers/xos/Dockerfile.synchronizer-base
@@ -13,7 +13,7 @@
 # limitations under the License.
 
 # xosproject/xos-synchronizer-base
-FROM xosproject/xos-client:2.1.3
+FROM xosproject/xos-client:2.1.4
 
 COPY xos/synchronizers/new_base /opt/xos/synchronizers/new_base
 COPY xos/xos/logger.py /opt/xos/xos/logger.py
diff --git a/containers/xos/Dockerfile.xos-core b/containers/xos/Dockerfile.xos-core
index 753f14f..2d6909d 100644
--- a/containers/xos/Dockerfile.xos-core
+++ b/containers/xos/Dockerfile.xos-core
@@ -13,7 +13,7 @@
 # limitations under the License.
 
 # xosproject/xos-core
-FROM xosproject/xos-libraries:2.1.3
+FROM xosproject/xos-libraries:2.1.4
 
 # Install XOS
 ADD xos /opt/xos
diff --git a/xos/xos_client/xosapi/convenience/service.py b/xos/xos_client/xosapi/convenience/service.py
index f8d108f..7e6ed09 100644
--- a/xos/xos_client/xosapi/convenience/service.py
+++ b/xos/xos_client/xosapi/convenience/service.py
@@ -64,5 +64,39 @@
             svcs.append(dep.subscriber_service)
         return svcs
 
+    def acquire_service_instance(self, subscriber_service_instance):
+        """ Given a subscriber_service_instance:
+              1) If there is an eligible provider_service_instance that can be used, then link to it
+              2) Otherwise, create a new provider_service_instance and link to it.
+
+            This is the base class, knows nothing of service specifics, so it assumes that #1 always yields no
+            eligible provider_service_instances. To get custom behavior, override this method in your own
+            convenience wrapper.
+        """
+        si_classname = self.get_service_instance_class_name()
+
+        ServiceInstanceLink = self.stub.ServiceInstanceLink
+
+        eastbound_si_class = getattr(self.stub, si_classname)
+        eastbound_si = eastbound_si_class(owner_id = self.id)
+        eastbound_si.save()
+
+        link = ServiceInstanceLink(provider_service_instance=eastbound_si,
+                                   subscriber_service_instance=subscriber_service_instance)
+        link.save()
+
+    def validate_links(self, subscriber_service_instance):
+        """ Validate existing links between the provider and subscriber service instances. If a valid link exists,
+            then return it. Return [] otherwise.
+
+            This is the base class, knows nothing of service specifics, so it assumes that all existing links are
+            valid. To get custom behavior, override this method in your own convenience wrapper.
+        """
+        matched = []
+        for link in subscriber_service_instance.subscribed_links.all():
+            if link.provider_service_instance.owner.id == self.id:
+                matched.append(link.provider_service_instance.leaf_model)
+        return matched
+
 
 register_convenience_wrapper("Service", ORMWrapperService)