blob: 55e9d6e023f904b040efa6717b224bb1be2765a6 [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
41 stage('Refresh_pillar') {
42 salt.runSaltProcessStep(pepperEnv, '*', 'saltutil.refresh_pillar', [], null, true, 5)
43 }
44
45 // split minion id on '.' and remove '*'
46 def target = HOST.split("\\.")[0].replace("*", "")
47
48 salt.runSaltProcessStep(pepperEnv, 'I@salt:master', 'saltutil.sync_grains', [], null, true, 5)
49 def _pillar = salt.getGrain(pepperEnv, 'I@salt:master', 'domain')
50 domain = _pillar['return'][0].values()[0].values()[0]
51
52 if (HOST_TYPE.toLowerCase() == 'rgw') {
53 // Remove Ceph rgw
54 stage('Remove Ceph RGW') {
55 salt.enforceState(pepperEnv, 'I@ceph:radosgw', ['keepalived', 'haproxy'], true)
Jiri Broulik99887c82017-10-31 09:27:52 +010056 }
Mateusz Los9f503772019-05-07 15:10:45 +020057
58 stage('Purge Ceph RGW pkgs') {
59 salt.runSaltProcessStep(pepperEnv, HOST, 'pkg.purge', 'ceph-common,libcephfs2,python-cephfs,radosgw,python-rados,python-rbd,python-rgw')
60 }
Jiri Broulik99887c82017-10-31 09:27:52 +010061 }
62
Jakub Josefa63f9862018-01-11 17:58:38 +010063 if (HOST_TYPE.toLowerCase() != 'osd') {
64
65 // virsh destroy rgw04.deploy-name.local; virsh undefine rgw04.deploy-name.local;
66 stage('Destroy/Undefine VM') {
67 _pillar = salt.getGrain(pepperEnv, 'I@salt:control', 'id')
68 def kvm01 = _pillar['return'][0].values()[0].values()[0]
69
70 _pillar = salt.getPillar(pepperEnv, "${kvm01}", "salt:control:cluster:internal:node:${target}:provider")
71 def targetProvider = _pillar['return'][0].values()[0]
72
73 salt.cmdRun(pepperEnv, "${targetProvider}", "virsh destroy ${target}.${domain}")
74 salt.cmdRun(pepperEnv, "${targetProvider}", "virsh undefine ${target}.${domain}")
75 }
76 } else if (HOST_TYPE.toLowerCase() == 'osd') {
77 def osd_ids = []
Mateusz Los2ae66db2020-04-28 16:36:11 +020078 def device_grain_name = "ceph_disk"
Jakub Josefa63f9862018-01-11 17:58:38 +010079 // get list of osd disks of the host
80 salt.runSaltProcessStep(pepperEnv, HOST, 'saltutil.sync_grains', [], null, true, 5)
mjedynski12955c72019-12-09 15:17:58 +010081 def ceph_disks = salt.getGrain(pepperEnv, HOST, 'ceph')['return'][0].values()[0].values()[0][device_grain_name]
Jakub Josefa63f9862018-01-11 17:58:38 +010082
83 for (i in ceph_disks) {
84 def osd_id = i.getKey().toString()
85 osd_ids.add('osd.' + osd_id)
86 print("Will delete " + osd_id)
87 }
88
89 // `ceph osd out <id> <id>`
90 stage('Set OSDs out') {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +040091 salt.cmdRun(pepperEnv, ADMIN_HOST, 'ceph osd out ' + osd_ids.join(' '))
Jakub Josefa63f9862018-01-11 17:58:38 +010092 }
93
94 // wait for healthy cluster
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +040095 if (WAIT_FOR_HEALTHY.toBoolean()) {
Jakub Josefa63f9862018-01-11 17:58:38 +010096 sleep(5)
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +040097 ceph.waitForHealthy(pepperEnv, ADMIN_HOST)
Jakub Josefa63f9862018-01-11 17:58:38 +010098 }
99
100 // stop osd daemons
101 stage('Stop OSD daemons') {
102 for (i in osd_ids) {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400103 salt.runSaltProcessStep(pepperEnv, HOST, 'service.stop', ['ceph-osd@' + i.replaceAll('osd.', '')], null, true)
Jakub Josefa63f9862018-01-11 17:58:38 +0100104 }
105 }
106
107 // `ceph osd crush remove osd.2`
108 stage('Remove OSDs from CRUSH') {
109 for (i in osd_ids) {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400110 salt.cmdRun(pepperEnv, ADMIN_HOST, 'ceph osd crush remove ' + i)
Jakub Josefa63f9862018-01-11 17:58:38 +0100111 }
112 }
113
114 // remove keyring `ceph auth del osd.3`
115 stage('Remove OSD keyrings from auth') {
116 for (i in osd_ids) {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400117 salt.cmdRun(pepperEnv, ADMIN_HOST, 'ceph auth del ' + i)
Jakub Josefa63f9862018-01-11 17:58:38 +0100118 }
119 }
120
121 // remove osd `ceph osd rm osd.3`
122 stage('Remove OSDs') {
123 for (i in osd_ids) {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400124 salt.cmdRun(pepperEnv, ADMIN_HOST, 'ceph osd rm ' + i)
Jakub Josefa63f9862018-01-11 17:58:38 +0100125 }
126 }
127
128 for (osd_id in osd_ids) {
129
130 id = osd_id.replaceAll('osd.', '')
131 def dmcrypt = ""
132 try {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400133 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 +0100134 } catch (Exception e) {
135 common.warningMsg(e)
136 }
137
138 if (dmcrypt?.trim()) {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400139 mount = salt.cmdRun(pepperEnv, HOST, "lsblk -rp | grep /var/lib/ceph/osd/ceph-${id} -B1")['return'][0].values()[0]
140 dev = mount.split()[0].replaceAll("[0-9]", "")
Jakub Josefa63f9862018-01-11 17:58:38 +0100141
142 // remove partition tables
143 stage("dd part table on ${dev}") {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400144 salt.cmdRun(pepperEnv, HOST, "dd if=/dev/zero of=${dev} bs=512 count=1 conv=notrunc")
Jakub Josefa63f9862018-01-11 17:58:38 +0100145 }
146
147 }
148 // remove journal, block_db, block_wal partition `parted /dev/sdj rm 3`
149 stage('Remove journal / block_db / block_wal partition') {
150 def partition_uuid = ""
151 def journal_partition_uuid = ""
152 def block_db_partition_uuid = ""
153 def block_wal_partition_uuid = ""
154 try {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400155 journal_partition_uuid = salt.cmdRun(pepperEnv, HOST, "ls -la /var/lib/ceph/osd/ceph-${id}/ | grep journal | grep partuuid")
156 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 +0100157 } catch (Exception e) {
158 common.infoMsg(e)
159 }
160 try {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400161 block_db_partition_uuid = salt.cmdRun(pepperEnv, HOST, "ls -la /var/lib/ceph/osd/ceph-${id}/ | grep 'block.db' | grep partuuid")
162 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 +0100163 } catch (Exception e) {
164 common.infoMsg(e)
165 }
166
167 try {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400168 block_wal_partition_uuid = salt.cmdRun(pepperEnv, HOST, "ls -la /var/lib/ceph/osd/ceph-${id}/ | grep 'block.wal' | grep partuuid")
169 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 +0100170 } catch (Exception e) {
171 common.infoMsg(e)
172 }
173
174 // set partition_uuid = 2c76f144-f412-481e-b150-4046212ca932
175 if (journal_partition_uuid?.trim()) {
176 partition_uuid = journal_partition_uuid
177 } else if (block_db_partition_uuid?.trim()) {
178 partition_uuid = block_db_partition_uuid
179 }
180
181 // if disk has journal, block_db or block_wal on different disk, then remove the partition
182 if (partition_uuid?.trim()) {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400183 ceph.removePartition(pepperEnv, HOST, partition_uuid)
Jakub Josefa63f9862018-01-11 17:58:38 +0100184 }
185 if (block_wal_partition_uuid?.trim()) {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400186 ceph.removePartition(pepperEnv, HOST, block_wal_partition_uuid)
Jakub Josefa63f9862018-01-11 17:58:38 +0100187 }
188 }
189 }
190
191 // purge Ceph pkgs
192 stage('Purge Ceph OSD pkgs') {
Mateusz Los9f503772019-05-07 15:10:45 +0200193 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 +0100194 }
195
196 stage('Remove OSD host from crushmap') {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400197 def hostname = salt.cmdRun(pepperEnv, HOST, "hostname -s")['return'][0].values()[0].split('\n')[0]
Jakub Josefa63f9862018-01-11 17:58:38 +0100198 try {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400199 salt.cmdRun(pepperEnv, ADMIN_HOST, "ceph osd crush remove ${hostname}")
Jakub Josefa63f9862018-01-11 17:58:38 +0100200 } catch (Exception e) {
201 common.warningMsg(e)
202 }
203 }
204
205 // stop salt-minion service and move its configuration
206 stage('Stop salt-minion') {
207 salt.cmdRun(pepperEnv, HOST, "mv /etc/salt/minion.d/minion.conf minion.conf")
208 salt.runSaltProcessStep(pepperEnv, HOST, 'service.stop', ['salt-minion'], [], null, true, 5)
Jiri Broulik99887c82017-10-31 09:27:52 +0100209 }
210 }
211
Jakub Josefa63f9862018-01-11 17:58:38 +0100212 stage('Remove salt-key') {
Jiri Broulikeb7b82f2017-11-30 13:55:40 +0100213 try {
Jakub Josefa63f9862018-01-11 17:58:38 +0100214 salt.cmdRun(pepperEnv, 'I@salt:master', "salt-key -d ${target}.${domain} -y")
Jiri Broulikeb7b82f2017-11-30 13:55:40 +0100215 } catch (Exception e) {
216 common.warningMsg(e)
217 }
Jiri Broulikc7ec65e2017-11-30 16:55:58 +0100218 try {
Jakub Josefa63f9862018-01-11 17:58:38 +0100219 salt.cmdRun(pepperEnv, 'I@salt:master', "rm /srv/salt/reclass/nodes/_generated/${target}.${domain}.yml")
Jiri Broulikc7ec65e2017-11-30 16:55:58 +0100220 } catch (Exception e) {
221 common.warningMsg(e)
222 }
223 }
224
Jakub Josefa63f9862018-01-11 17:58:38 +0100225 stage('Remove keyring') {
226 def keyring = ""
227 def keyring_lines = ""
Jiri Broulik99887c82017-10-31 09:27:52 +0100228 try {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400229 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 +0100230 } catch (Exception e) {
231 common.warningMsg(e)
232 }
Jakub Josefa63f9862018-01-11 17:58:38 +0100233 for (line in keyring_lines) {
234 if (line.toLowerCase().contains(target.toLowerCase())) {
235 keyring = line
236 break
237 }
238 }
239 if (keyring?.trim()) {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400240 salt.cmdRun(pepperEnv, ADMIN_HOST, "ceph auth del ${keyring}")
Jiri Broulik3485b2c2017-11-28 15:06:12 +0100241 }
Jiri Broulik99887c82017-10-31 09:27:52 +0100242 }
Jiri Broulik99887c82017-10-31 09:27:52 +0100243
Jakub Josefa63f9862018-01-11 17:58:38 +0100244 if (HOST_TYPE.toLowerCase() == 'mon') {
245 // Update Monmap
246 stage('Update monmap') {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400247 salt.cmdRun(pepperEnv, 'I@ceph:mon', "ceph mon getmap -o monmap.backup")
Jakub Josefa63f9862018-01-11 17:58:38 +0100248 try {
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400249 salt.cmdRun(pepperEnv, 'I@ceph:mon', "ceph mon remove ${target}")
Jakub Josefa63f9862018-01-11 17:58:38 +0100250 } catch (Exception e) {
251 common.warningMsg(e)
252 }
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400253 salt.cmdRun(pepperEnv, 'I@ceph:mon', "monmaptool /tmp/monmap --rm ${target}")
Jakub Josefa63f9862018-01-11 17:58:38 +0100254 }
255
256 def target_hosts = salt.getMinions(pepperEnv, 'I@ceph:common')
257 print target_hosts
258
259 // Update configs
260 stage('Update Ceph configs') {
261 for (tgt in target_hosts) {
262 salt.enforceState(pepperEnv, tgt, 'ceph.common', true)
263 }
264 }
Mateusz Los9f503772019-05-07 15:10:45 +0200265
266 stage('Purge Ceph MON pkgs') {
267 salt.runSaltProcessStep(pepperEnv, HOST, 'pkg.purge', 'ceph-base,ceph-common,ceph-mgr,ceph-mon,libcephfs2,python-cephfs,python-rbd,python-rgw')
268 }
Jakub Josefa63f9862018-01-11 17:58:38 +0100269 }
270
Mateusz Losbb352892019-10-09 11:36:10 +0200271 def crushmap_target = salt.getMinions(pepperEnv, "I@ceph:setup:crush")
Ivan Berezovskiy19c685a2019-11-05 17:42:57 +0400272 if (HOST_TYPE.toLowerCase() == 'osd' && GENERATE_CRUSHMAP.toBoolean() == true && crushmap_target) {
Jakub Josefa63f9862018-01-11 17:58:38 +0100273 stage('Generate CRUSHMAP') {
274 salt.enforceState(pepperEnv, 'I@ceph:setup:crush', 'ceph.setup.crush', true)
275 }
Jiri Broulik99887c82017-10-31 09:27:52 +0100276 }
277 }
278}