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:
parent
d019e22e7d
commit
b556b142ec
3 changed files with 86 additions and 22 deletions
3
changelogs/fragments/4724-proxmox-qemu-extend.yaml
Normal file
3
changelogs/fragments/4724-proxmox-qemu-extend.yaml
Normal 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).
|
|
@ -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')
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue