Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix virt module to undefine a domain with nvram or other metadata #136

Merged
merged 1 commit into from
Aug 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions changelogs/fragments/136_fix_undefine_nvram.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
bugfixes:
- virt - fix virt module to undefine a domain with nvram, managed_save, snapshot_metadata or checkpoints_metadata (https://github.com/ansible-collections/community.libvirt/issues/40).
94 changes: 90 additions & 4 deletions plugins/modules/virt.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,29 @@
short_description: Manages virtual machines supported by libvirt
description:
- Manages virtual machines supported by I(libvirt).
options:
flags:
choices: [ 'managed_save', 'snapshots_metadata', 'nvram', 'keep_nvram', 'checkpoints_metadata']
description:
- Pass additional parameters.
- Currently only implemented with command C(undefine).
Specify which metadata should be removed with C(undefine).
Useful option to be able to C(undefine) guests with UEFI nvram.
C(nvram) and C(keep_nvram) are conflicting and mutually exclusive.
Consider option C(force) if all related metadata should be removed.
type: list
elements: str
force:
description:
- Enforce an action.
- Currently only implemented with command C(undefine).
This option can be used instead of providing all C(flags).
If C(yes), C(undefine) removes also any related nvram or other metadata, if existing.
If C(no) or not set, C(undefine) executes only if there is no nvram or other metadata existing.
Otherwise the task fails and the guest is kept defined without change.
C(yes) and option C(flags) should not be provided together. In this case
C(undefine) ignores C(yes), considers only C(flags) and issues a warning.
type: bool
extends_documentation_fragment:
- community.libvirt.virt.options_uri
- community.libvirt.virt.options_xml
Expand Down Expand Up @@ -67,6 +90,30 @@
xml: "{{ lookup('template', 'vm_template.xml.j2') }}"
autostart: yes

# Undefine VM only, if it has no existing nvram or other metadata
- name: Undefine qemu VM
community.libvirt.virt:
name: foo

# Undefine VM and force remove all of its related metadata (nvram, snapshots, etc.)
- name: "Undefine qemu VM with force"
community.libvirt.virt:
name: foo
force: yes

# Undefine VM and remove all of its specified metadata specified
# Result would the same as with force=true
- name: Undefine qemu VM with list of flags
community.libvirt.virt:
name: foo
flags: managed_save, snapshots_metadata, nvram, checkpoints_metadata

# Undefine VM, but keep its nvram
- name: Undefine qemu VM and keep its nvram
community.libvirt.virt:
name: foo
flags: keep_nvram

# Listing VMs
- name: List all VMs
community.libvirt.virt:
Expand Down Expand Up @@ -134,6 +181,17 @@
6: 'crashed',
}

ENTRY_UNDEFINE_FLAGS_MAP = {
'managed_save': 1,
'snapshots_metadata': 2,
'nvram': 4,
'keep_nvram': 8,
'checkpoints_metadata': 16,
}

ALL_FLAGS = []
ALL_FLAGS.extend(ENTRY_UNDEFINE_FLAGS_MAP.keys())


class VMNotFound(Exception):
pass
Expand Down Expand Up @@ -198,8 +256,8 @@ def create(self, vmid):
def destroy(self, vmid):
return self.find_vm(vmid).destroy()

def undefine(self, vmid):
return self.find_vm(vmid).undefine()
def undefine(self, vmid, flag):
return self.find_vm(vmid).undefineFlags(flag)

def get_status2(self, vm):
state = vm.info()[0]
Expand Down Expand Up @@ -367,11 +425,11 @@ def destroy(self, vmid):
self.__get_conn()
return self.conn.destroy(vmid)

def undefine(self, vmid):
def undefine(self, vmid, flag):
""" Stop a domain, and then wipe it from the face of the earth. (delete disk/config file) """

self.__get_conn()
return self.conn.undefine(vmid)
return self.conn.undefine(vmid, flag)

def status(self, vmid):
"""
Expand Down Expand Up @@ -419,6 +477,8 @@ def core(module):
autostart = module.params.get('autostart', None)
guest = module.params.get('name', None)
command = module.params.get('command', None)
force = module.params.get('force', None)
flags = module.params.get('flags', None)
uri = module.params.get('uri', None)
xml = module.params.get('xml', None)

Expand Down Expand Up @@ -513,6 +573,30 @@ def core(module):

elif not guest:
module.fail_json(msg="%s requires 1 argument: guest" % command)

elif command == 'undefine':
# Use the undefine function with flag to also handle various metadata.
# This is especially important for UEFI enabled guests with nvram.
# Provide flag as an integer of all desired bits, see 'ENTRY_UNDEFINE_FLAGS_MAP'.
# Integer 23 takes care of all cases (23 = 1 + 2 + 4 + 16).
flag = 0
if flags is not None:
if force is True:
module.warn("Ignoring 'force', because 'flags' are provided.")
nv = ['nvram', 'keep_nvram']
# Check mutually exclusive flags
if set(nv) <= set(flags):
raise ValueError("Flags '%s' are mutually exclusive" % "' and '".join(nv))
for item in flags:
# Get and add flag integer from mapping, otherwise 0.
flag += ENTRY_UNDEFINE_FLAGS_MAP.get(item, 0)
elif force is True:
flag = 23
# Finally, execute with flag
res = getattr(v, command)(guest, flag)
if not isinstance(res, dict):
res = {command: res}

else:
res = getattr(v, command)(guest)
if not isinstance(res, dict):
Expand All @@ -539,6 +623,8 @@ def main():
state=dict(type='str', choices=['destroyed', 'paused', 'running', 'shutdown']),
autostart=dict(type='bool'),
command=dict(type='str', choices=ALL_COMMANDS),
flags=dict(type='list', elements='str', choices=ALL_FLAGS),
force=dict(type='bool'),
uri=dict(type='str', default='qemu:///system'),
xml=dict(type='str'),
),
Expand Down