blob: 4ee9f177cc4cb235e9682e5e10476b91513e26a9 [file] [log] [blame]
Jiri Broulikdc87d722017-11-03 15:43:22 +01001/**
2 *
3 * Filestore to Bluestore or vice versa backend migration
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 * OSD OSD ids to be migrated if single OSD host is targeted (comma-separated list - 1,2,3)
11 * TARGET Hosts (minion ids) to be targeted
12 * CLUSTER_FLAGS Comma separated list of tags to apply to cluster
13 * WAIT_FOR_HEALTHY Wait for cluster rebalance before stoping daemons
14 * ORIGIN_BACKEND Ceph backend before upgrade
Jiri Broulik96c867a2017-11-07 16:14:10 +010015 * PER_OSD_CONTROL Set to true if Ceph status verification after every osd disk migration is desired
16 * PER_OSD_HOST_CONTROL Set to true if Ceph status verificaton after whole OSD host migration is desired
Jiri Broulikdc87d722017-11-03 15:43:22 +010017 *
18 */
19
20common = new com.mirantis.mk.Common()
21salt = new com.mirantis.mk.Salt()
22def python = new com.mirantis.mk.Python()
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +040023ceph = new com.mirantis.mk.Ceph()
Jiri Broulikdc87d722017-11-03 15:43:22 +010024
25MIGRATION_METHOD = "per-osd"
26// TBD: per-host
27
28def pepperEnv = "pepperEnv"
29def flags = CLUSTER_FLAGS.tokenize(',')
30def osds = OSD.tokenize(',')
31
Jiri Broulikeb7b82f2017-11-30 13:55:40 +010032def removeJournalOrBlockPartitions(master, target, id) {
Jiri Broulikeb7b82f2017-11-30 13:55:40 +010033 // remove journal, block_db, block_wal partition `parted /dev/sdj rm 3`
34 stage('Remove journal / block_db / block_wal partition') {
35 def partition_uuid = ""
36 def journal_partition_uuid = ""
37 def block_db_partition_uuid = ""
38 def block_wal_partition_uuid = ""
39 try {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +040040 journal_partition_uuid = salt.cmdRun(master, target, "ls -la /var/lib/ceph/osd/ceph-${id}/ | grep journal | grep partuuid")
Jiri Broulikeb7b82f2017-11-30 13:55:40 +010041 journal_partition_uuid = journal_partition_uuid.toString().trim().split("\n")[0].substring(journal_partition_uuid.toString().trim().lastIndexOf("/")+1)
42 } catch (Exception e) {
43 common.infoMsg(e)
44 }
45 try {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +040046 block_db_partition_uuid = salt.cmdRun(master, target, "ls -la /var/lib/ceph/osd/ceph-${id}/ | grep 'block.db' | grep partuuid")
Jiri Broulikeb7b82f2017-11-30 13:55:40 +010047 block_db_partition_uuid = block_db_partition_uuid.toString().trim().split("\n")[0].substring(block_db_partition_uuid.toString().trim().lastIndexOf("/")+1)
48 } catch (Exception e) {
49 common.infoMsg(e)
50 }
51
52 try {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +040053 block_wal_partition_uuid = salt.cmdRun(master, target, "ls -la /var/lib/ceph/osd/ceph-${id}/ | grep 'block.wal' | grep partuuid")
Jiri Broulikeb7b82f2017-11-30 13:55:40 +010054 block_wal_partition_uuid = block_wal_partition_uuid.toString().trim().split("\n")[0].substring(block_wal_partition_uuid.toString().trim().lastIndexOf("/")+1)
55 } catch (Exception e) {
56 common.infoMsg(e)
57 }
58
59 // set partition_uuid = 2c76f144-f412-481e-b150-4046212ca932
60 if (journal_partition_uuid?.trim()) {
61 partition_uuid = journal_partition_uuid
62 } else if (block_db_partition_uuid?.trim()) {
63 partition_uuid = block_db_partition_uuid
64 }
65
66 // if disk has journal, block_db or block_wal on different disk, then remove the partition
67 if (partition_uuid?.trim()) {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +040068 ceph.removePartition(master, target, partition_uuid)
Jiri Broulikeb7b82f2017-11-30 13:55:40 +010069 }
70 if (block_wal_partition_uuid?.trim()) {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +040071 ceph.removePartition(master, target, block_wal_partition_uuid)
Jiri Broulikeb7b82f2017-11-30 13:55:40 +010072 }
73 }
74 return
75}
76
Jakub Josefa63f9862018-01-11 17:58:38 +010077timeout(time: 12, unit: 'HOURS') {
78 node("python") {
Jiri Broulik96c867a2017-11-07 16:14:10 +010079
Jakub Josefa63f9862018-01-11 17:58:38 +010080 // create connection to salt master
81 python.setupPepperVirtualenv(pepperEnv, SALT_MASTER_URL, SALT_MASTER_CREDENTIALS)
Jiri Broulikdc87d722017-11-03 15:43:22 +010082
Jakub Josefa63f9862018-01-11 17:58:38 +010083 if (MIGRATION_METHOD == 'per-osd') {
Jiri Broulikdc87d722017-11-03 15:43:22 +010084
Jakub Josefa63f9862018-01-11 17:58:38 +010085 if (flags.size() > 0) {
86 stage('Set cluster flags') {
87 for (flag in flags) {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +040088 salt.cmdRun(pepperEnv, ADMIN_HOST, 'ceph osd set ' + flag)
Jakub Josefa63f9862018-01-11 17:58:38 +010089 }
Jiri Broulikdc87d722017-11-03 15:43:22 +010090 }
91 }
92
Jakub Josefa63f9862018-01-11 17:58:38 +010093 def target_hosts = salt.getMinions(pepperEnv, TARGET)
Mateusz Los2ae66db2020-04-28 16:36:11 +020094 def device_grain_name = "ceph_disk"
Tomek Jaroszyk6d8a3aa2020-07-07 12:07:40 +020095 try {
96 for (tgt in target_hosts) {
97 def osd_ids = []
Jiri Broulikdc87d722017-11-03 15:43:22 +010098
Tomek Jaroszyk6d8a3aa2020-07-07 12:07:40 +020099 // get list of osd disks of the tgt
100 salt.runSaltProcessStep(pepperEnv, tgt, 'saltutil.sync_grains', [], null, true, 5)
101 def ceph_disks = salt.getGrain(pepperEnv, tgt, 'ceph')['return'][0].values()[0].values()[0][device_grain_name]
Jiri Broulikdc87d722017-11-03 15:43:22 +0100102
Tomek Jaroszyk6d8a3aa2020-07-07 12:07:40 +0200103 for (i in ceph_disks) {
104 def osd_id = i.getKey().toString()
105 if (osd_id in osds || OSD == '*') {
106 osd_ids.add('osd.' + osd_id)
107 print("Will migrate " + osd_id)
Jakub Josefa63f9862018-01-11 17:58:38 +0100108 } else {
Tomek Jaroszyk6d8a3aa2020-07-07 12:07:40 +0200109 print("Skipping " + osd_id)
110 }
111 }
Jakub Josefa63f9862018-01-11 17:58:38 +0100112
Tomek Jaroszyk6d8a3aa2020-07-07 12:07:40 +0200113 for (osd_id in osd_ids) {
Jakub Josefa63f9862018-01-11 17:58:38 +0100114
Tomek Jaroszyk6d8a3aa2020-07-07 12:07:40 +0200115 def id = osd_id.replaceAll('osd.', '')
116 def backend = salt.cmdRun(pepperEnv, ADMIN_HOST, "ceph osd metadata ${id} | grep osd_objectstore")['return'][0].values()[0]
Jakub Josefa63f9862018-01-11 17:58:38 +0100117
Tomek Jaroszyk6d8a3aa2020-07-07 12:07:40 +0200118 if (backend.contains(ORIGIN_BACKEND.toLowerCase())) {
119
120 // wait for healthy cluster before manipulating with osds
121 if (WAIT_FOR_HEALTHY.toBoolean()) {
122 ceph.waitForHealthy(pepperEnv, ADMIN_HOST)
Jakub Josefa63f9862018-01-11 17:58:38 +0100123 }
124
Tomek Jaroszyk6d8a3aa2020-07-07 12:07:40 +0200125 // `ceph osd out <id> <id>`
126 stage('Set OSDs out') {
127 salt.cmdRun(pepperEnv, ADMIN_HOST, "ceph osd out ${osd_id}")
Jakub Josefa63f9862018-01-11 17:58:38 +0100128 }
Jakub Josefa63f9862018-01-11 17:58:38 +0100129
Tomek Jaroszyk6d8a3aa2020-07-07 12:07:40 +0200130 if (WAIT_FOR_HEALTHY.toBoolean()) {
Jakub Josefa63f9862018-01-11 17:58:38 +0100131 sleep(5)
Tomek Jaroszyk6d8a3aa2020-07-07 12:07:40 +0200132 ceph.waitForHealthy(pepperEnv, ADMIN_HOST)
Jakub Josefa63f9862018-01-11 17:58:38 +0100133 }
134
Tomek Jaroszyk6d8a3aa2020-07-07 12:07:40 +0200135 // stop osd daemons
136 stage('Stop OSD daemons') {
137 salt.runSaltProcessStep(pepperEnv, tgt, 'service.stop', ['ceph-osd@' + osd_id.replaceAll('osd.', '')], null, true)
138 }
139
140 // remove keyring `ceph auth del osd.3`
141 stage('Remove OSD keyrings from auth') {
142 salt.cmdRun(pepperEnv, ADMIN_HOST, 'ceph auth del ' + osd_id)
143 }
144
145 // remove osd `ceph osd rm osd.3`
146 stage('Remove OSDs') {
147 salt.cmdRun(pepperEnv, ADMIN_HOST, 'ceph osd rm ' + osd_id)
148 }
149
150 def dmcrypt = ""
151 try {
152 dmcrypt = salt.cmdRun(pepperEnv, tgt, "ls -la /var/lib/ceph/osd/ceph-${id}/ | grep dmcrypt")['return'][0].values()[0]
153 } catch (Exception e) {
154 common.warningMsg(e)
155 }
156
157 if (dmcrypt?.trim()) {
158 def mount = salt.cmdRun(pepperEnv, tgt, "lsblk -rp | grep /var/lib/ceph/osd/ceph-${id} -B1")['return'][0].values()[0]
159 dev = mount.split()[0].replaceAll("[0-9]","")
160
161 // remove partition tables
162 stage('dd part tables') {
163 salt.cmdRun(pepperEnv, tgt, "dd if=/dev/zero of=${dev} bs=512 count=1 conv=notrunc")
164 }
165
166 // remove journal, block_db, block_wal partition `parted /dev/sdj rm 3`
167 removeJournalOrBlockPartitions(pepperEnv, tgt, id)
168
169 // reboot
170 stage('reboot and wait') {
171 salt.runSaltProcessStep(pepperEnv, tgt, 'system.reboot', null, null, true, 5)
172 salt.minionsReachable(pepperEnv, 'I@salt:master', tgt)
173 sleep(10)
174 }
175
176 // zap disks `ceph-disk zap /dev/sdi`
177 stage('Zap devices') {
178 try {
179 salt.cmdRun(pepperEnv, tgt, 'ceph-disk zap ' + dev)
180 } catch (Exception e) {
181 common.warningMsg(e)
182 }
183 salt.cmdRun(pepperEnv, tgt, 'ceph-disk zap ' + dev)
184 }
185
186 } else {
187
188 def mount = salt.cmdRun(pepperEnv, tgt, "mount | grep /var/lib/ceph/osd/ceph-${id}")['return'][0].values()[0]
189 dev = mount.split()[0].replaceAll("[0-9]","")
190
191 // remove journal, block_db, block_wal partition `parted /dev/sdj rm 3`
192 removeJournalOrBlockPartitions(pepperEnv, tgt, id)
193
194 // umount `umount /dev/sdi1`
195 stage('Umount devices') {
196 salt.cmdRun(pepperEnv, tgt, "umount /var/lib/ceph/osd/ceph-${id}")
197 }
198
199 // zap disks `ceph-disk zap /dev/sdi`
200 stage('Zap device') {
201 salt.cmdRun(pepperEnv, tgt, 'ceph-disk zap ' + dev)
202 }
203 }
204
205 // Deploy Ceph OSD
206 stage('Deploy Ceph OSD') {
207 salt.runSaltProcessStep(pepperEnv, tgt, 'saltutil.refresh_pillar', [], null, true, 5)
208 salt.enforceState(pepperEnv, tgt, 'ceph.osd', true)
209 }
210
211 if (PER_OSD_CONTROL.toBoolean() == true) {
212 stage("Verify backend version for osd.${id}") {
213 sleep(5)
214 salt.cmdRun(pepperEnv, tgt, "ceph osd metadata ${id} | grep osd_objectstore")
215 salt.cmdRun(pepperEnv, tgt, "ceph -s")
216 }
217
218 stage('Ask for manual confirmation') {
219 input message: "From the verification commands above, please check the backend version of osd.${id} and ceph status. If it is correct, Do you want to continue to migrate next osd?"
220 }
Jakub Josefa63f9862018-01-11 17:58:38 +0100221 }
Jiri Broulik96c867a2017-11-07 16:14:10 +0100222 }
223 }
Tomek Jaroszyk6d8a3aa2020-07-07 12:07:40 +0200224 if (PER_OSD_HOST_CONTROL.toBoolean() == true) {
225 stage("Verify backend versions") {
226 sleep(5)
227 salt.cmdRun(pepperEnv, tgt, "ceph osd metadata | grep osd_objectstore -B2")
228 salt.cmdRun(pepperEnv, tgt, "ceph -s")
229 }
230
231 stage('Ask for manual confirmation') {
232 input message: "From the verification command above, please check the ceph status and backend version of osds on this host. If it is correct, Do you want to continue to migrate next OSD host?"
233 }
Jakub Josefa63f9862018-01-11 17:58:38 +0100234 }
235
Jiri Broulik96c867a2017-11-07 16:14:10 +0100236 }
Jiri Broulik96c867a2017-11-07 16:14:10 +0100237 }
Tomek Jaroszyk6d8a3aa2020-07-07 12:07:40 +0200238 finally {
239 // remove cluster flags
240 if (flags.size() > 0) {
241 stage('Unset cluster flags') {
242 for (flag in flags) {
243 common.infoMsg('Removing flag ' + flag)
244 salt.cmdRun(pepperEnv, ADMIN_HOST, 'ceph osd unset ' + flag)
245 }
Jakub Josefa63f9862018-01-11 17:58:38 +0100246 }
Jiri Broulikdc87d722017-11-03 15:43:22 +0100247 }
248 }
249 }
250 }
251}