blob: a8e085d2e91181a5e0e117cf36960756a915afd5 [file] [log] [blame]
Oleksandr Bryndzii13bb1362019-06-14 14:46:39 +00001/**
2 * Upgrade MySQL and Galera packages on dbs nodes.
3 * Update packages on given nodes
4 *
5 * Expected parameters:
6 * SALT_MASTER_CREDENTIALS Credentials to the Salt API.
7 * SALT_MASTER_URL Full Salt API address [http://10.10.10.15:6969].
8 * SHUTDOWN_CLUSTER Shutdown all mysql instances on target nodes at the same time.
9 * OS_DIST_UPGRADE Upgrade system packages including kernel (apt-get dist-upgrade).
10 * OS_UPGRADE Upgrade all installed applications (apt-get upgrade)
11 * TARGET_SERVERS Comma separated list of salt compound definitions to upgrade.
12 * INTERACTIVE Ask interactive questions during pipeline run (bool).
Roman Lubianyifb10a4d2022-02-11 12:37:46 +020013 * UPDATE_TO_MYSQL57 Set this flag if you are updating MySQL from 5.6 to 5.7
Oleksandr Bryndzii13bb1362019-06-14 14:46:39 +000014 *
15**/
16
17def common = new com.mirantis.mk.Common()
18def salt = new com.mirantis.mk.Salt()
19def python = new com.mirantis.mk.Python()
20def debian = new com.mirantis.mk.Debian()
21def openstack = new com.mirantis.mk.Openstack()
22def galera = new com.mirantis.mk.Galera()
23def shutdownCluster = SHUTDOWN_CLUSTER.toBoolean()
24def interactive = INTERACTIVE.toBoolean()
25def LinkedHashMap upgradeStageMap = [:]
Roman Lubianyifb10a4d2022-02-11 12:37:46 +020026def updateToMysql57 = UPDATE_TO_MYSQL57.toBoolean()
Oleksandr Bryndzii13bb1362019-06-14 14:46:39 +000027
28upgradeStageMap.put('Pre upgrade',
29 [
30 'Description': 'Only non destructive actions will be applied during this phase. Basic service verification will be performed.',
31 'Status': 'NOT_LAUNCHED',
32 'Expected behaviors': '''
33 * No service downtime
34 * No workload downtime''',
35 'Launched actions': '''
36 * Verify API, perform basic CRUD operations for services.
37 * Verify MySQL is running and Galera cluster is operational.''',
38 'State result': 'Basic checks around wsrep Galera status are passed.'
39 ])
40
41upgradeStageMap.put('Stop MySQL service',
42 [
43 'Description': 'All MySQL services will be stopped on All TARGET_SERVERS nodes.',
44 'Status': 'NOT_LAUNCHED',
45 'Expected behaviors': '''
46 * MySQL services are stopped.
47 * OpenStack APIs are not accessible from this point.
48 * No workload downtime''',
49 'Launched actions': '''
50 * Stop MySQL services''',
51 'State result': 'MySQL service is stopped',
52 ])
53
54upgradeStageMap.put('Upgrade OS',
55 [
56 'Description': 'Optional step. OS packages will be upgraded during this phase, depending on the job parameters dist-upgrade might be called. And reboot of node executed.',
57 'Status': 'NOT_LAUNCHED',
58 'Expected behaviors': '''
59 * No workload downtime
60 * The nodes might be rebooted''',
61 'Launched actions': '''
62 * Install new version of system packages
63 * If doing dist-upgrade new kernel might be installed and node rebooted
64 * System packages are updated
65 * Node might be rebooted
66'''
67 ])
68
69upgradeStageMap.put('Upgrade MySQL server',
70 [
71 'Description': 'MySQL and Erlang code will be upgraded during this stage. No workload downtime is expected.',
72 'Status': 'NOT_LAUNCHED',
73 'Expected behaviors': '''
74 * OpenStack services loose connection to MySQL server
75 * No workload downtime''',
76 'Launched actions': '''
77 * Install new version of MySQL and Galera packages
78 * Render version of configs''',
79 'State result': '''
80 * MySQL packages are upgraded''',
81 ])
82
83upgradeStageMap.put('Start MySQL service',
84 [
85 'Description': 'All MySQL services will be running on All TARGET_SERVERS nodes.',
86 'Status': 'NOT_LAUNCHED',
87 'Expected behaviors': '''
88 * MySQL service is running.
89 * OpenStack API are accessible from this point.
90 * No workload downtime''',
91 'Launched actions': '''
92 * Start MySQL service''',
93 'State result': 'MySQL service is running',
94 ])
95
96def env = "env"
97timeout(time: 12, unit: 'HOURS') {
98 node() {
99
100 stage('Setup virtualenv for Pepper') {
101 python.setupPepperVirtualenv(env, SALT_MASTER_URL, SALT_MASTER_CREDENTIALS)
102 }
103
104 def upgradeTargets = salt.getMinionsSorted(env, TARGET_SERVERS)
105
106 if (upgradeTargets.isEmpty()) {
107 error("No servers for upgrade matched by ${TARGET_SERVERS}")
108 }
109
110 def targetSecMapping = [:]
111 def secNoList = []
112 def out
113 def stopTargets = upgradeTargets.reverse()
114 common.printStageMap(upgradeStageMap)
115
116 if (interactive){
117 input message: common.getColorizedString(
118 "Above you can find detailed info this pipeline will execute.\nThe info provides brief description of each stage, actions that will be performed and service/workload impact during each stage.\nPlease read it carefully.", "yellow")
119 }
120
121 for (target in upgradeTargets) {
122 salt.runSaltProcessStep(env, target, 'saltutil.refresh_pillar', [], null, true)
Roman Lubianyifb10a4d2022-02-11 12:37:46 +0200123 mysqlPillarVersion = salt.getPillar(env, target, "galera:version:mysql").get("return")[0].values()[0].toString().toLowerCase()
124 mysql56InstalledVersion = salt.getReturnValues(salt.runSaltProcessStep(env, target, 'pkg.version', 'mysql-wsrep-server-5.6', null, true)).toString().toLowerCase().take(3)
125 mysql57InstalledVersion = salt.getReturnValues(salt.runSaltProcessStep(env, target, 'pkg.version', 'mysql-wsrep-server-5.7', null, true)).toString().toLowerCase().take(3)
126
127 if (mysqlPillarVersion == '5.6' && mysql57InstalledVersion == '5.7') {
128 error("""Pre upgrade check failed. You are trying to downgrade MySQL package from 5.7 version to 5.6.
129 Check value for galera_mysql_version variable in your model.""")
130 }
131 if (mysqlPillarVersion == '5.7' && mysql56InstalledVersion == '5.6' && updateToMysql57 != true) {
132 error("""Pre upgrade check failed. You are trying to update MySQL package from version 5.6 to version 5.7 the wrong way.
133 If you want to update from 5.6 version to 5.7 set flag UPDATE_TO_MYSQL57 in the current job.
134 If you don't want to update from 5.6 version to 5.7 you need to change the value for galera_mysql_version to 5.6 in your model.""")
135 }
136
Oleksandr Bryndzii13bb1362019-06-14 14:46:39 +0000137 salt.enforceState(env, target, ['linux.system.repo'])
138 common.stageWrapper(upgradeStageMap, "Pre upgrade", target, interactive) {
139 openstack.runOpenStackUpgradePhase(env, target, 'pre')
140 openstack.runOpenStackUpgradePhase(env, target, 'verify')
141 }
142 }
143
Roman Lubianyifb10a4d2022-02-11 12:37:46 +0200144 if (updateToMysql57 == true) {
145 shutdownCluster = true
146 }
147
Oleksandr Bryndzii13bb1362019-06-14 14:46:39 +0000148 if (shutdownCluster){
149 for (target in stopTargets) {
150 common.stageWrapper(upgradeStageMap, "Stop MySQL service", target, interactive) {
151 openstack.runOpenStackUpgradePhase(env, target, 'service_stopped')
152 }
153 }
154 }
155
Roman Lubianyi34603b32022-01-26 15:48:36 +0200156 def masterNode = salt.getMinionsSorted(env, galera.getGaleraLastShutdownNode(env))[0]
Oleksandr Bryndzii13bb1362019-06-14 14:46:39 +0000157 common.infoMsg("Master node is: ${masterNode}")
158
159 // Make sure we start upgrade always from master node
160 upgradeTargets.remove(masterNode)
161 upgradeTargets = [masterNode] + upgradeTargets
162 common.infoMsg("Upgrade targets are: ${upgradeTargets}")
163
164 for (target in upgradeTargets) {
165
166 common.stageWrapper(upgradeStageMap, "Stop MySQL service", target, interactive) {
167 openstack.runOpenStackUpgradePhase(env, target, 'service_stopped')
168 }
169
170 common.stageWrapper(upgradeStageMap, "Upgrade OS", target, interactive) {
171 if (OS_DIST_UPGRADE.toBoolean() == true){
172 upgrade_mode = 'dist-upgrade'
173 } else if (OS_UPGRADE.toBoolean() == true){
174 upgrade_mode = 'upgrade'
175 }
176 if (OS_DIST_UPGRADE.toBoolean() == true || OS_UPGRADE.toBoolean() == true) {
177 debian.osUpgradeNode(env, target, upgrade_mode, false)
178 }
179 }
180
181 common.stageWrapper(upgradeStageMap, "Upgrade MySQL server", target, interactive) {
Roman Lubianyifb10a4d2022-02-11 12:37:46 +0200182 if (updateToMysql57 == true) {
183 if (target == masterNode) {
184 openstack.runOpenStackUpgradePhase(env, target, 'update_master')
185 }
186 else {
187 openstack.runOpenStackUpgradePhase(env, target, 'update_slave')
188 }
189 }
190 else {
191 openstack.runOpenStackUpgradePhase(env, target, 'pkgs_latest')
192 openstack.runOpenStackUpgradePhase(env, target, 'render_config')
193 }
Oleksandr Bryndzii13bb1362019-06-14 14:46:39 +0000194 }
195
196 if (shutdownCluster && target == masterNode){
197 //Start first node.
198 common.stageWrapper(upgradeStageMap, "Start MySQL service", target, interactive) {
199 galera.startFirstNode(env, target)
200 }
201 }
202
203 common.stageWrapper(upgradeStageMap, "Start MySQL service", target, interactive) {
204 openstack.runOpenStackUpgradePhase(env, target, 'service_running')
205 openstack.runOpenStackUpgradePhase(env, target, 'verify')
206 }
207 }
208
209 // restart first node by applying state.
210
211 if (shutdownCluster) {
212 openstack.runOpenStackUpgradePhase(env, masterNode, 'render_config')
Roman Lubianyi10d70fd2022-01-26 16:00:01 +0200213 salt.cmdRun(env, masterNode, "systemctl restart mysql")
Oleksandr Bryndzii13bb1362019-06-14 14:46:39 +0000214 openstack.runOpenStackUpgradePhase(env, masterNode, 'verify')
215 }
216
217 for (target in upgradeTargets) {
218 ensureClusterState = galera.getWsrepParameters(env, target, 'wsrep_evs_state')
219 if (ensureClusterState['wsrep_evs_state'] == 'OPERATIONAL') {
220 common.infoMsg('Node is in OPERATIONAL state.')
221 } else {
222 throw new Exception("Node is NOT in OPERATIONAL state.")
223 }
224 }
225 }
226}