blob: 66bad8a302e5181fde49bdf46ba8fc7cb0d1ef28 [file] [log] [blame]
Jiri Broulik60dcab32018-03-08 17:42:06 +01001/**
2 * Update packages on given nodes
3 *
4 * Expected parameters:
5 * SALT_MASTER_CREDENTIALS Credentials to the Salt API.
6 * SALT_MASTER_URL Full Salt API address [https://10.10.10.1:8000].
7 * SNAPSHOT_NAME Snapshot name
8 * CFG_NODE_PROVIDER Physical machine name hosting Salt-Master VM (ex. kvm01*)
9 * INTERACTIVE Ask interactive questions during pipeline run (bool)
10 * PER_NODE Target nodes will be managed one by one (bool)
11 * ROLLBACK_BY_REDEPLOY Omit taking live snapshots. Rollback is planned to be done by redeployment (bool)
12 * STOP_SERVICES Stop API services before update (bool)
13 * TARGET_UPDATES Comma separated list of nodes to update (Valid values are cfg,ctl,prx,msg,dbs,log,mon,mtr,ntw,nal,gtw-virtual,cmn,rgw,cid,cmp,kvm,osd,gtw-physical)
Jiri Broulik906e9972018-03-26 16:12:00 +020014 * TARGET_ROLLBACKS Comma separated list of nodes to rollback (Valid values are ctl,prx,msg,dbs,log,mon,mtr,ntw,nal,gtw-virtual,cmn,rgw,cmp,kvm,osd,gtw-physical)
15 * TARGET_MERGES Comma separated list of nodes to merge (Valid values are cfg,ctl,prx,msg,dbs,log,mon,mtr,ntw,nal,gtw-virtual,cmn,rgw,cid)
Jiri Broulik60dcab32018-03-08 17:42:06 +010016 * CTL_TARGET Salt targeted CTL nodes (ex. ctl*)
17 * PRX_TARGET Salt targeted PRX nodes (ex. prx*)
18 * MSG_TARGET Salt targeted MSG nodes (ex. msg*)
19 * DBS_TARGET Salt targeted DBS nodes (ex. dbs*)
20 * LOG_TARGET Salt targeted LOG nodes (ex. log*)
21 * MON_TARGET Salt targeted MON nodes (ex. mon*)
22 * MTR_TARGET Salt targeted MTR nodes (ex. mtr*)
23 * NTW_TARGET Salt targeted NTW nodes (ex. ntw*)
24 * NAL_TARGET Salt targeted NAL nodes (ex. nal*)
25 * CMN_TARGET Salt targeted CMN nodes (ex. cmn*)
26 * RGW_TARGET Salt targeted RGW nodes (ex. rgw*)
27 * CID_TARGET Salt targeted CID nodes (ex. cid*)
28 * CMP_TARGET Salt targeted physical compute nodes (ex. cmp001*)
29 * KVM_TARGET Salt targeted physical KVM nodes (ex. kvm01*)
30 * CEPH_OSD_TARGET Salt targeted physical Ceph OSD nodes (ex. osd001*)
Jiri Broulik906e9972018-03-26 16:12:00 +020031 * GTW_TARGET Salt targeted physical or virtual GTW nodes (ex. gtw01*)
Jiri Broulik60dcab32018-03-08 17:42:06 +010032 * REBOOT Reboot nodes after update (bool)
Jiri Broulik906e9972018-03-26 16:12:00 +020033 * ROLLBACK_PKG_VERSIONS Space separated list of pkgs=versions to rollback to on physical targeted machines (ex. pkg_name1=pkg_version1 pkg_name2=pkg_version2)
34 * PURGE_PKGS Space separated list of pkgs=versions to be purged on physical targeted machines (ex. pkg_name1=pkg_version1 pkg_name2=pkg_version2)
35 * REMOVE_PKGS Space separated list of pkgs=versions to be removed on physical targeted machines (ex. pkg_name1=pkg_version1 pkg_name2=pkg_version2)
Jiri Broulik60dcab32018-03-08 17:42:06 +010036 * RESTORE_GALERA Restore Galera DB (bool)
37 * RESTORE_CONTRAIL_DB Restore Cassandra and Zookeeper DBs for OpenContrail (bool)
38 *
39**/
40def common = new com.mirantis.mk.Common()
41def salt = new com.mirantis.mk.Salt()
42def python = new com.mirantis.mk.Python()
43def virsh = new com.mirantis.mk.Virsh()
44
45def updates = TARGET_UPDATES.tokenize(",").collect{it -> it.trim()}
46def rollbacks = TARGET_ROLLBACKS.tokenize(",").collect{it -> it.trim()}
47def merges = TARGET_MERGES.tokenize(",").collect{it -> it.trim()}
48
49def pepperEnv = "pepperEnv"
50def minions
51def result
52def packages
53def command
54def commandKwargs
55
56def updatePkgs(pepperEnv, target, targetType="", targetPackages="") {
57 def salt = new com.mirantis.mk.Salt()
58 def common = new com.mirantis.mk.Common()
59 def commandKwargs
60 def distUpgrade
61 def pkgs
62 def out
63
64 salt.enforceState(pepperEnv, target, 'linux.system.repo')
65
66 stage("List package upgrades") {
67 common.infoMsg("Listing all the packages that have a new update available on ${target}")
68 pkgs = salt.getReturnValues(salt.runSaltProcessStep(pepperEnv, target, 'pkg.list_upgrades', [], null, true))
69 if(targetPackages != "" && targetPackages != "*"){
70 common.infoMsg("Note that only the ${targetPackages} would be installed from the above list of available updates on the ${target}")
71 }
72 }
73
74 if (INTERACTIVE.toBoolean()) {
75 stage("Confirm live package upgrades on ${target}") {
76 if (targetPackages=="") {
77 def userInput = input(
78 id: 'userInput', message: 'Insert package names for update', parameters: [
79 [$class: 'TextParameterDefinition', defaultValue: pkgs.keySet().join(",").toString(), description: 'Package names (or *)', name: 'packages']
80 ])
81 if (userInput!= "" && userInput!= "*") {
82 targetPackages = userInput
83 }
84 } else {
85 input message: "Approve live package upgrades on ${target} nodes?"
86 }
87 }
88 } else {
89 targetPackages = pkgs.keySet().join(",").toString()
90 }
91
92 if (targetPackages != "") {
93 // list installed versions of pkgs that will be upgraded
94 def installedPkgs = []
95 def newPkgs = []
96 def targetPkgList = targetPackages.tokenize(',')
97 for (pkg in targetPkgList) {
98 def version
99 try {
100 def pkgsDetails = salt.getReturnValues(salt.runSaltProcessStep(pepperEnv, target, 'pkg.info_installed', [pkg], null, true))
101 version = pkgsDetails.get(pkg).get('version')
102 } catch (Exception er) {
103 common.infoMsg("${pkg} not installed yet")
104 }
105 if (version?.trim()) {
106 installedPkgs.add(pkg + '=' + version)
107 } else {
108 newPkgs.add(pkg)
109 }
110 }
111 common.warningMsg("the following list of pkgs will be upgraded")
112 common.warningMsg(installedPkgs.join(" "))
113 common.warningMsg("the following list of pkgs will be newly installed")
114 common.warningMsg(newPkgs.join(" "))
115 // set variables
116 command = "pkg.install"
117 packages = targetPackages
118 commandKwargs = ['only_upgrade': 'true','force_yes': 'true']
119
120 }else {
121 command = "pkg.upgrade"
122 commandKwargs = ['dist_upgrade': 'true']
123 distUpgrade = true
124 packages = null
125 }
126
127 // todo exception to cfg or cicd
128 stage("stop services on ${target}") {
129 if ((STOP_SERVICES.toBoolean()) && (targetType != 'cicd')) {
130 if (targetType == 'contrail') {
131 stopContrailServices(pepperEnv, target)
132 } else {
133 def probe = salt.getFirstMinion(pepperEnv, "${target}")
134 stopServices(pepperEnv, probe, target)
135 }
136 }
137 }
138
139 stage('Apply package upgrades') {
140 // salt master pkg
141 if (targetType == 'I@salt:master') {
142 common.warningMsg('salt-master pkg upgrade, rerun the pipeline if disconnected')
143 salt.runSaltProcessStep(pepperEnv, target, 'pkg.install', ['salt-master'], null, true, 5)
144 salt.minionsReachable(pepperEnv, 'I@salt:master', '*')
145 }
146 // salt minion pkg
147 salt.runSaltProcessStep(pepperEnv, target, 'pkg.install', ['salt-minion'], null, true, 5)
148 salt.minionsReachable(pepperEnv, 'I@salt:master', target)
149 common.infoMsg('Performing pkg upgrades ... ')
150 common.retry(3){
151 out = salt.runSaltCommand(pepperEnv, 'local', ['expression': target, 'type': 'compound'], command, true, packages, commandKwargs)
152 salt.printSaltCommandResult(out)
153 }
154 def osRelease = salt.getGrain(pepperEnv, target, 'lsb_distrib_codename')
155 if (osRelease.toString().toLowerCase().contains('trusty')) {
156 args = 'export DEBIAN_FRONTEND=noninteractive; apt-get -y -q --force-yes -o Dpkg::Options::=\"--force-confdef\" -o Dpkg::Options::=\"--force-confold\" '
157 } else {
158 args = 'export DEBIAN_FRONTEND=noninteractive; apt-get -y -q -f --allow-downgrades -o Dpkg::Options::=\"--force-confdef\" -o Dpkg::Options::=\"--force-confold\" '
159 }
160 if (out.toString().contains('errors:')) {
161 try {
162 if (packages?.trim()) {
163 packages = packages.replaceAll(',', ' ')
164 common.retry(3){
165 out = salt.runSaltProcessStep(pepperEnv, target, 'cmd.run', [args + ' install ' + packages])
166 }
167 } else {
168 if (distUpgrade) {
169 common.retry(3){
170 out = salt.runSaltProcessStep(pepperEnv, target, 'cmd.run', [args + ' dist-upgrade'])
171 }
172 } else {
173 common.retry(3){
174 out = salt.runSaltProcessStep(pepperEnv, target, 'cmd.run', [args + ' upgrade'])
175 }
176 } }
177 if (out.toString().contains('E: ')) {
178 common.errorMsg(out)
179 if (INTERACTIVE.toBoolean()) {
180 input message: "Pkgs update failed to be updated on ${target}. Please fix it manually."
181 } else {
182 salt.printSaltCommandResult(out)
183 throw new Exception("Pkgs update failed")
184 }
185 }
186 } catch (Exception e) {
187 common.errorMsg(out)
188 common.errorMsg(e)
189 if (INTERACTIVE.toBoolean()) {
190 input message: "Pkgs update failed to be updated on ${target}. Please fix it manually."
191 } else {
192 throw new Exception("Pkgs update failed")
193 }
194 }
195 }
196 }
197}
198
199def rollbackPkgs(pepperEnv, target, targetType = "", targetPackages="") {
200 def salt = new com.mirantis.mk.Salt()
201 def common = new com.mirantis.mk.Common()
202 def probe = salt.getFirstMinion(pepperEnv, "${target}")
203 def distUpgrade
204 def pkgs
205 def out
206
207 salt.enforceState(pepperEnv, target, 'linux.system.repo')
208
209 if (ROLLBACK_PKG_VERSIONS == "") {
210 stage("List package upgrades") {
211 common.infoMsg("Listing all the packages that have a new update available on ${target}")
212 pkgs = salt.getReturnValues(salt.runSaltProcessStep(pepperEnv, target, 'pkg.list_upgrades', [], null, true))
213 if(targetPackages != "" && targetPackages != "*"){
214 common.infoMsg("Note that only the ${targetPackages} would be installed from the above list of available updates on the ${target}")
215 }
216 }
217
218 if (INTERACTIVE.toBoolean()) {
219 stage("Confirm live package upgrades on ${target}") {
220 if(targetPackages==""){
221 timeout(time: 2, unit: 'HOURS') {
222 def userInput = input(
223 id: 'userInput', message: 'Insert package names for update', parameters: [
224 [$class: 'TextParameterDefinition', defaultValue: pkgs.keySet().join(",").toString(), description: 'Package names (or *)', name: 'packages']
225 ])
226 if(userInput!= "" && userInput!= "*"){
227 targetPackages = userInput
228 }
229 }
230 }else{
231 timeout(time: 2, unit: 'HOURS') {
232 input message: "Approve live package upgrades on ${target} nodes?"
233 }
234 }
235 }
236 } else {
237 targetPackages = pkgs.keySet().join(",").toString()
238 }
239 } else {
240 targetPackages = ROLLBACK_PKG_VERSIONS
241 }
242
243 if (targetPackages != "") {
244 // set variables
245 packages = targetPackages
246 } else {
247 distUpgrade = true
248 packages = null
249 }
250
251 stage("stop services on ${target}") {
252 try {
253 if (INTERACTIVE.toBoolean()) {
254 input message: "Click PROCEED to interactively stop services on ${target}. Otherwise click ABORT to skip stopping them and continue."
255 }
256 } catch (Exception er) {
257 common.infoMsg('skipping stopping services')
258 return
259 }
260 if (STOP_SERVICES.toBoolean()) {
261 stopServices(pepperEnv, probe, target)
262 }
263 }
264
265 stage('Apply package downgrades') {
266 args = 'export DEBIAN_FRONTEND=noninteractive; apt-get -y -q --allow-downgrades -o Dpkg::Options::=\"--force-confdef\" -o Dpkg::Options::=\"--force-confold\" '
267 common.infoMsg('Performing pkgs purge/remove ... ')
268 try {
269 if (PURGE_PKGS != "") {
270 def purgePackages = PURGE_PKGS.replaceAll(',', ' ')
271 common.retry(3){
272 out = salt.runSaltProcessStep(pepperEnv, target, 'cmd.run', [args + ' purge ' + purgePackages])
273 }
274 }
275 if (REMOVE_PKGS != "") {
276 def removePackages = REMOVE_PKGS.replaceAll(',', ' ')
277 common.retry(3){
278 out = salt.runSaltProcessStep(pepperEnv, target, 'cmd.run', [args + ' remove ' + removePackages])
279 }
280 }
281 if (out.toString().contains('E: ')) {
282 common.errorMsg(out)
283 if (INTERACTIVE.toBoolean()) {
284 input message: "Pkgs ${packages} purge failed on ${target}. Please fix it manually."
285 } else {
286 salt.printSaltCommandResult(out)
287 throw new Exception("Pkgs {packages} purge failed")
288 }
289 }
290 } catch (Exception e) {
291 common.errorMsg(out)
292 common.errorMsg(e)
293 if (INTERACTIVE.toBoolean()) {
294 input message: "Pkgs {packages} purge on ${target}. Please fix it manually."
295 } else {
296 throw new Exception("Pkgs {packages} purge failed")
297 }
298 }
299
300 common.infoMsg('Performing pkg downgrades ... ')
301 try {
302 packages = packages.replaceAll(',', ' ')
303 if (packages?.trim()) {
304 packages = packages.replaceAll(',', ' ')
305 common.retry(3){
306 out = salt.runSaltProcessStep(pepperEnv, target, 'cmd.run', [args + ' install salt-minion'], null, true, 5)
307 }
308 salt.minionsReachable(pepperEnv, 'I@salt:master', target)
309 common.retry(3){
310 out = salt.runSaltProcessStep(pepperEnv, target, 'cmd.run', [args + ' install ' + packages])
311 }
312 } else {
313 if (distUpgrade) {
314 common.retry(3){
315 out = salt.runSaltProcessStep(pepperEnv, target, 'cmd.run', [args + ' dist-upgrade'])
316 }
317 } else {
318 common.retry(3){
319 out = salt.runSaltProcessStep(pepperEnv, target, 'cmd.run', [args + ' upgrade'])
320 }
321 }
322 }
323 if (out.toString().contains('E: ')) {
324 common.errorMsg(out)
325 if (INTERACTIVE.toBoolean()) {
326 input message: "Pkgs rollback failed on ${target}. Please fix it manually."
327 } else {
328 salt.printSaltCommandResult(out)
329 throw new Exception("Pkgs rollback failed")
330 }
331 }
332 } catch (Exception e) {
333 common.errorMsg(out)
334 common.errorMsg(e)
335 if (INTERACTIVE.toBoolean()) {
336 input message: "Pkgs rollback failed on ${target}. Please fix it manually."
337 } else {
338 throw new Exception("Pkgs rollback failed")
339 }
340 }
341 }
342}
343
344def getCfgNodeProvider(pepperEnv, master_name) {
345 def salt = new com.mirantis.mk.Salt()
346 def common = new com.mirantis.mk.Common()
347 if (!CFG_NODE_PROVIDER?.trim()) {
348 kvms = salt.getMinions(pepperEnv, 'I@salt:control')
349 for (kvm in kvms) {
350 try {
351 vms = salt.getReturnValues(salt.runSaltProcessStep(pepperEnv, kvm, 'virt.list_active_vms', [], null, true))
352 if (vms.toString().contains(master_name)) {
353 CFG_NODE_PROVIDER = kvm
354 //break
355 }
356 } catch (Exception er) {
357 common.infoMsg("${master_name} not present on ${kvm}")
358 }
359 }
360 }
361}
362
363/*
364def rollbackSaltMaster(pepperEnv, target, path='/var/lib/libvirt/images') {
365 def salt = new com.mirantis.mk.Salt()
366 def common = new com.mirantis.mk.Common()
367 try {
368 input message: "PART1 - Are you sure to rollback ${target}? To rollback click on PROCEED. To skip rollback PART1 click on ABORT."
369 } catch (Exception er) {
370 common.infoMsg("skipping rollback of ${target}")
371 return
372 }
373 def domain = salt.getDomainName(pepperEnv)
374 def master = salt.getReturnValues(salt.getPillar(pepperEnv, target, 'linux:network:hostname'))
375 getCfgNodeProvider(pepperEnv, master)
376 try {
377 try {
378 salt.getReturnValues(salt.cmdRun(pepperEnv, CFG_NODE_PROVIDER, "ls -la ${path}/${master}.${domain}.xml"))
379 common.errorMsg('Pipeline is about to disconnect from salt-api. You will have to rerun the pipeline with ROLLBACK_CFG checked and skip PART1 to finish rollback.')
380 salt.cmdRun(pepperEnv, CFG_NODE_PROVIDER, "virsh destroy ${master}.${domain}; virsh define ${path}/${master}.${domain}.xml; virsh start ${master}.${domain} ")
381 } catch (Exception er) {
382 common.errorMsg(er)
383 input message: "Rollback for ${target} failed. Rollback manually."
384 }
385 } catch (Exception er) {
386 common.errorMsg(er)
387 input message: "Rollback for ${target} failed. Rollback manually."
388 }
389}
390
391def finishSaltMasterRollback(pepperEnv, target, path='/var/lib/libvirt/images') {
392 def salt = new com.mirantis.mk.Salt()
393 def common = new com.mirantis.mk.Common()
394 def virsh = new com.mirantis.mk.Virsh()
395 try {
396 input message: "PART2 - Are you sure to finalize ${target} rollback? Click on PROCEED. To skip rollback click on ABORT."
397 } catch (Exception er) {
398 common.infoMsg("skipping finalize rollback of ${target}")
399 return
400 }
401 salt.minionsReachable(pepperEnv, 'I@salt:master', '*')
402 def domain = salt.getDomainName(pepperEnv)
403 def master = salt.getReturnValues(salt.getPillar(pepperEnv, target, 'linux:network:hostname'))
404 getCfgNodeProvider(pepperEnv, master)
405 try {
406 virsh.liveSnapshotAbsent(pepperEnv, CFG_NODE_PROVIDER, master, SNAPSHOT_NAME, path)
407 // purge and setup previous repos
408 salt.enforceState(pepperEnv, target, 'linux.system.repo')
409 } catch (Exception e) {
410 common.errorMsg(e)
411 input message: "Check what failed after ${target} rollback. Do you want to PROCEED?"
412 }
413}*/
414
415def stopServices(pepperEnv, probe, target) {
416 def openstack = new com.mirantis.mk.Openstack()
417 def services = []
418 services.add('keepalived')
419 services.add('nginx')
420 services.add('haproxy')
421 services.add('nova-api')
422 services.add('cinder')
423 services.add('glance')
424 services.add('heat')
425 services.add('neutron')
426 services.add('apache2')
427 services.add('rabbitmq-server')
428 if (INTERACTIVE.toBoolean()) {
429 openstack.stopServices(pepperEnv, probe, target, services, true)
430 } else {
431 openstack.stopServices(pepperEnv, probe, target, services)
432 }
433}
434
435// must be stopped separately due to OC on Trusty
436def stopContrailServices(pepperEnv, target) {
437 def salt = new com.mirantis.mk.Salt()
438 def common = new com.mirantis.mk.Common()
439 def services = []
440 services.add('keepalived')
441 services.add('haproxy')
442 services.add('supervisor-control')
443 services.add('supervisor-config')
444 services.add('supervisor-database')
445 services.add('zookeeper')
446 services.add('ifmap-server')
447 for (s in services) {
448 try {
449 salt.runSaltProcessStep(pepperEnv, target, 'service.stop', [s], null, true)
450 } catch (Exception er) {
451 common.infoMsg(er)
452 }
453 }
454}
455
456def highstate(pepperEnv, target) {
457 def salt = new com.mirantis.mk.Salt()
458 def common = new com.mirantis.mk.Common()
459
460 stage("Apply highstate on ${target} nodes") {
461 try {
462 common.retry(3){
Jiri Broulikad606d02018-03-28 14:22:43 +0200463 salt.enforceHighstate(pepperEnv, target)
Jiri Broulik60dcab32018-03-08 17:42:06 +0100464 }
465 } catch (Exception e) {
466 common.errorMsg(e)
467 if (INTERACTIVE.toBoolean()) {
468 input message: "Highstate failed on ${target}. Fix it manually or run rollback on ${target}."
469 } else {
470 throw new Exception("highstate failed")
471 }
472 }
473 }
474 // optionally reboot
475 if (REBOOT.toBoolean()) {
476 stage("Reboot ${target} nodes") {
477 salt.runSaltProcessStep(pepperEnv, target, 'system.reboot', null, null, true, 5)
478 sleep(10)
479 salt.minionsReachable(pepperEnv, 'I@salt:master', target)
480 }
481 }
482}
483
484def rollback(pepperEnv, tgt, generalTarget) {
485 def common = new com.mirantis.mk.Common()
486 try {
487 if (INTERACTIVE.toBoolean()) {
488 input message: "Are you sure to rollback ${generalTarget}? To rollback click on PROCEED. To skip rollback click on ABORT."
489 }
490 } catch (Exception er) {
491 common.infoMsg('skipping rollback')
492 return
493 }
494 try {
495 rollbackLiveSnapshot(pepperEnv, tgt, generalTarget)
496 } catch (Exception err) {
497 common.errorMsg(err)
498 if (INTERACTIVE.toBoolean()) {
499 input message: "Rollback for ${tgt} failed please fix it manually before clicking PROCEED."
500 } else {
501 throw new Exception("Rollback failed for ${tgt}")
502 }
503 }
504}
505
506def liveSnapshot(pepperEnv, tgt, generalTarget) {
507 def salt = new com.mirantis.mk.Salt()
508 def common = new com.mirantis.mk.Common()
509 def virsh = new com.mirantis.mk.Virsh()
510 def domain = salt.getDomainName(pepperEnv)
511 def target_hosts = salt.getMinionsSorted(pepperEnv, "${tgt}")
512 common.warningMsg(target_hosts)
513 //def nodeCount = 1
514 for (t in target_hosts) {
515 def target = salt.stripDomainName(t)
516 def nodeCount = target[4]
517 common.warningMsg(nodeCount)
518 def nodeProvider = salt.getNodeProvider(pepperEnv, "${generalTarget}0${nodeCount}")
519 virsh.liveSnapshotPresent(pepperEnv, nodeProvider, target, SNAPSHOT_NAME)
520 //nodeCount++
521 }
522}
523
524def mergeSnapshot(pepperEnv, tgt, generalTarget='') {
525 def salt = new com.mirantis.mk.Salt()
526 def virsh = new com.mirantis.mk.Virsh()
527 def domain = salt.getDomainName(pepperEnv)
528 def target_hosts = salt.getMinionsSorted(pepperEnv, "${tgt}")
529 def nodeCount = 1
530 for (t in target_hosts) {
531 if (tgt == 'I@salt:master') {
532 def master = salt.getReturnValues(salt.getPillar(pepperEnv, target, 'linux:network:hostname'))
533 getCfgNodeProvider(pepperEnv, master)
534 virsh.liveSnapshotMerge(pepperEnv, CFG_NODE_PROVIDER, master, SNAPSHOT_NAME)
535 } else {
536 def target = salt.stripDomainName(t)
537 def nodeProvider = salt.getNodeProvider(pepperEnv, "${generalTarget}0${nodeCount}")
538 virsh.liveSnapshotMerge(pepperEnv, nodeProvider, target, SNAPSHOT_NAME)
539 }
540 nodeCount++
541 }
Jiri Broulik906e9972018-03-26 16:12:00 +0200542 salt.minionsReachable(pepperEnv, 'I@salt:master', tgt)
Jiri Broulik60dcab32018-03-08 17:42:06 +0100543}
544
545
546
547def rollbackLiveSnapshot(pepperEnv, tgt, generalTarget) {
548 def salt = new com.mirantis.mk.Salt()
549 def virsh = new com.mirantis.mk.Virsh()
550 def common = new com.mirantis.mk.Common()
551 def domain = salt.getDomainName(pepperEnv)
552 def target_hosts = salt.getMinionsSorted(pepperEnv, "${tgt}")
553 // first destroy all vms
554 def nodeCount = 1
555 for (t in target_hosts) {
556 def target = salt.stripDomainName(t)
557 def nodeProvider = salt.getNodeProvider(pepperEnv, "${generalTarget}0${nodeCount}")
558 salt.runSaltProcessStep(pepperEnv, "${nodeProvider}*", 'virt.destroy', ["${target}.${domain}"], null, true)
559 nodeCount++
560 }
561 nodeCount = 1
562 // rollback vms
563 for (t in target_hosts) {
564 def target = salt.stripDomainName(t)
565 def nodeProvider = salt.getNodeProvider(pepperEnv, "${generalTarget}0${nodeCount}")
566 virsh.liveSnapshotRollback(pepperEnv, nodeProvider, target, SNAPSHOT_NAME)
567 nodeCount++
568 }
569 try {
570 salt.minionsReachable(pepperEnv, 'I@salt:master', tgt)
571 // purge and setup previous repos
572 salt.enforceState(pepperEnv, tgt, 'linux.system.repo')
573 } catch (Exception e) {
574 common.errorMsg(e)
575 if (INTERACTIVE.toBoolean()) {
576 input message: "Salt state linux.system.repo on ${tgt} failed. Do you want to PROCEED?."
577 } else {
578 throw new Exception("Salt state linux.system.repo on ${tgt} failed")
579 }
580 }
581}
582
583def removeNode(pepperEnv, tgt, generalTarget) {
584 def salt = new com.mirantis.mk.Salt()
585 def virsh = new com.mirantis.mk.Virsh()
586 def common = new com.mirantis.mk.Common()
587 def domain = salt.getDomainName(pepperEnv)
588 def target_hosts = salt.getMinionsSorted(pepperEnv, "${tgt}")
589 // first destroy all vms
590 def nodeCount = 1
591 for (t in target_hosts) {
592 def target = salt.stripDomainName(t)
593 def nodeProvider = salt.getNodeProvider(pepperEnv, "${generalTarget}0${nodeCount}")
594 salt.runSaltProcessStep(pepperEnv, "${nodeProvider}*", 'virt.destroy', ["${target}.${domain}"], null, true)
595 salt.runSaltProcessStep(pepperEnv, "${nodeProvider}*", 'virt.undefine', ["${target}.${domain}"], null, true)
596 try {
597 salt.cmdRun(pepperEnv, 'I@salt:master', "salt-key -d ${target}.${domain} -y")
598 } catch (Exception e) {
599 common.warningMsg('does not match any accepted, unaccepted or rejected keys. They were probably already removed. We should continue to run')
600 }
601 nodeCount++
602 }
603}
604
Jiri Broulik906e9972018-03-26 16:12:00 +0200605def saltMasterBackup(pepperEnv) {
606 def salt = new com.mirantis.mk.Salt()
607 salt.enforceState(pepperEnv, 'I@salt:master', 'backupninja')
608 salt.cmdRun(pepperEnv, 'I@salt:master', "su root -c 'backupninja -n --run /etc/backup.d/200.backup.rsync'")
609}
610
Jiri Broulik60dcab32018-03-08 17:42:06 +0100611def backupCeph(pepperEnv, tgt) {
612 def salt = new com.mirantis.mk.Salt()
613 salt.enforceState(pepperEnv, 'I@ceph:backup:server', 'ceph.backup')
614 salt.enforceState(pepperEnv, "I@ceph:backup:client and ${tgt}", 'ceph.backup')
615 salt.cmdRun(pepperEnv, "I@ceph:backup:client and ${tgt}", "su root -c '/usr/local/bin/ceph-backup-runner-call.sh -s'")
616}
617
618def backupGalera(pepperEnv) {
619 def salt = new com.mirantis.mk.Salt()
620 salt.enforceState(pepperEnv, 'I@xtrabackup:server', ['linux.system.repo', 'xtrabackup'])
621 salt.enforceState(pepperEnv, 'I@xtrabackup:client', ['linux.system.repo', 'openssh.client'])
622 salt.cmdRun(pepperEnv, 'I@xtrabackup:client', "su root -c 'salt-call state.sls xtrabackup'")
623 salt.cmdRun(pepperEnv, 'I@xtrabackup:client', "su root -c '/usr/local/bin/innobackupex-runner.sh -s -f'")
624}
625
626// cluster galera - wsrep_cluster_size
627def clusterGalera(pepperEnv) {
628 def salt = new com.mirantis.mk.Salt()
629 def common = new com.mirantis.mk.Common()
630 try {
631 salt.runSaltProcessStep(pepperEnv, 'I@galera:slave', 'service.stop', ['mysql'])
632 } catch (Exception er) {
633 common.warningMsg('Mysql service already stopped')
634 }
635 try {
636 salt.runSaltProcessStep(pepperEnv, 'I@galera:master', 'service.stop', ['mysql'])
637 } catch (Exception er) {
638 common.warningMsg('Mysql service already stopped')
639 }
640 try {
641 salt.cmdRun(pepperEnv, 'I@galera:slave', "rm /var/lib/mysql/ib_logfile*")
642 } catch (Exception er) {
643 common.warningMsg('Files are not present')
644 }
645 salt.cmdRun(pepperEnv, 'I@galera:master', "sed -i '/gcomm/c\\wsrep_cluster_address=\"gcomm://\"' /etc/mysql/my.cnf")
646 salt.runSaltProcessStep(pepperEnv, 'I@galera:master', 'service.start', ['mysql'])
647 // wait until mysql service on galera master is up
648 try {
649 salt.commandStatus(pepperEnv, 'I@galera:master', 'service mysql status', 'running')
650 } catch (Exception er) {
651 if (INTERACTIVE.toBoolean()) {
652 input message: "Database is not running please fix it first and only then click on PROCEED."
653 } else {
654 throw new Exception("Database is not running correctly")
655 }
656 }
657 salt.runSaltProcessStep(pepperEnv, 'I@galera:slave', 'service.start', ['mysql'])
658}
659
660def restoreGalera(pepperEnv) {
661 def salt = new com.mirantis.mk.Salt()
662 def common = new com.mirantis.mk.Common()
663 def openstack = new com.mirantis.mk.Openstack()
664 salt.cmdRun(pepperEnv, 'I@xtrabackup:client', "rm -rf /var/lib/mysql/*")
665 openstack.restoreGaleraDb(pepperEnv)
666}
667
668def backupZookeeper(pepperEnv) {
669 def salt = new com.mirantis.mk.Salt()
670 def common = new com.mirantis.mk.Common()
671 salt.enforceState(pepperEnv, 'I@zookeeper:backup:server', 'zookeeper.backup')
672 salt.enforceState(pepperEnv, 'I@zookeeper:backup:client', 'zookeeper.backup')
673 try {
674 salt.cmdRun(pepperEnv, 'I@opencontrail:control', "su root -c '/usr/local/bin/zookeeper-backup-runner.sh -s'")
675 } catch (Exception er) {
676 throw new Exception('Zookeeper failed to backup. Please fix it before continuing.')
677 }
678}
679
680def backupCassandra(pepperEnv) {
681 def salt = new com.mirantis.mk.Salt()
682 def common = new com.mirantis.mk.Common()
683
684 salt.enforceState(pepperEnv, 'I@cassandra:backup:server', 'cassandra.backup')
685 salt.enforceState(pepperEnv, 'I@cassandra:backup:client', 'cassandra.backup')
686 try {
687 salt.cmdRun(pepperEnv, 'I@cassandra:backup:client', "su root -c '/usr/local/bin/cassandra-backup-runner-call.sh -s'")
688 } catch (Exception er) {
689 throw new Exception('Cassandra failed to backup. Please fix it before continuing.')
690 }
691}
692
693def backupContrail(pepperEnv) {
694 backupZookeeper(pepperEnv)
695 backupCassandra(pepperEnv)
696}
697
698// cassandra and zookeeper
699def restoreContrailDb(pepperEnv) {
700 def salt = new com.mirantis.mk.Salt()
701 def common = new com.mirantis.mk.Common()
702 build job: "deploy-zookeeper-restore", parameters: [
703 [$class: 'StringParameterValue', name: 'SALT_MASTER_CREDENTIALS', value: SALT_MASTER_CREDENTIALS],
704 [$class: 'StringParameterValue', name: 'SALT_MASTER_URL', value: SALT_MASTER_URL]
705 ]
706 build job: "deploy-cassandra-db-restore", parameters: [
707 [$class: 'StringParameterValue', name: 'SALT_MASTER_CREDENTIALS', value: SALT_MASTER_CREDENTIALS],
708 [$class: 'StringParameterValue', name: 'SALT_MASTER_URL', value: SALT_MASTER_URL]
709 ]
710}
711
Jiri Broulikd2dd5632018-03-27 15:44:56 +0200712def verifyAPIs(pepperEnv, target) {
Jiri Broulik60dcab32018-03-08 17:42:06 +0100713 def salt = new com.mirantis.mk.Salt()
714 def common = new com.mirantis.mk.Common()
Jiri Broulikad606d02018-03-28 14:22:43 +0200715 def out = salt.cmdRun(pepperEnv, target, '. /root/keystonercv3; openstack service list; openstack image list; openstack flavor list; openstack compute service list; openstack server list; openstack network list; openstack volume list; openstack orchestration service list')
716 if (out.toString().toLowerCase().contains('error')) {
717 common.errorMsg(out)
718 if (INTERACTIVE.toBoolean()) {
719 input message: "APIs are not working as expected. Please fix it manually."
720 } else {
721 throw new Exception("APIs are not working as expected")
722 }
723 }
Jiri Broulik60dcab32018-03-08 17:42:06 +0100724}
725
Jiri Broulikad606d02018-03-28 14:22:43 +0200726def verifyGalera(pepperEnv, target, count=0, maxRetries=200) {
Jiri Broulik60dcab32018-03-08 17:42:06 +0100727 def salt = new com.mirantis.mk.Salt()
728 def common = new com.mirantis.mk.Common()
Jiri Broulikad606d02018-03-28 14:22:43 +0200729 def out
730 while(count < maxRetries) {
731 try {
732 out = salt.getReturnValues(salt.cmdRun(pepperEnv, target, 'salt-call mysql.status | grep -A1 wsrep_cluster_size'))
733 } catch (Exception er) {
734 common.infoMsg(er)
735 }
736 if ((!out.toString().contains('wsrep_cluster_size')) || (out.toString().contains('0'))) {
737 count++
738 if (count == maxRetries) {
739 if (INTERACTIVE.toBoolean()) {
740 input message: "Galera is not working as expected. Please check it and fix it first before clicking on PROCEED."
741 } else {
742 common.errorMsg(out)
743 throw new Exception("Galera is not working as expected")
744 }
745 }
746 sleep(time: 500, unit: 'MILLISECONDS')
Jiri Broulik60dcab32018-03-08 17:42:06 +0100747 } else {
Jiri Broulikad606d02018-03-28 14:22:43 +0200748 break
Jiri Broulik60dcab32018-03-08 17:42:06 +0100749 }
750 }
751}
752
753def verifyContrail(pepperEnv, target) {
754 def salt = new com.mirantis.mk.Salt()
755 def common = new com.mirantis.mk.Common()
756 salt.commandStatus(pepperEnv, target, "contrail-status | grep -v == | grep -v \'disabled on boot\' | grep -v nodemgr | grep -v active | grep -v backup", null, false)
757}
758
759
760def verifyService(pepperEnv, target, service) {
761 def salt = new com.mirantis.mk.Salt()
762 def common = new com.mirantis.mk.Common()
763 def targetHosts = salt.getMinionsSorted(pepperEnv, target)
764 for (t in targetHosts) {
765 try {
766 salt.commandStatus(pepperEnv, t, "service ${service} status", 'running')
767 } catch (Exception er) {
768 common.errorMsg(er)
769 if (INTERACTIVE.toBoolean()) {
770 input message: "${service} service is not running correctly on ${t}. Please fix it first manually and only then click on PROCEED."
771 } else {
772 throw new Exception("${service} service is not running correctly on ${t}")
773 }
774 }
775 }
776}
777
778def verifyCeph(pepperEnv, target, type) {
779 def salt = new com.mirantis.mk.Salt()
780 def common = new com.mirantis.mk.Common()
781 def targetHosts = salt.getMinionsSorted(pepperEnv, target)
782 for (t in targetHosts) {
783 def hostname = salt.getReturnValues(salt.getPillar(pepperEnv, t, 'linux:network:hostname'))
784 try {
785 salt.commandStatus(pepperEnv, t, "systemctl status ceph-${type}${hostname}", 'running')
786 } catch (Exception er) {
787 common.errorMsg(er)
788 if (INTERACTIVE.toBoolean()) {
789 input message: "Ceph-${type}${hostname} service is not running correctly on ${t}. Please fix it first manually and only then click on PROCEED."
790 } else {
791 throw new Exception("Ceph-${type}${hostname} service is not running correctly on ${t}")
792 }
793 }
794 }
795}
796
797def verifyCephOsds(pepperEnv, target) {
798 def salt = new com.mirantis.mk.Salt()
799 def common = new com.mirantis.mk.Common()
800 def targetHosts = salt.getMinionsSorted(pepperEnv, target)
801 for (t in targetHosts) {
802 def osd_ids = []
803 // get list of osd disks of the host
804 salt.runSaltProcessStep(pepperEnv, t, 'saltutil.sync_grains', [], null, true, 5)
805 def cephGrain = salt.getGrain(pepperEnv, t, 'ceph')
806 if(cephGrain['return'].isEmpty()){
807 throw new Exception("Ceph salt grain cannot be found!")
808 }
809 common.print(cephGrain)
810 def ceph_disks = cephGrain['return'][0].values()[0].values()[0]['ceph_disk']
811 for (i in ceph_disks) {
812 def osd_id = i.getKey().toString()
813 osd_ids.add('osd.' + osd_id)
814 print("Will check osd." + osd_id)
815 }
816 for (i in osd_ids) {
817 try {
818 salt.commandStatus(pepperEnv, t, "ceph osd tree | grep -w ${i}", 'up')
819 } catch (Exception er) {
820 common.errorMsg(er)
821 if (INTERACTIVE.toBoolean()) {
822 input message: "Ceph ${i} is not running correctly on ${t}. Please fix it first manually and only then click on PROCEED."
823 } else {
824 throw new Exception("Ceph ${i} is not running correctly on ${t}")
825 }
826 }
827 }
828 }
829}
830
831
832timeout(time: 12, unit: 'HOURS') {
833 node() {
834 try {
835
836 stage('Setup virtualenv for Pepper') {
837 python.setupPepperVirtualenv(pepperEnv, SALT_MASTER_URL, SALT_MASTER_CREDENTIALS)
838 }
839
840 // TODO, add possibility to update just specific components like kernel, openstack, contrail, ovs, rabbitmq, galera, etc.
841
842 /*
843 * Update section
844 */
845 if (updates.contains("cfg")) {
846 def target = 'I@salt:master'
847 if (salt.testTarget(pepperEnv, target)) {
848 def master = salt.getReturnValues(salt.getPillar(pepperEnv, target, 'linux:network:hostname'))
849 getCfgNodeProvider(pepperEnv, master)
850 if (!ROLLBACK_BY_REDEPLOY.toBoolean()) {
851 virsh.liveSnapshotPresent(pepperEnv, CFG_NODE_PROVIDER, master, SNAPSHOT_NAME)
Jiri Broulik906e9972018-03-26 16:12:00 +0200852 } else {
853 saltMasterBackup(pepperEnv)
Jiri Broulik60dcab32018-03-08 17:42:06 +0100854 }
855 if (PER_NODE.toBoolean()) {
856 def targetHosts = salt.getMinionsSorted(pepperEnv, target)
857 for (t in targetHosts) {
858 updatePkgs(pepperEnv, t, target)
859 highstate(pepperEnv, t)
860 }
861 } else {
862 updatePkgs(pepperEnv, target)
863 highstate(pepperEnv, target)
864 }
865 }
866 }
867
868 if (updates.contains("ctl")) {
869 def target = CTL_TARGET
870 if (salt.testTarget(pepperEnv, target)) {
871 if (!ROLLBACK_BY_REDEPLOY.toBoolean()) {
872 def generalTarget = 'ctl'
873 liveSnapshot(pepperEnv, target, generalTarget)
874 }
875 if (PER_NODE.toBoolean()) {
876 def targetHosts = salt.getMinionsSorted(pepperEnv, target)
877 for (t in targetHosts) {
878 updatePkgs(pepperEnv, t)
879 highstate(pepperEnv, t)
880 }
881 } else {
882 updatePkgs(pepperEnv, target)
883 highstate(pepperEnv, target)
884 }
885 verifyAPIs(pepperEnv, target)
886 }
887 }
888
889 if (updates.contains("prx")) {
890 def target = PRX_TARGET
891 if (salt.testTarget(pepperEnv, target)) {
892 if (!ROLLBACK_BY_REDEPLOY.toBoolean()) {
893 def generalTarget = 'prx'
894 liveSnapshot(pepperEnv, target, generalTarget)
895 }
896 if (PER_NODE.toBoolean()) {
897 def targetHosts = salt.getMinionsSorted(pepperEnv, target)
898 for (t in targetHosts) {
899 updatePkgs(pepperEnv, t)
900 highstate(pepperEnv, t)
901 }
902 } else {
903 updatePkgs(pepperEnv, target)
904 highstate(pepperEnv, target)
905 }
906 verifyService(pepperEnv, target, 'nginx')
907 }
908 }
909
910 if (updates.contains("msg")) {
911 def target = MSG_TARGET
912 if (salt.testTarget(pepperEnv, target)) {
913 if (!ROLLBACK_BY_REDEPLOY.toBoolean()) {
914 def generalTarget = 'msg'
915 liveSnapshot(pepperEnv, target, generalTarget)
916 }
917 if (PER_NODE.toBoolean()) {
918 def targetHosts = salt.getMinionsSorted(pepperEnv, target)
919 for (t in targetHosts) {
920 updatePkgs(pepperEnv, t)
921 highstate(pepperEnv, t)
922 }
923 } else {
924 updatePkgs(pepperEnv, target, target)
925 highstate(pepperEnv, target)
926 }
927 verifyService(pepperEnv, target, 'rabbitmq-server')
928 }
929 }
930
931 if (updates.contains("dbs")) {
932 def target = DBS_TARGET
933 if (salt.testTarget(pepperEnv, target)) {
934 backupGalera(pepperEnv)
Jiri Broulik60dcab32018-03-08 17:42:06 +0100935 if (!ROLLBACK_BY_REDEPLOY.toBoolean()) {
936 def generalTarget = 'dbs'
937 liveSnapshot(pepperEnv, target, generalTarget)
938 }
Jiri Broulikd2dd5632018-03-27 15:44:56 +0200939 if (REBOOT.toBoolean() || PER_NODE.toBoolean()) {
Jiri Broulik60dcab32018-03-08 17:42:06 +0100940 def targetHosts = salt.getMinionsSorted(pepperEnv, target)
Jiri Broulik60dcab32018-03-08 17:42:06 +0100941 for (t in targetHosts) {
942 updatePkgs(pepperEnv, t)
943 highstate(pepperEnv, t)
Jiri Broulikad606d02018-03-28 14:22:43 +0200944 verifyGalera(pepperEnv, t)
Jiri Broulik60dcab32018-03-08 17:42:06 +0100945 }
946 } else {
947 updatePkgs(pepperEnv, target)
948 highstate(pepperEnv, target)
Jiri Broulikad606d02018-03-28 14:22:43 +0200949 verifyGalera(pepperEnv, target)
Jiri Broulik60dcab32018-03-08 17:42:06 +0100950 }
Jiri Broulik60dcab32018-03-08 17:42:06 +0100951 }
952 }
953
954 if (updates.contains("ntw")) {
955 def target = NTW_TARGET
956 if (salt.testTarget(pepperEnv, target)) {
957 backupContrail(pepperEnv)
958 if (!ROLLBACK_BY_REDEPLOY.toBoolean()) {
959 def generalTarget = 'ntw'
960 liveSnapshot(pepperEnv, target, generalTarget)
961 }
962 if (PER_NODE.toBoolean()) {
963 def targetHosts = salt.getMinionsSorted(pepperEnv, target)
964 for (t in targetHosts) {
965 updatePkgs(pepperEnv, t, 'contrail')
966 highstate(pepperEnv, t)
967 verifyContrail(pepperEnv, t)
968 }
969 } else {
970 updatePkgs(pepperEnv, target, 'contrail')
971 highstate(pepperEnv, target)
972 verifyContrail(pepperEnv, target)
973 }
974 }
975 }
976
977 if (updates.contains("nal")) {
978 def target = NAL_TARGET
979 if (salt.testTarget(pepperEnv, target)) {
980 if (!ROLLBACK_BY_REDEPLOY.toBoolean()) {
981 def generalTarget = 'nal'
982 liveSnapshot(pepperEnv, target, generalTarget)
983 }
984 if (PER_NODE.toBoolean()) {
985 def targetHosts = salt.getMinionsSorted(pepperEnv, target)
986 for (t in targetHosts) {
987 updatePkgs(pepperEnv, t, 'contrail')
988 highstate(pepperEnv, t)
989 }
990 } else {
991 updatePkgs(pepperEnv, target, 'contrail')
992 highstate(pepperEnv, target)
993 }
994 verifyContrail(pepperEnv, target)
995 }
996 }
997
998 if (updates.contains("gtw-virtual")) {
999 def target = GTW_TARGET
1000 if (salt.testTarget(pepperEnv, target)) {
1001 if (!ROLLBACK_BY_REDEPLOY.toBoolean()) {
1002 def generalTarget = 'gtw'
1003 liveSnapshot(pepperEnv, target, generalTarget)
1004 }
1005 if (PER_NODE.toBoolean()) {
1006 def targetHosts = salt.getMinionsSorted(pepperEnv, target)
1007 for (t in targetHosts) {
1008 updatePkgs(pepperEnv, t)
1009 highstate(pepperEnv, t)
1010 }
1011 } else {
1012 updatePkgs(pepperEnv, target)
1013 highstate(pepperEnv, target)
1014 }
1015 verifyService(pepperEnv, target, 'neutron-dhcp-agent')
1016 }
1017 }
1018
1019 if (updates.contains("cmn")) {
1020 def target = CMN_TARGET
1021 if (salt.testTarget(pepperEnv, target)) {
1022 if (!ROLLBACK_BY_REDEPLOY.toBoolean()) {
1023 def generalTarget = 'cmn'
1024 liveSnapshot(pepperEnv, target, generalTarget)
1025 } else {
Jiri Broulik906e9972018-03-26 16:12:00 +02001026 backupCeph(pepperEnv, target)
Jiri Broulik60dcab32018-03-08 17:42:06 +01001027 }
1028 if (PER_NODE.toBoolean()) {
1029 def targetHosts = salt.getMinionsSorted(pepperEnv, target)
1030 for (t in targetHosts) {
1031 updatePkgs(pepperEnv, t)
1032 highstate(pepperEnv, t)
1033 }
1034 } else {
1035 updatePkgs(pepperEnv, target)
1036 highstate(pepperEnv, target)
1037 }
1038 verifyCeph(pepperEnv, target, 'mon@')
1039 }
1040 }
1041
1042 if (updates.contains("rgw")) {
1043 def target = RGW_TARGET
1044 if (salt.testTarget(pepperEnv, target)) {
1045 if (!ROLLBACK_BY_REDEPLOY.toBoolean()) {
1046 def generalTarget = 'rgw'
1047 liveSnapshot(pepperEnv, target, generalTarget)
1048 }
1049 if (PER_NODE.toBoolean()) {
1050 def targetHosts = salt.getMinionsSorted(pepperEnv, target)
1051 for (t in targetHosts) {
1052 updatePkgs(pepperEnv, t)
1053 highstate(pepperEnv, t)
1054 }
1055 } else {
1056 updatePkgs(pepperEnv, target)
1057 highstate(pepperEnv, target)
1058 }
1059 verifyCeph(pepperEnv, target, 'radosgw@rgw.')
1060 }
1061 }
1062
1063 if (updates.contains("log")) {
1064 def target = LOG_TARGET
1065 if (salt.testTarget(pepperEnv, target)) {
1066 if (!ROLLBACK_BY_REDEPLOY.toBoolean()) {
1067 def generalTarget = 'log'
1068 liveSnapshot(pepperEnv, target, generalTarget)
1069 }
1070 if (PER_NODE.toBoolean()) {
1071 def targetHosts = salt.getMinionsSorted(pepperEnv, target)
1072 for (t in targetHosts) {
1073 updatePkgs(pepperEnv, t)
1074 highstate(pepperEnv, t)
1075 }
1076 } else {
1077 updatePkgs(pepperEnv, target)
1078 highstate(pepperEnv, target)
1079 }
1080 }
1081 }
1082
1083 if (updates.contains("mon")) {
1084 def target = MON_TARGET
1085 if (salt.testTarget(pepperEnv, target)) {
1086 if (!ROLLBACK_BY_REDEPLOY.toBoolean()) {
1087 def generalTarget = 'mon'
1088 liveSnapshot(pepperEnv, target, generalTarget)
1089 }
1090 if (PER_NODE.toBoolean()) {
1091 def targetHosts = salt.getMinionsSorted(pepperEnv, target)
1092 for (t in targetHosts) {
1093 updatePkgs(pepperEnv, t)
1094 highstate(pepperEnv, t)
1095 }
1096 } else {
1097 updatePkgs(pepperEnv, target)
1098 highstate(pepperEnv, target)
1099 }
1100 }
1101 }
1102
1103 if (updates.contains("mtr")) {
1104 def target = MTR_TARGET
1105 if (salt.testTarget(pepperEnv, target)) {
1106 if (!ROLLBACK_BY_REDEPLOY.toBoolean()) {
1107 def generalTarget = 'mtr'
1108 liveSnapshot(pepperEnv, target, generalTarget)
1109 }
1110 if (PER_NODE.toBoolean()) {
1111 def targetHosts = salt.getMinionsSorted(pepperEnv, target)
1112 for (t in targetHosts) {
1113 updatePkgs(pepperEnv, t)
1114 highstate(pepperEnv, t)
1115 }
1116 } else {
1117 updatePkgs(pepperEnv, target)
1118 highstate(pepperEnv, target)
1119 }
1120 }
1121 }
1122
1123 if (updates.contains("cid")) {
1124 def target = CID_TARGET
1125 if (salt.testTarget(pepperEnv, target)) {
1126 if (!ROLLBACK_BY_REDEPLOY.toBoolean()) {
1127 def generalTarget = 'cid'
1128 liveSnapshot(pepperEnv, target, generalTarget)
1129 }
1130 updatePkgs(pepperEnv, target, 'cicd')
1131 highstate(pepperEnv, target)
1132 verifyService(pepperEnv, target, 'docker')
1133 }
1134 }
1135
1136 //
1137 //physical machines update CMP_TARGET
1138 //
1139 if (updates.contains("cmp")) {
1140 def target = CMP_TARGET
1141 if (salt.testTarget(pepperEnv, target)) {
1142 if (PER_NODE.toBoolean()) {
1143 def targetHosts = salt.getMinionsSorted(pepperEnv, target)
1144 for (t in targetHosts) {
1145 updatePkgs(pepperEnv, t)
1146 highstate(pepperEnv, t)
1147 }
1148 } else {
1149 updatePkgs(pepperEnv, target)
1150 highstate(pepperEnv, target)
1151 }
1152 verifyService(pepperEnv, target, 'nova-compute')
1153 }
1154 }
1155
1156 if (updates.contains("kvm")) {
1157 def target = KVM_TARGET
1158 if (salt.testTarget(pepperEnv, target)) {
1159 if (PER_NODE.toBoolean()) {
1160 def targetHosts = salt.getMinionsSorted(pepperEnv, target)
1161 for (t in targetHosts) {
1162 updatePkgs(pepperEnv, t)
1163 highstate(pepperEnv, t)
1164 }
1165 } else {
1166 updatePkgs(pepperEnv, target, target)
1167 highstate(pepperEnv, target)
1168 }
1169 verifyService(pepperEnv, target, 'libvirt-bin')
1170 }
1171 }
1172
1173 if (updates.contains("osd")) {
1174 def target = CEPH_OSD_TARGET
1175 if (salt.testTarget(pepperEnv, target)) {
1176 if (PER_NODE.toBoolean()) {
1177 def targetHosts = salt.getMinionsSorted(pepperEnv, target)
1178 for (t in targetHosts) {
1179 updatePkgs(pepperEnv, t)
1180 highstate(pepperEnv, t)
1181 }
1182 } else {
1183 updatePkgs(pepperEnv, target)
1184 highstate(pepperEnv, target)
1185 }
1186 verifyCephOsds(pepperEnv, target)
1187 }
1188 }
1189
1190 if (updates.contains("gtw-physical")) {
1191 def target = GTW_TARGET
1192 if (salt.testTarget(pepperEnv, target)) {
1193 if (PER_NODE.toBoolean()) {
1194 def targetHosts = salt.getMinionsSorted(pepperEnv, target)
1195 for (t in targetHosts) {
1196 updatePkgs(pepperEnv, t)
1197 highstate(pepperEnv, t)
1198 }
1199 } else {
1200 updatePkgs(pepperEnv, target)
1201 highstate(pepperEnv, target)
1202 }
1203 verifyService(pepperEnv, target, 'neutron-dhcp-agent')
1204 }
1205 }
1206
1207 /*
1208 * Rollback section
1209 */
Jiri Broulik906e9972018-03-26 16:12:00 +02001210 /* if (rollbacks.contains("cfg")) {
Jiri Broulik60dcab32018-03-08 17:42:06 +01001211 if (salt.testTarget(pepperEnv, 'I@salt:master')) {
1212 stage('ROLLBACK_CFG') {
1213 input message: "To rollback CFG nodes run the following commands on kvm nodes hosting the CFG nodes: virsh destroy cfg0X.domain; virsh define /var/lib/libvirt/images/cfg0X.domain.xml; virsh start cfg0X.domain; virsh snapshot-delete cfg0X.domain --metadata ${SNAPSHOT_NAME}; rm /var/lib/libvirt/images/cfg0X.domain.${SNAPSHOT_NAME}.qcow2; rm /var/lib/libvirt/images/cfg0X.domain.xml; At the end restart 'docker' service on all cicd nodes and run 'linux.system.repo' Salt states on cicd nodes. After running the previous commands current pipeline job will be killed."
1214 //rollbackSaltMaster(pepperEnv, 'I@salt:master')
1215 //finishSaltMasterRollback(pepperEnv, 'I@salt:master')
1216 }
1217 }
1218 } */
1219
1220 if (rollbacks.contains("ctl")) {
1221 def target = CTL_TARGET
1222 if (salt.testTarget(pepperEnv, target)) {
1223 if (!ROLLBACK_BY_REDEPLOY.toBoolean()) {
1224 rollback(pepperEnv, target, 'ctl')
1225 verifyAPIs(pepperEnv, target)
1226 } else {
1227 removeNode(pepperEnv, target, 'ctl')
1228 }
1229 }
1230 }
1231
1232 if (rollbacks.contains("prx")) {
1233 def target = PRX_TARGET
1234 if (salt.testTarget(pepperEnv, target)) {
1235 if (!ROLLBACK_BY_REDEPLOY.toBoolean()) {
1236 rollback(pepperEnv, target, 'prx')
1237 verifyService(pepperEnv, target, 'nginx')
1238 } else {
1239 removeNode(pepperEnv, target, 'prx')
1240 }
1241 }
1242 }
1243
1244 if (rollbacks.contains("msg")) {
1245 def target = MSG_TARGET
1246 if (salt.testTarget(pepperEnv, target)) {
1247 if (!ROLLBACK_BY_REDEPLOY.toBoolean()) {
1248 rollback(pepperEnv, target, 'msg')
1249 salt.enforceState(pepperEnv, target, 'rabbitmq')
1250 verifyService(pepperEnv, target, 'rabbitmq-server')
1251 } else {
1252 removeNode(pepperEnv, target, 'msg')
1253 }
1254 }
1255 }
1256
1257 if (rollbacks.contains("dbs")) {
1258 def target = DBS_TARGET
1259 if (salt.testTarget(pepperEnv, target)) {
1260 if (!ROLLBACK_BY_REDEPLOY.toBoolean()) {
1261 rollback(pepperEnv, target, 'dbs')
1262 clusterGalera(pepperEnv)
Jiri Broulikad606d02018-03-28 14:22:43 +02001263 verifyGalera(pepperEnv, target)
Jiri Broulik60dcab32018-03-08 17:42:06 +01001264 } else {
1265 removeNode(pepperEnv, target, 'dbs')
1266 }
1267 }
1268 }
1269
1270 if (rollbacks.contains("ntw")) {
1271 def target = NTW_TARGET
1272 if (salt.testTarget(pepperEnv, target)) {
1273 if (!ROLLBACK_BY_REDEPLOY.toBoolean()) {
1274 rollback(pepperEnv, target, 'ntw')
1275 verifyContrail(pepperEnv, target)
1276 } else {
1277 removeNode(pepperEnv, target, 'ntw')
1278 }
1279 }
1280 }
1281
1282 if (rollbacks.contains("nal")) {
1283 def target = NAL_TARGET
1284 if (salt.testTarget(pepperEnv, target)) {
1285 if (!ROLLBACK_BY_REDEPLOY.toBoolean()) {
1286 rollback(pepperEnv, target, 'nal')
1287 verifyContrail(pepperEnv, target)
1288 } else {
1289 removeNode(pepperEnv, target, 'nal')
1290 }
1291 }
1292 }
1293
1294 if (rollbacks.contains("gtw-virtual")) {
1295 def target = GTW_TARGET
1296 if (salt.testTarget(pepperEnv, target)) {
1297 if (!ROLLBACK_BY_REDEPLOY.toBoolean()) {
1298 rollback(pepperEnv, target, 'gtw')
1299 verifyService(pepperEnv, target, 'neutron-dhcp-agent')
1300 } else {
1301 removeNode(pepperEnv, target, 'gtw')
1302 }
1303 }
1304 }
1305
1306 if (rollbacks.contains("cmn")) {
1307 def target = CMN_TARGET
1308 if (salt.testTarget(pepperEnv, target)) {
1309 if (!ROLLBACK_BY_REDEPLOY.toBoolean()) {
1310 rollback(pepperEnv, target, 'cmn')
1311 verifyCeph(pepperEnv, target, 'mon@')
1312 } else {
1313 removeNode(pepperEnv, target, 'cmn')
1314 }
1315 }
1316 }
1317
1318 if (rollbacks.contains("rgw")) {
1319 def target = RGW_TARGET
1320 if (salt.testTarget(pepperEnv, target)) {
1321 if (!ROLLBACK_BY_REDEPLOY.toBoolean()) {
1322 rollback(pepperEnv, target, 'rgw')
1323 verifyCeph(pepperEnv, target, 'radosgw@rgw.')
1324 } else {
1325 removeNode(pepperEnv, target, 'rgw')
1326 }
1327 }
1328 }
1329
1330 if (rollbacks.contains("log")) {
1331 def target = LOG_TARGET
1332 if (salt.testTarget(pepperEnv, target)) {
1333 if (!ROLLBACK_BY_REDEPLOY.toBoolean()) {
1334 rollback(pepperEnv, target, 'log')
1335 } else {
1336 removeNode(pepperEnv, target, 'log')
1337 }
1338 }
1339 }
1340
1341 if (rollbacks.contains("mon")) {
1342 def target = MON_TARGET
1343 if (salt.testTarget(pepperEnv, target)) {
1344 if (!ROLLBACK_BY_REDEPLOY.toBoolean()) {
1345 rollback(pepperEnv, target, 'mon')
1346 } else {
1347 removeNode(pepperEnv, target, 'mon')
1348 }
1349 }
1350 }
1351
1352 if (rollbacks.contains("mtr")) {
1353 def target = MTR_TARGET
1354 if (salt.testTarget(pepperEnv, target)) {
1355 if (!ROLLBACK_BY_REDEPLOY.toBoolean()) {
1356 rollback(pepperEnv, target, 'mtr')
1357 } else {
1358 removeNode(pepperEnv, target, 'mtr')
1359 }
1360 }
1361 }
1362 /*
1363 if (ROLLBACK_CID.toBoolean()) {
1364 def target = 'cid*'
1365 if (salt.testTarget(pepperEnv, target)) {
1366 stage('ROLLBACK_CID') {
1367 input message: "To rollback CICD nodes run the following commands on kvm nodes hosting the cicd nodes: virsh destroy cid0X.domain; virsh define /var/lib/libvirt/images/cid0X.domain.xml; virsh start cid0X.domain; virsh snapshot-delete cid0X.domain --metadata ${SNAPSHOT_NAME}; rm /var/lib/libvirt/images/cid0X.domain.${SNAPSHOT_NAME}.qcow2; rm /var/lib/libvirt/images/cid0X.domain.xml; At the end restart 'docker' service on all cicd nodes and run 'linux.system.repo' Salt states on cicd nodes. After running the previous commands current pipeline job will be killed."
1368 }
1369 }
1370 } */
1371
1372 //
1373 //physical machines rollback CMP_TARGET
1374 //
1375 if (rollbacks.contains("cmp")) {
1376 def target = CMP_TARGET
1377 if (salt.testTarget(pepperEnv, target)) {
1378 if (PER_NODE.toBoolean()) {
1379 def targetHosts = salt.getMinionsSorted(pepperEnv, target)
1380 for (t in targetHosts) {
1381 rollbackPkgs(pepperEnv, t)
1382 highstate(pepperEnv, t)
1383 }
1384 } else {
1385 rollbackPkgs(pepperEnv, target, target)
1386 highstate(pepperEnv, target)
1387 }
1388 verifyService(pepperEnv, target, 'nova-compute')
1389 }
1390 }
1391
1392 if (rollbacks.contains("kvm")) {
1393 def target = KVM_TARGET
1394 if (salt.testTarget(pepperEnv, target)) {
1395 if (PER_NODE.toBoolean()) {
1396 def targetHosts = salt.getMinionsSorted(pepperEnv, target)
1397 for (t in targetHosts) {
1398 rollbackPkgs(pepperEnv, t)
1399 highstate(pepperEnv, t)
1400 }
1401 } else {
1402 rollbackPkgs(pepperEnv, target, target)
1403 highstate(pepperEnv, target)
1404 }
1405 verifyService(pepperEnv, target, 'libvirt-bin')
1406 }
1407 }
1408
1409 if (rollbacks.contains("osd")) {
1410 def target = CEPH_OSD_TARGET
1411 if (salt.testTarget(pepperEnv, target)) {
1412 if (PER_NODE.toBoolean()) {
1413 def targetHosts = salt.getMinionsSorted(pepperEnv, target)
1414 for (t in targetHosts) {
1415 rollbackPkgs(pepperEnv, t)
1416 highstate(pepperEnv, t)
1417 }
1418 } else {
1419 rollbackPkgs(pepperEnv, target, target)
1420 highstate(pepperEnv, target)
1421 }
1422 verifyCephOsds(pepperEnv, target)
1423 }
1424 }
1425
1426 if (rollbacks.contains("gtw-physical")) {
1427 def target = GTW_TARGET
1428 if (salt.testTarget(pepperEnv, target)) {
1429 if (PER_NODE.toBoolean()) {
1430 def targetHosts = salt.getMinionsSorted(pepperEnv, target)
1431 for (t in targetHosts) {
1432 rollbackPkgs(pepperEnv, t)
1433 highstate(pepperEnv, t)
1434 }
1435 } else {
1436 rollbackPkgs(pepperEnv, target, target)
1437 highstate(pepperEnv, target)
1438 }
1439 verifyService(pepperEnv, target, 'neutron-dhcp-agent')
1440 }
1441 }
1442
1443 /*
1444 * Merge snapshots section
1445 */
1446 if (merges.contains("cfg")) {
1447 if (salt.testTarget(pepperEnv, 'I@salt:master')) {
1448 mergeSnapshot(pepperEnv, 'I@salt:master')
1449 }
1450 }
1451
1452 if (merges.contains("ctl")) {
1453 if (salt.testTarget(pepperEnv, CTL_TARGET)) {
1454 mergeSnapshot(pepperEnv, CTL_TARGET, 'ctl')
Jiri Broulik906e9972018-03-26 16:12:00 +02001455 verifyService(pepperEnv, CTL_TARGET, 'nova-api')
Jiri Broulik60dcab32018-03-08 17:42:06 +01001456 }
1457 }
1458
1459 if (merges.contains("prx")) {
1460 if (salt.testTarget(pepperEnv, PRX_TARGET)) {
1461 mergeSnapshot(pepperEnv, PRX_TARGET, 'prx')
Jiri Broulik906e9972018-03-26 16:12:00 +02001462 verifyService(pepperEnv, PRX_TARGET, 'nginx')
Jiri Broulik60dcab32018-03-08 17:42:06 +01001463 }
1464 }
1465
1466 if (merges.contains("msg")) {
1467 if (salt.testTarget(pepperEnv, MSG_TARGET)) {
1468 mergeSnapshot(pepperEnv, MSG_TARGET, 'msg')
Jiri Broulik906e9972018-03-26 16:12:00 +02001469 verifyService(pepperEnv, MSG_TARGET, 'rabbitmq-server')
Jiri Broulik60dcab32018-03-08 17:42:06 +01001470 }
1471 }
1472
1473 if (merges.contains("dbs")) {
1474 if (salt.testTarget(pepperEnv, DBS_TARGET)) {
1475 mergeSnapshot(pepperEnv, DBS_TARGET, 'dbs')
Jiri Broulikad606d02018-03-28 14:22:43 +02001476 verifyGalera(pepperEnv, DBS_TARGET)
Jiri Broulik906e9972018-03-26 16:12:00 +02001477 backupGalera(pepperEnv)
Jiri Broulik60dcab32018-03-08 17:42:06 +01001478 }
1479 }
1480
1481 if (merges.contains("ntw")) {
1482 if (salt.testTarget(pepperEnv, NTW_TARGET)) {
1483 mergeSnapshot(pepperEnv, NTW_TARGET, 'ntw')
Jiri Broulik906e9972018-03-26 16:12:00 +02001484 verifyContrail(pepperEnv, NTW_TARGET)
1485 backupContrail(pepperEnv)
Jiri Broulik60dcab32018-03-08 17:42:06 +01001486 }
1487 }
1488
1489 if (merges.contains("nal")) {
1490 if (salt.testTarget(pepperEnv, NAL_TARGET)) {
1491 mergeSnapshot(pepperEnv, NAL_TARGET, 'nal')
Jiri Broulik906e9972018-03-26 16:12:00 +02001492 verifyContrail(pepperEnv, NAL_TARGET)
Jiri Broulik60dcab32018-03-08 17:42:06 +01001493 }
1494 }
1495
1496 if (merges.contains("gtw-virtual")) {
1497 if (salt.testTarget(pepperEnv, GTW_TARGET)) {
1498 mergeSnapshot(pepperEnv, GTW_TARGET, 'gtw')
Jiri Broulik906e9972018-03-26 16:12:00 +02001499 verifyService(pepperEnv, GTW_TARGET, 'neutron-dhcp-agent')
Jiri Broulik60dcab32018-03-08 17:42:06 +01001500 }
1501 }
1502
1503 if (merges.contains("cmn")) {
1504 if (salt.testTarget(pepperEnv, CMN_TARGET)) {
1505 mergeSnapshot(pepperEnv, CMN_TARGET, 'cmn')
Jiri Broulik906e9972018-03-26 16:12:00 +02001506 verifyCeph(pepperEnv, CMN_TARGET, 'mon@')
1507 backupCeph(pepperEnv, CMN_TARGET)
Jiri Broulik60dcab32018-03-08 17:42:06 +01001508 }
1509 }
1510
1511 if (merges.contains("rgw")) {
1512 if (salt.testTarget(pepperEnv, RGW_TARGET)) {
1513 mergeSnapshot(pepperEnv, RGW_TARGET, 'rgw')
Jiri Broulik906e9972018-03-26 16:12:00 +02001514 verifyCeph(pepperEnv, RGW_TARGET, 'radosgw@rgw.')
Jiri Broulik60dcab32018-03-08 17:42:06 +01001515 }
1516 }
1517
1518 if (merges.contains("log")) {
1519 if (salt.testTarget(pepperEnv, LOG_TARGET)) {
1520 mergeSnapshot(pepperEnv, LOG_TARGET. 'log')
1521 }
1522 }
1523
1524 if (merges.contains("mon")) {
1525 if (salt.testTarget(pepperEnv, MON_TARGET)) {
1526 mergeSnapshot(pepperEnv, MON_TARGET, 'mon')
1527 }
1528 }
1529
1530 if (merges.contains("mtr")) {
1531 if (salt.testTarget(pepperEnv, MTR_TARGET)) {
1532 mergeSnapshot(pepperEnv, MTR_TARGET, 'mtr')
1533 }
1534 }
1535
1536 if (merges.contains("cid")) {
1537 if (salt.testTarget(pepperEnv, CID_TARGET)) {
1538 mergeSnapshot(pepperEnv, CID_TARGET, 'cid')
Jiri Broulik906e9972018-03-26 16:12:00 +02001539 verifyService(pepperEnv, CID_TARGET, 'docker')
Jiri Broulik60dcab32018-03-08 17:42:06 +01001540 }
1541 }
1542
1543 if (RESTORE_GALERA.toBoolean()) {
1544 restoreGalera(pepperEnv)
Jiri Broulikad606d02018-03-28 14:22:43 +02001545 verifyGalera(pepperEnv, DBS_TARGET)
Jiri Broulik60dcab32018-03-08 17:42:06 +01001546 }
1547
1548 if (RESTORE_CONTRAIL_DB.toBoolean()) {
1549 restoreContrailDb(pepperEnv)
Jiri Broulik906e9972018-03-26 16:12:00 +02001550 // verification is already present in restore pipelines
Jiri Broulik60dcab32018-03-08 17:42:06 +01001551 }
1552
1553 } catch (Throwable e) {
1554 // If there was an error or exception thrown, the build failed
1555 currentBuild.result = "FAILURE"
1556 currentBuild.description = currentBuild.description ? e.message + " " + currentBuild.description : e.message
1557 throw e
1558 }
1559 }
1560}