From f1812b0f1591e6f3f1d599738ec30b3d5c0f60ae Mon Sep 17 00:00:00 2001 From: Ondra Machacek Date: Mon, 5 Dec 2016 21:23:42 +0100 Subject: [PATCH] module_utils: ovirt: Add support to fetch nested object's attributes (#18666) * module_utils: ovirt: Add support to fetch nested object's attributes This patch fixes issue #3555 * Update documentation --- lib/ansible/module_utils/ovirt.py | 39 +++++++++++- .../utils/module_docs_fragments/ovirt.py | 13 +++- .../module_docs_fragments/ovirt_facts.py | 61 +++++++++++++++++++ 3 files changed, 109 insertions(+), 4 deletions(-) create mode 100644 lib/ansible/utils/module_docs_fragments/ovirt_facts.py diff --git a/lib/ansible/module_utils/ovirt.py b/lib/ansible/module_utils/ovirt.py index 4808e1ddab8..96edc68d384 100644 --- a/lib/ansible/module_utils/ovirt.py +++ b/lib/ansible/module_utils/ovirt.py @@ -51,7 +51,7 @@ def check_sdk(module): ) -def get_dict_of_struct(struct): +def get_dict_of_struct(struct, connection=None, fetch_nested=False, attributes=None): """ Convert SDK Struct type into dictionary. """ @@ -64,18 +64,32 @@ def get_dict_of_struct(struct): res = {} if struct is not None: for key, value in struct.__dict__.items(): + nested = False key = remove_underscore(key) if value is None: continue + elif isinstance(value, sdk.Struct): res[key] = get_dict_of_struct(value) elif isinstance(value, Enum) or isinstance(value, datetime): res[key] = str(value) - elif isinstance(value, list): + elif isinstance(value, list) or isinstance(value, sdk.List): + if isinstance(value, sdk.List) and fetch_nested and value.href: + value = connection.follow_link(value) + nested = True + res[key] = [] for i in value: if isinstance(i, sdk.Struct): - res[key].append(get_dict_of_struct(i)) + if not nested: + res[key].append(get_dict_of_struct(i)) + else: + nested_obj = dict( + (attr, getattr(i, attr)) + for attr in attributes if getattr(i, attr, None) + ) + nested_obj['id'] = getattr(i, 'id', None), + res[key].append(nested_obj) elif isinstance(i, Enum): res[key].append(str(i)) else: @@ -265,6 +279,23 @@ def wait( time.sleep(float(poll_interval)) +def ovirt_facts_full_argument_spec(**kwargs): + """ + Extend parameters of facts module with parameters which are common to all + oVirt facts modules. + + :param kwargs: kwargs to be extended + :return: extended dictionary with common parameters + """ + spec = dict( + auth=dict(required=True, type='dict'), + fetch_nested=dict(default=False, type='bool'), + nested_attributes=dict(type='list'), + ) + spec.update(kwargs) + return spec + + def ovirt_full_argument_spec(**kwargs): """ Extend parameters of module with parameters which are common to all oVirt modules. @@ -277,6 +308,8 @@ def ovirt_full_argument_spec(**kwargs): timeout=dict(default=180, type='int'), wait=dict(default=True, type='bool'), poll_interval=dict(default=3, type='int'), + fetch_nested=dict(default=False, type='bool'), + nested_attributes=dict(type='list'), ) spec.update(kwargs) return spec diff --git a/lib/ansible/utils/module_docs_fragments/ovirt.py b/lib/ansible/utils/module_docs_fragments/ovirt.py index 68f97a04eb2..7334bb8a08d 100644 --- a/lib/ansible/utils/module_docs_fragments/ovirt.py +++ b/lib/ansible/utils/module_docs_fragments/ovirt.py @@ -25,7 +25,18 @@ class ModuleDocFragment(object): options: wait: description: - - "True if the module should wait for the entity to get into desired state." + - "I(True) if the module should wait for the entity to get into desired state." + fetch_nested: + description: + - "If I(True) the module will fetch additional data from the API." + - "It will fetch IDs of the VMs disks, snapshots, etc. User can configure to fetch other + attributes of the nested entities by specifing C(nested_attributes)." + version_added: "2.3" + nested_attributes: + description: + - "Specifies list of the attributes which should be fetched from the API." + - "This parameter apply only when C(fetch_nested) is I(true)." + version_added: "2.3" auth: required: True description: diff --git a/lib/ansible/utils/module_docs_fragments/ovirt_facts.py b/lib/ansible/utils/module_docs_fragments/ovirt_facts.py new file mode 100644 index 00000000000..c46c3b3798a --- /dev/null +++ b/lib/ansible/utils/module_docs_fragments/ovirt_facts.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# +# Copyright (c) 2016 Red Hat, Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . +# + +class ModuleDocFragment(object): + + # facts standart oVirt documentation fragment + DOCUMENTATION = ''' +options: + fetch_nested: + description: + - "If I(True) the module will fetch additional data from the API." + - "It will fetch IDs of the VMs disks, snapshots, etc. User can configure to fetch other + attributes of the nested entities by specifing C(nested_attributes)." + version_added: "2.3" + nested_attributes: + description: + - "Specifies list of the attributes which should be fetched from the API." + - "This parameter apply only when C(fetch_nested) is I(true)." + version_added: "2.3" + auth: + required: True + description: + - "Dictionary with values needed to create HTTP/HTTPS connection to oVirt:" + - "C(username)[I(required)] - The name of the user, something like `I(admin@internal)`." + - "C(password)[I(required)] - The password of the user." + - "C(url)[I(required)] - A string containing the base URL of the server, usually + something like `I(https://server.example.com/ovirt-engine/api)`." + - "C(token) - Token to be used instead of login with username/password." + - "C(insecure) - A boolean flag that indicates if the server TLS + certificate and host name should be checked." + - "C(ca_file) - A PEM file containing the trusted CA certificates. The + certificate presented by the server will be verified using these CA + certificates. If `C(ca_file)` parameter is not set, system wide + CA certificate store is used." + - "C(kerberos) - A boolean flag indicating if Kerberos authentication + should be used instead of the default basic authentication." +requirements: + - python >= 2.7 + - ovirt-engine-sdk-python >= 4.0.0 +notes: + - "In order to use this module you have to install oVirt Python SDK. + To ensure it's installed with correct version you can create the following task: + pip: name=ovirt-engine-sdk-python version=4.0.0" +'''