Merge "Add checkClusterTimeSync method"
diff --git a/src/com/mirantis/mk/Openstack.groovy b/src/com/mirantis/mk/Openstack.groovy
index 284adec..c195c2e 100644
--- a/src/com/mirantis/mk/Openstack.groovy
+++ b/src/com/mirantis/mk/Openstack.groovy
@@ -162,15 +162,17 @@
 }
 
 /**
- * Create new OpenStack Heat stack
+ * Create new OpenStack Heat stack. Will wait for action to be complited in
+ * specified amount of time (by default 120min)
  *
  * @param env          Connection parameters for OpenStack API endpoint
  * @param template     HOT template for the new Heat stack
  * @param environment  Environmentale parameters of the new Heat stack
  * @param name         Name of the new Heat stack
  * @param path         Optional path to the custom virtualenv
+ * @param timeout      Optional number in minutes to wait for stack action is applied.
  */
-def createHeatStack(client, name, template, params = [], environment = null, path = null, action="create") {
+def createHeatStack(client, name, template, params = [], environment = null, path = null, action="create", timeout=120) {
     def python = new com.mirantis.mk.Python()
     def templateFile = "${env.WORKSPACE}/template/template/${template}.hot"
     def envFile
@@ -192,41 +194,17 @@
     }
 
     def cmd
-    def waitState
+    def cmd_args = "-t ${templateFile} -e ${envFile} --timeout ${timeout} --wait ${name}"
 
     if (action == "create") {
-        cmd = "heat stack-create -f ${templateFile} -e ${envFile} ${name}"
-        waitState = "CREATE_COMPLETE"
+        cmd = "openstack stack create ${cmd_args}"
     } else {
-        cmd = "heat stack-update -f ${templateFile} -e ${envFile} ${name}"
-        waitState = "UPDATE_COMPLETE"
+        cmd = "openstack stack update ${cmd_args}"
     }
 
     dir("${env.WORKSPACE}/template/template") {
-        outputTable = runOpenstackCommand(cmd, client, path)
+        def out = runOpenstackCommand(cmd, client, path)
     }
-
-    output = python.parseTextTable(outputTable, 'item', 'prettytable', path)
-
-    def heatStatusCheckerCount = 1
-    while (heatStatusCheckerCount <= 250) {
-        status = getHeatStackStatus(client, name, path)
-        echo("[Heat Stack] Status: ${status}, Check: ${heatStatusCheckerCount}")
-
-        if (status.contains('CREATE_FAILED')) {
-            info = getHeatStackInfo(client, name, path)
-            throw new Exception(info.stack_status_reason)
-
-        } else if (status.contains(waitState)) {
-            info = getHeatStackInfo(client, name, path)
-            echo(info.stack_status_reason)
-            break
-        }
-
-        sleep(30)
-        heatStatusCheckerCount++
-    }
-    echo("[Heat Stack] Status: ${status}")
 }
 
 /**
@@ -802,4 +780,4 @@
 
     salt.runSaltProcessStep(env, "I@galera:master and not ${lastNodeTarget}", 'service.start', ['mysql'])
     salt.runSaltProcessStep(env, "I@galera:slave and not ${lastNodeTarget}", 'service.start', ['mysql'])
-}
\ No newline at end of file
+}
diff --git a/src/com/mirantis/mk/Orchestrate.groovy b/src/com/mirantis/mk/Orchestrate.groovy
index 29a8626..5f2700a 100644
--- a/src/com/mirantis/mk/Orchestrate.groovy
+++ b/src/com/mirantis/mk/Orchestrate.groovy
@@ -560,9 +560,19 @@
     salt.enforceStateWithExclude([saltId: master, target: "I@opencontrail:collector ${extra_tgt}", state: "opencontrail", excludedStates: "opencontrail.client"])
 
     salt.enforceStateWithTest([saltId: master, target: "( I@opencontrail:control or I@opencontrail:collector ) ${extra_tgt}", state: 'docker.client', testTargetMatcher: "I@docker:client and I@opencontrail:control ${extra_tgt}"])
+}
 
-    // Waiting until Contrail API is started
-    salt.runSaltProcessStep(master, "I@opencontrail:database:id:1 ${extra_tgt}", 'contrail_health.get_api_status')
+
+def checkContrailApiReadiness(master, extra_tgt = '') {
+    def common = new com.mirantis.mk.Common()
+    def salt = new com.mirantis.mk.Salt()
+
+    def apiCheckResult = salt.getReturnValues(salt.runSaltProcessStep(master, "I@opencontrail:control:role:primary ${extra_tgt}", 'contrail_health.get_api_status', ['wait_for=900', 'tries=50']))
+    if (!apiCheckResult){
+        throw new Exception("Contrail is not working after deployment: contrail-api service is not in healthy state")
+    } else {
+        common.infoMsg('Contrail API is ready to service requests')
+    }
 }
 
 
diff --git a/src/com/mirantis/mk/Test.groovy b/src/com/mirantis/mk/Test.groovy
index 8c663e5..d9de536 100644
--- a/src/com/mirantis/mk/Test.groovy
+++ b/src/com/mirantis/mk/Test.groovy
@@ -411,7 +411,7 @@
     def salt = new com.mirantis.mk.Salt()
     def dockerPackagesPillar = salt.getPillar(master, target, 'docker:host:pkgs')
     def dockerPackages = salt.getReturnValues(dockerPackagesPillar) ?: ['docker.io']
-    salt.runSaltProcessStep(master, target, 'pkg.install', dockerPackages)
+    salt.runSaltProcessStep(master, target, 'pkg.install', [dockerPackages.join(',')])
 }