Add mk libraries

Change-Id: I829b299b6329e8f4d4424c89717d432513d1eece
diff --git a/src/com/mirantis/mk/openstack.groovy b/src/com/mirantis/mk/openstack.groovy
new file mode 100644
index 0000000..1d6bcca
--- /dev/null
+++ b/src/com/mirantis/mk/openstack.groovy
@@ -0,0 +1,296 @@
+package com.mirantis.mk
+
+/**
+ *
+ * Openstack functions
+ *
+ */
+
+/**
+ * Install OpenStack service clients in isolated environment
+ *
+ * @param path        Path where virtualenv is created
+ * @param version     Version of the OpenStack clients
+ */
+
+def setupOpenstackVirtualenv(path, version = 'kilo'){
+    def python = new com.mirantis.mk.python()
+
+    def openstack_kilo_packages = [
+        'python-cinderclient>=1.3.1,<1.4.0',
+        'python-glanceclient>=0.19.0,<0.20.0',
+        'python-heatclient>=0.6.0,<0.7.0',
+        'python-keystoneclient>=1.6.0,<1.7.0',
+        'python-neutronclient>=2.2.6,<2.3.0',
+        'python-novaclient>=2.19.0,<2.20.0',
+        'python-swiftclient>=2.5.0,<2.6.0',
+        'oslo.config>=2.2.0,<2.3.0',
+        'oslo.i18n>=2.3.0,<2.4.0',
+        'oslo.serialization>=1.8.0,<1.9.0',
+        'oslo.utils>=1.4.0,<1.5.0',
+    ]
+
+    def openstack_latest_packages = openstack_kilo_packages
+
+    if(version == 'kilo') {
+        requirements = openstack_kilo_packages
+    }
+    else if(version == 'liberty') {
+        requirements = openstack_kilo_packages
+    }
+    else if(version == 'mitaka') {
+        requirements = openstack_kilo_packages
+    }
+    else {
+        requirements = openstack_latest_packages
+    }
+    python.setupVirtualenv(path, 'python2', requirements)
+}
+
+/**
+ * create connection to OpenStack API endpoint
+ *
+ * @param url             OpenStack API endpoint address
+ * @param credentialsId   Credentials to the OpenStack API
+ * @param project         OpenStack project to connect to
+ */
+@NonCPS
+def createOpenstackEnv(url, credentialsId, project) {
+    def common = new com.mirantis.mk.common()
+    creds = common.getPasswordCredentials(credentialsId)
+    params = [
+        "OS_USERNAME": creds.username,
+        "OS_PASSWORD": creds.password.toString(),
+        "OS_TENANT_NAME": project,
+        "OS_AUTH_URL": url,
+        "OS_AUTH_STRATEGY": "keystone"
+    ]
+    res = ""
+    for ( e in params ) {
+        res = "${res}export ${e.key}=${e.value}\n"
+    }
+    writeFile file: "${env.WORKSPACE}/keystonerc", text: res
+    return "${env.WORKSPACE}/keystonerc"
+    //return res.substring(1)
+}
+
+/**
+ * Run command with OpenStack env params and optional python env
+ *
+ * @param cmd    Command to be executed
+ * @param env    Environmental parameters with endpoint credentials
+ * @param path   Optional path to virtualenv with specific clients
+ */
+def runOpenstackCommand(cmd, venv, path = null) {
+    def python = new com.mirantis.mk.python()
+    openstackCmd = ". ${venv}; ${cmd}"
+    if (path) {
+        output = python.runVirtualenvCommand(path, openstackCmd)
+    }
+    else {
+        echo("[Command]: ${openstackCmd}")
+        output = sh (
+            script: openstackCmd,
+            returnStdout: true
+        ).trim()
+    }
+    return output
+}
+
+/**
+ * Get OpenStack Keystone token for current credentials
+ *
+ * @param env          Connection parameters for OpenStack API endpoint
+ * @param path         Optional path to the custom virtualenv
+ */
+def getKeystoneToken(client, path = null) {
+    def python = new com.mirantis.mk.python()
+    cmd = "keystone token-get"
+    outputTable = runOpenstackCommand(cmd, client, path)
+    output = python.parseTextTable(outputTable, 'item', 'prettytable')
+    return output
+}
+
+/**
+ * Get OpenStack Keystone token for current credentials
+ *
+ * @param env          Connection parameters for OpenStack API endpoint
+ * @param path         Optional path to the custom virtualenv
+ */
+def createHeatEnv(file, environment = [], original_file = null) {
+    if (original_file) {
+        envString = readFile file: original_file
+    }
+    else {
+        envString = "parameters:\n"
+    }
+    for ( int i = 0; i < environment.size; i++ ) {
+        envString = "${envString}  ${environment.get(i).get(0)}: ${environment.get(i).get(1)}\n"
+    }
+    writeFile file: file, text: envString
+}
+
+/**
+ * Create new OpenStack Heat stack
+ *
+ * @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
+ */
+def createHeatStack(client, name, template, params = [], environment = null, path = null) {
+    def python = new com.mirantis.mk.python()
+    templateFile = "${env.WORKSPACE}/template/template/${template}.hot"
+    if (environment) {
+        envFile = "${env.WORKSPACE}/template/env/${template}/${name}.env"
+        envSource = "${env.WORKSPACE}/template/env/${template}/${environment}.env"
+        createHeatEnv(envFile, params, envSource)
+    }
+    else {
+        envFile = "${env.WORKSPACE}/template/${name}.env"
+        createHeatEnv(envFile, params)
+    }
+    cmd = "heat stack-create -f ${templateFile} -e ${envFile} ${name}"
+    dir("${env.WORKSPACE}/template/template") {
+        outputTable = runOpenstackCommand(cmd, client, path)
+    }
+    output = python.parseTextTable(outputTable, 'item', 'prettytable')
+
+    i = 1
+    while (true) {
+        status = getHeatStackStatus(client, name, path)
+        echo("[Heat Stack] Status: ${status}, Check: ${i}")
+        if (status == 'CREATE_FAILED') {
+            info = getHeatStackInfo(client, name, path)
+            throw new Exception(info.stack_status_reason)
+        }
+        else if (status == 'CREATE_COMPLETE') {
+            info = getHeatStackInfo(client, name, path)
+            echo(info.stack_status_reason)
+            break
+        }
+        sh('sleep 5s')
+        i++
+    }
+    echo("[Heat Stack] Status: ${status}")
+}
+
+/**
+ * Get life cycle status for existing OpenStack Heat stack
+ *
+ * @param env          Connection parameters for OpenStack API endpoint
+ * @param name         Name of the managed Heat stack instance
+ * @param path         Optional path to the custom virtualenv
+ */
+def getHeatStackStatus(client, name, path = null) {
+    cmd = 'heat stack-list | awk -v stack='+name+' \'{if ($4==stack) print $6}\''
+    return runOpenstackCommand(cmd, client, path)
+}
+
+/**
+ * Get info about existing OpenStack Heat stack
+ *
+ * @param env          Connection parameters for OpenStack API endpoint
+ * @param name         Name of the managed Heat stack instance
+ * @param path         Optional path to the custom virtualenv
+ */
+def getHeatStackInfo(env, name, path = null) {
+    def python = new com.mirantis.mk.python()
+    cmd = "heat stack-show ${name}"
+    outputTable = runOpenstackCommand(cmd, env, path)
+    output = python.parseTextTable(outputTable, 'item', 'prettytable')
+    return output
+}
+
+/**
+ * Get existing OpenStack Heat stack output parameter
+ *
+ * @param env          Connection parameters for OpenStack API endpoint
+ * @param name         Name of the managed Heat stack
+ * @param parameter    Name of the output parameter
+ * @param path         Optional path to the custom virtualenv
+ */
+def getHeatStackOutputParam(env, name, outputParam, path = null) {
+    cmd = "heat output-show ${name} ${outputParam}"
+    output = runOpenstackCommand(cmd, env, path)
+    return output.substring(1, output.length()-1)
+}
+
+/**
+ * List all resources from existing OpenStack Heat stack
+ *
+ * @param env          Connection parameters for OpenStack API endpoint
+ * @param name         Name of the managed Heat stack instance
+ * @param path         Optional path to the custom virtualenv
+ */
+def getHeatStackResources(env, name, path = null) {
+    def python = new com.mirantis.mk.python()
+    cmd = "heat resource-list ${name}"
+    outputTable = runOpenstackCommand(cmd, env, path)
+    output = python.parseTextTable(outputTable, 'list', 'prettytable')
+    return output
+}
+
+/**
+ * Get info about resource from existing OpenStack Heat stack
+ *
+ * @param env          Connection parameters for OpenStack API endpoint
+ * @param name         Name of the managed Heat stack instance
+ * @param path         Optional path to the custom virtualenv
+ */
+def getHeatStackResourceInfo(env, name, resource, path = null) {
+    def python = new com.mirantis.mk.python()
+    cmd = "heat resource-show ${name} ${resource}"
+    outputTable = runOpenstackCommand(cmd, env, path)
+    output = python.parseTextTable(outputTable, 'item', 'prettytable')
+    return output
+}
+
+/**
+ * Update existing OpenStack Heat stack
+ *
+ * @param env          Connection parameters for OpenStack API endpoint
+ * @param name         Name of the managed Heat stack instance
+ * @param path         Optional path to the custom virtualenv
+ */
+def updateHeatStack(env, name, path = null) {
+    def python = new com.mirantis.mk.python()
+    cmd = "heat stack-update ${name}"
+    outputTable = runOpenstackCommand(cmd, env, path)
+    output = python.parseTextTable(outputTable, 'item', 'prettytable')
+    return output
+}
+
+/**
+ * Delete existing OpenStack Heat stack
+ *
+ * @param env          Connection parameters for OpenStack API endpoint
+ * @param name         Name of the managed Heat stack instance
+ * @param path         Optional path to the custom virtualenv
+ */
+def deleteHeatStack(env, name, path = null) {
+    cmd = "heat stack-delete ${name}"
+    outputTable = runOpenstackCommand(cmd, env, path)
+}
+
+/**
+ * Return list of servers from OpenStack Heat stack
+ *
+ * @param env          Connection parameters for OpenStack API endpoint
+ * @param name         Name of the managed Heat stack instance
+ * @param path         Optional path to the custom virtualenv
+ */
+def getHeatStackServers(env, name, path = null) {
+    resources = heatGetStackResources(env, name, path)
+    servers = []
+    for (resource in resources) {
+        if (resource.resource_type == 'OS::Nova::Server') {
+            resourceName = resource.resource_name
+            server = heatGetStackResourceInfo(env, name, resourceName, path)
+            servers.add(server.attributes.name)
+        }
+    }
+    echo("[Stack ${name}] Servers: ${servers}")
+    return servers
+}