blob: 18b03fb338fac12cadae1da9a9c05530dc475ddb [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
Jakub Josefa63f9862018-01-11 17:58:38 +010022timeout(time: 12, unit: 'HOURS') {
23 node("python") {
Jiri Broulik96c867a2017-11-07 16:14:10 +010024
Jakub Josefa63f9862018-01-11 17:58:38 +010025 // create connection to salt master
26 python.setupPepperVirtualenv(pepperEnv, SALT_MASTER_URL, SALT_MASTER_CREDENTIALS)
Jiri Broulik99887c82017-10-31 09:27:52 +010027
Jakub Josefa63f9862018-01-11 17:58:38 +010028 matches = ["osd", "mon", "rgw"]
29 def found = false
30 for (s in matches) {
31 if (HOST_TYPE.toLowerCase() == s) {
32 found = true
Jiri Broulik99887c82017-10-31 09:27:52 +010033 }
34 }
35
Jakub Josefa63f9862018-01-11 17:58:38 +010036 if (!found) {
37 common.errorMsg("No such HOST_TYPE was found. Please insert one of the following types: mon/osd/rgw")
38 throw new InterruptedException()
39 }
40
Mateusz Los13d05202020-05-11 09:51:13 +020041 def checknode = salt.runSaltProcessStep(pepperEnv, HOST, 'test.ping')
42 if (checknode['return'][0].values().isEmpty()) {
43 common.errorMsg("Host not found")
44 throw new InterruptedException()
45 }
46
Jakub Josefa63f9862018-01-11 17:58:38 +010047 stage('Refresh_pillar') {
48 salt.runSaltProcessStep(pepperEnv, '*', 'saltutil.refresh_pillar', [], null, true, 5)
49 }
50
51 // split minion id on '.' and remove '*'
52 def target = HOST.split("\\.")[0].replace("*", "")
53
54 salt.runSaltProcessStep(pepperEnv, 'I@salt:master', 'saltutil.sync_grains', [], null, true, 5)
55 def _pillar = salt.getGrain(pepperEnv, 'I@salt:master', 'domain')
56 domain = _pillar['return'][0].values()[0].values()[0]
57
58 if (HOST_TYPE.toLowerCase() == 'rgw') {
59 // Remove Ceph rgw
60 stage('Remove Ceph RGW') {
61 salt.enforceState(pepperEnv, 'I@ceph:radosgw', ['keepalived', 'haproxy'], true)
Jiri Broulik99887c82017-10-31 09:27:52 +010062 }
Mateusz Los9f503772019-05-07 15:10:45 +020063
64 stage('Purge Ceph RGW pkgs') {
65 salt.runSaltProcessStep(pepperEnv, HOST, 'pkg.purge', 'ceph-common,libcephfs2,python-cephfs,radosgw,python-rados,python-rbd,python-rgw')
66 }
Jiri Broulik99887c82017-10-31 09:27:52 +010067 }
68
Jakub Josefa63f9862018-01-11 17:58:38 +010069 if (HOST_TYPE.toLowerCase() != 'osd') {
70
71 // virsh destroy rgw04.deploy-name.local; virsh undefine rgw04.deploy-name.local;
72 stage('Destroy/Undefine VM') {
73 _pillar = salt.getGrain(pepperEnv, 'I@salt:control', 'id')
74 def kvm01 = _pillar['return'][0].values()[0].values()[0]
75
76 _pillar = salt.getPillar(pepperEnv, "${kvm01}", "salt:control:cluster:internal:node:${target}:provider")
77 def targetProvider = _pillar['return'][0].values()[0]
78
79 salt.cmdRun(pepperEnv, "${targetProvider}", "virsh destroy ${target}.${domain}")
80 salt.cmdRun(pepperEnv, "${targetProvider}", "virsh undefine ${target}.${domain}")
81 }
82 } else if (HOST_TYPE.toLowerCase() == 'osd') {
83 def osd_ids = []
Mateusz Los2ae66db2020-04-28 16:36:11 +020084 def device_grain_name = "ceph_disk"
Jakub Josefa63f9862018-01-11 17:58:38 +010085 // get list of osd disks of the host
86 salt.runSaltProcessStep(pepperEnv, HOST, 'saltutil.sync_grains', [], null, true, 5)
mjedynski12955c72019-12-09 15:17:58 +010087 def ceph_disks = salt.getGrain(pepperEnv, HOST, 'ceph')['return'][0].values()[0].values()[0][device_grain_name]
Jakub Josefa63f9862018-01-11 17:58:38 +010088
89 for (i in ceph_disks) {
90 def osd_id = i.getKey().toString()
91 osd_ids.add('osd.' + osd_id)
92 print("Will delete " + osd_id)
93 }
94
95 // `ceph osd out <id> <id>`
96 stage('Set OSDs out') {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +040097 salt.cmdRun(pepperEnv, ADMIN_HOST, 'ceph osd out ' + osd_ids.join(' '))
Jakub Josefa63f9862018-01-11 17:58:38 +010098 }
99
100 // wait for healthy cluster
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400101 if (WAIT_FOR_HEALTHY.toBoolean()) {
Jakub Josefa63f9862018-01-11 17:58:38 +0100102 sleep(5)
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400103 ceph.waitForHealthy(pepperEnv, ADMIN_HOST)
Jakub Josefa63f9862018-01-11 17:58:38 +0100104 }
105
106 // stop osd daemons
107 stage('Stop OSD daemons') {
108 for (i in osd_ids) {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400109 salt.runSaltProcessStep(pepperEnv, HOST, 'service.stop', ['ceph-osd@' + i.replaceAll('osd.', '')], null, true)
Jakub Josefa63f9862018-01-11 17:58:38 +0100110 }
111 }
112
113 // `ceph osd crush remove osd.2`
114 stage('Remove OSDs from CRUSH') {
115 for (i in osd_ids) {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400116 salt.cmdRun(pepperEnv, ADMIN_HOST, 'ceph osd crush remove ' + i)
Jakub Josefa63f9862018-01-11 17:58:38 +0100117 }
118 }
119
120 // remove keyring `ceph auth del osd.3`
121 stage('Remove OSD keyrings from auth') {
122 for (i in osd_ids) {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400123 salt.cmdRun(pepperEnv, ADMIN_HOST, 'ceph auth del ' + i)
Jakub Josefa63f9862018-01-11 17:58:38 +0100124 }
125 }
126
127 // remove osd `ceph osd rm osd.3`
128 stage('Remove OSDs') {
129 for (i in osd_ids) {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400130 salt.cmdRun(pepperEnv, ADMIN_HOST, 'ceph osd rm ' + i)
Jakub Josefa63f9862018-01-11 17:58:38 +0100131 }
132 }
133
134 for (osd_id in osd_ids) {
135
136 id = osd_id.replaceAll('osd.', '')
137 def dmcrypt = ""
138 try {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400139 dmcrypt = salt.cmdRun(pepperEnv, HOST, "ls -la /var/lib/ceph/osd/ceph-${id}/ | grep dmcrypt")['return'][0].values()[0]
Jakub Josefa63f9862018-01-11 17:58:38 +0100140 } catch (Exception e) {
141 common.warningMsg(e)
142 }
143
144 if (dmcrypt?.trim()) {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400145 mount = salt.cmdRun(pepperEnv, HOST, "lsblk -rp | grep /var/lib/ceph/osd/ceph-${id} -B1")['return'][0].values()[0]
146 dev = mount.split()[0].replaceAll("[0-9]", "")
Jakub Josefa63f9862018-01-11 17:58:38 +0100147
148 // remove partition tables
149 stage("dd part table on ${dev}") {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400150 salt.cmdRun(pepperEnv, HOST, "dd if=/dev/zero of=${dev} bs=512 count=1 conv=notrunc")
Jakub Josefa63f9862018-01-11 17:58:38 +0100151 }
152
153 }
154 // remove journal, block_db, block_wal partition `parted /dev/sdj rm 3`
155 stage('Remove journal / block_db / block_wal partition') {
156 def partition_uuid = ""
157 def journal_partition_uuid = ""
158 def block_db_partition_uuid = ""
159 def block_wal_partition_uuid = ""
160 try {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400161 journal_partition_uuid = salt.cmdRun(pepperEnv, HOST, "ls -la /var/lib/ceph/osd/ceph-${id}/ | grep journal | grep partuuid")
162 journal_partition_uuid = journal_partition_uuid.toString().trim().split("\n")[0].substring(journal_partition_uuid.toString().trim().lastIndexOf("/") + 1)
Jakub Josefa63f9862018-01-11 17:58:38 +0100163 } catch (Exception e) {
164 common.infoMsg(e)
165 }
166 try {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400167 block_db_partition_uuid = salt.cmdRun(pepperEnv, HOST, "ls -la /var/lib/ceph/osd/ceph-${id}/ | grep 'block.db' | grep partuuid")
168 block_db_partition_uuid = block_db_partition_uuid.toString().trim().split("\n")[0].substring(block_db_partition_uuid.toString().trim().lastIndexOf("/") + 1)
Jakub Josefa63f9862018-01-11 17:58:38 +0100169 } catch (Exception e) {
170 common.infoMsg(e)
171 }
172
173 try {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400174 block_wal_partition_uuid = salt.cmdRun(pepperEnv, HOST, "ls -la /var/lib/ceph/osd/ceph-${id}/ | grep 'block.wal' | grep partuuid")
175 block_wal_partition_uuid = block_wal_partition_uuid.toString().trim().split("\n")[0].substring(block_wal_partition_uuid.toString().trim().lastIndexOf("/") + 1)
Jakub Josefa63f9862018-01-11 17:58:38 +0100176 } catch (Exception e) {
177 common.infoMsg(e)
178 }
179
180 // set partition_uuid = 2c76f144-f412-481e-b150-4046212ca932
181 if (journal_partition_uuid?.trim()) {
182 partition_uuid = journal_partition_uuid
183 } else if (block_db_partition_uuid?.trim()) {
184 partition_uuid = block_db_partition_uuid
185 }
186
187 // if disk has journal, block_db or block_wal on different disk, then remove the partition
188 if (partition_uuid?.trim()) {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400189 ceph.removePartition(pepperEnv, HOST, partition_uuid)
Jakub Josefa63f9862018-01-11 17:58:38 +0100190 }
191 if (block_wal_partition_uuid?.trim()) {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400192 ceph.removePartition(pepperEnv, HOST, block_wal_partition_uuid)
Jakub Josefa63f9862018-01-11 17:58:38 +0100193 }
194 }
195 }
196
197 // purge Ceph pkgs
198 stage('Purge Ceph OSD pkgs') {
Mateusz Los9f503772019-05-07 15:10:45 +0200199 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 +0100200 }
201
202 stage('Remove OSD host from crushmap') {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400203 def hostname = salt.cmdRun(pepperEnv, HOST, "hostname -s")['return'][0].values()[0].split('\n')[0]
Jakub Josefa63f9862018-01-11 17:58:38 +0100204 try {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400205 salt.cmdRun(pepperEnv, ADMIN_HOST, "ceph osd crush remove ${hostname}")
Jakub Josefa63f9862018-01-11 17:58:38 +0100206 } catch (Exception e) {
207 common.warningMsg(e)
208 }
209 }
210
211 // stop salt-minion service and move its configuration
212 stage('Stop salt-minion') {
213 salt.cmdRun(pepperEnv, HOST, "mv /etc/salt/minion.d/minion.conf minion.conf")
214 salt.runSaltProcessStep(pepperEnv, HOST, 'service.stop', ['salt-minion'], [], null, true, 5)
Jiri Broulik99887c82017-10-31 09:27:52 +0100215 }
216 }
217
Jakub Josefa63f9862018-01-11 17:58:38 +0100218 stage('Remove salt-key') {
Jiri Broulikeb7b82f2017-11-30 13:55:40 +0100219 try {
Jakub Josefa63f9862018-01-11 17:58:38 +0100220 salt.cmdRun(pepperEnv, 'I@salt:master', "salt-key -d ${target}.${domain} -y")
Jiri Broulikeb7b82f2017-11-30 13:55:40 +0100221 } catch (Exception e) {
222 common.warningMsg(e)
223 }
Jiri Broulikc7ec65e2017-11-30 16:55:58 +0100224 try {
Jakub Josefa63f9862018-01-11 17:58:38 +0100225 salt.cmdRun(pepperEnv, 'I@salt:master', "rm /srv/salt/reclass/nodes/_generated/${target}.${domain}.yml")
Jiri Broulikc7ec65e2017-11-30 16:55:58 +0100226 } catch (Exception e) {
227 common.warningMsg(e)
228 }
229 }
230
Jakub Josefa63f9862018-01-11 17:58:38 +0100231 stage('Remove keyring') {
232 def keyring = ""
233 def keyring_lines = ""
Jiri Broulik99887c82017-10-31 09:27:52 +0100234 try {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400235 keyring_lines = salt.cmdRun(pepperEnv, ADMIN_HOST, "ceph auth list | grep ${target}")['return'][0].values()[0].split('\n')
Jiri Broulik99887c82017-10-31 09:27:52 +0100236 } catch (Exception e) {
237 common.warningMsg(e)
238 }
Jakub Josefa63f9862018-01-11 17:58:38 +0100239 for (line in keyring_lines) {
240 if (line.toLowerCase().contains(target.toLowerCase())) {
241 keyring = line
242 break
243 }
244 }
245 if (keyring?.trim()) {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400246 salt.cmdRun(pepperEnv, ADMIN_HOST, "ceph auth del ${keyring}")
Jiri Broulik3485b2c2017-11-28 15:06:12 +0100247 }
Jiri Broulik99887c82017-10-31 09:27:52 +0100248 }
Jiri Broulik99887c82017-10-31 09:27:52 +0100249
Jakub Josefa63f9862018-01-11 17:58:38 +0100250 if (HOST_TYPE.toLowerCase() == 'mon') {
251 // Update Monmap
252 stage('Update monmap') {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400253 salt.cmdRun(pepperEnv, 'I@ceph:mon', "ceph mon getmap -o monmap.backup")
Jakub Josefa63f9862018-01-11 17:58:38 +0100254 try {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400255 salt.cmdRun(pepperEnv, 'I@ceph:mon', "ceph mon remove ${target}")
Jakub Josefa63f9862018-01-11 17:58:38 +0100256 } catch (Exception e) {
257 common.warningMsg(e)
258 }
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400259 salt.cmdRun(pepperEnv, 'I@ceph:mon', "monmaptool /tmp/monmap --rm ${target}")
Jakub Josefa63f9862018-01-11 17:58:38 +0100260 }
261
262 def target_hosts = salt.getMinions(pepperEnv, 'I@ceph:common')
263 print target_hosts
264
265 // Update configs
266 stage('Update Ceph configs') {
267 for (tgt in target_hosts) {
268 salt.enforceState(pepperEnv, tgt, 'ceph.common', true)
269 }
270 }
Mateusz Los9f503772019-05-07 15:10:45 +0200271
272 stage('Purge Ceph MON pkgs') {
273 salt.runSaltProcessStep(pepperEnv, HOST, 'pkg.purge', 'ceph-base,ceph-common,ceph-mgr,ceph-mon,libcephfs2,python-cephfs,python-rbd,python-rgw')
274 }
Jakub Josefa63f9862018-01-11 17:58:38 +0100275 }
276
Mateusz Losbb352892019-10-09 11:36:10 +0200277 def crushmap_target = salt.getMinions(pepperEnv, "I@ceph:setup:crush")
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400278 if (HOST_TYPE.toLowerCase() == 'osd' && GENERATE_CRUSHMAP.toBoolean() == true && crushmap_target) {
Jakub Josefa63f9862018-01-11 17:58:38 +0100279 stage('Generate CRUSHMAP') {
280 salt.enforceState(pepperEnv, 'I@ceph:setup:crush', 'ceph.setup.crush', true)
281 }
Jiri Broulik99887c82017-10-31 09:27:52 +0100282 }
283 }
284}