Merge "add missing neutron state"
diff --git a/change-config.groovy b/change-config.groovy
new file mode 100644
index 0000000..69f7519
--- /dev/null
+++ b/change-config.groovy
@@ -0,0 +1,93 @@
+/**
+ * Make change to the node(s) configuration
+ *
+ * Expected parameters:
+ *   SALT_MASTER_CREDENTIALS    Credentials to the Salt API.
+ *   SALT_MASTER_URL            Full Salt API address [https://10.10.10.1:8000].
+ *   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.
+ *
+**/
+
+def common = new com.mirantis.mk.Common()
+def salt = new com.mirantis.mk.Salt()
+
+def saltMaster
+def targetAll = ['expression': TARGET_SERVERS, 'type': 'compound']
+def targetTestSubset
+def targetLiveSubset
+def targetLiveAll
+def minions
+def result
+def states
+
+node() {
+    try {
+
+        if (TARGET_STATES != "") {
+            states = TARGET_STATES
+        }
+        else {
+            states = null
+        }
+
+        stage('Connect to Salt master') {
+            saltMaster = salt.connection(SALT_MASTER_URL, SALT_MASTER_CREDENTIALS)
+        }
+
+        stage('List target servers') {
+            minions = salt.getMinions(saltMaster, targetAll)
+            if (TARGET_SUBSET_TEST != "") {
+                targetTestSubset = ['expression': minions.subList(0, Integer.valueOf(TARGET_SUBSET_TEST)).join(' or '), 'type': 'compound']
+            }
+            else {
+                targetTestSubset = ['expression': minions.join(' or '), 'type': 'compound']
+            }
+            targetLiveSubset = ['expression': minions.subList(0, Integer.valueOf(TARGET_SUBSET_LIVE)).join(' or '), 'type': 'compound']
+            targetLiveAll = ['expression': minions.join(' or '), 'type': 'compound']
+            common.infoMsg("Found nodes: ${targetLiveAll.expression}")
+            common.infoMsg("Selected test nodes: ${targetTestSubset.expression}")
+            common.infoMsg("Selected sample nodes: ${targetLiveSubset.expression}")
+        }
+
+        stage('Test config changes') {
+            def kwargs = [
+                'test': true
+            ]
+            result = salt.runSaltCommand(saltMaster, 'local', targetTestSubset, 'state.apply', null, states, kwargs)
+            salt.printSaltStateResult(result)
+        }
+
+        stage('Confirm live changes on sample') {
+            timeout(time: 2, unit: 'HOURS') {
+               input message: "Approve live config change on ${targetLiveSubset.expression} nodes?"
+            }
+        }
+
+        stage('Apply config changes on sample') {
+            result = salt.runSaltCommand(saltMaster, 'local', targetLiveSubset, 'state.apply', null, states)
+            salt.printSaltStateResult(result)
+        }
+
+        stage('Confirm live changes on all nodes') {
+            timeout(time: 2, unit: 'HOURS') {
+               input message: "Approve live config change on ${targetLiveAll.expression} nodes?"
+            }
+        }
+
+        stage('Apply config changes on all nodes') {
+            result = salt.runSaltCommand(saltMaster, 'local', targetLiveAll, 'state.apply', null, states)
+            salt.printSaltStateResult(result)
+        }
+
+    } catch (Throwable e) {
+        currentBuild.result = 'FAILURE'
+        throw e
+    } finally {
+        // send notification
+        //common.sendNotification(currentBuild.result,HEAT_STACK_NAME,["slack"])
+    }
+}
diff --git a/update-package.groovy b/update-package.groovy
index e2ce9e4..b17eb01 100644
--- a/update-package.groovy
+++ b/update-package.groovy
@@ -1,48 +1,103 @@
 /**
- * Update packages pipeline script
+ * Update packages on given nodes
  *
  * Expected parameters:
- * SALT_MASTER_CREDENTIALS     Credentials to the Salt API (str)
- * SALT_MASTER_URL             URL of Salt-API (str)
- *
- * UPDATE_SERVERS              Salt target for updated servers (str)
- * UPDATE_COMMIT               Confirm update should be performed (boot)
- * UPDATE_PACKAGES             List of packages to update
+ *   SALT_MASTER_CREDENTIALS    Credentials to the Salt API.
+ *   SALT_MASTER_URL            Full Salt API address [https://10.10.10.1:8000].
+ *   TARGET_SERVERS             Salt compound target to match nodes to be updated [*, G@osfamily:debian].
+ *   TARGET_PACKAGES            Space delimited list of packages to be updates [package1=version package2=version], empty string means all updating all packages to the latest version.
+ *   TARGET_SIZE_TEST           Number of nodes to list package updates, empty string means all targetted nodes.
+ *   TARGET_SIZE_SAMPLE         Number of selected noded to live apply selected package update.
+ *   TARGET_SIZE_BATCH          Batch size for the complete live package update on all nodes, empty string means apply to all targetted nodes.
  *
 **/
 
-
-
 def common = new com.mirantis.mk.Common()
 def salt = new com.mirantis.mk.Salt()
-timestamps {
-    node() {
-      try {
 
-        stage("Connect to Salt master") {
-          saltMaster = salt.connection(SALT_MASTER_URL, SALT_MASTER_CREDENTIALS)
+def saltMaster
+def targetAll = ['expression': TARGET_SERVERS, 'type': 'compound']
+def targetTestSubset
+def targetLiveSubset
+def targetLiveAll
+def minions
+def result
+def command
+def packages
+
+node() {
+    try {
+
+        if (TARGET_PACKAGES != "") {
+            command = "pkg.install"
+            packages = TARGET_PACKAGES.tokenize(' ')
+        }
+        else {
+            command = "pkg.upgrade"
+            packages = null
         }
 
-        stage("Get package versions") {
-          salt.runSaltProcessStep(saltMaster, UPDATE_SERVERS, 'pkg.list_upgrades', [], null, true)
+        stage('Connect to Salt master') {
+            saltMaster = salt.connection(SALT_MASTER_URL, SALT_MASTER_CREDENTIALS)
         }
 
-        if (UPDATE_COMMIT.toBoolean() == true) {
-          stage("Update packages") {
-            if (UPDATE_PACKAGES == "") {
-              salt.runSaltProcessStep(saltMaster, UPDATE_SERVERS, 'pkg.install', [], null, true)
-            } else {
-              salt.runSaltProcessStep(saltMaster, UPDATE_SERVERS, 'pkg.install', UPDATE_PACKAGES.split(' '), null, true)
+        stage('List target servers') {
+            minions = salt.getMinions(saltMaster, targetAll)
+            if (TARGET_SUBSET_TEST != "") {
+                targetTestSubset = minions.subList(0, Integer.valueOf(TARGET_SUBSET_TEST)).join(' or ')
             }
-          }
+            else {
+                targetTestSubset = minions.join(' or ')
+            }
+            targetLiveSubset = minions.subList(0, Integer.valueOf(TARGET_SUBSET_LIVE)).join(' or ')
+            targetLiveAll = minions.join(' or ')
+            common.infoMsg("Found nodes: ${targetLiveAll}")
+            common.infoMsg("Selected test nodes: ${targetTestSubset}")
+            common.infoMsg("Selected sample nodes: ${targetLiveSubset}")
         }
 
-      } catch (Throwable e) {
-         // If there was an error or exception thrown, the build failed
-         currentBuild.result = "FAILURE"
-         throw e
-      } finally {
-         // common.sendNotification(currentBuild.result,"",["slack"])
-      }
+        stage("List package upgrades") {
+            salt.runSaltProcessStep(saltMaster, targetTestSubset, 'pkg.list_upgrades', [], null, true)
+        }
+
+        stage('Confirm live package upgrades on sample') {
+            if(TARGET_PACKAGES==""){
+                timeout(time: 2, unit: 'HOURS') {
+                    def userInput = input(
+                     id: 'userInput', message: 'Insert package names for update', parameters: [
+                     [$class: 'TextParameterDefinition', defaultValue: '', description: 'Package names (or *)', name: 'packages']
+                    ])
+                    if(userInput['packages'] != ""){
+                        packages = userInput['packages'].tokenize(" ")
+                    }
+                }
+            }else{
+                timeout(time: 2, unit: 'HOURS') {
+                   input message: "Approve live package upgrades on ${targetLiveSubset} nodes?"
+                }
+            }
+        }
+
+        stage('Apply package upgrades on sample') {
+            salt.runSaltProcessStep(saltMaster, targetLiveSubset, command, packages, null, true)
+
+        }
+
+        stage('Confirm package upgrades on all nodes') {
+            timeout(time: 2, unit: 'HOURS') {
+               input message: "Approve live package upgrades on ${targetLiveAll} nodes?"
+            }
+        }
+
+        stage('Apply package upgrades on all nodes') {
+            salt.runSaltProcessStep(saltMaster, targetLiveAll, command, packages, null, true)
+        }
+
+    } catch (Throwable e) {
+        // If there was an error or exception thrown, the build failed
+        currentBuild.result = "FAILURE"
+        throw e
+    } finally {
+        // common.sendNotification(currentBuild.result,"",["slack"])
     }
 }