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

Proxmox add storage content listing (#7725)

Add module to list content on proxmox storage

We first add a method to list storage content for proxmox, then use that
new methode to add an Ansible module to list content on storage attached
to a proxmox node. User can also use content filtering to define what
they want to list (backup, iso, images,...).

This commit also include the integration and unit test for that new
module.

Co-authored-by: Julian Vanden Broeck <julian.vandenbroeck@dalibo.com>
This commit is contained in:
Julian 2023-12-31 15:21:20 +01:00 committed by GitHub
parent 3318034403
commit 4f92f39720
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 269 additions and 0 deletions

2
.github/BOTMETA.yml vendored
View file

@ -1053,6 +1053,8 @@ files:
maintainers: Kogelvis
$modules/proxmox_node_info.py:
maintainers: jwbernin
$modules/proxmox_storage_contents_info.py:
maintainers: l00ptr
$modules/proxmox_tasks_info:
maintainers: paginabianca
$modules/proxmox_template.py:

View file

@ -180,3 +180,17 @@ class ProxmoxAnsible(object):
return self.proxmox_api.storage.get(type=type)
except Exception as e:
self.module.fail_json(msg="Unable to retrieve storages information with type %s: %s" % (type, e))
def get_storage_content(self, node, storage, content=None, vmid=None):
try:
return (
self.proxmox_api.nodes(node)
.storage(storage)
.content()
.get(content=content, vmid=vmid)
)
except Exception as e:
self.module.fail_json(
msg="Unable to list content on %s, %s for %s and %s: %s"
% (node, storage, content, vmid, e)
)

View file

@ -0,0 +1,144 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright Julian Vanden Broeck (@l00ptr) <julian.vandenbroeck at dalibo.com>
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = """
---
module: proxmox_storage_contents_info
short_description: List content from a Proxmox VE storage
version_added: 8.2.0
description:
- Retrieves information about stored objects on a specific storage attached to a node.
options:
storage:
description:
- Only return content stored on that specific storage.
aliases: ['name']
type: str
required: true
node:
description:
- Proxmox node to which the storage is attached.
type: str
required: true
content:
description:
- Filter on a specific content type.
type: str
choices: ["all", "backup", "rootdir", "images", "iso"]
default: "all"
vmid:
description:
- Filter on a specific VMID.
type: int
author: Julian Vanden Broeck (@l00ptr)
extends_documentation_fragment:
- community.general.proxmox.documentation
- community.general.attributes
- community.general.attributes.info_module
"""
EXAMPLES = """
- name: List existing storages
community.general.proxmox_storage_contents_info:
api_host: helldorado
api_user: root@pam
api_password: "{{ password | default(omit) }}"
api_token_id: "{{ token_id | default(omit) }}"
api_token_secret: "{{ token_secret | default(omit) }}"
storage: lvm2
content: backup
vmid: 130
"""
RETURN = """
proxmox_storage_content:
description: Content of of storage attached to a node.
type: list
returned: success
elements: dict
contains:
content:
description: Proxmox content of listed objects on this storage.
type: str
returned: success
ctime:
description: Creation time of the listed objects.
type: str
returned: success
format:
description: Format of the listed objects (can be V(raw), V(pbs-vm), V(iso),...).
type: str
returned: success
size:
description: Size of the listed objects.
type: int
returned: success
subtype:
description: Subtype of the listed objects (can be V(qemu) or V(lxc)).
type: str
returned: When storage is dedicated to backup, typically on PBS storage.
verification:
description: Backup verification status of the listed objects.
type: dict
returned: When storage is dedicated to backup, typically on PBS storage.
sample: {
"state": "ok",
"upid": "UPID:backup-srv:00130F49:1A12D8375:00001CD7:657A2258:verificationjob:daily\\x3av\\x2dd0cc18c5\\x2d8707:root@pam:"
}
volid:
description: Volume identifier of the listed objects.
type: str
returned: success
"""
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.community.general.plugins.module_utils.proxmox import (
ProxmoxAnsible, proxmox_auth_argument_spec)
def proxmox_storage_info_argument_spec():
return dict(
storage=dict(type="str", required=True, aliases=["name"]),
content=dict(type="str", required=False, default="all", choices=["all", "backup", "rootdir", "images", "iso"]),
vmid=dict(type="int"),
node=dict(required=True, type="str"),
)
def main():
module_args = proxmox_auth_argument_spec()
storage_info_args = proxmox_storage_info_argument_spec()
module_args.update(storage_info_args)
module = AnsibleModule(
argument_spec=module_args,
required_one_of=[("api_password", "api_token_id")],
required_together=[("api_token_id", "api_token_secret")],
supports_check_mode=True,
)
result = dict(changed=False)
proxmox = ProxmoxAnsible(module)
res = proxmox.get_storage_content(
node=module.params["node"],
storage=module.params["storage"],
content=None if module.params["content"] == "all" else module.params["content"],
vmid=module.params["vmid"],
)
result["proxmox_storage_content"] = res
module.exit_json(**result)
if __name__ == "__main__":
main()

View file

@ -129,6 +129,25 @@
- results_storage.proxmox_storages|length == 1
- results_storage.proxmox_storages[0].storage == "{{ storage }}"
- name: List content on storage
proxmox_storage_contents_info:
api_host: "{{ api_host }}"
api_user: "{{ user }}@{{ domain }}"
api_password: "{{ api_password | default(omit) }}"
api_token_id: "{{ api_token_id | default(omit) }}"
api_token_secret: "{{ api_token_secret | default(omit) }}"
validate_certs: "{{ validate_certs }}"
storage: "{{ storage }}"
node: "{{ node }}"
content: images
register: results_list_storage
- assert:
that:
- results_storage is not changed
- results_storage.proxmox_storage_content is defined
- results_storage.proxmox_storage_content |length == 1
- name: VM creation
tags: [ 'create' ]
block:

View file

@ -0,0 +1,90 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2023, Julian Vanden Broeck <julian.vandenbroeck at dalibo.com>
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import pytest
proxmoxer = pytest.importorskip("proxmoxer")
from ansible_collections.community.general.plugins.modules import proxmox_storage_contents_info
from ansible_collections.community.general.tests.unit.compat.mock import patch
from ansible_collections.community.general.tests.unit.plugins.modules.utils import (
AnsibleExitJson,
AnsibleFailJson,
ModuleTestCase,
set_module_args,
)
import ansible_collections.community.general.plugins.module_utils.proxmox as proxmox_utils
NODE1 = "pve"
RAW_LIST_OUTPUT = [
{
"content": "backup",
"ctime": 1702528474,
"format": "pbs-vm",
"size": 273804166061,
"subtype": "qemu",
"vmid": 931,
"volid": "datastore:backup/vm/931/2023-12-14T04:34:34Z",
},
{
"content": "backup",
"ctime": 1702582560,
"format": "pbs-vm",
"size": 273804166059,
"subtype": "qemu",
"vmid": 931,
"volid": "datastore:backup/vm/931/2023-12-14T19:36:00Z",
},
]
def get_module_args(node, storage, content="all", vmid=None):
return {
"api_host": "host",
"api_user": "user",
"api_password": "password",
"node": node,
"storage": storage,
"content": content,
"vmid": vmid,
}
class TestProxmoxStorageContentsInfo(ModuleTestCase):
def setUp(self):
super(TestProxmoxStorageContentsInfo, self).setUp()
proxmox_utils.HAS_PROXMOXER = True
self.module = proxmox_storage_contents_info
self.connect_mock = patch(
"ansible_collections.community.general.plugins.module_utils.proxmox.ProxmoxAnsible._connect",
).start()
self.connect_mock.return_value.nodes.return_value.storage.return_value.content.return_value.get.return_value = (
RAW_LIST_OUTPUT
)
self.connect_mock.return_value.nodes.get.return_value = [{"node": NODE1}]
def tearDown(self):
self.connect_mock.stop()
super(TestProxmoxStorageContentsInfo, self).tearDown()
def test_module_fail_when_required_args_missing(self):
with pytest.raises(AnsibleFailJson) as exc_info:
set_module_args({})
self.module.main()
def test_storage_contents_info(self):
with pytest.raises(AnsibleExitJson) as exc_info:
set_module_args(get_module_args(node=NODE1, storage="datastore"))
expected_output = {}
self.module.main()
result = exc_info.value.args[0]
assert not result["changed"]
assert result["proxmox_storage_content"] == RAW_LIST_OUTPUT