Jiri Broulik | 2c00f4c | 2017-10-26 13:23:11 +0200 | [diff] [blame] | 1 | /** |
| 2 | * |
| 3 | * Add Ceph node to 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 added |
Tomek Jaroszyk | 08ad67e | 2020-11-09 13:58:02 +0100 | [diff] [blame] | 9 | * CLUSTER_FLAGS Expected flags on the cluster during job run |
| 10 | * OSD_ONLY Add only new osds while keep rest intact |
| 11 | * USE_UPMAP Use upmap for rebalance the data after node was added |
Jiri Broulik | 2c00f4c | 2017-10-26 13:23:11 +0200 | [diff] [blame] | 12 | * |
| 13 | */ |
| 14 | |
Tomek Jaroszyk | 08ad67e | 2020-11-09 13:58:02 +0100 | [diff] [blame] | 15 | def common = new com.mirantis.mk.Common() |
| 16 | def salt = new com.mirantis.mk.Salt() |
| 17 | def ceph = new com.mirantis.mk.Ceph() |
| 18 | def orchestrate = new com.mirantis.mk.Orchestrate() |
Jiri Broulik | 2c00f4c | 2017-10-26 13:23:11 +0200 | [diff] [blame] | 19 | def python = new com.mirantis.mk.Python() |
| 20 | |
| 21 | def pepperEnv = "pepperEnv" |
Tomek Jaroszyk | 08ad67e | 2020-11-09 13:58:02 +0100 | [diff] [blame] | 22 | def flags = CLUSTER_FLAGS.tokenize(',').toSet() |
| 23 | def osdOnly = OSD_ONLY.toBoolean() |
| 24 | def useUpmap = USE_UPMAP.toBoolean() |
| 25 | |
Jakub Josef | a63f986 | 2018-01-11 17:58:38 +0100 | [diff] [blame] | 26 | timeout(time: 12, unit: 'HOURS') { |
| 27 | node("python") { |
Jiri Broulik | 2c00f4c | 2017-10-26 13:23:11 +0200 | [diff] [blame] | 28 | |
Jakub Josef | a63f986 | 2018-01-11 17:58:38 +0100 | [diff] [blame] | 29 | // create connection to salt master |
| 30 | python.setupPepperVirtualenv(pepperEnv, SALT_MASTER_URL, SALT_MASTER_CREDENTIALS) |
Jiri Broulik | 2c00f4c | 2017-10-26 13:23:11 +0200 | [diff] [blame] | 31 | |
Tomek Jaroszyk | 08ad67e | 2020-11-09 13:58:02 +0100 | [diff] [blame] | 32 | def target = salt.getMinions(pepperEnv, HOST) |
| 33 | if(target.isEmpty()) { |
Mateusz Los | 13d0520 | 2020-05-11 09:51:13 +0200 | [diff] [blame] | 34 | common.errorMsg("Host not found") |
| 35 | throw new InterruptedException() |
| 36 | } |
Tomek Jaroszyk | 08ad67e | 2020-11-09 13:58:02 +0100 | [diff] [blame] | 37 | else if(target.size() > 1) { |
| 38 | common.warningMsg("$HOST targeted more than one minion") |
| 39 | } |
Mateusz Los | 13d0520 | 2020-05-11 09:51:13 +0200 | [diff] [blame] | 40 | |
Tomek Jaroszyk | 08ad67e | 2020-11-09 13:58:02 +0100 | [diff] [blame] | 41 | if(useUpmap) { |
| 42 | stage('enable upmap balancer') { |
| 43 | def features = ceph.cmdRun(pepperEnv, "ceph features --format json", false) |
| 44 | features = common.parseJSON(features) |
| 45 | for(group in features['client']) { |
| 46 | if(group instanceof java.util.HashMap$Node) { // Luminous |
| 47 | if(group.getValue()['release'] != 'luminous') { |
| 48 | throw new Exception("Some of installed clients does not support upmap. Update all clients to luminous or newer before using upmap") |
| 49 | } |
| 50 | } |
| 51 | else if(group['release'] != 'luminous') { // Nautilus |
| 52 | throw new Exception("Some of installed clients does not support upmap. Update all clients to luminous or newer before using upmap") |
| 53 | } |
| 54 | } |
| 55 | ceph.cmdRun(pepperEnv, 'ceph osd set-require-min-compat-client luminous') |
| 56 | ceph.cmdRun(pepperEnv, 'ceph balancer on') |
| 57 | ceph.cmdRun(pepperEnv, 'ceph balancer mode upmap') |
| 58 | } |
| 59 | } |
Jakub Josef | a63f986 | 2018-01-11 17:58:38 +0100 | [diff] [blame] | 60 | |
Tomek Jaroszyk | 08ad67e | 2020-11-09 13:58:02 +0100 | [diff] [blame] | 61 | salt.fullRefresh(pepperEnv, HOST) |
| 62 | |
| 63 | stage("set flags") { |
| 64 | if(useUpmap) { |
| 65 | flags.add('norebalance') |
| 66 | } |
| 67 | ceph.setFlags(pepperEnv, flags) |
| 68 | } |
| 69 | |
| 70 | try { |
Jakub Josef | a63f986 | 2018-01-11 17:58:38 +0100 | [diff] [blame] | 71 | stage('Launch VMs') { |
Tomek Jaroszyk | 08ad67e | 2020-11-09 13:58:02 +0100 | [diff] [blame] | 72 | if(salt.testTarget(pepperEnv, "$HOST and not I@ceph:osd")) { |
| 73 | // launch VMs |
Tomek Jaroszyk | 224c799 | 2021-02-08 14:29:28 +0100 | [diff] [blame] | 74 | salt.enforceState([saltId: pepperEnv, target: "I@salt:control", state: 'salt.control']) |
Jakub Josef | a63f986 | 2018-01-11 17:58:38 +0100 | [diff] [blame] | 75 | |
Tomek Jaroszyk | 08ad67e | 2020-11-09 13:58:02 +0100 | [diff] [blame] | 76 | // wait till the HOST appears in salt-key on salt-master |
| 77 | salt.minionPresent(pepperEnv, 'I@salt:master', HOST) |
| 78 | } |
| 79 | else { |
| 80 | common.infoMsg("No VM require for a osd node.") |
Jakub Josef | a63f986 | 2018-01-11 17:58:38 +0100 | [diff] [blame] | 81 | } |
| 82 | } |
Tomek Jaroszyk | 08ad67e | 2020-11-09 13:58:02 +0100 | [diff] [blame] | 83 | |
| 84 | stage('Install infra') { |
| 85 | if(!osdOnly) { |
| 86 | // run basic states |
| 87 | orchestrate.installFoundationInfraOnTarget(pepperEnv, HOST) |
| 88 | } |
| 89 | else { |
| 90 | common.infoMsg('Stage skipped due to OSD_ONLY.') |
| 91 | } |
| 92 | } |
| 93 | |
| 94 | stage('Install ceph components') { |
| 95 | if(salt.testTarget(pepperEnv, "$HOST and I@ceph:mon")) { |
| 96 | ceph.installMon(pepperEnv, HOST) |
| 97 | } |
| 98 | if(salt.testTarget(pepperEnv, "$HOST and I@ceph:radosgw")) { |
| 99 | ceph.installRgw(pepperEnv, HOST) |
| 100 | } |
| 101 | if(salt.testTarget(pepperEnv, "$HOST and I@ceph:osd")) { |
| 102 | ceph.installOsd(pepperEnv, HOST, !osdOnly) //skip setup while osdOnly |
| 103 | } |
| 104 | else if(osdOnly) { |
| 105 | common.infoMsg('Stage skipped due to OSD_ONLY.') |
| 106 | } |
| 107 | } |
| 108 | |
| 109 | stage("Update/Install monitoring and hosts files") { |
| 110 | if(!osdOnly) { |
| 111 | ceph.updateMonitoring(pepperEnv, HOST) |
| 112 | salt.enforceState([saltId: pepperEnv, target: "I@ceph:common", state: 'linux.network.host']) |
| 113 | } |
| 114 | else { |
| 115 | common.infoMsg('Stage skipped due to OSD_ONLY.') |
| 116 | } |
| 117 | } |
| 118 | |
| 119 | if(useUpmap) { |
| 120 | stage("update mappings") { |
Tomek Jaroszyk | 08ad67e | 2020-11-09 13:58:02 +0100 | [diff] [blame] | 121 | def pgmap |
| 122 | for (int x = 1; x <= 3; x++) { |
| 123 | pgmap = ceph.cmdRun(pepperEnv, 'ceph pg ls remapped --format=json', false) |
| 124 | if (pgmap.trim()) { |
| 125 | pgmap = "{\"pgs\":$pgmap}" // common.parseJSON() can't parse a list of maps |
| 126 | pgmap = common.parseJSON(pgmap)['pgs'] |
Tomek Jaroszyk | 4c13ce7 | 2022-02-01 15:10:40 +0100 | [diff] [blame] | 127 | if (pgmap instanceof java.util.Map && pgmap.get('pg_ready', false)) { |
| 128 | continue |
Tomek Jaroszyk | 08ad67e | 2020-11-09 13:58:02 +0100 | [diff] [blame] | 129 | } |
Tomek Jaroszyk | 4c13ce7 | 2022-02-01 15:10:40 +0100 | [diff] [blame] | 130 | def mapping = [] |
| 131 | ceph.generateMapping(pgmap, mapping) |
| 132 | for(map in mapping) { |
| 133 | ceph.cmdRun(pepperEnv, map) |
| 134 | } |
| 135 | sleep(30) |
Tomek Jaroszyk | 08ad67e | 2020-11-09 13:58:02 +0100 | [diff] [blame] | 136 | } |
| 137 | } |
| 138 | } |
| 139 | |
| 140 | stage('Unset norebalance') { |
| 141 | ceph.unsetFlags(pepperEnv, 'norebalance') |
| 142 | flags.removeElement('norebalance') |
| 143 | } |
| 144 | } |
| 145 | stage('Wait for healthy cluster status') { |
| 146 | ceph.waitForHealthy(pepperEnv, flags) |
Jakub Josef | a63f986 | 2018-01-11 17:58:38 +0100 | [diff] [blame] | 147 | } |
Jiri Broulik | 2c00f4c | 2017-10-26 13:23:11 +0200 | [diff] [blame] | 148 | } |
Tomek Jaroszyk | 08ad67e | 2020-11-09 13:58:02 +0100 | [diff] [blame] | 149 | finally { |
| 150 | stage('Unset cluster flags') { |
| 151 | ceph.unsetFlags(pepperEnv, flags) |
Ivan Berezovskiy | 19c685a | 2019-11-05 17:42:57 +0400 | [diff] [blame] | 152 | } |
Ildar Svetlov | 9e9aa95 | 2018-04-13 23:13:07 +0400 | [diff] [blame] | 153 | } |
Jiri Broulik | 2c00f4c | 2017-10-26 13:23:11 +0200 | [diff] [blame] | 154 | } |
| 155 | } |