blob: f5bee781619a1b77e23b03312fc9996218adbb6e [file] [log] [blame]
Jiri Broulikbb447ac2017-05-04 15:36:22 +02001/**
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +03002 * Upgrade OpenStack packages on control plane nodes.
3 * There are no silver boollet in uprading cloud.
Jiri Broulikbb447ac2017-05-04 15:36:22 +02004 * Update packages on given nodes
5 *
6 * Expected parameters:
Jiri Brouliked3a9e62018-02-13 16:08:40 +01007 * SALT_MASTER_CREDENTIALS Credentials to the Salt API.
8 * SALT_MASTER_URL Full Salt API address [http://10.10.10.1:8000].
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +03009 * 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.
Vasyl Saienko1a034dd2018-06-22 15:33:37 +030012 * INTERACTIVE Ask interactive questions during pipeline run (bool).
Jiri Broulikbb447ac2017-05-04 15:36:22 +020013 *
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +030014 * TODO:
15 * * Add OS_RELEASE_UPGRADE
Jiri Broulikbb447ac2017-05-04 15:36:22 +020016**/
17
18def common = new com.mirantis.mk.Common()
19def salt = new com.mirantis.mk.Salt()
chnyda625f4b42017-10-11 14:10:31 +020020def python = new com.mirantis.mk.Python()
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +030021def debian = new com.mirantis.mk.Debian()
22def openstack = new com.mirantis.mk.Openstack()
Jiri Broulikbb447ac2017-05-04 15:36:22 +020023
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +030024def interactive = INTERACTIVE.toBoolean()
25def LinkedHashMap upgradeStageMap = [:]
26
27upgradeStageMap.put('Pre upgrade',
28 [
29 'Description': 'Only non destructive actions will be applied during this phase. Basic api, service verification will be performed.',
30 'Status': 'NOT_LAUNCHED',
31 'Expected behaviors': '''
32 * No service downtime
33 * No workload downtime''',
34 'Launched actions': '''
Oleksandr Pidrepnyid662e5c2019-07-18 16:06:57 +030035 * Refresh pillars on the target nodes.
36 * Apply the 'linux.system.repo' state on the target nodes.
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +030037 * Verify API, perform basic CRUD operations for services.
38 * Verify that compute/neutron agents on hosts are up.
39 * Run some service built in checkers like keystone-manage doctor or nova-status upgrade.''',
40 'State result': 'Basic checks around services API are passed.'
41 ])
42upgradeStageMap.put('Stop OpenStack services',
43 [
44 'Description': 'All OpenStack python services will be stopped on All control nodes. This does not affect data plane services such as openvswitch or qemu.',
45 'Status': 'NOT_LAUNCHED',
46 'Expected behaviors': '''
47 * OpenStack python services are stopped.
48 * OpenStack API are not accessible from this point.
49 * No workload downtime''',
50 'Launched actions': '''
51 * Stop OpenStack python services''',
52 'State result': 'OpenStack python services are stopped',
53 ])
Ivan Udovichenko24f40f42018-11-29 18:14:34 +030054upgradeStageMap.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 * OpenStack services might flap
60 * No workload downtime
61 * The nodes might be rebooted''',
62 'Launched actions': '''
63 * Install new version of system packages
64 * If doing dist-upgrade new kernel might be installed and node rebooted
65 * System packages are updated
66 * Node might be rebooted
67'''
68 ])
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +030069upgradeStageMap.put('Upgrade OpenStack',
70 [
71 'Description': 'OpenStack python code will be upgraded during this stage. No workload downtime is expected.',
72 'Status': 'NOT_LAUNCHED',
73 'Expected behaviors': '''
74 * OpenStack services might flap
75 * No workload downtime''',
76 'Launched actions': '''
77 * Install new version of OpenStack packages
78 * Render version of configs
79 * Apply offline dbsync
80 * Start OpenStack services
81 * Verify agents are alive/connected
82 * Run basic API validation''',
83 'State result': '''
84 * OpenStack packages are upgraded
85 * Services are running
86 * Basic checks around services API are passed
87 * Verified that agents/services on data plane nodes are connected to new control plane
88'''
89 ])
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +030090
91def stopOpenStackServices(env, target) {
Jiri Broulik0d111e92018-04-25 21:30:42 +020092 def salt = new com.mirantis.mk.Salt()
Jiri Brouliked3a9e62018-02-13 16:08:40 +010093 def openstack = new com.mirantis.mk.Openstack()
Jiri Brouliked3a9e62018-02-13 16:08:40 +010094 def common = new com.mirantis.mk.Common()
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +030095
96 def services = openstack.getOpenStackUpgradeServices(env, target)
97 def st
98 for (service in services){
99 st = "${service}.upgrade.service_stopped".trim()
100 common.infoMsg("Stopping ${st} services on ${target}")
101 salt.enforceState(env, target, st)
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100102 }
103}
104
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300105def snapshotVM(env, domain, snapshotName) {
106 def common = new com.mirantis.mk.Common()
107 def salt = new com.mirantis.mk.Salt()
108
109 def target = salt.getNodeProvider(env, domain)
110
111 // TODO: gracefully migrate all workloads from VM, and stop it
112 salt.runSaltProcessStep(env, target, 'virt.shutdown', [domain], null, true, 3600)
113
114 //TODO: wait while VM is powered off
115
116 common.infoMsg("Creating snapshot ${snapshotName} for VM ${domain} on node ${target}")
117 salt.runSaltProcessStep(env, target, 'virt.snapshot', [domain, snapshotName], null, true, 3600)
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100118}
119
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300120def revertSnapshotVM(env, domain, snapshotName, ensureUp=true) {
121 def common = new com.mirantis.mk.Common()
122 def salt = new com.mirantis.mk.Salt()
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100123
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300124 def target = salt.getNodeProvider(env, domain)
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100125
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300126 common.infoMsg("Reverting snapshot ${snapshotName} for VM ${domain} on node ${target}")
127 salt.runSaltProcessStep(env, target, 'virt.revert_snapshot', [snapshotName, domain], null, true, 3600)
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100128
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300129 if (ensureUp){
130 salt.runSaltProcessStep(env, target, 'virt.start', [domain], null, true, 300)
131 }
132}
133
Valeriy Sakharov01f16542023-03-23 20:50:09 +0400134def restartDesignate(env, target) {
Valeriy Sakharovf264ade2023-02-17 15:49:32 +0400135 def common = new com.mirantis.mk.Common()
136 def salt = new com.mirantis.mk.Salt()
137 // Workaround for PROD-33592, restart designate-central services if enabled
Valeriy Sakharov01f16542023-03-23 20:50:09 +0400138 designate_enabled = salt.getPillar(env, target, "designate:server:enabled").get("return")[0].values()[0]
Valeriy Sakharovf264ade2023-02-17 15:49:32 +0400139 if (designate_enabled == '' || designate_enabled == 'false' || designate_enabled == null) {
140 common.infoMsg('Designate is disabled, nothing to do')
141 } else {
142 try {
Valeriy Sakharov01f16542023-03-23 20:50:09 +0400143 salt.runSaltProcessStep(env, target, "service.restart", "designate-central", null, true)
Valeriy Sakharovf264ade2023-02-17 15:49:32 +0400144 }
145 catch (Exception ex) {
146 common.infoMsg(ex)
147 error('Designate service is broken, please check logs')
148 }
149 }
150}
151
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300152def env = "env"
153timeout(time: 12, unit: 'HOURS') {
154 node() {
155
156 stage('Setup virtualenv for Pepper') {
157 python.setupPepperVirtualenv(env, SALT_MASTER_URL, SALT_MASTER_CREDENTIALS)
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100158 }
159
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300160 def upgradeTargets = salt.getMinionsSorted(env, TARGET_SERVERS)
161
162 if (upgradeTargets.isEmpty()) {
163 error("No servers for upgrade matched by ${TARGET_SERVERS}")
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100164 }
165
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300166 common.printStageMap(upgradeStageMap)
167 if (interactive){
168 input message: common.getColorizedString(
169 "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")
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100170 }
171
Vladimir Khlyunevf1a65332021-08-30 13:28:08 +0400172 common.infoMsg("Refreshing haproxy config for mysql proxies")
173 salt.enforceState(env, 'I@haproxy:proxy:listen:mysql_cluster', ['haproxy.proxy'])
Jiri Broulik827d0112018-04-25 16:00:07 +0200174
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300175 for (target in upgradeTargets){
176 common.stageWrapper(upgradeStageMap, "Pre upgrade", target, interactive) {
177 openstack.runOpenStackUpgradePhase(env, target, 'pre')
Oleksandr Pidrepnyid662e5c2019-07-18 16:06:57 +0300178 salt.runSaltProcessStep(env, target, 'saltutil.refresh_pillar', [], null, true)
179 salt.enforceState(env, target, 'linux.system.repo')
Valeriy Sakharov01f16542023-03-23 20:50:09 +0400180 restartDesignate(env, target)
Vasyl Saienkob286f6c2018-10-03 14:35:40 +0300181 openstack.runOpenStackUpgradePhase(env, target, 'verify')
Vasyl Saienko1a034dd2018-06-22 15:33:37 +0300182 }
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100183 }
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100184
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300185 for (target in upgradeTargets) {
186 common.stageWrapper(upgradeStageMap, "Stop OpenStack services", target, interactive) {
187 stopOpenStackServices(env, target)
188 }
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100189 }
190
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300191 for (target in upgradeTargets) {
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300192 common.stageWrapper(upgradeStageMap, "Upgrade OS", target, interactive) {
193 if (OS_DIST_UPGRADE.toBoolean() == true){
194 upgrade_mode = 'dist-upgrade'
195 } else if (OS_UPGRADE.toBoolean() == true){
196 upgrade_mode = 'upgrade'
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100197 }
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300198 if (OS_DIST_UPGRADE.toBoolean() == true || OS_UPGRADE.toBoolean() == true) {
199 debian.osUpgradeNode(env, target, upgrade_mode, false)
200 }
Vasyl Saienko278179b2019-06-24 23:44:39 +0300201 // Workaround for PROD-31413, install python-tornado from latest release if available and
202 // restart minion to apply new code.
203 salt.upgradePackageAndRestartSaltMinion(env, target, 'python-tornado')
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300204 }
Ivan Udovichenko24f40f42018-11-29 18:14:34 +0300205
206 common.stageWrapper(upgradeStageMap, "Upgrade OpenStack", target, interactive) {
207 openstack.runOpenStackUpgradePhase(env, target, 'upgrade')
208 openstack.applyOpenstackAppsStates(env, target)
209 openstack.runOpenStackUpgradePhase(env, target, 'verify')
210 }
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100211 }
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300212 }
Vasyl Saienko1a034dd2018-06-22 15:33:37 +0300213}