blob: 4124ce4b19bf8273d3d98f08d30e79268f51d347 [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
Tomek Jaroszykd085e512020-11-09 13:58:02 +01009 * WAIT_FOR_HEALTHY Wait for cluster rebalance after a osd was removed
10 * CLUSTER_FLAGS Expected flags on the cluster during job run
11 * FAST_WIPE Clean only partition table insted of full wipe
12 * CLEAN_ORPHANS Clean ceph partition which are no longer part of the cluster
13 * OSD Coma separated list of OSDs to remove while keep the rest intact
14 * GENERATE_CRUSHMAP Generate new crush map. Excludes OSD
Jiri Broulik99887c82017-10-31 09:27:52 +010015 *
16 */
17
Ivan Berezovskiy2325dcb2019-11-05 17:42:57 +040018def common = new com.mirantis.mk.Common()
19def salt = new com.mirantis.mk.Salt()
20def ceph = new com.mirantis.mk.Ceph()
Jiri Broulik99887c82017-10-31 09:27:52 +010021def python = new com.mirantis.mk.Python()
Tomek Jaroszykd085e512020-11-09 13:58:02 +010022
Jiri Broulik99887c82017-10-31 09:27:52 +010023def pepperEnv = "pepperEnv"
24
Tomek Jaroszykd085e512020-11-09 13:58:02 +010025def osds = OSD.tokenize(',').toSet()
26def flags = CLUSTER_FLAGS.tokenize(',').toSet()
27def cleanOrphans = CLEAN_ORPHANS.toBoolean()
28def fullWipe = !FAST_WIPE.toBoolean()
29def safeRemove = WAIT_FOR_HEALTHY.toBoolean()
30
31def osdOnly = OSD.trim() as Boolean
32def generateCrushmap = osdOnly ? false : GENERATE_CRUSHMAP.toBoolean()
Mateusz Los1535aa22020-05-11 10:33:58 +020033
Jakub Josefa63f9862018-01-11 17:58:38 +010034timeout(time: 12, unit: 'HOURS') {
35 node("python") {
Jiri Broulik96c867a2017-11-07 16:14:10 +010036
Jakub Josefa63f9862018-01-11 17:58:38 +010037 // create connection to salt master
38 python.setupPepperVirtualenv(pepperEnv, SALT_MASTER_URL, SALT_MASTER_CREDENTIALS)
Jiri Broulik99887c82017-10-31 09:27:52 +010039
Tomek Jaroszykd085e512020-11-09 13:58:02 +010040 def target = salt.getMinions(pepperEnv, HOST)
41 if(target.isEmpty()) {
Mateusz Losb5663e62020-05-11 09:51:13 +020042 common.errorMsg("Host not found")
43 throw new InterruptedException()
44 }
Tomek Jaroszykd085e512020-11-09 13:58:02 +010045 else if(target.size() > 1) {
46 common.errorMsg("$HOST targeted more than one minion")
47 throw new InterruptedException()
Jakub Josefa63f9862018-01-11 17:58:38 +010048 }
49
Tomek Jaroszykd085e512020-11-09 13:58:02 +010050 salt.fullRefresh(pepperEnv, HOST)
Jakub Josefa63f9862018-01-11 17:58:38 +010051
Tomek Jaroszykd085e512020-11-09 13:58:02 +010052 stage('Set flags') {
53 ceph.setFlags(pepperEnv, flags)
Jiri Broulik99887c82017-10-31 09:27:52 +010054 }
55
Tomek Jaroszykd085e512020-11-09 13:58:02 +010056 try {
Jakub Josefa63f9862018-01-11 17:58:38 +010057 stage('Remove OSDs') {
Tomek Jaroszykd085e512020-11-09 13:58:02 +010058 if(salt.testTarget(pepperEnv, "$HOST and I@ceph:osd")) {
59 // get list of osd disks of the host
60 def cephGrain = ceph.getGrain(pepperEnv, HOST, 'ceph')
61 def cephDisks = cephGrain.get('ceph_disk',[:]).keySet()
62 if (cephGrain.isEmpty()) {
63 throw new Exception("Ceph salt grains cannot be found on $HOST")
64 }
65
Tomek Jaroszykd0ddb562021-02-17 15:25:06 +010066 // glob for OSD input or whole node is going to be removed
67 if(OSD == '*' || !osdOnly) {
Tomek Jaroszykd085e512020-11-09 13:58:02 +010068 osds = cephDisks
69 }
70
71 // discard all osds which aren't deployed on target HOST
72 osds = osds.intersect(cephDisks)
73
74 if(!osds.isEmpty()) {
75 common.infoMsg("The following osds will be removed: ${osds.join(', ')}")
76 }
77 if(osds != cephDisks) {
78 common.infoMsg("The following osds will be skiped: ${cephDisks.removeAll(osds).join(', ')}")
79 }
80
81 ceph.removeOsd(pepperEnv, HOST, osds, flags, safeRemove, fullWipe)
82
83 if(cleanOrphans) {
84 ceph.removeOrphans(pepperEnv, HOST, fullWipe)
85 }
86 }
87 else {
88 common.infoMsg('Stage skipped.')
Jakub Josefa63f9862018-01-11 17:58:38 +010089 }
90 }
91
Tomek Jaroszykd085e512020-11-09 13:58:02 +010092 stage('Remove keyring') {
93 // only non-osd nodes as keyrings for osds was removed already in previous step
94 if(salt.testTarget(pepperEnv, "$HOST and not I@ceph:osd")) {
95 ceph.deleteKeyrings(pepperEnv, HOST)
96 }
97 else {
98 common.infoMsg('Stage skipped.')
99 }
100 }
Jakub Josefa63f9862018-01-11 17:58:38 +0100101
Tomek Jaroszykd085e512020-11-09 13:58:02 +0100102 stage('Update monmap') {
103 if(salt.testTarget(pepperEnv, "$HOST and I@ceph:mon")) {
104 def hostname = ceph.getGrain(pepperEnv, HOST, 'host')
105 ceph.cmdRun(pepperEnv, 'ceph mon getmap -o monmap.backup')
106 ceph.cmdRun(pepperEnv, "ceph mon remove $hostname")
107 salt.cmdRun(pepperEnv, 'I@ceph:mon', "monmaptool /tmp/monmap --rm $hostname")
108 }
109 else {
110 common.infoMsg('Stage skipped.')
111 }
112 }
Mateusz Los1535aa22020-05-11 10:33:58 +0200113
Tomek Jaroszykd085e512020-11-09 13:58:02 +0100114 stage('Update Ceph configs/crushmap') {
115 //TODO: it won't remove removed mon from config
116 if(salt.testTarget(pepperEnv, "$HOST and I@ceph:mon")) {
117 salt.enforceState(pepperEnv, 'I@ceph:common', 'ceph.common', true)
118 }
119 else if (salt.testTarget(pepperEnv, "$HOST and I@ceph:osd") && salt.testTarget(pepperEnv, "I@ceph:setup:crush and not $HOST") && generateCrushmap) {
120 salt.enforceState(pepperEnv, 'I@ceph:setup:crush', 'ceph.setup.crush', true)
121 }
122 else {
123 common.infoMsg('Stage skipped.')
124 }
125 }
126
127 stage('Purge Ceph components') {
128 Set pkgs = ['ceph-base','ceph-common']
129 if(salt.testTarget(pepperEnv, "$HOST and I@ceph:osd")) {
130 pkgs.addAll(['ceph-osd','ceph-fuse','ceph-mds','python-cephfs','librados2','python-rados','python-rbd','python-rgw'])
131 }
132 //TODO: why removed pkgs on vm which will be remved as whole in next stage
133 if(salt.testTarget(pepperEnv, "$HOST and I@ceph:radosgw")) {
134 ceph.removeRgw(pepperEnv, HOST)
135 pkgs.addAll(['radosgw','libcephfs2','python-cephfs','python-rados','python-rbd','python-rgw'])
136 }
137 if(salt.testTarget(pepperEnv, "$HOST and I@ceph:mon")) {
138 pkgs.addAll(['ceph-mon','ceph-mgr','libcephfs2','python-cephfs','python-rbd','python-rgw'])
139 }
140
141 if(!osdOnly) {
142 salt.runSaltProcessStep(pepperEnv, HOST, 'pkg.purge', pkgs)
143 }
144 else {
145 common.infoMsg('Stage skipped.')
146 }
147 }
148
149 stage('Remove salt minion and destroy VM') {
150 if(!osdOnly) {
151 if(salt.testTarget(pepperEnv, "$HOST and I@ceph:osd")) {
152 ceph.removeSalt(pepperEnv, HOST)
Jakub Josefa63f9862018-01-11 17:58:38 +0100153 }
Mateusz Los1535aa22020-05-11 10:33:58 +0200154 else {
Tomek Jaroszykd085e512020-11-09 13:58:02 +0100155 ceph.removeVm(pepperEnv, HOST)
Mateusz Los1535aa22020-05-11 10:33:58 +0200156 }
157 }
Tomek Jaroszykd085e512020-11-09 13:58:02 +0100158 else {
159 common.infoMsg('Stage skipped.')
Mateusz Los1535aa22020-05-11 10:33:58 +0200160 }
Jiri Broulik3485b2c2017-11-28 15:06:12 +0100161 }
Jiri Broulik99887c82017-10-31 09:27:52 +0100162 }
Tomek Jaroszykd085e512020-11-09 13:58:02 +0100163 finally {
164 stage('Unset cluster flags') {
165 ceph.unsetFlags(pepperEnv, flags)
Jakub Josefa63f9862018-01-11 17:58:38 +0100166 }
Jiri Broulik99887c82017-10-31 09:27:52 +0100167 }
168 }
169}