blob: 771a3996c48771bde30dcb01a7fa78b221398526 [file] [log] [blame]
Jiri Broulik99887c82017-10-31 09:27:52 +01001/**
2 *
3 * Remove Ceph node from existing cluster
4 *
5 * Requred parameters:
6 * SALT_MASTER_URL URL of Salt master
7 * SALT_MASTER_CREDENTIALS Credentials to the Salt API
8 * HOST Host (minion id) to be removed
9 * HOST_TYPE Type of Ceph node to be removed. Valid values are mon/osd/rgw
10 * ADMIN_HOST Host (minion id) with admin keyring
11 * WAIT_FOR_HEALTHY Wait for cluster rebalance before stoping daemons
12 * GENERATE_CRUSHMAP Set to true if the crush map should be generated
13 *
14 */
15
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +040016def common = new com.mirantis.mk.Common()
17def salt = new com.mirantis.mk.Salt()
18def ceph = new com.mirantis.mk.Ceph()
Jiri Broulik99887c82017-10-31 09:27:52 +010019def python = new com.mirantis.mk.Python()
Jiri Broulik99887c82017-10-31 09:27:52 +010020def pepperEnv = "pepperEnv"
21
Mateusz Los8b64b812020-05-11 10:33:58 +020022def cleanDisk = CLEANDISK
23
Jakub Josefa63f9862018-01-11 17:58:38 +010024timeout(time: 12, unit: 'HOURS') {
25 node("python") {
Jiri Broulik96c867a2017-11-07 16:14:10 +010026
Jakub Josefa63f9862018-01-11 17:58:38 +010027 // create connection to salt master
28 python.setupPepperVirtualenv(pepperEnv, SALT_MASTER_URL, SALT_MASTER_CREDENTIALS)
Jiri Broulik99887c82017-10-31 09:27:52 +010029
Jakub Josefa63f9862018-01-11 17:58:38 +010030 matches = ["osd", "mon", "rgw"]
31 def found = false
32 for (s in matches) {
33 if (HOST_TYPE.toLowerCase() == s) {
34 found = true
Jiri Broulik99887c82017-10-31 09:27:52 +010035 }
36 }
37
Jakub Josefa63f9862018-01-11 17:58:38 +010038 if (!found) {
39 common.errorMsg("No such HOST_TYPE was found. Please insert one of the following types: mon/osd/rgw")
40 throw new InterruptedException()
41 }
42
Mateusz Los13d05202020-05-11 09:51:13 +020043 def checknode = salt.runSaltProcessStep(pepperEnv, HOST, 'test.ping')
44 if (checknode['return'][0].values().isEmpty()) {
45 common.errorMsg("Host not found")
46 throw new InterruptedException()
47 }
48
Jakub Josefa63f9862018-01-11 17:58:38 +010049 stage('Refresh_pillar') {
50 salt.runSaltProcessStep(pepperEnv, '*', 'saltutil.refresh_pillar', [], null, true, 5)
51 }
52
53 // split minion id on '.' and remove '*'
54 def target = HOST.split("\\.")[0].replace("*", "")
55
56 salt.runSaltProcessStep(pepperEnv, 'I@salt:master', 'saltutil.sync_grains', [], null, true, 5)
57 def _pillar = salt.getGrain(pepperEnv, 'I@salt:master', 'domain')
58 domain = _pillar['return'][0].values()[0].values()[0]
59
60 if (HOST_TYPE.toLowerCase() == 'rgw') {
61 // Remove Ceph rgw
62 stage('Remove Ceph RGW') {
63 salt.enforceState(pepperEnv, 'I@ceph:radosgw', ['keepalived', 'haproxy'], true)
Jiri Broulik99887c82017-10-31 09:27:52 +010064 }
Mateusz Los9f503772019-05-07 15:10:45 +020065
66 stage('Purge Ceph RGW pkgs') {
67 salt.runSaltProcessStep(pepperEnv, HOST, 'pkg.purge', 'ceph-common,libcephfs2,python-cephfs,radosgw,python-rados,python-rbd,python-rgw')
68 }
Jiri Broulik99887c82017-10-31 09:27:52 +010069 }
70
Jakub Josefa63f9862018-01-11 17:58:38 +010071 if (HOST_TYPE.toLowerCase() != 'osd') {
72
73 // virsh destroy rgw04.deploy-name.local; virsh undefine rgw04.deploy-name.local;
74 stage('Destroy/Undefine VM') {
75 _pillar = salt.getGrain(pepperEnv, 'I@salt:control', 'id')
76 def kvm01 = _pillar['return'][0].values()[0].values()[0]
77
78 _pillar = salt.getPillar(pepperEnv, "${kvm01}", "salt:control:cluster:internal:node:${target}:provider")
79 def targetProvider = _pillar['return'][0].values()[0]
80
81 salt.cmdRun(pepperEnv, "${targetProvider}", "virsh destroy ${target}.${domain}")
82 salt.cmdRun(pepperEnv, "${targetProvider}", "virsh undefine ${target}.${domain}")
83 }
Mateusz Los8b64b812020-05-11 10:33:58 +020084 }
85 else if (HOST_TYPE.toLowerCase() == 'osd') {
Jakub Josefa63f9862018-01-11 17:58:38 +010086 def osd_ids = []
Mateusz Los2ae66db2020-04-28 16:36:11 +020087 def device_grain_name = "ceph_disk"
Jakub Josefa63f9862018-01-11 17:58:38 +010088 // get list of osd disks of the host
89 salt.runSaltProcessStep(pepperEnv, HOST, 'saltutil.sync_grains', [], null, true, 5)
mjedynski12955c72019-12-09 15:17:58 +010090 def ceph_disks = salt.getGrain(pepperEnv, HOST, 'ceph')['return'][0].values()[0].values()[0][device_grain_name]
Jakub Josefa63f9862018-01-11 17:58:38 +010091
92 for (i in ceph_disks) {
93 def osd_id = i.getKey().toString()
94 osd_ids.add('osd.' + osd_id)
95 print("Will delete " + osd_id)
96 }
97
98 // `ceph osd out <id> <id>`
99 stage('Set OSDs out') {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400100 salt.cmdRun(pepperEnv, ADMIN_HOST, 'ceph osd out ' + osd_ids.join(' '))
Jakub Josefa63f9862018-01-11 17:58:38 +0100101 }
102
103 // wait for healthy cluster
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400104 if (WAIT_FOR_HEALTHY.toBoolean()) {
Jakub Josefa63f9862018-01-11 17:58:38 +0100105 sleep(5)
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400106 ceph.waitForHealthy(pepperEnv, ADMIN_HOST)
Jakub Josefa63f9862018-01-11 17:58:38 +0100107 }
108
109 // stop osd daemons
110 stage('Stop OSD daemons') {
111 for (i in osd_ids) {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400112 salt.runSaltProcessStep(pepperEnv, HOST, 'service.stop', ['ceph-osd@' + i.replaceAll('osd.', '')], null, true)
Jakub Josefa63f9862018-01-11 17:58:38 +0100113 }
114 }
115
116 // `ceph osd crush remove osd.2`
117 stage('Remove OSDs from CRUSH') {
118 for (i in osd_ids) {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400119 salt.cmdRun(pepperEnv, ADMIN_HOST, 'ceph osd crush remove ' + i)
Jakub Josefa63f9862018-01-11 17:58:38 +0100120 }
121 }
122
123 // remove keyring `ceph auth del osd.3`
124 stage('Remove OSD keyrings from auth') {
125 for (i in osd_ids) {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400126 salt.cmdRun(pepperEnv, ADMIN_HOST, 'ceph auth del ' + i)
Jakub Josefa63f9862018-01-11 17:58:38 +0100127 }
128 }
129
130 // remove osd `ceph osd rm osd.3`
131 stage('Remove OSDs') {
132 for (i in osd_ids) {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400133 salt.cmdRun(pepperEnv, ADMIN_HOST, 'ceph osd rm ' + i)
Jakub Josefa63f9862018-01-11 17:58:38 +0100134 }
135 }
136
137 for (osd_id in osd_ids) {
Jakub Josefa63f9862018-01-11 17:58:38 +0100138 id = osd_id.replaceAll('osd.', '')
Jakub Josefa63f9862018-01-11 17:58:38 +0100139
Jakub Josefa63f9862018-01-11 17:58:38 +0100140 // remove journal, block_db, block_wal partition `parted /dev/sdj rm 3`
141 stage('Remove journal / block_db / block_wal partition') {
142 def partition_uuid = ""
143 def journal_partition_uuid = ""
144 def block_db_partition_uuid = ""
145 def block_wal_partition_uuid = ""
Mateusz Los8b64b812020-05-11 10:33:58 +0200146 def ceph_version = salt.getPillar(pepperEnv, HOST, 'ceph:common:ceph_version').get('return')[0].values()[0]
147
148 if (ceph_version == "luminous") {
149 try {
150 journal_partition_uuid = salt.cmdRun(pepperEnv, HOST, "cat /var/lib/ceph/osd/ceph-${id}/journal_uuid")['return'][0].values()[0].split("\n")[0]
151 }
152 catch(Exception e) {
153 common.infoMsg(e)
154 }
155 try {
156 block_db_partition_uuid = salt.cmdRun(pepperEnv, HOST, "cat /var/lib/ceph/osd/ceph-${id}/block.db_uuid")['return'][0].values()[0].split("\n")[0]
157 }
158 catch(Exception e) {
159 common.infoMsg(e)
160 }
161 try {
162 block_wal_partition_uuid = salt.cmdRun(pepperEnv, HOST, "cat /var/lib/ceph/osd/ceph-${id}/block.wal_uuid")['return'][0].values()[0].split("\n")[0]
163 }
164 catch(Exception e) {
165 common.infoMsg(e)
166 }
Jakub Josefa63f9862018-01-11 17:58:38 +0100167 }
Mateusz Los8b64b812020-05-11 10:33:58 +0200168 else {
169 def volumes = salt.cmdRun(pepperEnv, HOST, "ceph-volume lvm list --format=json", checkResponse=true, batch=null, output=false)
170 volumes = new groovy.json.JsonSlurperClassic().parseText(volumes['return'][0].values()[0])
171
172 block_db_partition_uuid = volumes[id][0]['tags'].get('ceph.db_uuid')
173 block_wal_partition_uuid = volumes[id][0]['tags'].get('ceph.wal_uuid')
Jakub Josefa63f9862018-01-11 17:58:38 +0100174 }
175
Jakub Josefa63f9862018-01-11 17:58:38 +0100176
Jakub Josefa63f9862018-01-11 17:58:38 +0100177 if (journal_partition_uuid?.trim()) {
Mateusz Los8b64b812020-05-11 10:33:58 +0200178 ceph.removePartition(pepperEnv, HOST, journal_partition_uuid)
Jakub Josefa63f9862018-01-11 17:58:38 +0100179 }
Mateusz Los8b64b812020-05-11 10:33:58 +0200180 if (block_db_partition_uuid?.trim()) {
181 ceph.removePartition(pepperEnv, HOST, block_db_partition_uuid)
Jakub Josefa63f9862018-01-11 17:58:38 +0100182 }
183 if (block_wal_partition_uuid?.trim()) {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400184 ceph.removePartition(pepperEnv, HOST, block_wal_partition_uuid)
Jakub Josefa63f9862018-01-11 17:58:38 +0100185 }
Mateusz Los8b64b812020-05-11 10:33:58 +0200186
187 try {
188 salt.cmdRun(pepperEnv, HOST, "partprobe")
189 } catch (Exception e) {
190 common.warningMsg(e)
191 }
192 }
193
194 if (cleanDisk) {
195 // remove data / block / lockbox partition `parted /dev/sdj rm 3`
196 stage('Remove data / block / lockbox partition') {
197 def data_partition_uuid = ""
198 def block_partition_uuid = ""
199 def osd_fsid = ""
200 def lvm = ""
201 def lvm_enabled= salt.getPillar(pepperEnv,"I@ceph:osd","ceph:osd:lvm_enabled")['return'].first().containsValue(true)
202 try {
203 osd_fsid = salt.cmdRun(pepperEnv, HOST, "cat /var/lib/ceph/osd/ceph-${id}/fsid")['return'][0].values()[0].split("\n")[0]
204 if (lvm_enabled) {
205 lvm = salt.runSaltCommand(pepperEnv, 'local', ['expression': HOST, 'type': 'compound'], 'cmd.run', null, "salt-call lvm.lvdisplay --output json -l quiet")['return'][0].values()[0]
206 lvm = new groovy.json.JsonSlurperClassic().parseText(lvm)
207 lvm["local"].each { lv, params ->
208 if (params["Logical Volume Name"].contains(osd_fsid)) {
209 data_partition_uuid = params["Logical Volume Name"].minus("/dev/")
210 }
211 }
212 } else {
213 data_partition_uuid = osd_fsid
214 }
215 } catch (Exception e) {
216 common.infoMsg(e)
217 }
218 try {
219 block_partition_uuid = salt.cmdRun(pepperEnv, HOST, "cat /var/lib/ceph/osd/ceph-${id}/block_uuid")['return'][0].values()[0].split("\n")[0]
220 }
221 catch (Exception e) {
222 common.infoMsg(e)
223 }
224
225 // remove partition_uuid = 2c76f144-f412-481e-b150-4046212ca932
226 if (block_partition_uuid?.trim()) {
227 ceph.removePartition(pepperEnv, HOST, block_partition_uuid)
228 try {
229 salt.cmdRun(pepperEnv, HOST, "ceph-volume lvm zap `readlink /var/lib/ceph/osd/ceph-${id}/block` --destroy")
230 }
231 catch (Exception e) {
232 common.infoMsg(e)
233 }
234 }
235 if (data_partition_uuid?.trim()) {
236 ceph.removePartition(pepperEnv, HOST, data_partition_uuid, 'data', id)
237 }
238 }
Jakub Josefa63f9862018-01-11 17:58:38 +0100239 }
240 }
241
242 // purge Ceph pkgs
243 stage('Purge Ceph OSD pkgs') {
Mateusz Los9f503772019-05-07 15:10:45 +0200244 salt.runSaltProcessStep(pepperEnv, HOST, 'pkg.purge', 'ceph-base,ceph-common,ceph-fuse,ceph-mds,ceph-osd,python-cephfs,librados2,python-rados,python-rbd,python-rgw')
Jakub Josefa63f9862018-01-11 17:58:38 +0100245 }
246
247 stage('Remove OSD host from crushmap') {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400248 def hostname = salt.cmdRun(pepperEnv, HOST, "hostname -s")['return'][0].values()[0].split('\n')[0]
Jakub Josefa63f9862018-01-11 17:58:38 +0100249 try {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400250 salt.cmdRun(pepperEnv, ADMIN_HOST, "ceph osd crush remove ${hostname}")
Jakub Josefa63f9862018-01-11 17:58:38 +0100251 } catch (Exception e) {
252 common.warningMsg(e)
253 }
254 }
255
256 // stop salt-minion service and move its configuration
257 stage('Stop salt-minion') {
258 salt.cmdRun(pepperEnv, HOST, "mv /etc/salt/minion.d/minion.conf minion.conf")
259 salt.runSaltProcessStep(pepperEnv, HOST, 'service.stop', ['salt-minion'], [], null, true, 5)
Jiri Broulik99887c82017-10-31 09:27:52 +0100260 }
Jiri Broulik99887c82017-10-31 09:27:52 +0100261
Mateusz Los8b64b812020-05-11 10:33:58 +0200262 stage('Remove salt-key') {
263 try {
264 salt.cmdRun(pepperEnv, 'I@salt:master', "salt-key -d ${target}.${domain} -y")
265 } catch (Exception e) {
266 common.warningMsg(e)
Jakub Josefa63f9862018-01-11 17:58:38 +0100267 }
Mateusz Los8b64b812020-05-11 10:33:58 +0200268 try {
269 salt.cmdRun(pepperEnv, 'I@salt:master', "rm /srv/salt/reclass/nodes/_generated/${target}.${domain}.yml")
270 } catch (Exception e) {
271 common.warningMsg(e)
272 }
Jiri Broulik3485b2c2017-11-28 15:06:12 +0100273 }
Jiri Broulik99887c82017-10-31 09:27:52 +0100274 }
Jiri Broulik99887c82017-10-31 09:27:52 +0100275
Jakub Josefa63f9862018-01-11 17:58:38 +0100276 if (HOST_TYPE.toLowerCase() == 'mon') {
277 // Update Monmap
278 stage('Update monmap') {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400279 salt.cmdRun(pepperEnv, 'I@ceph:mon', "ceph mon getmap -o monmap.backup")
Jakub Josefa63f9862018-01-11 17:58:38 +0100280 try {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400281 salt.cmdRun(pepperEnv, 'I@ceph:mon', "ceph mon remove ${target}")
Jakub Josefa63f9862018-01-11 17:58:38 +0100282 } catch (Exception e) {
283 common.warningMsg(e)
284 }
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400285 salt.cmdRun(pepperEnv, 'I@ceph:mon', "monmaptool /tmp/monmap --rm ${target}")
Jakub Josefa63f9862018-01-11 17:58:38 +0100286 }
287
288 def target_hosts = salt.getMinions(pepperEnv, 'I@ceph:common')
Jakub Josefa63f9862018-01-11 17:58:38 +0100289
290 // Update configs
291 stage('Update Ceph configs') {
292 for (tgt in target_hosts) {
293 salt.enforceState(pepperEnv, tgt, 'ceph.common', true)
294 }
295 }
Mateusz Los9f503772019-05-07 15:10:45 +0200296
297 stage('Purge Ceph MON pkgs') {
298 salt.runSaltProcessStep(pepperEnv, HOST, 'pkg.purge', 'ceph-base,ceph-common,ceph-mgr,ceph-mon,libcephfs2,python-cephfs,python-rbd,python-rgw')
299 }
Jakub Josefa63f9862018-01-11 17:58:38 +0100300 }
301
Mateusz Losbb352892019-10-09 11:36:10 +0200302 def crushmap_target = salt.getMinions(pepperEnv, "I@ceph:setup:crush")
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400303 if (HOST_TYPE.toLowerCase() == 'osd' && GENERATE_CRUSHMAP.toBoolean() == true && crushmap_target) {
Jakub Josefa63f9862018-01-11 17:58:38 +0100304 stage('Generate CRUSHMAP') {
305 salt.enforceState(pepperEnv, 'I@ceph:setup:crush', 'ceph.setup.crush', true)
306 }
Jiri Broulik99887c82017-10-31 09:27:52 +0100307 }
308 }
309}