Jiri Broulik | bb447ac | 2017-05-04 15:36:22 +0200 | [diff] [blame] | 1 | /** |
| 2 | * Update packages on given nodes |
| 3 | * |
| 4 | * Expected parameters: |
Jiri Broulik | ed3a9e6 | 2018-02-13 16:08:40 +0100 | [diff] [blame] | 5 | * SALT_MASTER_CREDENTIALS Credentials to the Salt API. |
| 6 | * SALT_MASTER_URL Full Salt API address [http://10.10.10.1:8000]. |
| 7 | * STAGE_TEST_UPGRADE Run test upgrade stage (bool) |
| 8 | * STAGE_REAL_UPGRADE Run real upgrade stage (bool) |
| 9 | * STAGE_ROLLBACK_UPGRADE Run rollback upgrade stage (bool) |
| 10 | * SKIP_VM_RELAUNCH Set to true if vms should not be recreated (bool) |
| 11 | * OPERATING_SYSTEM_RELEASE_UPGRADE Set to true if operating system of vms should be upgraded to newer release (bool) |
Vasyl Saienko | 1a034dd | 2018-06-22 15:33:37 +0300 | [diff] [blame^] | 12 | * INTERACTIVE Ask interactive questions during pipeline run (bool). |
Jiri Broulik | bb447ac | 2017-05-04 15:36:22 +0200 | [diff] [blame] | 13 | * |
| 14 | **/ |
| 15 | |
| 16 | def common = new com.mirantis.mk.Common() |
| 17 | def salt = new com.mirantis.mk.Salt() |
chnyda | 625f4b4 | 2017-10-11 14:10:31 +0200 | [diff] [blame] | 18 | def python = new com.mirantis.mk.Python() |
Jiri Broulik | bb447ac | 2017-05-04 15:36:22 +0200 | [diff] [blame] | 19 | |
Jiri Broulik | 0d111e9 | 2018-04-25 21:30:42 +0200 | [diff] [blame] | 20 | def getNodeProvider(pepperEnv, name) { |
| 21 | def salt = new com.mirantis.mk.Salt() |
| 22 | def kvm = salt.getKvmMinionId(pepperEnv) |
| 23 | return salt.getReturnValues(salt.getPillar(pepperEnv, "${kvm}", "salt:control:cluster:internal:node:${name}:provider")) |
| 24 | } |
| 25 | |
Jiri Broulik | ed3a9e6 | 2018-02-13 16:08:40 +0100 | [diff] [blame] | 26 | def stopServices(pepperEnv, probe, target, type) { |
| 27 | def openstack = new com.mirantis.mk.Openstack() |
| 28 | def services = [] |
| 29 | if (type == 'prx') { |
| 30 | services.add('keepalived') |
| 31 | services.add('nginx') |
| 32 | } else if (type == 'ctl') { |
| 33 | services.add('keepalived') |
| 34 | services.add('haproxy') |
| 35 | services.add('nova') |
| 36 | services.add('cinder') |
| 37 | services.add('glance') |
| 38 | services.add('heat') |
| 39 | services.add('neutron') |
| 40 | services.add('apache2') |
| 41 | } |
| 42 | openstack.stopServices(pepperEnv, probe, target, services) |
| 43 | } |
| 44 | |
| 45 | def retryStateRun(pepperEnv, target, state) { |
| 46 | def common = new com.mirantis.mk.Common() |
| 47 | def salt = new com.mirantis.mk.Salt() |
| 48 | try { |
| 49 | salt.enforceState(pepperEnv, target, state) |
| 50 | } catch (Exception e) { |
| 51 | common.warningMsg("running ${state} state again") |
| 52 | salt.enforceState(pepperEnv, target, state) |
| 53 | } |
| 54 | } |
| 55 | |
| 56 | def stateRun(pepperEnv, target, state) { |
| 57 | def common = new com.mirantis.mk.Common() |
| 58 | def salt = new com.mirantis.mk.Salt() |
| 59 | try { |
| 60 | salt.enforceState(pepperEnv, target, state) |
| 61 | } catch (Exception e) { |
| 62 | common.warningMsg("Some parts of ${state} state failed. We should continue to run.") |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | |
| 67 | def vcpTestUpgrade(pepperEnv) { |
| 68 | def common = new com.mirantis.mk.Common() |
| 69 | def salt = new com.mirantis.mk.Salt() |
| 70 | def test_upgrade_node = "upg01" |
| 71 | salt.runSaltProcessStep(pepperEnv, 'I@salt:master', 'saltutil.refresh_pillar', [], null, true, 2) |
| 72 | |
| 73 | stateRun(pepperEnv, 'I@salt:master', 'linux.system.repo') |
| 74 | stateRun(pepperEnv, 'I@salt:master', 'salt.master') |
| 75 | stateRun(pepperEnv, 'I@salt:master', 'reclass') |
| 76 | stateRun(pepperEnv, 'I@salt:master', 'linux.system.repo') |
| 77 | |
| 78 | try { |
| 79 | salt.runSaltProcessStep(pepperEnv, '*', 'saltutil.refresh_pillar', [], null, true, 2) |
| 80 | } catch (Exception e) { |
| 81 | common.warningMsg("No response from some minions. We should continue to run") |
| 82 | } |
| 83 | |
| 84 | try { |
| 85 | salt.runSaltProcessStep(pepperEnv, '*', 'saltutil.sync_all', [], null, true, 2) |
| 86 | } catch (Exception e) { |
| 87 | common.warningMsg("No response from some minions. We should continue to run") |
| 88 | } |
| 89 | |
| 90 | def domain = salt.getDomainName(pepperEnv) |
| 91 | |
| 92 | def backupninja_backup_host = salt.getReturnValues(salt.getPillar(pepperEnv, '( I@galera:master or I@galera:slave ) and I@backupninja:client', '_param:backupninja_backup_host')) |
| 93 | |
| 94 | if (SKIP_VM_RELAUNCH.toBoolean() == false) { |
| 95 | |
Jiri Broulik | 0d111e9 | 2018-04-25 21:30:42 +0200 | [diff] [blame] | 96 | def upgNodeProvider = getNodeProvider(pepperEnv, test_upgrade_node) |
Jiri Broulik | ed3a9e6 | 2018-02-13 16:08:40 +0100 | [diff] [blame] | 97 | |
| 98 | salt.runSaltProcessStep(pepperEnv, "${upgNodeProvider}", 'virt.destroy', ["${test_upgrade_node}.${domain}"]) |
| 99 | salt.runSaltProcessStep(pepperEnv, "${upgNodeProvider}", 'virt.undefine', ["${test_upgrade_node}.${domain}"]) |
| 100 | |
| 101 | try { |
| 102 | salt.cmdRun(pepperEnv, 'I@salt:master', "salt-key -d ${test_upgrade_node}.${domain} -y") |
| 103 | } catch (Exception e) { |
| 104 | common.warningMsg("${test_upgrade_node}.${domain} does not match any accepted, unaccepted or rejected keys. The key did not exist yet or was already removed. We should continue to run") |
| 105 | } |
| 106 | |
| 107 | // salt 'kvm02*' state.sls salt.control |
Jiri Broulik | 3818cb2 | 2018-04-27 18:39:00 +0200 | [diff] [blame] | 108 | stateRun(pepperEnv, "${upgNodeProvider}", 'salt.control') |
Jiri Broulik | ed3a9e6 | 2018-02-13 16:08:40 +0100 | [diff] [blame] | 109 | // wait until upg node is registered in salt-key |
| 110 | salt.minionPresent(pepperEnv, 'I@salt:master', test_upgrade_node) |
| 111 | // salt '*' saltutil.refresh_pillar |
| 112 | salt.runSaltProcessStep(pepperEnv, "${test_upgrade_node}*", 'saltutil.refresh_pillar', []) |
| 113 | // salt '*' saltutil.sync_all |
| 114 | salt.runSaltProcessStep(pepperEnv, "${test_upgrade_node}*", 'saltutil.sync_all', []) |
| 115 | } |
| 116 | |
Jiri Broulik | 827d011 | 2018-04-25 16:00:07 +0200 | [diff] [blame] | 117 | stateRun(pepperEnv, "${test_upgrade_node}*", ['linux.network.proxy']) |
| 118 | try { |
| 119 | salt.runSaltProcessStep(pepperEnv, "${test_upgrade_node}*", 'state.sls', ["salt.minion.base"], null, true, 60) |
| 120 | } catch (Exception e) { |
| 121 | common.warningMsg(e) |
| 122 | } |
| 123 | |
Jiri Broulik | ed3a9e6 | 2018-02-13 16:08:40 +0100 | [diff] [blame] | 124 | stateRun(pepperEnv, "${test_upgrade_node}*", ['linux', 'openssh']) |
| 125 | |
| 126 | try { |
Jiri Broulik | 827d011 | 2018-04-25 16:00:07 +0200 | [diff] [blame] | 127 | salt.runSaltProcessStep(pepperEnv, "${test_upgrade_node}*", 'state.sls', ["salt.minion"], null, true, 60) |
Jiri Broulik | ed3a9e6 | 2018-02-13 16:08:40 +0100 | [diff] [blame] | 128 | } catch (Exception e) { |
| 129 | common.warningMsg(e) |
| 130 | } |
| 131 | stateRun(pepperEnv, "${test_upgrade_node}*", ['ntp', 'rsyslog']) |
| 132 | salt.enforceState(pepperEnv, "${test_upgrade_node}*", ['linux', 'openssh', 'salt.minion', 'ntp', 'rsyslog']) |
| 133 | salt.enforceState(pepperEnv, "${test_upgrade_node}*", ['rabbitmq', 'memcached']) |
| 134 | try { |
| 135 | salt.enforceState(pepperEnv, '( I@galera:master or I@galera:slave ) and I@backupninja:client', ['openssh.client', 'salt.minion']) |
| 136 | } catch (Exception e) { |
| 137 | common.warningMsg('salt-minion was restarted. We should continue to run') |
| 138 | } |
Jiri Broulik | 3818cb2 | 2018-04-27 18:39:00 +0200 | [diff] [blame] | 139 | salt.runSaltProcessStep(master, '( I@galera:master or I@galera:slave ) and I@backupninja:client', 'saltutil.sync_grains') |
| 140 | salt.runSaltProcessStep(master, '( I@galera:master or I@galera:slave ) and I@backupninja:client', 'mine.flush') |
| 141 | salt.runSaltProcessStep(master, '( I@galera:master or I@galera:slave ) and I@backupninja:client', 'mine.update') |
| 142 | salt.enforceState(pepperEnv, '( I@galera:master or I@galera:slave ) and I@backupninja:client', 'backupninja') |
Jiri Broulik | ed3a9e6 | 2018-02-13 16:08:40 +0100 | [diff] [blame] | 143 | try { |
| 144 | salt.enforceState(pepperEnv, 'I@backupninja:server', ['salt.minion']) |
| 145 | } catch (Exception e) { |
| 146 | common.warningMsg('salt-minion was restarted. We should continue to run') |
| 147 | } |
Jiri Broulik | 3818cb2 | 2018-04-27 18:39:00 +0200 | [diff] [blame] | 148 | |
Jiri Broulik | ed3a9e6 | 2018-02-13 16:08:40 +0100 | [diff] [blame] | 149 | salt.enforceState(pepperEnv, 'I@backupninja:server', 'backupninja') |
Jiri Broulik | ed3a9e6 | 2018-02-13 16:08:40 +0100 | [diff] [blame] | 150 | salt.runSaltProcessStep(pepperEnv, '( I@galera:master or I@galera:slave ) and I@backupninja:client', 'ssh.rm_known_host', ["root", "${backupninja_backup_host}"]) |
| 151 | try { |
| 152 | salt.cmdRun(pepperEnv, '( I@galera:master or I@galera:slave ) and I@backupninja:client', "arp -d ${backupninja_backup_host}") |
| 153 | } catch (Exception e) { |
| 154 | common.warningMsg('The ARP entry does not exist. We should continue to run.') |
| 155 | } |
| 156 | salt.runSaltProcessStep(pepperEnv, '( I@galera:master or I@galera:slave ) and I@backupninja:client', 'ssh.set_known_host', ["root", "${backupninja_backup_host}"]) |
| 157 | salt.cmdRun(pepperEnv, '( I@galera:master or I@galera:slave ) and I@backupninja:client', 'backupninja -n --run /etc/backup.d/101.mysql') |
| 158 | salt.cmdRun(pepperEnv, '( I@galera:master or I@galera:slave ) and I@backupninja:client', 'backupninja -n --run /etc/backup.d/200.backup.rsync > /tmp/backupninjalog') |
| 159 | |
| 160 | salt.enforceState(pepperEnv, 'I@xtrabackup:server', 'xtrabackup') |
| 161 | salt.enforceState(pepperEnv, 'I@xtrabackup:client', 'openssh.client') |
| 162 | salt.cmdRun(pepperEnv, 'I@xtrabackup:client', "su root -c 'salt-call state.sls xtrabackup'") |
Jiri Broulik | 60dcab3 | 2018-03-08 17:42:06 +0100 | [diff] [blame] | 163 | salt.cmdRun(pepperEnv, 'I@xtrabackup:client', "su root -c '/usr/local/bin/innobackupex-runner.sh -f -s'") |
Jiri Broulik | ed3a9e6 | 2018-02-13 16:08:40 +0100 | [diff] [blame] | 164 | |
| 165 | def databases = salt.cmdRun(pepperEnv, 'I@mysql:client','salt-call mysql.db_list | grep upgrade | awk \'/-/ {print \$2}\'') |
| 166 | if(databases && databases != ""){ |
| 167 | def databasesList = salt.getReturnValues(databases).trim().tokenize("\n") |
| 168 | for( i = 0; i < databasesList.size(); i++){ |
| 169 | if(databasesList[i].toLowerCase().contains('upgrade')){ |
| 170 | salt.runSaltProcessStep(pepperEnv, 'I@mysql:client', 'mysql.db_remove', ["${databasesList[i]}"]) |
| 171 | common.warningMsg("removing database ${databasesList[i]}") |
| 172 | salt.runSaltProcessStep(pepperEnv, 'I@mysql:client', 'file.remove', ["/root/mysql/flags/${databasesList[i]}-installed"]) |
| 173 | } |
| 174 | } |
| 175 | salt.enforceState(pepperEnv, 'I@mysql:client', 'mysql.client') |
| 176 | }else{ |
| 177 | common.errorMsg("No _upgrade databases were returned") |
| 178 | } |
| 179 | |
| 180 | try { |
| 181 | salt.enforceState(pepperEnv, "${test_upgrade_node}*", 'keystone.server') |
| 182 | salt.runSaltProcessStep(pepperEnv, "${test_upgrade_node}*", 'service.restart', ['apache2']) |
| 183 | } catch (Exception e) { |
| 184 | common.warningMsg('Restarting Apache2') |
| 185 | salt.runSaltProcessStep(pepperEnv, "${test_upgrade_node}*", 'service.restart', ['apache2']) |
| 186 | } |
| 187 | retryStateRun(pepperEnv, "${test_upgrade_node}*", 'keystone.client') |
| 188 | retryStateRun(pepperEnv, "${test_upgrade_node}*", 'glance') |
| 189 | salt.enforceState(pepperEnv, "${test_upgrade_node}*", 'keystone.server') |
| 190 | |
| 191 | retryStateRun(pepperEnv, "${test_upgrade_node}*", 'nova') |
| 192 | retryStateRun(pepperEnv, "${test_upgrade_node}*", 'nova') // run nova state again as sometimes nova does not enforce itself for some reason |
| 193 | retryStateRun(pepperEnv, "${test_upgrade_node}*", 'cinder') |
| 194 | retryStateRun(pepperEnv, "${test_upgrade_node}*", 'neutron') |
| 195 | retryStateRun(pepperEnv, "${test_upgrade_node}*", 'heat') |
| 196 | |
| 197 | salt.cmdRun(pepperEnv, "${test_upgrade_node}*", '. /root/keystonercv3; openstack service list; openstack image list; openstack flavor list; openstack compute service list; openstack server list; openstack network list; openstack volume list; openstack orchestration service list') |
| 198 | |
Vasyl Saienko | 1a034dd | 2018-06-22 15:33:37 +0300 | [diff] [blame^] | 199 | if (INTERACTIVE.toBoolean() && STAGE_TEST_UPGRADE.toBoolean() == true && STAGE_REAL_UPGRADE.toBoolean() == true) { |
| 200 | stage('Ask for manual confirmation') { |
| 201 | input message: "Do you want to continue with upgrade?" |
| 202 | } |
Jiri Broulik | ed3a9e6 | 2018-02-13 16:08:40 +0100 | [diff] [blame] | 203 | } |
| 204 | } |
| 205 | |
| 206 | |
| 207 | def vcpRealUpgrade(pepperEnv) { |
| 208 | def common = new com.mirantis.mk.Common() |
| 209 | def salt = new com.mirantis.mk.Salt() |
| 210 | def openstack = new com.mirantis.mk.Openstack() |
| 211 | def virsh = new com.mirantis.mk.Virsh() |
| 212 | |
| 213 | def upgrade_target = [] |
| 214 | upgrade_target.add('I@horizon:server') |
| 215 | upgrade_target.add('I@keystone:server and not upg*') |
| 216 | |
| 217 | def proxy_general_target = "I@horizon:server" |
| 218 | def control_general_target = "I@keystone:server and not upg*" |
| 219 | def upgrade_general_target = "( I@keystone:server and not upg* ) or I@horizon:server" |
| 220 | |
| 221 | def snapshotName = "upgradeSnapshot1" |
| 222 | |
| 223 | def domain = salt.getDomainName(pepperEnv) |
| 224 | def errorOccured = false |
| 225 | |
| 226 | for (tgt in upgrade_target) { |
| 227 | def target_hosts = salt.getMinionsSorted(pepperEnv, "${tgt}") |
| 228 | def node = salt.getFirstMinion(pepperEnv, "${tgt}") |
| 229 | def general_target = "" |
| 230 | |
| 231 | if (tgt.toString().contains('horizon:server')) { |
| 232 | general_target = 'prx' |
| 233 | } else if (tgt.toString().contains('keystone:server')) { |
| 234 | general_target = 'ctl' |
| 235 | } |
| 236 | |
| 237 | if (OPERATING_SYSTEM_RELEASE_UPGRADE.toBoolean() == false) { |
| 238 | stopServices(pepperEnv, node, tgt, general_target) |
| 239 | } |
| 240 | |
Jiri Broulik | ed3a9e6 | 2018-02-13 16:08:40 +0100 | [diff] [blame] | 241 | for (t in target_hosts) { |
| 242 | def target = salt.stripDomainName(t) |
Jiri Broulik | caf721e | 2018-04-25 17:16:50 +0200 | [diff] [blame] | 243 | def nodeProvider = salt.getNodeProvider(pepperEnv, t) |
Jiri Broulik | ed3a9e6 | 2018-02-13 16:08:40 +0100 | [diff] [blame] | 244 | if ((OPERATING_SYSTEM_RELEASE_UPGRADE.toBoolean() == true) && (SKIP_VM_RELAUNCH.toBoolean() == false)) { |
| 245 | salt.runSaltProcessStep(pepperEnv, "${nodeProvider}", 'virt.destroy', ["${target}.${domain}"]) |
| 246 | sleep(2) |
| 247 | try { |
| 248 | salt.cmdRun(pepperEnv, "${nodeProvider}", "[ ! -f /root/${target}.${domain}.qcow2.bak ] && cp /var/lib/libvirt/images/${target}.${domain}/system.qcow2 ./${target}.${domain}.qcow2.bak") |
| 249 | } catch (Exception e) { |
| 250 | common.warningMsg('File already exists') |
| 251 | } |
| 252 | salt.runSaltProcessStep(pepperEnv, "${nodeProvider}", 'virt.undefine', ["${target}.${domain}"]) |
| 253 | try { |
| 254 | salt.cmdRun(pepperEnv, 'I@salt:master', "salt-key -d ${target}.${domain} -y") |
| 255 | } catch (Exception e) { |
| 256 | common.warningMsg('does not match any accepted, unaccepted or rejected keys. They were probably already removed. We should continue to run') |
| 257 | } |
| 258 | } else if (OPERATING_SYSTEM_RELEASE_UPGRADE.toBoolean() == false) { |
| 259 | virsh.liveSnapshotPresent(pepperEnv, nodeProvider, target, snapshotName) |
| 260 | } |
Jiri Broulik | ed3a9e6 | 2018-02-13 16:08:40 +0100 | [diff] [blame] | 261 | } |
| 262 | } |
| 263 | |
| 264 | if ((OPERATING_SYSTEM_RELEASE_UPGRADE.toBoolean() == true) && (SKIP_VM_RELAUNCH.toBoolean() == false)) { |
Jiri Broulik | 60dcab3 | 2018-03-08 17:42:06 +0100 | [diff] [blame] | 265 | salt.cmdRun(pepperEnv, 'I@xtrabackup:client', "su root -c '/usr/local/bin/innobackupex-runner.sh -f -s'") |
Jiri Broulik | ed3a9e6 | 2018-02-13 16:08:40 +0100 | [diff] [blame] | 266 | |
| 267 | salt.enforceState(pepperEnv, 'I@salt:control', 'salt.control') |
| 268 | |
| 269 | for (tgt in upgrade_target) { |
| 270 | salt.minionsPresent(pepperEnv, 'I@salt:master', tgt) |
| 271 | } |
| 272 | } |
| 273 | |
| 274 | // salt '*' saltutil.refresh_pillar |
| 275 | salt.runSaltProcessStep(pepperEnv, upgrade_general_target, 'saltutil.refresh_pillar', []) |
| 276 | // salt '*' saltutil.sync_all |
| 277 | salt.runSaltProcessStep(pepperEnv, upgrade_general_target, 'saltutil.sync_all', []) |
| 278 | |
Jiri Broulik | 827d011 | 2018-04-25 16:00:07 +0200 | [diff] [blame] | 279 | stateRun(pepperEnv, upgrade_general_target, ['linux.network.proxy']) |
| 280 | try { |
| 281 | salt.runSaltProcessStep(pepperEnv, upgrade_general_target, 'state.sls', ["salt.minion.base"], null, true, 60) |
| 282 | } catch (Exception e) { |
| 283 | common.warningMsg(e) |
| 284 | } |
| 285 | |
Jiri Broulik | ed3a9e6 | 2018-02-13 16:08:40 +0100 | [diff] [blame] | 286 | if (OPERATING_SYSTEM_RELEASE_UPGRADE.toBoolean() == false) { |
| 287 | |
| 288 | try { |
| 289 | salt.enforceState(pepperEnv, upgrade_general_target, ['linux.system.repo']) |
| 290 | } catch (Exception e) { |
| 291 | common.warningMsg(e) |
| 292 | } |
| 293 | |
| 294 | salt.runSaltProcessStep(pepperEnv, upgrade_general_target, 'pkg.install', ['salt-minion'], null, true, 5) |
| 295 | salt.minionsReachable(pepperEnv, 'I@salt:master', upgrade_general_target) |
| 296 | |
| 297 | // Apply package upgrades |
| 298 | args = 'export DEBIAN_FRONTEND=noninteractive; apt-get -y -q --allow-downgrades --allow-unauthenticated -o Dpkg::Options::=\"--force-confdef\" -o Dpkg::Options::=\"--force-confold\" dist-upgrade;' |
| 299 | common.warningMsg("Running apt dist-upgrade on ${proxy_general_target} and ${control_general_target}, this might take a while...") |
| 300 | out = salt.runSaltProcessStep(pepperEnv, upgrade_general_target, 'cmd.run', [args]) |
| 301 | // stop services again |
| 302 | def proxy_node = salt.getFirstMinion(pepperEnv, proxy_general_target) |
| 303 | def control_node = salt.getFirstMinion(pepperEnv, control_general_target) |
| 304 | stopServices(pepperEnv, proxy_node, proxy_general_target, 'prx') |
| 305 | stopServices(pepperEnv, control_node, control_general_target, 'ctl') |
| 306 | salt.printSaltCommandResult(out) |
Vasyl Saienko | 1a034dd | 2018-06-22 15:33:37 +0300 | [diff] [blame^] | 307 | if (out.toString().contains("dpkg returned an error code")){ |
| 308 | if (INTERACTIVE.toBoolean()) { |
| 309 | input message: "Apt dist-upgrade failed, please fix it manually and then click on proceed. If unable to fix it, click on abort and run the rollback stage." |
| 310 | } else { |
| 311 | error("Apt dist-upgrade failed. And interactive mode was disabled, failing...") |
| 312 | } |
Jiri Broulik | ed3a9e6 | 2018-02-13 16:08:40 +0100 | [diff] [blame] | 313 | } |
| 314 | // run base states |
| 315 | try { |
| 316 | salt.enforceState(pepperEnv, upgrade_general_target, ['linux', 'openssh', 'salt.minion', 'ntp', 'rsyslog']) |
| 317 | } catch (Exception e) { |
| 318 | common.warningMsg(e) |
| 319 | } |
| 320 | salt.enforceState(pepperEnv, control_general_target, ['keepalived', 'haproxy']) |
| 321 | } else { |
| 322 | // initial VM setup |
| 323 | try { |
| 324 | salt.enforceState(pepperEnv, upgrade_general_target, ['linux', 'openssh']) |
| 325 | } catch (Exception e) { |
| 326 | common.warningMsg(e) |
| 327 | } |
| 328 | try { |
Jiri Broulik | 827d011 | 2018-04-25 16:00:07 +0200 | [diff] [blame] | 329 | salt.runSaltProcessStep(pepperEnv, upgrade_general_target, 'state.sls', ["salt.minion"], null, true, 60) |
Jiri Broulik | ed3a9e6 | 2018-02-13 16:08:40 +0100 | [diff] [blame] | 330 | } catch (Exception e) { |
| 331 | common.warningMsg(e) |
| 332 | } |
| 333 | try { |
| 334 | salt.enforceState(pepperEnv, upgrade_general_target, ['ntp', 'rsyslog']) |
| 335 | } catch (Exception e) { |
| 336 | common.warningMsg(e) |
| 337 | } |
| 338 | salt.enforceState(pepperEnv, upgrade_general_target, ['linux', 'openssh', 'salt.minion', 'ntp', 'rsyslog']) |
| 339 | salt.enforceState(pepperEnv, control_general_target, ['keepalived', 'haproxy']) |
| 340 | salt.runSaltProcessStep(pepperEnv, control_general_target, 'service.restart', ['rsyslog']) |
| 341 | } |
| 342 | |
| 343 | try { |
| 344 | try { |
| 345 | salt.enforceState(pepperEnv, control_general_target, ['memcached', 'keystone.server']) |
| 346 | salt.runSaltProcessStep(pepperEnv, control_general_target, 'service.restart', ['apache2']) |
| 347 | } catch (Exception e) { |
| 348 | common.warningMsg('Restarting Apache2 and enforcing keystone.server state again') |
| 349 | salt.runSaltProcessStep(pepperEnv, control_general_target, 'service.restart', ['apache2']) |
| 350 | salt.enforceState(pepperEnv, control_general_target, 'keystone.server') |
| 351 | } |
| 352 | // salt 'ctl01*' state.sls keystone.client |
| 353 | retryStateRun(pepperEnv, "I@keystone:client and ${control_general_target}", 'keystone.client') |
| 354 | retryStateRun(pepperEnv, control_general_target, 'glance') |
| 355 | salt.enforceState(pepperEnv, control_general_target, 'glusterfs.client') |
| 356 | salt.enforceState(pepperEnv, control_general_target, 'keystone.server') |
| 357 | retryStateRun(pepperEnv, control_general_target, 'nova') |
| 358 | retryStateRun(pepperEnv, control_general_target, 'cinder') |
| 359 | retryStateRun(pepperEnv, control_general_target, 'neutron') |
| 360 | retryStateRun(pepperEnv, control_general_target, 'heat') |
| 361 | } catch (Exception e) { |
| 362 | errorOccured = true |
Vasyl Saienko | 1a034dd | 2018-06-22 15:33:37 +0300 | [diff] [blame^] | 363 | if (INTERACTIVE.toBoolean()){ |
| 364 | if (OPERATING_SYSTEM_RELEASE_UPGRADE.toBoolean() == false) { |
| 365 | input message: "Some states that require syncdb failed. Please check the reason. Click proceed only if you want to restore database into it's pre-upgrade state. If you want restore production database and also the VMs into its pre-upgrade state please click on abort and run the rollback stage." |
| 366 | } else { |
| 367 | input message: "Some states that require syncdb failed. Please check the reason and click proceed only if you want to restore database into it's pre-upgrade state. Otherwise, click abort." |
| 368 | } |
Jiri Broulik | ed3a9e6 | 2018-02-13 16:08:40 +0100 | [diff] [blame] | 369 | } else { |
Vasyl Saienko | 1a034dd | 2018-06-22 15:33:37 +0300 | [diff] [blame^] | 370 | error("Stage Real control upgrade failed. And interactive mode was disabled, failing...") |
Jiri Broulik | ed3a9e6 | 2018-02-13 16:08:40 +0100 | [diff] [blame] | 371 | } |
| 372 | openstack.restoreGaleraDb(pepperEnv) |
| 373 | common.errorMsg("Stage Real control upgrade failed") |
| 374 | } |
| 375 | if(!errorOccured){ |
| 376 | |
| 377 | if (OPERATING_SYSTEM_RELEASE_UPGRADE.toBoolean() == true) { |
| 378 | |
| 379 | try { |
| 380 | if (salt.testTarget(pepperEnv, "I@ceph:client and ${control_general_target}*")) { |
| 381 | salt.enforceState(pepperEnv, "I@ceph:client and ${control_general_target}*", 'ceph.client') |
| 382 | } |
| 383 | } catch (Exception er) { |
| 384 | common.warningMsg("Ceph client state on controllers failed. Please fix it manually") |
| 385 | } |
| 386 | try { |
| 387 | if (salt.testTarget(pepperEnv, "I@ceph:common and ${control_general_target}*")) { |
| 388 | salt.enforceState(pepperEnv, "I@ceph:common and ${control_general_target}*", ['ceph.common', 'ceph.setup.keyring']) |
| 389 | } |
| 390 | } catch (Exception er) { |
| 391 | common.warningMsg("Ceph common state on controllers failed. Please fix it manually") |
| 392 | } |
| 393 | try { |
| 394 | if (salt.testTarget(pepperEnv, "I@ceph:common and ${control_general_target}*")) { |
| 395 | salt.runSaltProcessStep(master, "I@ceph:common and ${control_general_target}*", 'service.restart', ['glance-api', 'glance-glare', 'glance-registry']) |
| 396 | } |
| 397 | } catch (Exception er) { |
| 398 | common.warningMsg("Restarting Glance services on controllers failed. Please fix it manually") |
| 399 | } |
| 400 | } |
| 401 | |
| 402 | // salt 'cmp*' cmd.run 'service nova-compute restart' |
| 403 | salt.runSaltProcessStep(pepperEnv, 'I@nova:compute', 'service.restart', ['nova-compute']) |
| 404 | salt.runSaltProcessStep(pepperEnv, control_general_target, 'service.restart', ['nova-conductor']) |
| 405 | salt.runSaltProcessStep(pepperEnv, control_general_target, 'service.restart', ['nova-scheduler']) |
| 406 | |
| 407 | retryStateRun(pepperEnv, proxy_general_target, 'keepalived') |
| 408 | retryStateRun(pepperEnv, proxy_general_target, 'horizon') |
| 409 | retryStateRun(pepperEnv, proxy_general_target, 'nginx') |
| 410 | retryStateRun(pepperEnv, proxy_general_target, 'memcached') |
| 411 | |
| 412 | try { |
| 413 | salt.enforceHighstate(pepperEnv, control_general_target) |
| 414 | } catch (Exception er) { |
| 415 | common.errorMsg("Highstate was executed on controller nodes but something failed. Please check it and fix it accordingly.") |
| 416 | } |
| 417 | |
| 418 | try { |
| 419 | salt.enforceHighstate(pepperEnv, proxy_general_target) |
| 420 | } catch (Exception er) { |
| 421 | common.errorMsg("Highstate was executed on proxy nodes but something failed. Please check it and fix it accordingly.") |
| 422 | } |
| 423 | |
| 424 | try { |
| 425 | salt.cmdRun(pepperEnv, "${control_general_target}01*", '. /root/keystonercv3; openstack service list; openstack image list; openstack flavor list; openstack compute service list; openstack server list; openstack network list; openstack volume list; openstack orchestration service list') |
| 426 | } catch (Exception er) { |
| 427 | common.errorMsg(er) |
| 428 | } |
| 429 | |
| 430 | /* |
| 431 | if (OPERATING_SYSTEM_RELEASE_UPGRADE.toBoolean() == false) { |
Vasyl Saienko | 1a034dd | 2018-06-22 15:33:37 +0300 | [diff] [blame^] | 432 | if (INTERACTIVE.toBoolean()){ |
| 433 | input message: "Please verify if the control upgrade was successful! If so, by clicking proceed the original VMs disk images will be backed up and snapshot will be merged to the upgraded VMs which will finalize the upgrade procedure" |
| 434 | } |
Jiri Broulik | ed3a9e6 | 2018-02-13 16:08:40 +0100 | [diff] [blame] | 435 | node_count = 1 |
| 436 | for (t in proxy_target_hosts) { |
| 437 | def target = salt.stripDomainName(t) |
| 438 | def nodeProvider = salt.getNodeProvider(pepperEnv, "${general_target}0${node_count}") |
| 439 | try { |
| 440 | salt.cmdRun(pepperEnv, "${nodeProvider}", "[ ! -f /root/${target}.${domain}.qcow2.bak ] && cp /var/lib/libvirt/images/${target}.${domain}/system.qcow2 ./${target}.${domain}.qcow2.bak") |
| 441 | } catch (Exception e) { |
| 442 | common.warningMsg('File already exists') |
| 443 | } |
| 444 | virsh.liveSnapshotMerge(pepperEnv, nodeProvider, target, snapshotName) |
| 445 | node_count++ |
| 446 | } |
| 447 | node_count = 1 |
| 448 | for (t in control_target_hosts) { |
| 449 | def target = salt.stripDomainName(t) |
| 450 | def nodeProvider = salt.getNodeProvider(pepperEnv, "${general_target}0${node_count}") |
| 451 | try { |
| 452 | salt.cmdRun(pepperEnv, "${nodeProvider}", "[ ! -f /root/${target}.${domain}.qcow2.bak ] && cp /var/lib/libvirt/images/${target}.${domain}/system.qcow2 ./${target}.${domain}.qcow2.bak") |
| 453 | } catch (Exception e) { |
| 454 | common.warningMsg('File already exists') |
| 455 | } |
| 456 | virsh.liveSnapshotMerge(pepperEnv, nodeProvider, target, snapshotName) |
| 457 | node_count++ |
| 458 | } |
Vasyl Saienko | 1a034dd | 2018-06-22 15:33:37 +0300 | [diff] [blame^] | 459 | if (INTERACTIVE.toBoolean()){ |
| 460 | input message: "Please scroll up and look for red highlighted messages containing 'virsh blockcommit' string. |
| 461 | If there are any fix it manually. Otherwise click on proceed." |
| 462 | } |
Jiri Broulik | ed3a9e6 | 2018-02-13 16:08:40 +0100 | [diff] [blame] | 463 | } |
| 464 | */ |
| 465 | } |
| 466 | } |
| 467 | |
| 468 | |
| 469 | def vcpRollback(pepperEnv) { |
| 470 | def common = new com.mirantis.mk.Common() |
| 471 | def salt = new com.mirantis.mk.Salt() |
| 472 | def openstack = new com.mirantis.mk.Openstack() |
| 473 | def virsh = new com.mirantis.mk.Virsh() |
| 474 | def snapshotName = "upgradeSnapshot1" |
| 475 | try { |
| 476 | salt.runSaltProcessStep(pepperEnv, '*', 'saltutil.refresh_pillar', [], null, true, 2) |
| 477 | } catch (Exception e) { |
| 478 | common.warningMsg("No response from some minions. We should continue to run") |
| 479 | } |
| 480 | |
| 481 | def domain = salt.getDomainName(pepperEnv) |
| 482 | |
| 483 | def rollback_target = [] |
| 484 | rollback_target.add('I@horizon:server') |
| 485 | rollback_target.add('I@keystone:server and not upg*') |
| 486 | |
| 487 | def control_general_target = "I@keystone:server and not upg*" |
| 488 | def upgrade_general_target = "( I@keystone:server and not upg* ) or I@horizon:server" |
| 489 | |
| 490 | openstack.restoreGaleraDb(pepperEnv) |
| 491 | |
| 492 | for (tgt in rollback_target) { |
| 493 | def target_hosts = salt.getMinionsSorted(pepperEnv, "${tgt}") |
| 494 | def node = salt.getFirstMinion(pepperEnv, "${tgt}") |
| 495 | def general_target = salt.getMinionsGeneralName(pepperEnv, "${tgt}") |
| 496 | |
| 497 | if (tgt.toString().contains('horizon:server')) { |
| 498 | general_target = 'prx' |
| 499 | } else if (tgt.toString().contains('keystone:server')) { |
| 500 | general_target = 'ctl' |
| 501 | } |
| 502 | |
Jiri Broulik | ed3a9e6 | 2018-02-13 16:08:40 +0100 | [diff] [blame] | 503 | for (t in target_hosts) { |
| 504 | def target = salt.stripDomainName(t) |
Jiri Broulik | caf721e | 2018-04-25 17:16:50 +0200 | [diff] [blame] | 505 | def nodeProvider = salt.getNodeProvider(pepperEnv, t) |
Jiri Broulik | ed3a9e6 | 2018-02-13 16:08:40 +0100 | [diff] [blame] | 506 | salt.runSaltProcessStep(pepperEnv, "${nodeProvider}", 'virt.destroy', ["${target}.${domain}"]) |
| 507 | sleep(2) |
| 508 | if (OPERATING_SYSTEM_RELEASE_UPGRADE.toBoolean() == true) { |
| 509 | salt.runSaltProcessStep(pepperEnv, "${nodeProvider}", 'file.copy', ["/root/${target}.${domain}.qcow2.bak", "/var/lib/libvirt/images/${target}.${domain}/system.qcow2"]) |
| 510 | try { |
| 511 | salt.cmdRun(pepperEnv, 'I@salt:master', "salt-key -d ${target}.${domain} -y") |
| 512 | } catch (Exception e) { |
| 513 | common.warningMsg('does not match any accepted, unaccepted or rejected keys. They were probably already removed. We should continue to run') |
| 514 | } |
| 515 | salt.runSaltProcessStep(pepperEnv, "${nodeProvider}", 'virt.start', ["${target}.${domain}"]) |
| 516 | } else { |
| 517 | salt.cmdRun(pepperEnv, "${nodeProvider}", "virsh define /var/lib/libvirt/images/${target}.${domain}.xml") |
| 518 | salt.runSaltProcessStep(pepperEnv, "${nodeProvider}", 'virt.start', ["${target}.${domain}"]) |
| 519 | virsh.liveSnapshotAbsent(pepperEnv, nodeProvider, target, snapshotName) |
| 520 | } |
Jiri Broulik | ed3a9e6 | 2018-02-13 16:08:40 +0100 | [diff] [blame] | 521 | } |
| 522 | } |
| 523 | |
| 524 | // salt 'cmp*' cmd.run 'service nova-compute restart' |
| 525 | salt.runSaltProcessStep(pepperEnv, 'I@nova:compute', 'service.restart', ['nova-compute']) |
| 526 | |
| 527 | if (OPERATING_SYSTEM_RELEASE_UPGRADE.toBoolean() == true) { |
| 528 | for (tgt in rollback_target) { |
| 529 | salt.minionsPresent(pepperEnv, 'I@salt:master', tgt) |
| 530 | } |
| 531 | } |
| 532 | |
| 533 | salt.minionsReachable(pepperEnv, 'I@salt:master', upgrade_general_target) |
| 534 | |
| 535 | salt.runSaltProcessStep(pepperEnv, control_general_target, 'service.restart', ['nova-conductor']) |
| 536 | salt.runSaltProcessStep(pepperEnv, control_general_target, 'service.restart', ['nova-scheduler']) |
| 537 | |
| 538 | def control_node = salt.getFirstMinion(pepperEnv, control_general_target) |
| 539 | |
| 540 | salt.cmdRun(pepperEnv, "${control_node}*", '. /root/keystonerc; nova service-list; glance image-list; nova flavor-list; nova hypervisor-list; nova list; neutron net-list; cinder list; heat service-list') |
| 541 | } |
| 542 | |
| 543 | |
chnyda | 625f4b4 | 2017-10-11 14:10:31 +0200 | [diff] [blame] | 544 | def pepperEnv = "pepperEnv" |
Jakub Josef | a63f986 | 2018-01-11 17:58:38 +0100 | [diff] [blame] | 545 | timeout(time: 12, unit: 'HOURS') { |
| 546 | node() { |
Jiri Broulik | bb447ac | 2017-05-04 15:36:22 +0200 | [diff] [blame] | 547 | |
Jakub Josef | a63f986 | 2018-01-11 17:58:38 +0100 | [diff] [blame] | 548 | stage('Setup virtualenv for Pepper') { |
| 549 | python.setupPepperVirtualenv(pepperEnv, SALT_MASTER_URL, SALT_MASTER_CREDENTIALS) |
| 550 | } |
Jiri Broulik | bb447ac | 2017-05-04 15:36:22 +0200 | [diff] [blame] | 551 | |
Jakub Josef | a63f986 | 2018-01-11 17:58:38 +0100 | [diff] [blame] | 552 | if (STAGE_TEST_UPGRADE.toBoolean() == true) { |
| 553 | stage('Test upgrade') { |
Jiri Broulik | ed3a9e6 | 2018-02-13 16:08:40 +0100 | [diff] [blame] | 554 | vcpTestUpgrade(pepperEnv) |
Ruslan Kamaldinov | 6feef40 | 2017-08-02 16:55:58 +0400 | [diff] [blame] | 555 | } |
| 556 | } |
Ruslan Kamaldinov | 6feef40 | 2017-08-02 16:55:58 +0400 | [diff] [blame] | 557 | |
Jakub Josef | a63f986 | 2018-01-11 17:58:38 +0100 | [diff] [blame] | 558 | if (STAGE_REAL_UPGRADE.toBoolean() == true) { |
| 559 | stage('Real upgrade') { |
| 560 | // # actual upgrade |
Jiri Broulik | ed3a9e6 | 2018-02-13 16:08:40 +0100 | [diff] [blame] | 561 | vcpRealUpgrade(pepperEnv) |
Jakub Josef | a63f986 | 2018-01-11 17:58:38 +0100 | [diff] [blame] | 562 | } |
| 563 | |
Vasyl Saienko | 1a034dd | 2018-06-22 15:33:37 +0300 | [diff] [blame^] | 564 | if (INTERACTIVE.toBoolean() && STAGE_REAL_UPGRADE.toBoolean() == true && STAGE_ROLLBACK_UPGRADE.toBoolean() == true) { |
Jakub Josef | a63f986 | 2018-01-11 17:58:38 +0100 | [diff] [blame] | 565 | stage('Ask for manual confirmation') { |
Jiri Broulik | ed3a9e6 | 2018-02-13 16:08:40 +0100 | [diff] [blame] | 566 | input message: "Please verify if the control upgrade was successful. If it did not succeed, in the worst scenario, you can click on proceed to continue with control-upgrade-rollback. Do you want to continue with the rollback?" |
Jakub Josef | a63f986 | 2018-01-11 17:58:38 +0100 | [diff] [blame] | 567 | } |
| 568 | } |
| 569 | } |
| 570 | |
| 571 | if (STAGE_ROLLBACK_UPGRADE.toBoolean() == true) { |
| 572 | stage('Rollback upgrade') { |
Vasyl Saienko | 1a034dd | 2018-06-22 15:33:37 +0300 | [diff] [blame^] | 573 | if (INTERACTIVE.toBoolean()){ |
| 574 | stage('Ask for manual confirmation') { |
Jiri Broulik | ed3a9e6 | 2018-02-13 16:08:40 +0100 | [diff] [blame] | 575 | input message: "Before rollback please check the documentation for reclass model changes. Do you really want to continue with the rollback?" |
Vasyl Saienko | 1a034dd | 2018-06-22 15:33:37 +0300 | [diff] [blame^] | 576 | } |
Jakub Josef | a63f986 | 2018-01-11 17:58:38 +0100 | [diff] [blame] | 577 | } |
Jiri Broulik | ed3a9e6 | 2018-02-13 16:08:40 +0100 | [diff] [blame] | 578 | vcpRollback(pepperEnv) |
Ruslan Kamaldinov | 6feef40 | 2017-08-02 16:55:58 +0400 | [diff] [blame] | 579 | } |
| 580 | } |
| 581 | } |
Vasyl Saienko | 1a034dd | 2018-06-22 15:33:37 +0300 | [diff] [blame^] | 582 | } |