blob: 3d5802f74ff3547cd3f0588e5595af24de9dc327 [file] [log] [blame]
Martin Polreichf7a1bb02018-12-05 11:12:23 +01001/**
2 * Verify and restore Galera cluster
3 *
4 * Expected parameters:
5 * SALT_MASTER_CREDENTIALS Credentials to the Salt API.
6 * SALT_MASTER_URL Full Salt API address [http://10.10.10.1:8000].
Sergey6579de62019-01-15 17:27:59 +04007 * ASK_CONFIRMATION Ask confirmation for restore
Martin Polreich721b7252019-01-21 14:42:48 +01008 * CHECK_TIME_SYNC Set to true to check time synchronization accross selected nodes.
Martin Polreichf7889b52019-02-01 14:46:10 +01009 * VERIFICATION_RETRIES Number of restries to verify the restoration.
Martin Polreichddfdb612019-03-21 15:12:15 +010010 * RESTORE_TYPE Sets restoration method
Martin Polreichf7a1bb02018-12-05 11:12:23 +010011 *
12**/
13
14def common = new com.mirantis.mk.Common()
15def salt = new com.mirantis.mk.Salt()
Martin Polreich208c4872019-02-15 10:09:10 +010016def galera = new com.mirantis.mk.Galera()
Martin Polreichf7a1bb02018-12-05 11:12:23 +010017def python = new com.mirantis.mk.Python()
Martin Polreichf7a1bb02018-12-05 11:12:23 +010018def pepperEnv = "pepperEnv"
19def resultCode = 99
Martin Polreichddfdb612019-03-21 15:12:15 +010020def restoreType = env.RESTORE_TYPE
21def runRestoreDb = false
22def runBackupDb = false
Martin Polreichf7a1bb02018-12-05 11:12:23 +010023
Sergey6579de62019-01-15 17:27:59 +040024askConfirmation = (env.getProperty('ASK_CONFIRMATION') ?: true).toBoolean()
Martin Polreich721b7252019-01-21 14:42:48 +010025checkTimeSync = (env.getProperty('CHECK_TIME_SYNC') ?: true).toBoolean()
Martin Polreich49f16c02019-02-04 13:14:01 +010026if (common.validInputParam('VERIFICATION_RETRIES') && VERIFICATION_RETRIES.isInteger()) {
Martin Polreichf7889b52019-02-01 14:46:10 +010027 verificationRetries = VERIFICATION_RETRIES.toInteger()
28} else {
29 verificationRetries = 5
30}
Martin Polreichddfdb612019-03-21 15:12:15 +010031if (restoreType.equals("BACKUP_AND_RESTORE") || restoreType.equals("ONLY_RESTORE")) {
32 runRestoreDb = true
33}
34if (restoreType.equals("BACKUP_AND_RESTORE")) {
35 runBackupDb = true
36}
Sergey6579de62019-01-15 17:27:59 +040037
Martin Polreichf7a1bb02018-12-05 11:12:23 +010038timeout(time: 12, unit: 'HOURS') {
39 node() {
40 stage('Setup virtualenv for Pepper') {
41 python.setupPepperVirtualenv(pepperEnv, SALT_MASTER_URL, SALT_MASTER_CREDENTIALS)
42 }
Martin Polreichddfdb612019-03-21 15:12:15 +010043 stage('Verify status') {
Ivan Berezovskiy844da962019-07-24 15:30:54 +040044 def sysstatTargets = 'I@xtrabackup:client or I@xtrabackup:server'
45 def sysstatTargetsNodes = salt.getMinions(pepperEnv, sysstatTargets)
46 try {
47 if (!salt.isPackageInstalled(['saltId': pepperEnv, 'target': sysstatTargets, 'packageName': 'sysstat', 'output': false])) {
48 if (askConfirmation) {
49 input message: "Do you want to install 'sysstat' package on targeted nodes: ${sysstatTargetsNodes}? Click to confirm"
50 }
51 salt.runSaltProcessStep(pepperEnv, sysstatTargets, 'pkg.install', ['sysstat'])
52 }
53 } catch (Exception e) {
54 common.errorMsg("Unable to determine status of sysstat package on target nodes: ${sysstatTargetsNodes}.")
55 if (askConfirmation) {
56 input message: "Do you want to continue? Click to confirm"
57 }
58 }
Martin Polreich208c4872019-02-15 10:09:10 +010059 resultCode = galera.verifyGaleraStatus(pepperEnv, false, checkTimeSync)
Martin Polreichf7a1bb02018-12-05 11:12:23 +010060 if (resultCode == 128) {
61 common.errorMsg("Unable to connect to Galera Master. Trying slaves...")
Martin Polreich208c4872019-02-15 10:09:10 +010062 resultCode = galera.verifyGaleraStatus(pepperEnv, true, checkTimeSync)
Martin Polreichf7a1bb02018-12-05 11:12:23 +010063 if (resultCode == 129) {
Ivan Berezovskiy64824112019-07-26 15:55:24 +040064 common.errorMsg("Unable to obtain Galera slave minions list. Without fixing this issue, pipeline cannot continue in verification, backup and restoration.")
Martin Polreichf7a1bb02018-12-05 11:12:23 +010065 currentBuild.result = "FAILURE"
Martin Polreichf7889b52019-02-01 14:46:10 +010066 return
Martin Polreichf7a1bb02018-12-05 11:12:23 +010067 } else if (resultCode == 130) {
Martin Polreich0f3b85d2019-04-02 14:22:11 +020068 common.errorMsg("Neither master or slaves are reachable. Without fixing this issue, pipeline cannot continue in verification, backup and restoration.")
Martin Polreichf7a1bb02018-12-05 11:12:23 +010069 currentBuild.result = "FAILURE"
Martin Polreichf7889b52019-02-01 14:46:10 +010070 return
Martin Polreichf7a1bb02018-12-05 11:12:23 +010071 }
72 }
Martin Polreich721b7252019-01-21 14:42:48 +010073 if (resultCode == 131) {
Martin Polreich0f3b85d2019-04-02 14:22:11 +020074 common.errorMsg("Time desynced - Please fix this issue and rerun the pipeline.")
Martin Polreich721b7252019-01-21 14:42:48 +010075 currentBuild.result = "FAILURE"
Martin Polreich0f3b85d2019-04-02 14:22:11 +020076 return
77 }
78 if (resultCode == 140 || resultCode == 141) {
79 common.errorMsg("Disk utilization check failed - Please fix this issue and rerun the pipeline.")
80 currentBuild.result = "FAILURE"
81 return
Martin Polreich721b7252019-01-21 14:42:48 +010082 }
Martin Polreichf7a1bb02018-12-05 11:12:23 +010083 if (resultCode == 1) {
Ivan Berezovskiy64824112019-07-26 15:55:24 +040084 if (askConfirmation) {
85 input message: "There was a problem with parsing the status output or with determining it. Do you want to run a restore?"
Sergey6579de62019-01-15 17:27:59 +040086 } else {
87 common.warningMsg("There was a problem with parsing the status output or with determining it. Try to restore.")
88 }
Martin Polreichf7a1bb02018-12-05 11:12:23 +010089 } else if (resultCode > 1) {
Ivan Berezovskiy64824112019-07-26 15:55:24 +040090 if (askConfirmation) {
91 input message: "There's something wrong with the cluster, do you want to continue with backup and/or restore?"
Sergey6579de62019-01-15 17:27:59 +040092 } else {
Martin Polreich0f3b85d2019-04-02 14:22:11 +020093 common.warningMsg("There's something wrong with the cluster, try to backup and/or restore.")
Sergey6579de62019-01-15 17:27:59 +040094 }
Martin Polreichf7a1bb02018-12-05 11:12:23 +010095 } else {
Ivan Berezovskiy64824112019-07-26 15:55:24 +040096 if (askConfirmation) {
97 input message: "There seems to be everything alright with the cluster, do you still want to continue with backup and/or restore?"
Sergey6579de62019-01-15 17:27:59 +040098 } else {
Ivan Berezovskiy64824112019-07-26 15:55:24 +040099 common.warningMsg("There seems to be everything alright with the cluster, no backup and no restoration will be done.")
100 currentBuild.result = "SUCCESS"
101 return
Sergey6579de62019-01-15 17:27:59 +0400102 }
Martin Polreichf7a1bb02018-12-05 11:12:23 +0100103 }
Martin Polreich0f3b85d2019-04-02 14:22:11 +0200104 }
105 if (runBackupDb) {
Ivan Berezovskiy64824112019-07-26 15:55:24 +0400106 if (askConfirmation) {
107 input message: "Are you sure you want to run a backup? Click to confirm"
108 }
Martin Polreich0f3b85d2019-04-02 14:22:11 +0200109 stage('Backup') {
Ivan Berezovskiy64824112019-07-26 15:55:24 +0400110 deployBuild = build(job: 'galera_backup_database', parameters: [
111 [$class: 'StringParameterValue', name: 'SALT_MASTER_URL', value: SALT_MASTER_URL],
112 [$class: 'StringParameterValue', name: 'SALT_MASTER_CREDENTIALS', value: SALT_MASTER_CREDENTIALS],
113 [$class: 'StringParameterValue', name: 'OVERRIDE_BACKUP_NODE', value: "none"],
114 ]
Martin Polreich0f3b85d2019-04-02 14:22:11 +0200115 )
116 }
117 }
Ivan Berezovskiy64824112019-07-26 15:55:24 +0400118 if (runRestoreDb) {
119 stage('Restore') {
120 if (askConfirmation) {
121 input message: "Are you sure you want to run a restore? Click to confirm"
Sergey6579de62019-01-15 17:27:59 +0400122 }
Ivan Berezovskiy64824112019-07-26 15:55:24 +0400123 try {
124 if ((!askConfirmation && resultCode > 0) || askConfirmation) {
125 galera.restoreGaleraCluster(pepperEnv, runRestoreDb)
126 }
127 } catch (Exception e) {
128 common.errorMsg("Restoration process has failed.")
129 }
Martin Polreichf7a1bb02018-12-05 11:12:23 +0100130 }
Ivan Berezovskiy64824112019-07-26 15:55:24 +0400131 stage('Verify restoration result') {
132 common.retry(verificationRetries, 15) {
133 exitCode = galera.verifyGaleraStatus(pepperEnv, false, false)
134 if (exitCode >= 1) {
135 error("Verification attempt finished with an error. This may be caused by cluster not having enough time to come up or to sync. Next verification attempt in 5 seconds.")
136 } else {
137 common.infoMsg("Restoration procedure seems to be successful. See verification report to be sure.")
138 currentBuild.result = "SUCCESS"
139 }
Martin Polreichf7889b52019-02-01 14:46:10 +0100140 }
Martin Polreich7bc654c2019-01-18 14:17:52 +0100141 }
142 }
Martin Polreichf7a1bb02018-12-05 11:12:23 +0100143 }
144}