Merge "Call restore state from Salt master"
diff --git a/generate-cookiecutter-products.groovy b/generate-cookiecutter-products.groovy
index 553029e..0924951 100644
--- a/generate-cookiecutter-products.groovy
+++ b/generate-cookiecutter-products.groovy
@@ -25,7 +25,7 @@
 // options from CC contexts
 // currently, just mix them together in one set
 def testCfg01ExtraFormulas = 'glusterfs jenkins logrotate maas ntp rsyslog fluentd telegraf prometheus ' +
-                             'grafana backupninja auditd'
+                             'grafana backupninja'
 
 
 timeout(time: 2, unit: 'HOURS') {
@@ -58,6 +58,10 @@
         user = env.BUILD_USER_ID
       }
 
+      if (mcpVersion != '2018.4.0') {
+        testCfg01ExtraFormulas += ' auditd'
+      }
+
       currentBuild.description = clusterName
       print("Using context:\n" + COOKIECUTTER_TEMPLATE_CONTEXT)
 
diff --git a/git-merge-branches-pipeline.groovy b/git-merge-branches-pipeline.groovy
deleted file mode 100644
index d1c3ee2..0000000
--- a/git-merge-branches-pipeline.groovy
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * Git merge branches pipeline
- * REPO_URL - Repository URL
- * TARGET_BRANCH - Target branch for merging
- * SOURCE_BRANCH - The branch will be merged to TARGET_BRANCH
- * CREDENTIALS_ID - Used credentails ID
- *
-**/
-
-def common = new com.mirantis.mk.Common()
-def git = new com.mirantis.mk.Git()
-timeout(time: 12, unit: 'HOURS') {
-  node {
-    try{
-      stage("checkout") {
-        git.checkoutGitRepository('repo', REPO_URL, TARGET_BRANCH, IMAGE_CREDENTIALS_ID)
-      }
-      stage("merge") {
-        dir("repo"){
-          sh("git fetch origin/${SOURCE_BRANCH} && git merge ${SOURCE_BRANCH} && git push origin ${TARGET_BRANCH}")
-        }
-      }
-    } catch (Throwable e) {
-       // If there was an error or exception thrown, the build failed
-       currentBuild.result = "FAILURE"
-       currentBuild.description = currentBuild.description ? e.message + " " + currentBuild.description : e.message
-       throw e
-    }
-  }
-}
-
diff --git a/promote-vcp-images.groovy b/promote-vcp-images.groovy
new file mode 100644
index 0000000..181eafa
--- /dev/null
+++ b/promote-vcp-images.groovy
@@ -0,0 +1,134 @@
+/**
+ *
+ * Promote VCP(qcow2) images
+ *
+ * Expected parameters:
+ *   VCP_IMAGE_LIST - multiline with qcow2 file names
+ *   TAG            - Target tag of image.Possible are: "nightly|testing|proposed|201X.X.X"
+ *   SOURCE_TAG     - Initial tag to be tagged with TAG. Will replace SUBS_SOURCE_VCP_IMAGE_TAG in VCP_IMAGE_LIST
+ *   UPLOAD_URL     - WebDav url with creds, from\to download images
+ *
+ */
+
+def common = new com.mirantis.mk.Common()
+def jenkinsUtils = new com.mirantis.mk.JenkinsUtils()
+
+// Better to chose slave with ssd and fast network to webDav host
+slaveNode = env.SLAVE_NODE ?: 'jsl23.mcp.mirantis.net'
+def job_env = env.getEnvironment().findAll { k, v -> v }
+def verify = job_env.VERIFY_DOWNLOAD ?: true
+
+
+timeout(time: 6, unit: 'HOURS') {
+    node(slaveNode) {
+
+        String description = ''
+        insufficientPermissions = false
+        try {
+            // Pre-run verify
+            // promote is restricted to users in aptly-promote-users LDAP group
+            if (!jenkinsUtils.currentUserInGroups(["mcp-cicd-admins", "aptly-promote-users"])) {
+                insufficientPermissions = true
+                error(String.format("You don't have permissions to make promote from source:%s to target:%s! Only CI/CD and QA team can perform promote.", job_env.SOURCE_TAG, job_env.TAG))
+            }
+            // Check for required opts
+            for (opt in ['UPLOAD_URL', 'SOURCE_TAG', 'TAG', 'VCP_IMAGE_LIST']) {
+                if (!job_env.get(opt, null)) {
+                    error("Invalid input params, at least ${opt} param missing")
+                }
+            }
+            def images = job_env.VCP_IMAGE_LIST.trim().tokenize()
+            for (image in images) {
+                if (image.startsWith('#')) {
+                    common.warningMsg("Skipping image ${image}")
+                    continue
+                }
+                common.infoMsg("Replacing SUBS_SOURCE_VCP_IMAGE_TAG => ${job_env.SOURCE_TAG}")
+                sourceImage = image.replace('SUBS_SOURCE_VCP_IMAGE_TAG', job_env.SOURCE_TAG)
+                targetImage = image.replace('SUBS_SOURCE_VCP_IMAGE_TAG', job_env.TAG)
+
+                // TODO: normalize url's?
+                sourceImageUrl = job_env.UPLOAD_URL + '/' + sourceImage
+                sourceImageMd5Url = job_env.UPLOAD_URL + '/' + sourceImage + '.md5'
+                targetImageUrl = job_env.UPLOAD_URL + '/' + targetImage
+                targetImageMd5Url = job_env.UPLOAD_URL + '/' + targetImage + '.md5'
+
+                common.infoMsg("Attempt to download: ${sourceImage} => ${targetImage}")
+                common.retry(3, 5) {
+                    sh(script: "wget --progress=dot:giga --auth-no-challenge -O ${targetImage} ${sourceImageUrl}")
+                }
+                def targetImageMd5 = common.cutOrDie("md5sum ${targetImage} | tee ${targetImage}.md5", 0)
+                if (verify.toBoolean()) {
+                    common.infoMsg("Checking md5's ")
+                    sh(script: "wget --progress=dot:giga --auth-no-challenge -O ${targetImage}_source_md5 ${sourceImageMd5Url}")
+                    def sourceImageMd5 = readFile(file: "${targetImage}_source_md5").tokenize(' ')[0]
+                    // Compare downloaded and remote files
+                    if (sourceImageMd5 != targetImageMd5) {
+                        error("Image ${targetImage} md5sum verify failed!")
+                    } else {
+                        common.infoMsg("sourceImageMd5: ${sourceImageMd5} == target to upload ImageMd5: ${targetImageMd5}")
+                    }
+                    // Compare downloaded file, and remote file-to-be-promoted. If same - no sense to promote same file
+                    remoteImageMd5Status = sh(script: "wget --progress=dot:giga --auth-no-challenge -O ${targetImage}_expected_target_md5 ${targetImageMd5Url}", returnStatus: true)
+                    if (remoteImageMd5Status == '8') {
+                        common.infoMsg("target to upload ImageMd5 file not even exist.Continue..")
+                    } else {
+                        def remoteImageMd5 = readFile(file: "${targetImage}_expected_target_md5").tokenize(' ')[0]
+                        if (sourceImageMd5 == remoteImageMd5) {
+                            common.infoMsg("sourceImageMd5: ${sourceImageMd5} and target to upload ImageMd5: ${targetImageMd5} are same")
+                            common.warningMsg("Skipping to upload: ${targetImage} since it already same")
+                            description += "Skipping to upload: ${targetImage} since it already same\n"
+                            continue
+                        }
+                    }
+                    common.infoMsg("Check, that we are not going to overwrite released file..")
+                    if (['proposed', 'testing', 'nightly'].contains(job_env.TAG)) {
+                        common.infoMsg("Uploading to ${job_env.TAG} looks safe..")
+                    } else if (['stable'].contains(job_env.TAG)) {
+                        common.warningMsg("Uploading to ${job_env.TAG} not safe! But still possible")
+                    } else {
+                        common.warningMsg("Looks like uploading to new release: ${job_env.TAG}. Checking, that it is not exist yet..")
+                        remoteImageStatus = ''
+                        remoteImageStatus = sh(script: "wget  --auth-no-challenge --spider ${targetImageUrl} 2>/dev/null", returnStatus: true)
+                        // wget return code 8 ,if file not exist
+                        if (remoteImageStatus != '8') {
+                            error("Attempt to overwrite existing release! Target: ${targetImage} already exist!")
+                        }
+                    }
+                }
+
+                common.infoMsg("Attempt to UPLOAD: ${targetImage} => ${targetImageUrl}")
+                //
+                def uploadImageStatus = ''
+                def uploadImageMd5Status = ''
+                common.retry(3, 5) {
+                    uploadImageStatus = sh(script: "curl -f -T ${targetImage} ${job_env.UPLOAD_URL}", returnStatus: true)
+                    if (uploadImageStatus != 0) {
+                        error("Uploading file: ${targetImage} failed!")
+                    }
+                }
+                uploadImageMd5Status = sh(script: "curl -f -T ${targetImage}.md5 ${job_env.UPLOAD_URL}", returnStatus: true)
+                if (uploadImageMd5Status != 0) {
+                    error("Uploading file: ${targetImage}.md5 failed!")
+                }
+
+                description += "<a href='http://apt.mirantis.net:8085/images/${targetImage}'>${job_env.SOURCE_TAG}=>${targetImage}</a>"
+            }
+            currentBuild.description = description
+        } catch (Throwable e) {
+            // If there was an error or exception thrown, the build failed
+            if (insufficientPermissions) {
+                currentBuild.result = "ABORTED"
+                currentBuild.description = "Promote aborted due to insufficient permissions"
+            } else {
+                currentBuild.result = "FAILURE"
+                currentBuild.description = currentBuild.description ? e.message + " " + currentBuild.description : e.message
+            }
+            throw e
+        }
+        finally {
+            common.infoMsg("Cleanup..")
+            sh(script: 'find . -mindepth 1 -delete > /dev/null || true')
+        }
+    }
+}
diff --git a/release-mcp-version.groovy b/release-mcp-version.groovy
index b1b3d77..faf891c 100644
--- a/release-mcp-version.groovy
+++ b/release-mcp-version.groovy
@@ -16,92 +16,104 @@
  *   DOCKER_IMAGES
  *   GIT_CREDENTIALS
  *   GIT_REPO_LIST
+ *   VCP_IMAGE_LIST - list of images
+ *   RELEASE_VCP_IMAGES - boolean
  *   EMAIL_NOTIFY
  *   NOTIFY_RECIPIENTS
  *   NOTIFY_TEXT
  *
-*/
+ */
 
 common = new com.mirantis.mk.Common()
 git = new com.mirantis.mk.Git()
 
-def triggerAptlyPromoteJob(aptlyUrl, components, diffOnly, dumpPublish, packages, recreate, source, storages, target){
-  build job: "aptly-promote-all-testing-stable", parameters: [
-    [$class: 'StringParameterValue', name: 'APTLY_URL', value: aptlyUrl],
-    [$class: 'StringParameterValue', name: 'COMPONENTS', value: components],
-    [$class: 'BooleanParameterValue', name: 'DIFF_ONLY', value: diffOnly],
-    [$class: 'BooleanParameterValue', name: 'DUMP_PUBLISH', value: dumpPublish],
-    [$class: 'StringParameterValue', name: 'PACKAGES', value: packages],
-    [$class: 'BooleanParameterValue', name: 'RECREATE', value: recreate],
-    [$class: 'StringParameterValue', name: 'SOURCE', value: source],
-    [$class: 'StringParameterValue', name: 'STORAGES', value: storages],
-    [$class: 'StringParameterValue', name: 'TARGET', value: target],
-  ]
+def triggerAptlyPromoteJob(aptlyUrl, components, diffOnly, dumpPublish, packages, recreate, source, storages, target) {
+    build job: "aptly-promote-all-testing-stable", parameters: [
+        [$class: 'StringParameterValue', name: 'APTLY_URL', value: aptlyUrl],
+        [$class: 'StringParameterValue', name: 'COMPONENTS', value: components],
+        [$class: 'BooleanParameterValue', name: 'DIFF_ONLY', value: diffOnly],
+        [$class: 'BooleanParameterValue', name: 'DUMP_PUBLISH', value: dumpPublish],
+        [$class: 'StringParameterValue', name: 'PACKAGES', value: packages],
+        [$class: 'BooleanParameterValue', name: 'RECREATE', value: recreate],
+        [$class: 'StringParameterValue', name: 'SOURCE', value: source],
+        [$class: 'StringParameterValue', name: 'STORAGES', value: storages],
+        [$class: 'StringParameterValue', name: 'TARGET', value: target],
+    ]
 }
 
 def triggerDockerMirrorJob(dockerCredentials, dockerRegistryUrl, targetTag, imageList, sourceImageTag) {
-  build job: "docker-images-mirror", parameters: [
-    [$class: 'StringParameterValue', name: 'TARGET_REGISTRY_CREDENTIALS_ID', value: dockerCredentials],
-    [$class: 'StringParameterValue', name: 'REGISTRY_URL', value: dockerRegistryUrl],
-    [$class: 'StringParameterValue', name: 'IMAGE_TAG', value: targetTag],
-    [$class: 'StringParameterValue', name: 'IMAGE_LIST', value: imageList],
-    [$class: 'StringParameterValue', name: 'SOURCE_IMAGE_TAG', value: sourceImageTag],
-  ]
+    build job: "docker-images-mirror", parameters: [
+        [$class: 'StringParameterValue', name: 'TARGET_REGISTRY_CREDENTIALS_ID', value: dockerCredentials],
+        [$class: 'StringParameterValue', name: 'REGISTRY_URL', value: dockerRegistryUrl],
+        [$class: 'StringParameterValue', name: 'IMAGE_TAG', value: targetTag],
+        [$class: 'StringParameterValue', name: 'IMAGE_LIST', value: imageList],
+        [$class: 'StringParameterValue', name: 'SOURCE_IMAGE_TAG', value: sourceImageTag],
+    ]
 }
 
 def triggerMirrorRepoJob(snapshotId, snapshotName) {
-  build job: "mirror-snapshot-name-all", parameters: [
-    [$class: 'StringParameterValue', name: 'SNAPSHOT_NAME', value: snapshotName],
-    [$class: 'StringParameterValue', name: 'SNAPSHOT_ID', value: snapshotId],
-  ]
+    build job: "mirror-snapshot-name-all", parameters: [
+        [$class: 'StringParameterValue', name: 'SNAPSHOT_NAME', value: snapshotName],
+        [$class: 'StringParameterValue', name: 'SNAPSHOT_ID', value: snapshotId],
+    ]
 }
 
 def triggerGitTagJob(gitRepoList, gitCredentials, tag, sourceTag) {
-  build job: "tag-git-repos-stable", parameters: [
-    [$class: 'StringParameterValue', name: 'GIT_REPO_LIST', value: gitRepoList],
-    [$class: 'StringParameterValue', name: 'GIT_CREDENTIALS', value: gitCredentials],
-    [$class: 'StringParameterValue', name: 'TAG', value: tag],
-    [$class: 'StringParameterValue', name: 'SOURCE_TAG', value: sourceTag],
-  ]
+    build job: "tag-git-repos-stable", parameters: [
+        [$class: 'StringParameterValue', name: 'GIT_REPO_LIST', value: gitRepoList],
+        [$class: 'StringParameterValue', name: 'GIT_CREDENTIALS', value: gitCredentials],
+        [$class: 'StringParameterValue', name: 'TAG', value: tag],
+        [$class: 'StringParameterValue', name: 'SOURCE_TAG', value: sourceTag],
+    ]
+}
+
+def triggerPromoteVCPJob(VcpImageList, tag, sourceTag) {
+    build job: "promote-vcp-images-all", parameters: [
+        [$class: 'StringParameterValue', name: 'VCP_IMAGE_LIST', value: VcpImageList],
+        [$class: 'StringParameterValue', name: 'TAG', value: tag],
+        [$class: 'StringParameterValue', name: 'SOURCE_TAG', value: sourceTag]
+    ]
 }
 
 timeout(time: 12, unit: 'HOURS') {
-  node() {
-    try {
-      stage("Promote"){
-        if(RELEASE_APTLY.toBoolean())
-        {
-          common.infoMsg("Promoting Aptly")
-          triggerAptlyPromoteJob(APTLY_URL, 'all', false, true, 'all', false, "(.*)/${SOURCE_REVISION}", APTLY_STORAGES, "{0}/${TARGET_REVISION}")
-        }
+    node() {
+        try {
+            stage("Promote") {
+                if (RELEASE_APTLY.toBoolean()) {
+                    common.infoMsg("Promoting Aptly")
+                    triggerAptlyPromoteJob(APTLY_URL, 'all', false, true, 'all', false, "(.*)/${SOURCE_REVISION}", APTLY_STORAGES, "{0}/${TARGET_REVISION}")
+                }
 
-        if(RELEASE_DEB_MIRRORS.toBoolean()){
-          common.infoMsg("Promoting Debmirrors")
-          triggerMirrorRepoJob(SOURCE_REVISION, TARGET_REVISION)
-        }
+                if (RELEASE_DEB_MIRRORS.toBoolean()) {
+                    common.infoMsg("Promoting Debmirrors")
+                    triggerMirrorRepoJob(SOURCE_REVISION, TARGET_REVISION)
+                }
 
-        if(RELEASE_DOCKER.toBoolean())
-        {
-          common.infoMsg("Promoting Docker images")
-          triggerDockerMirrorJob(DOCKER_CREDENTIALS, DOCKER_URL, TARGET_REVISION, DOCKER_IMAGES, SOURCE_REVISION)
-        }
+                if (RELEASE_DOCKER.toBoolean()) {
+                    common.infoMsg("Promoting Docker images")
+                    triggerDockerMirrorJob(DOCKER_CREDENTIALS, DOCKER_URL, TARGET_REVISION, DOCKER_IMAGES, SOURCE_REVISION)
+                }
 
-        if(RELEASE_GIT.toBoolean())
-        {
-          common.infoMsg("Promoting Git repositories")
-          triggerGitTagJob(GIT_REPO_LIST, GIT_CREDENTIALS, TARGET_REVISION, SOURCE_REVISION)
+                if (RELEASE_GIT.toBoolean()) {
+                    common.infoMsg("Promoting Git repositories")
+                    triggerGitTagJob(GIT_REPO_LIST, GIT_CREDENTIALS, TARGET_REVISION, SOURCE_REVISION)
 
-        }
-        if (EMAIL_NOTIFY.toBoolean()) {
-          emailext(to: NOTIFY_RECIPIENTS,
-            body: NOTIFY_TEXT,
-            subject: "MCP Promotion has been done")
-        }
-      }
-      } catch (Throwable e) {
+                }
+                if (RELEASE_VCP_IMAGES.toBoolean()) {
+                    common.infoMsg("Promoting VCP images")
+                    triggerPromoteVCPJob(VCP_IMAGE_LIST, TARGET_REVISION, SOURCE_REVISION)
+
+                }
+                if (EMAIL_NOTIFY.toBoolean()) {
+                    emailext(to: NOTIFY_RECIPIENTS,
+                        body: NOTIFY_TEXT,
+                        subject: "MCP Promotion has been done")
+                }
+            }
+        } catch (Throwable e) {
             // If there was an error or exception thrown, the build failed
             currentBuild.result = "FAILURE"
             throw e
-          }
         }
-      }
+    }
+}
diff --git a/rollout-config-change.groovy b/rollout-config-change.groovy
deleted file mode 100644
index dcb9034..0000000
--- a/rollout-config-change.groovy
+++ /dev/null
@@ -1,96 +0,0 @@
-
-/**
- * Rollout changes to the node(s) configuration
- *
- * Expected parameters:
- *   TST_SALT_MASTER_CREDENTIALS  Credentials to the Salt API (QA environment).
- *   TST_SALT_MASTER_URL          Full Salt API address [https://10.10.10.1:8000].
- *   PRD_SALT_MASTER_CREDENTIALS  Credentials to the Salt API (PRD environment).
- *   PRD_SALT_MASTER_URL          Full Salt API address [https://10.10.10.1:8000].
- * Model parameters:
- *   MODEL_REPO_CREDENTIALS       Credentials to the Model.
- *   MODEL_REPO_URL               Full model repo address.
- *   MODEL_REPO_SOURCE_BRANCH     Source branch to merge from.
- *   MODEL_REPO_TARGET_BRANCH     Target branch to merge fo.
- * Change settings:
- *   TARGET_SERVERS               Salt compound target to match nodes to be updated [*, G@osfamily:debian].
- *   TARGET_STATES                States to be applied, empty string means running highstate [linux, linux,openssh, salt.minion.grains].
- *   TARGET_SUBSET_TEST           Number of nodes to test config changes, empty string means all targetted nodes.
- *   TARGET_SUBSET_LIVE           Number of selected noded to live apply selected config changes.
- *   TARGET_BATCH_LIVE            Batch size for the complete live config changes on all nodes, empty string means apply to all targetted nodes.
- * Test settings:
- *   TEST_SERVICE                 Comma separated list of services to test
- *   TEST_K8S_API_SERVER          Kubernetes API address
- *   TEST_K8S_CONFORMANCE_IMAGE   Path to docker image with conformance e2e tests
- *   TEST_DOCKER_INSTALL          Install docker on the target if true
- *   TEST_TEMPEST_IMAGE           Tempest image link
- *   TEST_TEMPEST_PATTERN         If not false, run tests matched to pattern only
- *   TEST_TEMPEST_TARGET          Salt target for tempest node
- *
-**/
-
-def common = new com.mirantis.mk.Common()
-def salt = new com.mirantis.mk.Salt()
-timeout(time: 12, unit: 'HOURS') {
-  node() {
-      try {
-
-          stage('Run config change on test env') {
-              build job: "deploy-update-service-config", parameters: [
-                [$class: 'StringParameterValue', name: 'SALT_MASTER_URL', value: TST_SALT_MASTER_URL],
-                [$class: 'StringParameterValue', name: 'SALT_MASTER_CREDENTIALS', value: TST_SALT_MASTER_CREDENTIALS],
-                [$class: 'StringParameterValue', name: 'TARGET_BATCH_LIVE', value: TARGET_BATCH_LIVE],
-                [$class: 'StringParameterValue', name: 'TARGET_SERVERS', value: TARGET_SERVERS],
-                [$class: 'StringParameterValue', name: 'TARGET_STATES', value: TARGET_STATES],
-                [$class: 'StringParameterValue', name: 'TARGET_SUBSET_LIVE', value: TARGET_SUBSET_LIVE],
-                [$class: 'StringParameterValue', name: 'TARGET_SUBSET_TEST', value: TARGET_SUBSET_TEST],
-              ]
-          }
-
-          stage('Test config change on test env') {
-              build job: "deploy-test-service", parameters: [
-                [$class: 'StringParameterValue', name: 'SALT_MASTER_URL', value: TST_SALT_MASTER_URL],
-                [$class: 'StringParameterValue', name: 'SALT_MASTER_CREDENTIALS', value: TST_SALT_MASTER_CREDENTIALS],
-                [$class: 'StringParameterValue', name: 'TEST_SERVICE', value: TEST_SERVICE],
-                [$class: 'StringParameterValue', name: 'TEST_K8S_API_SERVER', value: TEST_K8S_API_SERVER],
-                [$class: 'StringParameterValue', name: 'TEST_K8S_CONFORMANCE_IMAGE', value: TEST_K8S_CONFORMANCE_IMAGE],
-              ]
-          }
-
-          stage('Promote config change in repo') {
-              build job: "git-merge-branches", parameters: [
-                [$class: 'StringParameterValue', name: 'REPO_URL', value: MODEL_REPO_URL],
-                [$class: 'StringParameterValue', name: 'CREDENTIALS_ID', value: MODEL_REPO_CREDENTIALS],
-                [$class: 'StringParameterValue', name: 'SOURCE_BRANCH', value: MODEL_REPO_SOURCE_BRANCH],
-                [$class: 'StringParameterValue', name: 'TARGET_BRANCH', value: MODEL_REPO_TARGET_BRANCH],
-              ]
-          }
-
-          stage('Run config change on production env') {
-              build job: "deploy-update-service-config", parameters: [
-                [$class: 'StringParameterValue', name: 'SALT_MASTER_URL', value: PRD_SALT_MASTER_URL],
-                [$class: 'StringParameterValue', name: 'SALT_MASTER_CREDENTIALS', value: PRD_SALT_MASTER_CREDENTIALS],
-                [$class: 'StringParameterValue', name: 'TARGET_BATCH_LIVE', value: TARGET_BATCH_LIVE],
-                [$class: 'StringParameterValue', name: 'TARGET_SERVERS', value: TARGET_SERVERS],
-                [$class: 'StringParameterValue', name: 'TARGET_STATES', value: TARGET_STATES],
-                [$class: 'StringParameterValue', name: 'TARGET_SUBSET_LIVE', value: TARGET_SUBSET_LIVE],
-                [$class: 'StringParameterValue', name: 'TARGET_SUBSET_TEST', value: TARGET_SUBSET_TEST],
-              ]
-          }
-
-          stage('Test config change on prod env') {
-              def result = build job: "deploy-test-service", parameters: [
-                [$class: 'StringParameterValue', name: 'SALT_MASTER_URL', value: PRD_SALT_MASTER_URL],
-                [$class: 'StringParameterValue', name: 'SALT_MASTER_CREDENTIALS', value: PRD_SALT_MASTER_CREDENTIALS],
-                [$class: 'StringParameterValue', name: 'TEST_SERVICE', value: TEST_SERVICE],
-                [$class: 'StringParameterValue', name: 'TEST_K8S_API_SERVER', value: TEST_K8S_API_SERVER],
-                [$class: 'StringParameterValue', name: 'TEST_K8S_CONFORMANCE_IMAGE', value: TEST_K8S_CONFORMANCE_IMAGE],
-              ]
-          }
-
-      } catch (Throwable e) {
-          currentBuild.result = 'FAILURE'
-          throw e
-      }
-  }
-}
diff --git a/test-service.groovy b/test-service.groovy
deleted file mode 100644
index f9c34e3..0000000
--- a/test-service.groovy
+++ /dev/null
@@ -1,96 +0,0 @@
-/**
- *
- * Service test pipeline
- *
- * Expected parameters:
- *   SALT_MASTER_URL              URL of Salt master
- *   SALT_MASTER_CREDENTIALS      Credentials to the Salt API
- * Test settings:
- *   TEST_SERVICE                 Comma separated list of services to test
- *   TEST_K8S_API_SERVER          Kubernetes API address
- *   TEST_K8S_CONFORMANCE_IMAGE   Path to docker image with conformance e2e tests
- *   TEST_DOCKER_INSTALL          Install docker on the target if true
- *   TEST_TEMPEST_IMAGE           Tempest image link
- *   TEST_TEMPEST_PATTERN         If not false, run tests matched to pattern only
- *   TEST_TEMPEST_TARGET          Salt target for tempest node
- *
- */
-
-common = new com.mirantis.mk.Common()
-git = new com.mirantis.mk.Git()
-salt = new com.mirantis.mk.Salt()
-test = new com.mirantis.mk.Test()
-def python = new com.mirantis.mk.Python()
-
-def pepperEnv = "pepperEnv"
-timeout(time: 12, unit: 'HOURS') {
-    node("python") {
-        try {
-
-            stage('Setup virtualenv for Pepper') {
-                python.setupPepperVirtualenv(pepperEnv, SALT_MASTER_URL, SALT_MASTER_CREDENTIALS)
-            }
-
-            //
-            // Test
-            //
-            def artifacts_dir = '_artifacts/'
-
-            if (common.checkContains('TEST_SERVICE', 'k8s')) {
-                stage('Run k8s bootstrap tests') {
-                    def image = 'tomkukral/k8s-scripts'
-                    def output_file = image.replaceAll('/', '-') + '.output'
-
-                    // run image
-                    test.runConformanceTests(pepperEnv, 'ctl01*', TEST_K8S_API_SERVER, image)
-
-                    // collect output
-                    sh "mkdir -p ${artifacts_dir}"
-                    file_content = salt.getFileContent(pepperEnv, 'ctl01*', '/tmp/' + output_file)
-                    writeFile file: "${artifacts_dir}${output_file}", text: file_content
-                    sh "cat ${artifacts_dir}${output_file}"
-
-                    // collect artifacts
-                    archiveArtifacts artifacts: "${artifacts_dir}${output_file}"
-                }
-
-                stage('Run k8s conformance e2e tests') {
-                    def image = K8S_CONFORMANCE_IMAGE
-                    def output_file = image.replaceAll('/', '-') + '.output'
-
-                    // run image
-                    test.runConformanceTests(pepperEnv, 'ctl01*', TEST_K8S_API_SERVER, image)
-
-                    // collect output
-                    sh "mkdir -p ${artifacts_dir}"
-                    file_content = salt.getFileContent(pepperEnv, 'ctl01*', '/tmp/' + output_file)
-                    writeFile file: "${artifacts_dir}${output_file}", text: file_content
-                    sh "cat ${artifacts_dir}${output_file}"
-
-                    // collect artifacts
-                    archiveArtifacts artifacts: "${artifacts_dir}${output_file}"
-                }
-            }
-
-            if (common.checkContains('TEST_SERVICE', 'openstack')) {
-                if (common.checkContains('TEST_DOCKER_INSTALL', 'true')) {
-                    test.install_docker(pepperEnv, TEST_TEMPEST_TARGET)
-                }
-
-                stage('Run OpenStack tests') {
-                    test.runTempestTests(pepperEnv, TEST_TEMPEST_IMAGE, TEST_TEMPEST_TARGET, TEST_TEMPEST_PATTERN)
-                }
-
-                writeFile(file: 'report.xml', text: salt.getFileContent(pepperEnv, TEST_TEMPEST_TARGET, '/root/report.xml'))
-                junit(keepLongStdio: true, testResults: 'report.xml', healthScaleFactor:  Double.parseDouble(TEST_JUNIT_RATIO))
-                def testResults = test.collectJUnitResults(currentBuild.rawBuild.getAction(hudson.tasks.test.AbstractTestResultAction.class))
-                if(testResults){
-                    currentBuild.desc = String.format("result: %s", testResults["failed"] / testResults["total"])
-                }
-            }
-        } catch (Throwable e) {
-            currentBuild.result = 'FAILURE'
-            throw e
-        }
-    }
-}