blob: 00aff85917c4da0eb2dd74a30a28164bb7e592c6 [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') {
Martin Polreich208c4872019-02-15 10:09:10 +010044 resultCode = galera.verifyGaleraStatus(pepperEnv, false, checkTimeSync)
Martin Polreichf7a1bb02018-12-05 11:12:23 +010045 if (resultCode == 128) {
46 common.errorMsg("Unable to connect to Galera Master. Trying slaves...")
Martin Polreich208c4872019-02-15 10:09:10 +010047 resultCode = galera.verifyGaleraStatus(pepperEnv, true, checkTimeSync)
Martin Polreichf7a1bb02018-12-05 11:12:23 +010048 if (resultCode == 129) {
Ivan Berezovskiy64824112019-07-26 15:55:24 +040049 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 +010050 currentBuild.result = "FAILURE"
Martin Polreichf7889b52019-02-01 14:46:10 +010051 return
Martin Polreichf7a1bb02018-12-05 11:12:23 +010052 } else if (resultCode == 130) {
Martin Polreich0f3b85d2019-04-02 14:22:11 +020053 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 +010054 currentBuild.result = "FAILURE"
Martin Polreichf7889b52019-02-01 14:46:10 +010055 return
Martin Polreichf7a1bb02018-12-05 11:12:23 +010056 }
57 }
Martin Polreich721b7252019-01-21 14:42:48 +010058 if (resultCode == 131) {
Martin Polreich0f3b85d2019-04-02 14:22:11 +020059 common.errorMsg("Time desynced - Please fix this issue and rerun the pipeline.")
Martin Polreich721b7252019-01-21 14:42:48 +010060 currentBuild.result = "FAILURE"
Martin Polreich0f3b85d2019-04-02 14:22:11 +020061 return
62 }
63 if (resultCode == 140 || resultCode == 141) {
64 common.errorMsg("Disk utilization check failed - Please fix this issue and rerun the pipeline.")
65 currentBuild.result = "FAILURE"
66 return
Martin Polreich721b7252019-01-21 14:42:48 +010067 }
Martin Polreichf7a1bb02018-12-05 11:12:23 +010068 if (resultCode == 1) {
Ivan Berezovskiy64824112019-07-26 15:55:24 +040069 if (askConfirmation) {
70 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 +040071 } else {
72 common.warningMsg("There was a problem with parsing the status output or with determining it. Try to restore.")
73 }
Martin Polreichf7a1bb02018-12-05 11:12:23 +010074 } else if (resultCode > 1) {
Ivan Berezovskiy64824112019-07-26 15:55:24 +040075 if (askConfirmation) {
76 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 +040077 } else {
Martin Polreich0f3b85d2019-04-02 14:22:11 +020078 common.warningMsg("There's something wrong with the cluster, try to backup and/or restore.")
Sergey6579de62019-01-15 17:27:59 +040079 }
Martin Polreichf7a1bb02018-12-05 11:12:23 +010080 } else {
Ivan Berezovskiy64824112019-07-26 15:55:24 +040081 if (askConfirmation) {
82 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 +040083 } else {
Ivan Berezovskiy64824112019-07-26 15:55:24 +040084 common.warningMsg("There seems to be everything alright with the cluster, no backup and no restoration will be done.")
85 currentBuild.result = "SUCCESS"
86 return
Sergey6579de62019-01-15 17:27:59 +040087 }
Martin Polreichf7a1bb02018-12-05 11:12:23 +010088 }
Martin Polreich0f3b85d2019-04-02 14:22:11 +020089 }
90 if (runBackupDb) {
Ivan Berezovskiy64824112019-07-26 15:55:24 +040091 if (askConfirmation) {
92 input message: "Are you sure you want to run a backup? Click to confirm"
93 }
Martin Polreich0f3b85d2019-04-02 14:22:11 +020094 stage('Backup') {
Ivan Berezovskiy64824112019-07-26 15:55:24 +040095 deployBuild = build(job: 'galera_backup_database', parameters: [
96 [$class: 'StringParameterValue', name: 'SALT_MASTER_URL', value: SALT_MASTER_URL],
97 [$class: 'StringParameterValue', name: 'SALT_MASTER_CREDENTIALS', value: SALT_MASTER_CREDENTIALS],
98 [$class: 'StringParameterValue', name: 'OVERRIDE_BACKUP_NODE', value: "none"],
99 ]
Martin Polreich0f3b85d2019-04-02 14:22:11 +0200100 )
101 }
102 }
Ivan Berezovskiy64824112019-07-26 15:55:24 +0400103 if (runRestoreDb) {
104 stage('Restore') {
105 if (askConfirmation) {
106 input message: "Are you sure you want to run a restore? Click to confirm"
Sergey6579de62019-01-15 17:27:59 +0400107 }
Ivan Berezovskiy64824112019-07-26 15:55:24 +0400108 try {
109 if ((!askConfirmation && resultCode > 0) || askConfirmation) {
110 galera.restoreGaleraCluster(pepperEnv, runRestoreDb)
111 }
112 } catch (Exception e) {
113 common.errorMsg("Restoration process has failed.")
114 }
Martin Polreichf7a1bb02018-12-05 11:12:23 +0100115 }
Ivan Berezovskiy64824112019-07-26 15:55:24 +0400116 stage('Verify restoration result') {
117 common.retry(verificationRetries, 15) {
118 exitCode = galera.verifyGaleraStatus(pepperEnv, false, false)
119 if (exitCode >= 1) {
120 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.")
121 } else {
122 common.infoMsg("Restoration procedure seems to be successful. See verification report to be sure.")
123 currentBuild.result = "SUCCESS"
124 }
Martin Polreichf7889b52019-02-01 14:46:10 +0100125 }
Martin Polreich7bc654c2019-01-18 14:17:52 +0100126 }
127 }
Martin Polreichf7a1bb02018-12-05 11:12:23 +0100128 }
129}