blob: d972d915c937862fbbc04e1369ec58b61185bc50 [file] [log] [blame]
package com.mirantis.mk
/**
*
* Virsh functions
*
*/
/**
* Ensures that the live snapshot exists
*
* @param nodeProvider KVM node that hosts the VM
* @param target Unique identification of the VM being snapshoted without domain (for ex. ctl01)
* @param snapshotName Snapshot name
* @param path Path where snapshot image and dumpxml are being put
* @param diskName Disk name of the snapshot
*/
def liveSnapshotPresent(master, nodeProvider, target, snapshotName, path='/var/lib/libvirt/images', diskName='vda') {
def salt = new com.mirantis.mk.Salt()
def common = new com.mirantis.mk.Common()
def snapshotPresent = ""
def domain = salt.getDomainName(master)
try {
snapshotPresent = salt.getReturnValues(salt.cmdRun(master, "${nodeProvider}*", "virsh snapshot-list ${target}.${domain} | grep ${snapshotName}")).split("\n")[0]
} catch (Exception er) {
common.infoMsg('snapshot not present')
}
if (!snapshotPresent.contains(snapshotName)) {
def dumpxmlPresent = ''
try {
dumpxmlPresent = salt.getReturnValues(salt.cmdRun(master, "${nodeProvider}*", "ls -la ${path}/${target}.${domain}.xml")).split("\n")[0]
} catch (Exception er) {
common.infoMsg('dumpxml file not present')
}
if (!dumpxmlPresent?.trim()) {
salt.cmdRun(master, "${nodeProvider}*", "virsh dumpxml ${target}.${domain} > ${path}/${target}.${domain}.xml")
}
salt.cmdRun(master, "${nodeProvider}*", "virsh snapshot-create-as --domain ${target}.${domain} ${snapshotName} --diskspec ${diskName},file=${path}/${target}.${domain}.${snapshotName}.qcow2 --disk-only --atomic")
}
}
/**
* Ensures that the live snapshot does not exist
*
* @param nodeProvider KVM node that hosts the VM
* @param target Unique identification of the VM being snapshoted without domain (for ex. ctl01)
* @param snapshotName Snapshot name
* @param path Path where snapshot image and dumpxml are being put
*/
def liveSnapshotAbsent(master, nodeProvider, target, snapshotName, path='/var/lib/libvirt/images') {
def salt = new com.mirantis.mk.Salt()
def common = new com.mirantis.mk.Common()
def domain = salt.getDomainName(master)
try {
salt.cmdRun(master, "${nodeProvider}*", "virsh snapshot-delete ${target}.${domain} --metadata ${snapshotName}")
} catch (Exception e) {
common.warningMsg("Snapshot ${snapshotName} for ${target}.${domain} does not exist or failed to be removed")
}
try {
salt.runSaltProcessStep(master, "${nodeProvider}*", 'file.remove', ["${path}/${target}.${domain}.${snapshotName}.qcow2"], null, true)
} catch (Exception e) {
common.warningMsg("Snapshot ${snapshotName} qcow2 file for ${target}.${domain} does not exist or failed to be removed")
}
try {
salt.runSaltProcessStep(master, "${nodeProvider}*", 'file.remove', ["${path}/${target}.${domain}.xml"], null, true)
} catch (Exception e) {
common.warningMsg("Dumpxml file for ${target}.${domain} does not exist or failed to be removed")
}
}
/**
* Rollback
*
* @param nodeProvider KVM node that hosts the VM
* @param target Unique identification of the VM being snapshoted without domain (for ex. ctl01)
* @param snapshotName Snapshot name
* @param path Path where snapshot image and dumpxml are being put
*/
def liveSnapshotRollback(master, nodeProvider, target, snapshotName, path='/var/lib/libvirt/images') {
def salt = new com.mirantis.mk.Salt()
def common = new com.mirantis.mk.Common()
def domain = salt.getDomainName(master)
try {
salt.getReturnValues(salt.cmdRun(master, "${nodeProvider}*", "ls -la ${path}/${target}.${domain}.xml"))
salt.runSaltProcessStep(master, "${nodeProvider}*", 'virt.destroy', ["${target}.${domain}"], null, true)
salt.cmdRun(master, "${nodeProvider}*", "virsh define ${path}/${target}.${domain}.xml")
liveSnapshotAbsent(master, nodeProvider, target, snapshotName, path)
salt.runSaltProcessStep(master, "${nodeProvider}*", 'virt.start', ["${target}.${domain}"], null, true)
} catch (Exception er) {
common.infoMsg("No rollback for ${target}.${domain} was executed. Dumpxml file not present.")
}
}
/**
* Merge snapshot while instance is running
*
* @param nodeProvider KVM node that hosts the VM
* @param target Unique identification of the VM being snapshoted without domain (for ex. ctl01)
* @param snapshotName Snapshot name
* @param path Path where snapshot image and dumpxml are being put
* @param diskName Disk name of the snapshot
*/
def liveSnapshotMerge(master, nodeProvider, target, snapshotName, path='/var/lib/libvirt/images', diskName='vda') {
def salt = new com.mirantis.mk.Salt()
def common = new com.mirantis.mk.Common()
def domain = salt.getDomainName(master)
try {
salt.cmdRun(master, "${nodeProvider}*", "virsh blockcommit ${target}.${domain} ${diskName} --active --verbose --pivot")
try {
salt.cmdRun(master, "${nodeProvider}*", "virsh snapshot-delete ${target}.${domain} --metadata ${snapshotName}")
} catch (Exception e) {
common.warningMsg("Snapshot ${snapshotName} for ${target}.${domain} does not exist or failed to be removed")
}
try {
salt.runSaltProcessStep(master, "${nodeProvider}*", 'file.remove', ["${path}/${target}.${domain}.${snapshotName}.qcow2"], null, true)
} catch (Exception e) {
common.warningMsg("Snapshot ${snapshotName} qcow2 file for ${target}.${domain} does not exist or failed to be removed")
}
try {
salt.runSaltProcessStep(master, "${nodeProvider}*", 'file.remove', ["${path}/${target}.${domain}.xml"], null, true)
} catch (Exception e) {
common.warningMsg("Dumpxml file for ${target}.${domain} does not exist or failed to be removed")
}
} catch (Exception e) {
common.errorMsg("The live snapshoted VM ${target}.${domain} failed to be merged, trying to fix it")
checkLiveSnapshotMerge(master, nodeProvider, target, snapshotName, path, diskName)
}
}
/**
* Check live snapshot merge failure due to known qemu issue not receiving message about merge completion
*
* @param nodeProvider KVM node that hosts the VM
* @param target Unique identification of the VM being snapshoted without domain (for ex. ctl01)
* @param snapshotName Snapshot name
* @param path Path where snapshot image and dumpxml are being put
* @param diskName Disk name of the snapshot
*/
def checkLiveSnapshotMerge(master, nodeProvider, target, snapshotName, path='/var/lib/libvirt/images', diskName='vda') {
def salt = new com.mirantis.mk.Salt()
def domain = salt.getDomainName(master)
def out = salt.getReturnValues(salt.cmdRun(master, "${nodeProvider}*", "virsh blockjob ${target}.${domain} ${diskName} --info"))
if (out.contains('Block Commit')) {
def blockJobs = salt.getReturnValues(salt.cmdRun(master, "{nodeProvider}*", "virsh qemu-monitor-command ${target}.${domain} --pretty -- '{ \"execute\": \"query-block-jobs\" }'"))
if (blockJobs.contains('offset')) {
// if Block Commit hangs on 100 and check offset - len = 0, then it is safe to merge the image
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."
}
}
}