push addional code

Change-Id: Ia427bb3460cda3a896f8faced2de69eaf3807b74
Signed-off-by: Michael Lando <ml636r@att.com>
diff --git a/openecomp-be/tools/build/scripts/action_library_client/action_library_client.py b/openecomp-be/tools/build/scripts/action_library_client/action_library_client.py
new file mode 100644
index 0000000..7d6e32e
--- /dev/null
+++ b/openecomp-be/tools/build/scripts/action_library_client/action_library_client.py
@@ -0,0 +1,704 @@
+#!/usr/bin/python
+
+##############################################################################
+#
+# action_library_client.py
+#
+# A command-line client for the SDC Action Library.
+#
+#
+# Usage:
+#
+#  Usage: action_library_client.py [--help] [--url <url>] [--in <filename>]
+#                                  [--out <filename>] [--config <filename>]
+#                                  [--log <filename>] [--uuid <uuid>]
+#                                  [--curl] [--dryrun] [--verbose] [--version]
+#                                  [--list | --create | --update= | --delete |
+#                                   --checkout | --undocheckout | --checkin | --submit]
+#
+#  Optional arguments:
+#    --help                Show this help message and exit
+#    --url <url>           REST endpoint URL
+#    --in <filename>       Path to JSON input file (else STDIN)
+#    --out <filename>      Path to JSON output file (else STDOUT or logfile)
+#    --config <filename>   Path to configuration file
+#    --log <filename>      Path to logfile (else STDOUT)
+#    --uuid <uuid>         Action UUID, (=='actionInvariantUUID')
+#    --curl                Use curl transport impl
+#    --dryrun              Describe what will happen, execute nothing
+#    --verbose             Verbose diagnostic output
+#    --version             Print script version and exit
+#    --list                List actions
+#    --create              Create new action (requires --in)
+#    --update              Update existing action (requires --uuid, --in)
+#    --delete              Delete existing action (requires --uuid)
+#    --checkout            Create minor version candidate (requires --uuid)
+#    --undocheckout        Discard minor version candidate (requires --uuid)
+#    --checkin             Create minor version from candidate (requires --uuid)
+#    --submit              Create next major version (requires --uuid)
+#
+# For example:
+#
+#    ./action_library_client.py --url http://10.147.97.199:8080 --list
+#
+# Output:
+#   - Return values:
+#      - 0 - OK
+#      - 1 - GENERAL_ERROR
+#      - 2 - ARGUMENTS_ERROR
+#      - 3 - HTTP_FORBIDDEN_ERROR
+#      - 4 - HTTP_BAD_REQUEST_ERROR
+#      - 5 - HTTP_GENERAL_ERROR
+#      - 6 - PROCESS_ERROR
+#   - JSON - to stdout:
+#      - Delimited by "----------"
+#      - Delimiter overrideable with ALC_JSON_DELIMITER setting.
+#
+# Configuration/env settings:
+#   - ALC_HTTP_USER - HTTP BASIC username
+#   - ALC_HTTP_PASS - HTTP BASIC password
+#   - ALC_HTTP_INSECURE - allow untrusted SSL (server) connections.
+#   - ALC_TIMEOUT_SECONDS - invocation (e.g. HTTP) timeout in seconds.
+#   - ALC_JSON_DELIMITER - JSON delimiter in ouput.
+#   - ALC_ECOMP_INSTANCE_ID - X-ECOMP-InstanceID header
+#
+# Configuration by 0600-mode INI file (section "action_library_client") is preferred.
+#
+# See:
+#    http://10.147.97.199:8080/api-docs/ - REST API Swagger docs
+#    https://www.python.org/dev/peps/pep-0008/ - style guide
+#    ../doc/SDC_Action_Lib_API_AID_1610_13.pdf - REST API dev guide
+#
+# Version history:
+# - 1.0.0 November 28th 2016, LP, initial impl.
+# - 1.0.1 November 29th 2016, LP, constants, documentation, add --version.
+# - 1.0.2 November 29th 2016, LP, logging to files, stream-handling.
+# - 1.0.3 November 30th 2016, LP, optionally read config from env or config file.
+# - 1.1.0 December 3rd 2016, LP, backport from Python 3.4.2 to 2.6.6(!).
+#
+##############################################################################
+
+
+import sys
+import os
+import logging
+import base64
+import tempfile
+import uuid
+import json
+import ssl
+import urllib2
+import subprocess
+import ConfigParser
+from abc import abstractmethod
+
+
+###############################################################################
+
+
+class Constants(object):
+    """Common constants, for want of a better language feature..."""
+    # Values.
+    VERSION = "1.1.0"
+    APPLICATION = "action_library_client"
+    ACTIONS_URI = "onboarding-api/workflow/v1.0/actions"
+    ECOMP_INSTANCE_ID = "sdc_alc"
+    TIMEOUT_SECONDS_DEFAULT = 30
+    JSON_DELIMITER_DEFAULT = "----------"
+    LOG_FORMAT = "%(name)s\t%(levelname)s\t%(asctime)s\t%(message)s"
+    # Env variable names.
+    ENV_HTTP_USER = "ALC_HTTP_USER"
+    ENV_HTTP_PASS = "ALC_HTTP_PASS"
+    ENV_HTTP_INSECURE = "ALC_HTTP_INSECURE"
+    ENV_HTTP_CAFILE = "ALC_HTTP_CAFILE"
+    ENV_TIMEOUT_SECONDS = "ALC_TIMEOUT_SECONDS"
+    ENV_JSON_DELIMITER = "ALC_JSON_DELIMITER"
+    ENV_ECOMP_INSTANCE_ID = "ALC_ECOMP_INSTANCE_ID"
+
+
+###############################################################################
+
+
+class ResponseCodes(object):
+    """Responses returned by IRESTClient impls."""
+    OK = 0
+    GENERAL_ERROR = 1
+    ARGUMENTS_ERROR = 2
+    HTTP_NOT_FOUND_ERROR = 3
+    HTTP_FORBIDDEN_ERROR = 4
+    HTTP_BAD_REQUEST_ERROR = 5
+    HTTP_GENERAL_ERROR = 6
+    PROCESS_GENERAL_ERROR = 9
+
+
+###############################################################################
+
+
+class FinalizeStatus(object):
+    """Finalization operations."""
+    Checkout = "Checkout"
+    UndoCheckout = "Undo_Checkout"
+    CheckIn = "Checkin"
+    Submit = "Submit"
+
+
+###############################################################################
+
+
+class ArgsDict(dict):
+    """A dict which makes attributes accessible as properties."""
+    def __getattr__(self, attr):
+        return self[attr]
+
+    def __setattr__(self, attr, value):
+        self[attr] = value
+
+
+###############################################################################
+
+
+class ArgumentParser(object):
+    """A minimal reimpl of the argparse library, core in later Python releases"""
+    ACTIONS = ["list", "create", "update", "delete", "checkout", "undocheckout", "checkin", "submit"]
+    PARMS = ["url", "in", "out", "config", "log", "uuid"]
+    OTHER = ["curl", "dryrun", "verbose", "version", "help"]
+
+    def parse_args(self, clargs):
+        """Parse command-line args, returning a dict that exposes everything as properties."""
+        args = ArgsDict()
+        args.action = None
+        for arg in self.ACTIONS + self.PARMS + self.OTHER:
+            args[arg] = None
+        skip = False
+        try:
+            for i, clarg in enumerate(clargs):
+                if skip:
+                    skip = False
+                    continue
+                if not clarg.startswith("--"):
+                    raise Exception("Invalid argument: {0}".format(clarg))
+                arg = str(clarg[2:])
+                if arg in self.ACTIONS:
+                    if args.action:
+                        raise Exception("Duplicate actions: --{0}, {1}".format(args.action, clarg))
+                    args.action = arg
+                elif arg in self.PARMS:
+                    try:
+                        args[arg] = clargs[i + 1]
+                        skip = True
+                    except IndexError:
+                        raise Exception("Option {0} requires an argument".format(clarg))
+                elif arg in self.OTHER:
+                    args[arg] = True
+                else:
+                    raise Exception("Invalid argument: {0}".format(clarg))
+
+            # Check action args.
+
+            if args.action:
+                if not args.url:
+                    raise Exception("--url required for every action")
+                if not args.uuid:
+                    if args.action not in ["create", "list"]:
+                        raise Exception("--uuid required for every action EXCEPT --list/--create")
+
+            # Read from file or stdin, and replace the problematic "in"
+            # property with "infile".
+
+            if args.action in ["create", "update"]:
+                if args["in"]:
+                    args.infile = open(args["in"], mode="r")
+                else:
+                    args.infile = sys.stdin
+
+        except Exception as e:
+            print(e)
+            ArgumentParser.usage()
+            sys.exit(ResponseCodes.ARGUMENTS_ERROR)
+        return args
+
+    @staticmethod
+    def usage():
+        """Print usage message."""
+        print("" +
+            "Usage: action_library_client.py [--help] [--url <url>] [--in <filename>]\n" +
+            "                                 [--out <filename>] [--config <filename>]\n" +
+            "                                 [--log <filename>] [--uuid <uuid>]\n" +
+            "                                 [--curl] [--dryrun] [--verbose] [--version]\n" +
+            "                                 [--list | --create | --update= | --delete |\n" +
+            "                                  --checkout | --undocheckout | --checkin | --submit]\n" +
+            "\n" +
+            "Optional arguments:\n" +
+            "  --help                Show this help message and exit\n" +
+            "  --url <url>           REST endpoint URL\n" +
+            "  --in <filename>       Path to JSON input file (else STDIN)\n" +
+            "  --out <filename>      Path to JSON output file (else STDOUT or logfile)\n" +
+            "  --config <filename>   Path to configuration file\n" +
+            "  --log <filename>      Path to logfile (else STDOUT)\n" +
+            "  --uuid <uuid>         Action UUID, (=='actionInvariantUUID')\n" +
+            "  --curl                Use curl transport impl\n" +
+            "  --dryrun              Describe what will happen, execute nothing\n" +
+            "  --verbose             Verbose diagnostic output\n" +
+            "  --version             Print script version and exit\n" +
+            "  --list                List actions\n" +
+            "  --create              Create new action (requires --in)\n" +
+            "  --update              Update existing action (requires --uuid, --in)\n" +
+            "  --delete              Delete existing action (requires --uuid)\n" +
+            "  --checkout            Create minor version candidate (requires --uuid)\n" +
+            "  --undocheckout        Discard minor version candidate (requires --uuid)\n" +
+            "  --checkin             Create minor version from candidate (requires --uuid)\n" +
+            "  --submit              Create next major version (requires --uuid)")
+
+
+###############################################################################
+
+
+class Settings(object):
+    """Settings read from (optional) configfile, or environment."""
+
+    def __init__(self, args):
+        """Construct for command-line args."""
+        self.config = ConfigParser.ConfigParser()
+        if args.config:
+            self.config.read(args.config)
+
+    def get(self, name, default_value=None):
+        """Get setting from configfile or environment"""
+        try:
+            return self.config.get(Constants.APPLICATION, name)
+        except (KeyError, ConfigParser.NoSectionError, ConfigParser.NoOptionError):
+            try:
+                return os.environ[name]
+            except KeyError:
+                return default_value
+
+
+###############################################################################
+
+
+# Python3: metaclass=ABCMeta
+class IRESTClient(object):
+    """Base class for local, proxy and dryrun impls."""
+
+    def __init__(self, args):
+        self.args = args
+        self.logger = Runner.get_logger()
+        self.settings = Settings(args)
+
+    @abstractmethod
+    def list(self):
+        """Abstract list operation."""
+        pass
+
+    @abstractmethod
+    def create(self):
+        """Abstract list operation."""
+        pass
+
+    @abstractmethod
+    def update(self):
+        """Abstract list operation."""
+        pass
+
+    @abstractmethod
+    def delete(self):
+        """Abstract list operation."""
+        pass
+
+    @abstractmethod
+    def version(self, status):
+        """Abstract list operation."""
+        pass
+
+    @staticmethod
+    def new_uuid():
+        """Generate UUID."""
+        return str(uuid.uuid4())
+
+    def get_timeout_seconds(self):
+        """Get request timeout in seconds."""
+        return self.settings.get(Constants.ENV_TIMEOUT_SECONDS,
+                                 Constants.TIMEOUT_SECONDS_DEFAULT)
+
+    def get_http_insecure(self):
+        """Get whether SSL certificate checks are (inadvisably) disabled."""
+        return True if self.settings.get(Constants.ENV_HTTP_INSECURE) else False
+
+    def get_http_cafile(self):
+        """Get optional CA file for SSL server cert validation"""
+        if not self.get_http_insecure():
+            return self.settings.get(Constants.ENV_HTTP_CAFILE)
+
+    def get_basic_credentials(self):
+        """Generate Authorization: header."""
+        usr = self.settings.get(Constants.ENV_HTTP_USER)
+        pwd = self.settings.get(Constants.ENV_HTTP_PASS)
+        if usr and pwd:
+            return base64.b64encode(bytes("{0}:{1}".format(usr, pwd))).decode("ascii")
+        else:
+            raise Exception("REST service credentials not found")
+
+    def make_service_url(self):
+        """Generate service URL based on command-line arguments."""
+        url = self.args.url
+        if "/onboarding-api/" not in url:
+            separator = "" if url.endswith("/") else "/"
+            url = "{0}{1}{2}".format(url, separator, str(Constants.ACTIONS_URI))
+        if self.args.uuid:
+            separator = "" if url.endswith("/") else "/"
+            url = "{0}{1}{2}".format(url, separator, self.args.uuid)
+        return url
+
+    def log_json_response(self, method, json_dict):
+        """Log JSON response regardless of transport."""
+        json_str = json.dumps(json_dict, indent=4)
+        delimiter = self.settings.get(Constants.ENV_JSON_DELIMITER, Constants.JSON_DELIMITER_DEFAULT)
+        self.logger.info("HTTP {0} JSON response:\n{1}\n{2}\n{3}\n".format(method, delimiter, json_str, delimiter))
+        if self.args.out:
+            with open(self.args.out, "w") as tmp:
+                tmp.write(json_str)
+                tmp.flush()
+        elif self.args.log:
+            # Directly to stdout if logging is sent to a file.
+            print(json_str)
+
+    def log_action(self, action, status=None):
+        """Debug action before invocation."""
+        url = self.make_service_url()
+        name = status if status else self.__get_name()
+        self.logger.debug("{0}::{1}({2})".format(name, action, url))
+
+    @staticmethod
+    def _get_result_from_http_response(code):
+        """Get script returncode from HTTP error."""
+        if code == 400:
+            return ResponseCodes.HTTP_BAD_REQUEST_ERROR
+        elif code == 403:
+            return ResponseCodes.HTTP_FORBIDDEN_ERROR
+        elif code == 404:
+            return ResponseCodes.HTTP_NOT_FOUND_ERROR
+        return ResponseCodes.HTTP_GENERAL_ERROR
+
+    def __get_name(self):
+        """Get classname for diags"""
+        return type(self).__name__
+
+
+###############################################################################
+
+
+class NativeRESTClient(IRESTClient):
+    """In-process IRESTClient impl."""
+
+    def list(self):
+        """In-process list impl."""
+        self.log_action("list")
+        return self.__exec(method="GET", expect_json=True)
+
+    def create(self):
+        """In-process create impl."""
+        self.log_action("create")
+        json_bytes = bytes(self.args.infile.read())
+        return self.__exec(method="POST", json_bytes=json_bytes, expect_json=True)
+
+    def update(self):
+        """In-process update impl."""
+        self.log_action("update")
+        json_bytes = bytes(self.args.infile.read())
+        return self.__exec(method="PUT", json_bytes=json_bytes, expect_json=True)
+
+    def delete(self):
+        """In-process delete impl."""
+        self.log_action("delete")
+        return self.__exec(method="DELETE")
+
+    def version(self, status):
+        """In-process version impl."""
+        self.log_action("version", status)
+        json_bytes = bytes(json.dumps({"status": status}))
+        return self.__exec(method="POST", json_bytes=json_bytes, expect_json=True)
+
+    def __exec(self, method, json_bytes=None, expect_json=None):
+        """Build command, execute it, validate and return response."""
+        try:
+            url = self.make_service_url()
+            timeout = float(self.get_timeout_seconds())
+            cafile = self.get_http_cafile()
+            headers = {
+                "Content-Type": "application/json",
+                "Accept": "application/json",
+                "Authorization": "Basic {0}".format(self.get_basic_credentials()),
+                "X-ECOMP-InstanceID": Constants.ECOMP_INSTANCE_ID,
+                "X-ECOMP-RequestID": IRESTClient.new_uuid()
+            }
+
+            handler = urllib2.HTTPHandler
+            if hasattr(ssl, 'create_default_context'):
+                ctx = ssl.create_default_context(cafile=cafile)
+                if self.get_http_insecure():
+                    ctx.check_hostname = False
+                    ctx.verify_mode = ssl.CERT_NONE
+                handler = urllib2.HTTPSHandler(context=ctx) if url.lower().startswith("https") else urllib2.HTTPHandler
+
+            self.logger.debug("URL {0} {1}: {2}".format(url, method, json_bytes))
+
+            opener = urllib2.build_opener(handler)
+            request = urllib2.Request(url, data=json_bytes, headers=headers)
+            request.get_method = lambda: method
+
+            f = None
+            try:
+                f = opener.open(request, timeout=timeout)
+                return self.__handle_response(f, method, expect_json)
+            finally:
+                if f:
+                    f.close()
+
+        except urllib2.HTTPError as err:
+            self.logger.exception(err)
+            return IRESTClient._get_result_from_http_response(err.getcode())
+        except urllib2.URLError as err:
+            self.logger.exception(err)
+            return ResponseCodes.HTTP_GENERAL_ERROR
+
+    def __handle_response(self, f, method, expect_json):
+        """Devolve response handling because of the """
+        self.logger.debug("HTTP {0} status {1}, reason:\n{2}".format(method, f.getcode(), f.info()))
+        if expect_json:
+            # JSON responses get "returned", but actually it's the logging that
+            # most callers will be looking for.
+            json_body = json.loads(f.read().decode("utf-8"))
+            self.log_json_response(method, json_body)
+            return json_body
+        # Not JSON, but the operation succeeded, so return True.
+        return ResponseCodes.OK
+
+
+###############################################################################
+
+
+class CURLRESTClient(IRESTClient):
+    """Remote/curl IRESTClient impl."""
+
+    def list(self):
+        """curl list impl"""
+        self.log_action("list")
+        return self._exec(method="GET", expect_json=True)
+
+    def create(self):
+        """curl create impl"""
+        self.log_action("create")
+        data_args = ["--data", "@{0}".format(self.args.infile.name)]
+        return self._exec(method="POST", extra_args=data_args, expect_json=True)
+
+    def update(self):
+        """curl update impl"""
+        self.log_action("update")
+        data_args = ["--data", "@{0}".format(self.args.infile.name)]
+        return self._exec(method="PUT", extra_args=data_args, expect_json=True)
+
+    def delete(self):
+        """curl delete impl"""
+        self.log_action("delete")
+        return self._exec(method="DELETE", expect_json=False)
+
+    def version(self, status):
+        """curl version impl"""
+        self.log_action("version", status)
+        with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp:
+            tmp.write(json.dumps({"status": status}))
+            tmp.flush()
+        data_args = ["--data", "@{0}".format(tmp.name)]
+        return self._exec(method="POST", extra_args=data_args, expect_json=True)
+
+    def make_curl_cmd(self, method, url, extra_args):
+        """Build curl command without executing."""
+        cmd = ["curl", "-i", "-s", "-X", method]
+        if self.get_http_insecure():
+            cmd.append("-k")
+        cmd.extend(["--connect-timeout", str(self.get_timeout_seconds())])
+        cmd.extend(["--header", "Accept: application/json"])
+        cmd.extend(["--header", "Content-Type: application/json"])
+        cmd.extend(["--header", "Authorization: Basic {0}".format(self.get_basic_credentials())])
+        cmd.extend(["--header", "X-ECOMP-InstanceID: {0}".format(Constants.ECOMP_INSTANCE_ID)])
+        cmd.extend(["--header", "X-ECOMP-RequestID: {0}".format(IRESTClient.new_uuid())])
+        if extra_args:
+            for extra_arg in extra_args:
+                cmd.append(extra_arg)
+        cmd.append("{0}".format(url))
+        return cmd
+
+    @staticmethod
+    def debug_curl_cmd(cmd):
+        """Debug curl command, for diags and dryrun."""
+        buf = ""
+        for token in cmd:
+            if token is "curl" or token.startswith("-"):
+                buf = "{0}{1} ".format(buf, token)
+            else:
+                buf = "{0}\"{1}\" ".format(buf, token)
+        return buf
+
+    def _exec(self, method, extra_args=None, expect_json=None):
+        """Execute action.
+
+        Build command, invoke curl, validate and return response.
+        Overridden by DryRunRESTClient.
+        """
+        url = self.make_service_url()
+        cmd = self.make_curl_cmd(method, url, extra_args)
+        self.logger.info("Executing: {0}".format(CURLRESTClient.debug_curl_cmd(cmd)))
+
+        try:
+            output = subprocess.check_output(cmd, stderr=subprocess.STDOUT).decode()
+            if not expect_json:
+                return ResponseCodes.OK
+            try:
+                separator = output.index("\r\n\r\n{")
+                self.logger.debug("HTTP preamble:\n{0}".format(output[:separator]))
+                json_body = json.loads(output[(separator+4):])
+                self.log_json_response(method, json_body)
+                return json_body
+            except ValueError:
+                self.logger.warning("Couldn't find HTTP separator in curl output:\n{}".format(output))
+            code = CURLRESTClient.__get_http_code(output)
+            return IRESTClient._get_result_from_http_response(code)
+        except subprocess.CalledProcessError as err:
+            self.logger.exception(err)
+            return ResponseCodes.PROCESS_GENERAL_ERROR
+
+    @staticmethod
+    def __get_http_code(output):
+        """Attempt to guess HTTP result from (error) output."""
+        for line in output.splitlines():
+            if line.startswith("HTTP"):
+                tokens = line.split()
+                if len(tokens) > 2:
+                    try:
+                        return int(tokens[1])
+                    except ValueError:
+                        pass
+        return ResponseCodes.HTTP_GENERAL_ERROR
+
+
+###############################################################################
+
+
+class DryRunRESTClient(CURLRESTClient):
+    """Neutered IRESTClient impl; only logs."""
+
+    def _exec(self, method, extra_args=None, expect_json=None):
+        """Override."""
+        url = self.make_service_url()
+        cmd = self.make_curl_cmd(method, url, extra_args)
+        self.logger.info("[DryRun] {0}".format(CURLRESTClient.debug_curl_cmd(cmd)))
+
+
+###############################################################################
+
+
+class Runner(object):
+    """A bunch of static housekeeping supporting the launcher."""
+
+    @staticmethod
+    def get_logger():
+        """Get logger instance."""
+        return logging.getLogger(Constants.APPLICATION)
+
+    @staticmethod
+    def get_rest_client(args):
+        """Get the configured REST client impl, local, remote or dryrun."""
+        if args.dryrun:
+            return DryRunRESTClient(args)
+        elif args.curl:
+            return CURLRESTClient(args)
+        else:
+            return NativeRESTClient(args)
+
+    @staticmethod
+    def execute(args):
+        """Execute the requested action."""
+        client = Runner.get_rest_client(args)
+        if args.version:
+            print(Constants.VERSION)
+        elif args.help:
+            ArgumentParser.usage()
+        elif args.action == "list":
+            return client.list()
+        elif args.action == "create":
+            return client.create()
+        elif args.action == "update":
+            return client.update()
+        elif args.action == "delete":
+            return client.delete()
+        elif args.action == "checkout":
+            return client.version(FinalizeStatus.Checkout)
+        elif args.action == "checkin":
+            return client.version(FinalizeStatus.CheckIn)
+        elif args.action == "undocheckout":
+            return client.version(FinalizeStatus.UndoCheckout)
+        elif args.action == "submit":
+            return client.version(FinalizeStatus.Submit)
+        else:
+            logger = Runner.get_logger()
+            logger.info("No action specified. Try --help.")
+
+    @staticmethod
+    def parse_args(raw):
+        """Parse command-line args, returning dict."""
+        return ArgumentParser().parse_args(raw)
+
+
+###############################################################################
+
+
+def execute(raw):
+    """Delegate which executes minus error-handling, exposed for unit-testing."""
+
+    # Intercept Python 2.X.
+
+    if not (sys.version_info[0] == 2 and sys.version_info[1] >= 6):
+        raise EnvironmentError("Python 2.6/2.7 required")
+
+    # Parse command-line args.
+
+    args = Runner.parse_args(raw)
+
+    # Redirect logging to a file (freeing up STDIN) if directed.
+
+    logging.basicConfig(level=logging.INFO, filename=args.log, format=Constants.LOG_FORMAT)
+
+    # Set loglevel.
+
+    logger = Runner.get_logger()
+    if args.verbose:
+        logger.setLevel(logging.DEBUG)
+    logger.debug("Parsed arguments: {0}".format(args))
+
+    # Execute request.
+
+    return Runner.execute(args)
+
+
+###############################################################################
+
+
+def main(raw):
+    """Execute for command-line arguments."""
+
+    logger = Runner.get_logger()
+    try:
+        result = execute(raw)
+        result_code = result if isinstance(result, int) else ResponseCodes.OK
+        logger.debug("Execution complete. Returning result {0} ({1})".format(result, result_code))
+        sys.exit(result_code)
+    except Exception as err:
+        logger.exception(err)
+        sys.exit(ResponseCodes.GENERAL_ERROR)
+
+
+###############################################################################
+
+
+if __name__ == "__main__":
+    main(sys.argv[1:])
diff --git a/openecomp-be/tools/build/scripts/action_library_client/doc/TESTPLAN.TXT b/openecomp-be/tools/build/scripts/action_library_client/doc/TESTPLAN.TXT
new file mode 100644
index 0000000..be6a77c
--- /dev/null
+++ b/openecomp-be/tools/build/scripts/action_library_client/doc/TESTPLAN.TXT
@@ -0,0 +1,10 @@
+1.  Unit + integration tests.
+2.  Reading credentials from configfile.
+3.  Writing output to logfile, response to stdout.
+4.  Reading JSON from stdin.
+5.  TLS URL, success, failure (if Python checks, and with insecure mode enabled).
+6.  Auth failure.
+7.  Print help, version.
+8.  Python 2.6/2.7 sanity (whichever isn't primary)
+9.  Run BASH example scripts.
+10. Run Python example script(s).
diff --git a/openecomp-be/tools/build/scripts/action_library_client/test/scenarios/Backout.json b/openecomp-be/tools/build/scripts/action_library_client/test/scenarios/Backout.json
new file mode 100644
index 0000000..12b7b4d
--- /dev/null
+++ b/openecomp-be/tools/build/scripts/action_library_client/test/scenarios/Backout.json
@@ -0,0 +1,45 @@
+{
+      "name": "Backout",
+      "displayName": "Backout",
+      "description": "MCAP Backout",
+      "vendorList": ["BROCADE"],
+      "categoryList": ["Upgrade"],
+      "endpointURI": "engine-rest/process-definition/key/Backout/start",
+      "supportedModels": [{
+            "versionID": "AA56B177-9383-4934-8543-0F91A7A04971",
+            "versionInvariantUUID": "CC87B177-9383-4934-8543-0F91A7A07193",
+            "name": "vCE",
+            "version": "2.1",
+            "category": "cpe"
+      }],
+      "supportedComponents": [{
+            "ID": "BB47B177-9383-4934-8543-0F91A7A06448",
+            "componentName": "appc"
+      }],
+      "inputParameters": [{
+            "name": "VNF_NAME",
+            "description": "VNF name",
+            "type": "STRING",
+            "max-length": "50",
+            "optional": true,
+            "allowed_values": ["string1", "string2"]
+      }],
+      "outputParameters": [{
+            "name": "STATUS",
+            "defaultValue": "Default Value",
+            "type": "STRING",
+            "description": "The status of execution"
+      }],
+      "operationalData": {
+            "outageDuration": "0",
+            "approxDuration": "5",
+            "staticFields": {},
+            "updatableFields": {}
+      },
+      "serverList": [{
+            "name": "appcserver",
+            "hostName": "cm-server1.client.com",
+            "port": "666"
+      }],
+      "updatedBy": "AUTHusername"
+}
diff --git a/openecomp-be/tools/build/scripts/action_library_client/test/scenarios/Copy_image.json b/openecomp-be/tools/build/scripts/action_library_client/test/scenarios/Copy_image.json
new file mode 100644
index 0000000..06da2ae
--- /dev/null
+++ b/openecomp-be/tools/build/scripts/action_library_client/test/scenarios/Copy_image.json
@@ -0,0 +1,45 @@
+{
+      "name": "Copy_image",
+      "displayName": "Copy_image",
+      "description": "MCAP Copy Image",
+      "vendorList": ["BROCADE"],
+      "categoryList": ["Upgrade"],
+      "endpointURI": "engine-rest/process-definition/key/Copy_image/start",
+      "supportedModels": [{
+            "versionID": "AA56B177-9383-4934-8543-0F91A7A04971",
+            "versionInvariantUUID": "CC87B177-9383-4934-8543-0F91A7A07193",
+            "name": "vCE",
+            "version": "2.1",
+            "category": "cpe"
+      }],
+      "supportedComponents": [{
+            "ID": "BB47B177-9383-4934-8543-0F91A7A06448",
+            "componentName": "appc"
+      }],
+      "inputParameters": [{
+            "name": "VNF_NAME",
+            "description": "VNF name",
+            "type": "STRING",
+            "max-length": "50",
+            "optional": true,
+            "allowed_values": ["string1", "string2"]
+      }],
+      "outputParameters": [{
+            "name": "STATUS",
+            "defaultValue": "Default Value",
+            "type": "STRING",
+            "description": "The status of execution"
+      }],
+      "operationalData": {
+            "outageDuration": "0",
+            "approxDuration": "5",
+            "staticFields": {},
+            "updatableFields": {}
+      },
+      "serverList": [{
+            "name": "appcserver",
+            "hostName": "cm-server1.client.com",
+            "port": "666"
+      }],
+      "updatedBy": "AUTHusername"
+}
diff --git a/openecomp-be/tools/build/scripts/action_library_client/test/scenarios/Healthcheck.json b/openecomp-be/tools/build/scripts/action_library_client/test/scenarios/Healthcheck.json
new file mode 100644
index 0000000..b1be8f7
--- /dev/null
+++ b/openecomp-be/tools/build/scripts/action_library_client/test/scenarios/Healthcheck.json
@@ -0,0 +1,45 @@
+{
+      "name": "Healthcheck",
+      "displayName": "Healthcheck",
+      "description": "MCAP Healthcheck",
+      "vendorList": ["BROCADE"],
+      "categoryList": ["Upgrade"],
+      "endpointURI": "engine-rest/process-definition/key/Healthcheck/start",
+      "supportedModels": [{
+            "versionID": "AA56B177-9383-4934-8543-0F91A7A04971",
+            "versionInvariantUUID": "CC87B177-9383-4934-8543-0F91A7A07193",
+            "name": "vCE",
+            "version": "2.1",
+            "category": "cpe"
+      }],
+      "supportedComponents": [{
+            "ID": "BB47B177-9383-4934-8543-0F91A7A06448",
+            "componentName": "appc"
+      }],
+      "inputParameters": [{
+            "name": "VNF_NAME",
+            "description": "VNF name",
+            "type": "STRING",
+            "max-length": "50",
+            "optional": true,
+            "allowed_values": ["string1", "string2"]
+      }],
+      "outputParameters": [{
+            "name": "STATUS",
+            "defaultValue": "Default Value",
+            "type": "STRING",
+            "description": "The status of execution"
+      }],
+      "operationalData": {
+            "outageDuration": "0",
+            "approxDuration": "5",
+            "staticFields": {},
+            "updatableFields": {}
+      },
+      "serverList": [{
+            "name": "appcserver",
+            "hostName": "cm-server1.client.com",
+            "port": "666"
+      }],
+      "updatedBy": "AUTHusername"
+}
diff --git a/openecomp-be/tools/build/scripts/action_library_client/test/scenarios/Reboot.json b/openecomp-be/tools/build/scripts/action_library_client/test/scenarios/Reboot.json
new file mode 100644
index 0000000..72cbb65
--- /dev/null
+++ b/openecomp-be/tools/build/scripts/action_library_client/test/scenarios/Reboot.json
@@ -0,0 +1,45 @@
+{
+      "name": "Reboot",
+      "displayName": "Reboot",
+      "description": "MCAP Reboot",
+      "vendorList": ["BROCADE"],
+      "categoryList": ["Upgrade"],
+      "endpointURI": "engine-rest/process-definition/key/Reboot/start",
+      "supportedModels": [{
+            "versionID": "AA56B177-9383-4934-8543-0F91A7A04971",
+            "versionInvariantUUID": "CC87B177-9383-4934-8543-0F91A7A07193",
+            "name": "vCE",
+            "version": "2.1",
+            "category": "cpe"
+      }],
+      "supportedComponents": [{
+            "ID": "BB47B177-9383-4934-8543-0F91A7A06448",
+            "componentName": "appc"
+      }],
+      "inputParameters": [{
+            "name": "VNF_NAME",
+            "description": "VNF name",
+            "type": "STRING",
+            "max-length": "50",
+            "optional": true,
+            "allowed_values": ["string1", "string2"]
+      }],
+      "outputParameters": [{
+            "name": "STATUS",
+            "defaultValue": "Default Value",
+            "type": "STRING",
+            "description": "The status of execution"
+      }],
+      "operationalData": {
+            "outageDuration": "0",
+            "approxDuration": "5",
+            "staticFields": {},
+            "updatableFields": {}
+      },
+      "serverList": [{
+            "name": "appcserver",
+            "hostName": "cm-server1.client.com",
+            "port": "666"
+      }],
+      "updatedBy": "AUTHusername"
+}
diff --git a/openecomp-be/tools/build/scripts/action_library_client/test/seq.txt b/openecomp-be/tools/build/scripts/action_library_client/test/seq.txt
new file mode 100644
index 0000000..b18fcc5
--- /dev/null
+++ b/openecomp-be/tools/build/scripts/action_library_client/test/seq.txt
@@ -0,0 +1 @@
+535
\ No newline at end of file
diff --git a/openecomp-be/tools/build/scripts/action_library_client/test/test_action_library_client.py b/openecomp-be/tools/build/scripts/action_library_client/test/test_action_library_client.py
new file mode 100644
index 0000000..dc1161c
--- /dev/null
+++ b/openecomp-be/tools/build/scripts/action_library_client/test/test_action_library_client.py
@@ -0,0 +1,154 @@
+import unittest
+import os
+import tempfile
+import ConfigParser
+import action_library_client as ALC
+
+
+class D(dict):
+
+    def __init__(self, *args, **kwargs):
+        super(D, self).__init__(*args, **kwargs)
+        self.__dict__ = self
+
+
+class UnitTest(unittest.TestCase):
+
+    def __write_config_file(self, map):
+        with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp:
+            config = ConfigParser.ConfigParser()
+            config.add_section("action_library_client")
+            for k, v in map.items():
+                section = config.set("action_library_client", k, v)
+            config.write(tmp)
+            tmp.flush()
+            return tmp.name
+
+    def test_argument_parser(self):
+        # nothing = ALC.ArgumentParser().parse_args([])
+        # self.assertEquals(nothing.help, None)
+        # self.assertEquals(nothing.version, None)
+        # self.assertEquals(nothing.verbose, None)
+        #
+        # help = ALC.ArgumentParser().parse_args(["--help"])
+        # self.assertEquals(help.help, True)
+
+        uuidx = ALC.ArgumentParser().parse_args(["--uuid", "abc"])
+        self.assertEquals(uuidx.uuid, "abc")
+
+
+    def test_settings_get(self):
+
+        os.environ["a"] = "aa"
+        os.environ["b"] = "WILL_BE_OVERRIDDEN"
+
+        section = dict()
+        section['ALC_HTTP_USER'] = "batman"
+        section['ECOMP_INSTANCE_ID'] = "acdc"
+        section['b'] = "bb"
+        filename = self.__write_config_file(section)
+
+        # with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp:
+        #     config = configparser.ConfigParser()
+        #     config.add_section("action_library_client")
+        #     section = config["action_library_client"]
+        #     config.write(tmp)
+        #     tmp.flush()
+
+        settings = ALC.Settings(ALC.Runner.parse_args(["--config", filename]))
+        self.assertEquals("aa", settings.get("a"))
+        self.assertEquals("bb", settings.get("b"))
+        self.assertEquals("batman", settings.get("ALC_HTTP_USER"))
+        self.assertEquals("batman", settings.get(ALC.Constants.ENV_HTTP_USER))
+        self.assertEquals("ALC_ECOMP_INSTANCE_ID", settings.get("c", ALC.Constants.ENV_ECOMP_INSTANCE_ID))
+
+        os.remove(filename)
+
+    def test_parse_args(self):
+        c1 = ALC.Runner.parse_args(["--version"])
+        with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp:
+            config = ConfigParser.ConfigParser()
+            config.add_section("action_library_client")
+            config.set("action_library_client", "ALC_HTTP_USER", "batman")
+            config.write(tmp)
+            tmp.flush()
+        self.assertEquals(c1.version, True)
+
+    def test_get_http_insecure(self):
+        c = ALC.DryRunRESTClient(ALC.Runner.parse_args([]))
+        self.assertEquals(False, c.get_http_insecure())
+
+    def test_get_http_cafile(self):
+        c1 = ALC.DryRunRESTClient(ALC.Runner.parse_args([]))
+        self.assertEquals(False, c1.get_http_insecure())
+        self.assertIsNone(c1.get_http_cafile())
+
+        filename = self.__write_config_file({"ALC_HTTP_CAFILE": "/tmp/x"})
+        c2 = ALC.DryRunRESTClient(ALC.Runner.parse_args(["--config", filename]))
+        self.assertEquals(False, c2.get_http_insecure())
+        self.assertEquals("/tmp/x", c2.get_http_cafile())
+
+    def test_get_timeout_seconds(self):
+        args = ALC.Runner.parse_args(["--version"])
+        self.assertEquals(30, ALC.DryRunRESTClient(args).get_timeout_seconds())
+
+    def test_get_basic_credentials(self):
+        try:
+            saved_user = os.environ["ALC_HTTP_USER"]
+            saved_pass = os.environ["ALC_HTTP_PASS"]
+        except KeyError:
+            saved_user = ""
+            saved_pass = ""
+        try:
+            os.environ["ALC_HTTP_USER"] = "AUTH-DELETE"
+            os.environ["ALC_HTTP_PASS"] = "test"
+            c = ALC.DryRunRESTClient(ALC.Runner.parse_args([]))
+            c1 = c.get_basic_credentials()
+            self.assertEqual(c1, "QVVUSC1ERUxFVEU6dGVzdA==")
+            os.environ["ALC_HTTP_USER"] = "AUTH-DELETE"
+            os.environ["ALC_HTTP_PASS"] = "death"
+            c2 = c.get_basic_credentials()
+            self.assertNotEqual(c2, "QVVUSC1ERUxFVEU6dGVzdA==")
+        finally:
+            os.environ["ALC_HTTP_USER"] = saved_user
+            os.environ["ALC_HTTP_PASS"] = saved_pass
+
+    def test_get_rest_client(self):
+        uuid = ALC.IRESTClient.new_uuid()
+        c1 = ALC.Runner.get_rest_client(ALC.Runner.parse_args(["--dryrun"]))
+        self.assertTrue(isinstance(c1, ALC.DryRunRESTClient))
+        c2 = ALC.Runner.get_rest_client(ALC.Runner.parse_args(["--curl"]))
+        self.assertTrue(isinstance(c2, ALC.CURLRESTClient))
+        c3 = ALC.Runner.get_rest_client(ALC.Runner.parse_args(["--uuid", uuid]))
+        self.assertTrue(isinstance(c3, ALC.NativeRESTClient))
+
+    def test_get_logger(self):
+        logger = ALC.Runner.get_logger()
+        logger.info("idotlogger")
+
+    def test_new_uuid(self):
+        uuid = ALC.IRESTClient.new_uuid()
+        self.assertEqual(len(uuid), 36)
+
+    def test_make_service_url(self):
+        uuid = ALC.IRESTClient.new_uuid()
+
+        args1 = ALC.Runner.parse_args(["--url", "http://banana"])
+        client1 = ALC.DryRunRESTClient(args1)
+        self.assertEqual(client1.make_service_url(),
+                         "http://banana/onboarding-api/workflow/v1.0/actions")
+
+        args2 = ALC.Runner.parse_args(["--url", "http://banana/"])
+        client2 = ALC.DryRunRESTClient(args2)
+        self.assertEqual(client2.make_service_url(),
+                         "http://banana/onboarding-api/workflow/v1.0/actions")
+
+        args3 = ["--url", "http://banana/onboarding-api/workflow/v1.1/actions", "--uuid", uuid]
+        client3 = ALC.DryRunRESTClient(ALC.Runner.parse_args(args3))
+        self.assertEqual(client3.make_service_url(),
+                         "http://banana/onboarding-api/workflow/v1.1/actions/{}".format(uuid))
+
+    def test_debug_curl_cmd(self):
+        cmd = ["curl", "--header", "banana", "http://something/somewhere"]
+        debug = ALC.CURLRESTClient.debug_curl_cmd(cmd)
+        self.assertEqual("curl --header \"banana\" \"http://something/somewhere\" ", debug)
\ No newline at end of file
diff --git a/openecomp-be/tools/build/scripts/action_library_client/test/test_action_library_client_integration.py b/openecomp-be/tools/build/scripts/action_library_client/test/test_action_library_client_integration.py
new file mode 100644
index 0000000..b6418e6
--- /dev/null
+++ b/openecomp-be/tools/build/scripts/action_library_client/test/test_action_library_client_integration.py
@@ -0,0 +1,329 @@
+import sys
+import os
+import unittest
+import uuid
+import json
+import tempfile
+import action_library_client
+
+class IntegrationTest(unittest.TestCase):
+
+    HTTP = "http://10.147.97.199:8080"
+    HTTPS = "https://10.147.97.199:8443"
+
+    def setUp(self):
+        os.environ["ALC_HTTP_USER"] = "AUTH-DELETE"
+        os.environ["ALC_HTTP_PASS"] = "test"
+
+    def tearDown(self):
+        os.environ["ALC_HTTP_INSECURE"] = ""
+        os.environ["ALC_HTTP_USER"] = ""
+        os.environ["ALC_HTTP_PASS"] = ""
+
+    @staticmethod
+    def __prepare(testcase, name):
+        with open(testcase, 'r') as fin:
+            jsonk = json.loads(fin.read())
+            jsonk['name'] = name
+            with tempfile.NamedTemporaryFile(mode='w', delete=False) as temp:
+                temp.write(json.dumps(jsonk))
+                temp.flush()
+                return temp.name
+
+    @staticmethod
+    def __get_sequence():
+        with open(r'./seq.txt', 'r+') as f:
+            value = int(f.read())
+            f.seek(0)
+            f.write(str(value + 1))
+            return value
+
+    def __print_separator(self):
+        logger = action_library_client.Runner.get_logger()
+        logger.info("==================================================")
+
+    def __list(self, stdargs):
+        logger = action_library_client.Runner.get_logger()
+        list_response = action_library_client.execute(["--list"] + stdargs)
+        logger.info("--list response: {}".format(list_response))
+        self.assertTrue(isinstance(list_response, dict))
+        return list_response
+
+    def __get_action(self, list_response, ai_uuid):
+        for action in list_response['actionList']:
+            if action['actionInvariantUUID'] == ai_uuid:
+                return action
+
+    def __create_delete(self, extraargs):
+
+        logger = action_library_client.Runner.get_logger()
+
+        # Setup.
+
+        seq = IntegrationTest.__get_sequence()
+        name = "Backout{}".format(seq)
+        path = IntegrationTest.__prepare("scenarios/Backout.json", name)
+        stdargs = ["--url", self.HTTP, "--verbose"]
+        if extraargs:
+            stdargs.extend(extraargs)
+
+        # List actions.
+
+        self.__print_separator()
+        list_response1 = self.__list(stdargs)
+        self.assertTrue(isinstance(list_response1, dict))
+
+        # CREATE action.
+
+        self.__print_separator()
+        create_response = action_library_client.execute(["--create", "--in", path] + stdargs)
+        logger.info("--create response: {}".format(create_response))
+        self.assertTrue(isinstance(create_response, dict))
+        ai_uuid = create_response['actionInvariantUUID']
+        self.assertTrue(ai_uuid)
+        self.assertEquals(create_response['status'], 'Locked')
+        self.assertEquals(create_response['version'], '0.1')
+
+        # UPDATE action #1.
+
+        self.__print_separator()
+        update_response1 = action_library_client.execute(["--update", "--in", path, "--uuid", ai_uuid] + stdargs)
+        logger.info("--update response: {}".format(update_response1))
+        self.assertTrue(isinstance(update_response1, dict))
+
+        # UPDATE action #2.
+
+        self.__print_separator()
+        update_response2 = action_library_client.execute(["--update", "--in", path, "--uuid", ai_uuid] + stdargs)
+        logger.info("--update response: {}".format(update_response2))
+        self.assertTrue(isinstance(update_response2, dict))
+
+        # CHECKOUT action (usage unknown).
+
+        self.__print_separator()
+        try:
+            action_library_client.execute(["--checkout", "--uuid", ai_uuid] + stdargs)
+            self.fail("--checkout should fail")
+        except Exception as err:
+            print(err)
+
+        # CHECKIN action.
+
+        self.__print_separator()
+        checkin_response = action_library_client.execute(["--checkin", "--in", path, "--uuid", ai_uuid] + stdargs)
+        logger.info("--checkin response: {}".format(checkin_response))
+        self.assertTrue(isinstance(checkin_response, dict))
+        self.assertEquals(checkin_response['status'], 'Available')
+        self.assertEquals(checkin_response['version'], '0.1')
+
+        # SUBMIT action.
+
+        self.__print_separator()
+        submit_response = action_library_client.execute(["--submit", "--in", path, "--uuid", ai_uuid] + stdargs)
+        logger.info("--submit response: {}".format(submit_response))
+        self.assertTrue(isinstance(submit_response, dict))
+        self.assertEquals(submit_response['status'], 'Final')
+        self.assertEquals(submit_response['version'], '1.0')
+
+        # LIST again
+
+        self.__print_separator()
+        list_response2 = self.__list(stdargs)
+        action_found2 = self.__get_action(list_response2, ai_uuid)
+        self.assertTrue(action_found2)
+
+        # DELETE action.
+
+        self.__print_separator()
+        delete_response = action_library_client.execute(["--delete", "--uuid", ai_uuid] + stdargs)
+        logger.info("--delete response: {}".format(delete_response))
+        self.assertEqual(delete_response, action_library_client.ResponseCodes.OK)
+
+        # LIST yet again
+
+        self.__print_separator()
+        list_response3 = self.__list(stdargs)
+        action_found3 = self.__get_action(list_response3, ai_uuid)
+        self.assertFalse(action_found3)
+
+    def __create_undo(self, extraargs):
+
+        # Setup
+
+        logger = action_library_client.Runner.get_logger()
+        seq = IntegrationTest.__get_sequence()
+        name = "Backout{}".format(seq)
+        path = IntegrationTest.__prepare("scenarios/Backout.json", name)
+        stdargs = ["--url", self.HTTP, "--verbose"]
+
+        # CREATE action.
+
+        self.__print_separator()
+        create_response = action_library_client.execute(["--create", "--in", path] + stdargs + extraargs)
+        logger.info("--create response: {}".format(create_response))
+        self.assertTrue(isinstance(create_response, dict))
+        ai_uuid = create_response['actionInvariantUUID']
+        self.assertTrue(ai_uuid)
+        self.assertEquals(create_response['status'], 'Locked')
+        self.assertEquals(create_response['version'], '0.1')
+
+        # UNDOCHECKOUT action
+
+        self.__print_separator()
+        undocheckout_response = action_library_client.execute(["--undocheckout", "--uuid", ai_uuid] + stdargs + extraargs)
+        self.assertTrue(isinstance(undocheckout_response, dict))
+
+    def __create_list(self, extraargs):
+        # Setup
+
+        logger = action_library_client.Runner.get_logger()
+        seq = IntegrationTest.__get_sequence()
+        name = "Backout{}".format(seq)
+        path = IntegrationTest.__prepare("scenarios/Backout.json", name)
+        stdargs = ["--url", self.HTTP, "--verbose"]
+
+        # CREATE action.
+
+        self.__print_separator()
+        create_response = action_library_client.execute(["--create", "--in", path] + stdargs + extraargs)
+        logger.info("--create response: {}".format(create_response))
+        self.assertTrue(isinstance(create_response, dict))
+        ai_uuid = create_response['actionInvariantUUID']
+        self.assertTrue(ai_uuid)
+        self.assertEquals(create_response['status'], 'Locked')
+        self.assertEquals(create_response['version'], '0.1')
+
+        # CHECKIN action.
+
+        self.__print_separator()
+        checkin_response = action_library_client.execute(["--checkin", "--in", path, "--uuid", ai_uuid] +
+                                                         stdargs + extraargs)
+        logger.info("--checkin response: {}".format(checkin_response))
+        self.assertTrue(isinstance(checkin_response, dict))
+        self.assertEquals(checkin_response['status'], 'Available')
+        self.assertEquals(checkin_response['version'], '0.1')
+
+        try:
+            # LIST.
+
+            self.__print_separator()
+            list_response1 = self.__list(stdargs + extraargs)
+            action_found1 = self.__get_action(list_response1, ai_uuid)
+            self.assertTrue(action_found1)
+
+            # LIST with UUID.
+
+            self.__print_separator()
+            list_response2 = self.__list(stdargs + extraargs + ["--uuid", ai_uuid])
+            self.assertFalse(hasattr(list_response2, 'actionList'))
+            self.assertEquals(len(list_response2['versions']), 1)
+
+            # LIST with bad UUID.
+
+            self.__print_separator()
+            list_response3 = action_library_client.execute(["--list"] + stdargs + extraargs +
+                                                           ["--uuid", "where_the_wind_blows"])
+            if isinstance(list_response3, int):
+                self.assertEquals(action_library_client.ResponseCodes.HTTP_NOT_FOUND_ERROR, list_response3)
+            else:
+                self.assertEquals("ACT1045", list_response3["code"])
+
+        finally:
+
+            # DELETE action
+
+            self.__print_separator()
+            action_library_client.execute(["--delete", "--uuid", ai_uuid] + stdargs + extraargs)
+
+    def __http_secure(self, extraargs):
+        os.environ["ALC_HTTP_INSECURE"] = ""
+        try:
+            self.__list(["--url", self.HTTPS, "--verbose"] + extraargs)
+            if not (sys.version_info[0] == 2 and sys.version_info[1] == 6):
+                self.fail("Should fail (non-2.6) for TLS + secure")
+        except Exception:
+            pass
+
+    def __http_insecure(self, extraargs):
+        os.environ["ALC_HTTP_INSECURE"] = True
+        self.__list(["--url", self.HTTPS, "--verbose"] + extraargs)
+
+    def __no_credentials(self, extraargs):
+
+        args = ["--url", self.HTTP] + extraargs
+        self.__list(args)
+        print("OK")
+
+        os.environ["ALC_HTTP_USER"] = ""
+        os.environ["ALC_HTTP_PASS"] = ""
+        try:
+            action_library_client.execute(["--list"] + args)
+            self.fail("Should fail for missing credentials")
+        except Exception as e:
+            self.assertEquals("REST service credentials not found", e.message)
+
+    def __bad_credentials(self, extraargs):
+
+        args = ["--url", self.HTTP] + extraargs
+        self.__list(args)
+
+        os.environ["ALC_HTTP_USER"] = "wakey_wakey"
+        os.environ["ALC_HTTP_PASS"] = "rise_and_shine"
+        code = action_library_client.execute(["--list"] + args)
+        self.assertEquals(action_library_client.ResponseCodes.HTTP_FORBIDDEN_ERROR, code)
+
+    ################################################################################
+
+    def test_https_insecure_local_fail(self):
+        self.__http_secure([])
+
+    def test_https_insecure_remote_fail(self):
+        self.__http_secure(["--curl"])
+
+    def test_https_native(self):
+        self.__http_secure([])
+
+    def test_https_curl(self):
+        self.__http_secure(["--curl"])
+
+    def test_undo_checkout_native(self):
+        self.__create_undo([])
+
+    def test_undo_checkout_curl(self):
+        self.__create_undo(["--curl"])
+
+    def test_create_delete_native(self):
+        self.__create_delete([])
+
+    def test_create_delete_curl(self):
+        self.__create_delete(["--curl"])
+
+    def test_create_list_native(self):
+        self.__create_list([])
+
+    def test_create_list_curl(self):
+        self.__create_list(["--curl"])
+
+    def test_bad_credentials_native(self):
+        self.__bad_credentials([])
+
+    def test_bad_credentials_curl(self):
+        self.__bad_credentials(["--curl"])
+    #
+    def test_no_credentials_native(self):
+        self.__no_credentials([])
+
+    def test_no_credentials_curl(self):
+        self.__no_credentials(["--curl"])
+
+    def test_create_to_delete_dryrun(self):
+        ai_uuid = str(uuid.uuid4())
+        path = IntegrationTest.__prepare("scenarios/Backout.json", "Backout{}".format("001"))
+        stdargs = ["--url", self.HTTP, "--verbose", "--dryrun"]
+        action_library_client.execute(["--create", "--in", path] + stdargs)
+        action_library_client.execute(["--update", "--in", path, "--uuid", ai_uuid] + stdargs)
+        action_library_client.execute(["--checkout", "--uuid", ai_uuid] + stdargs)
+        action_library_client.execute(["--undocheckout", "--uuid", ai_uuid] + stdargs)
+        action_library_client.execute(["--checkin", "--uuid", ai_uuid] + stdargs)
+        action_library_client.execute(["--submit", "--uuid", ai_uuid] + stdargs)
+        action_library_client.execute(["--list"] + stdargs)
diff --git a/openecomp-be/tools/build/scripts/cassandra-commands.json b/openecomp-be/tools/build/scripts/cassandra-commands.json
new file mode 100644
index 0000000..8354ff2
--- /dev/null
+++ b/openecomp-be/tools/build/scripts/cassandra-commands.json
@@ -0,0 +1,76 @@
+{
+  "create": {
+    "version": "CREATE TYPE IF NOT EXISTS version (major int, minor int)",
+    "user_candidate_version": "CREATE TYPE IF NOT EXISTS user_candidate_version (version frozen<version>, user text)",
+    "version_info": "CREATE TABLE IF NOT EXISTS version_info (entity_type text, entity_id text, active_version frozen<version>, status text, candidate frozen<user_candidate_version>, viewable_versions set<frozen<version>>, latest_final_version frozen<version>, PRIMARY KEY (entity_type, entity_id))",
+    "version_info_deleted": "CREATE TABLE IF NOT EXISTS version_info_deleted (entity_type text, entity_id text, active_version frozen<version>, status text, candidate frozen<user_candidate_version>, viewable_versions set<frozen<version>>, latest_final_version frozen<version>, PRIMARY KEY (entity_type, entity_id))",
+    "unique_value" : "CREATE TABLE IF NOT EXISTS unique_value (type text, value text, PRIMARY KEY ((type, value)))",
+    "choice_or_other": "CREATE TYPE IF NOT EXISTS choice_or_other (result text)",
+    "multi_choice_or_other": "CREATE TYPE IF NOT EXISTS multi_choice_or_other (results set<text>)",
+    "vendor_license_model": "CREATE TABLE IF NOT EXISTS vendor_license_model (vlm_id text, version frozen<version>, vendor_name text, description text, icon text, PRIMARY KEY ((vlm_id, version)))",
+    "license_agreement": "CREATE TABLE IF NOT EXISTS license_agreement (vlm_id text, version frozen<version>, la_id text, name text, description text, lic_term frozen<choice_or_other>, req_const text, fg_ids set<text>, PRIMARY KEY ((vlm_id, version), la_id))",
+    "feature_group": "CREATE TABLE IF NOT EXISTS feature_group (vlm_id text, version frozen<version>, fg_id text, name text, description text, part_num text, ep_ids set<text>, lkg_ids set<text>, ref_la_ids set<text>, PRIMARY KEY ((vlm_id, version), fg_id))",
+    "license_key_group": "CREATE TABLE IF NOT EXISTS license_key_group (vlm_id text, version frozen<version>, lkg_id text,name text,description text, type text, operational_scope frozen<multi_choice_or_other>, ref_fg_ids set<text>, version_uuid text, PRIMARY KEY ((vlm_id, version), lkg_id))",
+    "entitlement_pool": "CREATE TABLE IF NOT EXISTS entitlement_pool (vlm_id text, version frozen<version>, ep_id text,name text,description text,threshold float,threshold_unit text,entitlement_metric frozen<choice_or_other>,increments text,aggregation_func frozen<choice_or_other>, operational_scope frozen<multi_choice_or_other>, time frozen<choice_or_other>,manufacturer_ref_num text,ref_fg_ids set<text>, version_uuid text, PRIMARY KEY ((vlm_id, version), ep_id))",
+    "vsp_information": "CREATE TABLE IF NOT EXISTS vsp_information (VSP_ID text, version frozen<version>, NAME text,DESCRIPTION text,CATEGORY text,SUB_CATEGORY text,ICON text,PACKAGE_NAME text,PACKAGE_VERSION text,vendor_name text, vendor_id text,LICENSE_AGREEMENT text,FEATURE_GROUPS list<text>,VALIDATION_DATA text,CONTENT_DATA blob, questionnaire_data text, vlm_version frozen<version>, PRIMARY KEY ((VSP_ID, version)))",
+    "package_details": "CREATE TABLE IF NOT EXISTS package_details (VSP_ID text, version frozen<version>,DISPLAY_NAME text,vsp_name text,vsp_description text,VENDOR_NAME text,CATEGORY text,SUB_CATEGORY text,VENDOR_RELEASE text,PACKAGE_CHECKSUM text,PACKAGE_TYPE text,TRANSLATE_CONTENT blob,PRIMARY KEY ((VSP_ID, version)))",
+    "vsp_network": "CREATE TABLE IF NOT EXISTS vsp_network (vsp_id text, version frozen<version>, network_id text, composition_data text, questionnaire_data text, PRIMARY KEY ((vsp_id, version), network_id))",
+    "vsp_component": "CREATE TABLE IF NOT EXISTS vsp_component (vsp_id text, version frozen<version>, component_id text, composition_data text, questionnaire_data text, PRIMARY KEY ((vsp_id, version), component_id))",
+    "vsp_component_nic": "CREATE TABLE IF NOT EXISTS vsp_component_nic (vsp_id text, version frozen<version>, component_id text, nic_id text, composition_data text, questionnaire_data text, PRIMARY KEY ((vsp_id, version), component_id, nic_id))",
+    "vsp_process" : "CREATE TABLE IF NOT EXISTS vsp_process (vsp_id text, version frozen<version>, component_id text, process_id text, name text, description text, artifact_name text, artifact blob, PRIMARY KEY ((vsp_id, version), component_id, process_id))",
+    "vsp_service_artifact" : "CREATE TABLE IF NOT EXISTS vsp_service_artifact (vsp_id text, version frozen<version>, name text, content_data blob, PRIMARY KEY ((vsp_id, version), name))",
+    "vsp_service_template" : "CREATE TABLE IF NOT EXISTS vsp_service_template (vsp_id text, version frozen<version>, base_name text static, name text, content_data blob, PRIMARY KEY ((vsp_id, version), name))",
+    "vsp_enriched_service_template" : "CREATE TABLE IF NOT EXISTS vsp_enriched_service_template (vsp_id text, version frozen<version>, base_name text static, name text, content_data blob, PRIMARY KEY ((vsp_id, version), name))",
+    "vsp_enriched_service_artifact" : "CREATE TABLE IF NOT EXISTS vsp_enriched_service_artifact (vsp_id text, version frozen<version>, name text, content_data blob, PRIMARY KEY ((vsp_id, version), name))",
+    "application_config" : "CREATE TABLE IF NOT EXISTS application_config (namespace text, key text, value text, PRIMARY KEY (namespace, key))",
+    "action" : "CREATE TABLE IF NOT EXISTS dox.Action (actionUUID text, actionInvariantUUID text, version frozen<version>, status text, name text, vendor_list set<text>, category_list set<text>, timestamp timestamp, user text, supportedModels set<text>, supportedComponents set<text>, data text, PRIMARY KEY ((actionInvariantUUID, version)))",
+    "supportedComponents_index" : "CREATE INDEX IF NOT EXISTS action_supportedComponents ON dox.Action (supportedComponents)",
+    "category_list_index" : "CREATE INDEX IF NOT EXISTS action_category_list ON dox.Action (category_list)",
+    "supportedModels_index" : "CREATE INDEX IF NOT EXISTS action_supportedModels ON dox.Action (supportedModels)",
+    "vendor_list_index" : "CREATE INDEX IF NOT EXISTS action_vendor_list ON dox.Action (vendor_list)",
+    "actionUUID_index" : "CREATE INDEX IF NOT EXISTS action_actionUUID ON dox.Action (actionUUID)",
+    "ecomp_component": "CREATE TABLE IF NOT EXISTS dox.ecompcomponent(id text PRIMARY KEY, name text)",
+    "vsp_component_artifact": "CREATE TABLE IF NOT EXISTS vsp_component_artifact (vsp_id text, version frozen<version>, component_id text, artifact_type text, artifact_id text, name text, description text, artifact blob,  PRIMARY KEY ((vsp_id, version), component_id, artifact_type, artifact_id))",
+    "name_index": "CREATE INDEX IF NOT EXISTS action_name ON dox.Action (name)",
+    "action_artifact":"CREATE TABLE IF NOT EXISTS action_artifact(artifactuuid text, effective_version int, artifact blob, PRIMARY KEY(artifactuuid, effective_version)) WITH CLUSTERING ORDER BY (effective_version DESC)"
+  },
+  "drop": {
+    "version_info": "DROP TABLE IF EXISTS version_info",
+    "version_info_deleted": "DROP TABLE IF EXISTS version_info_deleted",
+    "unique_value": "DROP TABLE IF EXISTS unique_value",
+    "entitlement_pool": "DROP TABLE IF EXISTS entitlement_pool",
+    "vendor_license_model": "DROP TABLE IF EXISTS vendor_license_model",
+    "license_agreement": "DROP TABLE IF EXISTS license_agreement",
+    "feature_group": "DROP TABLE IF EXISTS feature_group",
+    "license_key_group": "DROP TABLE IF EXISTS license_key_group",
+    "vsp_information": "DROP   TABLE IF EXISTS vsp_information",
+    "package_details": "DROP TABLE IF EXISTS package_details",
+    "vsp_network": "DROP TABLE IF EXISTS vsp_network",
+    "vsp_component": "DROP TABLE IF EXISTS vsp_component",
+    "vsp_component_nic": "DROP TABLE IF EXISTS vsp_component_nic",
+    "vsp_process":"DROP TABLE IF EXISTS vsp_process",
+    "choice_or_other": "DROP TYPE IF EXISTS choice_or_other",
+    "multi_choice_or_other": "DROP TYPE IF EXISTS multi_choice_or_other",
+    "application_config" : "DROP TABLE IF EXISTS application_config",
+    "vsp_service_artifact" :"DROP TABLE IF EXISTS vsp_service_artifact",
+    "vsp_service_template" :"DROP TABLE IF EXISTS vsp_service_template",
+    "vsp_enriched_service_artifact" :"DROP TABLE IF EXISTS vsp_enriched_service_artifact",
+    "vsp_enriched_service_template" :"DROP TABLE IF EXISTS vsp_enriched_service_template",
+    "action" : "DROP TABLE IF EXISTS action",
+    "supportedComponents_index" : "DROP INDEX IF EXISTS dox.action_supportedComponents",
+    "category_list_index" : "DROP INDEX IF EXISTS dox.action_category_list",
+    "supportedModels_index" : "DROP INDEX IF EXISTS dox.action_supportedModels",
+    "vendor_list_index" : "DROP INDEX IF EXISTS dox.action_vendor_list",
+    "actionUUID_index" : "DROP INDEX IF EXISTS dox.action_actionUUID",
+    "name_index" : "DROP INDEX IF EXISTS dox.action_name",
+    "ecomp_component": "DROP TABLE IF EXISTS dox.ecompcomponent",
+    "vsp_component_artifact": "DROP TABLE IF EXISTS dox.vsp_component_artifact",
+    "action_artifact":"DROP TABLE IF EXISTS action_artifact"
+  },
+  "alter": {
+    "vsp_information": "ALTER TABLE vsp_information ADD questionnaire_data text",
+    "vsp_information_1": "ALTER TABLE vsp_information ADD vlm_version frozen<version>",
+    "entitlement_pool": "alter table entitlement_pool ADD version_uuid text",
+    "license_key_group": "alter table license_key_group ADD version_uuid text"
+  }
+}
diff --git a/openecomp-be/tools/build/scripts/generate-application-config-insert-cql.sh b/openecomp-be/tools/build/scripts/generate-application-config-insert-cql.sh
new file mode 100644
index 0000000..e4e1ff0
--- /dev/null
+++ b/openecomp-be/tools/build/scripts/generate-application-config-insert-cql.sh
@@ -0,0 +1,64 @@
+#/bin/sh
+
+##############################################################################
+###
+### generate-application-config-insert-cql.sh
+###
+### A script that generates the CQL commands to INSERT validation schemas to the application_config table.
+### We keep the schemas FTL files under a folder - this folder will be parsed and INSERT commands will be created.
+###
+### If the path is 'schemaTemplates/composition/myFile.ftl' the result KEY will be: composition.myFile .
+###
+### Usage:
+###
+###    ./generate-application-config-insert-cql.sh <namespace> <schemas-folder>
+###
+###
+### Author: Avi Ziv
+### Version 1.0 for OPENECOMP
+### Date: 10 Aug 2016
+###
+##############################################################################
+
+#GLOBALS
+
+APP_CONFIG_TABLE='application_config'
+
+#### Functions - Start  ####
+usage() { echo "Usage: $0 <namespace> <schemaTemplates-folder>, for example: $0 vsp.schemaTemplates schemaTemplates/" 1>&2; exit 1; }
+
+getFileContent()
+{
+        file=$1
+        str=$(<$file)
+        echo $str
+}
+
+
+main()
+{
+        namespace=$1
+        path=$2
+        for fileName in $(find ${path} -type f)
+        do
+                value=$(getFileContent ${fileName})
+                onlyFilename=$(basename $fileName)
+                name="${onlyFilename%.*}"
+                tempPath=$(dirname $fileName)
+                keyColumn=$(basename $tempPath).$name
+                echo "INSERT INTO $APP_CONFIG_TABLE (namespace,key,value) VALUES ('$namespace', '$keyColumn', '$value');"
+        done
+
+
+exit 0
+}
+
+#### Functions - End    ####
+
+# Check arguements
+if [ "$#" -lt 2 ] || [ "$#" -gt 2 ]; then
+        usage
+fi
+
+
+main $1 $2
diff --git a/openecomp-be/tools/build/scripts/generate-cassandra-alter-cql.sh b/openecomp-be/tools/build/scripts/generate-cassandra-alter-cql.sh
new file mode 100644
index 0000000..827b3ab
--- /dev/null
+++ b/openecomp-be/tools/build/scripts/generate-cassandra-alter-cql.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+##############################################################################
+###
+### generate-cassandra-alter-cql.sh
+###
+### A script that generates the CQL commands of ALTER for the Cassnadra init.
+###
+### Usage:
+###
+###    ./generate-cassandra-alter-cql.sh cassandra-commands.json
+###
+###
+### Author: Avi Ziv
+### Version 2.0 for OPENECOMP
+### Date: 21 Sep 2016
+###
+##############################################################################
+
+#GLOBALS
+
+RUN_PATH=$(cd "$(dirname "$0")" && pwd)
+
+#### Functions - Start  ####
+usage() { echo "Usage: $0 <db-cql-json-file>, for example: $0 cassandra-commands.json" 1>&2; exit 1; }
+
+main()
+{
+        echo "USE dox;"
+        $RUN_PATH/parse-json.py -t alter -f $1
+}
+
+#### Functions - End    ####
+
+# Check arguements
+if [ "$#" -lt 1 ] || [ "$#" -gt 1 ]; then
+        usage
+fi
+
+main $1
diff --git a/openecomp-be/tools/build/scripts/generate-cassandra-drop-cql.sh b/openecomp-be/tools/build/scripts/generate-cassandra-drop-cql.sh
new file mode 100644
index 0000000..ddbf846
--- /dev/null
+++ b/openecomp-be/tools/build/scripts/generate-cassandra-drop-cql.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+##############################################################################
+###
+### generate-cassandra-drop-cql.sh
+###
+### A script that generates the CQL commands of DROP for the Cassnadra init.
+###
+### Usage:
+###
+###    ./generate-cassandra-init-cql.sh cassandra-commands.json
+###
+###
+### Author: Avi Ziv
+### Version 1.0 for OPENECOMP
+### Date: 21 Sep 2016
+###
+##############################################################################
+
+#GLOBALS
+
+RUN_PATH=$(cd "$(dirname "$0")" && pwd)
+
+#### Functions - Start  ####
+usage() { echo "Usage: $0 <db-cql-json-file>, for example: $0 cassandra-commands.json" 1>&2; exit 1; }
+
+main()
+{
+        echo "USE dox;"
+        $RUN_PATH/parse-json.py -t drop -f $1
+}
+
+#### Functions - End    ####
+
+# Check arguements
+if [ "$#" -lt 1 ] || [ "$#" -gt 1 ]; then
+        usage
+fi
+
+main $1
diff --git a/openecomp-be/tools/build/scripts/generate-cassandra-init-cql.sh b/openecomp-be/tools/build/scripts/generate-cassandra-init-cql.sh
new file mode 100644
index 0000000..65af5a5
--- /dev/null
+++ b/openecomp-be/tools/build/scripts/generate-cassandra-init-cql.sh
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+##############################################################################
+###
+### generate-cassandra-init-cql.sh
+###
+### A script that generates the CQL commands of CREATE for the Cassnadra init.
+###
+### Usage:
+###
+###    ./generate-cassandra-init-cql.sh cassandra-commands.json
+###
+###
+### Author: Avi Ziv
+### Version 2.0 for OPENECOMP
+### Date: 21 Sep 2016, added support for keyspace yes/no for OPENECOMP DevOps build
+###
+##############################################################################
+
+#GLOBALS
+
+RUN_PATH=$(cd "$(dirname "$0")" && pwd)
+
+#### Functions - Start  ####
+usage() { echo "Usage: $0 <db-cql-json-file> keyspace yes/no, for example: $0 cassandra-commands.json keyspace yes" 1>&2; exit 1; }
+
+main()
+{
+        if [ $3 == 'yes' ]; then
+            echo "CREATE KEYSPACE IF NOT EXISTS dox WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 3 };"
+        fi
+        echo "USE dox;"
+        $RUN_PATH/parse-json.py -t create -f $1
+
+}
+
+#### Functions - End    ####
+
+# Check arguements
+if [ "$#" -lt 1 ] || [ "$#" -gt 3 ]; then
+        usage
+fi
+
+main $1 $2 $3
diff --git a/openecomp-be/tools/build/scripts/parse-json.py b/openecomp-be/tools/build/scripts/parse-json.py
new file mode 100644
index 0000000..46537ce
--- /dev/null
+++ b/openecomp-be/tools/build/scripts/parse-json.py
@@ -0,0 +1,83 @@
+#!/usr/bin/python
+
+##############################################################################
+###
+### parse-json.py
+###
+### A utility to parse a cassnadra-commands file and return the commands per type
+### An Example for a json file:
+###     {
+###         "create":{
+###                 "choice_or_other":"CREATE TYPE IF NOT EXISTS choice_or_other (results text)",
+###                 "vendor_license_model": "CREATE TABLE IF NOT EXISTS vendor_license_model (vlm_id text PRIMARY KEY, name text, description text, icon text)",
+###                 "license_agreement": "CREATE TABLE IF NOT EXISTS license_agreement (vlm_id text, la_id text, name text, description text, type text, contract text, req_const text, fg_ids set<text>, PRIMARY KEY (vlm_id, la_id))",
+###                 "feature_group": "CREATE TABLE IF NOT EXISTS feature_group (vlm_id text, fg_id text, name text, description text, ep_ids set<text>, lkg_ids set<text>, refd_by_las set<text>, PRIMARY KEY (vlm_id, fg_id))",
+###                 "license_key_group": "CREATE TABLE IF NOT EXISTS license_key_group (vlm_id text,lkg_id text,name text,description text, type text, operational_scope text, ref_fgs set<text>,PRIMARY KEY (vlm_id, lkg_id))",
+###         }
+###     }
+###
+### The return for "create" will be:
+###                 CREATE TYPE IF NOT EXISTS choice_or_other (results text)
+###                 CREATE TABLE IF NOT EXISTS vendor_license_model (vlm_id text PRIMARY KEY, name text, description text, icon text)
+###                 CREATE TABLE IF NOT EXISTS license_agreement (vlm_id text, la_id text, name text, description text, type text, contract text, req_const text, fg_ids set<text>, PRIMARY KEY (vlm_id, la_id))
+###                 CREATE TABLE IF NOT EXISTS feature_group (vlm_id text, fg_id text, name text, description text, ep_ids set<text>, lkg_ids set<text>, refd_by_las set<text>, PRIMARY KEY (vlm_id, fg_id))
+###                 CREATE TABLE IF NOT EXISTS license_key_group (vlm_id text,lkg_id text,name text,description text, type text, operational_scope text, ref_fgs set<text>,PRIMARY KEY (vlm_id, lkg_id))
+### Usage:
+###
+###    parse-json.py -t create -f cassandra-commands.json
+###
+### For example:
+###
+###
+### Author: Avi Ziv
+### Version 1.0
+### Date: 3 May 2016
+###
+##############################################################################
+
+import sys, getopt
+import json as json
+from collections import OrderedDict
+
+
+def readJsonFile(file, type):
+  with open(file, 'r') as f:
+     data = json.load(f, object_pairs_hook=OrderedDict)
+     return data[type]
+
+def printJsonTypeEntries(jsonData):
+        for i in jsonData.keys():
+                print jsonData[i] + ';'
+
+
+def usage():
+    print 'parseJsonFile.py [-f <json-file> & -t <cql-type: drop|create|insert|update|select]'
+
+def main(argv):
+    action = ''
+
+    try:
+        opts, args = getopt.getopt(argv, "h:f:t:")
+    except getopt.GetoptError:
+        usage()
+        sys.exit(2)
+    for opt, arg in opts:
+        if opt == '-h':
+            usage()
+            sys.exit()
+        elif opt == '-f':
+            jsonFile = arg
+            action = 'file'
+        elif opt == '-t':
+            type = arg
+
+    if action == 'file':
+        sJson = readJsonFile(jsonFile, type)
+        printJsonTypeEntries(sJson)
+        sys.exit()
+    else:
+        usage()
+
+
+if __name__ == "__main__":
+    main(sys.argv[1:])