blob: 22809c832fcf2627c5c15eaa1eecfb268567effd [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"
Jakub Josefa63f9862018-01-11 17:58:38 +010095 for (tgt in target_hosts) {
96 def osd_ids = []
Jiri Broulikdc87d722017-11-03 15:43:22 +010097
Jakub Josefa63f9862018-01-11 17:58:38 +010098 // get list of osd disks of the tgt
99 salt.runSaltProcessStep(pepperEnv, tgt, 'saltutil.sync_grains', [], null, true, 5)
mjedynski12955c72019-12-09 15:17:58 +0100100 def ceph_disks = salt.getGrain(pepperEnv, tgt, 'ceph')['return'][0].values()[0].values()[0][device_grain_name]
Jiri Broulikdc87d722017-11-03 15:43:22 +0100101
Jakub Josefa63f9862018-01-11 17:58:38 +0100102 for (i in ceph_disks) {
103 def osd_id = i.getKey().toString()
104 if (osd_id in osds || OSD == '*') {
105 osd_ids.add('osd.' + osd_id)
106 print("Will migrate " + osd_id)
Jiri Broulikeb7b82f2017-11-30 13:55:40 +0100107 } else {
Jakub Josefa63f9862018-01-11 17:58:38 +0100108 print("Skipping " + osd_id)
109 }
110 }
Jiri Broulikeb7b82f2017-11-30 13:55:40 +0100111
Jakub Josefa63f9862018-01-11 17:58:38 +0100112 for (osd_id in osd_ids) {
Jiri Broulikeb7b82f2017-11-30 13:55:40 +0100113
Jakub Josefa63f9862018-01-11 17:58:38 +0100114 def id = osd_id.replaceAll('osd.', '')
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400115 def backend = salt.cmdRun(pepperEnv, ADMIN_HOST, "ceph osd metadata ${id} | grep osd_objectstore")['return'][0].values()[0]
Jiri Broulikeb7b82f2017-11-30 13:55:40 +0100116
Jakub Josefa63f9862018-01-11 17:58:38 +0100117 if (backend.contains(ORIGIN_BACKEND.toLowerCase())) {
118
119 // wait for healthy cluster before manipulating with osds
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400120 if (WAIT_FOR_HEALTHY.toBoolean()) {
121 ceph.waitForHealthy(pepperEnv, ADMIN_HOST)
Jiri Broulika657d562017-11-28 14:19:32 +0100122 }
Jiri Broulikeb7b82f2017-11-30 13:55:40 +0100123
Jakub Josefa63f9862018-01-11 17:58:38 +0100124 // `ceph osd out <id> <id>`
125 stage('Set OSDs out') {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400126 salt.cmdRun(pepperEnv, ADMIN_HOST, "ceph osd out ${osd_id}")
Jiri Broulikdc87d722017-11-03 15:43:22 +0100127 }
Jiri Broulikdc87d722017-11-03 15:43:22 +0100128
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400129 if (WAIT_FOR_HEALTHY.toBoolean()) {
Jiri Broulik96c867a2017-11-07 16:14:10 +0100130 sleep(5)
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400131 ceph.waitForHealthy(pepperEnv, ADMIN_HOST)
Jiri Broulik96c867a2017-11-07 16:14:10 +0100132 }
133
Jakub Josefa63f9862018-01-11 17:58:38 +0100134 // stop osd daemons
135 stage('Stop OSD daemons') {
136 salt.runSaltProcessStep(pepperEnv, tgt, 'service.stop', ['ceph-osd@' + osd_id.replaceAll('osd.', '')], null, true)
137 }
138
139 // remove keyring `ceph auth del osd.3`
140 stage('Remove OSD keyrings from auth') {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400141 salt.cmdRun(pepperEnv, ADMIN_HOST, 'ceph auth del ' + osd_id)
Jakub Josefa63f9862018-01-11 17:58:38 +0100142 }
143
144 // remove osd `ceph osd rm osd.3`
145 stage('Remove OSDs') {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400146 salt.cmdRun(pepperEnv, ADMIN_HOST, 'ceph osd rm ' + osd_id)
Jakub Josefa63f9862018-01-11 17:58:38 +0100147 }
148
149 def dmcrypt = ""
150 try {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400151 dmcrypt = salt.cmdRun(pepperEnv, tgt, "ls -la /var/lib/ceph/osd/ceph-${id}/ | grep dmcrypt")['return'][0].values()[0]
Jakub Josefa63f9862018-01-11 17:58:38 +0100152 } catch (Exception e) {
153 common.warningMsg(e)
154 }
155
156 if (dmcrypt?.trim()) {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400157 def mount = salt.cmdRun(pepperEnv, tgt, "lsblk -rp | grep /var/lib/ceph/osd/ceph-${id} -B1")['return'][0].values()[0]
Jakub Josefa63f9862018-01-11 17:58:38 +0100158 dev = mount.split()[0].replaceAll("[0-9]","")
159
160 // remove partition tables
161 stage('dd part tables') {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400162 salt.cmdRun(pepperEnv, tgt, "dd if=/dev/zero of=${dev} bs=512 count=1 conv=notrunc")
Jakub Josefa63f9862018-01-11 17:58:38 +0100163 }
164
165 // remove journal, block_db, block_wal partition `parted /dev/sdj rm 3`
166 removeJournalOrBlockPartitions(pepperEnv, tgt, id)
167
168 // reboot
169 stage('reboot and wait') {
170 salt.runSaltProcessStep(pepperEnv, tgt, 'system.reboot', null, null, true, 5)
171 salt.minionsReachable(pepperEnv, 'I@salt:master', tgt)
172 sleep(10)
173 }
174
175 // zap disks `ceph-disk zap /dev/sdi`
176 stage('Zap devices') {
177 try {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400178 salt.cmdRun(pepperEnv, tgt, 'ceph-disk zap ' + dev)
Jakub Josefa63f9862018-01-11 17:58:38 +0100179 } catch (Exception e) {
180 common.warningMsg(e)
181 }
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400182 salt.cmdRun(pepperEnv, tgt, 'ceph-disk zap ' + dev)
Jakub Josefa63f9862018-01-11 17:58:38 +0100183 }
184
185 } else {
186
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400187 def mount = salt.cmdRun(pepperEnv, tgt, "mount | grep /var/lib/ceph/osd/ceph-${id}")['return'][0].values()[0]
Jakub Josefa63f9862018-01-11 17:58:38 +0100188 dev = mount.split()[0].replaceAll("[0-9]","")
189
190 // remove journal, block_db, block_wal partition `parted /dev/sdj rm 3`
191 removeJournalOrBlockPartitions(pepperEnv, tgt, id)
192
193 // umount `umount /dev/sdi1`
194 stage('Umount devices') {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400195 salt.cmdRun(pepperEnv, tgt, "umount /var/lib/ceph/osd/ceph-${id}")
Jakub Josefa63f9862018-01-11 17:58:38 +0100196 }
197
198 // zap disks `ceph-disk zap /dev/sdi`
199 stage('Zap device') {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400200 salt.cmdRun(pepperEnv, tgt, 'ceph-disk zap ' + dev)
Jakub Josefa63f9862018-01-11 17:58:38 +0100201 }
202 }
203
204 // Deploy Ceph OSD
205 stage('Deploy Ceph OSD') {
206 salt.runSaltProcessStep(pepperEnv, tgt, 'saltutil.refresh_pillar', [], null, true, 5)
207 salt.enforceState(pepperEnv, tgt, 'ceph.osd', true)
208 }
209
210 if (PER_OSD_CONTROL.toBoolean() == true) {
211 stage("Verify backend version for osd.${id}") {
212 sleep(5)
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400213 salt.cmdRun(pepperEnv, tgt, "ceph osd metadata ${id} | grep osd_objectstore")
214 salt.cmdRun(pepperEnv, tgt, "ceph -s")
Jakub Josefa63f9862018-01-11 17:58:38 +0100215 }
216
217 stage('Ask for manual confirmation') {
218 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?"
219 }
Jiri Broulik96c867a2017-11-07 16:14:10 +0100220 }
221 }
Jiri Broulikdc87d722017-11-03 15:43:22 +0100222 }
Jakub Josefa63f9862018-01-11 17:58:38 +0100223 if (PER_OSD_HOST_CONTROL.toBoolean() == true) {
224 stage("Verify backend versions") {
225 sleep(5)
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400226 salt.cmdRun(pepperEnv, tgt, "ceph osd metadata | grep osd_objectstore -B2")
227 salt.cmdRun(pepperEnv, tgt, "ceph -s")
Jakub Josefa63f9862018-01-11 17:58:38 +0100228 }
229
230 stage('Ask for manual confirmation') {
231 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?"
232 }
Jiri Broulik96c867a2017-11-07 16:14:10 +0100233 }
234
Jiri Broulik96c867a2017-11-07 16:14:10 +0100235 }
Jakub Josefa63f9862018-01-11 17:58:38 +0100236 // remove cluster flags
237 if (flags.size() > 0) {
238 stage('Unset cluster flags') {
239 for (flag in flags) {
240 common.infoMsg('Removing flag ' + flag)
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400241 salt.cmdRun(pepperEnv, ADMIN_HOST, 'ceph osd unset ' + flag)
Jakub Josefa63f9862018-01-11 17:58:38 +0100242 }
Jiri Broulikdc87d722017-11-03 15:43:22 +0100243 }
244 }
245 }
246 }
247}