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()))
+