From 305748b3331c099981396460e90cff7ada3e45b3 Mon Sep 17 00:00:00 2001 From: Tristan Le Guern Date: Mon, 22 Feb 2021 17:59:27 +0100 Subject: [PATCH] New module proxmox_storage_info (#1844) * proxmox_storage_info: new module Simple info module dedicated to the retrieval of information about the storages available on a Proxmox VE cluster. * Update plugins/modules/cloud/misc/proxmox_storage_info.py Co-authored-by: Felix Fontein * Update plugins/modules/cloud/misc/proxmox_storage_info.py Co-authored-by: Felix Fontein * Update plugins/modules/cloud/misc/proxmox_storage_info.py Co-authored-by: Felix Fontein * Update plugins/modules/cloud/misc/proxmox_storage_info.py Co-authored-by: Felix Fontein * Update plugins/modules/cloud/misc/proxmox_storage_info.py Co-authored-by: Felix Fontein --- .../cloud/misc/proxmox_storage_info.py | 190 ++++++++++++++++++ plugins/modules/proxmox_storage_info.py | 1 + tests/integration/targets/proxmox/aliases | 1 + .../targets/proxmox/tasks/main.yml | 18 ++ 4 files changed, 210 insertions(+) create mode 100644 plugins/modules/cloud/misc/proxmox_storage_info.py create mode 120000 plugins/modules/proxmox_storage_info.py diff --git a/plugins/modules/cloud/misc/proxmox_storage_info.py b/plugins/modules/cloud/misc/proxmox_storage_info.py new file mode 100644 index 0000000000..fb495435e0 --- /dev/null +++ b/plugins/modules/cloud/misc/proxmox_storage_info.py @@ -0,0 +1,190 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# Copyright: Tristan Le Guern (@Aversiste) +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: proxmox_storage_info +short_description: Retrieve information about one or more Proxmox VE storages +version_added: 2.2.0 +description: + - Retrieve information about one or more Proxmox VE storages. +options: + storage: + description: + - Only return informations on a specific storage. + aliases: ['name'] + type: str + type: + description: + - Filter on a specifc storage type. + type: str +author: Tristan Le Guern (@Aversiste) +extends_documentation_fragment: community.general.proxmox.documentation +notes: + - Storage specific options can be returned by this module, please look at the documentation at U(https://pve.proxmox.com/wiki/Storage). +''' + + +EXAMPLES = ''' +- name: List existing storages + community.general.proxmox_storage_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) }}" + register: proxmox_storages + +- name: List NFS storages only + community.general.proxmox_storage_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) }}" + type: nfs + register: proxmox_storages_nfs + +- name: Retrieve information about the lvm2 storage + community.general.proxmox_storage_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 + register: proxmox_storage_lvm +''' + + +RETURN = ''' +proxmox_storages: + description: List of storage pools. + returned: on success + type: list + elements: dict + contains: + content: + description: Proxmox content types available in this storage + returned: on success + type: list + elements: str + digest: + description: Storage's digest + returned: on success + type: str + nodes: + description: List of nodes associated to this storage + returned: on success, if storage is not local + type: list + elements: str + path: + description: Physical path to this storage + returned: on success + type: str + prune-backups: + description: Backup retention options + returned: on success + type: list + elements: dict + shared: + description: Is this storage shared + returned: on success + type: bool + storage: + description: Storage name + returned: on success + type: str + type: + description: Storage type + returned: on success + type: str +''' + + +from ansible.module_utils.basic import AnsibleModule, missing_required_lib +from ansible_collections.community.general.plugins.module_utils.proxmox import ( + proxmox_auth_argument_spec, ProxmoxAnsible, HAS_PROXMOXER, PROXMOXER_IMP_ERR, proxmox_to_ansible_bool) + + +class ProxmoxStorageInfoAnsible(ProxmoxAnsible): + def get_storage(self, storage): + try: + storage = self.proxmox_api.storage.get(storage) + except Exception: + self.module.fail_json(msg="Storage '%s' does not exist" % storage) + return ProxmoxStorage(storage) + + def get_storages(self, type=None): + storages = self.proxmox_api.storage.get(type=type) + storages = [ProxmoxStorage(storage) for storage in storages] + return storages + + +class ProxmoxStorage: + def __init__(self, storage): + self.storage = storage + # Convert proxmox representation of lists, dicts and boolean for easier + # manipulation within ansible. + if 'shared' in self.storage: + self.storage['shared'] = proxmox_to_ansible_bool(self.storage['shared']) + if 'content' in self.storage: + self.storage['content'] = self.storage['content'].split(',') + if 'nodes' in self.storage: + self.storage['nodes'] = self.storage['nodes'].split(',') + if 'prune-backups' in storage: + options = storage['prune-backups'].split(',') + self.storage['prune-backups'] = dict() + for option in options: + k, v = option.split('=') + self.storage['prune-backups'][k] = v + + +def proxmox_storage_info_argument_spec(): + return dict( + storage=dict(type='str', aliases=['name']), + type=dict(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')], + mutually_exclusive=[('storage', 'type')], + supports_check_mode=True + ) + result = dict( + changed=False + ) + + if not HAS_PROXMOXER: + module.fail_json(msg=missing_required_lib('proxmoxer'), exception=PROXMOXER_IMP_ERR) + + proxmox = ProxmoxStorageInfoAnsible(module) + storage = module.params['storage'] + storagetype = module.params['type'] + + if storage: + storages = [proxmox.get_storage(storage)] + else: + storages = proxmox.get_storages(type=storagetype) + result['proxmox_storages'] = [storage.storage for storage in storages] + + module.exit_json(**result) + + +if __name__ == '__main__': + main() diff --git a/plugins/modules/proxmox_storage_info.py b/plugins/modules/proxmox_storage_info.py new file mode 120000 index 0000000000..8128300547 --- /dev/null +++ b/plugins/modules/proxmox_storage_info.py @@ -0,0 +1 @@ +cloud/misc/proxmox_storage_info.py \ No newline at end of file diff --git a/tests/integration/targets/proxmox/aliases b/tests/integration/targets/proxmox/aliases index d5a5dcd139..caa35b7354 100644 --- a/tests/integration/targets/proxmox/aliases +++ b/tests/integration/targets/proxmox/aliases @@ -2,3 +2,4 @@ unsupported proxmox_domain_info proxmox_group_info proxmox_user_info +proxmox_storage_info diff --git a/tests/integration/targets/proxmox/tasks/main.yml b/tests/integration/targets/proxmox/tasks/main.yml index 235e412d98..6301cb66ef 100644 --- a/tests/integration/targets/proxmox/tasks/main.yml +++ b/tests/integration/targets/proxmox/tasks/main.yml @@ -110,6 +110,24 @@ - results_userid.proxmox_users[0].user == "{{ user }}" - results_userid.proxmox_users[0].userid == "{{ user }}@{{ domain }}" +- name: Retrieve info about storage + proxmox_storage_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 }}" + register: results_storage + +- assert: + that: + - results_storage is not changed + - results_storage.proxmox_storages is defined + - results_storage.proxmox_storages|length == 1 + - results_storage.proxmox_storages[0].storage == "{{ storage }}" + - name: VM creation tags: [ 'create' ] block: