blob: bb5f1e0b5961b5ab08ddd5f1e9033945daca5ab7 [file] [log] [blame]
vitalygusev22701372018-09-25 17:27:35 +04001/**
2 *
3 * Upgrade Stacklight packages and components
4 *
5 * Requred parameters:
6 * SALT_MASTER_URL URL of Salt master
7 * SALT_MASTER_CREDENTIALS Credentials to the Salt API
8 *
9 * STAGE_UPGRADE_SYSTEM_PART Set to True if upgrade of system part (telegraf, fluentd, prometheus-relay) is desired
10 * STAGE_UPGRADE_ES_KIBANA Set to True if Elasticsearch and Kibana upgrade is desired
11 * STAGE_UPGRADE_DOCKER_COMPONENTS Set to True if upgrade for components running in Docker Swarm is desired
12 *
13 */
14
vitalygusev4b331fa2018-12-04 19:03:47 +040015common = new com.mirantis.mk.Common()
16salt = new com.mirantis.mk.Salt()
17python = new com.mirantis.mk.Python()
18command = 'cmd.run'
19pepperEnv = "pepperEnv"
20errorOccured = false
Ivan Berezovskiyb5a74d42020-03-20 14:04:07 +040021def packageUpgradeMode = ''
22def forceUpgradeComonents = false
vitalygusev22701372018-09-25 17:27:35 +040023
Ivan Berezovskiyb5a74d42020-03-20 14:04:07 +040024def upgrade(master, target, service, pkg, state) {
vitalygusev4b331fa2018-12-04 19:03:47 +040025 stage("Upgrade ${service}") {
vitalygusev25872e12018-12-14 18:45:29 +040026 salt.runSaltProcessStep(master, "${target}", 'saltutil.refresh_pillar', [], null, true)
vitalygusev00826aa2018-12-24 13:44:47 +040027 salt.enforceState([saltId: master, target: "${target}", state: 'linux.system.repo', output: true, failOnError: true])
vitalygusev25872e12018-12-14 18:45:29 +040028 common.infoMsg("Upgrade ${service} package(s)")
vitalygusev22701372018-09-25 17:27:35 +040029 try {
Ivan Berezovskiyb5a74d42020-03-20 14:04:07 +040030 salt.runSaltProcessStep(master, "${target}", command, ["apt-get install -y -o Dpkg::Options::=\"--force-confold\" ${pkg}"], null, true)
vitalygusev22701372018-09-25 17:27:35 +040031 } catch (Exception er) {
32 errorOccured = true
Ivan Berezovskiyb5a74d42020-03-20 14:04:07 +040033 common.errorMsg("[ERROR] ${pkg} package(s) was not upgraded.")
vitalygusev25872e12018-12-14 18:45:29 +040034 throw er
vitalygusev22701372018-09-25 17:27:35 +040035 }
vitalygusev4b331fa2018-12-04 19:03:47 +040036 common.infoMsg("Run ${state} state on ${target} nodes")
vitalygusev22701372018-09-25 17:27:35 +040037 try {
vitalygusev00826aa2018-12-24 13:44:47 +040038 salt.enforceState([saltId: master, target: "${target}", state: ["${state}"], output: true, failOnError: true])
vitalygusev22701372018-09-25 17:27:35 +040039 } catch (Exception er) {
40 errorOccured = true
vitalygusev4b331fa2018-12-04 19:03:47 +040041 common.errorMsg("[ERROR] ${state} state was executed and failed. Please fix it manually.")
vitalygusev25872e12018-12-14 18:45:29 +040042 throw er
vitalygusev22701372018-09-25 17:27:35 +040043 }
vitalygusev25872e12018-12-14 18:45:29 +040044 common.infoMsg("Check ${service} service(s) status on the target nodes")
45 for (s in service.split(" ")){
46 salt.runSaltProcessStep(master, "${target}", "service.status", "${s}", null, true)
47 }
48 }
49}
50
51def verify_es_is_green(master) {
52 common.infoMsg('Verify that the Elasticsearch cluster status is green')
53 try {
Dmitry Kalashnik21df1472019-07-02 12:37:52 +040054 def retries_wait = 120
55 def retries = 60
Dmitry Kalashnik066740c2019-05-27 15:47:35 +040056
vitalygusev25872e12018-12-14 18:45:29 +040057 def elasticsearch_vip
Dmitry Kalashnik066740c2019-05-27 15:47:35 +040058 def pillar = salt.getReturnValues(salt.getPillar(master, "I@elasticsearch:client", 'elasticsearch:client:server:host'))
Dmitry Kalashnikaa4dcdc2019-05-27 16:43:04 +040059 if(pillar) {
Dmitry Kalashnik066740c2019-05-27 15:47:35 +040060 elasticsearch_vip = pillar
vitalygusev25872e12018-12-14 18:45:29 +040061 } else {
62 errorOccured = true
63 common.errorMsg('[ERROR] Elasticsearch VIP address could not be retrieved')
64 }
Dmitry Kalashnik066740c2019-05-27 15:47:35 +040065
66 pillar = salt.getReturnValues(salt.getPillar(master, "I@elasticsearch:client", 'elasticsearch:client:server:port'))
vitalygusev25872e12018-12-14 18:45:29 +040067 def elasticsearch_port
Dmitry Kalashnikaa4dcdc2019-05-27 16:43:04 +040068 if(pillar) {
Dmitry Kalashnik066740c2019-05-27 15:47:35 +040069 elasticsearch_port = pillar
vitalygusev25872e12018-12-14 18:45:29 +040070 } else {
71 errorOccured = true
72 common.errorMsg('[ERROR] Elasticsearch VIP port could not be retrieved')
73 }
Dmitry Kalashnik066740c2019-05-27 15:47:35 +040074
Dmitry Kalashnika59a89c2019-06-17 11:56:52 +040075 pillar = salt.getReturnValues(salt.getPillar(master, "I@elasticsearch:client", 'elasticsearch:client:server:scheme'))
Dmitry Kalashnikb5763f92019-05-23 10:11:42 +040076 def elasticsearch_scheme
Dmitry Kalashnikaa4dcdc2019-05-27 16:43:04 +040077 if(pillar) {
Dmitry Kalashnik066740c2019-05-27 15:47:35 +040078 elasticsearch_scheme = pillar
79 common.infoMsg("[INFO] Using elasticsearch scheme: ${elasticsearch_scheme}")
Dmitry Kalashnikb5763f92019-05-23 10:11:42 +040080 } else {
Dmitry Kalashnik066740c2019-05-27 15:47:35 +040081 common.infoMsg('[INFO] No pillar with Elasticsearch server scheme, using scheme: http')
Dmitry Kalashnikb5763f92019-05-23 10:11:42 +040082 elasticsearch_scheme = "http"
83 }
84
vitalygusev25872e12018-12-14 18:45:29 +040085 common.retry(retries,retries_wait) {
86 common.infoMsg('Waiting for Elasticsearch to become green..')
Dmitry Kalashnikb5763f92019-05-23 10:11:42 +040087 salt.cmdRun(master, "I@elasticsearch:client", "curl -sfk ${elasticsearch_scheme}://${elasticsearch_vip}:${elasticsearch_port}/_cat/health | awk '{print \$4}' | grep green")
vitalygusev25872e12018-12-14 18:45:29 +040088 }
89 } catch (Exception er) {
90 errorOccured = true
91 common.errorMsg("[ERROR] Elasticsearch cluster status is not \'green\'. Please fix it manually.")
92 throw er
vitalygusev22701372018-09-25 17:27:35 +040093 }
vitalygusev22701372018-09-25 17:27:35 +040094}
95
96def upgrade_es_kibana(master) {
vitalygusev25872e12018-12-14 18:45:29 +040097 def elasticsearch_version
98 def es_pillar = salt.getPillar(master, "I@elasticsearch:client", '_param:elasticsearch_version')
99 if(!es_pillar['return'].isEmpty()) {
100 elasticsearch_version = es_pillar['return'][0].values()[0]
101 }
vitalygusev4b331fa2018-12-04 19:03:47 +0400102 stage('Upgrade elasticsearch') {
vitalygusev25872e12018-12-14 18:45:29 +0400103 if (elasticsearch_version == '5') {
104 try {
105 common.infoMsg('Upgrade the Elasticsearch package')
106 salt.runSaltProcessStep(master, 'I@elasticsearch:server', command, ["systemctl stop elasticsearch"], null, true)
107 salt.runSaltProcessStep(master, 'I@elasticsearch:server', command, ["apt-get --only-upgrade install elasticsearch"], null, true)
108 salt.runSaltProcessStep(master, 'I@elasticsearch:server', command, ["systemctl daemon-reload"], null, true)
109 salt.runSaltProcessStep(master, 'I@elasticsearch:server', command, ["systemctl start elasticsearch"], null, true)
110 salt.runSaltProcessStep(master, '*', 'saltutil.sync_all', [], null, true)
111 verify_es_is_green(master)
112 } catch (Exception er) {
vitalygusev22701372018-09-25 17:27:35 +0400113 errorOccured = true
vitalygusev25872e12018-12-14 18:45:29 +0400114 common.errorMsg("[ERROR] Elasticsearch upgrade failed. Please fix it manually.")
115 throw er
vitalygusev22701372018-09-25 17:27:35 +0400116 }
vitalygusev25872e12018-12-14 18:45:29 +0400117 } else {
118 try {
119 salt.runSaltProcessStep(master, "*", 'saltutil.refresh_pillar', [], null, true)
vitalygusev00826aa2018-12-24 13:44:47 +0400120 salt.enforceState([saltId: master, target: "I@elasticsearch:server", state: 'linux.system.repo', output: true, failOnError: true])
vitalygusev25872e12018-12-14 18:45:29 +0400121 salt.runSaltProcessStep(master, 'I@elasticsearch:client', command, ["apt-get install -y -o Dpkg::Options::=\"--force-confold\" python-elasticsearch"], null, true)
vitalygusev00826aa2018-12-24 13:44:47 +0400122 salt.enforceState([saltId: master, target: "I@elasticsearch:server", state: 'salt.minion', output: true, failOnError: true])
vitalygusev25872e12018-12-14 18:45:29 +0400123 salt.runSaltProcessStep(master, 'I@elasticsearch:server', command, ["systemctl stop elasticsearch"], null, true)
124 salt.runSaltProcessStep(master, 'I@elasticsearch:server', command, ["export ES_PATH_CONF=/etc/elasticsearch; apt-get install -y -o Dpkg::Options::=\"--force-confold\" elasticsearch"], null, true)
vitalygusev00826aa2018-12-24 13:44:47 +0400125 salt.enforceState([saltId: master, target: "I@elasticsearch:server", state: 'elasticsearch.server', output: true, failOnError: true])
vitalygusev25872e12018-12-14 18:45:29 +0400126 verify_es_is_green(master)
vitalygusev00826aa2018-12-24 13:44:47 +0400127 salt.enforceState([saltId: master, target: "I@elasticsearch:client", state: 'elasticsearch.client.update_index_templates', output: true, failOnError: true])
128 salt.enforceState([saltId: master, target: "I@elasticsearch:client", state: 'elasticsearch.client', output: true, failOnError: true])
vitalygusev25872e12018-12-14 18:45:29 +0400129 } catch (Exception er) {
vitalygusev22701372018-09-25 17:27:35 +0400130 errorOccured = true
vitalygusev25872e12018-12-14 18:45:29 +0400131 common.errorMsg("[ERROR] Elasticsearch upgrade failed. Please fix it manually.")
132 throw er
vitalygusev22701372018-09-25 17:27:35 +0400133 }
vitalygusev22701372018-09-25 17:27:35 +0400134 }
135 }
vitalygusev4b331fa2018-12-04 19:03:47 +0400136 stage('Upgrade kibana') {
vitalygusev25872e12018-12-14 18:45:29 +0400137 def kibana_version
138 def kibana_pillar = salt.getPillar(master, "I@kibana:client", '_param:kibana_version')
139 if(!kibana_pillar['return'].isEmpty()) {
140 kibana_version = kibana_pillar['return'][0].values()[0]
141 }
142 if (kibana_version == '5') {
143 try {
144 common.infoMsg('Upgrade the Kibana package')
145 salt.runSaltProcessStep(master, 'I@kibana:server', command, ["systemctl stop kibana"], null, true)
146 salt.runSaltProcessStep(master, 'I@kibana:server', command, ["apt-get --only-upgrade install kibana"], null, true)
147 salt.runSaltProcessStep(master, 'I@kibana:server', command, ["systemctl start kibana"], null, true)
148 } catch (Exception er) {
149 errorOccured = true
150 common.errorMsg("[ERROR] Kibana upgrade failed. Please fix it manually.")
151 throw er
152 }
153 } else {
154 try {
155 salt.runSaltProcessStep(master, 'I@kibana:server', command, ["systemctl stop kibana"], null, true)
vitalygusev00826aa2018-12-24 13:44:47 +0400156 salt.enforceStateWithExclude([saltId: master, target: "I@kibana:server", state: "kibana.server", excludedStates: "[{'id': 'kibana_service'}]"])
vitalygusev25872e12018-12-14 18:45:29 +0400157 salt.runSaltProcessStep(master, 'I@kibana:server', command, ["apt-get install -y -o Dpkg::Options::=\"--force-confold\" kibana"], null, true)
vitalygusev00826aa2018-12-24 13:44:47 +0400158 salt.enforceState([saltId: master, target: "I@kibana:server", state: 'kibana.server', output: true, failOnError: true])
159 salt.enforceState([saltId: master, target: "I@kibana:client", state: 'kibana.client', output: true, failOnError: true])
vitalygusev25872e12018-12-14 18:45:29 +0400160 } catch (Exception er) {
161 errorOccured = true
162 common.errorMsg("[ERROR] Kibana upgrade failed. Please fix it manually.")
163 throw er
164 }
vitalygusev22701372018-09-25 17:27:35 +0400165 }
vitalygusev22701372018-09-25 17:27:35 +0400166
vitalygusev4b331fa2018-12-04 19:03:47 +0400167 common.infoMsg("Check kibana status on the target nodes")
168 salt.runSaltProcessStep(master, "I@kibana:server", "service.status", ["kibana"], null, true)
vitalygusev22701372018-09-25 17:27:35 +0400169 }
170}
171timeout(time: 12, unit: 'HOURS') {
172 node("python") {
173
Ivan Berezovskiyb5a74d42020-03-20 14:04:07 +0400174 if ((env.getProperty('OS_DIST_UPGRADE') ?: false).toBoolean()) {
175 packageUpgradeMode = 'dist-upgrade'
176 forceUpgradeComonents = true
177 } else if ((env.getProperty('OS_UPGRADE') ?: false).toBoolean()) {
178 packageUpgradeMode = 'upgrade'
179 forceUpgradeComonents = true
180 }
181
182 if(forceUpgradeComonents) {
183 common.infoMsg('Forcing to upgrade all Stacklight components because OS_DIST_UPGRADE or OS_UPGRADE is selected')
184 }
185
vitalygusev22701372018-09-25 17:27:35 +0400186 stage('Setup virtualenv for Pepper') {
187 python.setupPepperVirtualenv(pepperEnv, SALT_MASTER_URL, SALT_MASTER_CREDENTIALS)
188 }
189
vitalygusev00826aa2018-12-24 13:44:47 +0400190 stage('Update grains and mine') {
191 salt.enforceState([saltId: pepperEnv, target: '*', state: 'salt.minion.grains'])
192 salt.runSaltProcessStep(pepperEnv, '*', 'saltutil.refresh_modules')
193 salt.runSaltProcessStep(pepperEnv, '*', 'mine.update')
194 sleep(30)
195 }
vitalygusev25872e12018-12-14 18:45:29 +0400196
vitalygusev00826aa2018-12-24 13:44:47 +0400197 if (salt.testTarget(pepperEnv, "I@ceph:mon")) {
198 stage('Enable Ceph prometheus plugin') {
199 salt.enforceState([saltId: pepperEnv, target: 'I@ceph:mon', state: "ceph.mgr", output: true, failOnError: true])
200 }
201 }
vitalygusev25872e12018-12-14 18:45:29 +0400202
Ivan Berezovskiyb5a74d42020-03-20 14:04:07 +0400203 if (forceUpgradeComonents || (STAGE_UPGRADE_DOCKER_COMPONENTS.toBoolean() == true && !errorOccured)) {
vitalygusev4b331fa2018-12-04 19:03:47 +0400204 stage('Upgrade docker components') {
vitalygusev22701372018-09-25 17:27:35 +0400205 try {
vitalygusev4b331fa2018-12-04 19:03:47 +0400206 common.infoMsg('Disable and remove the previous versions of monitoring services')
207 salt.runSaltProcessStep(pepperEnv, 'I@docker:swarm:role:master and I@prometheus:server', command, ["docker stack rm monitoring"], null, true)
208 common.infoMsg('Rebuild the Prometheus configuration')
vitalygusev00826aa2018-12-24 13:44:47 +0400209 salt.enforceState([saltId: pepperEnv, target: 'I@docker:swarm and I@prometheus:server', state: 'prometheus'])
vitalygusev4b331fa2018-12-04 19:03:47 +0400210 common.infoMsg('Disable and remove the previous version of Grafana')
211 salt.runSaltProcessStep(pepperEnv, 'I@docker:swarm:role:master and I@prometheus:server', command, ["docker stack rm dashboard"], null, true)
212 common.infoMsg('Start the monitoring services')
vitalygusev00826aa2018-12-24 13:44:47 +0400213 salt.enforceState([saltId: pepperEnv, target: 'I@docker:swarm:role:master and I@prometheus:server', state: 'docker'])
vitalygusev22701372018-09-25 17:27:35 +0400214 salt.runSaltProcessStep(pepperEnv, '*', 'saltutil.sync_all', [], null, true)
Dmitry Kalashnikbc263f32019-06-21 16:02:27 +0400215 common.infoMsg("Waiting grafana service to start")
216 sleep(120)
217
vitalygusev4b331fa2018-12-04 19:03:47 +0400218 common.infoMsg('Refresh the Grafana dashboards')
Dmitry Kalashnikbc263f32019-06-21 16:02:27 +0400219 salt.enforceState([saltId: pepperEnv, target: 'I@grafana:client', state: 'grafana.client', retries: 10, retries_wait: 30])
vitalygusev22701372018-09-25 17:27:35 +0400220 } catch (Exception er) {
221 errorOccured = true
vitalygusev4b331fa2018-12-04 19:03:47 +0400222 common.errorMsg("[ERROR] Upgrade of docker components failed. Please fix it manually.")
vitalygusev25872e12018-12-14 18:45:29 +0400223 throw er
vitalygusev22701372018-09-25 17:27:35 +0400224 }
225 }
226 }
Michal Kobuse764e172020-03-05 13:29:34 +0100227
Ivan Berezovskiyb5a74d42020-03-20 14:04:07 +0400228 if (forceUpgradeComonents || (STAGE_UPGRADE_SYSTEM_PART.toBoolean() == true && !errorOccured)) {
Michal Kobuse764e172020-03-05 13:29:34 +0100229 upgrade(pepperEnv, "I@telegraf:agent or I@telegraf:remote_agent", "telegraf", "telegraf", "telegraf")
230 upgrade(pepperEnv, "I@fluentd:agent", "td-agent", "td-agent td-agent-additional-plugins", "fluentd")
231 if (salt.testTarget(pepperEnv, "I@prometheus:relay")) {
232 upgrade(pepperEnv, "I@prometheus:relay", "prometheus prometheus-relay", "prometheus-bin prometheus-relay", "prometheus")
233 salt.runSaltProcessStep(pepperEnv, "I@prometheus:relay", "service.restart", "prometheus", null, true)
234 }
235 if (salt.testTarget(pepperEnv, "I@prometheus:exporters:libvirt")) {
236 upgrade(pepperEnv, "I@prometheus:exporters:libvirt", "libvirt-exporter", "libvirt-exporter", "prometheus")
237 }
238 if (salt.testTarget(pepperEnv, "I@prometheus:exporters:jmx")) {
239 upgrade(pepperEnv, "I@prometheus:exporters:jmx", "jmx-exporter", "jmx-exporter", "prometheus")
240 }
241 }
242
Ivan Berezovskiyb5a74d42020-03-20 14:04:07 +0400243 if (forceUpgradeComonents || (STAGE_UPGRADE_ES_KIBANA.toBoolean() == true && !errorOccured)) {
Michal Kobuse764e172020-03-05 13:29:34 +0100244 upgrade_es_kibana(pepperEnv)
245 }
Ivan Berezovskiyb5a74d42020-03-20 14:04:07 +0400246
247 stage('Upgrade OS') {
248 if (packageUpgradeMode) {
249 def stacklightNodes = salt.getMinions(pepperEnv, 'I@elasticsearch:server or I@prometheus:server')
250 def stacklightNodesWithDocker = salt.getMinions(pepperEnv, 'I@docker:swarm and I@prometheus:server')
251 def elasticSearchNodes = salt.getMinions(pepperEnv, 'I@elasticsearch:server')
252 def debian = new com.mirantis.mk.Debian()
253 for (stacklightNode in stacklightNodes) {
254 salt.runSaltProcessStep(pepperEnv, stacklightNode, 'saltutil.refresh_pillar', [], null, true)
255 salt.enforceState([saltId: pepperEnv, target: stacklightNode, state: 'linux.system.repo', output: true, failOnError: true])
256 debian.osUpgradeNode(pepperEnv, stacklightNode, packageUpgradeMode, false, 60)
257 salt.checkTargetMinionsReady(['saltId': pepperEnv, 'target': stacklightNode, wait: 60, timeout: 10])
258 if (packageUpgradeMode == 'dist-upgrade' && stacklightNode in stacklightNodesWithDocker) {
259 common.infoMsg('Perform: Checking if Docker containers are up after reboot')
260 try {
261 common.retry(10, 30) {
262 salt.cmdRun(pepperEnv, stacklightNode, "! docker service ls | tail -n +2 | grep -v -E '\\s([0-9])/\\1\\s'")
263 }
264 }
265 catch (Exception ex) {
266 error("Docker containers for Stacklight services are having troubles with starting.")
267 }
268 }
269 if(stacklightNode in elasticSearchNodes) {
270 verify_es_is_green(pepperEnv)
271 }
272 }
273 } else {
274 common.infoMsg('Upgrade OS skipped...')
275 }
276 }
277
Dmitry Kalashnik847ebc02019-10-29 16:35:59 +0400278 stage('Post upgrade steps') {
279 common.infoMsg('Apply workaround for PROD-33878')
280 salt.runSaltProcessStep(pepperEnv, "I@fluentd:agent and I@rabbitmq:server", "service.restart", "td-agent", null, true)
281 }
vitalygusev22701372018-09-25 17:27:35 +0400282 }
283}