blob: d972d915c937862fbbc04e1369ec58b61185bc50 [file] [log] [blame]
Jiri Broulikf8f96942018-02-15 10:03:42 +01001package com.mirantis.mk
2
3/**
4 *
5 * Virsh functions
6 *
7 */
8
9/**
10 * Ensures that the live snapshot exists
11 *
12 * @param nodeProvider KVM node that hosts the VM
13 * @param target Unique identification of the VM being snapshoted without domain (for ex. ctl01)
14 * @param snapshotName Snapshot name
15 * @param path Path where snapshot image and dumpxml are being put
16 * @param diskName Disk name of the snapshot
17 */
18def liveSnapshotPresent(master, nodeProvider, target, snapshotName, path='/var/lib/libvirt/images', diskName='vda') {
19 def salt = new com.mirantis.mk.Salt()
20 def common = new com.mirantis.mk.Common()
21 def snapshotPresent = ""
22 def domain = salt.getDomainName(master)
23 try {
24 snapshotPresent = salt.getReturnValues(salt.cmdRun(master, "${nodeProvider}*", "virsh snapshot-list ${target}.${domain} | grep ${snapshotName}")).split("\n")[0]
25 } catch (Exception er) {
26 common.infoMsg('snapshot not present')
27 }
28 if (!snapshotPresent.contains(snapshotName)) {
29 def dumpxmlPresent = ''
30 try {
31 dumpxmlPresent = salt.getReturnValues(salt.cmdRun(master, "${nodeProvider}*", "ls -la ${path}/${target}.${domain}.xml")).split("\n")[0]
32 } catch (Exception er) {
33 common.infoMsg('dumpxml file not present')
34 }
35 if (!dumpxmlPresent?.trim()) {
36 salt.cmdRun(master, "${nodeProvider}*", "virsh dumpxml ${target}.${domain} > ${path}/${target}.${domain}.xml")
37 }
38 salt.cmdRun(master, "${nodeProvider}*", "virsh snapshot-create-as --domain ${target}.${domain} ${snapshotName} --diskspec ${diskName},file=${path}/${target}.${domain}.${snapshotName}.qcow2 --disk-only --atomic")
39 }
40}
41
42/**
43 * Ensures that the live snapshot does not exist
44 *
45 * @param nodeProvider KVM node that hosts the VM
46 * @param target Unique identification of the VM being snapshoted without domain (for ex. ctl01)
47 * @param snapshotName Snapshot name
48 * @param path Path where snapshot image and dumpxml are being put
49 */
50def liveSnapshotAbsent(master, nodeProvider, target, snapshotName, path='/var/lib/libvirt/images') {
51 def salt = new com.mirantis.mk.Salt()
52 def common = new com.mirantis.mk.Common()
53 def domain = salt.getDomainName(master)
54 try {
55 salt.cmdRun(master, "${nodeProvider}*", "virsh snapshot-delete ${target}.${domain} --metadata ${snapshotName}")
56 } catch (Exception e) {
Jiri Broulikd2a50552018-04-25 17:17:59 +020057 common.warningMsg("Snapshot ${snapshotName} for ${target}.${domain} does not exist or failed to be removed")
Jiri Broulikf8f96942018-02-15 10:03:42 +010058 }
59 try {
60 salt.runSaltProcessStep(master, "${nodeProvider}*", 'file.remove', ["${path}/${target}.${domain}.${snapshotName}.qcow2"], null, true)
61 } catch (Exception e) {
Jiri Broulikd2a50552018-04-25 17:17:59 +020062 common.warningMsg("Snapshot ${snapshotName} qcow2 file for ${target}.${domain} does not exist or failed to be removed")
Jiri Broulikf8f96942018-02-15 10:03:42 +010063 }
64 try {
65 salt.runSaltProcessStep(master, "${nodeProvider}*", 'file.remove', ["${path}/${target}.${domain}.xml"], null, true)
66 } catch (Exception e) {
Jiri Broulikd2a50552018-04-25 17:17:59 +020067 common.warningMsg("Dumpxml file for ${target}.${domain} does not exist or failed to be removed")
Jiri Broulikf8f96942018-02-15 10:03:42 +010068 }
69}
70
71/**
72 * Rollback
73 *
74 * @param nodeProvider KVM node that hosts the VM
75 * @param target Unique identification of the VM being snapshoted without domain (for ex. ctl01)
76 * @param snapshotName Snapshot name
77 * @param path Path where snapshot image and dumpxml are being put
78 */
79def liveSnapshotRollback(master, nodeProvider, target, snapshotName, path='/var/lib/libvirt/images') {
80 def salt = new com.mirantis.mk.Salt()
81 def common = new com.mirantis.mk.Common()
82 def domain = salt.getDomainName(master)
Jiri Broulik504cceb2018-02-22 13:26:49 +010083 try {
84 salt.getReturnValues(salt.cmdRun(master, "${nodeProvider}*", "ls -la ${path}/${target}.${domain}.xml"))
85 salt.runSaltProcessStep(master, "${nodeProvider}*", 'virt.destroy', ["${target}.${domain}"], null, true)
86 salt.cmdRun(master, "${nodeProvider}*", "virsh define ${path}/${target}.${domain}.xml")
87 liveSnapshotAbsent(master, nodeProvider, target, snapshotName, path)
88 salt.runSaltProcessStep(master, "${nodeProvider}*", 'virt.start', ["${target}.${domain}"], null, true)
89 } catch (Exception er) {
Jiri Broulikd2a50552018-04-25 17:17:59 +020090 common.infoMsg("No rollback for ${target}.${domain} was executed. Dumpxml file not present.")
Jiri Broulik504cceb2018-02-22 13:26:49 +010091 }
Jiri Broulikf8f96942018-02-15 10:03:42 +010092}
93
94/**
95 * Merge snapshot while instance is running
96 *
97 * @param nodeProvider KVM node that hosts the VM
98 * @param target Unique identification of the VM being snapshoted without domain (for ex. ctl01)
99 * @param snapshotName Snapshot name
100 * @param path Path where snapshot image and dumpxml are being put
101 * @param diskName Disk name of the snapshot
102 */
103def liveSnapshotMerge(master, nodeProvider, target, snapshotName, path='/var/lib/libvirt/images', diskName='vda') {
104 def salt = new com.mirantis.mk.Salt()
105 def common = new com.mirantis.mk.Common()
106 def domain = salt.getDomainName(master)
107 try {
Jiri Broulik743c0ab2018-02-15 14:32:03 +0100108 salt.cmdRun(master, "${nodeProvider}*", "virsh blockcommit ${target}.${domain} ${diskName} --active --verbose --pivot")
Jiri Broulikf8f96942018-02-15 10:03:42 +0100109 try {
Jiri Broulik743c0ab2018-02-15 14:32:03 +0100110 salt.cmdRun(master, "${nodeProvider}*", "virsh snapshot-delete ${target}.${domain} --metadata ${snapshotName}")
Jiri Broulikf8f96942018-02-15 10:03:42 +0100111 } catch (Exception e) {
Jiri Broulikd2a50552018-04-25 17:17:59 +0200112 common.warningMsg("Snapshot ${snapshotName} for ${target}.${domain} does not exist or failed to be removed")
Jiri Broulikf8f96942018-02-15 10:03:42 +0100113 }
114 try {
Jiri Broulik743c0ab2018-02-15 14:32:03 +0100115 salt.runSaltProcessStep(master, "${nodeProvider}*", 'file.remove', ["${path}/${target}.${domain}.${snapshotName}.qcow2"], null, true)
Jiri Broulikf8f96942018-02-15 10:03:42 +0100116 } catch (Exception e) {
Jiri Broulikd2a50552018-04-25 17:17:59 +0200117 common.warningMsg("Snapshot ${snapshotName} qcow2 file for ${target}.${domain} does not exist or failed to be removed")
Jiri Broulikf8f96942018-02-15 10:03:42 +0100118 }
119 try {
Jiri Broulik743c0ab2018-02-15 14:32:03 +0100120 salt.runSaltProcessStep(master, "${nodeProvider}*", 'file.remove', ["${path}/${target}.${domain}.xml"], null, true)
Jiri Broulikf8f96942018-02-15 10:03:42 +0100121 } catch (Exception e) {
Jiri Broulikd2a50552018-04-25 17:17:59 +0200122 common.warningMsg("Dumpxml file for ${target}.${domain} does not exist or failed to be removed")
Jiri Broulikf8f96942018-02-15 10:03:42 +0100123 }
124 } catch (Exception e) {
125 common.errorMsg("The live snapshoted VM ${target}.${domain} failed to be merged, trying to fix it")
126 checkLiveSnapshotMerge(master, nodeProvider, target, snapshotName, path, diskName)
127 }
128}
129
130
131/**
132 * Check live snapshot merge failure due to known qemu issue not receiving message about merge completion
133 *
134 * @param nodeProvider KVM node that hosts the VM
135 * @param target Unique identification of the VM being snapshoted without domain (for ex. ctl01)
136 * @param snapshotName Snapshot name
137 * @param path Path where snapshot image and dumpxml are being put
138 * @param diskName Disk name of the snapshot
139 */
140def checkLiveSnapshotMerge(master, nodeProvider, target, snapshotName, path='/var/lib/libvirt/images', diskName='vda') {
141 def salt = new com.mirantis.mk.Salt()
142 def domain = salt.getDomainName(master)
Jiri Broulik743c0ab2018-02-15 14:32:03 +0100143 def out = salt.getReturnValues(salt.cmdRun(master, "${nodeProvider}*", "virsh blockjob ${target}.${domain} ${diskName} --info"))
Jiri Broulikf8f96942018-02-15 10:03:42 +0100144 if (out.contains('Block Commit')) {
Jiri Broulik743c0ab2018-02-15 14:32:03 +0100145 def blockJobs = salt.getReturnValues(salt.cmdRun(master, "{nodeProvider}*", "virsh qemu-monitor-command ${target}.${domain} --pretty -- '{ \"execute\": \"query-block-jobs\" }'"))
Jiri Broulikf8f96942018-02-15 10:03:42 +0100146 if (blockJobs.contains('offset')) {
147 // if Block Commit hangs on 100 and check offset - len = 0, then it is safe to merge the image
148 input message: "Please check if offset - len = 0, If so run: virsh qemu-monitor-command ${target}.${domain} --pretty -- '{ \"execute\": \"block-job-complete\", \"arguments\": { \"device\": \"drive-virtio-disk0\" } }', then virsh define ${path}/${target}.${domain}.xml, then virsh snapshot-delete ${target}.${domain} --metadata ${snapshotName} and remove ${path}/${target}.${domain}.${snapshotName}.qcow2 file. When you resolve this issue click on PROCEED."
149 }
150 }
151}
152