diff options
author | Ondra Machacek <machacek.ondra@gmail.com> | 2017-02-02 19:50:52 +0100 |
---|---|---|
committer | Ryan Brown <sb@ryansb.com> | 2017-02-02 13:50:52 -0500 |
commit | ee7f1cde0ef54a9c2db385907fe9ccc19c75ad32 (patch) | |
tree | b68eb2b3c03535a47ebdaf8dbbf5662e24e118b0 /lib/ansible/module_utils/ovirt.py | |
parent | 6ca5fb49c303c4543e4fa498fe9aef52ab1f8ffb (diff) | |
download | ansible-ee7f1cde0ef54a9c2db385907fe9ccc19c75ad32.tar.gz |
ovirt: Add support to diff (#20698)
* cloud: ovirt: Add diff support to
* cloud: ovirt: Add ability to print nested list of objects
* cloud: ovirt: Fix waiting while reinstalling host
* cloud: ovirt: fix ovirt_vms 404 error
* cloud: ovirt: add check_mode support to ovirt_auth module
Diffstat (limited to 'lib/ansible/module_utils/ovirt.py')
-rw-r--r-- | lib/ansible/module_utils/ovirt.py | 119 |
1 files changed, 82 insertions, 37 deletions
diff --git a/lib/ansible/module_utils/ovirt.py b/lib/ansible/module_utils/ovirt.py index d4944da800..f4bb16702e 100644 --- a/lib/ansible/module_utils/ovirt.py +++ b/lib/ansible/module_utils/ovirt.py @@ -18,6 +18,7 @@ # along with Ansible. If not, see <http://www.gnu.org/licenses/>. # +import collections import inspect import os import time @@ -55,47 +56,56 @@ def get_dict_of_struct(struct, connection=None, fetch_nested=False, attributes=N """ Convert SDK Struct type into dictionary. """ + res = {} + def remove_underscore(val): if val.startswith('_'): val = val[1:] remove_underscore(val) return val - res = {} + def convert_value(value): + nested = False + + if isinstance(value, sdk.Struct): + return get_dict_of_struct(value) + elif isinstance(value, Enum) or isinstance(value, datetime): + return str(value) + elif isinstance(value, list) or isinstance(value, sdk.List): + if isinstance(value, sdk.List) and fetch_nested and value.href: + try: + value = connection.follow_link(value) + nested = True + except sdk.Error: + value = [] + + ret = [] + for i in value: + if isinstance(i, sdk.Struct): + if not nested: + ret.append(get_dict_of_struct(i)) + else: + nested_obj = dict( + (attr, convert_value(getattr(i, attr))) + for attr in attributes if getattr(i, attr, None) + ) + nested_obj['id'] = getattr(i, 'id', None), + ret.append(nested_obj) + elif isinstance(i, Enum): + ret.append(str(i)) + else: + ret.append(i) + return ret + else: + return value + 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) 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): - 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: - res[key].append(i) - else: - res[key] = value + key = remove_underscore(key) + res[key] = convert_value(value) return res @@ -283,9 +293,6 @@ def wait( if wait: start = time.time() while time.time() < start + timeout: - # Sleep for `poll_interval` seconds if none of the conditions apply: - time.sleep(float(poll_interval)) - # Exit if the condition of entity is valid: entity = get_entity(service) if condition(entity): @@ -293,6 +300,11 @@ def wait( elif fail_condition(entity): raise Exception("Error while waiting on result state of the entity.") + # Sleep for `poll_interval` seconds if none of the conditions apply: + time.sleep(float(poll_interval)) + + raise Exception("Timeout exceed while waiting on result state of the entity.") + def __get_auth_dict(): OVIRT_URL = os.environ.get('OVIRT_URL') @@ -331,7 +343,7 @@ def ovirt_facts_full_argument_spec(**kwargs): spec = dict( auth=__get_auth_dict(), fetch_nested=dict(default=False, type='bool'), - nested_attributes=dict(type='list'), + nested_attributes=dict(type='list', default=list()), ) spec.update(kwargs) return spec @@ -350,7 +362,7 @@ def ovirt_full_argument_spec(**kwargs): 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'), + nested_attributes=dict(type='list', default=list()), ) spec.update(kwargs) return spec @@ -401,6 +413,7 @@ class BaseModule(object): self._module = module self._service = service self._changed = changed + self._diff = {'after': dict(), 'before': dict()} @property def changed(self): @@ -464,6 +477,15 @@ class BaseModule(object): """ pass + def diff_update(self, after, update): + for k, v in update.items(): + if isinstance(v, collections.Mapping): + after[k] = self.diff_update(after.get(k, dict()), v) + else: + after[k] = update[k] + return after + + def create(self, entity=None, result_state=None, fail_condition=lambda e: False, search_params=None, **kwargs): """ Method which is called when state of the entity is 'present'. If user @@ -492,9 +514,25 @@ class BaseModule(object): # Entity exists, so update it: entity_service = self._service.service(entity.id) if not self.update_check(entity): + new_entity = self.build_entity() if not self._module.check_mode: - entity_service.update(self.build_entity()) + updated_entity = entity_service.update(new_entity) self.post_update(entity) + + # Update diffs only if user specified --diff paramter, + # so we don't useless overload API: + if self._module._diff: + before = get_dict_of_struct( + entity, + self._connection, + fetch_nested=True, + attributes=['name'], + ) + after = before.copy() + self.diff_update(after, get_dict_of_struct(new_entity)) + self._diff['before'] = before + self._diff['after'] = after + self.changed = True else: # Entity don't exists, so create it: @@ -530,6 +568,7 @@ class BaseModule(object): fetch_nested=self._module.params.get('fetch_nested'), attributes=self._module.params.get('nested_attributes'), ), + 'diff': self._diff, } def pre_remove(self, entity): @@ -540,6 +579,12 @@ class BaseModule(object): """ pass + def entity_name(self, entity): + return "{e_type} '{e_name}'".format( + e_type=type(entity).__name__.lower(), + e_name=getattr(entity, 'name', None), + ) + def remove(self, entity=None, search_params=None, **kwargs): """ Method which is called when state of the entity is 'absent'. If user @@ -568,7 +613,6 @@ class BaseModule(object): entity_service = self._service.service(entity.id) if not self._module.check_mode: entity_service.remove(**kwargs) - wait( service=entity_service, condition=lambda entity: not entity, @@ -662,6 +706,7 @@ class BaseModule(object): fetch_nested=self._module.params.get('fetch_nested'), attributes=self._module.params.get('nested_attributes'), ), + 'diff': self._diff, } def search_entity(self, search_params=None): |