blob: 5929390cb8b1e12569c5dfb2e388d03752a77c87 [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
134def env = "env"
135timeout(time: 12, unit: 'HOURS') {
136 node() {
137
138 stage('Setup virtualenv for Pepper') {
139 python.setupPepperVirtualenv(env, SALT_MASTER_URL, SALT_MASTER_CREDENTIALS)
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100140 }
141
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300142 def upgradeTargets = salt.getMinionsSorted(env, TARGET_SERVERS)
143
144 if (upgradeTargets.isEmpty()) {
145 error("No servers for upgrade matched by ${TARGET_SERVERS}")
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100146 }
147
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300148 common.printStageMap(upgradeStageMap)
149 if (interactive){
150 input message: common.getColorizedString(
151 "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 +0100152 }
153
Jiri Broulik827d0112018-04-25 16:00:07 +0200154
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300155 for (target in upgradeTargets){
156 common.stageWrapper(upgradeStageMap, "Pre upgrade", target, interactive) {
157 openstack.runOpenStackUpgradePhase(env, target, 'pre')
Oleksandr Pidrepnyid662e5c2019-07-18 16:06:57 +0300158 salt.runSaltProcessStep(env, target, 'saltutil.refresh_pillar', [], null, true)
159 salt.enforceState(env, target, 'linux.system.repo')
Vasyl Saienkob286f6c2018-10-03 14:35:40 +0300160 openstack.runOpenStackUpgradePhase(env, target, 'verify')
Vasyl Saienko1a034dd2018-06-22 15:33:37 +0300161 }
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100162 }
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100163
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300164 for (target in upgradeTargets) {
165 common.stageWrapper(upgradeStageMap, "Stop OpenStack services", target, interactive) {
166 stopOpenStackServices(env, target)
167 }
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100168 }
169
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300170 for (target in upgradeTargets) {
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300171 common.stageWrapper(upgradeStageMap, "Upgrade OS", target, interactive) {
172 if (OS_DIST_UPGRADE.toBoolean() == true){
173 upgrade_mode = 'dist-upgrade'
174 } else if (OS_UPGRADE.toBoolean() == true){
175 upgrade_mode = 'upgrade'
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100176 }
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300177 if (OS_DIST_UPGRADE.toBoolean() == true || OS_UPGRADE.toBoolean() == true) {
178 debian.osUpgradeNode(env, target, upgrade_mode, false)
179 }
Vasyl Saienko278179b2019-06-24 23:44:39 +0300180 // Workaround for PROD-31413, install python-tornado from latest release if available and
181 // restart minion to apply new code.
182 salt.upgradePackageAndRestartSaltMinion(env, target, 'python-tornado')
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300183 }
Ivan Udovichenko24f40f42018-11-29 18:14:34 +0300184
185 common.stageWrapper(upgradeStageMap, "Upgrade OpenStack", target, interactive) {
186 openstack.runOpenStackUpgradePhase(env, target, 'upgrade')
187 openstack.applyOpenstackAppsStates(env, target)
188 openstack.runOpenStackUpgradePhase(env, target, 'verify')
189 }
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100190 }
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300191 }
Vasyl Saienko1a034dd2018-06-22 15:33:37 +0300192}