blob: 72ac2d5ba8b34d7217ea46d3674ac105b5c309bc [file] [log] [blame]
Alena Kiseleva3a49b802018-12-07 17:03:02 +03001/**
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 * TARGET_SERVERS Salt compound target to match nodes to be updated [*, G@osfamily:debian].
8 */
9
10pepperEnv = "pepperEnv"
11salt = new com.mirantis.mk.Salt()
12def common = new com.mirantis.mk.Common()
13def python = new com.mirantis.mk.Python()
14def targetLiveSubset
15def targetLiveAll
16def minions
17def result
18def packages
19def command
20def commandKwargs
21def selMinions = []
22
23def runCephCommand(master, target, cmd) {
24 return salt.cmdRun(master, target, cmd)
25}
26
Martin Polreichbf174c92019-06-17 11:02:07 +020027def waitForHealthy(master, tgt, count=0, attempts=100) {
Alena Kiseleva3a49b802018-12-07 17:03:02 +030028 // wait for healthy cluster
29 common = new com.mirantis.mk.Common()
Alena Kiselevaa6afc5a2019-05-16 16:00:14 +030030 while (count<attempts) {
Martin Polreichbf174c92019-06-17 11:02:07 +020031 def health = runCephCommand(master, tgt, 'ceph health')['return'][0].values()[0]
Alena Kiseleva3a49b802018-12-07 17:03:02 +030032 if (health.contains('HEALTH_OK') || health.contains('HEALTH_WARN noout flag(s) set\n')) {
33 common.infoMsg('Cluster is healthy')
Alena Kiselevaa6afc5a2019-05-16 16:00:14 +030034 break;
Alena Kiseleva3a49b802018-12-07 17:03:02 +030035 }
Alena Kiselevaa6afc5a2019-05-16 16:00:14 +030036 count++
37 sleep(10)
Alena Kiseleva3a49b802018-12-07 17:03:02 +030038 }
39}
40
41timeout(time: 12, unit: 'HOURS') {
42 node() {
43 try {
44
45 stage('Setup virtualenv for Pepper') {
46 python.setupPepperVirtualenv(pepperEnv, SALT_MASTER_URL, SALT_MASTER_CREDENTIALS)
47 }
48
49 stage('List target servers') {
50 minions = salt.getMinions(pepperEnv, TARGET_SERVERS)
51
52 if (minions.isEmpty()) {
53 throw new Exception("No minion was targeted")
54 }
55
56 for (m in minions) {
57 if (m.startsWith("osd") || m.startsWith("cmn") || m.startsWith("rgw")) {
58 selMinions.add(m)
59 }
60 }
61 }
62
63
64
65 stage('Apply package upgrades on all nodes') {
66
67 for (tgt in selMinions) {
68 try {
69 if (tgt.startsWith("osd")) {
70 out = runCephCommand(pepperEnv, tgt, "apt install --only-upgrade ceph-osd -y")
71 salt.printSaltCommandResult(out)
72 } else if (tgt.startsWith("cmn")) {
73 out = runCephCommand(pepperEnv, tgt, "apt install --only-upgrade ceph-mon -y")
74 salt.printSaltCommandResult(out)
75 } else if (tgt.startsWith("rgw")) {
76 out = runCephCommand(pepperEnv, tgt, "apt install --only-upgrade radosgw -y")
77 salt.printSaltCommandResult(out)
78 }
79 } catch (Throwable e) {
80 if (e.message.contains("Unmet dependencies")) {
81 out = runCephCommand(pepperEnv, tgt, "apt -f install -y")
82 salt.printSaltCommandResult(out)
83 } else {
84 throw (e)
85 }
86 }
87 }
88 }
89
90 stage("Restart MONs and RGWs") {
91 for (tgt in selMinions) {
92 if (tgt.contains("cmn")) {
93 runCephCommand(pepperEnv, tgt, "systemctl restart ceph-mon.target")
94 waitForHealthy(pepperEnv, tgt)
95 } else if (tgt.contains("rgw")) {
96 runCephCommand(pepperEnv, tgt, "systemctl restart ceph-radosgw.target")
97 waitForHealthy(pepperEnv, tgt)
98 }
99 }
100 }
101
102 stage('Restart OSDs') {
103
104 for (tgt in selMinions) {
105 if (tgt.contains("osd")) {
106 salt.runSaltProcessStep(pepperEnv, tgt, 'saltutil.sync_grains', [], null, true, 5)
107 def ceph_disks = salt.getGrain(pepperEnv, tgt, 'ceph')['return'][0].values()[0].values()[0]['ceph_disk']
108
109 def osd_ids = []
110 for (i in ceph_disks) {
111 def osd_id = i.getKey().toString()
112 osd_ids.add('osd.' + osd_id)
113 }
114
115 runCephCommand(pepperEnv, tgt, 'ceph osd set noout')
116
117 for (i in osd_ids) {
118
119 salt.runSaltProcessStep(pepperEnv, tgt, 'service.restart', ['ceph-osd@' + i.replaceAll('osd.', '')], null, true)
120 // wait for healthy cluster
121 waitForHealthy(pepperEnv, tgt)
122 }
123
124 runCephCommand(pepperEnv, tgt, 'ceph osd unset noout')
125 }
126 }
127 }
128
129
130 } catch (Throwable e) {
131 // If there was an error or exception thrown, the build failed
132 currentBuild.result = "FAILURE"
133 currentBuild.description = currentBuild.description ? e.message + " " + currentBuild.description : e.message
134 throw e
135 }
136 }
137}