1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2024-09-14 20:13:21 +02:00

Proxmox Inventory: added new statuses for qemu (#4723)

* added new statuses for qemu

* added document fragment

* lint fixes

* replaced f strings with %

* move the qmpstatus for qemu to a dedicated group

* added documentation to explain the new addition

* update changelog fragment to reflect the change correctly

* update changelog fragment to reflect the change correctly

* Apply suggestions from code review

Co-authored-by: Felix Fontein <felix@fontein.de>

* added a switch to get the qemu extended status

* Apply suggestions from code review

Co-authored-by: Felix Fontein <felix@fontein.de>

* groups created when qemu_extended_statuses is true and added tests to make sure they are there

* added test to make sure the groups are not present when qemu_extended_statuses is false

* Apply suggestions from code review

Co-authored-by: Felix Fontein <felix@fontein.de>

Co-authored-by: Felix Fontein <felix@fontein.de>
This commit is contained in:
Ilija Matoski 2022-06-04 09:15:02 +02:00 committed by GitHub
parent d019e22e7d
commit b556b142ec
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 86 additions and 22 deletions

View file

@ -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).

View file

@ -92,9 +92,21 @@ DOCUMENTATION = '''
default: proxmox_ default: proxmox_
type: str type: str
want_facts: 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 default: no
type: bool 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
version_added: 5.1.0
want_proxmox_nodes_ansible_host: want_proxmox_nodes_ansible_host:
version_added: 3.0.0 version_added: 3.0.0
description: description:
@ -431,6 +443,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
def _get_vm_status(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)) 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('status')] = ret['status']
properties[self._fact('qmpstatus')] = ret['qmpstatus']
def _get_vm_snapshots(self, properties, node, vmid, vmtype, name): 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)) ret = self._get_json("%s/api2/json/nodes/%s/%s/%s/snapshot" % (self.proxmox_url, node, vmtype, vmid))
@ -489,7 +502,8 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
name, vmid = item['name'], item['vmid'] name, vmid = item['name'], item['vmid']
# get status, config and snapshots if want_facts == True # 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_status(properties, node, vmid, ittype, name)
self._get_vm_config(properties, node, vmid, ittype, name) self._get_vm_config(properties, node, vmid, ittype, name)
self._get_vm_snapshots(properties, node, vmid, ittype, name) self._get_vm_snapshots(properties, node, vmid, ittype, name)
@ -503,10 +517,13 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
node_type_group = self._group('%s_%s' % (node, ittype)) node_type_group = self._group('%s_%s' % (node, ittype))
self.inventory.add_child(self._group('all_' + ittype), name) self.inventory.add_child(self._group('all_' + ittype), name)
self.inventory.add_child(node_type_group, name) self.inventory.add_child(node_type_group, name)
if item['status'] == 'stopped':
self.inventory.add_child(self._group('all_stopped'), name) item_status = item['status']
elif item['status'] == 'running': if item_status == 'running':
self.inventory.add_child(self._group('all_running'), name) 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 return name
@ -528,10 +545,14 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
def _populate(self): def _populate(self):
# create common groups # create common groups
self.inventory.add_group(self._group('all_lxc')) default_groups = ['lxc', 'qemu', 'running', 'stopped']
self.inventory.add_group(self._group('all_qemu'))
self.inventory.add_group(self._group('all_running')) if self.get_option('qemu_extended_statuses'):
self.inventory.add_group(self._group('all_stopped')) default_groups.extend(['prelaunch', 'paused'])
for group in default_groups:
self.inventory.add_group(self._group('all_%s' % (group)))
nodes_group = self._group('nodes') nodes_group = self._group('nodes')
self.inventory.add_group(nodes_group) self.inventory.add_group(nodes_group)
@ -621,6 +642,9 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
if proxmox_password is None and (proxmox_token_id is None or proxmox_token_secret is None): 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.') 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.cache_key = self.get_cache_key(path)
self.use_cache = cache and self.get_option('cache') self.use_cache = cache and self.get_option('cache')
self.host_filters = self.get_option('filters') self.host_filters = self.get_option('filters')

View file

@ -541,17 +541,11 @@ def get_vm_status(properties, node, vmtype, vmid, name):
return True return True
def get_option(option): def get_option(opts):
if option == 'group_prefix': def fn(option):
return 'proxmox_' default = opts.get('default', False)
if option == 'facts_prefix': return opts.get(option, default)
return 'proxmox_' return fn
elif option == 'want_facts':
return True
elif option == 'want_proxmox_nodes_ansible_host':
return True
else:
return False
def test_populate(inventory, mocker): def test_populate(inventory, mocker):
@ -563,12 +557,20 @@ def test_populate(inventory, mocker):
inventory.facts_prefix = 'proxmox_' inventory.facts_prefix = 'proxmox_'
inventory.strict = False 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 # bypass authentication and API fetch calls
inventory._get_auth = mocker.MagicMock(side_effect=get_auth) inventory._get_auth = mocker.MagicMock(side_effect=get_auth)
inventory._get_json = mocker.MagicMock(side_effect=get_json) inventory._get_json = mocker.MagicMock(side_effect=get_json)
inventory._get_vm_status = mocker.MagicMock(side_effect=get_vm_status) inventory._get_vm_status = mocker.MagicMock(side_effect=get_vm_status)
inventory._get_vm_snapshots = mocker.MagicMock(side_effect=get_vm_snapshots) 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._can_add_host = mocker.MagicMock(return_value=True)
inventory._populate() inventory._populate()
@ -610,3 +612,38 @@ def test_populate(inventory, mocker):
# check that offline node is in inventory # check that offline node is in inventory
assert inventory.inventory.get_host('testnode2') 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