CORD-1053 modify onboarding synchronizer to support refactored synchronizers

Change-Id: I7654ad04cb4a3b0334add16664e853f210bc16c5
diff --git a/xos/core/admin.py b/xos/core/admin.py
index 48719f9..bfe45ee 100644
--- a/xos/core/admin.py
+++ b/xos/core/admin.py
@@ -1105,7 +1105,7 @@
 class ServiceControllerAdmin(XOSBaseAdmin):
     list_display = ("backend_status_icon", "name",)
     list_display_links = ('backend_status_icon', 'name',)
-    fieldList = ["backend_status_text", "name", "xos", "version", "provides", "requires", "base_url", "synchronizer_run", "synchronizer_config", "no_start"]
+    fieldList = ["backend_status_text", "name", "xos", "version", "provides", "requires", "base_url", "synchronizer_run", "synchronizer_config", "image", "no_start", "no_build", "no_deploy"]
     fieldsets = [
         (None, {'fields': fieldList, 'classes': ['suit-tab suit-tab-general']})]
     inlines = [LoadableModuleResourceInline]
diff --git a/xos/core/models/service.py b/xos/core/models/service.py
index 58891f3..365b1b2 100644
--- a/xos/core/models/service.py
+++ b/xos/core/models/service.py
@@ -257,7 +257,11 @@
     synchronizer_run = StrippedCharField(max_length=1024, help_text="synchronizer run command", null=True, blank=True)
     synchronizer_config = StrippedCharField(max_length=1024, help_text="synchronizer config file", null=True, blank=True)
 
+    image = StrippedCharField(max_length=200, help_text="docker image name", null=True, blank=True)
+
     no_start = models.BooleanField(help_text="Do not start the Synchronizer", default=False)
+    no_build = models.BooleanField(help_text="Do not build the Synchronizer container", default=False)
+    no_deploy = models.BooleanField(help_text="Do not add synchronizer container to onboarding-docker-compose", default=False)
 
 class ServiceControllerResource(LoadableModuleResource):
     class Meta:
diff --git a/xos/synchronizers/onboarding/steps/sync_servicecontroller.py b/xos/synchronizers/onboarding/steps/sync_servicecontroller.py
index b120dce..31e3b30 100644
--- a/xos/synchronizers/onboarding/steps/sync_servicecontroller.py
+++ b/xos/synchronizers/onboarding/steps/sync_servicecontroller.py
@@ -36,6 +36,10 @@
         if unready:
             raise Exception("Controller %s has unready resources: %s" % (str(sc), ",".join([str(x) for x in unready])))
 
+        if sc.no_build:
+            # nothing to do for a no-build ServiceController
+            return
+
         dockerfile = self.create_synchronizer_dockerfile(sc)
         if dockerfile:
             dockerfiles=[dockerfile]
diff --git a/xos/synchronizers/onboarding/xosbuilder.py b/xos/synchronizers/onboarding/xosbuilder.py
index 2a34f27..73b06a2 100644
--- a/xos/synchronizers/onboarding/xosbuilder.py
+++ b/xos/synchronizers/onboarding/xosbuilder.py
@@ -412,7 +412,44 @@
                     logger.warning("Controller %s has unready resources" % str(c))
                     continue
 
-                if c.loadable_module_resources.filter(kind="synchronizer").exists():
+                if c.no_deploy:
+                    logger.info("Controller %s has no_deploy set" % str(c))
+
+                if c.no_build and c.image:
+                    # refactored synchronizer containers
+
+                    nb_volume_list=[{"host_path": "/opt/cord_profile/node_key",
+                                  "container_path": "/opt/cord_profile/node_key",
+                                  "read_only": True},
+                                 {"host_path": "/opt/cord/build/platform-install/credentials/xosadmin@opencord.org",
+                                  "container_path": "/opt/xos/services/%s/credentials/xosadmin@opencord.org" % c.name,
+                                  "read_only": True}]
+
+                    # keys inside onboarding sync are relative to /opt/xos/key_import
+                    # keys outside onboarding sync are relative to /opt/cord_profile
+                    if os.path.exists("/opt/xos/key_import/%s_rsa" % c.name):
+                        nb_volume_list.append({"host_path": "/opt/cord_profile/key_import/%s_rsa" % c.name,    # Note: not all services have keys
+                                  "container_path": "/opt/xos/services/%s/keys/%s_rsa" % (c.name, c.name),
+                                  "read_only": True})
+
+                    if c.name == "vtr":
+                        # VTR is special -- it has the vSG's private key
+                        nb_volume_list.append({"host_path": "/opt/cord_profile/key_import/vsg_rsa",
+                                  "container_path": "/opt/cord_profile/services/%s/keys/vsg_rsa" % c.name,
+                                  "read_only": True})
+
+                    nb_external_links = []
+                    if xos.redis_container_name:
+                        nb_external_links.append("%s:%s" % (xos.redis_container_name, "redis"))
+
+                    containers["%s-synchronizer" % c.name] = {
+                        "image": c.image,
+                        "volumes": nb_volume_list,
+                        "external_links": nb_external_links,
+                        "networks": networks}
+
+                elif c.loadable_module_resources.filter(kind="synchronizer").exists():
+                    # old-style synchronizer containers
                     if c.synchronizer_run and c.synchronizer_config:
                         command = 'bash -c "sleep 120; cd /opt/xos/synchronizers/%s; python ./%s -C %s"' % (c.name, c.synchronizer_run, c.synchronizer_config)
                     else:
diff --git a/xos/tosca/custom_types/xos.m4 b/xos/tosca/custom_types/xos.m4
index 409e036..dc09b1d 100644
--- a/xos/tosca/custom_types/xos.m4
+++ b/xos/tosca/custom_types/xos.m4
@@ -165,6 +165,18 @@
                 type: string
                 required: false
                 description: third-party javascript files
+            image:
+                type: string
+                required: false
+                description: Image name for refactored synchronizer containers
+            no_build:
+                type: boolean
+                required: false
+                description: If true then refactored synchronizer container image is assumed
+            no_deploy:
+                type: boolean
+                required: false
+                description: If true then synchronizer container will not be added to docker-compose
 
     tosca.nodes.ServiceControllerResource:
         derived_from: tosca.nodes.Root
diff --git a/xos/tosca/custom_types/xos.yaml b/xos/tosca/custom_types/xos.yaml
index 1af0009..a089d9d 100644
--- a/xos/tosca/custom_types/xos.yaml
+++ b/xos/tosca/custom_types/xos.yaml
@@ -288,6 +288,18 @@
                 type: string
                 required: false
                 description: third-party javascript files
+            image:
+                type: string
+                required: false
+                description: Image name for refactored synchronizer containers
+            no_build:
+                type: boolean
+                required: false
+                description: If true then refactored synchronizer container image is assumed
+            no_deploy:
+                type: boolean
+                required: false
+                description: If true then synchronizer container will not be added to docker-compose
 
     tosca.nodes.ServiceControllerResource:
         derived_from: tosca.nodes.Root
diff --git a/xos/tosca/resources/servicecontroller.py b/xos/tosca/resources/servicecontroller.py
index e5fa6e2..d2bd10d 100644
--- a/xos/tosca/resources/servicecontroller.py
+++ b/xos/tosca/resources/servicecontroller.py
@@ -5,7 +5,7 @@
 class XOSServiceController(XOSLoadableModule):
     provides = "tosca.nodes.ServiceController"
     xos_model = ServiceController
-    copyin_props = ["version", "provides", "requires", "base_url", "synchronizer_run", "synchronizer_config"]
+    copyin_props = ["version", "provides", "requires", "base_url", "synchronizer_run", "synchronizer_config", "no_build", "no_deploy", "image"]
 
     def postprocess(self, obj):
         # allow these common resource to be specified directly by the ServiceController tosca object