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

Proxmox Inventory: added new statuses for qemu #4723

Merged
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
3 changes: 3 additions & 0 deletions changelogs/fragments/4724-proxmox-qemu-extend.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
minor_changes:
- proxmox inventory plugin - added new flag ``qemu_extended_statuses`` and new groups ``<group_prefix>prelaunch``, ``<group_prefix>paused``. They will be populated only when ``want_facts=true``, ``qemu_extended_statuses=true`` and only for ``QEMU`` machines
(https://github.com/ansible-collections/community.general/pull/4723).
44 changes: 34 additions & 10 deletions plugins/inventory/proxmox.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,21 @@
default: proxmox_
type: str
want_facts:
description: Gather LXC/QEMU configuration facts.
description:
- Gather LXC/QEMU configuration facts.
- When I(want_facts) is set to C(true) more details about QEMU VM status are possible, besides the running and stopped states.
Currently if the VM is running and it is suspended, the status will be running and the machine will be in C(running) group,
but its actual state will be paused. See I(qemu_extended_statuses) for how to retrieve the real status.
default: no
type: bool
qemu_extended_statuses:
description:
- Requires I(want_facts) to be set to C(true) to function. This will allow you to differentiate betweend C(paused) and C(prelaunch)
statuses of the QEMU VMs.
- This introduces multiple groups [prefixed with I(group_prefix)] C(prelaunch) and C(paused).
default: no
type: bool
ilijamt marked this conversation as resolved.
Show resolved Hide resolved
version_added: 5.1.0
want_proxmox_nodes_ansible_host:
version_added: 3.0.0
description:
Expand Down Expand Up @@ -431,6 +443,7 @@ def _get_vm_config(self, properties, node, vmid, vmtype, name):
def _get_vm_status(self, properties, node, vmid, vmtype, name):
ret = self._get_json("%s/api2/json/nodes/%s/%s/%s/status/current" % (self.proxmox_url, node, vmtype, vmid))
properties[self._fact('status')] = ret['status']
properties[self._fact('qmpstatus')] = ret['qmpstatus']

def _get_vm_snapshots(self, properties, node, vmid, vmtype, name):
ret = self._get_json("%s/api2/json/nodes/%s/%s/%s/snapshot" % (self.proxmox_url, node, vmtype, vmid))
Expand Down Expand Up @@ -489,7 +502,8 @@ def _handle_item(self, node, ittype, item):
name, vmid = item['name'], item['vmid']

# get status, config and snapshots if want_facts == True
if self.get_option('want_facts'):
want_facts = self.get_option('want_facts')
if want_facts:
self._get_vm_status(properties, node, vmid, ittype, name)
self._get_vm_config(properties, node, vmid, ittype, name)
self._get_vm_snapshots(properties, node, vmid, ittype, name)
Expand All @@ -503,10 +517,13 @@ def _handle_item(self, node, ittype, item):
node_type_group = self._group('%s_%s' % (node, ittype))
self.inventory.add_child(self._group('all_' + ittype), name)
self.inventory.add_child(node_type_group, name)
if item['status'] == 'stopped':
self.inventory.add_child(self._group('all_stopped'), name)
elif item['status'] == 'running':
self.inventory.add_child(self._group('all_running'), name)

item_status = item['status']
if item_status == 'running':
if want_facts and ittype == 'qemu' and self.get_option('qemu_extended_statuses'):
# get more details about the status of the qemu VM
item_status = properties.get(self._fact('qmpstatus'), item_status)
self.inventory.add_child(self._group('all_%s' % (item_status, )), name)

return name

Expand All @@ -528,10 +545,14 @@ def _populate_pool_groups(self, added_hosts):
def _populate(self):

# create common groups
self.inventory.add_group(self._group('all_lxc'))
self.inventory.add_group(self._group('all_qemu'))
self.inventory.add_group(self._group('all_running'))
self.inventory.add_group(self._group('all_stopped'))
default_groups = ['lxc', 'qemu', 'running', 'stopped']

if self.get_option('qemu_extended_statuses'):
default_groups.extend(['prelaunch', 'paused'])

for group in default_groups:
self.inventory.add_group(self._group('all_%s' % (group)))

nodes_group = self._group('nodes')
self.inventory.add_group(nodes_group)

Expand Down Expand Up @@ -621,6 +642,9 @@ def parse(self, inventory, loader, path, cache=True):
if proxmox_password is None and (proxmox_token_id is None or proxmox_token_secret is None):
raise AnsibleError('You must specify either a password or both token_id and token_secret.')

if self.get_option('qemu_extended_statuses') and not self.get_option('want_facts'):
raise AnsibleError('You must set want_facts to True if you want to use qemu_extended_statuses.')

self.cache_key = self.get_cache_key(path)
self.use_cache = cache and self.get_option('cache')
self.host_filters = self.get_option('filters')
Expand Down
61 changes: 49 additions & 12 deletions tests/unit/plugins/inventory/test_proxmox.py
Original file line number Diff line number Diff line change
Expand Up @@ -541,17 +541,11 @@ def get_vm_status(properties, node, vmtype, vmid, name):
return True


def get_option(option):
if option == 'group_prefix':
return 'proxmox_'
if option == 'facts_prefix':
return 'proxmox_'
elif option == 'want_facts':
return True
elif option == 'want_proxmox_nodes_ansible_host':
return True
else:
return False
def get_option(opts):
def fn(option):
default = opts.get('default', False)
return opts.get(option, default)
return fn


def test_populate(inventory, mocker):
Expand All @@ -563,12 +557,20 @@ def test_populate(inventory, mocker):
inventory.facts_prefix = 'proxmox_'
inventory.strict = False

opts = {
'group_prefix': 'proxmox_',
'facts_prefix': 'proxmox_',
'want_facts': True,
'want_proxmox_nodes_ansible_host': True,
'qemu_extended_statuses': True
}

# bypass authentication and API fetch calls
inventory._get_auth = mocker.MagicMock(side_effect=get_auth)
inventory._get_json = mocker.MagicMock(side_effect=get_json)
inventory._get_vm_status = mocker.MagicMock(side_effect=get_vm_status)
inventory._get_vm_snapshots = mocker.MagicMock(side_effect=get_vm_snapshots)
inventory.get_option = mocker.MagicMock(side_effect=get_option)
inventory.get_option = mocker.MagicMock(side_effect=get_option(opts))
inventory._can_add_host = mocker.MagicMock(return_value=True)
inventory._populate()

Expand Down Expand Up @@ -610,3 +612,38 @@ def test_populate(inventory, mocker):

# check that offline node is in inventory
assert inventory.inventory.get_host('testnode2')

# make sure that ['prelaunch', 'paused'] are in the group list
for group in ['paused', 'prelaunch']:
assert ('%sall_%s' % (inventory.group_prefix, group)) in inventory.inventory.groups


def test_populate_missing_qemu_extended_groups(inventory, mocker):
# module settings
inventory.proxmox_user = 'root@pam'
inventory.proxmox_password = 'password'
inventory.proxmox_url = 'https://localhost:8006'
inventory.group_prefix = 'proxmox_'
inventory.facts_prefix = 'proxmox_'
inventory.strict = False

opts = {
'group_prefix': 'proxmox_',
'facts_prefix': 'proxmox_',
'want_facts': True,
'want_proxmox_nodes_ansible_host': True,
'qemu_extended_statuses': False
}

# bypass authentication and API fetch calls
inventory._get_auth = mocker.MagicMock(side_effect=get_auth)
inventory._get_json = mocker.MagicMock(side_effect=get_json)
inventory._get_vm_status = mocker.MagicMock(side_effect=get_vm_status)
inventory._get_vm_snapshots = mocker.MagicMock(side_effect=get_vm_snapshots)
inventory.get_option = mocker.MagicMock(side_effect=get_option(opts))
inventory._can_add_host = mocker.MagicMock(return_value=True)
inventory._populate()

# make sure that ['prelaunch', 'paused'] are not in the group list
for group in ['paused', 'prelaunch']:
assert ('%sall_%s' % (inventory.group_prefix, group)) not in inventory.inventory.groups