blob: 5febb3cc19b5b322f31987257ee74fc853d16960 [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 ])
52upgradeStageMap.put('Upgrade OpenStack',
53 [
54 'Description': 'OpenStack python code will be upgraded during this stage. No workload downtime is expected.',
55 'Status': 'NOT_LAUNCHED',
56 'Expected behaviors': '''
57 * OpenStack services might flap
58 * No workload downtime''',
59 'Launched actions': '''
60 * Install new version of OpenStack packages
61 * Render version of configs
62 * Apply offline dbsync
63 * Start OpenStack services
64 * Verify agents are alive/connected
65 * Run basic API validation''',
66 'State result': '''
67 * OpenStack packages are upgraded
68 * Services are running
69 * Basic checks around services API are passed
70 * Verified that agents/services on data plane nodes are connected to new control plane
71'''
72 ])
73upgradeStageMap.put('Upgrade OS',
74 [
75 '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.',
76 'Status': 'NOT_LAUNCHED',
77 'Expected behaviors': '''
78 * OpenStack services might flap
79 * No workload downtime
80 * The nodes might be rebooted''',
81 'Launched actions': '''
82 * Install new version of system packages
83 * If doing dist-upgrade new kernel might be installed and node rebooted
84 * Verify agents are alive/connected
85 * Run basic API validation''',
86 'State result': '''
87 * System packages are updated
88 * Services are running
89 * Basic checks around services API are passed
90 * Verified that agents/services on data plane nodes are connected
91 * Node might be rebooted
92'''
93 ])
94
95def stopOpenStackServices(env, target) {
Jiri Broulik0d111e92018-04-25 21:30:42 +020096 def salt = new com.mirantis.mk.Salt()
Jiri Brouliked3a9e62018-02-13 16:08:40 +010097 def openstack = new com.mirantis.mk.Openstack()
Jiri Brouliked3a9e62018-02-13 16:08:40 +010098 def common = new com.mirantis.mk.Common()
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +030099
100 def services = openstack.getOpenStackUpgradeServices(env, target)
101 def st
102 for (service in services){
103 st = "${service}.upgrade.service_stopped".trim()
104 common.infoMsg("Stopping ${st} services on ${target}")
105 salt.enforceState(env, target, st)
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100106 }
107}
108
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300109def snapshotVM(env, domain, snapshotName) {
110 def common = new com.mirantis.mk.Common()
111 def salt = new com.mirantis.mk.Salt()
112
113 def target = salt.getNodeProvider(env, domain)
114
115 // TODO: gracefully migrate all workloads from VM, and stop it
116 salt.runSaltProcessStep(env, target, 'virt.shutdown', [domain], null, true, 3600)
117
118 //TODO: wait while VM is powered off
119
120 common.infoMsg("Creating snapshot ${snapshotName} for VM ${domain} on node ${target}")
121 salt.runSaltProcessStep(env, target, 'virt.snapshot', [domain, snapshotName], null, true, 3600)
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100122}
123
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300124def revertSnapshotVM(env, domain, snapshotName, ensureUp=true) {
125 def common = new com.mirantis.mk.Common()
126 def salt = new com.mirantis.mk.Salt()
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100127
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300128 def target = salt.getNodeProvider(env, domain)
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100129
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300130 common.infoMsg("Reverting snapshot ${snapshotName} for VM ${domain} on node ${target}")
131 salt.runSaltProcessStep(env, target, 'virt.revert_snapshot', [snapshotName, domain], null, true, 3600)
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100132
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300133 if (ensureUp){
134 salt.runSaltProcessStep(env, target, 'virt.start', [domain], null, true, 300)
135 }
136}
137
138def env = "env"
139timeout(time: 12, unit: 'HOURS') {
140 node() {
141
142 stage('Setup virtualenv for Pepper') {
143 python.setupPepperVirtualenv(env, SALT_MASTER_URL, SALT_MASTER_CREDENTIALS)
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100144 }
145
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300146 def upgradeTargets = salt.getMinionsSorted(env, TARGET_SERVERS)
147
148 if (upgradeTargets.isEmpty()) {
149 error("No servers for upgrade matched by ${TARGET_SERVERS}")
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100150 }
151
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300152 common.printStageMap(upgradeStageMap)
153 if (interactive){
154 input message: common.getColorizedString(
155 "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 +0100156 }
157
Jiri Broulik827d0112018-04-25 16:00:07 +0200158
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300159 for (target in upgradeTargets){
160 common.stageWrapper(upgradeStageMap, "Pre upgrade", target, interactive) {
161 openstack.runOpenStackUpgradePhase(env, target, 'pre')
Vasyl Saienkob286f6c2018-10-03 14:35:40 +0300162 openstack.runOpenStackUpgradePhase(env, target, 'verify')
Vasyl Saienko1a034dd2018-06-22 15:33:37 +0300163 }
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100164 }
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100165
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300166 for (target in upgradeTargets) {
167 common.stageWrapper(upgradeStageMap, "Stop OpenStack services", target, interactive) {
168 stopOpenStackServices(env, target)
169 }
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100170 }
171
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300172 for (target in upgradeTargets) {
173 common.stageWrapper(upgradeStageMap, "Upgrade OpenStack", target, interactive) {
174 openstack.runOpenStackUpgradePhase(env, target, 'upgrade')
175 openstack.applyOpenstackAppsStates(env, target)
176 openstack.runOpenStackUpgradePhase(env, target, 'verify')
177 }
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100178
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300179 common.stageWrapper(upgradeStageMap, "Upgrade OS", target, interactive) {
180 if (OS_DIST_UPGRADE.toBoolean() == true){
181 upgrade_mode = 'dist-upgrade'
182 } else if (OS_UPGRADE.toBoolean() == true){
183 upgrade_mode = 'upgrade'
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100184 }
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300185 if (OS_DIST_UPGRADE.toBoolean() == true || OS_UPGRADE.toBoolean() == true) {
186 debian.osUpgradeNode(env, target, upgrade_mode, false)
187 }
188 openstack.applyOpenstackAppsStates(env, target)
189 openstack.runOpenStackUpgradePhase(env, target, 'verify')
190 }
Jiri Brouliked3a9e62018-02-13 16:08:40 +0100191 }
Vasyl Saienkoab2a0c92018-09-05 17:24:32 +0300192 }
Vasyl Saienko1a034dd2018-06-22 15:33:37 +0300193}