blob: 445c097b457b339b4af584ae365e86cb22490241 [file] [log] [blame]
Richard Felkl26cae4d2017-12-19 00:19:16 +01001/**
2 *
3 * Update Salt environment pipeline
4 *
5 * Expected parameters:
6 * SALT_MASTER_URL Salt API server location
7 * SALT_MASTER_CREDENTIALS Credentials to the Salt API
azvyagintsev6dac3802018-11-09 15:11:30 +02008 * TARGET_MCP_VERSION Version of MCP to upgrade to
Richard Felkl0e80d892018-06-20 13:44:54 +02009 * UPGRADE_SALTSTACK Upgrade SaltStack packages to new version.
Richard Felkl970e0082018-06-12 18:00:51 +020010 * UPDATE_CLUSTER_MODEL Update MCP version parameter in cluster model
11 * UPDATE_PIPELINES Update pipeline repositories on Gerrit
Richard Felkl26cae4d2017-12-19 00:19:16 +010012 * UPDATE_LOCAL_REPOS Update local repositories
13 */
14
15// Load shared libs
Richard Felkl5f7fdaf2018-02-15 15:38:31 +010016salt = new com.mirantis.mk.Salt()
17common = new com.mirantis.mk.Common()
18python = new com.mirantis.mk.Python()
Richard Felkl970e0082018-06-12 18:00:51 +020019jenkinsUtils = new com.mirantis.mk.JenkinsUtils()
azvyagintsevf3bf77a2018-11-15 19:30:04 +020020def pipelineTimeout = 12
Richard Felkl5f7fdaf2018-02-15 15:38:31 +010021venvPepper = "venvPepper"
Richard Felkl0e80d892018-06-20 13:44:54 +020022workspace = ""
Richard Felkl5f7fdaf2018-02-15 15:38:31 +010023
azvyagintsev6dac3802018-11-09 15:11:30 +020024def triggerMirrorJob(jobName) {
Richard Felkl970e0082018-06-12 18:00:51 +020025 params = jenkinsUtils.getJobParameters(jobName)
26 build job: jobName, parameters: [
27 [$class: 'StringParameterValue', name: 'BRANCHES', value: params.get("BRANCHES")],
28 [$class: 'StringParameterValue', name: 'CREDENTIALS_ID', value: params.get("CREDENTIALS_ID")],
29 [$class: 'StringParameterValue', name: 'SOURCE_URL', value: params.get("SOURCE_URL")],
30 [$class: 'StringParameterValue', name: 'TARGET_URL', value: params.get("TARGET_URL")]
31 ]
32}
33
azvyagintsev6dac3802018-11-09 15:11:30 +020034def updateSaltStack(target, pkgs) {
35 try {
Richard Felkl0e80d892018-06-20 13:44:54 +020036 salt.runSaltProcessStep(venvPepper, target, 'pkg.install', ["force_yes=True", "pkgs='$pkgs'"], null, true, 5)
azvyagintsev6dac3802018-11-09 15:11:30 +020037 } catch (Exception ex) {
38 }
Richard Felkl0e80d892018-06-20 13:44:54 +020039
azvyagintsev6dac3802018-11-09 15:11:30 +020040 common.retry(20, 60) {
Richard Felkl0e80d892018-06-20 13:44:54 +020041 salt.minionsReachable(venvPepper, 'I@salt:master', '*')
42 def running = salt.runSaltProcessStep(venvPepper, target, 'saltutil.running', [], null, true, 5)
azvyagintsev6dac3802018-11-09 15:11:30 +020043 for (value in running.get("return")[0].values()) {
44 if (value != []) {
Richard Felkl0e80d892018-06-20 13:44:54 +020045 throw new Exception("Not all salt-minions are ready for execution")
46 }
47 }
48 }
49
azvyagintsevf3bf77a2018-11-15 19:30:04 +020050 def saltVersion = salt.getPillar(venvPepper, 'I@salt:master', '_param:salt_version').get('return')[0].values()[0]
Richard Felklf23257e2018-08-06 09:24:23 +020051 def saltMinionVersions = salt.cmdRun(venvPepper, target, "apt-cache policy salt-common | awk '/Installed/ && /$saltVersion/'").get("return")
Richard Felkl0e80d892018-06-20 13:44:54 +020052 def saltMinionVersion = ""
53
azvyagintsev6dac3802018-11-09 15:11:30 +020054 for (minion in saltMinionVersions[0].keySet()) {
55 saltMinionVersion = saltMinionVersions[0].get(minion).replace("Salt command execution success", "").trim()
56 if (saltMinionVersion == "") {
Richard Felkl0e80d892018-06-20 13:44:54 +020057 error("Installed version of Salt on $minion doesn't match specified version in the model.")
58 }
59 }
60}
61
azvyagintsev6dac3802018-11-09 15:11:30 +020062def archiveReclassInventory(filename) {
Richard Felkl0e80d892018-06-20 13:44:54 +020063 def ret = salt.cmdRun(venvPepper, 'I@salt:master', "reclass -i", true, null, false)
64 def reclassInv = ret.values()[0]
65 writeFile file: filename, text: reclassInv.toString()
66 archiveArtifacts artifacts: "$filename"
67}
68
azvyagintsevf3bf77a2018-11-15 19:30:04 +020069if (common.validInputParam('PIPELINE_TIMEOUT') && env.PIPELINE_TIMEOUT.isInteger()) {
70 pipelineTimeout = env.PIPELINE_TIMEOUT.toInteger()
Martin Polreich965c9032018-08-09 16:33:57 +020071}
72
73timeout(time: pipelineTimeout, unit: 'HOURS') {
Jakub Josefa63f9862018-01-11 17:58:38 +010074 node("python") {
75 try {
Richard Felkl0e80d892018-06-20 13:44:54 +020076 workspace = common.getWorkspace()
azvyagintsevf3bf77a2018-11-15 19:30:04 +020077 targetMcpVersion = null
78 if (!common.validInputParam('TARGET_MCP_VERSION') && !common.validInputParam('MCP_VERSION')) {
79 error('You must specify MCP version in TARGET_MCP_VERSION|MCP_VERSION variable')
azvyagintsev6dac3802018-11-09 15:11:30 +020080 }
azvyagintsevf3bf77a2018-11-15 19:30:04 +020081 // bw comp. for 2018.X => 2018.11 release
82 if (common.validInputParam('MCP_VERSION')){
83 targetMcpVersion = env.MCP_VERSION
84 common.warningMsg("targetMcpVersion has been changed to:${targetMcpVersion}, which was taken from deprecated pipeline viriable:MCP_VERSION")
85 }
86 else {
87 targetMcpVersion = env.TARGET_MCP_VERSION
88 }
89 // end bw comp. for 2018.X => 2018.11 release
90 def gitTargetMcpVersion = targetMcpVersion
91 if (targetMcpVersion == 'testing') {
92 gitTargetMcpVersion = 'master'
93 common.warningMsg("gitTargetMcpVersion has been changed to:${gitTargetMcpVersion}")
azvyagintsev6dac3802018-11-09 15:11:30 +020094 }
Jakub Josefa63f9862018-01-11 17:58:38 +010095 python.setupPepperVirtualenv(venvPepper, SALT_MASTER_URL, SALT_MASTER_CREDENTIALS)
Richard Felkl26cae4d2017-12-19 00:19:16 +010096
azvyagintsev6dac3802018-11-09 15:11:30 +020097 stage("Update Reclass") {
Richard Felkl970e0082018-06-12 18:00:51 +020098 def cluster_name = salt.getPillar(venvPepper, 'I@salt:master', "_param:cluster_name").get("return")[0].values()[0]
azvyagintsev6dac3802018-11-09 15:11:30 +020099 try {
Sergey382581a2018-10-25 12:22:26 +0400100 salt.cmdRun(venvPepper, 'I@salt:master', "cd /srv/salt/reclass/ && git diff-index --quiet HEAD --")
Richard Felkl970e0082018-06-12 18:00:51 +0200101 }
azvyagintsev6dac3802018-11-09 15:11:30 +0200102 catch (Exception ex) {
Sergey382581a2018-10-25 12:22:26 +0400103 error("You have uncommited changes in your Reclass cluster model repository. Please commit or reset them and rerun the pipeline.")
Richard Felkl970e0082018-06-12 18:00:51 +0200104 }
azvyagintsev6dac3802018-11-09 15:11:30 +0200105 if (UPDATE_CLUSTER_MODEL.toBoolean()) {
106 common.infoMsg('Perform: UPDATE_CLUSTER_MODEL')
Sergey382581a2018-10-25 12:22:26 +0400107 def dateTime = common.getDatetime()
108 salt.cmdRun(venvPepper, 'I@salt:master', "cd /srv/salt/reclass/classes/cluster/$cluster_name && " +
azvyagintsevf3bf77a2018-11-15 19:30:04 +0200109 "grep -r --exclude-dir=aptly -l 'mcp_version: .*' * | xargs --no-run-if-empty sed -i 's/mcp_version: .*/mcp_version: \"$targetMcpVersion\"/g'")
azvyagintsev6dac3802018-11-09 15:11:30 +0200110 // Do the same, for deprecated variable-duplicate
111 salt.cmdRun(venvPepper, 'I@salt:master', "cd /srv/salt/reclass/classes/cluster/$cluster_name && " +
azvyagintsevf3bf77a2018-11-15 19:30:04 +0200112 "grep -r --exclude-dir=aptly -l 'apt_mk_version: .*' * | xargs --no-run-if-empty sed -i 's/apt_mk_version: .*/apt_mk_version: \"$targetMcpVersion\"/g'")
azvyagintsev0a38ec22018-11-19 19:18:02 +0200113 salt.cmdRun(venvPepper, 'I@salt:master', "cd /srv/salt/reclass/classes/system && git checkout ${gitTargetMcpVersion}")
Sergey382581a2018-10-25 12:22:26 +0400114 // Add new defaults
115 common.infoMsg("Add new defaults")
116 salt.cmdRun(venvPepper, 'I@salt:master', "grep '^- system.defaults\$' /srv/salt/reclass/classes/cluster/$cluster_name/infra/init.yml || " +
azvyagintsev6dac3802018-11-09 15:11:30 +0200117 "sed -i 's/^classes:/classes:\\n- system.defaults/' /srv/salt/reclass/classes/cluster/$cluster_name/infra/init.yml")
Sergey382581a2018-10-25 12:22:26 +0400118 common.infoMsg("The following changes were made to the cluster model and will be commited. " +
azvyagintsev6dac3802018-11-09 15:11:30 +0200119 "Please consider if you want to push them to the remote repository or not. You have to do this manually when the run is finished.")
Sergey382581a2018-10-25 12:22:26 +0400120 salt.cmdRun(venvPepper, 'I@salt:master', "cd /srv/salt/reclass/classes/cluster/$cluster_name && git diff")
121 salt.cmdRun(venvPepper, 'I@salt:master', "cd /srv/salt/reclass/classes/cluster/$cluster_name && git status && " +
azvyagintsevf3bf77a2018-11-15 19:30:04 +0200122 "git add -u && git commit --allow-empty -m 'Cluster model update to the release $targetMcpVersion on $dateTime'")
Sergey382581a2018-10-25 12:22:26 +0400123 }
Sergey1b81c062018-10-16 17:10:21 +0400124 salt.enforceState(venvPepper, 'I@salt:master', 'reclass.storage', true)
Jakub Josefa63f9862018-01-11 17:58:38 +0100125 }
Richard Felkl26cae4d2017-12-19 00:19:16 +0100126
azvyagintsev6dac3802018-11-09 15:11:30 +0200127 if (UPDATE_LOCAL_REPOS.toBoolean()) {
Sergey1b81c062018-10-16 17:10:21 +0400128 def cluster_name = salt.getPillar(venvPepper, 'I@salt:master', "_param:cluster_name").get("return")[0].values()[0]
azvyagintsev6dac3802018-11-09 15:11:30 +0200129 stage("Update local repos") {
Jakub Josefa63f9862018-01-11 17:58:38 +0100130 common.infoMsg("Updating local repositories")
Sam Stoelingaaab79702018-04-09 18:49:39 -0700131
Sergey1b81c062018-10-16 17:10:21 +0400132 def engine = salt.getPillar(venvPepper, 'I@aptly:publisher', "aptly:publisher:source:engine")
Sam Stoelingaaab79702018-04-09 18:49:39 -0700133 runningOnDocker = engine.get("return")[0].containsValue("docker")
134
135 if (runningOnDocker) {
136 common.infoMsg("Aptly is running as Docker container")
azvyagintsev6dac3802018-11-09 15:11:30 +0200137 } else {
Sam Stoelingaaab79702018-04-09 18:49:39 -0700138 common.infoMsg("Aptly isn't running as Docker container. Going to use aptly user for executing aptly commands")
139 }
140
azvyagintsev6dac3802018-11-09 15:11:30 +0200141 if (runningOnDocker) {
azvyagintsevf3bf77a2018-11-15 19:30:04 +0200142 salt.cmdRun(venvPepper, 'I@aptly:publisher', "aptly mirror list --raw | grep -E '*' | xargs --no-run-if-empty -n 1 aptly mirror drop -force", true, null, true)
azvyagintsev6dac3802018-11-09 15:11:30 +0200143 } else {
azvyagintsevf3bf77a2018-11-15 19:30:04 +0200144 salt.cmdRun(venvPepper, 'I@aptly:publisher', "aptly mirror list --raw | grep -E '*' | xargs --no-run-if-empty -n 1 aptly mirror drop -force", true, null, true, ['runas=aptly'])
Richard Felkl5f7fdaf2018-02-15 15:38:31 +0100145 }
Richard Felkl26cae4d2017-12-19 00:19:16 +0100146
Sergey1b81c062018-10-16 17:10:21 +0400147 salt.enforceState(venvPepper, 'I@aptly:publisher', 'aptly', true)
Richard Felkl26cae4d2017-12-19 00:19:16 +0100148
azvyagintsev6dac3802018-11-09 15:11:30 +0200149 if (runningOnDocker) {
Sergey1b81c062018-10-16 17:10:21 +0400150 salt.runSaltProcessStep(venvPepper, 'I@aptly:publisher', 'cmd.script', ['salt://aptly/files/aptly_mirror_update.sh', "args=-sv"], null, true)
151 salt.runSaltProcessStep(venvPepper, 'I@aptly:publisher', 'cmd.script', ['salt://aptly/files/aptly_publish_update.sh', "args=-frv -u http://10.99.0.1:8080"], null, true)
azvyagintsev6dac3802018-11-09 15:11:30 +0200152 } else {
Sergey1b81c062018-10-16 17:10:21 +0400153 salt.runSaltProcessStep(venvPepper, 'I@aptly:publisher', 'cmd.script', ['salt://aptly/files/aptly_mirror_update.sh', "args=-sv", 'runas=aptly'], null, true)
154 salt.runSaltProcessStep(venvPepper, 'I@aptly:publisher', 'cmd.script', ['salt://aptly/files/aptly_publish_update.sh', "args=-afrv", 'runas=aptly'], null, true)
Richard Felkl5f7fdaf2018-02-15 15:38:31 +0100155 }
Richard Felkl79d7df12018-01-05 16:40:11 +0100156
Sergey1b81c062018-10-16 17:10:21 +0400157 salt.enforceState(venvPepper, 'I@aptly:publisher', 'docker.client.registry', true)
Richard Felkl26cae4d2017-12-19 00:19:16 +0100158
Sergey1b81c062018-10-16 17:10:21 +0400159 salt.enforceState(venvPepper, 'I@aptly:publisher', 'debmirror', true)
Richard Felkl26cae4d2017-12-19 00:19:16 +0100160
Sergey1b81c062018-10-16 17:10:21 +0400161 salt.enforceState(venvPepper, 'I@aptly:publisher', 'git.server', true)
Richard Felkl5f7fdaf2018-02-15 15:38:31 +0100162
Sergey1b81c062018-10-16 17:10:21 +0400163 salt.enforceState(venvPepper, 'I@aptly:publisher', 'linux.system.file', true)
Jakub Josefa63f9862018-01-11 17:58:38 +0100164 }
165 }
Richard Felkl26cae4d2017-12-19 00:19:16 +0100166
azvyagintsev6dac3802018-11-09 15:11:30 +0200167 stage("Update Drivetrain") {
azvyagintsevf3bf77a2018-11-15 19:30:04 +0200168 salt.cmdRun(venvPepper, 'I@salt:master', "sed -i -e 's/[^ ]*[^ ]/$targetMcpVersion/4' /etc/apt/sources.list.d/mcp_salt.list")
Richard Felkl970e0082018-06-12 18:00:51 +0200169 salt.cmdRun(venvPepper, 'I@salt:master', "apt-get -o Dir::Etc::sourcelist='/etc/apt/sources.list.d/mcp_salt.list' -o Dir::Etc::sourceparts='-' -o APT::Get::List-Cleanup='0' update")
Sergey1b81c062018-10-16 17:10:21 +0400170 // Workaround for PROD-22108
171 salt.cmdRun(venvPepper, 'I@salt:master', "apt-get purge -y salt-formula-octavia && " +
azvyagintsev6dac3802018-11-09 15:11:30 +0200172 "apt-get install -y salt-formula-octavia")
Sergey1b81c062018-10-16 17:10:21 +0400173 // End workaround for PROD-22108
Richard Felkl970e0082018-06-12 18:00:51 +0200174 salt.cmdRun(venvPepper, 'I@salt:master', "apt-get install -y --allow-downgrades salt-formula-*")
Richard Felkl0e80d892018-06-20 13:44:54 +0200175
176 def inventoryBeforeFilename = "reclass-inventory-before.out"
177 def inventoryAfterFilename = "reclass-inventory-after.out"
178
179 archiveReclassInventory(inventoryBeforeFilename)
180
azvyagintsevf3bf77a2018-11-15 19:30:04 +0200181 salt.cmdRun(venvPepper, 'I@salt:master', "sed -i -e 's/[^ ]*[^ ]/$targetMcpVersion/4' /etc/apt/sources.list.d/mcp_extra.list")
Richard Felkl0e80d892018-06-20 13:44:54 +0200182 salt.cmdRun(venvPepper, 'I@salt:master', "apt-get -o Dir::Etc::sourcelist='/etc/apt/sources.list.d/mcp_extra.list' -o Dir::Etc::sourceparts='-' -o APT::Get::List-Cleanup='0' update")
183 salt.cmdRun(venvPepper, 'I@salt:master', "apt-get install -y --allow-downgrades reclass")
184
Richard Felkl970e0082018-06-12 18:00:51 +0200185 salt.fullRefresh(venvPepper, 'I@salt:master')
Jakub Josefa63f9862018-01-11 17:58:38 +0100186
azvyagintsev6dac3802018-11-09 15:11:30 +0200187 try {
Richard Felkl970e0082018-06-12 18:00:51 +0200188 salt.enforceState(venvPepper, "I@salt:master", 'reclass', true)
189 }
azvyagintsev6dac3802018-11-09 15:11:30 +0200190 catch (Exception ex) {
Richard Felkl970e0082018-06-12 18:00:51 +0200191 error("Reclass fails rendering. Pay attention to your cluster model.")
192 }
Jakub Josefa63f9862018-01-11 17:58:38 +0100193
Richard Felkl970e0082018-06-12 18:00:51 +0200194 salt.fullRefresh(venvPepper, '*')
195
azvyagintsev6dac3802018-11-09 15:11:30 +0200196 try {
Richard Felkl970e0082018-06-12 18:00:51 +0200197 salt.cmdRun(venvPepper, 'I@salt:master', "reclass-salt --top")
198 }
azvyagintsev6dac3802018-11-09 15:11:30 +0200199 catch (Exception ex) {
Richard Felkl970e0082018-06-12 18:00:51 +0200200 error("Reclass fails rendering. Pay attention to your cluster model.")
201 }
202
Richard Felkl0e80d892018-06-20 13:44:54 +0200203 archiveReclassInventory(inventoryAfterFilename)
204
205 sh "diff -u $inventoryBeforeFilename $inventoryAfterFilename > reclass-inventory-diff.out || true"
206 archiveArtifacts artifacts: "reclass-inventory-diff.out"
207
azvyagintsev6dac3802018-11-09 15:11:30 +0200208 if (UPGRADE_SALTSTACK.toBoolean()) {
Richard Felkl0e80d892018-06-20 13:44:54 +0200209 salt.enforceState(venvPepper, "I@linux:system", 'linux.system.repo', true)
210
Denis Egorenkocf8a7412018-11-21 14:05:35 +0400211 // as salt package update leads to service restart and token changing - re-create pepperEnv and rerun package update
212 try {
213 updateSaltStack("I@salt:master", '["salt-master", "salt-common", "salt-api", "salt-minion"]')
214 } catch (Exception e) {
215 python.setupPepperVirtualenv(venvPepper, SALT_MASTER_URL, SALT_MASTER_CREDENTIALS)
216 updateSaltStack("I@salt:master", '["salt-master", "salt-common", "salt-api", "salt-minion"]')
217 }
Richard Felkl0e80d892018-06-20 13:44:54 +0200218
219 updateSaltStack("I@salt:minion and not I@salt:master", '["salt-minion"]')
220 }
221
azvyagintsev6dac3802018-11-09 15:11:30 +0200222 if (UPDATE_PIPELINES.toBoolean()) {
Richard Felkl970e0082018-06-12 18:00:51 +0200223 triggerMirrorJob("git-mirror-downstream-mk-pipelines")
224 triggerMirrorJob("git-mirror-downstream-pipeline-library")
225 }
226
227 salt.enforceState(venvPepper, "I@jenkins:client", 'jenkins.client', true)
228
229 salt.cmdRun(venvPepper, "I@salt:master", "salt -C 'I@jenkins:client and I@docker:client' state.sls docker.client --async")
230
231 sleep(180)
232
233 common.infoMsg("Checking if Docker containers are up")
234
azvyagintsev6dac3802018-11-09 15:11:30 +0200235 try {
236 common.retry(10, 30) {
Richard Felkl970e0082018-06-12 18:00:51 +0200237 salt.cmdRun(venvPepper, 'I@jenkins:client and I@docker:client', "! docker service ls | tail -n +2 | grep -v -E '\\s([0-9])/\\1\\s'")
238 }
239 }
azvyagintsev6dac3802018-11-09 15:11:30 +0200240 catch (Exception ex) {
Richard Felkl970e0082018-06-12 18:00:51 +0200241 error("Docker containers for CI/CD services are having troubles with starting.")
242 }
Richard Felkl26cae4d2017-12-19 00:19:16 +0100243 }
244 }
Jakub Josefa63f9862018-01-11 17:58:38 +0100245 catch (Throwable e) {
246 // If there was an error or exception thrown, the build failed
247 currentBuild.result = "FAILURE"
248 throw e
Richard Felkl26cae4d2017-12-19 00:19:16 +0100249 }
Richard Felkl26cae4d2017-12-19 00:19:16 +0100250 }
Jakub Josef2c21c6c2018-02-08 18:51:42 +0100251}