Add sync step class for docker image creation, docker network creation/deletion, docker container creation/deletion
diff --git a/xos/synchronizer/steps/sync_controller_images.py b/xos/synchronizer/steps/sync_controller_images.py
new file mode 100644
index 0000000..a54dd15
--- /dev/null
+++ b/xos/synchronizer/steps/sync_controller_images.py
@@ -0,0 +1,99 @@
+
+# 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
+import base64
+from synchronizers.swarm.swarmsyncstep import SwarmSyncStep
+from synchronizers.new_base.syncstep import *
+from synchronizers.new_base.ansible_helper import *
+from synchronizers.new_base.modelaccessor import * 
+from xos.logger import observer_logger as logger 
+import synchronizers.swarm.swarmlog as slog 
+
+
+class SyncControllerImages(SwarmSyncStep):
+    provides = [ControllerImages]
+    observes = ControllerImages
+    requested_interval = 0
+    playbook='sync_controller_images.yaml' 
+
+    def fetch_pending(self, deleted):
+        return super(SyncControllerImages, self).fetch_pending(deleted) 
+
+    def map_sync_inputs(self, controller_image):
+        swarm_manager_url = controller_image.controller.auth_url
+        (swarm_manager_address, docker_registry_port) = swarm_manager_url.split(':')
+        slog.debug("swarm_manager_address: %s    docker_registry_port: %s" 
+                    % (swarm_manager_address, docker_registry_port)) 
+
+        input_fields = {
+                        'swarm_manager_address' : swarm_manager_address,
+                        'docker_registry_port'  : docker_registry_port,
+                        'image_file_path'       : controller_image.image.path,
+                        'image_dir'             : os.path.dirname(controller_image.image.path),
+                        'image_name'            : controller_image.image.name,
+                        'image_tag'             : controller_image.image.tag, 
+                        'delete'                : False,
+                        'ansible_tag'           : '%s@%s' % (
+                                                    controller_image.image.name,
+                                                    controller_image.controller.name)  # name of ansible playbook
+                        } 
+        slog.debug("input_fields: %s" % str(input_fields))
+
+        return input_fields 
+
+    def map_sync_outputs(self, controller_image, res):
+        slog.debug("Ansible playbook result: %s" % str(res))
+        slog.debug("Ansible playbook result[4]['image']['Id']: %s" % str(res[4]['image']['Id']))
+        controller_image.glance_image_id = str(res[4]['image']['Id'])
+        if len(controller_image.glance_image_id) > 2:
+            controller_image.backend_status = '1 - OK'
+        else:
+            controller_image.backend_status = '2 - Ansible playbook failure'
+        controller_image.save() 
+
+    def map_delete_inputs(self, controller_image):
+        try:
+            controller_register = json.loads(instance.node.site_deployment.controller.backend_register)
+            slog.debug("controller_register: %s" % controller_register)
+
+            if (controller_register.get('disabled', False)):
+                slog.info('Controller %s is disabled' % instance.node.site_deployment.controller.name)
+                raise InnocuousException('Controller %s is disabled' % instance.node.site_deployment.controller.name) 
+            
+            swarm_manager_url = controller_image.controller.auth_url
+            (swarm_manager_address, docker_registry_port) = swarm_manager_url.split(':')
+            slog.info("swarm_manager_address: %s    docker_registry_port: %s" % 
+                        (swarm_manager_address, docker_registry_port)) 
+
+            input_fields = {
+                            'swarm_manager_address' : swarm_manager_address,
+                            'docker_registry_port'  : docker_registry_port,
+                            'image_file_path'       : controller_image.image.path,
+                            'image_dir'             : os.path.dirname(controller_image.image.path),
+                            'image_name'            : controller_image.image.name,
+                            'image_tag'             : controller_image.image.tag, 
+                            'delete'                : True,
+                            'ansible_tag'           : '%s@%s' % (
+                                                        controller_image.image.name,
+                                                        controller_image.controller.name)  # name of ansible playbook
+                            } 
+            slog.debug("input_fields: %s" % str(input_fields))
+            return input_fields 
+        except Exception as ex:
+            slog.error("Exception: %s   %s   %s" % (type(ex), str(ex), ex.args))
+            slog.error("%s" % str(traceback.format_exc()))
+
diff --git a/xos/synchronizer/steps/sync_controller_images.yaml b/xos/synchronizer/steps/sync_controller_images.yaml
index d7b5c09..14e185a 100644
--- a/xos/synchronizer/steps/sync_controller_images.yaml
+++ b/xos/synchronizer/steps/sync_controller_images.yaml
@@ -1,3 +1,19 @@
+
+# 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.
+
+
 ---
 - hosts: {{ swarm_manager_address }}
   become: true
@@ -28,6 +44,6 @@
         name: {{ swarm_manager_address }}:{{ docker_registry_port }}/{{ image_name }}:{{ image_tag }}
 
     {% else -%}
-    # Don't delete a docker image on docker registry and repository
+    # Don't delete a docker image 
     {% endif %}
 
diff --git a/xos/synchronizer/steps/sync_controller_networks.py b/xos/synchronizer/steps/sync_controller_networks.py
new file mode 100644
index 0000000..87bbe45
--- /dev/null
+++ b/xos/synchronizer/steps/sync_controller_networks.py
@@ -0,0 +1,206 @@
+
+# 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
+import base64
+import struct
+import socket
+from netaddr import IPAddress, IPNetwork
+from synchronizers.swarm.swarmsyncstep import SwarmSyncStep
+from synchronizers.new_base.syncstep import *
+from xos.logger import observer_logger as logger
+from synchronizers.new_base.ansible_helper import *
+from synchronizers.new_base.modelaccessor import *
+
+import synchronizers.swarm.swarmlog as slog 
+
+
+class SyncControllerNetworks(SwarmSyncStep):
+    requested_interval = 0
+    provides=[Network]
+    observes=ControllerNetwork
+    playbook='sync_controller_networks.yaml'
+
+    def alloc_subnet(self, uuid):
+        slog.debug("uuid: %s" % str(uuid))
+        # use 16 bits only 
+        uuid_masked = uuid & 0xffff
+        a = 10
+        b = uuid_masked >> 8
+        c = uuid_masked & 0xff
+        d = 0
+
+        cidr = '%d.%d.%d.%d/24'%(a,b,c,d)
+        slog.debug("subnet cidr: %s" % str(cidr))
+
+        return cidr
+
+    def alloc_gateway(self, subnet):
+        # given a CIDR, allocate a default gateway using the .1 address within the subnet.
+        #    10.123.0.0/24 --> 10.123.0.1
+        #    207.141.192.128/28 --> 207.141.192.129
+        (network, bits) = subnet.split("/")
+        network=network.strip()
+        bits=int(bits.strip())
+        netmask = (~(pow(2,32-bits)-1) & 0xFFFFFFFF)
+        ip = struct.unpack("!L", socket.inet_aton(network))[0]
+        ip = ip & netmask | 1
+        slog.debug("subnet: %s    gateway: %s" % (subnet,ip)) 
+        return socket.inet_ntoa(struct.pack("!L", ip))
+
+    def chk_net_exist(self, controller_network, swarm_manager_address):
+        duplicated_flag = False
+        try: 
+            slog.debug("network_name to check: %s" % controller_network.network.name)
+
+            import docker 
+            docker_api_base_url = "tcp://%s:4243" % swarm_manager_address
+            slog.info("Docker API Base URL: %s" % docker_api_base_url) 
+            my_client = docker.DockerClient(base_url=docker_api_base_url)
+            net = my_client.networks.get(controller_network.network.name)
+            slog.debug("network.id                  : %s" % net.id)
+            slog.debug("network.name                : %s" % net.name)
+            slog.debug("network.attrs[IPAM][Config] : %s" % net.attrs['IPAM']['Config'])
+            slog.debug("network.attrs               : %s" % net.attrs)
+        except Exception as ex:
+            slog.info("Exception: %s" % str(ex.args))
+            slog.info("Exception: %s" % str(ex))
+            duplicated_flag = False  # There is no same network.
+        else:
+            duplicated_flag = True   # There is same network.
+        slog.debug("network duplicated_flag: %s" % duplicated_flag)
+        return duplicated_flag 
+
+    def save_controller_network(self, controller_network):
+        network_name = controller_network.network.name 
+        if controller_network.subnet and controller_network.subnet.strip():
+            # If a subnet is already specified (pass in by the creator), then
+            # use that rather than auto-generating one.
+            cidr = controller_network.subnet.strip()
+            slog.info("subnet CIDR : %s" % cidr) 
+        else:
+            cidr = self.alloc_subnet(controller_network.pk)
+            slog.info("subnet CIDR (Auto generated by XOS): %s" % cidr) 
+
+        if controller_network.network.start_ip and controller_network.network.start_ip.strip():
+            start_ip = controller_network.network.start_ip.strip()
+            controller_network.gateway = start_ip  
+        else:
+            start_ip = None
+            controller_network.gateway = self.alloc_gateway(cidr)
+
+        if controller_network.network.end_ip and controller_network.network.end_ip.strip():
+            end_ip = controller_network.network.end_ip.strip()
+        else:
+            end_ip = None
+        slog.info("Start IP Address: %s    End IP Address: %s" % (start_ip, end_ip)) 
+
+        self.cidr=cidr
+        slice = controller_network.network.owner 
+
+        # "overlay" is default network driver for swarm
+        opt_driver = "--driver=overlay"
+        opt_ipam_driver = " "
+        opt_ipam_neutron_opt = " "
+        if controller_network.network.template.shared_network_name is not None:
+            if controller_network.network.template.shared_network_name.__contains__("kuryr"):
+                # update network driver for swarm
+                opt_driver = "--driver=%s" % controller_network.network.template.shared_network_name
+                opt_ipam_driver = "--ipam-driver=%s" % controller_network.network.template.shared_network_name
+                opt_ipam_neutron_opt = "--ipam-opt=neutron.pool.uuid=%s  -o neutron.pool.uuid=%s  -o neutron.net.name=%s" % (
+                                        controller_network.network.labels,
+                                        controller_network.network.labels,
+                                        controller_network.network.name)
+
+        swarm_manager_url = controller_network.controller.auth_url
+        (swarm_manager_address, docker_registry_port) = swarm_manager_url.split(':')
+        slog.info("swarm_manager_address: %s    docker_registry_port: %s"
+                    % (swarm_manager_address, docker_registry_port))
+
+        # check if this controller network is created already on swarm cluster.
+        duplicated_flag = self.chk_net_exist(controller_network, swarm_manager_address)
+
+        network_fields = {
+                            'swarm_manager_address' : swarm_manager_address,
+                            'network_name'          : network_name,
+                            'ansible_tag'           : '%s-%s@%s' % (
+                                                                    network_name,
+                                                                    slice.slicename,
+                                                                    controller_network.controller.name),
+                            'opt_driver'            : opt_driver,
+                            'opt_ipam_driver'       : opt_ipam_driver,
+                            'opt_ipam_neutron_opt'  : opt_ipam_neutron_opt,
+                            'opt_subnet'            : "--subnet=%s" % cidr,
+                            'opt_gateway'           : "--gateway=%s" % controller_network.gateway,
+                            'start_ip'              : start_ip,
+                            'end_ip'                : end_ip,
+                            'duplicated'            : duplicated_flag,
+                            'delete'                : False
+                            } 
+        slog.info("network_fields: %s" % network_fields) 
+        return network_fields
+
+    def map_sync_inputs(self, controller_network):
+        slog.debug("controller_network.subnet: %s" % controller_network.subnet)
+        slog.debug("controller_network.network.name: %s" % controller_network.network.name) 
+        if controller_network.network.owner and controller_network.network.owner.creator:
+            return self.save_controller_network(controller_network)
+        else:
+            slog.info("I could not create network controller information %s" % controller_network)
+            raise Exception('I could not create network controller %s'%controller_network)
+
+    def map_sync_outputs(self, controller_network, res):
+        slog.debug("ansible playbook ressult: %s" % str(res)) 
+        slog.debug("ansible playbook ressult[1][stdout]: %s" % str(res[1]['stdout'])) 
+        
+        res_stdout = res[1]['stdout'] 
+        json_content = json.loads(res_stdout)
+        slog.debug("json_content: %s" % str(json_content)) 
+        network_id = json_content[0]['Id']
+        slog.debug("network_id: %s" % str(network_id))
+        subnet_id = "%s-subnet-%s" % (network_id, self.cidr)
+        slog.debug("subnet_id: %s" % str(subnet_id)) 
+
+        controller_network.net_id = network_id
+        controller_network.subnet = self.cidr
+        controller_network.subnet_id = subnet_id
+        controller_network.backend_status = '1 - OK' 
+        controller_network.save()
+
+    def map_delete_inputs(self, controller_network):
+        # make sure to not delete a shared network
+        swarm_manager_url = controller_network.controller.auth_url
+        (swarm_manager_address, docker_registry_port) = swarm_manager_url.split(':')
+        slog.info("swarm_manager_address: %s    docker_registry_port: %s"
+                    % (swarm_manager_address, docker_registry_port)) 
+
+        try:
+            slice = controller_network.network.owner
+        except:
+            raise Exception('Could not get slice for Network %s' % controller_network.network.name)
+
+        network_name = controller_network.network.name
+        cidr = controller_network.subnet
+        network_fields = {
+                            'swarm_manager_address' : swarm_manager_address,
+                            'network_name'          :network_name,
+                            'ansible_tag'           :'%s-%s@%s'%(
+                                                        network_name,
+                                                        slice.slicename,
+                                                        controller_network.controller.name),
+                            'delete':True
+                         } 
+        return network_fields
diff --git a/xos/synchronizer/steps/sync_controller_networks.yaml b/xos/synchronizer/steps/sync_controller_networks.yaml
index 6ca2c90..1224723 100644
--- a/xos/synchronizer/steps/sync_controller_networks.yaml
+++ b/xos/synchronizer/steps/sync_controller_networks.yaml
@@ -1,3 +1,19 @@
+
+# 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.
+
+
 ---
 - hosts: {{ swarm_manager_address }}
   become: true 
diff --git a/xos/synchronizer/steps/sync_instances.py b/xos/synchronizer/steps/sync_instances.py
new file mode 100644
index 0000000..b2ef19e
--- /dev/null
+++ b/xos/synchronizer/steps/sync_instances.py
@@ -0,0 +1,305 @@
+
+# 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
+import base64
+import socket
+import threading
+import time 
+import sys, traceback
+
+from synchronizers.swarm.swarmsyncstep import SwarmSyncStep
+from synchronizers.new_base.ansible_helper import *
+from synchronizers.new_base.syncstep import *
+from xos.logger import observer_logger as logger
+from synchronizers.new_base.modelaccessor import *
+
+import synchronizers.swarm.swarmlog as slog
+
+
+class SyncInstances(SwarmSyncStep):
+    provides = [Instance]
+    requested_interval = 0
+    observes = Instance
+    playbook = 'sync_instances.yaml' 
+
+    def update_instance(self, instance):
+        slog.info("instance_name: %s   Thread: %s    instance.updated: %s" % (
+                    instance.instance_name, threading.current_thread().name, instance.updated)) 
+        time.sleep(1)
+
+        try:
+            inst_id = instance.id
+            slog.debug("inst_id: %s" % inst_id)
+            old_update = 0
+
+            for idx in range(1, 100, 1):
+                slog.debug("idx: %s" % idx)
+                new_inst = Instance.objects.get(id=inst_id)
+
+                if old_update == 0:
+                    old_update = new_inst.updated
+                slog.debug("updated(old): %s" % time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(old_update)))
+
+                if (new_inst.volumes is not None) and (new_inst.instance_name is not None):
+                    if (len(new_inst.volumes) > 2) and  (len(new_inst.instance_name) > 2):
+                        slog.debug("instance_name: %s (%s)" % (new_inst.instance_name, len(new_inst.instance_name)))
+                        slog.debug("volumes      : %s (%s)" % (new_inst.volumes, len(new_inst.volumes )))
+
+                        new_inst.numberCores = idx
+                        new_inst.updated = time.time()
+                        slog.debug("updated to renew : %s (%s)" % (
+                                        time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(new_inst.updated)), 
+                                        new_inst.updated)
+                                    )
+                        new_inst.save(update_fields=['updated', 'numberCores']) 
+                        time.sleep(1) 
+                        clone_inst = Instance.objects.get(id=inst_id)
+                        clone_inst.save(update_fields=['numberCores'])
+                        slog.debug("updated : %s (%s)" % (
+                                        time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(clone_inst.updated)),
+                                        clone_inst.updated)
+                                    )
+                        if clone_inst.updated == old_update:
+                            slog.debug("updated date was not changed. Nothing is executed. Waiting 5 seconds.")
+                            time.sleep(5)
+                        else:
+                            slog.debug("updated date was changed. Swarm synchronizer will run ansible")
+                            return 
+        except Exception as ex:
+            slog.error("Exception: %s   %s   %s" % (type(ex), str(ex), ex.args))
+            slog.error("%s" % str(traceback.format_exc())) 
+
+    def chk_svc_exist(self, instance, swarm_manager_address):
+        duplicated_flag = False
+        try:
+            instance_name = '%s-%s-%d' % (instance.slice.service.name, instance.slice.name, instance.id)
+            slog.debug("Service name to chkeck: %s" % instance_name)
+
+            import docker
+            docker_api_base_url = "tcp://%s:4243" % swarm_manager_address
+            slog.debug("Docker API Base URL: %s" % docker_api_base_url)
+            my_client = docker.DockerClient(base_url=docker_api_base_url)
+            swarm_svc = my_client.services.get(instance_name)
+
+            slog.debug("swarm_svc.id     : %s" % swarm_svc.id)
+            slog.debug("swarm_svc.name   : %s" % swarm_svc.name)
+            slog.debug("swarm_svc.attrs  : %s" % swarm_svc.attrs)
+        except Exception as ex:
+            slog.error("Exception: %s   %s   %s" % (type(ex), str(ex), ex.args))
+            slog.error("%s" % str(traceback.format_exc())) 
+            slog.info("There is no duplicated service name, I would create new service (%s)" % instance_name)
+            duplicated_flag = False 
+        else:
+            slog.info("There is duplicated service name (%s)" % instance_name)
+            duplicated_flag = True
+        return duplicated_flag 
+
+    def fetch_pending(self, deletion=False):
+        slog.info("begin fetch_pending(%s)" % deletion)
+        objs = super(SyncInstances, self).fetch_pending(deletion)
+        slog.info("objects: %s" % objs) 
+        objs = [x for x in objs if x.isolation == "vm"]
+        slog.info("VM objects: %s" % objs) 
+        return objs 
+
+    def map_sync_inputs(self, instance): 
+        try:
+            slog.debug("instance: %s    slice: %s" % (instance, instance.slice.name)) 
+            controller = instance.node.site_deployment.controller 
+            swarm_manager_url = controller.auth_url
+            slog.info("swarm_manager_url: %s" % swarm_manager_url)
+            (swarm_manager_address, docker_registry_port) = swarm_manager_url.split(':')
+            slog.info("swarm_manager_address: %s    docker_registry_port: %s" % (
+                        swarm_manager_address, docker_registry_port))
+
+            # if instance.instance_uuid is not None, 
+            # then This method will update the instance with new configuration.
+            swarm_service_update_flag = False
+            if instance.instance_uuid is not None:
+                if len(instance.instance_uuid) > 2:
+                    swarm_service_update_flag = True 
+
+            # check if this service is created already on swarm cluster.
+            duplicated_flag = self.chk_svc_exist(instance, swarm_manager_address)
+            if duplicated_flag is True:
+                swarm_service_update_flag = True 
+
+            # To get volume information 
+            slog.debug("slice.mount_data_sets: %s" % instance.slice.mount_data_sets)
+            mount_dest_path = "/usr/local/etc"
+            if len(instance.slice.mount_data_sets) < 2:
+                slog.debug("instance.slice.mount_data_sets(%s) is too short" % instance.slice.mount_data_sets)
+            else:
+                mount_dest_path = instance.slice.mount_data_sets
+            slog.debug("volume mount destination path: %s" % mount_dest_path)
+
+            # set options for volume mounting 
+            # (example) --mount type=bind,src=/opt/xos/instance_volume/1,dst=/usr/local/etc/haproxy  
+            volume_mount_opt = " "
+            if swarm_service_update_flag is True:
+                volume_mount_opt = "--mount-add type=bind,src=/opt/xos/instance_volume/%s,dst=%s" % (
+                                    instance.id, mount_dest_path) 
+            else:
+                volume_mount_opt = "--mount type=bind,src=/opt/xos/instance_volume/%s,dst=%s" % (
+                                    instance.id, mount_dest_path) 
+            slog.debug("volume_mount_opt: %s" % volume_mount_opt)
+            host_volume_path = "/opt/xos/instance_volume/%s" % instance.id
+            slog.debug("host_volume_path: %s" % host_volume_path)
+
+            # sanity check - make sure model_policy for slice has run
+            if ((not instance.slice.policed) or (instance.slice.policed < instance.slice.updated)):
+                slog.info("Instance %s waiting on Slice %s to execute model policies" % (
+                            instance, instance.slice.name))
+                raise DeferredException(
+                            "Instance %s waiting on Slice %s to execute model policies" % (
+                            instance, instance.slice.name))
+
+            # sanity check - make sure model_policy for all slice networks have run
+            networks = instance.slice.ownedNetworks.all()
+            slog.debug("network list for slice of this instance(%s): %s" % (instance.name, str(networks)))
+
+            for network in instance.slice.ownedNetworks.all():
+                slog.info("instance: %s   network of slice(%s): %s" % (instance.name, instance.slice.name, network.name))
+                if ((not network.policed) or (network.policed < network.updated)):
+                    slog.info("Instance %s waiting on Network %s to execute model policies" % (
+                                instance, network.name))
+                    raise DeferredException(
+                                "Instance %s waiting on Network %s to execute model policies" % (
+                                instance, network.name)) 
+            slog.debug("Model Policy checking is done successfully.")
+
+            swarm_network = ""
+            for network in networks:
+                slog.debug("networkd.id: %s(%s, %s)  controller.id: %s" % (
+                            network.id, network.name, network.subnet, 
+                            instance.node.site_deployment.controller.id))
+                if not ControllerNetwork.objects.filter(
+                                                network_id=network.id,
+                                                controller_id=instance.node.site_deployment.controller.id).exists():
+                    raise DeferredException(
+                                    "Instance %s Private Network %s lacks ControllerNetwork object" % (
+                                    instance, network.name))
+                swarm_network += " --network %s " % network.name
+            slog.debug("swarm_network: %s" % swarm_network)
+
+            image_name = None
+            controller_images = instance.image.controllerimages.all()
+            controller_images = [x for x in controller_images if
+                                 x.controller_id == instance.node.site_deployment.controller.id]
+            if controller_images:
+                image_name = controller_images[0].image.name
+                slog.info("using image from ControllerImage object: " + str(image_name))
+
+            host_filter = instance.node.name.strip()
+            slog.info("instance.node.name: %s" % instance.node.name)
+
+            instance_name = '%s-%s-%d' % (instance.slice.service.name, instance.slice.name, instance.id)
+            slog.info("service name: %s   instance.slice.name: %s    instance.id: %s    instance_name: %s" % (
+                        instance.slice.service.name, instance.slice.name, instance.id, instance_name))
+            self.instance_name = instance_name
+
+            input_fields = {
+                            'swarm_manager_address' : swarm_manager_address,
+                            'swarm_service_name'    : instance_name,
+                            'network_name'          : swarm_network,
+                            'replicas'              : "--replicas 1",
+                            'restart_condition'     : "--restart-condition any  --restart-delay 9s ",
+                            'volume'                : volume_mount_opt,
+                            'host_volume_path'      : host_volume_path,
+                            'docker_registry_port'  : docker_registry_port,
+                            'image_name'            : instance.image.name,
+                            'image_tag'             : instance.image.tag, 
+                            'ansible_tag'           : instance_name,
+                            'delete'                : False,
+                            'update'                : swarm_service_update_flag
+                            } 
+            slog.info("input_fields: %s" % input_fields)
+
+            if swarm_service_update_flag is False:
+                slog.info("swarm_service_update_flag is %s, so I will update once more" % 
+                            swarm_service_update_flag) 
+                try:
+                    my_thr = threading.Thread(target=self.update_instance, args=(instance,))
+                    my_thr.start()
+                except Exception as ex:
+                    slog.error("Exception: %s   %s   %s" % (type(ex), str(ex), ex.args))
+                    slog.error("%s" % str(traceback.format_exc())) 
+            return input_fields
+        except Exception as ex:
+            slog.error("Exception: %s   %s   %s" % (type(ex), str(ex), ex.args))
+            slog.error("%s" % str(traceback.format_exc())) 
+
+    def map_sync_outputs(self, instance, res):
+        try:
+            slog.debug("ansible playbook ressult: %s" % str(res))
+            slog.debug("ansible playbook ressult[3][stdout]: %s" % str(res[3]['stdout'])) 
+            res_stdout = res[3]['stdout']
+            json_content = json.loads(res_stdout)
+            slog.debug("json_content: %s" % str(json_content))
+            instance.instance_id = json_content[0]['Spec']["Name"]
+            slog.debug("instance.instance_id: %s" % str(instance.instance_id))
+            instance.instance_uuid = json_content[0]['ID']
+            slog.debug("instance.instance_uuid: %s" % str(instance.instance_uuid))
+
+            controller = instance.node.site_deployment.controller
+            swarm_manager_url = controller.auth_url
+            (swarm_manager_address, docker_registry_port) = swarm_manager_url.split(':')
+            slog.debug("swarm_manager_address: %s    docker_registry_port: %s" % (
+                        swarm_manager_address, docker_registry_port)) 
+            try: 
+                instance.ip = socket.gethostbyname(swarm_manager_address)
+            except Exception,e:
+                slog.info(str(e)) 
+                slog.info("hostname(%s) resolution fail" % swarm_manager_address)
+                pass 
+            instance.instance_name = self.instance_name
+            instance.save()
+        except Exception as ex:
+            slog.error("Exception: %s   %s   %s" % (type(ex), str(ex), ex.args))
+            slog.error("%s" % str(traceback.format_exc())) 
+
+    def map_delete_inputs(self, instance):
+        try:
+            controller_register = json.loads(instance.node.site_deployment.controller.backend_register)
+            slog.debug("controller_register: %s" % controller_register)
+
+            if (controller_register.get('disabled', False)):
+                slog.info('Controller %s is disabled' % instance.node.site_deployment.controller.name)
+                raise InnocuousException('Controller %s is disabled' % instance.node.site_deployment.controller.name)
+
+            instance_name = '%s-%s-%d' % (instance.slice.service.name, instance.slice.name, instance.id)
+            slog.debug("instance_name: %s" % instance_name)
+
+            controller = instance.node.site_deployment.controller
+            slog.debug("controller: %s" % controller) 
+            swarm_manager_url = controller.auth_url
+            slog.debug("swarm_manager_url: %s" % swarm_manager_url)
+            (swarm_manager_address, docker_registry_port) = swarm_manager_url.split(':')
+            slog.debug("swarm_manager_address: %s    docker_registry_port: %s" % (swarm_manager_address, docker_registry_port))
+            host_volume_path = "/opt/xos/instance_volume/%s" % instance.id
+            slog.debug("host_volume_path: %s" % host_volume_path) 
+            input = {
+                    'swarm_manager_address' : swarm_manager_address,
+                    'swarm_service_name'    : instance_name,
+                    'host_volume_path'      : host_volume_path,
+                    'ansible_tag'           : instance_name,
+                    'delete'                : True
+                    }
+            return input
+        except Exception as ex:
+            slog.error("Exception: %s   %s   %s" % (type(ex), str(ex), ex.args))
+            slog.error("%s" % str(traceback.format_exc()))
diff --git a/xos/synchronizer/steps/sync_instances.yaml b/xos/synchronizer/steps/sync_instances.yaml
index a129d02..816f829 100644
--- a/xos/synchronizer/steps/sync_instances.yaml
+++ b/xos/synchronizer/steps/sync_instances.yaml
@@ -1,3 +1,19 @@
+
+# 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.
+
+
 ---
 - hosts: {{ swarm_manager_address }}
   become: true