blob: 297feafc5e7538e039d058b57efc393dfe42958a [file] [log] [blame]
Jiri Broulikdc87d722017-11-03 15:43:22 +01001/**
2 *
3 * Upgrade Ceph mon/mgr/osd/rgw/client
4 *
5 * Requred parameters:
6 * SALT_MASTER_URL URL of Salt master
7 * SALT_MASTER_CREDENTIALS Credentials to the Salt API
8 *
9 * ADMIN_HOST Host (minion id) with admin keyring and /etc/crushmap file present
10 * CLUSTER_FLAGS Comma separated list of tags to apply to cluster
11 * WAIT_FOR_HEALTHY Wait for cluster rebalance before stoping daemons
12 * ORIGIN_RELEASE Ceph release version before upgrade
13 * TARGET_RELEASE Ceph release version after upgrade
14 * STAGE_UPGRADE_MON Set to True if Ceph mon nodes upgrade is desired
15 * STAGE_UPGRADE_MGR Set to True if Ceph mgr nodes upgrade or new deploy is desired
16 * STAGE_UPGRADE_OSD Set to True if Ceph osd nodes upgrade is desired
17 * STAGE_UPGRADE_RGW Set to True if Ceph rgw nodes upgrade is desired
18 * STAGE_UPGRADE_CLIENT Set to True if Ceph client nodes upgrade is desired (includes for example ctl/cmp nodes)
Michael Vollmanbcec46f2019-05-07 08:10:00 -040019 * STAGE_FINALIZE Set to True if configs recommended for TARGET_RELEASE should be set after upgrade is done
20 * BACKUP_ENABLED Select to copy the disks of Ceph VMs before upgrade and backup Ceph directories on OSD nodes
21 * BACKUP_DIR Select the target dir to backup to when BACKUP_ENABLED
Jiri Broulikdc87d722017-11-03 15:43:22 +010022 *
23 */
24
25common = new com.mirantis.mk.Common()
26salt = new com.mirantis.mk.Salt()
27def python = new com.mirantis.mk.Python()
Ivan Berezovskiy2325dcb2019-11-05 17:42:57 +040028ceph = new com.mirantis.mk.Ceph()
Jiri Broulikdc87d722017-11-03 15:43:22 +010029
30def pepperEnv = "pepperEnv"
Ivan Berezovskiy2325dcb2019-11-05 17:42:57 +040031flags = CLUSTER_FLAGS.tokenize(',')
Jiri Broulikdc87d722017-11-03 15:43:22 +010032
Ivan Berezovskiy2325dcb2019-11-05 17:42:57 +040033def backup(master, target) {
Jiri Broulik96c867a2017-11-07 16:14:10 +010034 stage("backup ${target}") {
35
Jiri Broulikfd2dcaf2017-12-08 15:19:51 +010036 if (target == 'osd') {
Jiri Broulik96c867a2017-11-07 16:14:10 +010037 try {
Jiri Broulikfd2dcaf2017-12-08 15:19:51 +010038 salt.enforceState(master, "I@ceph:${target}", "ceph.backup", true)
Ivan Berezovskiy2325dcb2019-11-05 17:42:57 +040039 salt.cmdRun(master, "I@ceph:${target}", "su root -c '/usr/local/bin/ceph-backup-runner-call.sh'")
Jiri Broulik96c867a2017-11-07 16:14:10 +010040 } catch (Exception e) {
Jiri Broulikfd2dcaf2017-12-08 15:19:51 +010041 common.errorMsg(e)
42 common.errorMsg("Make sure Ceph backup on OSD nodes is enabled")
43 throw new InterruptedException()
Jiri Broulik96c867a2017-11-07 16:14:10 +010044 }
Jiri Broulikfd2dcaf2017-12-08 15:19:51 +010045 } else {
46 def _pillar = salt.getGrain(master, 'I@salt:master', 'domain')
47 def domain = _pillar['return'][0].values()[0].values()[0]
48
49 def kvm_pillar = salt.getGrain(master, 'I@salt:control', 'id')
50 def kvm01 = kvm_pillar['return'][0].values()[0].values()[0]
51
52 def target_pillar = salt.getGrain(master, "I@ceph:${target}", 'host')
53 def minions = target_pillar['return'][0].values()
54 for (minion in minions) {
55 def minion_name = minion.values()[0]
56 def provider_pillar = salt.getPillar(master, "${kvm01}", "salt:control:cluster:internal:node:${minion_name}:provider")
57 def minionProvider = provider_pillar['return'][0].values()[0]
58
Ivan Berezovskiy2325dcb2019-11-05 17:42:57 +040059 ceph.waitForHealthy(master, ADMIN_HOST, flags)
Jiri Broulikfd2dcaf2017-12-08 15:19:51 +010060 try {
Michael Vollmanbcec46f2019-05-07 08:10:00 -040061 salt.cmdRun(master, "${minionProvider}", "[ ! -f ${BACKUP_DIR}/${minion_name}.${domain}.qcow2.bak ] && virsh destroy ${minion_name}.${domain}")
Jiri Broulikfd2dcaf2017-12-08 15:19:51 +010062 } catch (Exception e) {
63 common.warningMsg('Backup already exists')
64 }
65 try {
Michael Vollmanbcec46f2019-05-07 08:10:00 -040066 salt.cmdRun(master, "${minionProvider}", "[ ! -f ${BACKUP_DIR}/${minion_name}.${domain}.qcow2.bak ] && cp /var/lib/libvirt/images/${minion_name}.${domain}/system.qcow2 ${BACKUP_DIR}/${minion_name}.${domain}.qcow2.bak")
Jiri Broulikfd2dcaf2017-12-08 15:19:51 +010067 } catch (Exception e) {
68 common.warningMsg('Backup already exists')
69 }
70 try {
71 salt.cmdRun(master, "${minionProvider}", "virsh start ${minion_name}.${domain}")
72 } catch (Exception e) {
73 common.warningMsg(e)
74 }
75 salt.minionsReachable(master, 'I@salt:master', "${minion_name}*")
Ivan Berezovskiy2325dcb2019-11-05 17:42:57 +040076 ceph.waitForHealthy(master, ADMIN_HOST, flags)
Jiri Broulik96c867a2017-11-07 16:14:10 +010077 }
Jiri Broulik96c867a2017-11-07 16:14:10 +010078 }
79 }
80 return
81}
82
Ivan Berezovskiy2325dcb2019-11-05 17:42:57 +040083def upgrade(master, target) {
Jiri Broulikdc87d722017-11-03 15:43:22 +010084
85 stage("Change ${target} repos") {
86 salt.runSaltProcessStep(master, "I@ceph:${target}", 'saltutil.refresh_pillar', [], null, true, 5)
87 salt.enforceState(master, "I@ceph:${target}", 'linux.system.repo', true)
88 }
Jiri Broulikdc87d722017-11-03 15:43:22 +010089 if (target == 'mgr') {
90 stage('Run ceph mgr state') {
91 salt.enforceState(master, "I@ceph:mgr", "ceph.mgr", true)
92 }
93 }
Jiri Broulikdc87d722017-11-03 15:43:22 +010094 if (target == 'common') {
95 stage('Upgrade ceph-common pkgs') {
Ivan Berezovskiy2325dcb2019-11-05 17:42:57 +040096 salt.cmdRun(master, "I@ceph:${target}", "apt install ceph-${target} -y")
Jiri Broulikdc87d722017-11-03 15:43:22 +010097 }
98 } else {
Jiri Broulik96c867a2017-11-07 16:14:10 +010099 minions = salt.getMinions(master, "I@ceph:${target}")
Jiri Broulikdc87d722017-11-03 15:43:22 +0100100
Jiri Broulik96c867a2017-11-07 16:14:10 +0100101 for (minion in minions) {
102 // upgrade pkgs
103 if (target == 'radosgw') {
104 stage('Upgrade radosgw pkgs') {
Ivan Berezovskiy2325dcb2019-11-05 17:42:57 +0400105 salt.cmdRun(master, "I@ceph:${target}", "apt install ${target} -y ")
Jiri Broulik96c867a2017-11-07 16:14:10 +0100106 }
107 } else {
108 stage("Upgrade ${target} pkgs on ${minion}") {
Ivan Berezovskiy2325dcb2019-11-05 17:42:57 +0400109 salt.cmdRun(master, "${minion}", "apt install ceph-${target} -y")
Jiri Broulik96c867a2017-11-07 16:14:10 +0100110 }
111 }
112 // restart services
113 stage("Restart ${target} services on ${minion}") {
Mateusz Losaaeeb1d2019-09-18 21:58:54 +0200114 if (target == 'osd') {
Ivan Berezovskiy2325dcb2019-11-05 17:42:57 +0400115 def osds = salt.getGrain(master, "${minion}", 'ceph:ceph_disk').values()[0]
116 osds[0].values()[0].values()[0].each { osd, param ->
117 salt.cmdRun(master, "${minion}", "systemctl restart ceph-${target}@${osd}")
118 ceph.waitForHealthy(master, ADMIN_HOST, flags)
119 }
Mateusz Losaaeeb1d2019-09-18 21:58:54 +0200120 } else {
Ivan Berezovskiy2325dcb2019-11-05 17:42:57 +0400121 salt.cmdRun(master, "${minion}", "systemctl restart ceph-${target}.target")
122 ceph.waitForHealthy(master, ADMIN_HOST, flags)
Mateusz Losaaeeb1d2019-09-18 21:58:54 +0200123 }
Jiri Broulik96c867a2017-11-07 16:14:10 +0100124 }
125
126 stage("Verify services for ${minion}") {
127 sleep(10)
Ivan Berezovskiy2325dcb2019-11-05 17:42:57 +0400128 salt.cmdRun(master, "${minion}", "systemctl status ceph-${target}.target")
Jiri Broulik96c867a2017-11-07 16:14:10 +0100129 }
130
131 stage('Ask for manual confirmation') {
132 input message: "From the verification command above, please check Ceph ${target} joined the cluster correctly. If so, Do you want to continue to upgrade next node?"
133 }
Jiri Broulikdc87d722017-11-03 15:43:22 +0100134 }
135 }
Ivan Berezovskiy2325dcb2019-11-05 17:42:57 +0400136 salt.cmdRun(master, ADMIN_HOST, "ceph versions")
Jiri Broulikdc87d722017-11-03 15:43:22 +0100137 sleep(5)
138 return
139}
Ivan Berezovskiy2325dcb2019-11-05 17:42:57 +0400140
Jakub Josefa63f9862018-01-11 17:58:38 +0100141timeout(time: 12, unit: 'HOURS') {
142 node("python") {
Jiri Broulikdc87d722017-11-03 15:43:22 +0100143
Jakub Josefa63f9862018-01-11 17:58:38 +0100144 // create connection to salt master
145 python.setupPepperVirtualenv(pepperEnv, SALT_MASTER_URL, SALT_MASTER_CREDENTIALS)
Jiri Broulikdc87d722017-11-03 15:43:22 +0100146
Ivan Berezovskiy2325dcb2019-11-05 17:42:57 +0400147 stage('Check user choices') {
Alena Kiseleva639b0012019-01-22 17:09:33 +0300148 if (STAGE_UPGRADE_RGW.toBoolean() == true) {
149 // if rgw, check if other stuff has required version
150 def mon_ok = true
151 if (STAGE_UPGRADE_MON.toBoolean() == false) {
Ivan Berezovskiy2325dcb2019-11-05 17:42:57 +0400152 def mon_v = salt.cmdRun(pepperEnv, ADMIN_HOST, "ceph mon versions")['return'][0].values()[0]
Alena Kiseleva639b0012019-01-22 17:09:33 +0300153 mon_ok = mon_v.contains("${TARGET_RELEASE}") && !mon_v.contains("${ORIGIN_RELEASE}")
154 }
155 def mgr_ok = true
156 if (STAGE_UPGRADE_MGR.toBoolean() == false) {
Ivan Berezovskiy2325dcb2019-11-05 17:42:57 +0400157 def mgr_v = salt.cmdRun(pepperEnv, ADMIN_HOST, "ceph mgr versions")['return'][0].values()[0]
Alena Kiseleva639b0012019-01-22 17:09:33 +0300158 mgr_ok = mgr_v.contains("${TARGET_RELEASE}") && !mgr_v.contains("${ORIGIN_RELEASE}")
159 }
160 def osd_ok = true
161 if (STAGE_UPGRADE_OSD.toBoolean() == false) {
Ivan Berezovskiy2325dcb2019-11-05 17:42:57 +0400162 def osd_v = salt.cmdRun(pepperEnv, ADMIN_HOST, "ceph osd versions")['return'][0].values()[0]
Alena Kiseleva639b0012019-01-22 17:09:33 +0300163 osd_ok = osd_v.contains("${TARGET_RELEASE}") && !osd_v.contains("${ORIGIN_RELEASE}")
164 }
165 if (!mon_ok || !osd_ok || !mgr_ok) {
166 common.errorMsg('You may choose stages in any order, but RGW should be upgraded last')
167 throw new InterruptedException()
168 }
169 }
170 }
171
Jakub Josefa63f9862018-01-11 17:58:38 +0100172 if (BACKUP_ENABLED.toBoolean() == true) {
173 if (STAGE_UPGRADE_MON.toBoolean() == true) {
174 backup(pepperEnv, 'mon')
175 }
176 if (STAGE_UPGRADE_RGW.toBoolean() == true) {
177 backup(pepperEnv, 'radosgw')
178 }
179 if (STAGE_UPGRADE_OSD.toBoolean() == true) {
180 backup(pepperEnv, 'osd')
Jiri Broulikdc87d722017-11-03 15:43:22 +0100181 }
182 }
Jiri Broulikdc87d722017-11-03 15:43:22 +0100183
Jakub Josefa63f9862018-01-11 17:58:38 +0100184 if (flags.size() > 0) {
185 stage('Set cluster flags') {
186 for (flag in flags) {
Ivan Berezovskiy2325dcb2019-11-05 17:42:57 +0400187 salt.cmdRun(pepperEnv, ADMIN_HOST, 'ceph osd set ' + flag)
Jiri Broulikdc87d722017-11-03 15:43:22 +0100188 }
Jiri Broulikdc87d722017-11-03 15:43:22 +0100189 }
190 }
Jiri Broulikdc87d722017-11-03 15:43:22 +0100191
Jakub Josefa63f9862018-01-11 17:58:38 +0100192 if (STAGE_UPGRADE_MON.toBoolean() == true) {
Ivan Berezovskiy2325dcb2019-11-05 17:42:57 +0400193 upgrade(pepperEnv, 'mon')
Jakub Josefa63f9862018-01-11 17:58:38 +0100194 }
195
196 if (STAGE_UPGRADE_MGR.toBoolean() == true) {
Ivan Berezovskiy2325dcb2019-11-05 17:42:57 +0400197 upgrade(pepperEnv, 'mgr')
Jakub Josefa63f9862018-01-11 17:58:38 +0100198 }
199
200 if (STAGE_UPGRADE_OSD.toBoolean() == true) {
Ivan Berezovskiy2325dcb2019-11-05 17:42:57 +0400201 upgrade(pepperEnv, 'osd')
Jakub Josefa63f9862018-01-11 17:58:38 +0100202 }
203
204 if (STAGE_UPGRADE_RGW.toBoolean() == true) {
Ivan Berezovskiy2325dcb2019-11-05 17:42:57 +0400205 upgrade(pepperEnv, 'radosgw')
Jakub Josefa63f9862018-01-11 17:58:38 +0100206 }
207
208 if (STAGE_UPGRADE_CLIENT.toBoolean() == true) {
Ivan Berezovskiy2325dcb2019-11-05 17:42:57 +0400209 upgrade(pepperEnv, 'common')
Jakub Josefa63f9862018-01-11 17:58:38 +0100210 }
211
212 // remove cluster flags
213 if (flags.size() > 0) {
214 stage('Unset cluster flags') {
215 for (flag in flags) {
216 if (!flag.contains('sortbitwise')) {
217 common.infoMsg('Removing flag ' + flag)
Ivan Berezovskiy2325dcb2019-11-05 17:42:57 +0400218 salt.cmdRun(pepperEnv, ADMIN_HOST, 'ceph osd unset ' + flag)
Jakub Josefa63f9862018-01-11 17:58:38 +0100219 }
220
221 }
Jiri Broulik96c867a2017-11-07 16:14:10 +0100222 }
Jiri Broulikdc87d722017-11-03 15:43:22 +0100223 }
Jiri Broulikdc87d722017-11-03 15:43:22 +0100224
Jakub Josefa63f9862018-01-11 17:58:38 +0100225 if (STAGE_FINALIZE.toBoolean() == true) {
226 stage("Finalize ceph version upgrade") {
Ivan Berezovskiy2325dcb2019-11-05 17:42:57 +0400227 salt.cmdRun(pepperEnv, ADMIN_HOST, "ceph osd require-osd-release ${TARGET_RELEASE}")
Jakub Josefa63f9862018-01-11 17:58:38 +0100228 try {
Ivan Berezovskiy2325dcb2019-11-05 17:42:57 +0400229 salt.cmdRun(pepperEnv, ADMIN_HOST, "ceph osd set-require-min-compat-client ${ORIGIN_RELEASE}")
Jakub Josefa63f9862018-01-11 17:58:38 +0100230 } catch (Exception e) {
231 common.warningMsg(e)
232 }
233 try {
Ivan Berezovskiy2325dcb2019-11-05 17:42:57 +0400234 salt.cmdRun(pepperEnv, ADMIN_HOST, "ceph osd crush tunables optimal")
Jakub Josefa63f9862018-01-11 17:58:38 +0100235 } catch (Exception e) {
236 common.warningMsg(e)
237 }
238 }
239 }
240
241 // wait for healthy cluster
Ivan Berezovskiy2325dcb2019-11-05 17:42:57 +0400242 if (WAIT_FOR_HEALTHY.toBoolean()) {
243 ceph.waitForHealthy(pepperEnv, ADMIN_HOST, flags)
Jakub Josefa63f9862018-01-11 17:58:38 +0100244 }
Jiri Broulikdc87d722017-11-03 15:43:22 +0100245 }
246}