blob: f2dd78c2d5390af9bdbadb0e64128e7f76b7037a [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': '''
35 * Verify API, perform basic CRUD operations for services.
36 * Verify that compute/neutron agents on hosts are up.
37 * Run some service built in checkers like keystone-manage doctor or nova-status upgrade.''',
38 'State result': 'Basic checks around services API are passed.'
39 ])
40upgradeStageMap.put('Stop OpenStack services',
41 [
42 'Description': 'All OpenStack python services will be stopped on All control nodes. This does not affect data plane services such as openvswitch or qemu.',
43 'Status': 'NOT_LAUNCHED',
44 'Expected behaviors': '''
45 * OpenStack python services are stopped.
46 * OpenStack API are not accessible from this point.
47 * No workload downtime''',
48 'Launched actions': '''
49 * Stop OpenStack python services''',
50 'State result': 'OpenStack python services are stopped',
51 ])
Ivan Udovichenko24f40f42018-11-29 18:14:34 +030052upgradeStageMap.put('Upgrade OS',
53 [
54 '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.',
55 'Status': 'NOT_LAUNCHED',
56 'Expected behaviors': '''
57 * OpenStack services might flap
58 * No workload downtime
59 * The nodes might be rebooted''',
60 'Launched actions': '''
61 * Install new version of system packages
62 * If doing dist-upgrade new kernel might be installed and node rebooted
63 * System packages are updated
64 * Node might be rebooted
65'''
66 ])
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +030067upgradeStageMap.put('Upgrade OpenStack',
68 [
69 'Description': 'OpenStack python code will be upgraded during this stage. No workload downtime is expected.',
70 'Status': 'NOT_LAUNCHED',
71 'Expected behaviors': '''
72 * OpenStack services might flap
73 * No workload downtime''',
74 'Launched actions': '''
75 * Install new version of OpenStack packages
76 * Render version of configs
77 * Apply offline dbsync
78 * Start OpenStack services
79 * Verify agents are alive/connected
80 * Run basic API validation''',
81 'State result': '''
82 * OpenStack packages are upgraded
83 * Services are running
84 * Basic checks around services API are passed
85 * Verified that agents/services on data plane nodes are connected to new control plane
86'''
87 ])
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +030088
89def stopOpenStackServices(env, target) {
Jiri Broulik0d111e92018-04-25 21:30:42 +020090 def salt = new com.mirantis.mk.Salt()
Jiri Brouliked3a9e62018-02-13 16:08:40 +010091 def openstack = new com.mirantis.mk.Openstack()
Jiri Brouliked3a9e62018-02-13 16:08:40 +010092 def common = new com.mirantis.mk.Common()
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +030093
94 def services = openstack.getOpenStackUpgradeServices(env, target)
95 def st
96 for (service in services){
97 st = "${service}.upgrade.service_stopped".trim()
98 common.infoMsg("Stopping ${st} services on ${target}")
99 salt.enforceState(env, target, st)
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100100 }
101}
102
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300103def snapshotVM(env, domain, snapshotName) {
104 def common = new com.mirantis.mk.Common()
105 def salt = new com.mirantis.mk.Salt()
106
107 def target = salt.getNodeProvider(env, domain)
108
109 // TODO: gracefully migrate all workloads from VM, and stop it
110 salt.runSaltProcessStep(env, target, 'virt.shutdown', [domain], null, true, 3600)
111
112 //TODO: wait while VM is powered off
113
114 common.infoMsg("Creating snapshot ${snapshotName} for VM ${domain} on node ${target}")
115 salt.runSaltProcessStep(env, target, 'virt.snapshot', [domain, snapshotName], null, true, 3600)
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100116}
117
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300118def revertSnapshotVM(env, domain, snapshotName, ensureUp=true) {
119 def common = new com.mirantis.mk.Common()
120 def salt = new com.mirantis.mk.Salt()
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100121
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300122 def target = salt.getNodeProvider(env, domain)
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100123
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300124 common.infoMsg("Reverting snapshot ${snapshotName} for VM ${domain} on node ${target}")
125 salt.runSaltProcessStep(env, target, 'virt.revert_snapshot', [snapshotName, domain], null, true, 3600)
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100126
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300127 if (ensureUp){
128 salt.runSaltProcessStep(env, target, 'virt.start', [domain], null, true, 300)
129 }
130}
131
132def env = "env"
133timeout(time: 12, unit: 'HOURS') {
134 node() {
135
136 stage('Setup virtualenv for Pepper') {
137 python.setupPepperVirtualenv(env, SALT_MASTER_URL, SALT_MASTER_CREDENTIALS)
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100138 }
139
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300140 def upgradeTargets = salt.getMinionsSorted(env, TARGET_SERVERS)
141
142 if (upgradeTargets.isEmpty()) {
143 error("No servers for upgrade matched by ${TARGET_SERVERS}")
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100144 }
145
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300146 common.printStageMap(upgradeStageMap)
147 if (interactive){
148 input message: common.getColorizedString(
149 "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 +0100150 }
151
Jiri Broulik827d0112018-04-25 16:00:07 +0200152
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300153 for (target in upgradeTargets){
154 common.stageWrapper(upgradeStageMap, "Pre upgrade", target, interactive) {
155 openstack.runOpenStackUpgradePhase(env, target, 'pre')
Vasyl Saienkob286f6c2018-10-03 14:35:40 +0300156 openstack.runOpenStackUpgradePhase(env, target, 'verify')
Vasyl Saienko1a034dd2018-06-22 15:33:37 +0300157 }
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100158 }
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100159
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300160 for (target in upgradeTargets) {
161 common.stageWrapper(upgradeStageMap, "Stop OpenStack services", target, interactive) {
162 stopOpenStackServices(env, target)
163 }
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100164 }
165
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300166 for (target in upgradeTargets) {
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300167 common.stageWrapper(upgradeStageMap, "Upgrade OS", target, interactive) {
168 if (OS_DIST_UPGRADE.toBoolean() == true){
169 upgrade_mode = 'dist-upgrade'
170 } else if (OS_UPGRADE.toBoolean() == true){
171 upgrade_mode = 'upgrade'
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100172 }
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300173 if (OS_DIST_UPGRADE.toBoolean() == true || OS_UPGRADE.toBoolean() == true) {
174 debian.osUpgradeNode(env, target, upgrade_mode, false)
175 }
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300176 }
Ivan Udovichenko24f40f42018-11-29 18:14:34 +0300177
178 common.stageWrapper(upgradeStageMap, "Upgrade OpenStack", target, interactive) {
179 openstack.runOpenStackUpgradePhase(env, target, 'upgrade')
180 openstack.applyOpenstackAppsStates(env, target)
181 openstack.runOpenStackUpgradePhase(env, target, 'verify')
182 }
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100183 }
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300184 }
Vasyl Saienko1a034dd2018-06-22 15:33:37 +0300185}