From a3be23f78125630182c6b2c3e43b5f1d821aea7b Mon Sep 17 00:00:00 2001 From: Ansible Core Team Date: Mon, 9 Mar 2020 09:40:36 +0000 Subject: Migrated to ovirt.ovirt --- lib/ansible/module_utils/ovirt.py | 868 ------- .../modules/cloud/ovirt/ovirt_affinity_group.py | 329 --- .../modules/cloud/ovirt/ovirt_affinity_label.py | 210 -- .../cloud/ovirt/ovirt_affinity_label_info.py | 182 -- lib/ansible/modules/cloud/ovirt/ovirt_api_info.py | 98 - lib/ansible/modules/cloud/ovirt/ovirt_auth.py | 300 --- lib/ansible/modules/cloud/ovirt/ovirt_cluster.py | 745 ------ .../modules/cloud/ovirt/ovirt_cluster_info.py | 120 - .../modules/cloud/ovirt/ovirt_datacenter.py | 233 -- .../modules/cloud/ovirt/ovirt_datacenter_info.py | 103 - lib/ansible/modules/cloud/ovirt/ovirt_disk.py | 838 ------ lib/ansible/modules/cloud/ovirt/ovirt_disk_info.py | 120 - lib/ansible/modules/cloud/ovirt/ovirt_event.py | 249 -- .../modules/cloud/ovirt/ovirt_event_info.py | 170 -- .../modules/cloud/ovirt/ovirt_external_provider.py | 406 --- .../cloud/ovirt/ovirt_external_provider_info.py | 161 -- lib/ansible/modules/cloud/ovirt/ovirt_group.py | 185 -- .../modules/cloud/ovirt/ovirt_group_info.py | 118 - lib/ansible/modules/cloud/ovirt/ovirt_host.py | 701 ----- lib/ansible/modules/cloud/ovirt/ovirt_host_info.py | 144 -- .../modules/cloud/ovirt/ovirt_host_network.py | 601 ----- lib/ansible/modules/cloud/ovirt/ovirt_host_pm.py | 261 -- .../modules/cloud/ovirt/ovirt_host_storage_info.py | 182 -- .../modules/cloud/ovirt/ovirt_instance_type.py | 592 ----- lib/ansible/modules/cloud/ovirt/ovirt_job.py | 236 -- lib/ansible/modules/cloud/ovirt/ovirt_mac_pool.py | 181 -- lib/ansible/modules/cloud/ovirt/ovirt_network.py | 360 --- .../modules/cloud/ovirt/ovirt_network_info.py | 120 - lib/ansible/modules/cloud/ovirt/ovirt_nic.py | 318 --- lib/ansible/modules/cloud/ovirt/ovirt_nic_info.py | 138 - .../modules/cloud/ovirt/ovirt_permission.py | 320 --- .../modules/cloud/ovirt/ovirt_permission_info.py | 161 -- lib/ansible/modules/cloud/ovirt/ovirt_quota.py | 319 --- .../modules/cloud/ovirt/ovirt_quota_info.py | 138 - lib/ansible/modules/cloud/ovirt/ovirt_role.py | 190 -- .../cloud/ovirt/ovirt_scheduling_policy_info.py | 137 - lib/ansible/modules/cloud/ovirt/ovirt_snapshot.py | 551 ---- .../modules/cloud/ovirt/ovirt_snapshot_info.py | 133 - .../cloud/ovirt/ovirt_storage_connection.py | 285 -- .../modules/cloud/ovirt/ovirt_storage_domain.py | 809 ------ .../cloud/ovirt/ovirt_storage_domain_info.py | 120 - .../cloud/ovirt/ovirt_storage_template_info.py | 138 - .../modules/cloud/ovirt/ovirt_storage_vm_info.py | 138 - lib/ansible/modules/cloud/ovirt/ovirt_tag.py | 257 -- lib/ansible/modules/cloud/ovirt/ovirt_tag_info.py | 167 -- lib/ansible/modules/cloud/ovirt/ovirt_template.py | 1087 -------- .../modules/cloud/ovirt/ovirt_template_info.py | 120 - lib/ansible/modules/cloud/ovirt/ovirt_user.py | 176 -- lib/ansible/modules/cloud/ovirt/ovirt_user_info.py | 118 - lib/ansible/modules/cloud/ovirt/ovirt_vm.py | 2727 -------------------- lib/ansible/modules/cloud/ovirt/ovirt_vm_info.py | 160 -- lib/ansible/modules/cloud/ovirt/ovirt_vmpool.py | 485 ---- .../modules/cloud/ovirt/ovirt_vmpool_info.py | 118 - .../modules/cloud/ovirt/ovirt_vnic_profile.py | 321 --- .../modules/cloud/ovirt/ovirt_vnic_profile_info.py | 119 - lib/ansible/plugins/doc_fragments/ovirt.py | 102 - lib/ansible/plugins/doc_fragments/ovirt_info.py | 57 - test/sanity/ignore.txt | 256 -- 58 files changed, 18978 deletions(-) delete mode 100644 lib/ansible/module_utils/ovirt.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_affinity_group.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_affinity_label.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_affinity_label_info.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_api_info.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_auth.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_cluster.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_cluster_info.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_datacenter.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_datacenter_info.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_disk.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_disk_info.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_event.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_event_info.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_external_provider.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_external_provider_info.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_group.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_group_info.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_host.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_host_info.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_host_network.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_host_pm.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_host_storage_info.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_instance_type.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_job.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_mac_pool.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_network.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_network_info.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_nic.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_nic_info.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_permission.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_permission_info.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_quota.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_quota_info.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_role.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_scheduling_policy_info.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_snapshot.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_snapshot_info.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_storage_connection.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_storage_domain.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_storage_domain_info.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_storage_template_info.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_storage_vm_info.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_tag.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_tag_info.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_template.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_template_info.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_user.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_user_info.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_vm.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_vm_info.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_vmpool.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_vmpool_info.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_vnic_profile.py delete mode 100644 lib/ansible/modules/cloud/ovirt/ovirt_vnic_profile_info.py delete mode 100644 lib/ansible/plugins/doc_fragments/ovirt.py delete mode 100644 lib/ansible/plugins/doc_fragments/ovirt_info.py diff --git a/lib/ansible/module_utils/ovirt.py b/lib/ansible/module_utils/ovirt.py deleted file mode 100644 index 38b048f95e..0000000000 --- a/lib/ansible/module_utils/ovirt.py +++ /dev/null @@ -1,868 +0,0 @@ -# -*- 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 . -# - -import inspect -import os -import time - -from abc import ABCMeta, abstractmethod -from datetime import datetime -from distutils.version import LooseVersion - -from ansible.module_utils.cloud import CloudRetry -from ansible.module_utils.common._collections_compat import Mapping - -try: - from enum import Enum # enum is a ovirtsdk4 requirement - import ovirtsdk4 as sdk - import ovirtsdk4.version as sdk_version - import ovirtsdk4.types as otypes - HAS_SDK = LooseVersion(sdk_version.VERSION) >= LooseVersion('4.3.0') -except ImportError: - HAS_SDK = False - - -BYTES_MAP = { - 'kib': 2**10, - 'mib': 2**20, - 'gib': 2**30, - 'tib': 2**40, - 'pib': 2**50, -} - - -def check_sdk(module): - if not HAS_SDK: - module.fail_json( - msg='ovirtsdk4 version 4.3.0 or higher is required for this module' - ) - - -def get_dict_of_struct(struct, connection=None, fetch_nested=False, attributes=None): - """ - Convert SDK Struct type into dictionary. - """ - res = {} - - def resolve_href(value): - # Fetch nested values of struct: - try: - value = connection.follow_link(value) - except sdk.Error: - value = None - nested_obj = dict( - (attr, convert_value(getattr(value, attr))) - for attr in attributes if getattr(value, attr, None) is not None - ) - nested_obj['id'] = getattr(value, 'id', None) - nested_obj['href'] = getattr(value, 'href', None) - return nested_obj - - def remove_underscore(val): - if val.startswith('_'): - val = val[1:] - remove_underscore(val) - return val - - def convert_value(value): - nested = False - - if isinstance(value, sdk.Struct): - if not fetch_nested or not value.href: - return get_dict_of_struct(value) - return resolve_href(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 and fetch_nested and i.href: - ret.append(resolve_href(i)) - elif 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(): - if value is None: - continue - - key = remove_underscore(key) - res[key] = convert_value(value) - - return res - - -def engine_version(connection): - """ - Return string representation of oVirt engine version. - """ - engine_api = connection.system_service().get() - engine_version = engine_api.product_info.version - return '%s.%s' % (engine_version.major, engine_version.minor) - - -def create_connection(auth): - """ - Create a connection to Python SDK, from task `auth` parameter. - If user doesnt't have SSO token the `auth` dictionary has following parameters mandatory: - url, username, password - - If user has SSO token the `auth` dictionary has following parameters mandatory: - url, token - - The `ca_file` parameter is mandatory in case user want to use secure connection, - in case user want to use insecure connection, it's mandatory to send insecure=True. - - :param auth: dictionary which contains needed values for connection creation - :return: Python SDK connection - """ - - url = auth.get('url') - if url is None and auth.get('hostname') is not None: - url = 'https://{0}/ovirt-engine/api'.format(auth.get('hostname')) - - return sdk.Connection( - url=url, - username=auth.get('username'), - password=auth.get('password'), - ca_file=auth.get('ca_file', None), - insecure=auth.get('insecure', False), - token=auth.get('token', None), - kerberos=auth.get('kerberos', None), - headers=auth.get('headers', None), - ) - - -def convert_to_bytes(param): - """ - This method convert units to bytes, which follow IEC standard. - - :param param: value to be converted - """ - if param is None: - return None - - # Get rid of whitespaces: - param = ''.join(param.split()) - - # Convert to bytes: - if len(param) > 3 and param[-3].lower() in ['k', 'm', 'g', 't', 'p']: - return int(param[:-3]) * BYTES_MAP.get(param[-3:].lower(), 1) - elif param.isdigit(): - return int(param) * 2**10 - else: - raise ValueError( - "Unsupported value(IEC supported): '{value}'".format(value=param) - ) - - -def follow_link(connection, link): - """ - This method returns the entity of the element which link points to. - - :param connection: connection to the Python SDK - :param link: link of the entity - :return: entity which link points to - """ - - if link: - return connection.follow_link(link) - else: - return None - - -def get_link_name(connection, link): - """ - This method returns the name of the element which link points to. - - :param connection: connection to the Python SDK - :param link: link of the entity - :return: name of the entity, which link points to - """ - - if link: - return connection.follow_link(link).name - else: - return None - - -def equal(param1, param2, ignore_case=False): - """ - Compare two parameters and return if they are equal. - This parameter doesn't run equal operation if first parameter is None. - With this approach we don't run equal operation in case user don't - specify parameter in their task. - - :param param1: user inputted parameter - :param param2: value of entity parameter - :return: True if parameters are equal or first parameter is None, otherwise False - """ - if param1 is not None: - if ignore_case: - return param1.lower() == param2.lower() - return param1 == param2 - return True - - -def search_by_attributes(service, list_params=None, **kwargs): - """ - Search for the entity by attributes. Nested entities don't support search - via REST, so in case using search for nested entity we return all entities - and filter them by specified attributes. - """ - list_params = list_params or {} - # Check if 'list' method support search(look for search parameter): - if 'search' in inspect.getargspec(service.list)[0]: - res = service.list( - # There must be double quotes around name, because some oVirt resources it's possible to create then with space in name. - search=' and '.join('{0}="{1}"'.format(k, v) for k, v in kwargs.items()), - **list_params - ) - else: - res = [ - e for e in service.list(**list_params) if len([ - k for k, v in kwargs.items() if getattr(e, k, None) == v - ]) == len(kwargs) - ] - - res = res or [None] - return res[0] - - -def search_by_name(service, name, **kwargs): - """ - Search for the entity by its name. Nested entities don't support search - via REST, so in case using search for nested entity we return all entities - and filter them by name. - - :param service: service of the entity - :param name: name of the entity - :return: Entity object returned by Python SDK - """ - # Check if 'list' method support search(look for search parameter): - if 'search' in inspect.getargspec(service.list)[0]: - res = service.list( - # There must be double quotes around name, because some oVirt resources it's possible to create then with space in name. - search='name="{name}"'.format(name=name) - ) - else: - res = [e for e in service.list() if e.name == name] - - if kwargs: - res = [ - e for e in service.list() if len([ - k for k, v in kwargs.items() if getattr(e, k, None) == v - ]) == len(kwargs) - ] - - res = res or [None] - return res[0] - - -def get_entity(service, get_params=None): - """ - Ignore SDK Error in case of getting an entity from service. - """ - entity = None - try: - if get_params is not None: - entity = service.get(**get_params) - else: - entity = service.get() - except sdk.Error: - # We can get here 404, we should ignore it, in case - # of removing entity for example. - pass - return entity - - -def get_id_by_name(service, name, raise_error=True, ignore_case=False): - """ - Search an entity ID by it's name. - """ - entity = search_by_name(service, name) - - if entity is not None: - return entity.id - - if raise_error: - raise Exception("Entity '%s' was not found." % name) - - -def wait( - service, - condition, - fail_condition=lambda e: False, - timeout=180, - wait=True, - poll_interval=3, -): - """ - Wait until entity fulfill expected condition. - - :param service: service of the entity - :param condition: condition to be fulfilled - :param fail_condition: if this condition is true, raise Exception - :param timeout: max time to wait in seconds - :param wait: if True wait for condition, if False don't wait - :param poll_interval: Number of seconds we should wait until next condition check - """ - # Wait until the desired state of the entity: - if wait: - start = time.time() - while time.time() < start + timeout: - # Exit if the condition of entity is valid: - entity = get_entity(service) - if condition(entity): - return - 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') - OVIRT_HOSTNAME = os.environ.get('OVIRT_HOSTNAME') - OVIRT_USERNAME = os.environ.get('OVIRT_USERNAME') - OVIRT_PASSWORD = os.environ.get('OVIRT_PASSWORD') - OVIRT_TOKEN = os.environ.get('OVIRT_TOKEN') - OVIRT_CAFILE = os.environ.get('OVIRT_CAFILE') - OVIRT_INSECURE = OVIRT_CAFILE is None - - env_vars = None - if OVIRT_URL is None and OVIRT_HOSTNAME is not None: - OVIRT_URL = 'https://{0}/ovirt-engine/api'.format(OVIRT_HOSTNAME) - if OVIRT_URL and ((OVIRT_USERNAME and OVIRT_PASSWORD) or OVIRT_TOKEN): - env_vars = { - 'url': OVIRT_URL, - 'username': OVIRT_USERNAME, - 'password': OVIRT_PASSWORD, - 'insecure': OVIRT_INSECURE, - 'token': OVIRT_TOKEN, - 'ca_file': OVIRT_CAFILE, - } - if env_vars is not None: - auth = dict(default=env_vars, type='dict') - else: - auth = dict(required=True, type='dict') - - return auth - - -def ovirt_info_full_argument_spec(**kwargs): - """ - Extend parameters of info module with parameters which are common to all - oVirt info modules. - - :param kwargs: kwargs to be extended - :return: extended dictionary with common parameters - """ - spec = dict( - auth=__get_auth_dict(), - fetch_nested=dict(default=False, type='bool'), - nested_attributes=dict(type='list', default=list()), - ) - spec.update(kwargs) - return spec - - -# Left for third-party module compatibility -def ovirt_facts_full_argument_spec(**kwargs): - """ - This is deprecated. Please use ovirt_info_full_argument_spec instead! - - :param kwargs: kwargs to be extended - :return: extended dictionary with common parameters - """ - return ovirt_info_full_argument_spec(**kwargs) - - -def ovirt_full_argument_spec(**kwargs): - """ - Extend parameters of module with parameters which are common to all oVirt modules. - - :param kwargs: kwargs to be extended - :return: extended dictionary with common parameters - """ - spec = dict( - auth=__get_auth_dict(), - 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', default=list()), - ) - spec.update(kwargs) - return spec - - -def check_params(module): - """ - Most modules must have either `name` or `id` specified. - """ - if module.params.get('name') is None and module.params.get('id') is None: - module.fail_json(msg='"name" or "id" is required') - - -def engine_supported(connection, version): - return LooseVersion(engine_version(connection)) >= LooseVersion(version) - - -def check_support(version, connection, module, params): - """ - Check if parameters used by user are supported by oVirt Python SDK - and oVirt engine. - """ - api_version = LooseVersion(engine_version(connection)) - version = LooseVersion(version) - for param in params: - if module.params.get(param) is not None: - return LooseVersion(sdk_version.VERSION) >= version and api_version >= version - - return True - - -class BaseModule(object): - """ - This is base class for oVirt modules. oVirt modules should inherit this - class and override method to customize specific needs of the module. - The only abstract method of this class is `build_entity`, which must - to be implemented in child class. - """ - __metaclass__ = ABCMeta - - def __init__(self, connection, module, service, changed=False): - self._connection = connection - self._module = module - self._service = service - self._changed = changed - self._diff = {'after': dict(), 'before': dict()} - - @property - def changed(self): - return self._changed - - @changed.setter - def changed(self, changed): - if not self._changed: - self._changed = changed - - @abstractmethod - def build_entity(self): - """ - This method should return oVirt Python SDK type, which we want to - create or update, initialized by values passed by Ansible module. - - For example if we want to create VM, we will return following: - types.Vm(name=self._module.params['vm_name']) - - :return: Specific instance of sdk.Struct. - """ - pass - - def param(self, name, default=None): - """ - Return a module parameter specified by it's name. - """ - return self._module.params.get(name, default) - - def update_check(self, entity): - """ - This method handle checks whether the entity values are same as values - passed to ansible module. By default we don't compare any values. - - :param entity: Entity we want to compare with Ansible module values. - :return: True if values are same, so we don't need to update the entity. - """ - return True - - def pre_create(self, entity): - """ - This method is called right before entity is created. - - :param entity: Entity to be created or updated. - """ - pass - - def post_create(self, entity): - """ - This method is called right after entity is created. - - :param entity: Entity which was created. - """ - pass - - def post_update(self, entity): - """ - This method is called right after entity is updated. - - :param entity: Entity which was updated. - """ - pass - - def diff_update(self, after, update): - for k, v in update.items(): - if isinstance(v, 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, - update_params=None, - _wait=None, - force_create=False, - **kwargs - ): - """ - Method which is called when state of the entity is 'present'. If user - don't provide `entity` parameter the entity is searched using - `search_params` parameter. If entity is found it's updated, whether - the entity should be updated is checked by `update_check` method. - The corresponding updated entity is build by `build_entity` method. - - Function executed after entity is created can optionally be specified - in `post_create` parameter. Function executed after entity is updated - can optionally be specified in `post_update` parameter. - - :param entity: Entity we want to update, if exists. - :param result_state: State which should entity has in order to finish task. - :param fail_condition: Function which checks incorrect state of entity, if it returns `True` Exception is raised. - :param search_params: Dictionary of parameters to be used for search. - :param update_params: The params which should be passed to update method. - :param kwargs: Additional parameters passed when creating entity. - :return: Dictionary with values returned by Ansible module. - """ - if entity is None and not force_create: - entity = self.search_entity(search_params) - - self.pre_create(entity) - - if entity: - # 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: - update_params = update_params or {} - updated_entity = entity_service.update( - new_entity, - **update_params - ) - self.post_update(entity) - - # Update diffs only if user specified --diff parameter, - # 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: - if not self._module.check_mode: - entity = self._service.add( - self.build_entity(), - **kwargs - ) - self.post_create(entity) - self.changed = True - - if not self._module.check_mode: - # Wait for the entity to be created and to be in the defined state: - entity_service = self._service.service(entity.id) - - def state_condition(entity): - return entity - - if result_state: - - def state_condition(entity): - return entity and entity.status == result_state - - wait( - service=entity_service, - condition=state_condition, - fail_condition=fail_condition, - wait=_wait if _wait is not None else self._module.params['wait'], - timeout=self._module.params['timeout'], - poll_interval=self._module.params['poll_interval'], - ) - - return { - 'changed': self.changed, - 'id': getattr(entity, 'id', None), - type(entity).__name__.lower(): get_dict_of_struct( - struct=entity, - connection=self._connection, - fetch_nested=self._module.params.get('fetch_nested'), - attributes=self._module.params.get('nested_attributes'), - ), - 'diff': self._diff, - } - - def pre_remove(self, entity): - """ - This method is called right before entity is removed. - - :param entity: Entity which we want to remove. - """ - 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 - don't provide `entity` parameter the entity is searched using - `search_params` parameter. If entity is found it's removed. - - Function executed before remove is executed can optionally be specified - in `pre_remove` parameter. - - :param entity: Entity we want to remove. - :param search_params: Dictionary of parameters to be used for search. - :param kwargs: Additional parameters passed when removing entity. - :return: Dictionary with values returned by Ansible module. - """ - if entity is None: - entity = self.search_entity(search_params) - - if entity is None: - return { - 'changed': self.changed, - 'msg': "Entity wasn't found." - } - - self.pre_remove(entity) - - 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, - wait=self._module.params['wait'], - timeout=self._module.params['timeout'], - poll_interval=self._module.params['poll_interval'], - ) - self.changed = True - - return { - 'changed': self.changed, - 'id': entity.id, - type(entity).__name__.lower(): get_dict_of_struct( - struct=entity, - connection=self._connection, - fetch_nested=self._module.params.get('fetch_nested'), - attributes=self._module.params.get('nested_attributes'), - ), - } - - def action( - self, - action, - entity=None, - action_condition=lambda e: e, - wait_condition=lambda e: e, - fail_condition=lambda e: False, - pre_action=lambda e: e, - post_action=lambda e: None, - search_params=None, - **kwargs - ): - """ - This method is executed when we want to change the state of some oVirt - entity. The action to be executed on oVirt service is specified by - `action` parameter. Whether the action should be executed can be - specified by passing `action_condition` parameter. State which the - entity should be in after execution of the action can be specified - by `wait_condition` parameter. - - Function executed before an action on entity can optionally be specified - in `pre_action` parameter. Function executed after an action on entity can - optionally be specified in `post_action` parameter. - - :param action: Action which should be executed by service on entity. - :param entity: Entity we want to run action on. - :param action_condition: Function which is executed when checking if action should be executed. - :param fail_condition: Function which checks incorrect state of entity, if it returns `True` Exception is raised. - :param wait_condition: Function which is executed when waiting on result state. - :param pre_action: Function which is executed before running the action. - :param post_action: Function which is executed after running the action. - :param search_params: Dictionary of parameters to be used for search. - :param kwargs: Additional parameters passed to action. - :return: Dictionary with values returned by Ansible module. - """ - if entity is None: - entity = self.search_entity(search_params) - - entity = pre_action(entity) - - if entity is None: - self._module.fail_json( - msg="Entity not found, can't run action '{0}'.".format( - action - ) - ) - - entity_service = self._service.service(entity.id) - entity = entity_service.get() - if action_condition(entity): - if not self._module.check_mode: - getattr(entity_service, action)(**kwargs) - self.changed = True - - post_action(entity) - - wait( - service=self._service.service(entity.id), - condition=wait_condition, - fail_condition=fail_condition, - wait=self._module.params['wait'], - timeout=self._module.params['timeout'], - poll_interval=self._module.params['poll_interval'], - ) - return { - 'changed': self.changed, - 'id': entity.id, - type(entity).__name__.lower(): get_dict_of_struct( - struct=entity, - connection=self._connection, - fetch_nested=self._module.params.get('fetch_nested'), - attributes=self._module.params.get('nested_attributes'), - ), - 'diff': self._diff, - } - - def wait_for_import(self, condition=lambda e: True): - if self._module.params['wait']: - start = time.time() - timeout = self._module.params['timeout'] - poll_interval = self._module.params['poll_interval'] - while time.time() < start + timeout: - entity = self.search_entity() - if entity and condition(entity): - return entity - time.sleep(poll_interval) - - def search_entity(self, search_params=None, list_params=None): - """ - Always first try to search by `ID`, if ID isn't specified, - check if user constructed special search in `search_params`, - if not search by `name`. - """ - entity = None - - if 'id' in self._module.params and self._module.params['id'] is not None: - entity = get_entity(self._service.service(self._module.params['id']), get_params=list_params) - elif search_params is not None: - entity = search_by_attributes(self._service, list_params=list_params, **search_params) - elif self._module.params.get('name') is not None: - entity = search_by_attributes(self._service, list_params=list_params, name=self._module.params['name']) - - return entity - - def _get_major(self, full_version): - if full_version is None or full_version == "": - return None - if isinstance(full_version, otypes.Version): - return int(full_version.major) - return int(full_version.split('.')[0]) - - def _get_minor(self, full_version): - if full_version is None or full_version == "": - return None - if isinstance(full_version, otypes.Version): - return int(full_version.minor) - return int(full_version.split('.')[1]) - - -def _sdk4_error_maybe(): - """ - Allow for ovirtsdk4 not being installed. - """ - if HAS_SDK: - return sdk.Error - return type(None) - - -class OvirtRetry(CloudRetry): - base_class = _sdk4_error_maybe() - - @staticmethod - def status_code_from_exception(error): - return error.code - - @staticmethod - def found(response_code, catch_extra_error_codes=None): - # This is a list of error codes to retry. - retry_on = [ - # HTTP status: Conflict - 409, - ] - if catch_extra_error_codes: - retry_on.extend(catch_extra_error_codes) - - return response_code in retry_on diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_affinity_group.py b/lib/ansible/modules/cloud/ovirt/ovirt_affinity_group.py deleted file mode 100644 index 0711c2e24b..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_affinity_group.py +++ /dev/null @@ -1,329 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2017, Ansible Project -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - -DOCUMENTATION = ''' ---- -module: ovirt_affinity_group -short_description: Module to manage affinity groups in oVirt/RHV -version_added: "2.3" -author: -- Ondra Machacek (@machacekondra) -description: - - "This module manage affinity groups in oVirt/RHV. It can also manage assignments - of those groups to VMs." -options: - name: - description: - - Name of the affinity group to manage. - required: true - state: - description: - - Should the affinity group be present or absent. - choices: [ absent, present ] - default: present - cluster: - description: - - Name of the cluster of the affinity group. - description: - description: - - Description of the affinity group. - host_enforcing: - description: - - If I(yes) VM cannot start on host if it does not satisfy the C(host_rule). - - This parameter is support since oVirt/RHV 4.1 version. - type: bool - host_rule: - description: - - If I(positive) I(all) VMs in this group should run on the this host. - - If I(negative) I(no) VMs in this group should run on the this host. - - If I(disabled) this affinity group doesn't take effect. - - This parameter is support since oVirt/RHV 4.1 version. - choices: [ disabled, negative, positive ] - vm_enforcing: - description: - - If I(yes) VM cannot start if it does not satisfy the C(vm_rule). - type: bool - vm_rule: - description: - - If I(positive) I(all) VMs in this group should run on the host defined by C(host_rule). - - If I(negative) I(no) VMs in this group should run on the host defined by C(host_rule). - - If I(disabled) this affinity group doesn't take effect. - choices: [ disabled, negative, positive ] - vms: - description: - - List of the VMs names, which should have assigned this affinity group. - hosts: - description: - - List of the hosts names, which should have assigned this affinity group. - - This parameter is support since oVirt/RHV 4.1 version. -extends_documentation_fragment: ovirt -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -- name: Create(if not exists) and assign affinity group to VMs vm1 and vm2 and host host1 - ovirt_affinity_group: - name: mygroup - cluster: mycluster - vm_enforcing: true - vm_rule: positive - host_enforcing: true - host_rule: positive - vms: - - vm1 - - vm2 - hosts: - - host1 - -- name: Detach VMs from affinity group and disable VM rule - ovirt_affinity_group: - name: mygroup - cluster: mycluster - vm_enforcing: false - vm_rule: disabled - host_enforcing: true - host_rule: positive - vms: [] - hosts: - - host1 - - host2 - -- name: Remove affinity group - ovirt_affinity_group: - state: absent - cluster: mycluster - name: mygroup -''' - -RETURN = ''' -id: - description: ID of the affinity group which is managed - returned: On success if affinity group is found. - type: str - sample: 7de90f31-222c-436c-a1ca-7e655bd5b60c -affinity_group: - description: "Dictionary of all the affinity group attributes. Affinity group attributes can be found on your oVirt/RHV instance - at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/affinity_group." - returned: On success if affinity group is found. - type: str -''' - -import traceback - -try: - import ovirtsdk4.types as otypes -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - BaseModule, - check_sdk, - check_support, - create_connection, - get_id_by_name, - equal, - engine_supported, - ovirt_full_argument_spec, - search_by_name, -) - - -class AffinityGroupsModule(BaseModule): - - def __init__(self, vm_ids, host_ids, *args, **kwargs): - super(AffinityGroupsModule, self).__init__(*args, **kwargs) - self._vm_ids = vm_ids - self._host_ids = host_ids - - def update_vms(self, affinity_group): - """ - This method iterate via the affinity VM assignments and datech the VMs - which should not be attached to affinity and attach VMs which should be - attached to affinity. - """ - assigned_vms = self.assigned_vms(affinity_group) - to_remove = [vm for vm in assigned_vms if vm not in self._vm_ids] - to_add = [vm for vm in self._vm_ids if vm not in assigned_vms] - ag_service = self._service.group_service(affinity_group.id) - for vm in to_remove: - ag_service.vms_service().vm_service(vm).remove() - for vm in to_add: - # API return element instead of VM element, so we - # need to WA this issue, for oVirt/RHV versions having this bug: - try: - ag_service.vms_service().add(otypes.Vm(id=vm)) - except ValueError as ex: - if 'complete' not in str(ex): - raise ex - - def post_create(self, affinity_group): - self.update_vms(affinity_group) - - def post_update(self, affinity_group): - self.update_vms(affinity_group) - - def build_entity(self): - affinity_group = otypes.AffinityGroup( - name=self._module.params['name'], - description=self._module.params['description'], - positive=( - self._module.params['vm_rule'] == 'positive' - ) if self._module.params['vm_rule'] is not None else None, - enforcing=( - self._module.params['vm_enforcing'] - ) if self._module.params['vm_enforcing'] is not None else None, - ) - - # Those attributes are Supported since 4.1: - if not engine_supported(self._connection, '4.1'): - return affinity_group - - affinity_group.hosts_rule = otypes.AffinityRule( - positive=( - self.param('host_rule') == 'positive' - ) if self.param('host_rule') is not None else None, - enforcing=self.param('host_enforcing'), - ) if ( - self.param('host_enforcing') is not None or - self.param('host_rule') is not None - ) else None - - affinity_group.vms_rule = otypes.AffinityRule( - positive=( - self.param('vm_rule') == 'positive' - ) if self.param('vm_rule') is not None else None, - enforcing=self.param('vm_enforcing'), - enabled=( - self.param('vm_rule') in ['negative', 'positive'] - ) if self.param('vm_rule') is not None else None, - ) if ( - self.param('vm_enforcing') is not None or - self.param('vm_rule') is not None - ) else None - - affinity_group.hosts = [ - otypes.Host(id=host_id) for host_id in self._host_ids - ] if self._host_ids is not None else None - - return affinity_group - - def assigned_vms(self, affinity_group): - if getattr(affinity_group.vms, 'href', None): - return sorted([ - vm.id for vm in self._connection.follow_link(affinity_group.vms) - ]) - else: - return sorted([vm.id for vm in affinity_group.vms]) - - def update_check(self, entity): - assigned_vms = self.assigned_vms(entity) - do_update = ( - equal(self.param('description'), entity.description) and equal(self.param('vm_enforcing'), entity.enforcing) and equal( - self.param('vm_rule') == 'positive' if self.param('vm_rule') else None, - entity.positive - ) and equal(self._vm_ids, assigned_vms) - ) - # Following attributes is supported since 4.1, - # so return if it doesn't exist: - if not engine_supported(self._connection, '4.1'): - return do_update - - # Following is supported since 4.1: - return do_update and ( - equal( - self.param('host_rule') == 'positive' if self.param('host_rule') else None, - entity.hosts_rule.positive) and equal(self.param('host_enforcing'), entity.hosts_rule.enforcing) and equal( - self.param('vm_rule') in ['negative', 'positive'] if self.param('vm_rule') else None, - entity.vms_rule.enabled) and equal(self._host_ids, sorted([host.id for host in entity.hosts])) - ) - - -def main(): - argument_spec = ovirt_full_argument_spec( - state=dict(type='str', default='present', choices=['absent', 'present']), - cluster=dict(type='str', required=True), - name=dict(type='str', required=True), - description=dict(type='str'), - vm_enforcing=dict(type='bool'), - vm_rule=dict(type='str', choices=['disabled', 'negative', 'positive']), - host_enforcing=dict(type='bool'), - host_rule=dict(type='str', choices=['disabled', 'negative', 'positive']), - vms=dict(type='list'), - hosts=dict(type='list'), - ) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - ) - - check_sdk(module) - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - # Check if unsupported parameters were passed: - supported_41 = ('host_enforcing', 'host_rule', 'hosts') - if not check_support( - version='4.1', - connection=connection, - module=module, - params=supported_41, - ): - module.fail_json( - msg='Following parameters are supported since 4.1: {params}'.format( - params=supported_41, - ) - ) - clusters_service = connection.system_service().clusters_service() - vms_service = connection.system_service().vms_service() - hosts_service = connection.system_service().hosts_service() - cluster_name = module.params['cluster'] - cluster = search_by_name(clusters_service, cluster_name) - if cluster is None: - raise Exception("Cluster '%s' was not found." % cluster_name) - cluster_service = clusters_service.cluster_service(cluster.id) - affinity_groups_service = cluster_service.affinity_groups_service() - - # Fetch VM ids which should be assigned to affinity group: - vm_ids = sorted([ - get_id_by_name(vms_service, vm_name) - for vm_name in module.params['vms'] - ]) if module.params['vms'] is not None else None - # Fetch host ids which should be assigned to affinity group: - host_ids = sorted([ - get_id_by_name(hosts_service, host_name) - for host_name in module.params['hosts'] - ]) if module.params['hosts'] is not None else None - - affinity_groups_module = AffinityGroupsModule( - connection=connection, - module=module, - service=affinity_groups_service, - vm_ids=vm_ids, - host_ids=host_ids, - ) - - state = module.params['state'] - if state == 'present': - ret = affinity_groups_module.create() - elif state == 'absent': - ret = affinity_groups_module.remove() - - module.exit_json(**ret) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_affinity_label.py b/lib/ansible/modules/cloud/ovirt/ovirt_affinity_label.py deleted file mode 100644 index 6eae6f1db0..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_affinity_label.py +++ /dev/null @@ -1,210 +0,0 @@ -#!/usr/bin/python -# -*- 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 . -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_affinity_label -short_description: Module to manage affinity labels in oVirt/RHV -version_added: "2.3" -author: "Ondra Machacek (@machacekondra)" -description: - - "This module manage affinity labels in oVirt/RHV. It can also manage assignments - of those labels to hosts and VMs." -options: - name: - description: - - "Name of the affinity label to manage." - required: true - state: - description: - - "Should the affinity label be present or absent." - choices: ['present', 'absent'] - default: present - cluster: - description: - - "Name of the cluster where vms and hosts resides." - vms: - description: - - "List of the VMs names, which should have assigned this affinity label." - hosts: - description: - - "List of the hosts names, which should have assigned this affinity label." -extends_documentation_fragment: ovirt -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Create(if not exists) and assign affinity label to vms vm1 and vm2 and host host1 -- ovirt_affinity_label: - name: mylabel - cluster: mycluster - vms: - - vm1 - - vm2 - hosts: - - host1 - -# To detach all VMs from label -- ovirt_affinity_label: - name: mylabel - cluster: mycluster - vms: [] - -# Remove affinity label -- ovirt_affinity_label: - state: absent - name: mylabel -''' - -RETURN = ''' -id: - description: ID of the affinity label which is managed - returned: On success if affinity label is found. - type: str - sample: 7de90f31-222c-436c-a1ca-7e655bd5b60c -affinity_label: - description: "Dictionary of all the affinity label attributes. Affinity label attributes can be found on your oVirt/RHV instance - at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/affinity_label." - type: dict - returned: On success if affinity label is found. -''' - -import traceback - -try: - import ovirtsdk4.types as otypes -except ImportError: - pass - -from collections import defaultdict -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - BaseModule, - check_sdk, - create_connection, - ovirt_full_argument_spec, -) - - -class AffinityLabelsModule(BaseModule): - - def build_entity(self): - return otypes.AffinityLabel(name=self._module.params['name']) - - def post_create(self, entity): - self.update_check(entity) - - def pre_remove(self, entity): - self._module.params['vms'] = [] - self._module.params['hosts'] = [] - self.update_check(entity) - - def _update_label_assignments(self, entity, name, label_obj_type): - objs_service = getattr(self._connection.system_service(), '%s_service' % name)() - if self._module.params[name] is not None: - objs = self._connection.follow_link(getattr(entity, name)) - objs_names = defaultdict(list) - for obj in objs: - labeled_entity = objs_service.service(obj.id).get() - if self._module.params['cluster'] is None: - objs_names[labeled_entity.name].append(obj.id) - elif self._connection.follow_link(labeled_entity.cluster).name == self._module.params['cluster']: - objs_names[labeled_entity.name].append(obj.id) - - for obj in self._module.params[name]: - if obj not in objs_names: - for obj_id in objs_service.list( - search='name=%s and cluster=%s' % (obj, self._module.params['cluster']) - ): - label_service = getattr(self._service.service(entity.id), '%s_service' % name)() - if not self._module.check_mode: - label_service.add(**{ - name[:-1]: label_obj_type(id=obj_id.id) - }) - self.changed = True - - for obj in objs_names: - if obj not in self._module.params[name]: - label_service = getattr(self._service.service(entity.id), '%s_service' % name)() - if not self._module.check_mode: - for obj_id in objs_names[obj]: - label_service.service(obj_id).remove() - self.changed = True - - def update_check(self, entity): - self._update_label_assignments(entity, 'vms', otypes.Vm) - self._update_label_assignments(entity, 'hosts', otypes.Host) - return True - - -def main(): - argument_spec = ovirt_full_argument_spec( - state=dict( - choices=['present', 'absent'], - default='present', - ), - cluster=dict(default=None), - name=dict(default=None, required=True), - vms=dict(default=None, type='list'), - hosts=dict(default=None, type='list'), - ) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - required_if=[ - ('state', 'present', ['cluster']), - ], - ) - - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - affinity_labels_service = connection.system_service().affinity_labels_service() - affinity_labels_module = AffinityLabelsModule( - connection=connection, - module=module, - service=affinity_labels_service, - ) - - state = module.params['state'] - if state == 'present': - ret = affinity_labels_module.create() - elif state == 'absent': - ret = affinity_labels_module.remove() - - module.exit_json(**ret) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_affinity_label_info.py b/lib/ansible/modules/cloud/ovirt/ovirt_affinity_label_info.py deleted file mode 100644 index 4a9babcfba..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_affinity_label_info.py +++ /dev/null @@ -1,182 +0,0 @@ -#!/usr/bin/python -# -*- 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 . -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_affinity_label_info -short_description: Retrieve information about one or more oVirt/RHV affinity labels -author: "Ondra Machacek (@machacekondra)" -version_added: "2.3" -description: - - "Retrieve information about one or more oVirt/RHV affinity labels." - - This module was called C(ovirt_affinity_label_facts) before Ansible 2.9, returning C(ansible_facts). - Note that the M(ovirt_affinity_label_info) module no longer returns C(ansible_facts)! -notes: - - "This module returns a variable C(ovirt_affinity_labels), which - contains a list of affinity labels. You need to register the result with - the I(register) keyword to use it." -options: - name: - description: - - "Name of the affinity labels which should be listed." - vm: - description: - - "Name of the VM, which affinity labels should be listed." - host: - description: - - "Name of the host, which affinity labels should be listed." -extends_documentation_fragment: ovirt_info -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Gather information about all affinity labels, which names start with C(label): -- ovirt_affinity_label_info: - name: label* - register: result -- debug: - msg: "{{ result.ovirt_affinity_labels }}" - -# Gather information about all affinity labels, which are assigned to VMs -# which names start with C(postgres): -- ovirt_affinity_label_info: - vm: postgres* - register: result -- debug: - msg: "{{ result.ovirt_affinity_labels }}" - -# Gather information about all affinity labels, which are assigned to hosts -# which names start with C(west): -- ovirt_affinity_label_info: - host: west* - register: result -- debug: - msg: "{{ result.ovirt_affinity_labels }}" - -# Gather information about all affinity labels, which are assigned to hosts -# which names start with C(west) or VMs which names start with C(postgres): -- ovirt_affinity_label_info: - host: west* - vm: postgres* - register: result -- debug: - msg: "{{ result.ovirt_affinity_labels }}" -''' - -RETURN = ''' -ovirt_affinity_labels: - description: "List of dictionaries describing the affinity labels. Affinity labels attributes are mapped to dictionary keys, - all affinity labels attributes can be found at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/affinity_label." - returned: On success. - type: list -''' - -import fnmatch -import traceback - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - check_sdk, - create_connection, - get_dict_of_struct, - ovirt_info_full_argument_spec, - search_by_name, -) - - -def main(): - argument_spec = ovirt_info_full_argument_spec( - name=dict(default=None), - host=dict(default=None), - vm=dict(default=None), - ) - module = AnsibleModule(argument_spec) - is_old_facts = module._name == 'ovirt_affinity_label_facts' - if is_old_facts: - module.deprecate("The 'ovirt_affinity_label_facts' module has been renamed to 'ovirt_affinity_label_info', " - "and the renamed one no longer returns ansible_facts", version='2.13') - - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - affinity_labels_service = connection.system_service().affinity_labels_service() - labels = [] - all_labels = affinity_labels_service.list() - if module.params['name']: - labels.extend([ - l for l in all_labels - if fnmatch.fnmatch(l.name, module.params['name']) - ]) - if module.params['host']: - hosts_service = connection.system_service().hosts_service() - if search_by_name(hosts_service, module.params['host']) is None: - raise Exception("Host '%s' was not found." % module.params['host']) - labels.extend([ - label - for label in all_labels - for host in connection.follow_link(label.hosts) - if fnmatch.fnmatch(hosts_service.service(host.id).get().name, module.params['host']) - ]) - if module.params['vm']: - vms_service = connection.system_service().vms_service() - if search_by_name(vms_service, module.params['vm']) is None: - raise Exception("Vm '%s' was not found." % module.params['vm']) - labels.extend([ - label - for label in all_labels - for vm in connection.follow_link(label.vms) - if fnmatch.fnmatch(vms_service.service(vm.id).get().name, module.params['vm']) - ]) - - if not (module.params['vm'] or module.params['host'] or module.params['name']): - labels = all_labels - - result = dict( - ovirt_affinity_labels=[ - get_dict_of_struct( - struct=l, - connection=connection, - fetch_nested=module.params.get('fetch_nested'), - attributes=module.params.get('nested_attributes'), - ) for l in labels - ], - ) - if is_old_facts: - module.exit_json(changed=False, ansible_facts=result) - else: - module.exit_json(changed=False, **result) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_api_info.py b/lib/ansible/modules/cloud/ovirt/ovirt_api_info.py deleted file mode 100644 index e639ea4982..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_api_info.py +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright (c) 2017 Ansible Project -# 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 - - -ANSIBLE_METADATA = { - 'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community' -} - - -DOCUMENTATION = ''' ---- -module: ovirt_api_info -short_description: Retrieve information about the oVirt/RHV API -author: "Ondra Machacek (@machacekondra)" -version_added: "2.5" -description: - - "Retrieve information about the oVirt/RHV API." - - This module was called C(ovirt_api_facts) before Ansible 2.9, returning C(ansible_facts). - Note that the M(ovirt_api_info) module no longer returns C(ansible_facts)! -notes: - - "This module returns a variable C(ovirt_api), - which contains a information about oVirt/RHV API. You need to register the result with - the I(register) keyword to use it." -extends_documentation_fragment: ovirt_info -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Gather information oVirt API: -- ovirt_api_info: - register: result -- debug: - msg: "{{ result.ovirt_api }}" -''' - -RETURN = ''' -ovirt_api: - description: "Dictionary describing the oVirt API information. - Api attributes are mapped to dictionary keys, - all API attributes can be found at following - url: https://ovirt.example.com/ovirt-engine/api/model#types/api." - returned: On success. - type: dict -''' - -import traceback - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - check_sdk, - create_connection, - get_dict_of_struct, - ovirt_info_full_argument_spec, -) - - -def main(): - argument_spec = ovirt_info_full_argument_spec() - module = AnsibleModule(argument_spec) - is_old_facts = module._name == 'ovirt_api_facts' - if is_old_facts: - module.deprecate("The 'ovirt_api_facts' module has been renamed to 'ovirt_api_info', " - "and the renamed one no longer returns ansible_facts", version='2.13') - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - api = connection.system_service().get() - result = dict( - ovirt_api=get_dict_of_struct( - struct=api, - connection=connection, - fetch_nested=module.params.get('fetch_nested'), - attributes=module.params.get('nested_attributes'), - ) - ) - if is_old_facts: - module.exit_json(changed=False, ansible_facts=result) - else: - module.exit_json(changed=False, **result) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_auth.py b/lib/ansible/modules/cloud/ovirt/ovirt_auth.py deleted file mode 100644 index c8f7407b24..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_auth.py +++ /dev/null @@ -1,300 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (c) 2016 Red Hat, Inc. -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_auth -short_description: "Module to manage authentication to oVirt/RHV" -author: "Ondra Machacek (@machacekondra)" -version_added: "2.2" -description: - - "This module authenticates to oVirt/RHV engine and creates SSO token, which should be later used in - all other oVirt/RHV modules, so all modules don't need to perform login and logout. - This module returns an Ansible fact called I(ovirt_auth). Every module can use this - fact as C(auth) parameter, to perform authentication." -options: - state: - default: present - choices: ['present', 'absent'] - description: - - "Specifies if a token should be created or revoked." - username: - required: False - description: - - "The name of the user. For example: I(admin@internal) - Default value is set by I(OVIRT_USERNAME) environment variable." - password: - required: False - description: - - "The password of the user. Default value is set by I(OVIRT_PASSWORD) environment variable." - token: - required: False - description: - - "SSO token to be used instead of login with username/password. - Default value is set by I(OVIRT_TOKEN) environment variable." - version_added: 2.5 - url: - required: False - description: - - "A string containing the API URL of the server. - For example: I(https://server.example.com/ovirt-engine/api). - Default value is set by I(OVIRT_URL) environment variable." - - "Either C(url) or C(hostname) is required." - hostname: - required: False - description: - - "A string containing the hostname of the server. - For example: I(server.example.com). - Default value is set by I(OVIRT_HOSTNAME) environment variable." - - "Either C(url) or C(hostname) is required." - version_added: "2.6" - insecure: - required: False - description: - - "A boolean flag that indicates if the server TLS certificate and host name should be checked." - type: bool - ca_file: - required: False - description: - - "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. - Default value is set by I(OVIRT_CAFILE) environment variable." - timeout: - required: False - description: - - "The maximum total time to wait for the response, in - seconds. A value of zero (the default) means wait forever. If - the timeout expires before the response is received an exception - will be raised." - compress: - required: False - description: - - "A boolean flag indicating if the SDK should ask - the server to send compressed responses. The default is I(True). - Note that this is a hint for the server, and that it may return - uncompressed data even when this parameter is set to I(True)." - type: bool - kerberos: - required: False - description: - - "A boolean flag indicating if Kerberos authentication - should be used instead of the default basic authentication." - type: bool - headers: - required: False - description: - - "A dictionary of HTTP headers to be added to each API call." - version_added: "2.4" - -requirements: - - python >= 2.7 - - ovirt-engine-sdk-python >= 4.3.0 -notes: - - "Everytime you use ovirt_auth module to obtain ticket, you need to also revoke the ticket, - when you no longer need it, otherwise the ticket would be revoked by engine when it expires. - For an example of how to achieve that, please take a look at I(examples) section." - - "In order to use this module you have to install oVirt/RHV Python SDK. - To ensure it's installed with correct version you can create the following task: - I(pip: name=ovirt-engine-sdk-python version=4.3.0)" - - "Note that in oVirt/RHV 4.1 if you want to use a user which is not administrator - you must enable the I(ENGINE_API_FILTER_BY_DEFAULT) variable in engine. In - oVirt/RHV 4.2 and later it's enabled by default." -''' - -EXAMPLES = ''' - - block: - # Create a vault with `ovirt_password` variable which store your - # oVirt/RHV user's password, and include that yaml file with variable: - - include_vars: ovirt_password.yml - - - name: Obtain SSO token with using username/password credentials - ovirt_auth: - url: https://ovirt.example.com/ovirt-engine/api - username: admin@internal - ca_file: ca.pem - password: "{{ ovirt_password }}" - - # Previous task generated I(ovirt_auth) fact, which you can later use - # in different modules as follows: - - ovirt_vm: - auth: "{{ ovirt_auth }}" - state: absent - name: myvm - - always: - - name: Always revoke the SSO token - ovirt_auth: - state: absent - ovirt_auth: "{{ ovirt_auth }}" - -# When user will set following environment variables: -# OVIRT_URL = https://fqdn/ovirt-engine/api -# OVIRT_USERNAME = admin@internal -# OVIRT_PASSWORD = the_password -# User can login the oVirt using environment variable instead of variables -# in yaml file. -# This is mainly useful when using Ansible Tower or AWX, as it will work -# for Red Hat Virtualization credentials type. - - name: Obtain SSO token - ovirt_auth: - state: present -''' - -RETURN = ''' -ovirt_auth: - description: Authentication facts, needed to perform authentication to oVirt/RHV. - returned: success - type: complex - contains: - token: - description: SSO token which is used for connection to oVirt/RHV engine. - returned: success - type: str - sample: "kdfVWp9ZgeewBXV-iq3Js1-xQJZPSEQ334FLb3eksoEPRaab07DhZ8ED8ghz9lJd-MQ2GqtRIeqhvhCkrUWQPw" - url: - description: URL of the oVirt/RHV engine API endpoint. - returned: success - type: str - sample: "https://ovirt.example.com/ovirt-engine/api" - ca_file: - description: CA file, which is used to verify SSL/TLS connection. - returned: success - type: str - sample: "ca.pem" - insecure: - description: Flag indicating if insecure connection is used. - returned: success - type: bool - sample: False - timeout: - description: Number of seconds to wait for response. - returned: success - type: int - sample: 0 - compress: - description: Flag indicating if compression is used for connection. - returned: success - type: bool - sample: True - kerberos: - description: Flag indicating if kerberos is used for authentication. - returned: success - type: bool - sample: False - headers: - description: Dictionary of HTTP headers to be added to each API call. - returned: success - type: dict -''' - -import os -import traceback - -try: - import ovirtsdk4 as sdk -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import check_sdk - - -def main(): - module = AnsibleModule( - argument_spec=dict( - url=dict(default=None), - hostname=dict(default=None), - username=dict(default=None), - password=dict(default=None, no_log=True), - ca_file=dict(default=None, type='path'), - insecure=dict(required=False, type='bool', default=None), - timeout=dict(required=False, type='int', default=0), - compress=dict(required=False, type='bool', default=True), - kerberos=dict(required=False, type='bool', default=False), - headers=dict(required=False, type='dict'), - state=dict(default='present', choices=['present', 'absent']), - token=dict(default=None), - ovirt_auth=dict(required=None, type='dict'), - ), - required_if=[ - ('state', 'absent', ['ovirt_auth']), - ], - supports_check_mode=True, - ) - check_sdk(module) - - state = module.params.get('state') - if state == 'present': - params = module.params - elif state == 'absent': - params = module.params['ovirt_auth'] - - def get_required_parameter(param, env_var, required=False): - var = params.get(param) or os.environ.get(env_var) - if not var and required and state == 'present': - module.fail_json(msg="'%s' is a required parameter." % param) - - return var - - url = get_required_parameter('url', 'OVIRT_URL', required=False) - hostname = get_required_parameter('hostname', 'OVIRT_HOSTNAME', required=False) - if url is None and hostname is None: - module.fail_json(msg="You must specify either 'url' or 'hostname'.") - - if url is None and hostname is not None: - url = 'https://{0}/ovirt-engine/api'.format(hostname) - - username = get_required_parameter('username', 'OVIRT_USERNAME') - password = get_required_parameter('password', 'OVIRT_PASSWORD') - token = get_required_parameter('token', 'OVIRT_TOKEN') - ca_file = get_required_parameter('ca_file', 'OVIRT_CAFILE') - insecure = params.get('insecure') if params.get('insecure') is not None else not bool(ca_file) - - connection = sdk.Connection( - url=url, - username=username, - password=password, - ca_file=ca_file, - insecure=insecure, - timeout=params.get('timeout'), - compress=params.get('compress'), - kerberos=params.get('kerberos'), - headers=params.get('headers'), - token=token, - ) - try: - token = connection.authenticate() - module.exit_json( - changed=False, - ansible_facts=dict( - ovirt_auth=dict( - token=token, - url=url, - ca_file=ca_file, - insecure=insecure, - timeout=params.get('timeout'), - compress=params.get('compress'), - kerberos=params.get('kerberos'), - headers=params.get('headers'), - ) if state == 'present' else dict() - ) - ) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - # Close the connection, but don't revoke token - connection.close(logout=state == 'absent') - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_cluster.py b/lib/ansible/modules/cloud/ovirt/ovirt_cluster.py deleted file mode 100644 index dc15c61604..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_cluster.py +++ /dev/null @@ -1,745 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (c) 2016 Red Hat, Inc. -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_cluster -short_description: Module to manage clusters in oVirt/RHV -version_added: "2.3" -author: "Ondra Machacek (@machacekondra)" -description: - - "Module to manage clusters in oVirt/RHV" -options: - id: - description: - - "ID of the cluster to manage." - version_added: "2.8" - name: - description: - - "Name of the cluster to manage." - required: true - state: - description: - - "Should the cluster be present or absent." - choices: ['present', 'absent'] - default: present - data_center: - description: - - "Datacenter name where cluster reside." - description: - description: - - "Description of the cluster." - comment: - description: - - "Comment of the cluster." - network: - description: - - "Management network of cluster to access cluster hosts." - ballooning: - description: - - "If I(True) enable memory balloon optimization. Memory balloon is used to - re-distribute / reclaim the host memory based on VM needs - in a dynamic way." - type: bool - virt: - description: - - "If I(True), hosts in this cluster will be used to run virtual machines." - type: bool - gluster: - description: - - "If I(True), hosts in this cluster will be used as Gluster Storage - server nodes, and not for running virtual machines." - - "By default the cluster is created for virtual machine hosts." - type: bool - threads_as_cores: - description: - - "If I(True) the exposed host threads would be treated as cores - which can be utilized by virtual machines." - type: bool - ksm: - description: - - "I I(True) MoM enables to run Kernel Same-page Merging I(KSM) when - necessary and when it can yield a memory saving benefit that - outweighs its CPU cost." - type: bool - ksm_numa: - description: - - "If I(True) enables KSM C(ksm) for best performance inside NUMA nodes." - type: bool - ha_reservation: - description: - - "If I(True) enables the oVirt/RHV to monitor cluster capacity for highly - available virtual machines." - type: bool - trusted_service: - description: - - "If I(True) enables integration with an OpenAttestation server." - type: bool - vm_reason: - description: - - "If I(True) enables an optional reason field when a virtual machine - is shut down from the Manager, allowing the administrator to - provide an explanation for the maintenance." - type: bool - host_reason: - description: - - "If I(True) enables an optional reason field when a host is placed - into maintenance mode from the Manager, allowing the administrator - to provide an explanation for the maintenance." - type: bool - memory_policy: - description: - - "I(disabled) - Disables memory page sharing." - - "I(server) - Sets the memory page sharing threshold to 150% of the system memory on each host." - - "I(desktop) - Sets the memory page sharing threshold to 200% of the system memory on each host." - choices: ['disabled', 'server', 'desktop'] - rng_sources: - description: - - "List that specify the random number generator devices that all hosts in the cluster will use." - - "Supported generators are: I(hwrng) and I(random)." - spice_proxy: - description: - - "The proxy by which the SPICE client will connect to virtual machines." - - "The address must be in the following format: I(protocol://[host]:[port])" - fence_enabled: - description: - - "If I(True) enables fencing on the cluster." - - "Fencing is enabled by default." - type: bool - fence_skip_if_gluster_bricks_up: - description: - - "A flag indicating if fencing should be skipped if Gluster bricks are up and running in the host being fenced." - - "This flag is optional, and the default value is `false`." - type: bool - version_added: "2.8" - fence_skip_if_gluster_quorum_not_met: - description: - - "A flag indicating if fencing should be skipped if Gluster bricks are up and running and Gluster quorum will not - be met without those bricks." - - "This flag is optional, and the default value is `false`." - type: bool - version_added: "2.8" - fence_skip_if_sd_active: - description: - - "If I(True) any hosts in the cluster that are Non Responsive - and still connected to storage will not be fenced." - type: bool - fence_skip_if_connectivity_broken: - description: - - "If I(True) fencing will be temporarily disabled if the percentage - of hosts in the cluster that are experiencing connectivity issues - is greater than or equal to the defined threshold." - - "The threshold can be specified by C(fence_connectivity_threshold)." - type: bool - fence_connectivity_threshold: - description: - - "The threshold used by C(fence_skip_if_connectivity_broken)." - resilience_policy: - description: - - "The resilience policy defines how the virtual machines are prioritized in the migration." - - "Following values are supported:" - - "C(do_not_migrate) - Prevents virtual machines from being migrated. " - - "C(migrate) - Migrates all virtual machines in order of their defined priority." - - "C(migrate_highly_available) - Migrates only highly available virtual machines to prevent overloading other hosts." - choices: ['do_not_migrate', 'migrate', 'migrate_highly_available'] - migration_bandwidth: - description: - - "The bandwidth settings define the maximum bandwidth of both outgoing and incoming migrations per host." - - "Following bandwidth options are supported:" - - "C(auto) - Bandwidth is copied from the I(rate limit) [Mbps] setting in the data center host network QoS." - - "C(hypervisor_default) - Bandwidth is controlled by local VDSM setting on sending host." - - "C(custom) - Defined by user (in Mbps)." - choices: ['auto', 'hypervisor_default', 'custom'] - migration_bandwidth_limit: - description: - - "Set the I(custom) migration bandwidth limit." - - "This parameter is used only when C(migration_bandwidth) is I(custom)." - migration_auto_converge: - description: - - "If I(True) auto-convergence is used during live migration of virtual machines." - - "Used only when C(migration_policy) is set to I(legacy)." - - "Following options are supported:" - - "C(true) - Override the global setting to I(true)." - - "C(false) - Override the global setting to I(false)." - - "C(inherit) - Use value which is set globally." - choices: ['true', 'false', 'inherit'] - migration_compressed: - description: - - "If I(True) compression is used during live migration of the virtual machine." - - "Used only when C(migration_policy) is set to I(legacy)." - - "Following options are supported:" - - "C(true) - Override the global setting to I(true)." - - "C(false) - Override the global setting to I(false)." - - "C(inherit) - Use value which is set globally." - choices: ['true', 'false', 'inherit'] - migration_policy: - description: - - "A migration policy defines the conditions for live migrating - virtual machines in the event of host failure." - - "Following policies are supported:" - - "C(legacy) - Legacy behavior of 3.6 version." - - "C(minimal_downtime) - Virtual machines should not experience any significant downtime." - - "C(suspend_workload) - Virtual machines may experience a more significant downtime." - - "C(post_copy) - Virtual machines should not experience any significant downtime. - If the VM migration is not converging for a long time, the migration will be switched to post-copy. - Added in version I(2.4)." - choices: ['legacy', 'minimal_downtime', 'suspend_workload', 'post_copy'] - serial_policy: - description: - - "Specify a serial number policy for the virtual machines in the cluster." - - "Following options are supported:" - - "C(vm) - Sets the virtual machine's UUID as its serial number." - - "C(host) - Sets the host's UUID as the virtual machine's serial number." - - "C(custom) - Allows you to specify a custom serial number in C(serial_policy_value)." - serial_policy_value: - description: - - "Allows you to specify a custom serial number." - - "This parameter is used only when C(serial_policy) is I(custom)." - scheduling_policy: - description: - - "Name of the scheduling policy to be used for cluster." - scheduling_policy_properties: - description: - - "Custom scheduling policy properties of the cluster." - - "These optional properties override the properties of the - scheduling policy specified by the C(scheduling_policy) parameter." - version_added: "2.6" - cpu_arch: - description: - - "CPU architecture of cluster." - choices: ['x86_64', 'ppc64', 'undefined'] - cpu_type: - description: - - "CPU codename. For example I(Intel SandyBridge Family)." - switch_type: - description: - - "Type of switch to be used by all networks in given cluster. - Either I(legacy) which is using linux bridge or I(ovs) using - Open vSwitch." - choices: ['legacy', 'ovs'] - compatibility_version: - description: - - "The compatibility version of the cluster. All hosts in this - cluster must support at least this compatibility version." - mac_pool: - description: - - "MAC pool to be used by this cluster." - - "C(Note:)" - - "This is supported since oVirt version 4.1." - version_added: 2.4 - external_network_providers: - description: - - "List of references to the external network providers available - in the cluster. If the automatic deployment of the external - network provider is supported, the networks of the referenced - network provider are available on every host in the cluster." - - "This is supported since oVirt version 4.2." - suboptions: - name: - description: - - Name of the external network provider. Either C(name) or C(id) is required. - id: - description: - - ID of the external network provider. Either C(name) or C(id) is required. - version_added: 2.5 - firewall_type: - description: - - "The type of firewall to be used on hosts in this cluster." - - "Up to version 4.1, it was always I(iptables). Since version 4.2, you can choose between I(iptables) and I(firewalld). - For clusters with a compatibility version of 4.2 and higher, the default firewall type is I(firewalld)." - type: str - version_added: 2.8 - choices: ['firewalld', 'iptables'] - gluster_tuned_profile: - description: - - "The name of the U(https://fedorahosted.org/tuned) to set on all the hosts in the cluster. This is not mandatory - and relevant only for clusters with Gluster service." - - "Could be for example I(virtual-host), I(rhgs-sequential-io), I(rhgs-random-io)" - version_added: 2.8 - type: str -extends_documentation_fragment: ovirt -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Create cluster -- ovirt_cluster: - data_center: mydatacenter - name: mycluster - cpu_type: Intel SandyBridge Family - description: mycluster - compatibility_version: 4.0 - -# Create virt service cluster: -- ovirt_cluster: - data_center: mydatacenter - name: mycluster - cpu_type: Intel Nehalem Family - description: mycluster - switch_type: legacy - compatibility_version: 4.0 - ballooning: true - gluster: false - threads_as_cores: true - ha_reservation: true - trusted_service: false - host_reason: false - vm_reason: true - ksm_numa: true - memory_policy: server - rng_sources: - - hwrng - - random - -# Create cluster with default network provider -- ovirt_cluster: - name: mycluster - data_center: Default - cpu_type: Intel SandyBridge Family - external_network_providers: - - name: ovirt-provider-ovn - -# Remove cluster -- ovirt_cluster: - state: absent - name: mycluster - -# Change cluster Name -- ovirt_cluster: - id: 00000000-0000-0000-0000-000000000000 - name: "new_cluster_name" -''' - -RETURN = ''' -id: - description: ID of the cluster which is managed - returned: On success if cluster is found. - type: str - sample: 7de90f31-222c-436c-a1ca-7e655bd5b60c -cluster: - description: "Dictionary of all the cluster attributes. Cluster attributes can be found on your oVirt/RHV instance - at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/cluster." - type: dict - returned: On success if cluster is found. -''' - -import traceback - -try: - import ovirtsdk4.types as otypes -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - BaseModule, - check_sdk, - create_connection, - equal, - ovirt_full_argument_spec, - search_by_name, - get_id_by_name, -) - - -class ClustersModule(BaseModule): - - def __get_major(self, full_version): - if full_version is None: - return None - if isinstance(full_version, otypes.Version): - return full_version.major - return int(full_version.split('.')[0]) - - def __get_minor(self, full_version): - if full_version is None: - return None - if isinstance(full_version, otypes.Version): - return full_version.minor - return int(full_version.split('.')[1]) - - def param(self, name, default=None): - return self._module.params.get(name, default) - - def _get_memory_policy(self): - memory_policy = self.param('memory_policy') - if memory_policy == 'desktop': - return 200 - elif memory_policy == 'server': - return 150 - elif memory_policy == 'disabled': - return 100 - - def _get_policy_id(self): - # These are hardcoded IDs, once there is API, please fix this. - # legacy - 00000000-0000-0000-0000-000000000000 - # minimal downtime - 80554327-0569-496b-bdeb-fcbbf52b827b - # suspend workload if needed - 80554327-0569-496b-bdeb-fcbbf52b827c - # post copy - a7aeedb2-8d66-4e51-bb22-32595027ce71 - migration_policy = self.param('migration_policy') - if migration_policy == 'legacy': - return '00000000-0000-0000-0000-000000000000' - elif migration_policy == 'minimal_downtime': - return '80554327-0569-496b-bdeb-fcbbf52b827b' - elif migration_policy == 'suspend_workload': - return '80554327-0569-496b-bdeb-fcbbf52b827c' - elif migration_policy == 'post_copy': - return 'a7aeedb2-8d66-4e51-bb22-32595027ce71' - - def _get_sched_policy(self): - sched_policy = None - if self.param('scheduling_policy'): - sched_policies_service = self._connection.system_service().scheduling_policies_service() - sched_policy = search_by_name(sched_policies_service, self.param('scheduling_policy')) - if not sched_policy: - raise Exception("Scheduling policy '%s' was not found" % self.param('scheduling_policy')) - - return sched_policy - - def _get_mac_pool(self): - mac_pool = None - if self._module.params.get('mac_pool'): - mac_pool = search_by_name( - self._connection.system_service().mac_pools_service(), - self._module.params.get('mac_pool'), - ) - - return mac_pool - - def _get_external_network_providers(self): - return self.param('external_network_providers') or [] - - def _get_external_network_provider_id(self, external_provider): - return external_provider.get('id') or get_id_by_name( - self._connection.system_service().openstack_network_providers_service(), - external_provider.get('name') - ) - - def _get_external_network_providers_entity(self): - if self.param('external_network_providers') is not None: - return [otypes.ExternalProvider(id=self._get_external_network_provider_id(external_provider)) - for external_provider in self.param('external_network_providers')] - - def build_entity(self): - sched_policy = self._get_sched_policy() - return otypes.Cluster( - id=self.param('id'), - name=self.param('name'), - comment=self.param('comment'), - description=self.param('description'), - ballooning_enabled=self.param('ballooning'), - gluster_service=self.param('gluster'), - virt_service=self.param('virt'), - threads_as_cores=self.param('threads_as_cores'), - ha_reservation=self.param('ha_reservation'), - trusted_service=self.param('trusted_service'), - optional_reason=self.param('vm_reason'), - maintenance_reason_required=self.param('host_reason'), - scheduling_policy=otypes.SchedulingPolicy( - id=sched_policy.id, - ) if sched_policy else None, - serial_number=otypes.SerialNumber( - policy=otypes.SerialNumberPolicy(self.param('serial_policy')), - value=self.param('serial_policy_value'), - ) if ( - self.param('serial_policy') is not None or - self.param('serial_policy_value') is not None - ) else None, - migration=otypes.MigrationOptions( - auto_converge=otypes.InheritableBoolean( - self.param('migration_auto_converge'), - ) if self.param('migration_auto_converge') else None, - bandwidth=otypes.MigrationBandwidth( - assignment_method=otypes.MigrationBandwidthAssignmentMethod( - self.param('migration_bandwidth'), - ) if self.param('migration_bandwidth') else None, - custom_value=self.param('migration_bandwidth_limit'), - ) if ( - self.param('migration_bandwidth') or - self.param('migration_bandwidth_limit') - ) else None, - compressed=otypes.InheritableBoolean( - self.param('migration_compressed'), - ) if self.param('migration_compressed') else None, - policy=otypes.MigrationPolicy( - id=self._get_policy_id() - ) if self.param('migration_policy') else None, - ) if ( - self.param('migration_bandwidth') is not None or - self.param('migration_bandwidth_limit') is not None or - self.param('migration_auto_converge') is not None or - self.param('migration_compressed') is not None or - self.param('migration_policy') is not None - ) else None, - error_handling=otypes.ErrorHandling( - on_error=otypes.MigrateOnError( - self.param('resilience_policy') - ), - ) if self.param('resilience_policy') else None, - fencing_policy=otypes.FencingPolicy( - enabled=self.param('fence_enabled'), - skip_if_gluster_bricks_up=self.param('fence_skip_if_gluster_bricks_up'), - skip_if_gluster_quorum_not_met=self.param('fence_skip_if_gluster_quorum_not_met'), - skip_if_connectivity_broken=otypes.SkipIfConnectivityBroken( - enabled=self.param('fence_skip_if_connectivity_broken'), - threshold=self.param('fence_connectivity_threshold'), - ) if ( - self.param('fence_skip_if_connectivity_broken') is not None or - self.param('fence_connectivity_threshold') is not None - ) else None, - skip_if_sd_active=otypes.SkipIfSdActive( - enabled=self.param('fence_skip_if_sd_active'), - ) if self.param('fence_skip_if_sd_active') is not None else None, - ) if ( - self.param('fence_enabled') is not None or - self.param('fence_skip_if_sd_active') is not None or - self.param('fence_skip_if_connectivity_broken') is not None or - self.param('fence_skip_if_gluster_bricks_up') is not None or - self.param('fence_skip_if_gluster_quorum_not_met') is not None or - self.param('fence_connectivity_threshold') is not None - ) else None, - display=otypes.Display( - proxy=self.param('spice_proxy'), - ) if self.param('spice_proxy') else None, - required_rng_sources=[ - otypes.RngSource(rng) for rng in self.param('rng_sources') - ] if self.param('rng_sources') else None, - memory_policy=otypes.MemoryPolicy( - over_commit=otypes.MemoryOverCommit( - percent=self._get_memory_policy(), - ), - ) if self.param('memory_policy') else None, - ksm=otypes.Ksm( - enabled=self.param('ksm'), - merge_across_nodes=not self.param('ksm_numa'), - ) if ( - self.param('ksm_numa') is not None or - self.param('ksm') is not None - ) else None, - data_center=otypes.DataCenter( - name=self.param('data_center'), - ) if self.param('data_center') else None, - management_network=otypes.Network( - name=self.param('network'), - ) if self.param('network') else None, - cpu=otypes.Cpu( - architecture=otypes.Architecture( - self.param('cpu_arch') - ) if self.param('cpu_arch') else None, - type=self.param('cpu_type'), - ) if ( - self.param('cpu_arch') or self.param('cpu_type') - ) else None, - version=otypes.Version( - major=self.__get_major(self.param('compatibility_version')), - minor=self.__get_minor(self.param('compatibility_version')), - ) if self.param('compatibility_version') else None, - switch_type=otypes.SwitchType( - self.param('switch_type') - ) if self.param('switch_type') else None, - mac_pool=otypes.MacPool( - id=get_id_by_name(self._connection.system_service().mac_pools_service(), self.param('mac_pool')) - ) if self.param('mac_pool') else None, - external_network_providers=self._get_external_network_providers_entity(), - custom_scheduling_policy_properties=[ - otypes.Property( - name=sp.get('name'), - value=str(sp.get('value')), - ) for sp in self.param('scheduling_policy_properties') if sp - ] if self.param('scheduling_policy_properties') is not None else None, - firewall_type=otypes.FirewallType( - self.param('firewall_type') - ) if self.param('firewall_type') else None, - gluster_tuned_profile=self.param('gluster_tuned_profile'), - ) - - def _matches_entity(self, item, entity): - return equal(item.get('id'), entity.id) and equal(item.get('name'), entity.name) - - def _update_check_external_network_providers(self, entity): - if self.param('external_network_providers') is None: - return True - if entity.external_network_providers is None: - return not self.param('external_network_providers') - entity_providers = self._connection.follow_link(entity.external_network_providers) - entity_provider_ids = [provider.id for provider in entity_providers] - entity_provider_names = [provider.name for provider in entity_providers] - for provider in self._get_external_network_providers(): - if provider.get('id'): - if provider.get('id') not in entity_provider_ids: - return False - elif provider.get('name') and provider.get('name') not in entity_provider_names: - return False - for entity_provider in entity_providers: - if not any([self._matches_entity(provider, entity_provider) - for provider in self._get_external_network_providers()]): - return False - return True - - def update_check(self, entity): - sched_policy = self._get_sched_policy() - migration_policy = getattr(entity.migration, 'policy', None) - cluster_cpu = getattr(entity, 'cpu', dict()) - - def check_custom_scheduling_policy_properties(): - if self.param('scheduling_policy_properties'): - current = [] - if entity.custom_scheduling_policy_properties: - current = [(sp.name, str(sp.value)) for sp in entity.custom_scheduling_policy_properties] - passed = [(sp.get('name'), str(sp.get('value'))) for sp in self.param('scheduling_policy_properties') if sp] - for p in passed: - if p not in current: - return False - return True - - return ( - check_custom_scheduling_policy_properties() and - equal(self.param('name'), entity.name) and - equal(self.param('comment'), entity.comment) and - equal(self.param('description'), entity.description) and - equal(self.param('switch_type'), str(entity.switch_type)) and - equal(self.param('cpu_arch'), str(getattr(cluster_cpu, 'architecture', None))) and - equal(self.param('cpu_type'), getattr(cluster_cpu, 'type', None)) and - equal(self.param('ballooning'), entity.ballooning_enabled) and - equal(self.param('gluster'), entity.gluster_service) and - equal(self.param('virt'), entity.virt_service) and - equal(self.param('threads_as_cores'), entity.threads_as_cores) and - equal(self.param('ksm_numa'), not entity.ksm.merge_across_nodes) and - equal(self.param('ksm'), entity.ksm.enabled) and - equal(self.param('ha_reservation'), entity.ha_reservation) and - equal(self.param('trusted_service'), entity.trusted_service) and - equal(self.param('host_reason'), entity.maintenance_reason_required) and - equal(self.param('vm_reason'), entity.optional_reason) and - equal(self.param('spice_proxy'), getattr(entity.display, 'proxy', None)) and - equal(self.param('fence_enabled'), entity.fencing_policy.enabled) and - equal(self.param('fence_skip_if_gluster_bricks_up'), entity.fencing_policy.skip_if_gluster_bricks_up) and - equal(self.param('fence_skip_if_gluster_quorum_not_met'), entity.fencing_policy.skip_if_gluster_quorum_not_met) and - equal(self.param('fence_skip_if_sd_active'), entity.fencing_policy.skip_if_sd_active.enabled) and - equal(self.param('fence_skip_if_connectivity_broken'), entity.fencing_policy.skip_if_connectivity_broken.enabled) and - equal(self.param('fence_connectivity_threshold'), entity.fencing_policy.skip_if_connectivity_broken.threshold) and - equal(self.param('resilience_policy'), str(entity.error_handling.on_error)) and - equal(self.param('migration_bandwidth'), str(entity.migration.bandwidth.assignment_method)) and - equal(self.param('migration_auto_converge'), str(entity.migration.auto_converge)) and - equal(self.param('migration_compressed'), str(entity.migration.compressed)) and - equal(self.param('serial_policy'), str(getattr(entity.serial_number, 'policy', None))) and - equal(self.param('serial_policy_value'), getattr(entity.serial_number, 'value', None)) and - equal(self.param('scheduling_policy'), getattr(self._connection.follow_link(entity.scheduling_policy), 'name', None)) and - equal(self.param('firewall_type'), str(entity.firewall_type)) and - equal(self.param('gluster_tuned_profile'), getattr(entity, 'gluster_tuned_profile', None)) and - equal(self._get_policy_id(), getattr(migration_policy, 'id', None)) and - equal(self._get_memory_policy(), entity.memory_policy.over_commit.percent) and - equal(self.__get_minor(self.param('compatibility_version')), self.__get_minor(entity.version)) and - equal(self.__get_major(self.param('compatibility_version')), self.__get_major(entity.version)) and - equal( - self.param('migration_bandwidth_limit') if self.param('migration_bandwidth') == 'custom' else None, - entity.migration.bandwidth.custom_value - ) and - equal( - sorted(self.param('rng_sources')) if self.param('rng_sources') else None, - sorted([ - str(source) for source in entity.required_rng_sources - ]) - ) and - equal( - get_id_by_name(self._connection.system_service().mac_pools_service(), self.param('mac_pool'), raise_error=False), - entity.mac_pool.id - ) and - self._update_check_external_network_providers(entity) - ) - - -def main(): - argument_spec = ovirt_full_argument_spec( - state=dict( - choices=['present', 'absent'], - default='present', - ), - name=dict(default=None, required=True), - id=dict(default=None), - ballooning=dict(default=None, type='bool', aliases=['balloon']), - gluster=dict(default=None, type='bool'), - virt=dict(default=None, type='bool'), - threads_as_cores=dict(default=None, type='bool'), - ksm_numa=dict(default=None, type='bool'), - ksm=dict(default=None, type='bool'), - ha_reservation=dict(default=None, type='bool'), - trusted_service=dict(default=None, type='bool'), - vm_reason=dict(default=None, type='bool'), - host_reason=dict(default=None, type='bool'), - memory_policy=dict(default=None, choices=['disabled', 'server', 'desktop'], aliases=['performance_preset']), - rng_sources=dict(default=None, type='list'), - spice_proxy=dict(default=None), - fence_enabled=dict(default=None, type='bool'), - fence_skip_if_gluster_bricks_up=dict(default=None, type='bool'), - fence_skip_if_gluster_quorum_not_met=dict(default=None, type='bool'), - fence_skip_if_sd_active=dict(default=None, type='bool'), - fence_skip_if_connectivity_broken=dict(default=None, type='bool'), - fence_connectivity_threshold=dict(default=None, type='int'), - resilience_policy=dict(default=None, choices=['migrate_highly_available', 'migrate', 'do_not_migrate']), - migration_bandwidth=dict(default=None, choices=['auto', 'hypervisor_default', 'custom']), - migration_bandwidth_limit=dict(default=None, type='int'), - migration_auto_converge=dict(default=None, choices=['true', 'false', 'inherit']), - migration_compressed=dict(default=None, choices=['true', 'false', 'inherit']), - migration_policy=dict( - default=None, - choices=['legacy', 'minimal_downtime', 'suspend_workload', 'post_copy'] - ), - serial_policy=dict(default=None, choices=['vm', 'host', 'custom']), - serial_policy_value=dict(default=None), - scheduling_policy=dict(default=None), - data_center=dict(default=None), - description=dict(default=None), - comment=dict(default=None), - network=dict(default=None), - cpu_arch=dict(default=None, choices=['ppc64', 'undefined', 'x86_64']), - cpu_type=dict(default=None), - switch_type=dict(default=None, choices=['legacy', 'ovs']), - compatibility_version=dict(default=None), - mac_pool=dict(default=None), - external_network_providers=dict(default=None, type='list'), - scheduling_policy_properties=dict(type='list'), - firewall_type=dict(choices=['iptables', 'firewalld'], default=None), - gluster_tuned_profile=dict(default=None), - ) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - ) - - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - clusters_service = connection.system_service().clusters_service() - clusters_module = ClustersModule( - connection=connection, - module=module, - service=clusters_service, - ) - - state = module.params['state'] - if state == 'present': - ret = clusters_module.create() - elif state == 'absent': - ret = clusters_module.remove() - - module.exit_json(**ret) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_cluster_info.py b/lib/ansible/modules/cloud/ovirt/ovirt_cluster_info.py deleted file mode 100644 index 646c05efd9..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_cluster_info.py +++ /dev/null @@ -1,120 +0,0 @@ -#!/usr/bin/python -# -*- 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 . -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_cluster_info -short_description: Retrieve information about one or more oVirt/RHV clusters -author: "Ondra Machacek (@machacekondra)" -version_added: "2.3" -description: - - "Retrieve information about one or more oVirt/RHV clusters." - - This module was called C(ovirt_cluster_facts) before Ansible 2.9, returning C(ansible_facts). - Note that the M(ovirt_cluster_info) module no longer returns C(ansible_facts)! -notes: - - "This module returns a variable C(ovirt_clusters), which - contains a list of clusters. You need to register the result with - the I(register) keyword to use it." -options: - pattern: - description: - - "Search term which is accepted by oVirt/RHV search backend." - - "For example to search cluster X from datacenter Y use following pattern: - name=X and datacenter=Y" -extends_documentation_fragment: ovirt_info -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Gather information about all clusters which names start with C: -- ovirt_cluster_info: - pattern: - name: 'production*' - register: result -- debug: - msg: "{{ result.ovirt_clusters }}" -''' - -RETURN = ''' -ovirt_clusters: - description: "List of dictionaries describing the clusters. Cluster attributes are mapped to dictionary keys, - all clusters attributes can be found at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/cluster." - returned: On success. - type: list -''' - -import traceback - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - check_sdk, - create_connection, - get_dict_of_struct, - ovirt_info_full_argument_spec, -) - - -def main(): - argument_spec = ovirt_info_full_argument_spec( - pattern=dict(default='', required=False), - ) - module = AnsibleModule(argument_spec) - is_old_facts = module._name == 'ovirt_cluster_facts' - if is_old_facts: - module.deprecate("The 'ovirt_cluster_facts' module has been renamed to 'ovirt_cluster_info', " - "and the renamed one no longer returns ansible_facts", version='2.13') - - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - clusters_service = connection.system_service().clusters_service() - clusters = clusters_service.list(search=module.params['pattern']) - result = dict( - ovirt_clusters=[ - get_dict_of_struct( - struct=c, - connection=connection, - fetch_nested=module.params.get('fetch_nested'), - attributes=module.params.get('nested_attributes'), - ) for c in clusters - ], - ) - if is_old_facts: - module.exit_json(changed=False, ansible_facts=result) - else: - module.exit_json(changed=False, **result) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_datacenter.py b/lib/ansible/modules/cloud/ovirt/ovirt_datacenter.py deleted file mode 100644 index d86d5f485a..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_datacenter.py +++ /dev/null @@ -1,233 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (c) 2016 Red Hat, Inc. -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_datacenter -short_description: Module to manage data centers in oVirt/RHV -version_added: "2.3" -author: "Ondra Machacek (@machacekondra)" -description: - - "Module to manage data centers in oVirt/RHV" -options: - id: - description: - - "ID of the datacenter to manage." - version_added: "2.8" - name: - description: - - "Name of the data center to manage." - required: true - state: - description: - - "Should the data center be present or absent." - choices: ['present', 'absent'] - default: present - description: - description: - - "Description of the data center." - comment: - description: - - "Comment of the data center." - local: - description: - - "I(True) if the data center should be local, I(False) if should be shared." - - "Default value is set by engine." - type: bool - compatibility_version: - description: - - "Compatibility version of the data center." - quota_mode: - description: - - "Quota mode of the data center. One of I(disabled), I(audit) or I(enabled)" - choices: ['disabled', 'audit', 'enabled'] - mac_pool: - description: - - "MAC pool to be used by this datacenter." - - "IMPORTANT: This option is deprecated in oVirt/RHV 4.1. You should - use C(mac_pool) in C(ovirt_clusters) module, as MAC pools are - set per cluster since 4.1." - force: - description: - - "This parameter can be used only when removing a data center. - If I(True) data center will be forcibly removed, even though it - contains some clusters. Default value is I(False), which means - that only empty data center can be removed." - version_added: "2.5" - default: False - type: bool - -extends_documentation_fragment: ovirt -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Create datacenter -- ovirt_datacenter: - name: mydatacenter - local: True - compatibility_version: 4.0 - quota_mode: enabled - -# Remove datacenter -- ovirt_datacenter: - state: absent - name: mydatacenter - -# Change Datacenter Name -- ovirt_datacenter: - id: 00000000-0000-0000-0000-000000000000 - name: "new_datacenter_name" -''' - -RETURN = ''' -id: - description: "ID of the managed datacenter" - returned: "On success if datacenter is found." - type: str - sample: 7de90f31-222c-436c-a1ca-7e655bd5b60c -data_center: - description: "Dictionary of all the datacenter attributes. Datacenter attributes can be found on your oVirt/RHV instance - at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/datacenter." - returned: "On success if datacenter is found." - type: dict -''' - -import traceback - -try: - import ovirtsdk4.types as otypes -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - BaseModule, - check_sdk, - check_params, - create_connection, - equal, - ovirt_full_argument_spec, - search_by_name, -) - - -class DatacentersModule(BaseModule): - - def __get_major(self, full_version): - if full_version is None: - return None - if isinstance(full_version, otypes.Version): - return full_version.major - return int(full_version.split('.')[0]) - - def __get_minor(self, full_version): - if full_version is None: - return None - if isinstance(full_version, otypes.Version): - return full_version.minor - return int(full_version.split('.')[1]) - - def _get_mac_pool(self): - mac_pool = None - if self._module.params.get('mac_pool'): - mac_pool = search_by_name( - self._connection.system_service().mac_pools_service(), - self._module.params.get('mac_pool'), - ) - - return mac_pool - - def build_entity(self): - return otypes.DataCenter( - name=self._module.params['name'], - id=self._module.params['id'], - comment=self._module.params['comment'], - description=self._module.params['description'], - mac_pool=otypes.MacPool( - id=getattr(self._get_mac_pool(), 'id', None), - ) if self._module.params.get('mac_pool') else None, - quota_mode=otypes.QuotaModeType( - self._module.params['quota_mode'] - ) if self._module.params['quota_mode'] else None, - local=self._module.params['local'], - version=otypes.Version( - major=self.__get_major(self._module.params['compatibility_version']), - minor=self.__get_minor(self._module.params['compatibility_version']), - ) if self._module.params['compatibility_version'] else None, - ) - - def update_check(self, entity): - minor = self.__get_minor(self._module.params.get('compatibility_version')) - major = self.__get_major(self._module.params.get('compatibility_version')) - return ( - equal(getattr(self._get_mac_pool(), 'id', None), getattr(entity.mac_pool, 'id', None)) and - equal(self._module.params.get('comment'), entity.comment) and - equal(self._module.params.get('description'), entity.description) and - equal(self._module.params.get('name'), entity.name) and - equal(self._module.params.get('quota_mode'), str(entity.quota_mode)) and - equal(self._module.params.get('local'), entity.local) and - equal(minor, self.__get_minor(entity.version)) and - equal(major, self.__get_major(entity.version)) - ) - - -def main(): - argument_spec = ovirt_full_argument_spec( - state=dict( - choices=['present', 'absent'], - default='present', - ), - name=dict(default=None, required=True), - description=dict(default=None), - local=dict(type='bool'), - id=dict(default=None), - compatibility_version=dict(default=None), - quota_mode=dict(choices=['disabled', 'audit', 'enabled']), - comment=dict(default=None), - mac_pool=dict(default=None), - force=dict(default=None, type='bool'), - ) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - ) - - check_sdk(module) - check_params(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - data_centers_service = connection.system_service().data_centers_service() - data_centers_module = DatacentersModule( - connection=connection, - module=module, - service=data_centers_service, - ) - - state = module.params['state'] - if state == 'present': - ret = data_centers_module.create() - elif state == 'absent': - ret = data_centers_module.remove(force=module.params['force']) - - module.exit_json(**ret) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_datacenter_info.py b/lib/ansible/modules/cloud/ovirt/ovirt_datacenter_info.py deleted file mode 100644 index 9f17e82ed9..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_datacenter_info.py +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (c) 2016 Red Hat, Inc. -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_datacenter_info -short_description: Retrieve information about one or more oVirt/RHV datacenters -author: "Ondra Machacek (@machacekondra)" -version_added: "2.3" -description: - - "Retrieve information about one or more oVirt/RHV datacenters." - - This module was called C(ovirt_datacenter_facts) before Ansible 2.9, returning C(ansible_facts). - Note that the M(ovirt_datacenter_info) module no longer returns C(ansible_facts)! -notes: - - "This module returns a variable C(ovirt_datacenters), which - contains a list of datacenters. You need to register the result with - the I(register) keyword to use it." -options: - pattern: - description: - - "Search term which is accepted by oVirt/RHV search backend." - - "For example to search datacenter I(X) use following pattern: I(name=X)" -extends_documentation_fragment: ovirt_info -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Gather information about all data centers which names start with C(production): -- ovirt_datacenter_info: - pattern: name=production* - register: result -- debug: - msg: "{{ result.ovirt_datacenters }}" -''' - -RETURN = ''' -ovirt_datacenters: - description: "List of dictionaries describing the datacenters. Datacenter attributes are mapped to dictionary keys, - all datacenters attributes can be found at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/data_center." - returned: On success. - type: list -''' - -import traceback - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - check_sdk, - create_connection, - get_dict_of_struct, - ovirt_info_full_argument_spec, -) - - -def main(): - argument_spec = ovirt_info_full_argument_spec( - pattern=dict(default='', required=False), - ) - module = AnsibleModule(argument_spec) - is_old_facts = module._name == 'ovirt_datacenter_facts' - if is_old_facts: - module.deprecate("The 'ovirt_datacenter_facts' module has been renamed to 'ovirt_datacenter_info', " - "and the renamed one no longer returns ansible_facts", version='2.13') - - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - datacenters_service = connection.system_service().data_centers_service() - datacenters = datacenters_service.list(search=module.params['pattern']) - result = dict( - ovirt_datacenters=[ - get_dict_of_struct( - struct=d, - connection=connection, - fetch_nested=module.params.get('fetch_nested'), - attributes=module.params.get('nested_attributes'), - ) for d in datacenters - ], - ) - if is_old_facts: - module.exit_json(changed=False, ansible_facts=result) - else: - module.exit_json(changed=False, **result) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_disk.py b/lib/ansible/modules/cloud/ovirt/ovirt_disk.py deleted file mode 100644 index 6e6b0893be..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_disk.py +++ /dev/null @@ -1,838 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (c) 2016 Red Hat, Inc. -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_disk -short_description: "Module to manage Virtual Machine and floating disks in oVirt/RHV" -version_added: "2.2" -author: "Ondra Machacek (@machacekondra)" -description: - - "Module to manage Virtual Machine and floating disks in oVirt/RHV." -options: - id: - description: - - "ID of the disk to manage. Either C(id) or C(name) is required." - name: - description: - - "Name of the disk to manage. Either C(id) or C(name)/C(alias) is required." - aliases: ['alias'] - description: - description: - - "Description of the disk image to manage." - version_added: "2.5" - vm_name: - description: - - "Name of the Virtual Machine to manage. Either C(vm_id) or C(vm_name) is required if C(state) is I(attached) or I(detached)." - vm_id: - description: - - "ID of the Virtual Machine to manage. Either C(vm_id) or C(vm_name) is required if C(state) is I(attached) or I(detached)." - state: - description: - - "Should the Virtual Machine disk be present/absent/attached/detached/exported/imported." - choices: ['present', 'absent', 'attached', 'detached', 'exported', 'imported'] - default: 'present' - download_image_path: - description: - - "Path on a file system where disk should be downloaded." - - "Note that you must have an valid oVirt/RHV engine CA in your system trust store - or you must provide it in C(ca_file) parameter." - - "Note that the disk is not downloaded when the file already exists, - but you can forcibly download the disk when using C(force) I (true)." - version_added: "2.3" - upload_image_path: - description: - - "Path to disk image, which should be uploaded." - - "Note that currently we support only compatibility version 0.10 of the qcow disk." - - "Note that you must have an valid oVirt/RHV engine CA in your system trust store - or you must provide it in C(ca_file) parameter." - - "Note that there is no reliable way to achieve idempotency, so - if you want to upload the disk even if the disk with C(id) or C(name) exists, - then please use C(force) I(true). If you will use C(force) I(false), which - is default, then the disk image won't be uploaded." - version_added: "2.3" - size: - description: - - "Size of the disk. Size should be specified using IEC standard units. - For example 10GiB, 1024MiB, etc." - - "Size can be only increased, not decreased." - interface: - description: - - "Driver of the storage interface." - - "It's required parameter when creating the new disk." - choices: ['virtio', 'ide', 'virtio_scsi'] - format: - description: - - Specify format of the disk. - - Note that this option isn't idempotent as it's not currently possible to change format of the disk via API. - choices: ['raw', 'cow'] - content_type: - description: - - Specify if the disk is a data disk or ISO image or a one of a the Hosted Engine disk types - - The Hosted Engine disk content types are available with Engine 4.3+ and Ansible 2.8 - choices: ['data', 'iso', 'hosted_engine', 'hosted_engine_sanlock', 'hosted_engine_metadata', 'hosted_engine_configuration'] - default: 'data' - version_added: "2.8" - sparse: - required: False - type: bool - version_added: "2.5" - description: - - "I(True) if the disk should be sparse (also known as I(thin provision)). - If the parameter is omitted, cow disks will be created as sparse and raw disks as I(preallocated)" - - Note that this option isn't idempotent as it's not currently possible to change sparseness of the disk via API. - storage_domain: - description: - - "Storage domain name where disk should be created." - storage_domains: - description: - - "Storage domain names where disk should be copied." - - "C(**IMPORTANT**)" - - "There is no reliable way to achieve idempotency, so every time - you specify this parameter the disks are copied, so please handle - your playbook accordingly to not copy the disks all the time. This - is valid only for VM and floating disks, template disks works - as expected." - version_added: "2.3" - force: - description: - - "Please take a look at C(image_path) documentation to see the correct - usage of this parameter." - version_added: "2.3" - type: bool - profile: - description: - - "Disk profile name to be attached to disk. By default profile is chosen by oVirt/RHV engine." - quota_id: - description: - - "Disk quota ID to be used for disk. By default quota is chosen by oVirt/RHV engine." - version_added: "2.5" - bootable: - description: - - "I(True) if the disk should be bootable. By default when disk is created it isn't bootable." - type: bool - default: 'no' - shareable: - description: - - "I(True) if the disk should be shareable. By default when disk is created it isn't shareable." - type: bool - logical_unit: - description: - - "Dictionary which describes LUN to be directly attached to VM:" - suboptions: - address: - description: - - Address of the storage server. Used by iSCSI. - port: - description: - - Port of the storage server. Used by iSCSI. - target: - description: - - iSCSI target. - lun_id: - description: - - LUN id. - username: - description: - - CHAP Username to be used to access storage server. Used by iSCSI. - password: - description: - - CHAP Password of the user to be used to access storage server. Used by iSCSI. - storage_type: - description: - - Storage type either I(fcp) or I(iscsi). - sparsify: - description: - - "I(True) if the disk should be sparsified." - - "Sparsification frees space in the disk image that is not used by - its filesystem. As a result, the image will occupy less space on - the storage." - - "Note that this parameter isn't idempotent, as it's not possible - to check if the disk should be or should not be sparsified." - version_added: "2.4" - type: bool - openstack_volume_type: - description: - - "Name of the openstack volume type. This is valid when working - with cinder." - version_added: "2.4" - image_provider: - description: - - "When C(state) is I(exported) disk is exported to given Glance image provider." - - "When C(state) is I(imported) disk is imported from given Glance image provider." - - "C(**IMPORTANT**)" - - "There is no reliable way to achieve idempotency, so every time - you specify this parameter the disk is exported, so please handle - your playbook accordingly to not export the disk all the time. - This option is valid only for template disks." - version_added: "2.4" - host: - description: - - "When the hypervisor name is specified the newly created disk or - an existing disk will refresh its information about the - underlying storage( Disk size, Serial, Product ID, Vendor ID ...) - The specified host will be used for gathering the storage - related information. This option is only valid for passthrough - disks. This option requires at least the logical_unit.id to be - specified" - version_added: "2.8" - wipe_after_delete: - description: - - "If the disk's Wipe After Delete is enabled, then the disk is first wiped." - type: bool - activate: - description: - - I(True) if the disk should be activated. - - When creating disk of virtual machine it is set to I(True). - version_added: "2.8" - type: bool -extends_documentation_fragment: ovirt -''' - - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Create and attach new disk to VM -- ovirt_disk: - name: myvm_disk - vm_name: rhel7 - size: 10GiB - format: cow - interface: virtio - storage_domain: data - -# Attach logical unit to VM rhel7 -- ovirt_disk: - vm_name: rhel7 - logical_unit: - target: iqn.2016-08-09.brq.str-01:omachace - id: 1IET_000d0001 - address: 10.34.63.204 - interface: virtio - -# Detach disk from VM -- ovirt_disk: - state: detached - name: myvm_disk - vm_name: rhel7 - size: 10GiB - format: cow - interface: virtio - -# Change Disk Name -- ovirt_disk: - id: 00000000-0000-0000-0000-000000000000 - storage_domain: data - name: "new_disk_name" - vm_name: rhel7 - -# Upload local image to disk and attach it to vm: -# Since Ansible 2.3 -- ovirt_disk: - name: mydisk - vm_name: myvm - interface: virtio - size: 10GiB - format: cow - image_path: /path/to/mydisk.qcow2 - storage_domain: data - -# Download disk to local file system: -# Since Ansible 2.3 -- ovirt_disk: - id: 7de90f31-222c-436c-a1ca-7e655bd5b60c - download_image_path: /home/user/mydisk.qcow2 - -# Export disk as image to Glance domain -# Since Ansible 2.4 -- ovirt_disk: - id: 7de90f31-222c-436c-a1ca-7e655bd5b60c - image_provider: myglance - state: exported - -# Defining a specific quota while creating a disk image: -# Since Ansible 2.5 -- ovirt_quotas_facts: - data_center: Default - name: myquota -- ovirt_disk: - name: mydisk - size: 10GiB - storage_domain: data - description: somedescriptionhere - quota_id: "{{ ovirt_quotas[0]['id'] }}" - -# Upload an ISO image -# Since Ansible 2.8 -- ovirt_disk: - name: myiso - upload_image_path: /path/to/iso/image - storage_domain: data - size: 4 GiB - wait: true - bootable: true - format: raw - content_type: iso - -# Add fiber chanel disk -- name: Create disk - ovirt_disk: - name: fcp_disk - host: my_host - logical_unit: - id: 3600a09803830447a4f244c4657597777 - storage_type: fcp -''' - - -RETURN = ''' -id: - description: "ID of the managed disk" - returned: "On success if disk is found." - type: str - sample: 7de90f31-222c-436c-a1ca-7e655bd5b60c -disk: - description: "Dictionary of all the disk attributes. Disk attributes can be found on your oVirt/RHV instance - at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/disk." - returned: "On success if disk is found and C(vm_id) or C(vm_name) wasn't passed." - type: dict - -disk_attachment: - description: "Dictionary of all the disk attachment attributes. Disk attachment attributes can be found - on your oVirt/RHV instance at following url: - http://ovirt.github.io/ovirt-engine-api-model/master/#types/disk_attachment." - returned: "On success if disk is found and C(vm_id) or C(vm_name) was passed and VM was found." - type: dict -''' - -import os -import time -import traceback -import ssl - -from ansible.module_utils.six.moves.http_client import HTTPSConnection, IncompleteRead -from ansible.module_utils.six.moves.urllib.parse import urlparse -try: - import ovirtsdk4.types as otypes -except ImportError: - pass -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - BaseModule, - check_sdk, - check_params, - create_connection, - convert_to_bytes, - equal, - follow_link, - get_id_by_name, - ovirt_full_argument_spec, - get_dict_of_struct, - search_by_name, - wait, -) - - -def _search_by_lun(disks_service, lun_id): - """ - Find disk by LUN ID. - """ - res = [ - disk for disk in disks_service.list(search='disk_type=lun') if ( - disk.lun_storage.id == lun_id - ) - ] - return res[0] if res else None - - -def transfer(connection, module, direction, transfer_func): - transfers_service = connection.system_service().image_transfers_service() - transfer = transfers_service.add( - otypes.ImageTransfer( - image=otypes.Image( - id=module.params['id'], - ), - direction=direction, - ) - ) - transfer_service = transfers_service.image_transfer_service(transfer.id) - - try: - # After adding a new transfer for the disk, the transfer's status will be INITIALIZING. - # Wait until the init phase is over. The actual transfer can start when its status is "Transferring". - while transfer.phase == otypes.ImageTransferPhase.INITIALIZING: - time.sleep(module.params['poll_interval']) - transfer = transfer_service.get() - - proxy_url = urlparse(transfer.proxy_url) - context = ssl.create_default_context() - auth = module.params['auth'] - if auth.get('insecure'): - context.check_hostname = False - context.verify_mode = ssl.CERT_NONE - elif auth.get('ca_file'): - context.load_verify_locations(cafile=auth.get('ca_file')) - - proxy_connection = HTTPSConnection( - proxy_url.hostname, - proxy_url.port, - context=context, - ) - - transfer_func( - transfer_service, - proxy_connection, - proxy_url, - transfer.signed_ticket - ) - return True - finally: - transfer_service.finalize() - while transfer.phase in [ - otypes.ImageTransferPhase.TRANSFERRING, - otypes.ImageTransferPhase.FINALIZING_SUCCESS, - ]: - time.sleep(module.params['poll_interval']) - transfer = transfer_service.get() - if transfer.phase in [ - otypes.ImageTransferPhase.UNKNOWN, - otypes.ImageTransferPhase.FINISHED_FAILURE, - otypes.ImageTransferPhase.FINALIZING_FAILURE, - otypes.ImageTransferPhase.CANCELLED, - ]: - raise Exception( - "Error occurred while uploading image. The transfer is in %s" % transfer.phase - ) - if not module.params.get('logical_unit'): - disks_service = connection.system_service().disks_service() - wait( - service=disks_service.service(module.params['id']), - condition=lambda d: d.status == otypes.DiskStatus.OK, - wait=module.params['wait'], - timeout=module.params['timeout'], - ) - - -def download_disk_image(connection, module): - def _transfer(transfer_service, proxy_connection, proxy_url, transfer_ticket): - BUF_SIZE = 128 * 1024 - transfer_headers = { - 'Authorization': transfer_ticket, - } - proxy_connection.request( - 'GET', - proxy_url.path, - headers=transfer_headers, - ) - r = proxy_connection.getresponse() - path = module.params["download_image_path"] - image_size = int(r.getheader('Content-Length')) - with open(path, "wb") as mydisk: - pos = 0 - while pos < image_size: - to_read = min(image_size - pos, BUF_SIZE) - chunk = r.read(to_read) - if not chunk: - raise RuntimeError("Socket disconnected") - mydisk.write(chunk) - pos += len(chunk) - - return transfer( - connection, - module, - otypes.ImageTransferDirection.DOWNLOAD, - transfer_func=_transfer, - ) - - -def upload_disk_image(connection, module): - def _transfer(transfer_service, proxy_connection, proxy_url, transfer_ticket): - BUF_SIZE = 128 * 1024 - path = module.params['upload_image_path'] - - image_size = os.path.getsize(path) - proxy_connection.putrequest("PUT", proxy_url.path) - proxy_connection.putheader('Content-Length', "%d" % (image_size,)) - proxy_connection.endheaders() - with open(path, "rb") as disk: - pos = 0 - while pos < image_size: - to_read = min(image_size - pos, BUF_SIZE) - chunk = disk.read(to_read) - if not chunk: - transfer_service.pause() - raise RuntimeError("Unexpected end of file at pos=%d" % pos) - proxy_connection.send(chunk) - pos += len(chunk) - - return transfer( - connection, - module, - otypes.ImageTransferDirection.UPLOAD, - transfer_func=_transfer, - ) - - -class DisksModule(BaseModule): - - def build_entity(self): - hosts_service = self._connection.system_service().hosts_service() - logical_unit = self._module.params.get('logical_unit') - disk = otypes.Disk( - id=self._module.params.get('id'), - name=self._module.params.get('name'), - description=self._module.params.get('description'), - format=otypes.DiskFormat( - self._module.params.get('format') - ) if self._module.params.get('format') else None, - content_type=otypes.DiskContentType( - self._module.params.get('content_type') - ) if self._module.params.get('content_type') else None, - sparse=self._module.params.get( - 'sparse' - ) if self._module.params.get( - 'sparse' - ) is not None else self._module.params.get('format') != 'raw', - openstack_volume_type=otypes.OpenStackVolumeType( - name=self.param('openstack_volume_type') - ) if self.param('openstack_volume_type') else None, - provisioned_size=convert_to_bytes( - self._module.params.get('size') - ), - storage_domains=[ - otypes.StorageDomain( - name=self._module.params.get('storage_domain'), - ), - ], - quota=otypes.Quota(id=self._module.params.get('quota_id')) if self.param('quota_id') else None, - shareable=self._module.params.get('shareable'), - wipe_after_delete=self.param('wipe_after_delete'), - lun_storage=otypes.HostStorage( - host=otypes.Host( - id=get_id_by_name(hosts_service, self._module.params.get('host')) - ) if self.param('host') else None, - type=otypes.StorageType( - logical_unit.get('storage_type', 'iscsi') - ), - logical_units=[ - otypes.LogicalUnit( - address=logical_unit.get('address'), - port=logical_unit.get('port', 3260), - target=logical_unit.get('target'), - id=logical_unit.get('id'), - username=logical_unit.get('username'), - password=logical_unit.get('password'), - ) - ], - ) if logical_unit else None, - ) - if hasattr(disk, 'initial_size') and self._module.params['upload_image_path']: - disk.initial_size = convert_to_bytes( - self._module.params.get('size') - ) - - return disk - - def update_storage_domains(self, disk_id): - changed = False - disk_service = self._service.service(disk_id) - disk = disk_service.get() - sds_service = self._connection.system_service().storage_domains_service() - - # We don't support move© for non file based storages: - if disk.storage_type != otypes.DiskStorageType.IMAGE: - return changed - - # Initiate move: - if self._module.params['storage_domain']: - new_disk_storage_id = get_id_by_name(sds_service, self._module.params['storage_domain']) - changed = self.action( - action='move', - entity=disk, - action_condition=lambda d: new_disk_storage_id != d.storage_domains[0].id, - wait_condition=lambda d: d.status == otypes.DiskStatus.OK, - storage_domain=otypes.StorageDomain( - id=new_disk_storage_id, - ), - post_action=lambda _: time.sleep(self._module.params['poll_interval']), - )['changed'] - - if self._module.params['storage_domains']: - for sd in self._module.params['storage_domains']: - new_disk_storage = search_by_name(sds_service, sd) - changed = changed or self.action( - action='copy', - entity=disk, - action_condition=( - lambda disk: new_disk_storage.id not in [sd.id for sd in disk.storage_domains] - ), - wait_condition=lambda disk: disk.status == otypes.DiskStatus.OK, - storage_domain=otypes.StorageDomain( - id=new_disk_storage.id, - ), - )['changed'] - - return changed - - def _update_check(self, entity): - return ( - equal(self._module.params.get('name'), entity.name) and - equal(self._module.params.get('description'), entity.description) and - equal(self.param('quota_id'), getattr(entity.quota, 'id', None)) and - equal(convert_to_bytes(self._module.params.get('size')), entity.provisioned_size) and - equal(self._module.params.get('shareable'), entity.shareable) and - equal(self.param('wipe_after_delete'), entity.wipe_after_delete) - ) - - -class DiskAttachmentsModule(DisksModule): - - def build_entity(self): - return otypes.DiskAttachment( - disk=super(DiskAttachmentsModule, self).build_entity(), - interface=otypes.DiskInterface( - self._module.params.get('interface') - ) if self._module.params.get('interface') else None, - bootable=self._module.params.get('bootable'), - active=self.param('activate'), - ) - - def update_check(self, entity): - return ( - super(DiskAttachmentsModule, self)._update_check(follow_link(self._connection, entity.disk)) and - equal(self._module.params.get('interface'), str(entity.interface)) and - equal(self._module.params.get('bootable'), entity.bootable) and - equal(self.param('activate'), entity.active) - ) - - -def searchable_attributes(module): - """ - Return all searchable disk attributes passed to module. - """ - attributes = { - 'name': module.params.get('name'), - 'Storage.name': module.params.get('storage_domain'), - 'vm_names': module.params.get('vm_name'), - } - return dict((k, v) for k, v in attributes.items() if v is not None) - - -def get_vm_service(connection, module): - if module.params.get('vm_id') is not None or module.params.get('vm_name') is not None and module.params['state'] != 'absent': - vms_service = connection.system_service().vms_service() - - # If `vm_id` isn't specified, find VM by name: - vm_id = module.params['vm_id'] - if vm_id is None: - vm_id = get_id_by_name(vms_service, module.params['vm_name']) - - if vm_id is None: - module.fail_json( - msg="VM don't exists, please create it first." - ) - - return vms_service.vm_service(vm_id) - - -def main(): - argument_spec = ovirt_full_argument_spec( - state=dict( - choices=['present', 'absent', 'attached', 'detached', 'exported', 'imported'], - default='present' - ), - id=dict(default=None), - name=dict(default=None, aliases=['alias']), - description=dict(default=None), - vm_name=dict(default=None), - vm_id=dict(default=None), - size=dict(default=None), - interface=dict(default=None,), - storage_domain=dict(default=None), - storage_domains=dict(default=None, type='list'), - profile=dict(default=None), - quota_id=dict(default=None), - format=dict(default='cow', choices=['raw', 'cow']), - content_type=dict( - default='data', - choices=['data', 'iso', 'hosted_engine', 'hosted_engine_sanlock', 'hosted_engine_metadata', 'hosted_engine_configuration'] - ), - sparse=dict(default=None, type='bool'), - bootable=dict(default=None, type='bool'), - shareable=dict(default=None, type='bool'), - logical_unit=dict(default=None, type='dict'), - download_image_path=dict(default=None), - upload_image_path=dict(default=None, aliases=['image_path']), - force=dict(default=False, type='bool'), - sparsify=dict(default=None, type='bool'), - openstack_volume_type=dict(default=None), - image_provider=dict(default=None), - host=dict(default=None), - wipe_after_delete=dict(type='bool', default=None), - activate=dict(default=None, type='bool'), - ) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - ) - - lun = module.params.get('logical_unit') - host = module.params['host'] - # Fail when host is specified with the LUN id. Lun id is needed to identify - # an existing disk if already available inthe environment. - if (host and lun is None) or (host and lun.get("id") is None): - module.fail_json( - msg="Can not use parameter host ({0!s}) without " - "specifying the logical_unit id".format(host) - ) - - check_sdk(module) - check_params(module) - - try: - disk = None - state = module.params['state'] - auth = module.params.get('auth') - connection = create_connection(auth) - disks_service = connection.system_service().disks_service() - disks_module = DisksModule( - connection=connection, - module=module, - service=disks_service, - ) - - force_create = False - vm_service = get_vm_service(connection, module) - if lun: - disk = _search_by_lun(disks_service, lun.get('id')) - else: - disk = disks_module.search_entity(search_params=searchable_attributes(module)) - if vm_service and disk: - # If the VM don't exist in VMs disks, but still it's found it means it was found - # for template with same name as VM, so we should force create the VM disk. - force_create = disk.id not in [a.disk.id for a in vm_service.disk_attachments_service().list() if a.disk] - - ret = None - # First take care of creating the VM, if needed: - if state in ('present', 'detached', 'attached'): - # Always activate disk when its being created - if vm_service is not None and disk is None: - module.params['activate'] = True - ret = disks_module.create( - entity=disk if not force_create else None, - result_state=otypes.DiskStatus.OK if lun is None else None, - fail_condition=lambda d: d.status == otypes.DiskStatus.ILLEGAL if lun is None else False, - force_create=force_create, - ) - is_new_disk = ret['changed'] - ret['changed'] = ret['changed'] or disks_module.update_storage_domains(ret['id']) - # We need to pass ID to the module, so in case we want detach/attach disk - # we have this ID specified to attach/detach method: - module.params['id'] = ret['id'] - - # Upload disk image in case it's new disk or force parameter is passed: - if module.params['upload_image_path'] and (is_new_disk or module.params['force']): - uploaded = upload_disk_image(connection, module) - ret['changed'] = ret['changed'] or uploaded - # Download disk image in case it's file don't exist or force parameter is passed: - if ( - module.params['download_image_path'] and (not os.path.isfile(module.params['download_image_path']) or module.params['force']) - ): - downloaded = download_disk_image(connection, module) - ret['changed'] = ret['changed'] or downloaded - - # Disk sparsify, only if disk is of image type: - if not module.check_mode: - disk = disks_service.disk_service(module.params['id']).get() - if disk.storage_type == otypes.DiskStorageType.IMAGE: - ret = disks_module.action( - action='sparsify', - action_condition=lambda d: module.params['sparsify'], - wait_condition=lambda d: d.status == otypes.DiskStatus.OK, - ) - - # Export disk as image to glance domain - elif state == 'exported': - disk = disks_module.search_entity() - if disk is None: - module.fail_json( - msg="Can not export given disk '%s', it doesn't exist" % - module.params.get('name') or module.params.get('id') - ) - if disk.storage_type == otypes.DiskStorageType.IMAGE: - ret = disks_module.action( - action='export', - action_condition=lambda d: module.params['image_provider'], - wait_condition=lambda d: d.status == otypes.DiskStatus.OK, - storage_domain=otypes.StorageDomain(name=module.params['image_provider']), - ) - elif state == 'imported': - glance_service = connection.system_service().openstack_image_providers_service() - image_provider = search_by_name(glance_service, module.params['image_provider']) - images_service = glance_service.service(image_provider.id).images_service() - entity_id = get_id_by_name(images_service, module.params['name']) - images_service.service(entity_id).import_( - storage_domain=otypes.StorageDomain( - name=module.params['storage_domain'] - ) if module.params['storage_domain'] else None, - disk=otypes.Disk( - name=module.params['name'] - ), - import_as_template=False, - ) - # Wait for disk to appear in system: - disk = disks_module.wait_for_import( - condition=lambda t: t.status == otypes.DiskStatus.OK - ) - ret = disks_module.create(result_state=otypes.DiskStatus.OK) - elif state == 'absent': - ret = disks_module.remove() - - # If VM was passed attach/detach disks to/from the VM: - if vm_service: - disk_attachments_service = vm_service.disk_attachments_service() - disk_attachments_module = DiskAttachmentsModule( - connection=connection, - module=module, - service=disk_attachments_service, - changed=ret['changed'] if ret else False, - ) - - if state == 'present' or state == 'attached': - ret = disk_attachments_module.create() - if lun is None: - wait( - service=disk_attachments_service.service(ret['id']), - condition=lambda d: follow_link(connection, d.disk).status == otypes.DiskStatus.OK, - wait=module.params['wait'], - timeout=module.params['timeout'], - ) - elif state == 'detached': - ret = disk_attachments_module.remove() - - # When the host parameter is specified and the disk is not being - # removed, refresh the information about the LUN. - if state != 'absent' and host: - hosts_service = connection.system_service().hosts_service() - host_id = get_id_by_name(hosts_service, host) - disks_service.disk_service(disk.id).refresh_lun(otypes.Host(id=host_id)) - - module.exit_json(**ret) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_disk_info.py b/lib/ansible/modules/cloud/ovirt/ovirt_disk_info.py deleted file mode 100644 index af3d855160..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_disk_info.py +++ /dev/null @@ -1,120 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (c) 2017 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 . -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_disk_info -short_description: Retrieve information about one or more oVirt/RHV disks -author: "Katerina Koukiou (@KKoukiou)" -version_added: "2.5" -description: - - "Retrieve information about one or more oVirt/RHV disks." - - This module was called C(ovirt_disk_facts) before Ansible 2.9, returning C(ansible_facts). - Note that the M(ovirt_disk_info) module no longer returns C(ansible_facts)! -notes: - - "This module returns a variable C(ovirt_disks), which - contains a list of disks. You need to register the result with - the I(register) keyword to use it." -options: - pattern: - description: - - "Search term which is accepted by oVirt/RHV search backend." - - "For example to search Disk X from storage Y use following pattern: - name=X and storage.name=Y" -extends_documentation_fragment: ovirt_info -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Gather information about all Disks which names start with C(centos) -- ovirt_disk_info: - pattern: name=centos* - register: result -- debug: - msg: "{{ result.ovirt_disks }}" -''' - -RETURN = ''' -ovirt_disks: - description: "List of dictionaries describing the Disks. Disk attributes are mapped to dictionary keys, - all Disks attributes can be found at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/disk." - returned: On success. - type: list -''' - -import traceback - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - check_sdk, - create_connection, - get_dict_of_struct, - ovirt_info_full_argument_spec, -) - - -def main(): - argument_spec = ovirt_info_full_argument_spec( - pattern=dict(default='', required=False), - ) - module = AnsibleModule(argument_spec) - is_old_facts = module._name == 'ovirt_disk_facts' - if is_old_facts: - module.deprecate("The 'ovirt_disk_facts' module has been renamed to 'ovirt_disk_info', " - "and the renamed one no longer returns ansible_facts", version='2.13') - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - disks_service = connection.system_service().disks_service() - disks = disks_service.list( - search=module.params['pattern'], - ) - result = dict( - ovirt_disks=[ - get_dict_of_struct( - struct=c, - connection=connection, - fetch_nested=module.params.get('fetch_nested'), - attributes=module.params.get('nested_attributes'), - ) for c in disks - ], - ) - if is_old_facts: - module.exit_json(changed=False, ansible_facts=result) - else: - module.exit_json(changed=False, **result) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_event.py b/lib/ansible/modules/cloud/ovirt/ovirt_event.py deleted file mode 100644 index ea158e0176..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_event.py +++ /dev/null @@ -1,249 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright: (c) 2019, Ansible Project -# 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 - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - -DOCUMENTATION = ''' ---- -module: ovirt_event -short_description: Create or delete an event in oVirt/RHV -author: "Chris Keller (@nasx)" -version_added: "2.8" -description: - - "This module can be used to create or delete an event in oVirt/RHV." -options: - state: - description: - - "Should the event be present/absent." - - "The C(wait) option must be set to false when state is absent." - choices: ['present', 'absent'] - type: str - default: present - - description: - description: - - "Message for the event." - - "Required when state is present." - type: str - - severity: - description: - - "Severity of the event." - - "Required when state is present." - choices: ['error', 'normal', 'warning'] - default: normal - type: str - - origin: - description: - - "Originator of the event." - - "Required when state is present." - type: str - - custom_id: - description: - - "Custom ID for the event. This ID must be unique for each event." - - "Required when state is present." - type: int - - id: - description: - - "The event ID in the oVirt/RHV audit_log table. This ID is not the same as custom_id and is only used when state is absent." - - "Required when state is absent." - type: str - - cluster: - description: - - "The id of the cluster associated with this event." - type: str - - data_center: - description: - - "The id of the data center associated with this event." - type: str - - host: - description: - - "The id of the host associated with this event." - type: str - - storage_domain: - description: - - "The id of the storage domain associated with this event." - type: str - - template: - description: - - "The id of the template associated with this event." - type: str - - user: - description: - - "The id of the user associated with this event." - type: str - - vm: - description: - - "The id of the VM associated with this event." - type: str -extends_documentation_fragment: ovirt -''' - -EXAMPLES = ''' -# Examples don't contain the auth parameter for simplicity, -# look at the ovirt_auth module to see how to reuse authentication. - -- name: Create an event - ovirt_event: - state: present - description: "The file system /home on host xyz is almost full!" - origin: "mymonitor" - custom_id: 123456789 - severity: warning - -- name: Create an event and link it to a specific object - ovirt_event: - state: present - description: "The file system /home is almost full!" - origin: "mymonitor" - custom_id: 123456789 - severity: warning - vm: "c79db183-46ef-44d1-95f9-1a368c516c19" - -- name: Remove an event - ovirt_event: - state: absent - id: 123456789 - wait: false -''' - -RETURN = ''' -id: - description: "ID of the event that was created." - returned: "On success." - type: str -event: - description: "Dictionary of all the Event attributes. All event attributes can be found at the following url: - http://ovirt.github.io/ovirt-engine-api-model/master/#types/event" - returned: "On success." - type: dict -''' - -import traceback - -try: - import ovirtsdk4.types as otypes -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - BaseModule, - check_sdk, - check_params, - create_connection, - equal, - get_dict_of_struct, - ovirt_full_argument_spec, -) - - -class EventsModule(BaseModule): - - def build_entity(self): - return otypes.Event( - description=self._module.params['description'], - severity=otypes.LogSeverity(self._module.params['severity']), - origin=self._module.params['origin'], - custom_id=self._module.params['custom_id'], - id=self._module.params['id'], - cluster=otypes.Cluster( - id=self._module.params['cluster'] - ) if self._module.params['cluster'] is not None else None, - data_center=otypes.DataCenter( - id=self._module.params['data_center'] - ) if self._module.params['data_center'] is not None else None, - host=otypes.Host( - id=self._module.params['host'] - ) if self._module.params['host'] is not None else None, - storage_domain=otypes.StorageDomain( - id=self._module.params['storage_domain'] - ) if self._module.params['storage_domain'] is not None else None, - template=otypes.Template( - id=self._module.params['template'] - ) if self._module.params['template'] is not None else None, - user=otypes.User( - id=self._module.params['user'] - ) if self._module.params['user'] is not None else None, - vm=otypes.Vm( - id=self._module.params['vm'] - ) if self._module.params['vm'] is not None else None, - ) - - -def main(): - argument_spec = ovirt_full_argument_spec( - state=dict( - choices=['present', 'absent'], - default='present', - ), - description=dict(default=None), - severity=dict( - choices=['error', 'normal', 'warning'], - default='normal', - ), - origin=dict(default=None), - custom_id=dict(default=None, type='int'), - id=dict(default=None), - cluster=dict(default=None), - data_center=dict(default=None), - host=dict(default=None), - storage_domain=dict(default=None), - template=dict(default=None), - user=dict(default=None), - vm=dict(default=None), - ) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True - ) - - check_sdk(module) - - # Wait must be set to false if state == absent - - if module.params['state'] == 'absent' and module.params['wait'] is not False: - module.fail_json(msg='When "state" is absent, "wait" must be set to false.') - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - events_service = connection.system_service().events_service() - events_module = EventsModule( - connection=connection, - module=module, - service=events_service, - ) - - state = module.params['state'] - if state == 'present': - ret = events_module.create() - elif state == 'absent': - ret = events_module.remove() - - module.exit_json(**ret) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_event_info.py b/lib/ansible/modules/cloud/ovirt/ovirt_event_info.py deleted file mode 100644 index 6e15fb31d9..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_event_info.py +++ /dev/null @@ -1,170 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright: (c) 2019, Ansible Project -# 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 - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_event_info -short_description: This module can be used to retrieve information about one or more oVirt/RHV events -author: "Chris Keller (@nasx)" -version_added: "2.8" -description: - - "Retrieve information about one or more oVirt/RHV events." - - This module was called C(ovirt_event_facts) before Ansible 2.9, returning C(ansible_facts). - Note that the M(ovirt_event_info) module no longer returns C(ansible_facts)! -options: - case_sensitive: - description: - - "Indicates if the search performed using the search parameter should be performed taking case - into account. The default value is true, which means that case is taken into account. If you - want to search ignoring case set it to false." - required: false - default: true - type: bool - - from_: - description: - - "Indicates the event index after which events should be returned. The indexes of events are - strictly increasing, so when this parameter is used only the events with greater indexes - will be returned." - required: false - type: int - - max: - description: - - "Sets the maximum number of events to return. If not specified all the events are returned." - required: false - type: int - - search: - description: - - "Search term which is accepted by the oVirt/RHV API." - - "For example to search for events of severity alert use the following pattern: severity=alert" - required: false - type: str - - headers: - description: - - "Additional HTTP headers." - required: false - type: str - - query: - description: - - "Additional URL query parameters." - required: false - type: str - - wait: - description: - - "If True wait for the response." - required: false - default: true - type: bool -extends_documentation_fragment: ovirt_info -''' - -EXAMPLES = ''' -# Examples don't contain the auth parameter for simplicity, -# look at the ovirt_auth module to see how to reuse authentication. - -- name: Return all events - ovirt_event_info: - register: result - -- name: Return the last 10 events - ovirt_event_info: - max: 10 - register: result - -- name: Return all events of type alert - ovirt_event_info: - search: "severity=alert" - register: result -- debug: - msg: "{{ result.ovirt_events }}" -''' - -RETURN = ''' -ovirt_events: - description: "List of dictionaries describing the events. Event attributes are mapped to dictionary keys. - All event attributes can be found at the following url: - http://ovirt.github.io/ovirt-engine-api-model/master/#types/event" - returned: On success." - type: list -''' - -import traceback - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - check_sdk, - create_connection, - get_dict_of_struct, - ovirt_info_full_argument_spec, -) - - -def main(): - argument_spec = ovirt_info_full_argument_spec( - case_sensitive=dict(default=True, type='bool', required=False), - from_=dict(default=None, type='int', required=False), - max=dict(default=None, type='int', required=False), - search=dict(default='', required=False), - headers=dict(default='', required=False), - query=dict(default='', required=False), - wait=dict(default=True, type='bool', required=False) - ) - module = AnsibleModule(argument_spec) - is_old_facts = module._name == 'ovirt_event_facts' - if is_old_facts: - module.deprecate("The 'ovirt_event_facts' module has been renamed to 'ovirt_event_info', " - "and the renamed one no longer returns ansible_facts", version='2.13') - - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - events_service = connection.system_service().events_service() - events = events_service.list( - case_sensitive=module.params['case_sensitive'], - from_=module.params['from_'], - max=module.params['max'], - search=module.params['search'], - headers=module.params['headers'], - query=module.params['query'], - wait=module.params['wait'] - ) - - result = dict( - ovirt_events=[ - get_dict_of_struct( - struct=c, - connection=connection, - fetch_nested=module.params.get('fetch_nested'), - attributes=module.params.get('nested_attributes'), - ) for c in events - ], - ) - if is_old_facts: - module.exit_json(changed=False, ansible_facts=result) - else: - module.exit_json(changed=False, **result) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_external_provider.py b/lib/ansible/modules/cloud/ovirt/ovirt_external_provider.py deleted file mode 100644 index f36d5a4a9f..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_external_provider.py +++ /dev/null @@ -1,406 +0,0 @@ -#!/usr/bin/python -# -*- 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 . -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_external_provider -short_description: Module to manage external providers in oVirt/RHV -version_added: "2.3" -author: "Ondra Machacek (@machacekondra)" -description: - - "Module to manage external providers in oVirt/RHV" -options: - name: - description: - - "Name of the external provider to manage." - state: - description: - - "Should the external be present or absent" - - "When you are using absent for I(os_volume), you need to make - sure that SD is not attached to the data center!" - choices: ['present', 'absent'] - default: present - description: - description: - - "Description of the external provider." - type: - description: - - "Type of the external provider." - choices: ['os_image', 'network', 'os_volume', 'foreman'] - url: - description: - - "URL where external provider is hosted." - - "Applicable for those types: I(os_image), I(os_volume), I(network) and I(foreman)." - username: - description: - - "Username to be used for login to external provider." - - "Applicable for all types." - password: - description: - - "Password of the user specified in C(username) parameter." - - "Applicable for all types." - tenant_name: - description: - - "Name of the tenant." - - "Applicable for those types: I(os_image), I(os_volume) and I(network)." - aliases: ['tenant'] - authentication_url: - description: - - "Keystone authentication URL of the openstack provider." - - "Applicable for those types: I(os_image), I(os_volume) and I(network)." - aliases: ['auth_url'] - data_center: - description: - - "Name of the data center where provider should be attached." - - "Applicable for those type: I(os_volume)." - read_only: - description: - - "Specify if the network should be read only." - - "Applicable if C(type) is I(network)." - type: bool - network_type: - description: - - "Type of the external network provider either external (for example OVN) or neutron." - - "Applicable if C(type) is I(network)." - choices: ['external', 'neutron'] - default: ['external'] - authentication_keys: - description: - - "List of authentication keys. Each key is represented by dict - like {'uuid': 'our-uuid', 'value': 'YourSecretValue=='}" - - "When you will not pass these keys and there are already some - of them defined in the system they will be removed." - - "Applicable for I(os_volume)." - default: [] - version_added: "2.6" -extends_documentation_fragment: ovirt -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Add image external provider: -- ovirt_external_provider: - name: image_provider - type: os_image - url: http://1.2.3.4:9292 - username: admin - password: 123456 - tenant: admin - auth_url: http://1.2.3.4:35357/v2.0 - -# Add volume external provider: -- ovirt_external_provider: - name: image_provider - type: os_volume - url: http://1.2.3.4:9292 - username: admin - password: 123456 - tenant: admin - auth_url: http://1.2.3.4:5000/v2.0 - authentication_keys: - - - uuid: "1234567-a1234-12a3-a234-123abc45678" - value: "ABCD00000000111111222333445w==" - -# Add foreman provider: -- ovirt_external_provider: - name: foreman_provider - type: foreman - url: https://foreman.example.com - username: admin - password: 123456 - -# Add external network provider for OVN: -- ovirt_external_provider: - name: ovn_provider - type: network - network_type: external - url: http://1.2.3.4:9696 - -# Remove image external provider: -- ovirt_external_provider: - state: absent - name: image_provider - type: os_image -''' - -RETURN = ''' -id: - description: ID of the external provider which is managed - returned: On success if external provider is found. - type: str - sample: 7de90f31-222c-436c-a1ca-7e655bd5b60c -external_host_provider: - description: "Dictionary of all the external_host_provider attributes. External provider attributes can be found on your oVirt/RHV instance - at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/external_host_provider." - returned: "On success and if parameter 'type: foreman' is used." - type: dict -openstack_image_provider: - description: "Dictionary of all the openstack_image_provider attributes. External provider attributes can be found on your oVirt/RHV instance - at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/openstack_image_provider." - returned: "On success and if parameter 'type: os_image' is used." - type: dict -openstack_volume_provider: - description: "Dictionary of all the openstack_volume_provider attributes. External provider attributes can be found on your oVirt/RHV instance - at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/openstack_volume_provider." - returned: "On success and if parameter 'type: os_volume' is used." - type: dict -openstack_network_provider: - description: "Dictionary of all the openstack_network_provider attributes. External provider attributes can be found on your oVirt/RHV instance - at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/openstack_network_provider." - returned: "On success and if parameter 'type: network' is used." - type: dict -''' - -import traceback - -try: - import ovirtsdk4.types as otypes -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - BaseModule, - check_params, - check_sdk, - create_connection, - equal, - ovirt_full_argument_spec, -) - - -OS_VOLUME = 'os_volume' -OS_IMAGE = 'os_image' -NETWORK = 'network' -FOREMAN = 'foreman' - - -class ExternalProviderModule(BaseModule): - - non_provider_params = ['type', 'authentication_keys', 'data_center'] - - def provider_type(self, provider_type): - self._provider_type = provider_type - - def provider_module_params(self): - provider_params = [ - (key, value) for key, value in self._module.params.items() if key - not in self.non_provider_params - ] - provider_params.append(('data_center', self.get_data_center())) - return provider_params - - def get_data_center(self): - dc_name = self._module.params.get("data_center", None) - if dc_name: - system_service = self._connection.system_service() - data_centers_service = system_service.data_centers_service() - return data_centers_service.list( - search='name=%s' % dc_name, - )[0] - return dc_name - - def build_entity(self): - provider_type = self._provider_type( - requires_authentication=self._module.params.get('username') is not None, - ) - if self._module.params.pop('type') == NETWORK: - setattr( - provider_type, - 'type', - otypes.OpenStackNetworkProviderType(self._module.params.pop('network_type')) - ) - - for key, value in self.provider_module_params(): - if hasattr(provider_type, key): - setattr(provider_type, key, value) - - return provider_type - - def update_check(self, entity): - return ( - equal(self._module.params.get('description'), entity.description) and - equal(self._module.params.get('url'), entity.url) and - equal(self._module.params.get('authentication_url'), entity.authentication_url) and - equal(self._module.params.get('tenant_name'), getattr(entity, 'tenant_name', None)) and - equal(self._module.params.get('username'), entity.username) - ) - - def update_volume_provider_auth_keys( - self, provider, providers_service, keys - ): - """ - Update auth keys for volume provider, if not exist add them or remove - if they are not specified and there are already defined in the external - volume provider. - - Args: - provider (dict): Volume provider details. - providers_service (openstack_volume_providers_service): Provider - service. - keys (list): Keys to be updated/added to volume provider, each key - is represented as dict with keys: uuid, value. - """ - - provider_service = providers_service.provider_service(provider['id']) - auth_keys_service = provider_service.authentication_keys_service() - provider_keys = auth_keys_service.list() - # removing keys which are not defined - for key in [ - k.id for k in provider_keys if k.uuid not in [ - defined_key['uuid'] for defined_key in keys - ] - ]: - self.changed = True - if not self._module.check_mode: - auth_keys_service.key_service(key).remove() - if not (provider_keys or keys): - # Nothing need to do when both are empty. - return - for key in keys: - key_id_for_update = None - for existing_key in provider_keys: - if key['uuid'] == existing_key.uuid: - key_id_for_update = existing_key.id - - auth_key_usage_type = ( - otypes.OpenstackVolumeAuthenticationKeyUsageType("ceph") - ) - auth_key = otypes.OpenstackVolumeAuthenticationKey( - usage_type=auth_key_usage_type, - uuid=key['uuid'], - value=key['value'], - ) - - if not key_id_for_update: - self.changed = True - if not self._module.check_mode: - auth_keys_service.add(auth_key) - else: - # We cannot really distinguish here if it was really updated cause - # we cannot take key value to check if it was changed or not. So - # for sure we update here always. - self.changed = True - if not self._module.check_mode: - auth_key_service = ( - auth_keys_service.key_service(key_id_for_update) - ) - auth_key_service.update(auth_key) - - -def _external_provider_service(provider_type, system_service): - if provider_type == OS_IMAGE: - return otypes.OpenStackImageProvider, system_service.openstack_image_providers_service() - elif provider_type == NETWORK: - return otypes.OpenStackNetworkProvider, system_service.openstack_network_providers_service() - elif provider_type == OS_VOLUME: - return otypes.OpenStackVolumeProvider, system_service.openstack_volume_providers_service() - elif provider_type == FOREMAN: - return otypes.ExternalHostProvider, system_service.external_host_providers_service() - - -def main(): - argument_spec = ovirt_full_argument_spec( - state=dict( - choices=['present', 'absent'], - default='present', - ), - name=dict(default=None), - description=dict(default=None), - type=dict( - default=None, - required=True, - choices=[ - OS_IMAGE, NETWORK, OS_VOLUME, FOREMAN, - ], - aliases=['provider'], - ), - url=dict(default=None), - username=dict(default=None), - password=dict(default=None, no_log=True), - tenant_name=dict(default=None, aliases=['tenant']), - authentication_url=dict(default=None, aliases=['auth_url']), - data_center=dict(default=None), - read_only=dict(default=None, type='bool'), - network_type=dict( - default='external', - choices=['external', 'neutron'], - ), - authentication_keys=dict( - default=[], aliases=['auth_keys'], type='list', no_log=True, - ), - ) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - ) - - check_sdk(module) - check_params(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - provider_type_param = module.params.get('type') - provider_type, external_providers_service = _external_provider_service( - provider_type=provider_type_param, - system_service=connection.system_service(), - ) - external_providers_module = ExternalProviderModule( - connection=connection, - module=module, - service=external_providers_service, - ) - external_providers_module.provider_type(provider_type) - - state = module.params.pop('state') - if state == 'absent': - ret = external_providers_module.remove() - elif state == 'present': - ret = external_providers_module.create() - openstack_volume_provider_id = ret.get('id') - if ( - provider_type_param == OS_VOLUME and - openstack_volume_provider_id - ): - external_providers_module.update_volume_provider_auth_keys( - ret, external_providers_service, - module.params.get('authentication_keys'), - ) - - module.exit_json(**ret) - - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_external_provider_info.py b/lib/ansible/modules/cloud/ovirt/ovirt_external_provider_info.py deleted file mode 100644 index 4a23f17e69..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_external_provider_info.py +++ /dev/null @@ -1,161 +0,0 @@ -#!/usr/bin/python -# -*- 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 . -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_external_provider_info -short_description: Retrieve information about one or more oVirt/RHV external providers -author: "Ondra Machacek (@machacekondra)" -version_added: "2.3" -description: - - "Retrieve information about one or more oVirt/RHV external providers." - - This module was called C(ovirt_external_provider_facts) before Ansible 2.9, returning C(ansible_facts). - Note that the M(ovirt_external_provider_info) module no longer returns C(ansible_facts)! -notes: - - "This module returns a variable C(ovirt_external_providers), which - contains a list of external_providers. You need to register the result with - the I(register) keyword to use it." -options: - type: - description: - - "Type of the external provider." - choices: ['os_image', 'os_network', 'os_volume', 'foreman'] - required: true - name: - description: - - "Name of the external provider, can be used as glob expression." -extends_documentation_fragment: ovirt_info -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Gather information about all image external providers named C: -- ovirt_external_provider_info: - type: os_image - name: glance - register: result -- debug: - msg: "{{ result.ovirt_external_providers }}" -''' - -RETURN = ''' -ovirt_external_providers: - description: - - "List of dictionaries. Content depends on I(type)." - - "For type C(foreman), attributes appearing in the dictionary can be found on your oVirt/RHV instance - at the following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/external_host_provider." - - "For type C(os_image), attributes appearing in the dictionary can be found on your oVirt/RHV instance - at the following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/openstack_image_provider." - - "For type C(os_volume), attributes appearing in the dictionary can be found on your oVirt/RHV instance - at the following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/openstack_volume_provider." - - "For type C(os_network), attributes appearing in the dictionary can be found on your oVirt/RHV instance - at the following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/openstack_network_provider." - returned: On success - type: list -''' - -import fnmatch -import traceback - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - check_sdk, - create_connection, - get_dict_of_struct, - ovirt_info_full_argument_spec, -) - - -def _external_provider_service(provider_type, system_service): - if provider_type == 'os_image': - return system_service.openstack_image_providers_service() - elif provider_type == 'os_network': - return system_service.openstack_network_providers_service() - elif provider_type == 'os_volume': - return system_service.openstack_volume_providers_service() - elif provider_type == 'foreman': - return system_service.external_host_providers_service() - - -def main(): - argument_spec = ovirt_info_full_argument_spec( - name=dict(default=None, required=False), - type=dict( - default=None, - required=True, - choices=[ - 'os_image', 'os_network', 'os_volume', 'foreman', - ], - aliases=['provider'], - ), - ) - module = AnsibleModule(argument_spec) - is_old_facts = module._name == 'ovirt_external_provider_facts' - if is_old_facts: - module.deprecate("The 'ovirt_external_provider_facts' module has been renamed to 'ovirt_external_provider_info', " - "and the renamed one no longer returns ansible_facts", version='2.13') - - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - external_providers_service = _external_provider_service( - provider_type=module.params.pop('type'), - system_service=connection.system_service(), - ) - if module.params['name']: - external_providers = [ - e for e in external_providers_service.list() - if fnmatch.fnmatch(e.name, module.params['name']) - ] - else: - external_providers = external_providers_service.list() - - result = dict( - ovirt_external_providers=[ - get_dict_of_struct( - struct=c, - connection=connection, - fetch_nested=module.params.get('fetch_nested'), - attributes=module.params.get('nested_attributes'), - ) for c in external_providers - ], - ) - if is_old_facts: - module.exit_json(changed=False, ansible_facts=result) - else: - module.exit_json(changed=False, **result) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_group.py b/lib/ansible/modules/cloud/ovirt/ovirt_group.py deleted file mode 100644 index 4f6777ed25..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_group.py +++ /dev/null @@ -1,185 +0,0 @@ -#!/usr/bin/python -# -*- 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 . -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_group -short_description: Module to manage groups in oVirt/RHV -version_added: "2.3" -author: "Ondra Machacek (@machacekondra)" -description: - - "Module to manage groups in oVirt/RHV" -options: - name: - description: - - "Name of the group to manage." - required: true - state: - description: - - "Should the group be present/absent." - choices: ['present', 'absent'] - default: present - authz_name: - description: - - "Authorization provider of the group. In previous versions of oVirt/RHV known as domain." - required: true - aliases: ['domain'] - namespace: - description: - - "Namespace of the authorization provider, where group resides." - required: false -extends_documentation_fragment: ovirt -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Add group group1 from authorization provider example.com-authz -- ovirt_group: - name: group1 - domain: example.com-authz - -# Add group group1 from authorization provider example.com-authz -# In case of multi-domain Active Directory setup, you should pass -# also namespace, so it adds correct group: -- ovirt_group: - name: group1 - namespace: dc=ad2,dc=example,dc=com - domain: example.com-authz - -# Remove group group1 with authorization provider example.com-authz -- ovirt_group: - state: absent - name: group1 - domain: example.com-authz -''' - -RETURN = ''' -id: - description: ID of the group which is managed - returned: On success if group is found. - type: str - sample: 7de90f31-222c-436c-a1ca-7e655bd5b60c -group: - description: "Dictionary of all the group attributes. Group attributes can be found on your oVirt/RHV instance - at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/group." - returned: On success if group is found. - type: dict -''' - -import traceback - -try: - import ovirtsdk4.types as otypes -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - BaseModule, - check_sdk, - check_params, - create_connection, - equal, - ovirt_full_argument_spec, -) - - -def _group(connection, module): - groups = connection.system_service().groups_service().list( - search="name={name}".format( - name=module.params['name'], - ) - ) - - # If found more groups, filter them by namespace and authz name: - # (filtering here, as oVirt/RHV backend doesn't support it) - if len(groups) > 1: - groups = [ - g for g in groups if ( - equal(module.params['namespace'], g.namespace) and - equal(module.params['authz_name'], g.domain.name) - ) - ] - return groups[0] if groups else None - - -class GroupsModule(BaseModule): - - def build_entity(self): - return otypes.Group( - domain=otypes.Domain( - name=self._module.params['authz_name'] - ), - name=self._module.params['name'], - namespace=self._module.params['namespace'], - ) - - -def main(): - argument_spec = ovirt_full_argument_spec( - state=dict( - choices=['present', 'absent'], - default='present', - ), - name=dict(required=True), - authz_name=dict(required=True, aliases=['domain']), - namespace=dict(default=None), - ) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - ) - - check_sdk(module) - check_params(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - groups_service = connection.system_service().groups_service() - groups_module = GroupsModule( - connection=connection, - module=module, - service=groups_service, - ) - group = _group(connection, module) - state = module.params['state'] - if state == 'present': - ret = groups_module.create(entity=group) - elif state == 'absent': - ret = groups_module.remove(entity=group) - - module.exit_json(**ret) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_group_info.py b/lib/ansible/modules/cloud/ovirt/ovirt_group_info.py deleted file mode 100644 index b1381372d0..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_group_info.py +++ /dev/null @@ -1,118 +0,0 @@ -#!/usr/bin/python -# -*- 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 . -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_group_info -short_description: Retrieve information about one or more oVirt/RHV groups -author: "Ondra Machacek (@machacekondra)" -version_added: "2.3" -description: - - "Retrieve information about one or more oVirt/RHV groups." - - This module was called C(ovirt_group_facts) before Ansible 2.9, returning C(ansible_facts). - Note that the M(ovirt_group_info) module no longer returns C(ansible_facts)! -notes: - - "This module returns a variable C(ovirt_groups), which - contains a list of groups. You need to register the result with - the I(register) keyword to use it." -options: - pattern: - description: - - "Search term which is accepted by oVirt/RHV search backend." - - "For example to search group X use following pattern: name=X" -extends_documentation_fragment: ovirt_info -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Gather information about all groups which names start with C(admin): -- ovirt_group_info: - pattern: name=admin* - register: result -- debug: - msg: "{{ result.ovirt_groups }}" -''' - -RETURN = ''' -ovirt_groups: - description: "List of dictionaries describing the groups. Group attributes are mapped to dictionary keys, - all groups attributes can be found at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/group." - returned: On success. - type: list -''' - -import traceback - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - check_sdk, - create_connection, - get_dict_of_struct, - ovirt_info_full_argument_spec, -) - - -def main(): - argument_spec = ovirt_info_full_argument_spec( - pattern=dict(default='', required=False), - ) - module = AnsibleModule(argument_spec) - is_old_facts = module._name == 'ovirt_group_facts' - if is_old_facts: - module.deprecate("The 'ovirt_group_facts' module has been renamed to 'ovirt_group_info', " - "and the renamed one no longer returns ansible_facts", version='2.13') - - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - groups_service = connection.system_service().groups_service() - groups = groups_service.list(search=module.params['pattern']) - result = dict( - ovirt_groups=[ - get_dict_of_struct( - struct=c, - connection=connection, - fetch_nested=module.params.get('fetch_nested'), - attributes=module.params.get('nested_attributes'), - ) for c in groups - ], - ) - if is_old_facts: - module.exit_json(changed=False, ansible_facts=result) - else: - module.exit_json(changed=False, **result) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_host.py b/lib/ansible/modules/cloud/ovirt/ovirt_host.py deleted file mode 100644 index c5e26625f3..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_host.py +++ /dev/null @@ -1,701 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (c) 2016 Red Hat, Inc. -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_host -short_description: Module to manage hosts in oVirt/RHV -version_added: "2.3" -author: "Ondra Machacek (@machacekondra)" -description: - - "Module to manage hosts in oVirt/RHV" -options: - id: - description: - - "ID of the host to manage." - version_added: "2.8" - name: - description: - - "Name of the host to manage." - required: true - state: - description: - - "State which should a host to be in after successful completion." - - "I(iscsilogin) and I(iscsidiscover) are supported since version 2.4." - choices: [ - 'present', 'absent', 'maintenance', 'upgraded', 'started', - 'restarted', 'stopped', 'reinstalled', 'iscsidiscover', 'iscsilogin' - ] - default: present - comment: - description: - - "Description of the host." - timeout: - description: - - "The amount of time in seconds the module should wait for the host to - get into desired state." - default: 600 - cluster: - description: - - "Name of the cluster, where host should be created." - address: - description: - - "Host address. It can be either FQDN (preferred) or IP address." - password: - description: - - "Password of the root. It's required in case C(public_key) is set to I(False)." - public_key: - description: - - "I(True) if the public key should be used to authenticate to host." - - "It's required in case C(password) is not set." - default: False - type: bool - aliases: ['ssh_public_key'] - kdump_integration: - description: - - "Specify if host will have enabled Kdump integration." - choices: ['enabled', 'disabled'] - spm_priority: - description: - - "SPM priority of the host. Integer value from 1 to 10, where higher number means higher priority." - override_iptables: - description: - - "If True host iptables will be overridden by host deploy script." - - "Note that C(override_iptables) is I(false) by default in oVirt/RHV." - type: bool - force: - description: - - "Indicates that the host should be removed even if it is non-responsive, - or if it is part of a Gluster Storage cluster and has volume bricks on it." - - "WARNING: It doesn't forcibly remove the host if another host related operation is being executed on the host at the same time." - default: False - type: bool - override_display: - description: - - "Override the display address of all VMs on this host with specified address." - type: bool - kernel_params: - description: - - "List of kernel boot parameters." - - "Following are most common kernel parameters used for host:" - - "Hostdev Passthrough & SR-IOV: intel_iommu=on" - - "Nested Virtualization: kvm-intel.nested=1" - - "Unsafe Interrupts: vfio_iommu_type1.allow_unsafe_interrupts=1" - - "PCI Reallocation: pci=realloc" - - "C(Note:)" - - "Modifying kernel boot parameters settings can lead to a host boot failure. - Please consult the product documentation before doing any changes." - - "Kernel boot parameters changes require host deploy and restart. The host needs - to be I(reinstalled) successfully and then to be I(rebooted) for kernel boot parameters - to be applied." - hosted_engine: - description: - - "If I(deploy) it means this host should deploy also hosted engine - components." - - "If I(undeploy) it means this host should un-deploy hosted engine - components and this host will not function as part of the High - Availability cluster." - choices: - - 'deploy' - - 'undeploy' - power_management_enabled: - description: - - "Enable or disable power management of the host." - - "For more comprehensive setup of PM use C(ovirt_host_pm) module." - version_added: 2.4 - type: bool - activate: - description: - - "If C(state) is I(present) activate the host." - - "This parameter is good to disable, when you don't want to change - the state of host when using I(present) C(state)." - default: True - type: bool - version_added: 2.4 - iscsi: - description: - - "If C(state) is I(iscsidiscover) it means that the iscsi attribute is being - used to discover targets" - - "If C(state) is I(iscsilogin) it means that the iscsi attribute is being - used to login to the specified targets passed as part of the iscsi attribute" - suboptions: - username: - description: - - "A CHAP user name for logging into a target." - password: - description: - - "A CHAP password for logging into a target." - address: - description: - - "Address of the iSCSI storage server." - target: - description: - - "The target IQN for the storage device." - port: - description: - - "The port being used to connect with iscsi." - portal: - description: - - "The portal being used to connect with iscsi." - version_added: 2.10 - version_added: 2.4 - check_upgrade: - description: - - "If I(true) and C(state) is I(upgraded) run check for upgrade - action before executing upgrade action." - default: True - type: bool - version_added: 2.4 - reboot_after_upgrade: - description: - - "If I(true) and C(state) is I(upgraded) reboot host after successful upgrade." - default: True - type: bool - version_added: 2.6 - vgpu_placement: - description: - - If I(consolidated), each vGPU is placed on the first physical card with - available space. This is the default placement, utilizing all available - space on the physical cards. - - If I(separated), each vGPU is placed on a separate physical card, if - possible. This can be useful for improving vGPU performance. - choices: ['consolidated', 'separated'] - version_added: 2.8 -extends_documentation_fragment: ovirt -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Add host with username/password supporting SR-IOV. -# Note that override_iptables is false by default in oVirt/RHV: -- ovirt_host: - cluster: Default - name: myhost - address: 10.34.61.145 - password: secret - override_iptables: true - kernel_params: - - intel_iommu=on - -# Add host using public key -- ovirt_host: - public_key: true - cluster: Default - name: myhost2 - address: 10.34.61.145 - override_iptables: true - -# Deploy hosted engine host -- ovirt_host: - cluster: Default - name: myhost2 - password: secret - address: 10.34.61.145 - override_iptables: true - hosted_engine: deploy - -# Maintenance -- ovirt_host: - state: maintenance - name: myhost - -# Restart host using power management: -- ovirt_host: - state: restarted - name: myhost - -# Upgrade host -- ovirt_host: - state: upgraded - name: myhost - -# discover iscsi targets -- ovirt_host: - state: iscsidiscover - name: myhost - iscsi: - username: iscsi_user - password: secret - address: 10.34.61.145 - port: 3260 - - -# login to iscsi targets -- ovirt_host: - state: iscsilogin - name: myhost - iscsi: - username: iscsi_user - password: secret - address: 10.34.61.145 - target: "iqn.2015-07.com.mlipchuk2.redhat:444" - port: 3260 - - -# Reinstall host using public key -- ovirt_host: - state: reinstalled - name: myhost - public_key: true - -# Remove host -- ovirt_host: - state: absent - name: myhost - force: True - -# Retry removing host when failed (https://bugzilla.redhat.com/show_bug.cgi?id=1719271) -- ovirt_host: - state: absent - name: myhost - register: result - until: not result.failed - retries: 6 - delay: 20 - -# Change host Name -- ovirt_host: - id: 00000000-0000-0000-0000-000000000000 - name: "new host name" -''' - -RETURN = ''' -id: - description: ID of the host which is managed - returned: On success if host is found. - type: str - sample: 7de90f31-222c-436c-a1ca-7e655bd5b60c -host: - description: "Dictionary of all the host attributes. Host attributes can be found on your oVirt/RHV instance - at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/host." - returned: On success if host is found. - type: dict -iscsi_targets: - description: "List of host iscsi targets" - returned: On success if host is found and state is iscsidiscover. - type: list -''' - -import time -import traceback - -try: - import ovirtsdk4.types as otypes - - from ovirtsdk4.types import HostStatus as hoststate -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - BaseModule, - check_sdk, - create_connection, - equal, - get_id_by_name, - ovirt_full_argument_spec, - wait, -) - - -class HostsModule(BaseModule): - def __init__(self, start_event=None, *args, **kwargs): - super(HostsModule, self).__init__(*args, **kwargs) - self.start_event = start_event - - def build_entity(self): - return otypes.Host( - id=self._module.params.get('id'), - name=self.param('name'), - cluster=otypes.Cluster( - name=self.param('cluster') - ) if self.param('cluster') else None, - comment=self.param('comment'), - address=self.param('address'), - root_password=self.param('password'), - ssh=otypes.Ssh( - authentication_method=otypes.SshAuthenticationMethod.PUBLICKEY, - ) if self.param('public_key') else None, - spm=otypes.Spm( - priority=self.param('spm_priority'), - ) if self.param('spm_priority') else None, - override_iptables=self.param('override_iptables'), - display=otypes.Display( - address=self.param('override_display'), - ) if self.param('override_display') else None, - os=otypes.OperatingSystem( - custom_kernel_cmdline=' '.join(self.param('kernel_params')), - ) if self.param('kernel_params') else None, - power_management=otypes.PowerManagement( - enabled=self.param('power_management_enabled'), - kdump_detection=self.param('kdump_integration') == 'enabled', - ) if self.param('power_management_enabled') is not None or self.param('kdump_integration') else None, - vgpu_placement=otypes.VgpuPlacement( - self.param('vgpu_placement') - ) if self.param('vgpu_placement') is not None else None, - ) - - def update_check(self, entity): - kernel_params = self.param('kernel_params') - return ( - equal(self.param('comment'), entity.comment) and - equal(self.param('kdump_integration'), 'enabled' if entity.power_management.kdump_detection else 'disabled') and - equal(self.param('spm_priority'), entity.spm.priority) and - equal(self.param('name'), entity.name) and - equal(self.param('power_management_enabled'), entity.power_management.enabled) and - equal(self.param('override_display'), getattr(entity.display, 'address', None)) and - equal(self.param('vgpu_placement'), str(entity.vgpu_placement)) and - equal( - sorted(kernel_params) if kernel_params else None, - sorted(entity.os.custom_kernel_cmdline.split(' ')) - ) - ) - - def pre_remove(self, entity): - self.action( - entity=entity, - action='deactivate', - action_condition=lambda h: h.status != hoststate.MAINTENANCE, - wait_condition=lambda h: h.status == hoststate.MAINTENANCE, - ) - - def post_reinstall(self, host): - wait( - service=self._service.service(host.id), - condition=lambda h: h.status != hoststate.MAINTENANCE, - fail_condition=failed_state, - wait=self.param('wait'), - timeout=self.param('timeout'), - ) - - def raise_host_exception(self): - events = self._connection.system_service().events_service().list(from_=int(self.start_event.index)) - error_events = [ - event.description for event in events - if event.host is not None and (event.host.id == self.param('id') or event.host.name == self.param('name')) and - event.severity in [otypes.LogSeverity.WARNING, otypes.LogSeverity.ERROR] - ] - if error_events: - raise Exception("Error message: %s" % error_events) - return True - - def failed_state_after_reinstall(self, host, count=0): - if host.status in [ - hoststate.ERROR, - hoststate.INSTALL_FAILED, - hoststate.NON_OPERATIONAL, - ]: - return self.raise_host_exception() - - # If host is in non-responsive state after upgrade/install - # let's wait for few seconds and re-check again the state: - if host.status == hoststate.NON_RESPONSIVE: - if count <= 3: - time.sleep(20) - return self.failed_state_after_reinstall( - self._service.service(host.id).get(), - count + 1, - ) - else: - return self.raise_host_exception() - - return False - - -def failed_state(host): - return host.status in [ - hoststate.ERROR, - hoststate.INSTALL_FAILED, - hoststate.NON_RESPONSIVE, - hoststate.NON_OPERATIONAL, - ] - - -def control_state(host_module): - host = host_module.search_entity() - if host is None: - return - - state = host_module._module.params['state'] - host_service = host_module._service.service(host.id) - if failed_state(host): - # In case host is in INSTALL_FAILED status, we can reinstall it: - if hoststate.INSTALL_FAILED == host.status and state != 'reinstalled': - raise Exception( - "Not possible to manage host '%s' in state '%s'." % ( - host.name, - host.status - ) - ) - elif host.status in [ - hoststate.REBOOT, - hoststate.CONNECTING, - hoststate.INITIALIZING, - hoststate.INSTALLING, - hoststate.INSTALLING_OS, - ]: - wait( - service=host_service, - condition=lambda host: host.status == hoststate.UP, - fail_condition=failed_state, - ) - elif host.status == hoststate.PREPARING_FOR_MAINTENANCE: - wait( - service=host_service, - condition=lambda host: host.status == hoststate.MAINTENANCE, - fail_condition=failed_state, - ) - - return host - - -def main(): - argument_spec = ovirt_full_argument_spec( - state=dict( - choices=[ - 'present', 'absent', 'maintenance', 'upgraded', 'started', - 'restarted', 'stopped', 'reinstalled', 'iscsidiscover', 'iscsilogin' - ], - default='present', - ), - name=dict(required=True), - id=dict(default=None), - comment=dict(default=None), - cluster=dict(default=None), - address=dict(default=None), - password=dict(default=None, no_log=True), - public_key=dict(default=False, type='bool', aliases=['ssh_public_key']), - kdump_integration=dict(default=None, choices=['enabled', 'disabled']), - spm_priority=dict(default=None, type='int'), - override_iptables=dict(default=None, type='bool'), - force=dict(default=False, type='bool'), - timeout=dict(default=600, type='int'), - override_display=dict(default=None), - kernel_params=dict(default=None, type='list'), - hosted_engine=dict(default=None, choices=['deploy', 'undeploy']), - power_management_enabled=dict(default=None, type='bool'), - activate=dict(default=True, type='bool'), - iscsi=dict(default=None, type='dict'), - check_upgrade=dict(default=True, type='bool'), - reboot_after_upgrade=dict(default=True, type='bool'), - vgpu_placement=dict(default=None, choices=['consolidated', 'separated']), - ) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - required_if=[ - ['state', 'iscsidiscover', ['iscsi']], - ['state', 'iscsilogin', ['iscsi']] - ] - ) - - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - hosts_service = connection.system_service().hosts_service() - start_event = connection.system_service().events_service().list(max=1)[0] - hosts_module = HostsModule( - connection=connection, - module=module, - service=hosts_service, - start_event=start_event, - ) - - state = module.params['state'] - host = control_state(hosts_module) - if state == 'present': - ret = hosts_module.create( - deploy_hosted_engine=( - module.params.get('hosted_engine') == 'deploy' - ) if module.params.get('hosted_engine') is not None else None, - activate=module.params['activate'], - result_state=(hoststate.MAINTENANCE if module.params['activate'] is False else hoststate.UP) if host is None else None, - fail_condition=hosts_module.failed_state_after_reinstall if host is None else lambda h: False, - ) - if module.params['activate'] and host is not None: - ret = hosts_module.action( - action='activate', - action_condition=lambda h: h.status != hoststate.UP, - wait_condition=lambda h: h.status == hoststate.UP, - fail_condition=failed_state, - ) - elif state == 'absent': - ret = hosts_module.remove() - elif state == 'maintenance': - hosts_module.action( - action='deactivate', - action_condition=lambda h: h.status != hoststate.MAINTENANCE, - wait_condition=lambda h: h.status == hoststate.MAINTENANCE, - fail_condition=failed_state, - ) - ret = hosts_module.create() - elif state == 'upgraded': - result_state = hoststate.MAINTENANCE if host.status == hoststate.MAINTENANCE else hoststate.UP - events_service = connection.system_service().events_service() - last_event = events_service.list(max=1)[0] - - if module.params['check_upgrade']: - hosts_module.action( - action='upgrade_check', - action_condition=lambda host: not host.update_available, - wait_condition=lambda host: host.update_available or ( - len([ - event - for event in events_service.list( - from_=int(last_event.id), - search='type=885', - # Uncomment when 4.1 is EOL, and remove the cond: - # if host.name in event.description - # search='type=885 and host.name=%s' % host.name, - ) if host.name in event.description - ]) > 0 - ), - fail_condition=lambda host: len([ - event - for event in events_service.list( - from_=int(last_event.id), - search='type=839 or type=887 and host.name=%s' % host.name, - ) - ]) > 0, - ) - # Set to False, because upgrade_check isn't 'changing' action: - hosts_module._changed = False - ret = hosts_module.action( - action='upgrade', - action_condition=lambda h: h.update_available, - wait_condition=lambda h: h.status == result_state, - post_action=lambda h: time.sleep(module.params['poll_interval']), - fail_condition=lambda h: hosts_module.failed_state_after_reinstall(h) or ( - len([ - event - for event in events_service.list( - from_=int(last_event.id), - # Fail upgrade if migration fails: - # 17: Failed to switch Host to Maintenance mode - # 65, 140: Migration failed - # 166: No available host was found to migrate VM - search='type=65 or type=140 or type=166 or type=17', - ) if host.name in event.description - ]) > 0 - ), - reboot=module.params['reboot_after_upgrade'], - ) - elif state == 'iscsidiscover': - host_id = get_id_by_name(hosts_service, module.params['name']) - iscsi_param = module.params['iscsi'] - iscsi_targets = hosts_service.service(host_id).iscsi_discover( - iscsi=otypes.IscsiDetails( - port=int(iscsi_param.get('port', 3260)), - username=iscsi_param.get('username'), - password=iscsi_param.get('password'), - address=iscsi_param.get('address'), - portal=iscsi_param.get('portal'), - ), - ) - ret = { - 'changed': False, - 'id': host_id, - 'iscsi_targets': iscsi_targets, - } - elif state == 'iscsilogin': - host_id = get_id_by_name(hosts_service, module.params['name']) - iscsi_param = module.params['iscsi'] - ret = hosts_module.action( - action='iscsi_login', - iscsi=otypes.IscsiDetails( - port=int(iscsi_param.get('port', 3260)), - username=iscsi_param.get('username'), - password=iscsi_param.get('password'), - address=iscsi_param.get('address'), - target=iscsi_param.get('target'), - portal=iscsi_param.get('portal'), - ), - ) - elif state == 'started': - ret = hosts_module.action( - action='fence', - action_condition=lambda h: h.status == hoststate.DOWN, - wait_condition=lambda h: h.status in [hoststate.UP, hoststate.MAINTENANCE], - fail_condition=hosts_module.failed_state_after_reinstall, - fence_type='start', - ) - elif state == 'stopped': - hosts_module.action( - action='deactivate', - action_condition=lambda h: h.status not in [hoststate.MAINTENANCE, hoststate.DOWN], - wait_condition=lambda h: h.status in [hoststate.MAINTENANCE, hoststate.DOWN], - fail_condition=failed_state, - ) - ret = hosts_module.action( - action='fence', - action_condition=lambda h: h.status != hoststate.DOWN, - wait_condition=lambda h: h.status == hoststate.DOWN if module.params['wait'] else True, - fail_condition=failed_state, - fence_type='stop', - ) - elif state == 'restarted': - ret = hosts_module.action( - action='fence', - wait_condition=lambda h: h.status == hoststate.UP, - fail_condition=hosts_module.failed_state_after_reinstall, - fence_type='restart', - ) - elif state == 'reinstalled': - # Deactivate host if not in maintanence: - hosts_module.action( - action='deactivate', - action_condition=lambda h: h.status not in [hoststate.MAINTENANCE, hoststate.DOWN], - wait_condition=lambda h: h.status in [hoststate.MAINTENANCE, hoststate.DOWN], - fail_condition=failed_state, - ) - - # Reinstall host: - hosts_module.action( - action='install', - action_condition=lambda h: h.status == hoststate.MAINTENANCE, - post_action=hosts_module.post_reinstall, - wait_condition=lambda h: h.status == hoststate.MAINTENANCE, - fail_condition=hosts_module.failed_state_after_reinstall, - host=otypes.Host( - override_iptables=module.params['override_iptables'], - ) if module.params['override_iptables'] else None, - root_password=module.params['password'], - ssh=otypes.Ssh( - authentication_method=otypes.SshAuthenticationMethod.PUBLICKEY, - ) if module.params['public_key'] else None, - deploy_hosted_engine=( - module.params.get('hosted_engine') == 'deploy' - ) if module.params.get('hosted_engine') is not None else None, - undeploy_hosted_engine=( - module.params.get('hosted_engine') == 'undeploy' - ) if module.params.get('hosted_engine') is not None else None, - ) - - # Activate host after reinstall: - ret = hosts_module.action( - action='activate', - action_condition=lambda h: h.status == hoststate.MAINTENANCE, - wait_condition=lambda h: h.status == hoststate.UP, - fail_condition=failed_state, - ) - module.exit_json(**ret) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_host_info.py b/lib/ansible/modules/cloud/ovirt/ovirt_host_info.py deleted file mode 100644 index 807baa20dc..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_host_info.py +++ /dev/null @@ -1,144 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (c) 2016 Red Hat, Inc. -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_host_info -short_description: Retrieve information about one or more oVirt/RHV hosts -author: "Ondra Machacek (@machacekondra)" -version_added: "2.3" -description: - - "Retrieve information about one or more oVirt/RHV hosts." - - This module was called C(ovirt_host_facts) before Ansible 2.9, returning C(ansible_facts). - Note that the M(ovirt_host_info) module no longer returns C(ansible_facts)! -notes: - - "This module returns a variable C(ovirt_hosts), which - contains a list of hosts. You need to register the result with - the I(register) keyword to use it." -options: - pattern: - description: - - "Search term which is accepted by oVirt/RHV search backend." - - "For example to search host X from datacenter Y use following pattern: - name=X and datacenter=Y" - all_content: - description: - - "If I(true) all the attributes of the hosts should be - included in the response." - default: False - version_added: "2.7" - type: bool - cluster_version: - description: - - "Filter the hosts based on the cluster version." - type: str - version_added: "2.8" - -extends_documentation_fragment: ovirt_info -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Gather information about all hosts which names start with C(host) and -# belong to data center C(west): -- ovirt_host_info: - pattern: name=host* and datacenter=west - register: result -- debug: - msg: "{{ result.ovirt_hosts }}" -# All hosts with cluster version 4.2: -- ovirt_host_info: - pattern: name=host* - cluster_version: "4.2" - register: result -- debug: - msg: "{{ result.ovirt_hosts }}" -''' - -RETURN = ''' -ovirt_hosts: - description: "List of dictionaries describing the hosts. Host attributes are mapped to dictionary keys, - all hosts attributes can be found at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/host." - returned: On success. - type: list -''' - -import traceback - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - check_sdk, - create_connection, - get_dict_of_struct, - ovirt_info_full_argument_spec, -) - - -def get_filtered_hosts(cluster_version, hosts, connection): - # Filtering by cluster version returns only those which have same cluster version as input - filtered_hosts = [] - for host in hosts: - cluster = connection.follow_link(host.cluster) - cluster_version_host = str(cluster.version.major) + '.' + str(cluster.version.minor) - if cluster_version_host == cluster_version: - filtered_hosts.append(host) - return filtered_hosts - - -def main(): - argument_spec = ovirt_info_full_argument_spec( - pattern=dict(default='', required=False), - all_content=dict(default=False, type='bool'), - cluster_version=dict(default=None, type='str'), - ) - module = AnsibleModule(argument_spec) - is_old_facts = module._name == 'ovirt_host_facts' - if is_old_facts: - module.deprecate("The 'ovirt_host_facts' module has been renamed to 'ovirt_host_info', " - "and the renamed one no longer returns ansible_facts", version='2.13') - - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - hosts_service = connection.system_service().hosts_service() - hosts = hosts_service.list( - search=module.params['pattern'], - all_content=module.params['all_content'] - ) - cluster_version = module.params.get('cluster_version') - if cluster_version is not None: - hosts = get_filtered_hosts(cluster_version, hosts, connection) - result = dict( - ovirt_hosts=[ - get_dict_of_struct( - struct=c, - connection=connection, - fetch_nested=module.params.get('fetch_nested'), - attributes=module.params.get('nested_attributes'), - ) for c in hosts - ], - ) - if is_old_facts: - module.exit_json(changed=False, ansible_facts=result) - else: - module.exit_json(changed=False, **result) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_host_network.py b/lib/ansible/modules/cloud/ovirt/ovirt_host_network.py deleted file mode 100644 index 8c4ac44d70..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_host_network.py +++ /dev/null @@ -1,601 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (c) 2016, 2018 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 . -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_host_network -short_description: Module to manage host networks in oVirt/RHV -version_added: "2.3" -author: "Ondra Machacek (@machacekondra)" -description: - - "Module to manage host networks in oVirt/RHV." -options: - name: - description: - - "Name of the host to manage networks for." - required: true - aliases: - - 'host' - state: - description: - - "Should the host be present/absent." - choices: ['present', 'absent'] - default: present - bond: - description: - - "Dictionary describing network bond:" - suboptions: - name: - description: - - Bond name. - mode: - description: - - Bonding mode. - options: - description: - - Bonding options. - interfaces: - description: - - List of interfaces to create a bond. - interface: - description: - - "Name of the network interface where logical network should be attached." - networks: - description: - - "List of dictionary describing networks to be attached to interface or bond:" - suboptions: - name: - description: - - Name of the logical network to be assigned to bond or interface. - boot_protocol: - description: - - Boot protocol. - choices: ['none', 'static', 'dhcp'] - address: - description: - - IP address in case of I(static) boot protocol is used. - netmask: - description: - - Subnet mask in case of I(static) boot protocol is used. - gateway: - description: - - Gateway in case of I(static) boot protocol is used. - version: - description: - - IP version. Either v4 or v6. Default is v4. - custom_properties: - description: - - "Custom properties applied to the host network." - - "Custom properties is a list of dictionary which can have following values." - suboptions: - name: - description: - - Name of custom property. - value: - description: - - Value of custom property. - version_added: 2.10 - labels: - description: - - "List of names of the network label to be assigned to bond or interface." - check: - description: - - "If I(true) verify connectivity between host and engine." - - "Network configuration changes will be rolled back if connectivity between - engine and the host is lost after changing network configuration." - type: bool - save: - description: - - "If I(true) network configuration will be persistent, otherwise it is temporary. Default I(true) since Ansible 2.8." - type: bool - default: True - sync_networks: - description: - - "If I(true) all networks will be synchronized before modification" - type: bool - default: false - version_added: 2.8 -extends_documentation_fragment: ovirt -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# In all examples the durability of the configuration created is dependent on the 'save' option value: - -# Create bond on eth0 and eth1 interface, and put 'myvlan' network on top of it and persist the new configuration: -- name: Bonds - ovirt_host_network: - name: myhost - save: yes - bond: - name: bond0 - mode: 2 - interfaces: - - eth1 - - eth2 - networks: - - name: myvlan - boot_protocol: static - address: 1.2.3.4 - netmask: 255.255.255.0 - gateway: 1.2.3.4 - version: v4 - -# Create bond on eth1 and eth2 interface, specifying both mode and miimon: -- name: Bonds - ovirt_host_network: - name: myhost - bond: - name: bond0 - mode: 1 - options: - miimon: 200 - interfaces: - - eth1 - - eth2 - -# Remove bond0 bond from host interfaces: -- ovirt_host_network: - state: absent - name: myhost - bond: - name: bond0 - -# Assign myvlan1 and myvlan2 vlans to host eth0 interface: -- ovirt_host_network: - name: myhost - interface: eth0 - networks: - - name: myvlan1 - - name: myvlan2 - -# Remove myvlan2 vlan from host eth0 interface: -- ovirt_host_network: - state: absent - name: myhost - interface: eth0 - networks: - - name: myvlan2 - -# Remove all networks/vlans from host eth0 interface: -- ovirt_host_network: - state: absent - name: myhost - interface: eth0 - -# Add custom_properties to network: -- ovirt_host_network: - name: myhost - interface: eth0 - networks: - - name: myvlan1 - custom_properties: - - name: bridge_opts - value: gc_timer=10 -''' - -RETURN = ''' -id: - description: ID of the host NIC which is managed - returned: On success if host NIC is found. - type: str - sample: 7de90f31-222c-436c-a1ca-7e655bd5b60c -host_nic: - description: "Dictionary of all the host NIC attributes. Host NIC attributes can be found on your oVirt/RHV instance - at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/host_nic." - returned: On success if host NIC is found. - type: dict -''' - -import traceback - -try: - import ovirtsdk4.types as otypes -except ImportError: - pass - -from ansible.module_utils import six -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - BaseModule, - check_sdk, - create_connection, - equal, - get_dict_of_struct, - get_entity, - get_link_name, - ovirt_full_argument_spec, - search_by_name, - engine_supported -) - - -def get_bond_options(mode, usr_opts): - MIIMON_100 = dict(miimon='100') - DEFAULT_MODE_OPTS = { - '1': MIIMON_100, - '2': MIIMON_100, - '3': MIIMON_100, - '4': dict(xmit_hash_policy='2', **MIIMON_100) - } - - options = [] - if mode is None: - return options - - def get_type_name(mode_number): - """ - We need to maintain this type strings, for the __compare_options method, - for easier comparision. - """ - modes = [ - 'Active-Backup', - 'Load balance (balance-xor)', - None, - 'Dynamic link aggregation (802.3ad)', - ] - if (not 0 < mode_number <= len(modes)): - return None - return modes[mode_number - 1] - - try: - mode_number = int(mode) - except ValueError: - raise Exception('Bond mode must be a number.') - - options.append( - otypes.Option( - name='mode', - type=get_type_name(mode_number), - value=str(mode_number) - ) - ) - - opts_dict = DEFAULT_MODE_OPTS.get(str(mode), {}) - if usr_opts is not None: - opts_dict.update(**usr_opts) - - options.extend( - [otypes.Option(name=opt, value=str(value)) - for opt, value in six.iteritems(opts_dict)] - ) - return options - - -class HostNetworksModule(BaseModule): - - def __compare_options(self, new_options, old_options): - return sorted((get_dict_of_struct(opt) for opt in new_options), - key=lambda x: x["name"]) != sorted((get_dict_of_struct(opt) for opt in old_options), - key=lambda x: x["name"]) - - def build_entity(self): - return otypes.Host() - - def update_custom_properties(self, attachments_service, attachment, network): - if network.get('custom_properties'): - current = [] - if attachment.properties: - current = [(cp.name, str(cp.value)) for cp in attachment.properties] - passed = [(cp.get('name'), str(cp.get('value'))) for cp in network.get('custom_properties') if cp] - if sorted(current) != sorted(passed): - attachment.properties = [ - otypes.Property( - name=prop.get('name'), - value=prop.get('value') - ) for prop in network.get('custom_properties') - ] - if not self._module.check_mode: - attachments_service.service(attachment.id).update(attachment) - self.changed = True - - def update_address(self, attachments_service, attachment, network): - # Check if there is any change in address assignments and - # update it if needed: - for ip in attachment.ip_address_assignments: - if str(ip.ip.version) == network.get('version', 'v4'): - changed = False - if not equal(network.get('boot_protocol'), str(ip.assignment_method)): - ip.assignment_method = otypes.BootProtocol(network.get('boot_protocol')) - changed = True - if not equal(network.get('address'), ip.ip.address): - ip.ip.address = network.get('address') - changed = True - if not equal(network.get('gateway'), ip.ip.gateway): - ip.ip.gateway = network.get('gateway') - changed = True - if not equal(network.get('netmask'), ip.ip.netmask): - ip.ip.netmask = network.get('netmask') - changed = True - - if changed: - if not self._module.check_mode: - attachments_service.service(attachment.id).update(attachment) - self.changed = True - break - - def has_update(self, nic_service): - update = False - bond = self._module.params['bond'] - networks = self._module.params['networks'] - labels = self._module.params['labels'] - nic = get_entity(nic_service) - - if nic is None: - return update - - # Check if bond configuration should be updated: - if bond: - update = self.__compare_options(get_bond_options(bond.get('mode'), bond.get('options')), getattr(nic.bonding, 'options', [])) - update = update or not equal( - sorted(bond.get('interfaces')) if bond.get('interfaces') else None, - sorted(get_link_name(self._connection, s) for s in nic.bonding.slaves) - ) - - # Check if labels need to be updated on interface/bond: - if labels: - net_labels = nic_service.network_labels_service().list() - # If any labels which user passed aren't assigned, relabel the interface: - if sorted(labels) != sorted([lbl.id for lbl in net_labels]): - return True - - if not networks: - return update - - # Check if networks attachments configuration should be updated: - attachments_service = nic_service.network_attachments_service() - network_names = [network.get('name') for network in networks] - - attachments = {} - for attachment in attachments_service.list(): - name = get_link_name(self._connection, attachment.network) - if name in network_names: - attachments[name] = attachment - - for network in networks: - attachment = attachments.get(network.get('name')) - # If attachment don't exists, we need to create it: - if attachment is None: - return True - self.update_custom_properties(attachments_service, attachment, network) - self.update_address(attachments_service, attachment, network) - - return update - - def _action_save_configuration(self, entity): - if not self._module.check_mode: - self._service.service(entity.id).commit_net_config() - self.changed = True - - -def needs_sync(nics_service): - nics = nics_service.list() - for nic in nics: - nic_service = nics_service.nic_service(nic.id) - for network_attachment_service in nic_service.network_attachments_service().list(): - if not network_attachment_service.in_sync: - return True - return False - - -def main(): - argument_spec = ovirt_full_argument_spec( - state=dict( - choices=['present', 'absent'], - default='present', - ), - name=dict(aliases=['host'], required=True), - bond=dict(default=None, type='dict'), - interface=dict(default=None), - networks=dict(default=None, type='list'), - labels=dict(default=None, type='list'), - check=dict(default=None, type='bool'), - save=dict(default=True, type='bool'), - sync_networks=dict(default=False, type='bool'), - ) - module = AnsibleModule(argument_spec=argument_spec) - - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - hosts_service = connection.system_service().hosts_service() - host_networks_module = HostNetworksModule( - connection=connection, - module=module, - service=hosts_service, - ) - - host = host_networks_module.search_entity() - if host is None: - raise Exception("Host '%s' was not found." % module.params['name']) - - bond = module.params['bond'] - interface = module.params['interface'] - networks = module.params['networks'] - labels = module.params['labels'] - nic_name = bond.get('name') if bond else module.params['interface'] - - host_service = hosts_service.host_service(host.id) - nics_service = host_service.nics_service() - nic = search_by_name(nics_service, nic_name) - - if module.params["sync_networks"]: - if needs_sync(nics_service): - if not module.check_mode: - host_service.sync_all_networks() - host_networks_module.changed = True - - network_names = [network['name'] for network in networks or []] - state = module.params['state'] - - if ( - state == 'present' and - (nic is None or host_networks_module.has_update(nics_service.service(nic.id))) - ): - # Remove networks which are attached to different interface then user want: - attachments_service = host_service.network_attachments_service() - - # Append attachment ID to network if needs update: - for a in attachments_service.list(): - current_network_name = get_link_name(connection, a.network) - if current_network_name in network_names: - for n in networks: - if n['name'] == current_network_name: - n['id'] = a.id - - # Check if we have to break some bonds: - removed_bonds = [] - if nic is not None: - for host_nic in nics_service.list(): - if host_nic.bonding and nic.id in [slave.id for slave in host_nic.bonding.slaves]: - removed_bonds.append(otypes.HostNic(id=host_nic.id)) - - # Assign the networks: - setup_params = dict( - entity=host, - action='setup_networks', - check_connectivity=module.params['check'], - removed_bonds=removed_bonds if removed_bonds else None, - modified_bonds=[ - otypes.HostNic( - name=bond.get('name'), - bonding=otypes.Bonding( - options=get_bond_options(bond.get('mode'), bond.get('options')), - slaves=[ - otypes.HostNic(name=i) for i in bond.get('interfaces', []) - ], - ), - ), - ] if bond else None, - modified_labels=[ - otypes.NetworkLabel( - id=str(name), - host_nic=otypes.HostNic( - name=bond.get('name') if bond else interface - ), - ) for name in labels - ] if labels else None, - modified_network_attachments=[ - otypes.NetworkAttachment( - id=network.get('id'), - network=otypes.Network( - name=network['name'] - ) if network['name'] else None, - host_nic=otypes.HostNic( - name=bond.get('name') if bond else interface - ), - ip_address_assignments=[ - otypes.IpAddressAssignment( - assignment_method=otypes.BootProtocol( - network.get('boot_protocol', 'none') - ), - ip=otypes.Ip( - address=network.get('address'), - gateway=network.get('gateway'), - netmask=network.get('netmask'), - version=otypes.IpVersion( - network.get('version') - ) if network.get('version') else None, - ), - ), - ], - properties=[ - otypes.Property( - name=prop.get('name'), - value=prop.get('value') - ) for prop in network.get('custom_properties') - ] - ) for network in networks - ] if networks else None, - ) - if engine_supported(connection, '4.3'): - setup_params['commit_on_success'] = module.params['save'] - elif module.params['save']: - setup_params['post_action'] = host_networks_module._action_save_configuration - host_networks_module.action(**setup_params) - elif state == 'absent' and nic: - attachments = [] - nic_service = nics_service.nic_service(nic.id) - - attached_labels = set([str(lbl.id) for lbl in nic_service.network_labels_service().list()]) - if networks: - attachments_service = nic_service.network_attachments_service() - attachments = attachments_service.list() - attachments = [ - attachment for attachment in attachments - if get_link_name(connection, attachment.network) in network_names - ] - - # Remove unmanaged networks: - unmanaged_networks_service = host_service.unmanaged_networks_service() - unmanaged_networks = [(u.id, u.name) for u in unmanaged_networks_service.list()] - for net_id, net_name in unmanaged_networks: - if net_name in network_names: - if not module.check_mode: - unmanaged_networks_service.unmanaged_network_service(net_id).remove() - host_networks_module.changed = True - - # Need to check if there are any labels to be removed, as backend fail - # if we try to send remove non existing label, for bond and attachments it's OK: - if (labels and set(labels).intersection(attached_labels)) or bond or attachments: - setup_params = dict( - entity=host, - action='setup_networks', - check_connectivity=module.params['check'], - removed_bonds=[ - otypes.HostNic( - name=bond.get('name'), - ), - ] if bond else None, - removed_labels=[ - otypes.NetworkLabel(id=str(name)) for name in labels - ] if labels else None, - removed_network_attachments=attachments if attachments else None, - ) - if engine_supported(connection, '4.3'): - setup_params['commit_on_success'] = module.params['save'] - elif module.params['save']: - setup_params['post_action'] = host_networks_module._action_save_configuration - host_networks_module.action(**setup_params) - - nic = search_by_name(nics_service, nic_name) - module.exit_json(**{ - 'changed': host_networks_module.changed, - 'id': nic.id if nic else None, - 'host_nic': get_dict_of_struct(nic), - }) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_host_pm.py b/lib/ansible/modules/cloud/ovirt/ovirt_host_pm.py deleted file mode 100644 index aab2c9f922..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_host_pm.py +++ /dev/null @@ -1,261 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (c) 2016 Red Hat, Inc. -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_host_pm -short_description: Module to manage power management of hosts in oVirt/RHV -version_added: "2.3" -author: "Ondra Machacek (@machacekondra)" -description: - - "Module to manage power management of hosts in oVirt/RHV." -options: - name: - description: - - "Name of the host to manage." - required: true - aliases: ['host'] - state: - description: - - "Should the host be present/absent." - choices: ['present', 'absent'] - default: present - address: - description: - - "Address of the power management interface." - username: - description: - - "Username to be used to connect to power management interface." - password: - description: - - "Password of the user specified in C(username) parameter." - type: - description: - - "Type of the power management. oVirt/RHV predefined values are I(drac5), I(ipmilan), I(rsa), - I(bladecenter), I(alom), I(apc), I(apc_snmp), I(eps), I(wti), I(rsb), I(cisco_ucs), - I(drac7), I(hpblade), I(ilo), I(ilo2), I(ilo3), I(ilo4), I(ilo_ssh), - but user can have defined custom type." - port: - description: - - "Power management interface port." - options: - description: - - "Dictionary of additional fence agent options (including Power Management slot)." - - "Additional information about options can be found at U(https://github.com/ClusterLabs/fence-agents/blob/master/doc/FenceAgentAPI.md)." - encrypt_options: - description: - - "If I(true) options will be encrypted when send to agent." - aliases: ['encrypt'] - type: bool - order: - description: - - "Integer value specifying, by default it's added at the end." - version_added: "2.5" -extends_documentation_fragment: ovirt -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Add fence agent to host 'myhost' -- ovirt_host_pm: - name: myhost - address: 1.2.3.4 - options: - myoption1: x - myoption2: y - username: admin - password: admin - port: 3333 - type: ipmilan - -# Add fence agent to host 'myhost' using 'slot' option -- ovirt_host_pm: - name: myhost - address: 1.2.3.4 - options: - myoption1: x - myoption2: y - slot: myslot - username: admin - password: admin - port: 3333 - type: ipmilan - - -# Remove ipmilan fence agent with address 1.2.3.4 on host 'myhost' -- ovirt_host_pm: - state: absent - name: myhost - address: 1.2.3.4 - type: ipmilan -''' - -RETURN = ''' -id: - description: ID of the agent which is managed - returned: On success if agent is found. - type: str - sample: 7de90f31-222c-436c-a1ca-7e655bd5b60c -agent: - description: "Dictionary of all the agent attributes. Agent attributes can be found on your oVirt/RHV instance - at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/agent." - returned: On success if agent is found. - type: dict -''' - -import traceback - -try: - import ovirtsdk4.types as otypes -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - BaseModule, - check_sdk, - create_connection, - equal, - ovirt_full_argument_spec, - search_by_name, -) - - -class HostModule(BaseModule): - def build_entity(self): - return otypes.Host( - power_management=otypes.PowerManagement( - enabled=True, - ), - ) - - def update_check(self, entity): - return equal(True, entity.power_management.enabled) - - -class HostPmModule(BaseModule): - - def pre_create(self, entity): - # Save the entity, so we know if Agent already existed - self.entity = entity - - def build_entity(self): - last = next((s for s in sorted([a.order for a in self._service.list()])), 0) - order = self.param('order') if self.param('order') is not None else self.entity.order if self.entity else last + 1 - return otypes.Agent( - address=self._module.params['address'], - encrypt_options=self._module.params['encrypt_options'], - options=[ - otypes.Option( - name=name, - value=value, - ) for name, value in self._module.params['options'].items() - ] if self._module.params['options'] else None, - password=self._module.params['password'], - port=self._module.params['port'], - type=self._module.params['type'], - username=self._module.params['username'], - order=order, - ) - - def update_check(self, entity): - def check_options(): - if self.param('options'): - current = [] - if entity.options: - current = [(opt.name, str(opt.value)) for opt in entity.options] - passed = [(k, str(v)) for k, v in self.param('options').items()] - return sorted(current) == sorted(passed) - return True - - return ( - check_options() and - equal(self._module.params.get('address'), entity.address) and - equal(self._module.params.get('encrypt_options'), entity.encrypt_options) and - equal(self._module.params.get('username'), entity.username) and - equal(self._module.params.get('port'), entity.port) and - equal(self._module.params.get('type'), entity.type) and - equal(self._module.params.get('order'), entity.order) - ) - - -def main(): - argument_spec = ovirt_full_argument_spec( - state=dict( - choices=['present', 'absent'], - default='present', - ), - name=dict(default=None, required=True, aliases=['host']), - address=dict(default=None), - username=dict(default=None), - password=dict(default=None, no_log=True), - type=dict(default=None), - port=dict(default=None, type='int'), - order=dict(default=None, type='int'), - options=dict(default=None, type='dict'), - encrypt_options=dict(default=None, type='bool', aliases=['encrypt']), - ) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - ) - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - hosts_service = connection.system_service().hosts_service() - host = search_by_name(hosts_service, module.params['name']) - fence_agents_service = hosts_service.host_service(host.id).fence_agents_service() - - host_pm_module = HostPmModule( - connection=connection, - module=module, - service=fence_agents_service, - ) - host_module = HostModule( - connection=connection, - module=module, - service=hosts_service, - ) - - state = module.params['state'] - if state == 'present': - agent = host_pm_module.search_entity( - search_params={ - 'address': module.params['address'], - 'type': module.params['type'], - } - ) - ret = host_pm_module.create(entity=agent) - - # Enable Power Management, if it's not enabled: - host_module.create(entity=host) - elif state == 'absent': - agent = host_pm_module.search_entity( - search_params={ - 'address': module.params['address'], - 'type': module.params['type'], - } - ) - ret = host_pm_module.remove(entity=agent) - - module.exit_json(**ret) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_host_storage_info.py b/lib/ansible/modules/cloud/ovirt/ovirt_host_storage_info.py deleted file mode 100644 index 7eecafb4b1..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_host_storage_info.py +++ /dev/null @@ -1,182 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (c) 2017 Red Hat, Inc. -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - -DOCUMENTATION = ''' ---- -module: ovirt_host_storage_info -short_description: Retrieve information about one or more oVirt/RHV HostStorages (applicable only for block storage) -author: "Daniel Erez (@derez)" -version_added: "2.4" -description: - - "Retrieve information about one or more oVirt/RHV HostStorages (applicable only for block storage)." - - This module was called C(ovirt_host_storage_facts) before Ansible 2.9, returning C(ansible_facts). - Note that the M(ovirt_host_storage_info) module no longer returns C(ansible_facts)! -options: - host: - description: - - "Host to get device list from." - required: true - iscsi: - description: - - "Dictionary with values for iSCSI storage type:" - suboptions: - address: - description: - - "Address of the iSCSI storage server." - target: - description: - - "The target IQN for the storage device." - username: - description: - - "A CHAP user name for logging into a target." - password: - description: - - "A CHAP password for logging into a target." - portal: - description: - - "The portal being used to connect with iscsi." - version_added: 2.10 - fcp: - description: - - "Dictionary with values for fibre channel storage type:" - suboptions: - address: - description: - - "Address of the fibre channel storage server." - port: - description: - - "Port of the fibre channel storage server." - lun_id: - description: - - "LUN id." -extends_documentation_fragment: ovirt_info -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Gather information about HostStorages with specified target and address: -- ovirt_host_storage_info: - host: myhost - iscsi: - target: iqn.2016-08-09.domain-01:nickname - address: 10.34.63.204 - register: result -- debug: - msg: "{{ result.ovirt_host_storages }}" -''' - -RETURN = ''' -ovirt_host_storages: - description: "List of dictionaries describing the HostStorage. HostStorage attributes are mapped to dictionary keys, - all HostStorage attributes can be found at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/host_storage." - returned: On success. - type: list -''' - -import traceback - -try: - import ovirtsdk4.types as otypes -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - check_sdk, - create_connection, - get_dict_of_struct, - ovirt_info_full_argument_spec, - get_id_by_name, -) - - -def _login(host_service, iscsi): - host_service.iscsi_login( - iscsi=otypes.IscsiDetails( - username=iscsi.get('username'), - password=iscsi.get('password'), - address=iscsi.get('address'), - target=iscsi.get('target'), - portal=iscsi.get('portal') - ), - ) - - -def _get_storage_type(params): - for sd_type in ['iscsi', 'fcp']: - if params.get(sd_type) is not None: - return sd_type - - -def main(): - argument_spec = ovirt_info_full_argument_spec( - host=dict(required=True), - iscsi=dict(default=None, type='dict'), - fcp=dict(default=None, type='dict'), - ) - module = AnsibleModule(argument_spec) - is_old_facts = module._name == 'ovirt_host_storage_facts' - if is_old_facts: - module.deprecate("The 'ovirt_host_storage_facts' module has been renamed to 'ovirt_host_storage_info', " - "and the renamed one no longer returns ansible_facts", version='2.13') - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - - # Get Host - hosts_service = connection.system_service().hosts_service() - host_id = get_id_by_name(hosts_service, module.params['host']) - storage_type = _get_storage_type(module.params) - host_service = hosts_service.host_service(host_id) - - if storage_type == 'iscsi': - # Login - iscsi = module.params.get('iscsi') - _login(host_service, iscsi) - - # Get LUNs exposed from the specified target - host_storages = host_service.storage_service().list() - - if storage_type == 'iscsi': - filterred_host_storages = [host_storage for host_storage in host_storages - if host_storage.type == otypes.StorageType.ISCSI] - if 'target' in iscsi: - filterred_host_storages = [host_storage for host_storage in filterred_host_storages - if iscsi.get('target') == host_storage.logical_units[0].target] - elif storage_type == 'fcp': - filterred_host_storages = [host_storage for host_storage in host_storages - if host_storage.type == otypes.StorageType.FCP] - - result = dict( - ovirt_host_storages=[ - get_dict_of_struct( - struct=c, - connection=connection, - fetch_nested=module.params.get('fetch_nested'), - attributes=module.params.get('nested_attributes'), - ) for c in filterred_host_storages - ], - ) - if is_old_facts: - module.exit_json(changed=False, ansible_facts=result) - else: - module.exit_json(changed=False, **result) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_instance_type.py b/lib/ansible/modules/cloud/ovirt/ovirt_instance_type.py deleted file mode 100644 index 63e0471c17..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_instance_type.py +++ /dev/null @@ -1,592 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2017, Ansible Project -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - -DOCUMENTATION = ''' ---- -module: ovirt_instance_type -short_description: Module to manage Instance Types in oVirt/RHV -version_added: "2.8" -author: -- Martin Necas (@mnecas) -- Ondra Machacek (@machacekondra) -description: - - This module manages whole lifecycle of the Instance Type in oVirt/RHV. -options: - name: - description: - - Name of the Instance Type to manage. - - If instance type don't exists C(name) is required. Otherwise C(id) or C(name) can be used. - id: - description: - - ID of the Instance Type to manage. - state: - description: - - Should the Instance Type be present/absent. - - I(present) state will create/update instance type and don't change its state if it already exists. - choices: [ absent, present ] - default: present - memory: - description: - - Amount of memory of the Instance Type. Prefix uses IEC 60027-2 standard (for example 1GiB, 1024MiB). - - Default value is set by engine. - memory_guaranteed: - description: - - Amount of minimal guaranteed memory of the Instance Type. - Prefix uses IEC 60027-2 standard (for example 1GiB, 1024MiB). - - C(memory_guaranteed) parameter can't be lower than C(memory) parameter. - - Default value is set by engine. - nics: - description: - - List of NICs, which should be attached to Virtual Machine. NIC is described by following dictionary. - - C(name) - Name of the NIC. - - C(profile_name) - Profile name where NIC should be attached. - - C(interface) - Type of the network interface. One of following I(virtio), I(e1000), I(rtl8139), default is I(virtio). - - C(mac_address) - Custom MAC address of the network interface, by default it's obtained from MAC pool. - - NOTE - This parameter is used only when C(state) is I(running) or I(present) and is able to only create NICs. - To manage NICs of the instance type in more depth please use M(ovirt_nic) module instead. - memory_max: - description: - - Upper bound of instance type memory up to which memory hot-plug can be performed. - Prefix uses IEC 60027-2 standard (for example 1GiB, 1024MiB). - - Default value is set by engine. - cpu_cores: - description: - - Number of virtual CPUs cores of the Instance Type. - - Default value is set by oVirt/RHV engine. - cpu_sockets: - description: - - Number of virtual CPUs sockets of the Instance Type. - - Default value is set by oVirt/RHV engine. - cpu_threads: - description: - - Number of virtual CPUs sockets of the Instance Type. - - Default value is set by oVirt/RHV engine. - operating_system: - description: - - Operating system of the Instance Type. - - Default value is set by oVirt/RHV engine. - - "Possible values: debian_7, freebsd, freebsdx64, other, other_linux, - other_linux_ppc64, other_ppc64, rhel_3, rhel_4, rhel_4x64, rhel_5, rhel_5x64, - rhel_6, rhel_6x64, rhel_6_ppc64, rhel_7x64, rhel_7_ppc64, sles_11, sles_11_ppc64, - ubuntu_12_04, ubuntu_12_10, ubuntu_13_04, ubuntu_13_10, ubuntu_14_04, ubuntu_14_04_ppc64, - windows_10, windows_10x64, windows_2003, windows_2003x64, windows_2008, windows_2008x64, - windows_2008r2x64, windows_2008R2x64, windows_2012x64, windows_2012R2x64, windows_7, - windows_7x64, windows_8, windows_8x64, windows_xp" - boot_devices: - description: - - List of boot devices which should be used to boot. For example C([ cdrom, hd ]). - - Default value is set by oVirt/RHV engine. - choices: [ cdrom, hd, network ] - serial_console: - description: - - "I(True) enable VirtIO serial console, I(False) to disable it. By default is chosen by oVirt/RHV engine." - type: bool - usb_support: - description: - - "I(True) enable USB support, I(False) to disable it. By default is chosen by oVirt/RHV engine." - type: bool - high_availability: - description: - - If I(yes) Instance Type will be set as highly available. - - If I(no) Instance Type won't be set as highly available. - - If no value is passed, default value is set by oVirt/RHV engine. - type: bool - high_availability_priority: - description: - - Indicates the priority of the instance type inside the run and migration queues. - Instance Type with higher priorities will be started and migrated before instance types with lower - priorities. The value is an integer between 0 and 100. The higher the value, the higher the priority. - - If no value is passed, default value is set by oVirt/RHV engine. - watchdog: - description: - - "Assign watchdog device for the instance type." - - "Watchdogs is a dictionary which can have following values:" - - "C(model) - Model of the watchdog device. For example: I(i6300esb), I(diag288) or I(null)." - - "C(action) - Watchdog action to be performed when watchdog is triggered. For example: I(none), I(reset), I(poweroff), I(pause) or I(dump)." - host: - description: - - Specify host where Instance Type should be running. By default the host is chosen by engine scheduler. - - This parameter is used only when C(state) is I(running) or I(present). - graphical_console: - description: - - "Assign graphical console to the instance type." - - "Graphical console is a dictionary which can have following values:" - - "C(headless_mode) - If I(true) disable the graphics console for this instance type." - - "C(protocol) - Graphical protocol, a list of I(spice), I(vnc), or both." - description: - description: - - "Description of the instance type." - cpu_mode: - description: - - "CPU mode of the instance type. It can be some of the following: I(host_passthrough), I(host_model) or I(custom)." - - "For I(host_passthrough) CPU type you need to set C(placement_policy) to I(pinned)." - - "If no value is passed, default value is set by oVirt/RHV engine." - rng_device: - description: - - "Random number generator (RNG). You can choose of one the following devices I(urandom), I(random) or I(hwrng)." - - "In order to select I(hwrng), you must have it enabled on cluster first." - - "/dev/urandom is used for cluster version >= 4.1, and /dev/random for cluster version <= 4.0" - rng_bytes: - description: - - "Number of bytes allowed to consume per period." - rng_period: - description: - - "Duration of one period in milliseconds." - placement_policy: - description: - - "The configuration of the instance type's placement policy." - - "Placement policy can be one of the following values:" - - "C(migratable) - Allow manual and automatic migration." - - "C(pinned) - Do not allow migration." - - "C(user_migratable) - Allow manual migration only." - - "If no value is passed, default value is set by oVirt/RHV engine." - cpu_pinning: - description: - - "CPU Pinning topology to map instance type CPU to host CPU." - - "CPU Pinning topology is a list of dictionary which can have following values:" - - "C(cpu) - Number of the host CPU." - - "C(vcpu) - Number of the instance type CPU." - soundcard_enabled: - description: - - "If I(true), the sound card is added to the instance type." - type: bool - smartcard_enabled: - description: - - "If I(true), use smart card authentication." - type: bool - virtio_scsi: - description: - - "If I(true), virtio scsi will be enabled." - type: bool - io_threads: - description: - - "Number of IO threads used by instance type. I(0) means IO threading disabled." - ballooning_enabled: - description: - - "If I(true), use memory ballooning." - - "Memory balloon is a guest device, which may be used to re-distribute / reclaim the host memory - based on instance type needs in a dynamic way. In this way it's possible to create memory over commitment states." - type: bool -extends_documentation_fragment: ovirt -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Create instance type -- name: Create instance type - ovirt_instance_type: - state: present - name: myit - rng_device: hwrng - rng_bytes: 200 - rng_period: 200 - soundcard_enabled: true - virtio_scsi: true - boot_devices: - - network - -# Remove instance type -- ovirt_instance_type: - state: absent - name: myit - - -# Create instance type with predefined memory and cpu limits. -- ovirt_instance_type: - state: present - name: myit - memory: 2GiB - cpu_cores: 2 - cpu_sockets: 2 - nics: - - name: nic1 - -# Enable usb support and serial console -- ovirt_instance_type: - name: myit - usb_support: True - serial_console: True - -# Use graphical console with spice and vnc -- name: Create a instance type that has the console configured for both Spice and VNC - ovirt_instance_type: - name: myit - graphical_console: - protocol: - - spice - - vnc -''' - - -RETURN = ''' - -id: - description: ID of the instance type which is managed - returned: On success if instance type is found. - type: str - sample: 7de90f31-222c-436c-a1ca-7e655bd5b60c -instancetype: - description: "Dictionary of all the instance type attributes. instance type attributes can be found on your oVirt/RHV instance - at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/instance_type." - returned: On success if instance type is found. - type: dict -''' - -from ansible.module_utils.basic import AnsibleModule -import traceback - -from ansible.module_utils.ovirt import ( - BaseModule, - check_params, - check_sdk, - convert_to_bytes, - create_connection, - equal, - get_dict_of_struct, - get_entity, - get_link_name, - get_id_by_name, - ovirt_full_argument_spec, - search_by_attributes, - search_by_name, - wait, -) - -try: - import ovirtsdk4.types as otypes -except ImportError: - pass - - -class InstanceTypeModule(BaseModule): - def build_entity(self): - return otypes.InstanceType( - id=self.param('id'), - name=self.param('name'), - console=( - otypes.Console(enabled=self.param('serial_console')) - ) if self.param('serial_console') is not None else None, - usb=( - otypes.Usb(enabled=self.param('usb_support')) - ) if self.param('usb_support') is not None else None, - high_availability=otypes.HighAvailability( - enabled=self.param('high_availability'), - priority=self.param('high_availability_priority'), - ) if self.param('high_availability') is not None or self.param('high_availability_priority') else None, - cpu=otypes.Cpu( - topology=otypes.CpuTopology( - cores=self.param('cpu_cores'), - sockets=self.param('cpu_sockets'), - threads=self.param('cpu_threads'), - ) if any(( - self.param('cpu_cores'), - self.param('cpu_sockets'), - self.param('cpu_threads') - )) else None, - cpu_tune=otypes.CpuTune( - vcpu_pins=[ - otypes.VcpuPin(vcpu=int(pin['vcpu']), cpu_set=str(pin['cpu'])) for pin in self.param('cpu_pinning') - ], - ) if self.param('cpu_pinning') else None, - mode=otypes.CpuMode(self.param('cpu_mode')) if self.param( - 'cpu_mode') else None, - ) if any(( - self.param('cpu_cores'), - self.param('cpu_sockets'), - self.param('cpu_threads'), - self.param('cpu_mode'), - self.param('cpu_pinning') - )) else None, - os=otypes.OperatingSystem( - type=self.param('operating_system'), - boot=otypes.Boot( - devices=[ - otypes.BootDevice(dev) for dev in self.param('boot_devices') - ], - ) if self.param('boot_devices') else None - ), - rng_device=otypes.RngDevice( - source=otypes.RngSource(self.param('rng_device')), - rate=otypes.Rate( - bytes=self.param('rng_bytes'), - period=self.param('rng_period') - ) - ) if self.param('rng_device') else None, - memory=convert_to_bytes( - self.param('memory') - ) if self.param('memory') else None, - virtio_scsi=otypes.VirtioScsi( - enabled=self.param('virtio_scsi') - ) if self.param('virtio_scsi') else None, - memory_policy=otypes.MemoryPolicy( - guaranteed=convert_to_bytes(self.param('memory_guaranteed')), - ballooning=self.param('ballooning_enabled'), - max=convert_to_bytes(self.param('memory_max')), - ) if any(( - self.param('memory_guaranteed'), - self.param('ballooning_enabled') is not None, - self.param('memory_max') - )) else None, - description=self.param('description'), - placement_policy=otypes.VmPlacementPolicy( - affinity=otypes.VmAffinity(self.param('placement_policy')), - hosts=[ - otypes.Host(name=self.param('host')), - ] if self.param('host') else None, - ) if self.param('placement_policy') else None, - soundcard_enabled=self.param('soundcard_enabled'), - display=otypes.Display( - smartcard_enabled=self.param('smartcard_enabled') - ) if self.param('smartcard_enabled') is not None else None, - io=otypes.Io( - threads=self.param('io_threads'), - ) if self.param('io_threads') is not None else None, - ) - - def __attach_watchdog(self, entity): - watchdogs_service = self._service.service(entity.id).watchdogs_service() - watchdog = self.param('watchdog') - if watchdog is not None: - current_watchdog = next(iter(watchdogs_service.list()), None) - if watchdog.get('model') is None and current_watchdog: - watchdogs_service.watchdog_service(current_watchdog.id).remove() - return True - elif watchdog.get('model') is not None and current_watchdog is None: - watchdogs_service.add( - otypes.Watchdog( - model=otypes.WatchdogModel(watchdog.get('model').lower()), - action=otypes.WatchdogAction(watchdog.get('action')), - ) - ) - return True - elif current_watchdog is not None: - if ( - str(current_watchdog.model).lower() != watchdog.get('model').lower() or - str(current_watchdog.action).lower() != watchdog.get('action').lower() - ): - watchdogs_service.watchdog_service(current_watchdog.id).update( - otypes.Watchdog( - model=otypes.WatchdogModel(watchdog.get('model')), - action=otypes.WatchdogAction(watchdog.get('action')), - ) - ) - return True - return False - - def __get_vnic_profile_id(self, nic): - """ - Return VNIC profile ID looked up by it's name, because there can be - more VNIC profiles with same name, other criteria of filter is cluster. - """ - vnics_service = self._connection.system_service().vnic_profiles_service() - clusters_service = self._connection.system_service().clusters_service() - cluster = search_by_name(clusters_service, self.param('cluster')) - profiles = [ - profile for profile in vnics_service.list() - if profile.name == nic.get('profile_name') - ] - cluster_networks = [ - net.id for net in self._connection.follow_link(cluster.networks) - ] - try: - return next( - profile.id for profile in profiles - if profile.network.id in cluster_networks - ) - except StopIteration: - raise Exception( - "Profile '%s' was not found in cluster '%s'" % ( - nic.get('profile_name'), - self.param('cluster') - ) - ) - - def __attach_nics(self, entity): - # Attach NICs to instance type, if specified: - nics_service = self._service.service(entity.id).nics_service() - for nic in self.param('nics'): - if search_by_name(nics_service, nic.get('name')) is None: - if not self._module.check_mode: - nics_service.add( - otypes.Nic( - name=nic.get('name'), - interface=otypes.NicInterface( - nic.get('interface', 'virtio') - ), - vnic_profile=otypes.VnicProfile( - id=self.__get_vnic_profile_id(nic), - ) if nic.get('profile_name') else None, - mac=otypes.Mac( - address=nic.get('mac_address') - ) if nic.get('mac_address') else None, - ) - ) - self.changed = True - - def __attach_graphical_console(self, entity): - graphical_console = self.param('graphical_console') - if not graphical_console: - return False - - it_service = self._service.instance_type_service(entity.id) - gcs_service = it_service.graphics_consoles_service() - graphical_consoles = gcs_service.list() - # Remove all graphical consoles if there are any: - if bool(graphical_console.get('headless_mode')): - if not self._module.check_mode: - for gc in graphical_consoles: - gcs_service.console_service(gc.id).remove() - return len(graphical_consoles) > 0 - - # If there are not gc add any gc to be added: - protocol = graphical_console.get('protocol') - if isinstance(protocol, str): - protocol = [protocol] - - current_protocols = [str(gc.protocol) for gc in graphical_consoles] - if not current_protocols: - if not self._module.check_mode: - for p in protocol: - gcs_service.add( - otypes.GraphicsConsole( - protocol=otypes.GraphicsType(p), - ) - ) - return True - - # Update consoles: - if sorted(protocol) != sorted(current_protocols): - if not self._module.check_mode: - for gc in graphical_consoles: - gcs_service.console_service(gc.id).remove() - for p in protocol: - gcs_service.add( - otypes.GraphicsConsole( - protocol=otypes.GraphicsType(p), - ) - ) - return True - - def post_update(self, entity): - self.post_present(entity.id) - - def post_present(self, entity_id): - entity = self._service.service(entity_id).get() - self.changed = self.__attach_nics(entity) - self.changed = self.__attach_watchdog(entity) - self.changed = self.__attach_graphical_console(entity) - - def update_check(self, entity): - cpu_mode = getattr(entity.cpu, 'mode') - it_display = entity.display - return ( - not self.param('kernel_params_persist') and - equal(convert_to_bytes(self.param('memory_guaranteed')), entity.memory_policy.guaranteed) and - equal(convert_to_bytes(self.param('memory_max')), entity.memory_policy.max) and - equal(self.param('cpu_cores'), entity.cpu.topology.cores) and - equal(self.param('cpu_sockets'), entity.cpu.topology.sockets) and - equal(self.param('cpu_threads'), entity.cpu.topology.threads) and - equal(self.param('cpu_mode'), str(cpu_mode) if cpu_mode else None) and - equal(self.param('type'), str(entity.type)) and - equal(self.param('name'), str(entity.name)) and - equal(self.param('operating_system'), str(entity.os.type)) and - equal(self.param('soundcard_enabled'), entity.soundcard_enabled) and - equal(self.param('smartcard_enabled'), getattr(it_display, 'smartcard_enabled', False)) and - equal(self.param('io_threads'), entity.io.threads) and - equal(self.param('ballooning_enabled'), entity.memory_policy.ballooning) and - equal(self.param('serial_console'), getattr(entity.console, 'enabled', None)) and - equal(self.param('usb_support'), entity.usb.enabled) and - equal(self.param('virtio_scsi'), getattr(entity, 'smartcard_enabled', False)) and - equal(self.param('high_availability'), entity.high_availability.enabled) and - equal(self.param('high_availability_priority'), entity.high_availability.priority) and - equal(self.param('boot_devices'), [str(dev) for dev in getattr(entity.os.boot, 'devices', [])]) and - equal(self.param('description'), entity.description) and - equal(self.param('rng_device'), str(entity.rng_device.source) if entity.rng_device else None) and - equal(self.param('rng_bytes'), entity.rng_device.rate.bytes if entity.rng_device else None) and - equal(self.param('rng_period'), entity.rng_device.rate.period if entity.rng_device else None) and - equal(self.param('placement_policy'), str(entity.placement_policy.affinity) if entity.placement_policy else None) - ) - - -def main(): - argument_spec = ovirt_full_argument_spec( - state=dict(type='str', default='present', - choices=['absent', 'present']), - name=dict(type='str'), - id=dict(type='str'), - memory=dict(type='str'), - memory_guaranteed=dict(type='str'), - memory_max=dict(type='str'), - cpu_sockets=dict(type='int'), - cpu_cores=dict(type='int'), - cpu_threads=dict(type='int'), - operating_system=dict(type='str'), - boot_devices=dict(type='list', choices=['cdrom', 'hd', 'network']), - serial_console=dict(type='bool'), - usb_support=dict(type='bool'), - high_availability=dict(type='bool'), - high_availability_priority=dict(type='int'), - watchdog=dict(type='dict'), - host=dict(type='str'), - graphical_console=dict(type='dict'), - description=dict(type='str'), - cpu_mode=dict(type='str'), - rng_device=dict(type='str'), - rng_bytes=dict(type='int', default=None), - rng_period=dict(type='int', default=None), - placement_policy=dict(type='str'), - cpu_pinning=dict(type='list'), - soundcard_enabled=dict(type='bool', default=None), - virtio_scsi=dict(type='bool', default=None), - smartcard_enabled=dict(type='bool', default=None), - io_threads=dict(type='int', default=None), - nics=dict(type='list', default=[]), - ballooning_enabled=dict(type='bool', default=None), - ) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - required_one_of=[['id', 'name']], - ) - - check_sdk(module) - check_params(module) - - try: - state = module.params['state'] - auth = module.params.pop('auth') - connection = create_connection(auth) - its_service = connection.system_service().instance_types_service() - its_module = InstanceTypeModule( - connection=connection, - module=module, - service=its_service, - ) - it = its_module.search_entity() - - if state == 'present': - ret = its_module.create( - entity=it - ) - its_module.post_present(ret['id']) - ret['changed'] = its_module.changed - elif state == 'absent': - ret = its_module.remove() - module.exit_json(**ret) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_job.py b/lib/ansible/modules/cloud/ovirt/ovirt_job.py deleted file mode 100644 index 7b6c595ee3..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_job.py +++ /dev/null @@ -1,236 +0,0 @@ -#!/usr/bin/python -# -*- 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 . -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_job -short_description: Module to manage jobs in oVirt/RHV -version_added: "2.9" -author: "Martin Necas (@mnecas)" -description: - - "This module manage jobs in oVirt/RHV. It can also manage steps of the job." -options: - description: - description: - - "Description of the job." - - "When task with same description has already finished and you rerun taks it will create new job." - required: true - state: - description: - - "Should the job be C(present)/C(absent)/C(failed)." - - "C(started) is alias for C(present). C(finished) is alias for C(absent). Same in the steps." - - "Note when C(finished)/C(failed) it will finish/fail all steps." - choices: ['present', 'absent', 'started', 'finished', 'failed'] - default: present - steps: - description: - - "The steps of the job." - suboptions: - description: - description: - - "Description of the step." - required: true - state: - description: - - "Should the step be present/absent/failed." - - "Note when one step fail whole job will fail" - - "Note when all steps are finished it will finish job." - choices: ['present', 'absent', 'started', 'finished', 'failed'] - default: present - type: list -extends_documentation_fragment: ovirt -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -- name: Create job with two steps - ovirt_job: - description: job_name - steps: - - description: step_name_A - - description: step_name_B - -- name: Finish one step - ovirt_job: - description: job_name - steps: - - description: step_name_A - state: finished - -- name: When you fail one step whole job will stop - ovirt_job: - description: job_name - steps: - - description: step_name_B - state: failed - -- name: Finish all steps - ovirt_job: - description: job_name - state: finished -''' - -RETURN = ''' -id: - description: ID of the job which is managed - returned: On success if job is found. - type: str - sample: 7de90f31-222c-436c-a1ca-7e655bd5b60c -job: - description: "Dictionary of all the job attributes. Job attributes can be found on your oVirt/RHV instance - at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/job." - returned: On success if job is found. - type: dict -''' - -import traceback - -try: - import ovirtsdk4.types as otypes -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - check_sdk, - create_connection, - equal, - get_id_by_name, - ovirt_full_argument_spec, - get_dict_of_struct, -) - - -def build_job(description): - return otypes.Job( - description=description, - status=otypes.JobStatus.STARTED, - external=True, - auto_cleared=True - ) - - -def build_step(description, job_id): - return otypes.Step( - description=description, - type=otypes.StepEnum.UNKNOWN, - job=otypes.Job( - id=job_id - ), - status=otypes.StepStatus.STARTED, - external=True, - ) - - -def attach_steps(module, job_id, jobs_service): - changed = False - steps_service = jobs_service.job_service(job_id).steps_service() - if module.params.get('steps'): - for step in module.params.get('steps'): - step_entity = get_entity(steps_service, step.get('description')) - step_state = step.get('state', 'present') - if step_state in ['present', 'started']: - if step_entity is None: - steps_service.add(build_step(step.get('description'), job_id)) - changed = True - if step_entity is not None and step_entity.status not in [otypes.StepStatus.FINISHED, otypes.StepStatus.FAILED]: - if step_state in ['absent', 'finished']: - steps_service.step_service(step_entity.id).end(succeeded=True) - changed = True - elif step_state == 'failed': - steps_service.step_service(step_entity.id).end(succeeded=False) - changed = True - return changed - - -def get_entity(service, description): - all_entities = service.list() - for entity in all_entities: - if entity.description == description and entity.status not in [otypes.StepStatus.FINISHED, otypes.JobStatus.FINISHED]: - return entity - - -def main(): - argument_spec = ovirt_full_argument_spec( - state=dict( - choices=['present', 'absent', 'started', 'finished', 'failed'], - default='present', - ), - description=dict(default=None), - steps=dict(default=None, type='list'), - ) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=False, - ) - - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - jobs_service = connection.system_service().jobs_service() - - state = module.params['state'] - job = get_entity(jobs_service, module.params['description']) - changed = False - if state in ['present', 'started']: - if job is None or job.status in [otypes.JobStatus.FINISHED, otypes.JobStatus.FAILED]: - job = jobs_service.add(build_job(module.params['description'])) - changed = True - changed = attach_steps(module, job.id, jobs_service) or changed - - if job is not None and job.status not in [otypes.JobStatus.FINISHED, otypes.JobStatus.FAILED]: - if state in ['absent', 'finished']: - jobs_service.job_service(job.id).end(succeeded=True) - changed = True - - elif state == 'failed': - jobs_service.job_service(job.id).end(succeeded=False) - changed = True - - ret = { - 'changed': changed, - 'id': getattr(job, 'id', None), - 'job': get_dict_of_struct( - struct=job, - connection=connection, - fetch_nested=True, - attributes=module.params.get('nested_attributes'), - ), - } - - module.exit_json(**ret) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_mac_pool.py b/lib/ansible/modules/cloud/ovirt/ovirt_mac_pool.py deleted file mode 100644 index 7d9d2dbc09..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_mac_pool.py +++ /dev/null @@ -1,181 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (c) 2016 Red Hat, Inc. -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_mac_pool -short_description: Module to manage MAC pools in oVirt/RHV -version_added: "2.3" -author: "Ondra Machacek (@machacekondra)" -description: - - "This module manage MAC pools in oVirt/RHV." -options: - id: - description: - - "ID of the mac pool to manage." - version_added: "2.8" - name: - description: - - "Name of the MAC pool to manage." - required: true - description: - description: - - "Description of the MAC pool." - state: - description: - - "Should the mac pool be present or absent." - choices: ['present', 'absent'] - default: present - allow_duplicates: - description: - - "If I(true) allow a MAC address to be used multiple times in a pool." - - "Default value is set by oVirt/RHV engine to I(false)." - type: bool - ranges: - description: - - "List of MAC ranges. The from and to should be split by comma." - - "For example: 00:1a:4a:16:01:51,00:1a:4a:16:01:61" -extends_documentation_fragment: ovirt -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Create MAC pool: -- ovirt_mac_pool: - name: mymacpool - allow_duplicates: false - ranges: - - 00:1a:4a:16:01:51,00:1a:4a:16:01:61 - - 00:1a:4a:16:02:51,00:1a:4a:16:02:61 - -# Remove MAC pool: -- ovirt_mac_pool: - state: absent - name: mymacpool - -# Change MAC pool Name -- ovirt_nic: - id: 00000000-0000-0000-0000-000000000000 - name: "new_mac_pool_name" -''' - -RETURN = ''' -id: - description: ID of the MAC pool which is managed - returned: On success if MAC pool is found. - type: str - sample: 7de90f31-222c-436c-a1ca-7e655bd5b60c -template: - description: "Dictionary of all the MAC pool attributes. MAC pool attributes can be found on your oVirt/RHV instance - at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/mac_pool." - returned: On success if MAC pool is found. - type: dict -''' - -import traceback - -try: - import ovirtsdk4.types as otypes -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - BaseModule, - check_sdk, - equal, - create_connection, - ovirt_full_argument_spec, -) - - -class MACPoolModule(BaseModule): - - def build_entity(self): - return otypes.MacPool( - name=self._module.params['name'], - id=self._module.params['id'], - allow_duplicates=self._module.params['allow_duplicates'], - description=self._module.params['description'], - ranges=[ - otypes.Range( - from_=mac_range.split(',')[0], - to=mac_range.split(',')[1], - ) - for mac_range in self._module.params['ranges'] - ] if self._module.params['ranges'] else None, - ) - - def _compare_ranges(self, entity): - if self._module.params['ranges'] is not None: - ranges = sorted([ - '%s,%s' % (mac_range.from_, mac_range.to) - for mac_range in entity.ranges - ]) - return equal(sorted(self._module.params['ranges']), ranges) - - return True - - def update_check(self, entity): - return ( - self._compare_ranges(entity) and - equal(self._module.params['allow_duplicates'], entity.allow_duplicates) and - equal(self._module.params['description'], entity.description) and - equal(self._module.params['name'], entity.name) - ) - - -def main(): - argument_spec = ovirt_full_argument_spec( - state=dict( - choices=['present', 'absent'], - default='present', - ), - name=dict(required=True), - id=dict(default=None), - allow_duplicates=dict(default=None, type='bool'), - description=dict(default=None), - ranges=dict(default=None, type='list'), - ) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - ) - - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - mac_pools_service = connection.system_service().mac_pools_service() - mac_pools_module = MACPoolModule( - connection=connection, - module=module, - service=mac_pools_service, - ) - - state = module.params['state'] - if state == 'present': - ret = mac_pools_module.create() - elif state == 'absent': - ret = mac_pools_module.remove() - - module.exit_json(**ret) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_network.py b/lib/ansible/modules/cloud/ovirt/ovirt_network.py deleted file mode 100644 index ba88c5a798..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_network.py +++ /dev/null @@ -1,360 +0,0 @@ -#!/usr/bin/python -# -*- 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 . -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_network -short_description: Module to manage logical networks in oVirt/RHV -version_added: "2.3" -author: "Ondra Machacek (@machacekondra)" -description: - - "Module to manage logical networks in oVirt/RHV" -options: - id: - description: - - "ID of the network to manage." - version_added: "2.8" - name: - description: - - "Name of the network to manage." - required: true - state: - description: - - "Should the network be present or absent" - choices: ['present', 'absent'] - default: present - data_center: - description: - - "Datacenter name where network reside." - description: - description: - - "Description of the network." - comment: - description: - - "Comment of the network." - vlan_tag: - description: - - "Specify VLAN tag." - external_provider: - description: - - "Name of external network provider." - - "At first it tries to import the network when not found it will create network in external provider." - version_added: 2.8 - vm_network: - description: - - "If I(True) network will be marked as network for VM." - - "VM network carries traffic relevant to the virtual machine." - type: bool - mtu: - description: - - "Maximum transmission unit (MTU) of the network." - clusters: - description: - - "List of dictionaries describing how the network is managed in specific cluster." - suboptions: - name: - description: - - Cluster name. - assigned: - description: - - I(true) if the network should be assigned to cluster. Default is I(true). - type: bool - required: - description: - - I(true) if the network must remain operational for all hosts associated with this network. - type: bool - display: - description: - - I(true) if the network should marked as display network. - type: bool - migration: - description: - - I(true) if the network should marked as migration network. - type: bool - gluster: - description: - - I(true) if the network should marked as gluster network. - type: bool - label: - description: - - "Name of the label to assign to the network." - version_added: "2.5" -extends_documentation_fragment: ovirt -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Create network -- ovirt_network: - data_center: mydatacenter - name: mynetwork - vlan_tag: 1 - vm_network: true - -# Remove network -- ovirt_network: - state: absent - name: mynetwork - -# Change Network Name -- ovirt_network: - id: 00000000-0000-0000-0000-000000000000 - name: "new_network_name" - data_center: mydatacenter - -# Add network from external provider -- ovirt_network: - data_center: mydatacenter - name: mynetwork - external_provider: ovirt-provider-ovn -''' - -RETURN = ''' -id: - description: "ID of the managed network" - returned: "On success if network is found." - type: str - sample: 7de90f31-222c-436c-a1ca-7e655bd5b60c -network: - description: "Dictionary of all the network attributes. Network attributes can be found on your oVirt/RHV instance - at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/network." - returned: "On success if network is found." - type: dict -''' - -import traceback - -try: - import ovirtsdk4.types as otypes -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - BaseModule, - check_sdk, - check_params, - create_connection, - equal, - ovirt_full_argument_spec, - search_by_name, - get_id_by_name, - get_dict_of_struct, - get_entity -) - - -class NetworksModule(BaseModule): - def build_entity(self): - if self.param('external_provider'): - ons_service = self._connection.system_service().openstack_network_providers_service() - on_service = ons_service.provider_service(get_id_by_name(ons_service, self.param('external_provider'))) - return otypes.Network( - name=self._module.params['name'], - comment=self._module.params['comment'], - description=self._module.params['description'], - id=self._module.params['id'], - data_center=otypes.DataCenter( - name=self._module.params['data_center'], - ) if self._module.params['data_center'] else None, - vlan=otypes.Vlan( - self._module.params['vlan_tag'], - ) if self._module.params['vlan_tag'] else None, - usages=[ - otypes.NetworkUsage.VM if self._module.params['vm_network'] else None - ] if self._module.params['vm_network'] is not None else None, - mtu=self._module.params['mtu'], - external_provider=otypes.OpenStackNetworkProvider(id=on_service.get().id) - if self.param('external_provider') else None, - ) - - def post_create(self, entity): - self._update_label_assignments(entity) - - def _update_label_assignments(self, entity): - if self.param('label') is None: - return - - labels_service = self._service.service(entity.id).network_labels_service() - labels = [lbl.id for lbl in labels_service.list()] - if not self.param('label') in labels: - if not self._module.check_mode: - if labels: - labels_service.label_service(labels[0]).remove() - labels_service.add( - label=otypes.NetworkLabel(id=self.param('label')) - ) - self.changed = True - - def update_check(self, entity): - self._update_label_assignments(entity) - return ( - equal(self._module.params.get('comment'), entity.comment) and - equal(self._module.params.get('name'), entity.name) and - equal(self._module.params.get('description'), entity.description) and - equal(self._module.params.get('vlan_tag'), getattr(entity.vlan, 'id', None)) and - equal(self._module.params.get('vm_network'), True if entity.usages else False) and - equal(self._module.params.get('mtu'), entity.mtu) - ) - - -class ClusterNetworksModule(BaseModule): - - def __init__(self, network_id, cluster_network, *args, **kwargs): - super(ClusterNetworksModule, self).__init__(*args, **kwargs) - self._network_id = network_id - self._cluster_network = cluster_network - self._old_usages = [] - self._cluster_network_entity = get_entity(self._service.network_service(network_id)) - if self._cluster_network_entity is not None: - self._old_usages = self._cluster_network_entity.usages - - def build_entity(self): - return otypes.Network( - id=self._network_id, - name=self._module.params['name'], - required=self._cluster_network.get('required'), - display=self._cluster_network.get('display'), - usages=list(set([ - otypes.NetworkUsage(usage) - for usage in ['display', 'gluster', 'migration'] - if self._cluster_network.get(usage, False) - ] + self._old_usages)) - if ( - self._cluster_network.get('display') is not None or - self._cluster_network.get('gluster') is not None or - self._cluster_network.get('migration') is not None - ) else None, - ) - - def update_check(self, entity): - return ( - equal(self._cluster_network.get('required'), entity.required) and - equal(self._cluster_network.get('display'), entity.display) and - all( - x in [ - str(usage) - for usage in getattr(entity, 'usages', []) - # VM + MANAGEMENT is part of root network - if usage != otypes.NetworkUsage.VM and usage != otypes.NetworkUsage.MANAGEMENT - ] - for x in [ - usage - for usage in ['display', 'gluster', 'migration'] - if self._cluster_network.get(usage, False) - ] - ) - ) - - -def main(): - argument_spec = ovirt_full_argument_spec( - state=dict( - choices=['present', 'absent'], - default='present', - ), - data_center=dict(required=True), - id=dict(default=None), - name=dict(required=True), - description=dict(default=None), - comment=dict(default=None), - external_provider=dict(default=None), - vlan_tag=dict(default=None, type='int'), - vm_network=dict(default=None, type='bool'), - mtu=dict(default=None, type='int'), - clusters=dict(default=None, type='list'), - label=dict(default=None), - ) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - ) - - check_sdk(module) - check_params(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - clusters_service = connection.system_service().clusters_service() - networks_service = connection.system_service().networks_service() - networks_module = NetworksModule( - connection=connection, - module=module, - service=networks_service, - ) - state = module.params['state'] - search_params = { - 'name': module.params['name'], - 'datacenter': module.params['data_center'], - } - if state == 'present': - imported = False - if module.params.get('external_provider') and module.params.get('name') not in [net.name for net in networks_service.list()]: - # Try to import network - ons_service = connection.system_service().openstack_network_providers_service() - on_service = ons_service.provider_service(get_id_by_name(ons_service, module.params.get('external_provider'))) - on_networks_service = on_service.networks_service() - if module.params.get('name') in [net.name for net in on_networks_service.list()]: - network_service = on_networks_service.network_service(get_id_by_name(on_networks_service, module.params.get('name'))) - network_service.import_(data_center=otypes.DataCenter(name=module.params.get('data_center'))) - imported = True - - ret = networks_module.create(search_params=search_params) - ret['changed'] = ret['changed'] or imported - # Update clusters networks: - if module.params.get('clusters') is not None: - for param_cluster in module.params.get('clusters'): - cluster = search_by_name(clusters_service, param_cluster.get('name')) - if cluster is None: - raise Exception("Cluster '%s' was not found." % param_cluster.get('name')) - cluster_networks_service = clusters_service.service(cluster.id).networks_service() - cluster_networks_module = ClusterNetworksModule( - network_id=ret['id'], - cluster_network=param_cluster, - connection=connection, - module=module, - service=cluster_networks_service, - ) - if param_cluster.get('assigned', True): - ret = cluster_networks_module.create() - else: - ret = cluster_networks_module.remove() - - elif state == 'absent': - ret = networks_module.remove(search_params=search_params) - - module.exit_json(**ret) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_network_info.py b/lib/ansible/modules/cloud/ovirt/ovirt_network_info.py deleted file mode 100644 index cb65aa26e1..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_network_info.py +++ /dev/null @@ -1,120 +0,0 @@ -#!/usr/bin/python -# -*- 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 . -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_network_info -short_description: Retrieve information about one or more oVirt/RHV networks -author: "Ondra Machacek (@machacekondra)" -version_added: "2.3" -description: - - "Retrieve information about one or more oVirt/RHV networks." - - This module was called C(ovirt_network_facts) before Ansible 2.9, returning C(ansible_facts). - Note that the M(ovirt_network_info) module no longer returns C(ansible_facts)! -notes: - - "This module returns a variable C(ovirt_networks), which - contains a list of networks. You need to register the result with - the I(register) keyword to use it." -options: - pattern: - description: - - "Search term which is accepted by oVirt/RHV search backend." - - "For example to search network starting with string vlan1 use: name=vlan1*" -extends_documentation_fragment: ovirt_info -''' - - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Gather information about all networks which names start with C(vlan1): -- ovirt_network_info: - pattern: name=vlan1* - register: result -- debug: - msg: "{{ result.ovirt_networks }}" -''' - - -RETURN = ''' -ovirt_networks: - description: "List of dictionaries describing the networks. Network attributes are mapped to dictionary keys, - all networks attributes can be found at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/network." - returned: On success. - type: list -''' - -import traceback - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - check_sdk, - create_connection, - get_dict_of_struct, - ovirt_info_full_argument_spec, -) - - -def main(): - argument_spec = ovirt_info_full_argument_spec( - pattern=dict(default='', required=False), - ) - module = AnsibleModule(argument_spec) - is_old_facts = module._name == 'ovirt_network_facts' - if is_old_facts: - module.deprecate("The 'ovirt_network_facts' module has been renamed to 'ovirt_network_info', " - "and the renamed one no longer returns ansible_facts", version='2.13') - - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - networks_service = connection.system_service().networks_service() - networks = networks_service.list(search=module.params['pattern']) - result = dict( - ovirt_networks=[ - get_dict_of_struct( - struct=c, - connection=connection, - fetch_nested=module.params.get('fetch_nested'), - attributes=module.params.get('nested_attributes'), - ) for c in networks - ], - ) - if is_old_facts: - module.exit_json(changed=False, ansible_facts=result) - else: - module.exit_json(changed=False, **result) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_nic.py b/lib/ansible/modules/cloud/ovirt/ovirt_nic.py deleted file mode 100644 index 827009948e..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_nic.py +++ /dev/null @@ -1,318 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2017, Ansible Project -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - -DOCUMENTATION = ''' ---- -module: ovirt_nic -short_description: Module to manage network interfaces of Virtual Machines in oVirt/RHV -version_added: "2.3" -author: -- Ondra Machacek (@machacekondra) -description: - - Module to manage network interfaces of Virtual Machines in oVirt/RHV. -options: - id: - description: - - "ID of the nic to manage." - version_added: "2.8" - name: - description: - - Name of the network interface to manage. - required: true - vm: - description: - - Name of the Virtual Machine to manage. - - You must provide either C(vm) parameter or C(template) parameter. - template: - description: - - Name of the template to manage. - - You must provide either C(vm) parameter or C(template) parameter. - version_added: "2.4" - state: - description: - - Should the Virtual Machine NIC be present/absent/plugged/unplugged. - choices: [ absent, plugged, present, unplugged ] - default: present - network: - description: - - Logical network to which the VM network interface should use, - by default Empty network is used if network is not specified. - profile: - description: - - Virtual network interface profile to be attached to VM network interface. - - When not specified and network has only single profile it will be auto-selected, otherwise you must specify profile. - interface: - description: - - "Type of the network interface. For example e1000, pci_passthrough, rtl8139, rtl8139_virtio, spapr_vlan or virtio." - - "It's required parameter when creating the new NIC." - mac_address: - description: - - Custom MAC address of the network interface, by default it's obtained from MAC pool. - linked: - description: - - Defines if the NIC is linked to the virtual machine. - type: bool - version_added: "2.9" -extends_documentation_fragment: ovirt -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -- name: Add NIC to VM - ovirt_nic: - state: present - vm: myvm - name: mynic - interface: e1000 - mac_address: 00:1a:4a:16:01:56 - profile: ovirtmgmt - network: ovirtmgmt - -- name: Plug NIC to VM - ovirt_nic: - state: plugged - vm: myvm - name: mynic - -- name: Unplug NIC from VM - ovirt_nic: - state: unplugged - linked: false - vm: myvm - name: mynic - -- name: Add NIC to template - ovirt_nic: - auth: "{{ ovirt_auth }}" - state: present - template: my_template - name: nic1 - interface: virtio - profile: ovirtmgmt - network: ovirtmgmt - -- name: Remove NIC from VM - ovirt_nic: - state: absent - vm: myvm - name: mynic - -# Change NIC Name -- ovirt_nic: - id: 00000000-0000-0000-0000-000000000000 - name: "new_nic_name" - vm: myvm -''' - -RETURN = ''' -id: - description: ID of the network interface which is managed - returned: On success if network interface is found. - type: str - sample: 7de90f31-222c-436c-a1ca-7e655bd5b60c -nic: - description: "Dictionary of all the network interface attributes. Network interface attributes can be found on your oVirt/RHV instance - at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/nic." - returned: On success if network interface is found. - type: dict -''' - -try: - import ovirtsdk4.types as otypes -except ImportError: - pass - -import traceback - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - BaseModule, - check_sdk, - create_connection, - equal, - get_link_name, - ovirt_full_argument_spec, - search_by_name, -) - - -class EntityNicsModule(BaseModule): - - def __init__(self, *args, **kwargs): - super(EntityNicsModule, self).__init__(*args, **kwargs) - self.vnic_id = None - - @property - def vnic_id(self): - return self._vnic_id - - @vnic_id.setter - def vnic_id(self, vnic_id): - self._vnic_id = vnic_id - - def build_entity(self): - return otypes.Nic( - id=self._module.params.get('id'), - name=self._module.params.get('name'), - interface=otypes.NicInterface( - self._module.params.get('interface') - ) if self._module.params.get('interface') else None, - vnic_profile=otypes.VnicProfile( - id=self.vnic_id, - ) if self.vnic_id else None, - mac=otypes.Mac( - address=self._module.params.get('mac_address') - ) if self._module.params.get('mac_address') else None, - linked=self.param('linked') if self.param('linked') is not None else None, - ) - - def update_check(self, entity): - if self._module.params.get('vm'): - return ( - equal(self._module.params.get('interface'), str(entity.interface)) and - equal(self._module.params.get('linked'), entity.linked) and - equal(self._module.params.get('name'), str(entity.name)) and - equal(self._module.params.get('profile'), get_link_name(self._connection, entity.vnic_profile)) and - equal(self._module.params.get('mac_address'), entity.mac.address) - ) - elif self._module.params.get('template'): - return ( - equal(self._module.params.get('interface'), str(entity.interface)) and - equal(self._module.params.get('linked'), entity.linked) and - equal(self._module.params.get('name'), str(entity.name)) and - equal(self._module.params.get('profile'), get_link_name(self._connection, entity.vnic_profile)) - ) - - -def get_vnics(networks_service, network, connection): - resp = [] - vnic_services = connection.system_service().vnic_profiles_service() - for vnic in vnic_services.list(): - if vnic.network.id == network.id: - resp.append(vnic) - return resp - - -def main(): - argument_spec = ovirt_full_argument_spec( - state=dict(type='str', default='present', choices=['absent', 'plugged', 'present', 'unplugged']), - vm=dict(type='str'), - id=dict(default=None), - template=dict(type='str'), - name=dict(type='str', required=True), - interface=dict(type='str'), - profile=dict(type='str'), - network=dict(type='str'), - mac_address=dict(type='str'), - linked=dict(type='bool'), - ) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - required_one_of=[['vm', 'template']], - ) - - check_sdk(module) - - try: - # Locate the service that manages the virtual machines and use it to - # search for the NIC: - auth = module.params.pop('auth') - connection = create_connection(auth) - entity_name = None - - if module.params.get('vm'): - # Locate the VM, where we will manage NICs: - entity_name = module.params.get('vm') - collection_service = connection.system_service().vms_service() - elif module.params.get('template'): - entity_name = module.params.get('template') - collection_service = connection.system_service().templates_service() - - # TODO: We have to modify the search_by_name function to accept raise_error=True/False, - entity = search_by_name(collection_service, entity_name) - if entity is None: - raise Exception("Vm/Template '%s' was not found." % entity_name) - - service = collection_service.service(entity.id) - cluster_id = entity.cluster - - nics_service = service.nics_service() - entitynics_module = EntityNicsModule( - connection=connection, - module=module, - service=nics_service, - ) - - # Find vNIC id of the network interface (if any): - if module.params['network']: - profile = module.params.get('profile') - cluster_name = get_link_name(connection, cluster_id) - dcs_service = connection.system_service().data_centers_service() - dc = dcs_service.list(search='Clusters.name=%s' % cluster_name)[0] - networks_service = dcs_service.service(dc.id).networks_service() - network = next( - (n for n in networks_service.list() - if n.name == module.params['network']), - None - ) - if network is None: - raise Exception( - "Network '%s' was not found in datacenter '%s'." % ( - module.params['network'], - dc.name - ) - ) - if profile: - for vnic in connection.system_service().vnic_profiles_service().list(): - if vnic.name == profile and vnic.network.id == network.id: - entitynics_module.vnic_id = vnic.id - else: - # When not specified which vnic use ovirtmgmt/ovirtmgmt - vnics = get_vnics(networks_service, network, connection) - if len(vnics) == 1: - entitynics_module.vnic_id = vnics[0].id - else: - raise Exception( - "You didn't specify any vnic profile. " - "Following vnic profiles are in system: '%s', please specify one of them" % ([vnic.name for vnic in vnics]) - ) - # Handle appropriate action: - state = module.params['state'] - if state == 'present': - ret = entitynics_module.create() - elif state == 'absent': - ret = entitynics_module.remove() - elif state == 'plugged': - entitynics_module.create() - ret = entitynics_module.action( - action='activate', - action_condition=lambda nic: not nic.plugged, - wait_condition=lambda nic: nic.plugged, - ) - elif state == 'unplugged': - entitynics_module.create() - ret = entitynics_module.action( - action='deactivate', - action_condition=lambda nic: nic.plugged, - wait_condition=lambda nic: not nic.plugged, - ) - - module.exit_json(**ret) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_nic_info.py b/lib/ansible/modules/cloud/ovirt/ovirt_nic_info.py deleted file mode 100644 index 0b80020697..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_nic_info.py +++ /dev/null @@ -1,138 +0,0 @@ -#!/usr/bin/python -# -*- 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 . -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_nic_info -short_description: Retrieve information about one or more oVirt/RHV virtual machine network interfaces -author: "Ondra Machacek (@machacekondra)" -version_added: "2.3" -description: - - "Retrieve information about one or more oVirt/RHV virtual machine network interfaces." - - This module was called C(ovirt_nic_facts) before Ansible 2.9, returning C(ansible_facts). - Note that the M(ovirt_nic_info) module no longer returns C(ansible_facts)! -notes: - - "This module returns a variable C(ovirt_nics), which - contains a list of NICs. You need to register the result with - the I(register) keyword to use it." -options: - vm: - description: - - "Name of the VM where NIC is attached." - required: true - name: - description: - - "Name of the NIC, can be used as glob expression." -extends_documentation_fragment: ovirt_info -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Gather information about all NICs which names start with C(eth) for VM named C(centos7): -- ovirt_nic_info: - vm: centos7 - name: eth* - register: result -- debug: - msg: "{{ result.ovirt_nics }}" -''' - -RETURN = ''' -ovirt_nics: - description: "List of dictionaries describing the network interfaces. NIC attributes are mapped to dictionary keys, - all NICs attributes can be found at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/nic." - returned: On success. - type: list -''' - -import fnmatch -import traceback - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - check_sdk, - create_connection, - get_dict_of_struct, - ovirt_info_full_argument_spec, - search_by_name, -) - - -def main(): - argument_spec = ovirt_info_full_argument_spec( - vm=dict(required=True), - name=dict(default=None), - ) - module = AnsibleModule(argument_spec) - is_old_facts = module._name == 'ovirt_nic_facts' - if is_old_facts: - module.deprecate("The 'ovirt_nic_facts' module has been renamed to 'ovirt_nic_info', " - "and the renamed one no longer returns ansible_facts", version='2.13') - - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - vms_service = connection.system_service().vms_service() - vm_name = module.params['vm'] - vm = search_by_name(vms_service, vm_name) - if vm is None: - raise Exception("VM '%s' was not found." % vm_name) - - nics_service = vms_service.service(vm.id).nics_service() - if module.params['name']: - nics = [ - e for e in nics_service.list() - if fnmatch.fnmatch(e.name, module.params['name']) - ] - else: - nics = nics_service.list() - - result = dict( - ovirt_nics=[ - get_dict_of_struct( - struct=c, - connection=connection, - fetch_nested=module.params.get('fetch_nested'), - attributes=module.params.get('nested_attributes'), - ) for c in nics - ], - ) - if is_old_facts: - module.exit_json(changed=False, ansible_facts=result) - else: - module.exit_json(changed=False, **result) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_permission.py b/lib/ansible/modules/cloud/ovirt/ovirt_permission.py deleted file mode 100644 index f494bdbb4f..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_permission.py +++ /dev/null @@ -1,320 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2017, Ansible Project -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - -DOCUMENTATION = ''' ---- -module: ovirt_permission -short_description: Module to manage permissions of users/groups in oVirt/RHV -version_added: "2.3" -author: -- Ondra Machacek (@machacekondra) -description: - - Module to manage permissions of users/groups in oVirt/RHV. -options: - role: - description: - - Name of the role to be assigned to user/group on specific object. - default: UserRole - state: - description: - - Should the permission be present/absent. - choices: [ absent, present ] - default: present - object_id: - description: - - ID of the object where the permissions should be managed. - object_name: - description: - - Name of the object where the permissions should be managed. - object_type: - description: - - The object where the permissions should be managed. - choices: - - cluster - - cpu_profile - - data_center - - disk - - disk_profile - - host - - network - - storage_domain - - system - - template - - vm - - vm_pool - - vnic_profile - default: vm - user_name: - description: - - Username of the user to manage. In most LDAPs it's I(uid) of the user, - but in Active Directory you must specify I(UPN) of the user. - - Note that if user does not exist in the system this module will fail, - you should ensure the user exists by using M(ovirt_users) module. - group_name: - description: - - Name of the group to manage. - - Note that if group does not exist in the system this module will fail, - you should ensure the group exists by using M(ovirt_groups) module. - authz_name: - description: - - Authorization provider of the user/group. - required: true - aliases: [ domain ] - namespace: - description: - - Namespace of the authorization provider, where user/group resides. - quota_name: - description: - - Name of the quota to assign permission. Works only with C(object_type) I(data_center). - version_added: "2.7" -extends_documentation_fragment: ovirt -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -- name: Add user user1 from authorization provider example.com-authz - ovirt_permission: - user_name: user1 - authz_name: example.com-authz - object_type: vm - object_name: myvm - role: UserVmManager - -- name: Remove permission from user - ovirt_permission: - state: absent - user_name: user1 - authz_name: example.com-authz - object_type: cluster - object_name: mycluster - role: ClusterAdmin - -- name: Assign QuotaConsumer role to user - ovirt_permissions: - state: present - user_name: user1 - authz_name: example.com-authz - object_type: data_center - object_name: mydatacenter - quota_name: myquota - role: QuotaConsumer - -- name: Assign QuotaConsumer role to group - ovirt_permissions: - state: present - group_name: group1 - authz_name: example.com-authz - object_type: data_center - object_name: mydatacenter - quota_name: myquota - role: QuotaConsumer -''' - -RETURN = ''' -id: - description: ID of the permission which is managed - returned: On success if permission is found. - type: str - sample: 7de90f31-222c-436c-a1ca-7e655bd5b60c -permission: - description: "Dictionary of all the permission attributes. Permission attributes can be found on your oVirt/RHV instance - at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/permission." - returned: On success if permission is found. - type: dict -''' - -try: - import ovirtsdk4.types as otypes -except ImportError: - pass - -import traceback - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - BaseModule, - check_sdk, - create_connection, - equal, - follow_link, - get_link_name, - ovirt_full_argument_spec, - search_by_attributes, - search_by_name, - get_id_by_name -) - - -def _objects_service(connection, object_type): - if object_type == 'system': - return connection.system_service() - - return getattr( - connection.system_service(), - '%ss_service' % object_type, - None, - )() - - -def _object_service(connection, module): - object_type = module.params['object_type'] - objects_service = _objects_service(connection, object_type) - if object_type == 'system': - return objects_service - - object_id = module.params['object_id'] - if object_id is None: - sdk_object = search_by_name(objects_service, module.params['object_name']) - if sdk_object is None: - raise Exception( - "'%s' object '%s' was not found." % ( - module.params['object_type'], - module.params['object_name'] - ) - ) - object_id = sdk_object.id - - object_service = objects_service.service(object_id) - if module.params['quota_name'] and object_type == 'data_center': - quotas_service = object_service.quotas_service() - return quotas_service.quota_service(get_id_by_name(quotas_service, module.params['quota_name'])) - return object_service - - -def _permission(module, permissions_service, connection): - for permission in permissions_service.list(): - user = follow_link(connection, permission.user) - if ( - equal(module.params['user_name'], user.principal if user else None) and - equal(module.params['group_name'], get_link_name(connection, permission.group)) and - equal(module.params['role'], get_link_name(connection, permission.role)) - ): - return permission - - -class PermissionsModule(BaseModule): - - def _user(self): - user = search_by_attributes( - self._connection.system_service().users_service(), - usrname="{name}@{authz_name}".format( - name=self._module.params['user_name'], - authz_name=self._module.params['authz_name'], - ), - ) - if user is None: - raise Exception("User '%s' was not found." % self._module.params['user_name']) - return user - - def _group(self): - groups = self._connection.system_service().groups_service().list( - search="name={name}".format( - name=self._module.params['group_name'], - ) - ) - - # If found more groups, filter them by namespace and authz name: - # (filtering here, as oVirt/RHV backend doesn't support it) - if len(groups) > 1: - groups = [ - g for g in groups if ( - equal(self._module.params['namespace'], g.namespace) and - equal(self._module.params['authz_name'], g.domain.name) - ) - ] - if not groups: - raise Exception("Group '%s' was not found." % self._module.params['group_name']) - return groups[0] - - def build_entity(self): - entity = self._group() if self._module.params['group_name'] else self._user() - - return otypes.Permission( - user=otypes.User( - id=entity.id - ) if self._module.params['user_name'] else None, - group=otypes.Group( - id=entity.id - ) if self._module.params['group_name'] else None, - role=otypes.Role( - name=self._module.params['role'] - ), - ) - - -def main(): - argument_spec = ovirt_full_argument_spec( - state=dict(type='str', default='present', choices=['absent', 'present']), - role=dict(type='str', default='UserRole'), - object_type=dict(type='str', default='vm', - choices=[ - 'cluster', - 'cpu_profile', - 'data_center', - 'disk', - 'disk_profile', - 'host', - 'network', - 'storage_domain', - 'system', - 'template', - 'vm', - 'vm_pool', - 'vnic_profile', - ]), - authz_name=dict(type='str', required=True, aliases=['domain']), - object_id=dict(type='str'), - object_name=dict(type='str'), - user_name=dict(type='str'), - group_name=dict(type='str'), - namespace=dict(type='str'), - quota_name=dict(type='str'), - ) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - ) - - check_sdk(module) - - if (module.params['object_name'] is None and module.params['object_id'] is None) and module.params['object_type'] != 'system': - module.fail_json(msg='"object_name" or "object_id" is required') - - if module.params['user_name'] is None and module.params['group_name'] is None: - module.fail_json(msg='"user_name" or "group_name" is required') - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - permissions_service = _object_service(connection, module).permissions_service() - permissions_module = PermissionsModule( - connection=connection, - module=module, - service=permissions_service, - ) - - permission = _permission(module, permissions_service, connection) - state = module.params['state'] - if state == 'present': - ret = permissions_module.create(entity=permission) - elif state == 'absent': - ret = permissions_module.remove(entity=permission) - - module.exit_json(**ret) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_permission_info.py b/lib/ansible/modules/cloud/ovirt/ovirt_permission_info.py deleted file mode 100644 index bec4621374..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_permission_info.py +++ /dev/null @@ -1,161 +0,0 @@ -#!/usr/bin/python -# -*- 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 . -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_permission_info -short_description: Retrieve information about one or more oVirt/RHV permissions -author: "Ondra Machacek (@machacekondra)" -version_added: "2.3" -description: - - "Retrieve information about one or more oVirt/RHV permissions." - - This module was called C(ovirt_permission_facts) before Ansible 2.9, returning C(ansible_facts). - Note that the M(ovirt_permission_info) module no longer returns C(ansible_facts)! -notes: - - "This module returns a variable C(ovirt_permissions), which - contains a list of permissions. You need to register the result with - the I(register) keyword to use it." -options: - user_name: - description: - - "Username of the user to manage. In most LDAPs it's I(uid) of the user, but in Active Directory you must specify I(UPN) of the user." - group_name: - description: - - "Name of the group to manage." - authz_name: - description: - - "Authorization provider of the user/group. In previous versions of oVirt/RHV known as domain." - required: true - aliases: ['domain'] - namespace: - description: - - "Namespace of the authorization provider, where user/group resides." - required: false -extends_documentation_fragment: ovirt_info -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Gather information about all permissions of user with username C(john): -- ovirt_permission_info: - user_name: john - authz_name: example.com-authz - register: result -- debug: - msg: "{{ result.ovirt_permissions }}" -''' - -RETURN = ''' -ovirt_permissions: - description: "List of dictionaries describing the permissions. Permission attributes are mapped to dictionary keys, - all permissions attributes can be found at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/permission." - returned: On success. - type: list -''' - -import traceback - -try: - import ovirtsdk4 as sdk -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - check_sdk, - create_connection, - get_link_name, - ovirt_info_full_argument_spec, - search_by_name, -) - - -def _permissions_service(connection, module): - if module.params['user_name']: - service = connection.system_service().users_service() - entity = next( - iter( - service.list( - search='usrname={0}'.format( - '{0}@{1}'.format(module.params['user_name'], module.params['authz_name']) - ) - ) - ), - None - ) - else: - service = connection.system_service().groups_service() - entity = search_by_name(service, module.params['group_name']) - - if entity is None: - raise Exception("User/Group wasn't found.") - - return service.service(entity.id).permissions_service() - - -def main(): - argument_spec = ovirt_info_full_argument_spec( - authz_name=dict(required=True, aliases=['domain']), - user_name=dict(default=None), - group_name=dict(default=None), - namespace=dict(default=None), - ) - module = AnsibleModule(argument_spec) - is_old_facts = module._name == 'ovirt_permission_facts' - if is_old_facts: - module.deprecate("The 'ovirt_permission_facts' module has been renamed to 'ovirt_permission_info', " - "and the renamed one no longer returns ansible_facts", version='2.13') - - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - permissions_service = _permissions_service(connection, module) - permissions = [] - for p in permissions_service.list(): - newperm = dict() - for key, value in p.__dict__.items(): - if value and isinstance(value, sdk.Struct): - newperm[key[1:]] = get_link_name(connection, value) - newperm['%s_id' % key[1:]] = value.id - permissions.append(newperm) - - result = dict(ovirt_permissions=permissions) - if is_old_facts: - module.exit_json(changed=False, ansible_facts=result) - else: - module.exit_json(changed=False, **result) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_quota.py b/lib/ansible/modules/cloud/ovirt/ovirt_quota.py deleted file mode 100644 index 8e61473789..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_quota.py +++ /dev/null @@ -1,319 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (c) 2016 Red Hat, Inc. -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_quota -short_description: Module to manage datacenter quotas in oVirt/RHV -version_added: "2.3" -author: "Ondra Machacek (@machacekondra)" -description: - - "Module to manage datacenter quotas in oVirt/RHV" -options: - id: - description: - - "ID of the quota to manage." - version_added: "2.8" - name: - description: - - "Name of the quota to manage." - required: true - state: - description: - - "Should the quota be present/absent." - choices: ['present', 'absent'] - default: present - data_center: - description: - - "Name of the datacenter where quota should be managed." - required: true - description: - description: - - "Description of the quota to manage." - cluster_threshold: - description: - - "Cluster threshold(soft limit) defined in percentage (0-100)." - aliases: - - "cluster_soft_limit" - cluster_grace: - description: - - "Cluster grace(hard limit) defined in percentage (1-100)." - aliases: - - "cluster_hard_limit" - storage_threshold: - description: - - "Storage threshold(soft limit) defined in percentage (0-100)." - aliases: - - "storage_soft_limit" - storage_grace: - description: - - "Storage grace(hard limit) defined in percentage (1-100)." - aliases: - - "storage_hard_limit" - clusters: - description: - - "List of dictionary of cluster limits, which is valid to specific cluster." - - "If cluster isn't specified it's valid to all clusters in system:" - suboptions: - cluster: - description: - - Name of the cluster. - memory: - description: - - Memory limit (in GiB). - cpu: - description: - - CPU limit. - storages: - description: - - "List of dictionary of storage limits, which is valid to specific storage." - - "If storage isn't specified it's valid to all storages in system:" - suboptions: - storage: - description: - - Name of the storage. - size: - description: - - Size limit (in GiB). -extends_documentation_fragment: ovirt -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Add cluster quota to cluster cluster1 with memory limit 20GiB and CPU limit to 10: -- ovirt_quota: - name: quota1 - data_center: dcX - clusters: - - name: cluster1 - memory: 20 - cpu: 10 - -# Add cluster quota to all clusters with memory limit 30GiB and CPU limit to 15: -- ovirt_quota: - name: quota2 - data_center: dcX - clusters: - - memory: 30 - cpu: 15 - -# Add storage quota to storage data1 with size limit to 100GiB -- ovirt_quota: - name: quota3 - data_center: dcX - storage_grace: 40 - storage_threshold: 60 - storages: - - name: data1 - size: 100 - -# Remove quota quota1 (Note the quota must not be assigned to any VM/disk): -- ovirt_quota: - state: absent - data_center: dcX - name: quota1 - -# Change Quota Name -- ovirt_quota: - id: 00000000-0000-0000-0000-000000000000 - name: "new_quota_name" - data_center: dcX -''' - -RETURN = ''' -id: - description: ID of the quota which is managed - returned: On success if quota is found. - type: str - sample: 7de90f31-222c-436c-a1ca-7e655bd5b60c -quota: - description: "Dictionary of all the quota attributes. Quota attributes can be found on your oVirt/RHV instance - at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/quota." - returned: On success if quota is found. - type: dict -''' - -try: - import ovirtsdk4.types as otypes -except ImportError: - pass - -import traceback - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - BaseModule, - check_sdk, - create_connection, - equal, - get_link_name, - ovirt_full_argument_spec, - search_by_name, -) - - -class QuotasModule(BaseModule): - - def build_entity(self): - return otypes.Quota( - description=self._module.params['description'], - name=self._module.params['name'], - id=self._module.params['id'], - storage_hard_limit_pct=self._module.params.get('storage_grace'), - storage_soft_limit_pct=self._module.params.get('storage_threshold'), - cluster_hard_limit_pct=self._module.params.get('cluster_grace'), - cluster_soft_limit_pct=self._module.params.get('cluster_threshold'), - ) - - def update_storage_limits(self, entity): - new_limits = {} - for storage in self._module.params.get('storages'): - new_limits[storage.get('name', '')] = { - 'size': storage.get('size'), - } - - old_limits = {} - sd_limit_service = self._service.service(entity.id).quota_storage_limits_service() - for limit in sd_limit_service.list(): - storage = get_link_name(self._connection, limit.storage_domain) if limit.storage_domain else '' - old_limits[storage] = { - 'size': limit.limit, - } - sd_limit_service.service(limit.id).remove() - - return new_limits == old_limits - - def update_cluster_limits(self, entity): - new_limits = {} - for cluster in self._module.params.get('clusters'): - new_limits[cluster.get('name', '')] = { - 'cpu': cluster.get('cpu'), - 'memory': float(cluster.get('memory')), - } - - old_limits = {} - cl_limit_service = self._service.service(entity.id).quota_cluster_limits_service() - for limit in cl_limit_service.list(): - cluster = get_link_name(self._connection, limit.cluster) if limit.cluster else '' - old_limits[cluster] = { - 'cpu': limit.vcpu_limit, - 'memory': limit.memory_limit, - } - cl_limit_service.service(limit.id).remove() - - return new_limits == old_limits - - def update_check(self, entity): - # -- FIXME -- - # Note that we here always remove all cluster/storage limits, because - # it's not currently possible to update them and then re-create the limits - # appropriately, this shouldn't have any side-effects, but it's not considered - # as a correct approach. - # This feature is tracked here: https://bugzilla.redhat.com/show_bug.cgi?id=1398576 - # - - return ( - self.update_storage_limits(entity) and - self.update_cluster_limits(entity) and - equal(self._module.params.get('name'), entity.name) and - equal(self._module.params.get('description'), entity.description) and - equal(self._module.params.get('storage_grace'), entity.storage_hard_limit_pct) and - equal(self._module.params.get('storage_threshold'), entity.storage_soft_limit_pct) and - equal(self._module.params.get('cluster_grace'), entity.cluster_hard_limit_pct) and - equal(self._module.params.get('cluster_threshold'), entity.cluster_soft_limit_pct) - ) - - -def main(): - argument_spec = ovirt_full_argument_spec( - state=dict( - choices=['present', 'absent'], - default='present', - ), - id=dict(default=None), - name=dict(required=True), - data_center=dict(required=True), - description=dict(default=None), - cluster_threshold=dict(default=None, type='int', aliases=['cluster_soft_limit']), - cluster_grace=dict(default=None, type='int', aliases=['cluster_hard_limit']), - storage_threshold=dict(default=None, type='int', aliases=['storage_soft_limit']), - storage_grace=dict(default=None, type='int', aliases=['storage_hard_limit']), - clusters=dict(default=[], type='list'), - storages=dict(default=[], type='list'), - ) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - ) - - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - datacenters_service = connection.system_service().data_centers_service() - dc_name = module.params['data_center'] - dc_id = getattr(search_by_name(datacenters_service, dc_name), 'id', None) - if dc_id is None: - raise Exception("Datacenter '%s' was not found." % dc_name) - - quotas_service = datacenters_service.service(dc_id).quotas_service() - quotas_module = QuotasModule( - connection=connection, - module=module, - service=quotas_service, - ) - - state = module.params['state'] - if state == 'present': - ret = quotas_module.create() - - # Manage cluster limits: - cl_limit_service = quotas_service.service(ret['id']).quota_cluster_limits_service() - for cluster in module.params.get('clusters'): - cl_limit_service.add( - limit=otypes.QuotaClusterLimit( - memory_limit=float(cluster.get('memory')), - vcpu_limit=cluster.get('cpu'), - cluster=search_by_name( - connection.system_service().clusters_service(), - cluster.get('name') - ), - ), - ) - - # Manage storage limits: - sd_limit_service = quotas_service.service(ret['id']).quota_storage_limits_service() - for storage in module.params.get('storages'): - sd_limit_service.add( - limit=otypes.QuotaStorageLimit( - limit=storage.get('size'), - storage_domain=search_by_name( - connection.system_service().storage_domains_service(), - storage.get('name') - ), - ) - ) - - elif state == 'absent': - ret = quotas_module.remove() - - module.exit_json(**ret) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_quota_info.py b/lib/ansible/modules/cloud/ovirt/ovirt_quota_info.py deleted file mode 100644 index a1013ec67f..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_quota_info.py +++ /dev/null @@ -1,138 +0,0 @@ -#!/usr/bin/python -# -*- 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 . -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_quota_info -short_description: Retrieve information about one or more oVirt/RHV quotas -version_added: "2.3" -author: "Maor Lipchuk (@machacekondra)" -description: - - "Retrieve information about one or more oVirt/RHV quotas." - - This module was called C(ovirt_quota_facts) before Ansible 2.9, returning C(ansible_facts). - Note that the M(ovirt_quota_info) module no longer returns C(ansible_facts)! -notes: - - "This module returns a variable C(ovirt_quotas), which - contains a list of quotas. You need to register the result with - the I(register) keyword to use it." -options: - data_center: - description: - - "Name of the datacenter where quota resides." - required: true - name: - description: - - "Name of the quota, can be used as glob expression." -extends_documentation_fragment: ovirt_info -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Gather information about quota named C in Default datacenter: -- ovirt_quota_info: - data_center: Default - name: myquota - register: result -- debug: - msg: "{{ result.ovirt_quotas }}" -''' - -RETURN = ''' -ovirt_quotas: - description: "List of dictionaries describing the quotas. Quota attributes are mapped to dictionary keys, - all quotas attributes can be found at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/quota." - returned: On success. - type: list -''' - -import fnmatch -import traceback - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - check_sdk, - create_connection, - get_dict_of_struct, - ovirt_info_full_argument_spec, - search_by_name, -) - - -def main(): - argument_spec = ovirt_info_full_argument_spec( - data_center=dict(required=True), - name=dict(default=None), - ) - module = AnsibleModule(argument_spec) - is_old_facts = module._name == 'ovirt_quota_facts' - if is_old_facts: - module.deprecate("The 'ovirt_quota_facts' module has been renamed to 'ovirt_quota_info', " - "and the renamed one no longer returns ansible_facts", version='2.13') - - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - datacenters_service = connection.system_service().data_centers_service() - dc_name = module.params['data_center'] - dc = search_by_name(datacenters_service, dc_name) - if dc is None: - raise Exception("Datacenter '%s' was not found." % dc_name) - - quotas_service = datacenters_service.service(dc.id).quotas_service() - if module.params['name']: - quotas = [ - e for e in quotas_service.list() - if fnmatch.fnmatch(e.name, module.params['name']) - ] - else: - quotas = quotas_service.list() - - result = dict( - ovirt_quotas=[ - get_dict_of_struct( - struct=c, - connection=connection, - fetch_nested=module.params.get('fetch_nested'), - attributes=module.params.get('nested_attributes'), - ) for c in quotas - ], - ) - if is_old_facts: - module.exit_json(changed=False, ansible_facts=result) - else: - module.exit_json(changed=False, **result) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_role.py b/lib/ansible/modules/cloud/ovirt/ovirt_role.py deleted file mode 100644 index 9f1d94e79a..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_role.py +++ /dev/null @@ -1,190 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (c) 2016 Red Hat, Inc. -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - -DOCUMENTATION = ''' ---- -module: ovirt_role -short_description: Module to manage roles in oVirt/RHV -version_added: "2.8" -author: "Martin Necas (@mnecas)" -description: - - "Module to manage roles in oVirt/RHV." -options: - name: - description: - - "Name of the role to manage." - id: - description: - - "ID of the role to manage." - description: - description: - - "Description of the role." - state: - description: - - "Should the role be present/absent." - choices: ['present', 'absent'] - default: present - administrative: - description: - - "Defines the role as administrative-only or not." - type: bool - permits: - description: - - "List of permits which role will have" - - "Permit 'login' is default and all roles will have it." - - "List can contain name of permit." -extends_documentation_fragment: ovirt -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Create administrative role with two permits -- ovirt_role: - name: role - administrative: true - permits: - - manipulate_permissions - - create_instance - -# Remove role -- ovirt_role: - name: role - state: absent - -# Remove all permit -- ovirt_role: - name: role - administrative: ture - permits: - - login -''' - -RETURN = ''' -ovirt_role: - description: "List of dictionaries describing the Roles. Role attributes are mapped to dictionary keys, - all Roles attributes can be found at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/role." - returned: On success. - type: list -''' - -from ansible.module_utils.ovirt import ( - BaseModule, - check_sdk, - convert_to_bytes, - create_connection, - equal, - get_dict_of_struct, - get_link_name, - get_id_by_name, - ovirt_full_argument_spec, - search_by_attributes, - search_by_name, -) -from ansible.module_utils.basic import AnsibleModule -import traceback - -try: - import ovirtsdk4.types as otypes -except ImportError: - pass - - -class RoleModule(BaseModule): - def build_entity(self): - if 'login' not in self.param('permits'): - self.param('permits').append('login') - all_permits = self.get_all_permits() - return otypes.Role( - id=self.param('id'), - name=self.param('name'), - administrative=self.param('administrative') if self.param( - 'administrative') else None, - permits=[ - otypes.Permit(id=all_permits.get(new_permit)) for new_permit in self.param('permits') - ] if self.param('permits') else None, - description=self.param('description') if self.param('administrative') else None, - ) - - def get_all_permits(self): - return dict((permit.name, permit.id) for permit in self._connection.system_service().cluster_levels_service().level_service('4.3').get().permits) - - def update_check(self, entity): - def check_permits(): - if self.param('permits'): - if 'login' not in self.param('permits'): - self.param('permits').append('login') - permits_service = self._service.service(entity.id).permits_service() - current = [er.name for er in permits_service.list()] - passed = [pr for pr in self.param('permits')] - if not sorted(current) == sorted(passed): - if self._module.check_mode: - return False - # remove all - for permit in permits_service.list(): - permits_service.permit_service(permit.id).remove() - # add passed permits - all_permits = self.get_all_permits() - for new_permit in passed: - permits_service.add(otypes.Permit(id=all_permits.get(new_permit))) - return False - return True - - return ( - check_permits() and - equal(self.param('administrative'), entity.administrative) and - equal(self.param('description'), entity.description) - ) - - -def main(): - argument_spec = ovirt_full_argument_spec( - state=dict( - choices=['present', 'absent'], - default='present', - ), - id=dict(default=None), - name=dict(default=None), - description=dict(default=None), - administrative=dict(type='bool', default=False), - permits=dict(type='list', default=[]), - ) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - required_one_of=[['id', 'name']], - ) - - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - roles_service = connection.system_service().roles_service() - roles_module = RoleModule( - connection=connection, - module=module, - service=roles_service, - ) - state = module.params['state'] - if state == 'present': - ret = roles_module.create() - elif state == 'absent': - ret = roles_module.remove() - module.exit_json(**ret) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_scheduling_policy_info.py b/lib/ansible/modules/cloud/ovirt/ovirt_scheduling_policy_info.py deleted file mode 100644 index f238a44be1..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_scheduling_policy_info.py +++ /dev/null @@ -1,137 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (c) 2017 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 . -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_scheduling_policy_info -short_description: Retrieve information about one or more oVirt scheduling policies -author: "Ondra Machacek (@machacekondra)" -version_added: "2.4" -description: - - "Retrieve information about one or more oVirt scheduling policies." - - This module was called C(ovirt_scheduling_policy_facts) before Ansible 2.9, returning C(ansible_facts). - Note that the M(ovirt_scheduling_policy_info) module no longer returns C(ansible_facts)! -notes: - - "This module returns a variable C(ovirt_scheduling_policies), - which contains a list of scheduling policies. You need to register the result with - the I(register) keyword to use it." -options: - id: - description: - - "ID of the scheduling policy." - required: true - name: - description: - - "Name of the scheduling policy, can be used as glob expression." -extends_documentation_fragment: ovirt_info -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Gather information about all scheduling policies with name InClusterUpgrade: -- ovirt_scheduling_policy_info: - name: InClusterUpgrade - register: result -- debug: - msg: "{{ result.ovirt_scheduling_policies }}" -''' - -RETURN = ''' -ovirt_scheduling_policies: - description: "List of dictionaries describing the scheduling policies. - Scheduling policies attributes are mapped to dictionary keys, - all scheduling policies attributes can be found at following - url: https://ovirt.example.com/ovirt-engine/api/model#types/scheduling_policy." - returned: On success. - type: list -''' - -import fnmatch -import traceback - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - check_sdk, - create_connection, - get_dict_of_struct, - ovirt_info_full_argument_spec, -) - - -def main(): - argument_spec = ovirt_info_full_argument_spec( - id=dict(default=None), - name=dict(default=None), - ) - module = AnsibleModule(argument_spec) - is_old_facts = module._name == 'ovirt_scheduling_policy_facts' - if is_old_facts: - module.deprecate("The 'ovirt_scheduling_policy_facts' module has been renamed to 'ovirt_scheduling_policy_info', " - "and the renamed one no longer returns ansible_facts", version='2.13') - - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - system_service = connection.system_service() - sched_policies_service = system_service.scheduling_policies_service() - if module.params['name']: - sched_policies = [ - e for e in sched_policies_service.list() - if fnmatch.fnmatch(e.name, module.params['name']) - ] - elif module.params['id']: - sched_policies = [ - sched_policies_service.service(module.params['id']).get() - ] - else: - sched_policies = sched_policies_service.list() - - result = dict( - ovirt_scheduling_policies=[ - get_dict_of_struct( - struct=c, - connection=connection, - fetch_nested=module.params.get('fetch_nested'), - attributes=module.params.get('nested_attributes'), - ) for c in sched_policies - ], - ) - if is_old_facts: - module.exit_json(changed=False, ansible_facts=result) - else: - module.exit_json(changed=False, **result) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_snapshot.py b/lib/ansible/modules/cloud/ovirt/ovirt_snapshot.py deleted file mode 100644 index 869fd84f45..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_snapshot.py +++ /dev/null @@ -1,551 +0,0 @@ -#!/usr/bin/python -# -*- 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 . -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_snapshot -short_description: "Module to manage Virtual Machine Snapshots in oVirt/RHV" -version_added: "2.3" -author: "Ondra Machacek (@machacekondra)" -description: - - "Module to manage Virtual Machine Snapshots in oVirt/RHV" -options: - snapshot_id: - description: - - "ID of the snapshot to manage." - vm_name: - description: - - "Name of the Virtual Machine to manage." - required: true - state: - description: - - "Should the Virtual Machine snapshot be restore/present/absent." - choices: ['restore', 'present', 'absent'] - default: present - description: - description: - - "Description of the snapshot." - disk_id: - description: - - "Disk id which you want to upload or download" - - "To get disk, you need to define disk_id or disk_name" - version_added: "2.8" - disk_name: - description: - - "Disk name which you want to upload or download" - version_added: "2.8" - download_image_path: - description: - - "Path on a file system where snapshot should be downloaded." - - "Note that you must have an valid oVirt/RHV engine CA in your system trust store - or you must provide it in C(ca_file) parameter." - - "Note that the snapshot is not downloaded when the file already exists, - but you can forcibly download the snapshot when using C(force) I (true)." - version_added: "2.8" - upload_image_path: - description: - - "Path to disk image, which should be uploaded." - version_added: "2.8" - use_memory: - description: - - "If I(true) and C(state) is I(present) save memory of the Virtual - Machine if it's running." - - "If I(true) and C(state) is I(restore) restore memory of the - Virtual Machine." - - "Note that Virtual Machine will be paused while saving the memory." - aliases: - - "restore_memory" - - "save_memory" - type: bool - keep_days_old: - description: - - "Number of days after which should snapshot be deleted." - - "It will check all snapshots of virtual machine and delete them, if they are older." - version_added: "2.8" - disks: - description: - - "List of disks which should be created with snapshot." - suboptions: - id: - description: - - "Id of the disk which should will be created." - type: str - name: - description: - - "Name of the disk which should will be created." - type: str - type: list - version_added: "2.10" -notes: - - "Note that without a guest agent the data on the created snapshot may be - inconsistent." - - "Deleting a snapshot does not remove any information from the virtual - machine - it simply removes a return-point. However, restoring a virtual - machine from a snapshot deletes any content that was written to the - virtual machine after the time the snapshot was taken." -extends_documentation_fragment: ovirt -''' - - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Create snapshot: -- ovirt_snapshot: - vm_name: rhel7 - description: MySnapshot - register: snapshot - -# Create snapshot and save memory: -- ovirt_snapshot: - vm_name: rhel7 - description: SnapWithMem - use_memory: true - register: snapshot - -# Restore snapshot: -- ovirt_snapshot: - state: restore - vm_name: rhel7 - snapshot_id: "{{ snapshot.id }}" - -# Remove snapshot: -- ovirt_snapshot: - state: absent - vm_name: rhel7 - snapshot_id: "{{ snapshot.id }}" - -# Upload local image to disk and attach it to vm: -# Since Ansible 2.8 -- ovirt_snapshot: - name: mydisk - vm_name: myvm - upload_image_path: /path/to/mydisk.qcow2 - -# Download snapshot to local file system: -# Since Ansible 2.8 -- ovirt_snapshot: - snapshot_id: 7de90f31-222c-436c-a1ca-7e655bd5b60c - disk_name: DiskName - vm_name: myvm - download_image_path: /home/user/mysnaphost.qcow2 - -# Delete all snapshots older than 2 days -- ovirt_snapshot: - vm_name: test - keep_days_old: 2 - -- name: Select which disks should be add to snapshot - ovirt_snapshot: - vm_name: test - disks: - - id: 7de90f31-222c-436c-a1ca-7e655bd5b60c - - name: my_disk_name -''' - - -RETURN = ''' -id: - description: ID of the snapshot which is managed - returned: On success if snapshot is found. - type: str - sample: 7de90f31-222c-436c-a1ca-7e655bd5b60c -snapshot: - description: "Dictionary of all the snapshot attributes. Snapshot attributes can be found on your oVirt/RHV instance - at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/snapshot." - returned: On success if snapshot is found. - type: dict -snapshots: - description: List of deleted snapshots when keep_days_old is defined and snapshot is older than the input days - returned: On success returns deleted snapshots - type: list -''' - - -import traceback - -try: - import ovirtsdk4.types as otypes -except ImportError: - pass - - -import os -import ssl -import time - -from ansible.module_utils.six.moves.http_client import HTTPSConnection, IncompleteRead -from ansible.module_utils.six.moves.urllib.parse import urlparse - -from datetime import datetime -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - check_sdk, - create_connection, - get_dict_of_struct, - get_entity, - ovirt_full_argument_spec, - search_by_name, - wait, - get_id_by_name, - get_link_name -) - - -def transfer(connection, module, direction, transfer_func): - transfers_service = connection.system_service().image_transfers_service() - transfer = transfers_service.add( - otypes.ImageTransfer( - image=otypes.Image( - id=module.params['disk_id'], - ), - direction=direction, - ) - ) - transfer_service = transfers_service.image_transfer_service(transfer.id) - - try: - # After adding a new transfer for the disk, the transfer's status will be INITIALIZING. - # Wait until the init phase is over. The actual transfer can start when its status is "Transferring". - while transfer.phase == otypes.ImageTransferPhase.INITIALIZING: - time.sleep(module.params['poll_interval']) - transfer = transfer_service.get() - - proxy_url = urlparse(transfer.proxy_url) - context = ssl.create_default_context() - auth = module.params['auth'] - if auth.get('insecure'): - context.check_hostname = False - context.verify_mode = ssl.CERT_NONE - elif auth.get('ca_file'): - context.load_verify_locations(cafile=auth.get('ca_file')) - - proxy_connection = HTTPSConnection( - proxy_url.hostname, - proxy_url.port, - context=context, - ) - - transfer_func( - transfer_service, - proxy_connection, - proxy_url, - transfer.signed_ticket - ) - return True - finally: - transfer_service.finalize() - while transfer.phase in [ - otypes.ImageTransferPhase.TRANSFERRING, - otypes.ImageTransferPhase.FINALIZING_SUCCESS, - ]: - time.sleep(module.params['poll_interval']) - transfer = transfer_service.get() - if transfer.phase in [ - otypes.ImageTransferPhase.UNKNOWN, - otypes.ImageTransferPhase.FINISHED_FAILURE, - otypes.ImageTransferPhase.FINALIZING_FAILURE, - otypes.ImageTransferPhase.CANCELLED, - ]: - raise Exception( - "Error occurred while uploading image. The transfer is in %s" % transfer.phase - ) - if module.params.get('logical_unit'): - disks_service = connection.system_service().disks_service() - wait( - service=disks_service.service(module.params['id']), - condition=lambda d: d.status == otypes.DiskStatus.OK, - wait=module.params['wait'], - timeout=module.params['timeout'], - ) - - -def upload_disk_image(connection, module): - def _transfer(transfer_service, proxy_connection, proxy_url, transfer_ticket): - BUF_SIZE = 128 * 1024 - path = module.params['upload_image_path'] - - image_size = os.path.getsize(path) - proxy_connection.putrequest("PUT", proxy_url.path) - proxy_connection.putheader('Content-Length', "%d" % (image_size,)) - proxy_connection.endheaders() - with open(path, "rb") as disk: - pos = 0 - while pos < image_size: - to_read = min(image_size - pos, BUF_SIZE) - chunk = disk.read(to_read) - if not chunk: - transfer_service.pause() - raise RuntimeError("Unexpected end of file at pos=%d" % pos) - proxy_connection.send(chunk) - pos += len(chunk) - - return transfer( - connection, - module, - otypes.ImageTransferDirection.UPLOAD, - transfer_func=_transfer, - ) - - -def download_disk_image(connection, module): - def _transfer(transfer_service, proxy_connection, proxy_url, transfer_ticket): - BUF_SIZE = 128 * 1024 - transfer_headers = { - 'Authorization': transfer_ticket, - } - proxy_connection.request( - 'GET', - proxy_url.path, - headers=transfer_headers, - ) - r = proxy_connection.getresponse() - path = module.params["download_image_path"] - image_size = int(r.getheader('Content-Length')) - with open(path, "wb") as mydisk: - pos = 0 - while pos < image_size: - to_read = min(image_size - pos, BUF_SIZE) - chunk = r.read(to_read) - if not chunk: - raise RuntimeError("Socket disconnected") - mydisk.write(chunk) - pos += len(chunk) - - return transfer( - connection, - module, - otypes.ImageTransferDirection.DOWNLOAD, - transfer_func=_transfer, - ) - - -def get_disk_attachment(disk, disk_attachments, connection): - for disk_attachment in disk_attachments: - if get_link_name(connection, disk_attachment.disk) == disk.get('name') or\ - disk_attachment.disk.id == disk.get('id'): - return disk_attachment - - -def create_snapshot(module, vm_service, snapshots_service, connection): - changed = False - snapshot = get_entity( - snapshots_service.snapshot_service(module.params['snapshot_id']) - ) - if snapshot is None: - if not module.check_mode: - disk_attachments_id = set( - get_disk_attachment(disk, vm_service.disk_attachments_service().list(), connection).id - for disk in module.params.get('disks') - ) if module.params.get('disks') else None - - snapshot = snapshots_service.add( - otypes.Snapshot( - description=module.params.get('description'), - persist_memorystate=module.params.get('use_memory'), - disk_attachments=[otypes.DiskAttachment(disk=otypes.Disk(id=da_id)) for da_id in disk_attachments_id] if disk_attachments_id else None - ) - ) - changed = True - wait( - service=snapshots_service.snapshot_service(snapshot.id), - condition=lambda snap: snap.snapshot_status == otypes.SnapshotStatus.OK, - wait=module.params['wait'], - timeout=module.params['timeout'], - ) - return { - 'changed': changed, - 'id': snapshot.id, - 'snapshot': get_dict_of_struct(snapshot), - } - - -def remove_snapshot(module, vm_service, snapshots_service, snapshot_id=None): - changed = False - if not snapshot_id: - snapshot_id = module.params['snapshot_id'] - snapshot = get_entity( - snapshots_service.snapshot_service(snapshot_id) - ) - - if snapshot: - snapshot_service = snapshots_service.snapshot_service(snapshot.id) - if not module.check_mode: - snapshot_service.remove() - changed = True - wait( - service=snapshot_service, - condition=lambda snapshot: snapshot is None, - wait=module.params['wait'], - timeout=module.params['timeout'], - ) - - return { - 'changed': changed, - 'id': snapshot.id if snapshot else None, - 'snapshot': get_dict_of_struct(snapshot), - } - - -def restore_snapshot(module, vm_service, snapshots_service): - changed = False - snapshot_service = snapshots_service.snapshot_service( - module.params['snapshot_id'] - ) - snapshot = get_entity(snapshot_service) - if snapshot is None: - raise Exception( - "Snapshot with id '%s' doesn't exist" % module.params['snapshot_id'] - ) - - if snapshot.snapshot_status != otypes.SnapshotStatus.IN_PREVIEW: - if not module.check_mode: - snapshot_service.restore( - restore_memory=module.params.get('use_memory'), - ) - changed = True - else: - if not module.check_mode: - vm_service.commit_snapshot() - changed = True - - if changed: - wait( - service=snapshot_service, - condition=lambda snap: snap.snapshot_status == otypes.SnapshotStatus.OK, - wait=module.params['wait'], - timeout=module.params['timeout'], - ) - return { - 'changed': changed, - 'id': snapshot.id if snapshot else None, - 'snapshot': get_dict_of_struct(snapshot), - } - - -def get_snapshot_disk_id(module, snapshots_service): - snapshot_service = snapshots_service.snapshot_service(module.params.get('snapshot_id')) - snapshot_disks_service = snapshot_service.disks_service() - - disk_id = '' - if module.params.get('disk_id'): - disk_id = module.params.get('disk_id') - elif module.params.get('disk_name'): - disk_id = get_id_by_name(snapshot_disks_service, module.params.get('disk_name')) - return disk_id - - -def remove_old_snapshosts(module, vm_service, snapshots_service): - deleted_snapshots = [] - changed = False - date_now = datetime.now() - for snapshot in snapshots_service.list(): - if snapshot.vm is not None and snapshot.vm.name == module.params.get('vm_name'): - diff = date_now - snapshot.date.replace(tzinfo=None) - if diff.days >= module.params.get('keep_days_old'): - snapshot = remove_snapshot(module, vm_service, snapshots_service, snapshot.id).get('snapshot') - deleted_snapshots.append(snapshot) - changed = True - return dict(snapshots=deleted_snapshots, changed=changed) - - -def main(): - argument_spec = ovirt_full_argument_spec( - state=dict( - choices=['restore', 'present', 'absent'], - default='present', - ), - vm_name=dict(required=True), - snapshot_id=dict(default=None), - disks=dict( - type='list', - options=dict( - name=dict(default=None, type='str'), - id=dict(default=None, type='str'), - ) - ), - disk_id=dict(default=None), - disk_name=dict(default=None), - description=dict(default=None), - download_image_path=dict(default=None), - upload_image_path=dict(default=None), - keep_days_old=dict(default=None, type='int'), - use_memory=dict( - default=None, - type='bool', - aliases=['restore_memory', 'save_memory'], - ), - ) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - required_if=[ - ('state', 'absent', ['snapshot_id']), - ('state', 'restore', ['snapshot_id']), - ] - ) - - check_sdk(module) - ret = {} - vm_name = module.params.get('vm_name') - auth = module.params['auth'] - connection = create_connection(auth) - vms_service = connection.system_service().vms_service() - vm = search_by_name(vms_service, vm_name) - if not vm: - module.fail_json( - msg="Vm '{name}' doesn't exist.".format(name=vm_name), - ) - - vm_service = vms_service.vm_service(vm.id) - snapshots_service = vms_service.vm_service(vm.id).snapshots_service() - try: - state = module.params['state'] - if state == 'present': - if module.params.get('disk_id') or module.params.get('disk_name'): - module.params['disk_id'] = get_snapshot_disk_id(module, snapshots_service) - if module.params['upload_image_path']: - ret['changed'] = upload_disk_image(connection, module) - if module.params['download_image_path']: - ret['changed'] = download_disk_image(connection, module) - if module.params.get('keep_days_old') is not None: - ret = remove_old_snapshosts(module, vm_service, snapshots_service) - else: - ret = create_snapshot(module, vm_service, snapshots_service, connection) - elif state == 'restore': - ret = restore_snapshot(module, vm_service, snapshots_service) - elif state == 'absent': - ret = remove_snapshot(module, vm_service, snapshots_service) - module.exit_json(**ret) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_snapshot_info.py b/lib/ansible/modules/cloud/ovirt/ovirt_snapshot_info.py deleted file mode 100644 index 0d21e2fe7c..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_snapshot_info.py +++ /dev/null @@ -1,133 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (c) 2016 Red Hat, Inc. -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_snapshot_info -short_description: Retrieve information about one or more oVirt/RHV virtual machine snapshots -author: "Ondra Machacek (@machacekondra)" -version_added: "2.3" -description: - - "Retrieve information about one or more oVirt/RHV virtual machine snapshots." - - This module was called C(ovirt_snapshot_facts) before Ansible 2.9, returning C(ansible_facts). - Note that the M(ovirt_snapshot_info) module no longer returns C(ansible_facts)! -notes: - - "This module returns a variable C(ovirt_snapshots), which - contains a list of snapshots. You need to register the result with - the I(register) keyword to use it." -options: - vm: - description: - - "Name of the VM with snapshot." - required: true - description: - description: - - "Description of the snapshot, can be used as glob expression." - snapshot_id: - description: - - "Id of the snapshot we want to retrieve information about." -extends_documentation_fragment: ovirt_info -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Gather information about all snapshots which description start with C(update) for VM named C(centos7): -- ovirt_snapshot_info: - vm: centos7 - description: update* - register: result -- debug: - msg: "{{ result.ovirt_snapshots }}" -''' - -RETURN = ''' -ovirt_snapshots: - description: "List of dictionaries describing the snapshot. Snapshot attributes are mapped to dictionary keys, - all snapshot attributes can be found at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/snapshot." - returned: On success. - type: list -''' - - -import fnmatch -import traceback - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - check_sdk, - create_connection, - get_dict_of_struct, - ovirt_info_full_argument_spec, - search_by_name, -) - - -def main(): - argument_spec = ovirt_info_full_argument_spec( - vm=dict(required=True), - description=dict(default=None), - snapshot_id=dict(default=None), - ) - module = AnsibleModule(argument_spec) - is_old_facts = module._name == 'ovirt_snapshot_facts' - if is_old_facts: - module.deprecate("The 'ovirt_snapshot_facts' module has been renamed to 'ovirt_snapshot_info', " - "and the renamed one no longer returns ansible_facts", version='2.13') - - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - vms_service = connection.system_service().vms_service() - vm_name = module.params['vm'] - vm = search_by_name(vms_service, vm_name) - if vm is None: - raise Exception("VM '%s' was not found." % vm_name) - - snapshots_service = vms_service.service(vm.id).snapshots_service() - if module.params['description']: - snapshots = [ - e for e in snapshots_service.list() - if fnmatch.fnmatch(e.description, module.params['description']) - ] - elif module.params['snapshot_id']: - snapshots = [ - snapshots_service.snapshot_service(module.params['snapshot_id']).get() - ] - else: - snapshots = snapshots_service.list() - - result = dict( - ovirt_snapshots=[ - get_dict_of_struct( - struct=c, - connection=connection, - fetch_nested=module.params.get('fetch_nested'), - attributes=module.params.get('nested_attributes'), - ) for c in snapshots - ], - ) - if is_old_facts: - module.exit_json(changed=False, ansible_facts=result) - else: - module.exit_json(changed=False, **result) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_storage_connection.py b/lib/ansible/modules/cloud/ovirt/ovirt_storage_connection.py deleted file mode 100644 index cd74e8617a..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_storage_connection.py +++ /dev/null @@ -1,285 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (c) 2017 Red Hat, Inc. -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - -DOCUMENTATION = ''' ---- -module: ovirt_storage_connection -short_description: Module to manage storage connections in oVirt -version_added: "2.4" -author: "Ondra Machacek (@machacekondra)" -description: - - "Module to manage storage connections in oVirt" -options: - id: - description: - - "Id of the storage connection to manage." - state: - description: - - "Should the storage connection be present or absent." - choices: ['present', 'absent'] - default: present - storage: - description: - - "Name of the storage domain to be used with storage connection." - address: - description: - - "Address of the storage server. E.g.: myserver.mydomain.com" - path: - description: - - "Path of the mount point of the storage. E.g.: /path/to/my/data" - nfs_version: - description: - - "NFS version. One of: I(auto), I(v3), I(v4) or I(v4_1)." - nfs_timeout: - description: - - "The time in tenths of a second to wait for a response before retrying NFS requests. Range 0 to 65535." - nfs_retrans: - description: - - "The number of times to retry a request before attempting further recovery actions. Range 0 to 65535." - mount_options: - description: - - "Option which will be passed when mounting storage." - password: - description: - - "A CHAP password for logging into a target." - username: - description: - - "A CHAP username for logging into a target." - port: - description: - - "Port of the iSCSI storage server." - target: - description: - - "The target IQN for the storage device." - type: - description: - - "Storage type. For example: I(nfs), I(iscsi), etc." - vfs_type: - description: - - "Virtual File System type." - force: - description: - - "This parameter is relevant only when updating a connection." - - "If I(true) the storage domain don't have to be in I(MAINTENANCE) - state, so the storage connection is updated." - type: bool -extends_documentation_fragment: ovirt -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Add new storage connection: -- ovirt_storage_connection: - storage: myiscsi - address: 10.34.63.199 - target: iqn.2016-08-09.domain-01:nickname - port: 3260 - type: iscsi - -# Update the existing storage connection address: -- ovirt_storage_connection: - id: 26915c96-92ff-47e5-9e77-b581db2f2d36 - address: 10.34.63.204 - force: true - -# Remove storage connection: -- ovirt_storage_connection: - id: 26915c96-92ff-47e5-9e77-b581db2f2d36 -''' - -RETURN = ''' -id: - description: ID of the storage connection which is managed - returned: On success if storage connection is found. - type: str - sample: 7de90f31-222c-436c-a1ca-7e655bd5b60c -storage_connection: - description: "Dictionary of all the storage connection attributes. Storage connection attributes can be found on your oVirt instance - at following url: https://ovirt.example.com/ovirt-engine/api/model#types/storage_connection." - returned: On success if storage connection is found. - type: dict -''' - -try: - import ovirtsdk4.types as otypes -except ImportError: - pass - -import traceback - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - BaseModule, - check_sdk, - create_connection, - equal, - ovirt_full_argument_spec, - search_by_name, -) - - -class StorageConnectionModule(BaseModule): - - def build_entity(self): - return otypes.StorageConnection( - address=self.param('address'), - path=self.param('path'), - nfs_version=otypes.NfsVersion( - self.param('nfs_version') - ) if self.param('nfs_version') is not None else None, - nfs_timeo=self.param('nfs_timeout'), - nfs_retrans=self.param('nfs_retrans'), - mount_options=self.param('mount_options'), - password=self.param('password'), - username=self.param('username'), - port=self.param('port'), - target=self.param('target'), - type=otypes.StorageType( - self.param('type') - ) if self.param('type') is not None else None, - vfs_type=self.param('vfs_type'), - ) - - def _get_storage_domain_service(self): - sds_service = self._connection.system_service().storage_domains_service() - sd = search_by_name(sds_service, self.param('storage')) - if sd is None: - raise Exception( - "Storage '%s' was not found." % self.param('storage') - ) - return sd, sds_service.storage_domain_service(sd.id) - - def post_present(self, entity_id): - if self.param('storage'): - sd, sd_service = self._get_storage_domain_service() - if entity_id not in [ - sd_conn.id for sd_conn in self._connection.follow_link(sd.storage_connections) - ]: - scs_service = sd_service.storage_connections_service() - if not self._module.check_mode: - scs_service.add( - connection=otypes.StorageConnection( - id=entity_id, - ), - ) - self.changed = True - - def pre_remove(self, entity_id): - if self.param('storage'): - sd, sd_service = self._get_storage_domain_service() - if entity_id in [ - sd_conn.id for sd_conn in self._connection.follow_link(sd.storage_connections) - ]: - scs_service = sd_service.storage_connections_service() - sc_service = scs_service.connection_service(entity_id) - if not self._module.check_mode: - sc_service.remove() - self.changed = True - - def update_check(self, entity): - return ( - equal(self.param('address'), entity.address) and - equal(self.param('path'), entity.path) and - equal(self.param('nfs_version'), str(entity.nfs_version)) and - equal(self.param('nfs_timeout'), entity.nfs_timeo) and - equal(self.param('nfs_retrans'), entity.nfs_retrans) and - equal(self.param('mount_options'), entity.mount_options) and - equal(self.param('username'), entity.username) and - equal(self.param('port'), entity.port) and - equal(self.param('target'), entity.target) and - equal(self.param('type'), str(entity.type)) and - equal(self.param('vfs_type'), entity.vfs_type) - ) - - -def find_sc_by_attributes(module, storage_connections_service): - for sd_conn in [ - sc for sc in storage_connections_service.list() - if str(sc.type) == module.params['type'] - ]: - sd_conn_type = str(sd_conn.type) - if sd_conn_type in ['nfs', 'posixfs', 'glusterfs', 'localfs']: - if ( - module.params['address'] == sd_conn.address and - module.params['path'] == sd_conn.path - ): - return sd_conn - elif sd_conn_type in ['iscsi', 'fcp']: - if ( - module.params['address'] == sd_conn.address and - module.params['target'] == sd_conn.target - ): - return sd_conn - - -def main(): - argument_spec = ovirt_full_argument_spec( - state=dict( - choices=['present', 'absent'], - default='present', - ), - id=dict(default=None), - address=dict(default=None), - path=dict(default=None), - nfs_version=dict(default=None), - nfs_timeout=dict(default=None, type='int'), - nfs_retrans=dict(default=None, type='int'), - mount_options=dict(default=None), - password=dict(default=None, no_log=True), - username=dict(default=None), - port=dict(default=None, type='int'), - target=dict(default=None), - type=dict(default=None), - vfs_type=dict(default=None), - force=dict(type='bool', default=False), - storage=dict(default=None), - ) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - ) - - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - storage_connections_service = connection.system_service().storage_connections_service() - storage_connection_module = StorageConnectionModule( - connection=connection, - module=module, - service=storage_connections_service, - ) - entity = None - if module.params['id'] is None: - entity = find_sc_by_attributes(module, storage_connections_service) - - state = module.params['state'] - if state == 'present': - ret = storage_connection_module.create( - entity=entity, - update_params={'force': True}, - ) - storage_connection_module.post_present(ret['id']) - elif state == 'absent': - storage_connection_module.pre_remove(module.params['id']) - ret = storage_connection_module.remove(entity=entity) - - module.exit_json(**ret) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_storage_domain.py b/lib/ansible/modules/cloud/ovirt/ovirt_storage_domain.py deleted file mode 100644 index 26d5d12d0d..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_storage_domain.py +++ /dev/null @@ -1,809 +0,0 @@ -#!/usr/bin/python -# -*- 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 . -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_storage_domain -short_description: Module to manage storage domains in oVirt/RHV -version_added: "2.3" -author: "Ondra Machacek (@machacekondra)" -description: - - "Module to manage storage domains in oVirt/RHV" -options: - id: - description: - - "Id of the storage domain to be imported." - version_added: "2.4" - name: - description: - - "Name of the storage domain to manage. (Not required when state is I(imported))" - state: - description: - - "Should the storage domain be present/absent/maintenance/unattached/imported/update_ovf_store" - - "I(imported) is supported since version 2.4." - - "I(update_ovf_store) is supported since version 2.5, currently if C(wait) is (true), we don't wait for update." - choices: ['present', 'absent', 'maintenance', 'unattached', 'imported', 'update_ovf_store'] - default: present - description: - description: - - "Description of the storage domain." - comment: - description: - - "Comment of the storage domain." - data_center: - description: - - "Data center name where storage domain should be attached." - - "This parameter isn't idempotent, it's not possible to change data center of storage domain." - domain_function: - description: - - "Function of the storage domain." - - "This parameter isn't idempotent, it's not possible to change domain function of storage domain." - choices: ['data', 'iso', 'export'] - default: 'data' - aliases: ['type'] - host: - description: - - "Host to be used to mount storage." - localfs: - description: - - "Dictionary with values for localfs storage type:" - - "Note that these parameters are not idempotent." - suboptions: - path: - description: - - "Path of the mount point. E.g.: /path/to/my/data" - version_added: "2.4" - nfs: - description: - - "Dictionary with values for NFS storage type:" - - "Note that these parameters are not idempotent." - suboptions: - address: - description: - - "Address of the NFS server. E.g.: myserver.mydomain.com" - path: - description: - - "Path of the mount point. E.g.: /path/to/my/data" - version: - description: - - "NFS version. One of: I(auto), I(v3), I(v4) or I(v4_1)." - timeout: - description: - - "The time in tenths of a second to wait for a response before retrying NFS requests. Range 0 to 65535." - retrans: - description: - - "The number of times to retry a request before attempting further recovery actions. Range 0 to 65535." - mount_options: - description: - - "Option which will be passed when mounting storage." - iscsi: - description: - - "Dictionary with values for iSCSI storage type:" - - "Note that these parameters are not idempotent." - suboptions: - address: - description: - - Address of the iSCSI storage server. - port: - description: - - Port of the iSCSI storage server. - target: - description: - - The target IQN for the storage device. - lun_id: - description: - - LUN id(s). - username: - description: - - A CHAP user name for logging into a target. - password: - description: - - A CHAP password for logging into a target. - override_luns: - description: - - If I(True) ISCSI storage domain luns will be overridden before adding. - type: bool - target_lun_map: - description: - - List of dictionary containing targets and LUNs. - version_added: 2.5 - posixfs: - description: - - "Dictionary with values for PosixFS storage type:" - - "Note that these parameters are not idempotent." - suboptions: - path: - description: - - "Path of the mount point. E.g.: /path/to/my/data" - vfs_type: - description: - - Virtual File System type. - mount_options: - description: - - Option which will be passed when mounting storage. - glusterfs: - description: - - "Dictionary with values for GlusterFS storage type:" - - "Note that these parameters are not idempotent." - suboptions: - address: - description: - - "Address of the Gluster server. E.g.: myserver.mydomain.com" - path: - description: - - "Path of the mount point. E.g.: /path/to/my/data" - mount_options: - description: - - Option which will be passed when mounting storage. - managed_block_storage: - description: - - "Dictionary with values for managed block storage type" - - "Note: available from ovirt 4.3" - suboptions: - driver_options: - description: - - "The options to be passed when creating a storage domain using a cinder driver." - - "List of dictionary containing C(name) and C(value) of driver option" - driver_sensitive_options: - description: - - "Parameters containing sensitive information, to be passed when creating a storage domain using a cinder driver." - - "List of dictionary containing C(name) and C(value) of driver sensitive option" - version_added: "2.9" - fcp: - description: - - "Dictionary with values for fibre channel storage type:" - - "Note that these parameters are not idempotent." - suboptions: - lun_id: - description: - - LUN id. - override_luns: - description: - - If I(True) FCP storage domain LUNs will be overridden before adding. - type: bool - wipe_after_delete: - description: - - "Boolean flag which indicates whether the storage domain should wipe the data after delete." - type: bool - version_added: "2.5" - backup: - description: - - "Boolean flag which indicates whether the storage domain is configured as backup or not." - type: bool - version_added: "2.5" - critical_space_action_blocker: - description: - - "Indicates the minimal free space the storage domain should contain in percentages." - version_added: "2.5" - warning_low_space: - description: - - "Indicates the minimum percentage of a free space in a storage domain to present a warning." - version_added: "2.5" - destroy: - description: - - "Logical remove of the storage domain. If I(true) retains the storage domain's data for import." - - "This parameter is relevant only when C(state) is I(absent)." - type: bool - format: - description: - - "If I(True) storage domain will be formatted after removing it from oVirt/RHV." - - "This parameter is relevant only when C(state) is I(absent)." - type: bool - discard_after_delete: - description: - - "If I(True) storage domain blocks will be discarded upon deletion. Enabled by default." - - "This parameter is relevant only for block based storage domains." - type: bool - version_added: 2.5 -extends_documentation_fragment: ovirt -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Add data NFS storage domain -- ovirt_storage_domain: - name: data_nfs - host: myhost - data_center: mydatacenter - nfs: - address: 10.34.63.199 - path: /path/data - -# Add data NFS storage domain with id for data center -- ovirt_storage_domain: - name: data_nfs - host: myhost - data_center: 11111 - nfs: - address: 10.34.63.199 - path: /path/data - mount_options: noexec,nosuid - -# Add data localfs storage domain -- ovirt_storage_domain: - name: data_localfs - host: myhost - data_center: mydatacenter - localfs: - path: /path/to/data - -# Add data iSCSI storage domain: -- ovirt_storage_domain: - name: data_iscsi - host: myhost - data_center: mydatacenter - iscsi: - target: iqn.2016-08-09.domain-01:nickname - lun_id: - - 1IET_000d0001 - - 1IET_000d0002 - address: 10.34.63.204 - discard_after_delete: True - backup: False - critical_space_action_blocker: 5 - warning_low_space: 10 - -# Since Ansible 2.5 you can specify multiple targets for storage domain, -# Add data iSCSI storage domain with multiple targets: -- ovirt_storage_domain: - name: data_iscsi - host: myhost - data_center: mydatacenter - iscsi: - target_lun_map: - - target: iqn.2016-08-09.domain-01:nickname - lun_id: 1IET_000d0001 - - target: iqn.2016-08-09.domain-02:nickname - lun_id: 1IET_000d0002 - address: 10.34.63.204 - discard_after_delete: True - -# Add data glusterfs storage domain -- ovirt_storage_domain: - name: glusterfs_1 - host: myhost - data_center: mydatacenter - glusterfs: - address: 10.10.10.10 - path: /path/data - -# Create export NFS storage domain: -- ovirt_storage_domain: - name: myexportdomain - domain_function: export - host: myhost - data_center: mydatacenter - nfs: - address: 10.34.63.199 - path: /path/export - wipe_after_delete: False - backup: True - critical_space_action_blocker: 2 - warning_low_space: 5 - -# Import export NFS storage domain: -- ovirt_storage_domain: - state: imported - domain_function: export - host: myhost - data_center: mydatacenter - nfs: - address: 10.34.63.199 - path: /path/export - -# Import FCP storage domain: -- ovirt_storage_domain: - state: imported - name: data_fcp - host: myhost - data_center: mydatacenter - fcp: {} - -# Update OVF_STORE: -- ovirt_storage_domain: - state: update_ovf_store - name: domain - -# Create ISO NFS storage domain -- ovirt_storage_domain: - name: myiso - domain_function: iso - host: myhost - data_center: mydatacenter - nfs: - address: 10.34.63.199 - path: /path/iso - -# Create managed storage domain -# Available from ovirt 4.3 and ansible 2.9 -- ovirt_storage_domain: - name: my_managed_domain - host: myhost - data_center: mydatacenter - managed_block_storage: - driver_options: - - name: rbd_pool - value: pool1 - - name: rbd_user - value: admin - - name: volume_driver - value: cinder.volume.drivers.rbd.RBDDriver - - name: rbd_keyring_conf - value: /etc/ceph/keyring - driver_sensitive_options: - - name: secret_password - value: password - -# Remove storage domain -- ovirt_storage_domain: - state: absent - name: mystorage_domain - format: true -''' - -RETURN = ''' -id: - description: ID of the storage domain which is managed - returned: On success if storage domain is found. - type: str - sample: 7de90f31-222c-436c-a1ca-7e655bd5b60c -storage_domain: - description: "Dictionary of all the storage domain attributes. Storage domain attributes can be found on your oVirt/RHV instance - at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/storage_domain." - returned: On success if storage domain is found. - type: dict -''' - -try: - import ovirtsdk4.types as otypes - - from ovirtsdk4.types import StorageDomainStatus as sdstate - from ovirtsdk4.types import HostStatus as hoststate - from ovirtsdk4.types import DataCenterStatus as dcstatus -except ImportError: - pass - -import traceback - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - BaseModule, - check_sdk, - create_connection, - equal, - get_entity, - get_id_by_name, - OvirtRetry, - ovirt_full_argument_spec, - search_by_name, - search_by_attributes, - wait, -) - - -class StorageDomainModule(BaseModule): - - def _get_storage_type(self): - for sd_type in ['nfs', 'iscsi', 'posixfs', 'glusterfs', 'fcp', 'localfs', 'managed_block_storage']: - if self.param(sd_type) is not None: - return sd_type - - def _get_storage(self): - for sd_type in ['nfs', 'iscsi', 'posixfs', 'glusterfs', 'fcp', 'localfs', 'managed_block_storage']: - if self.param(sd_type) is not None: - return self.param(sd_type) - - def _login(self, storage_type, storage): - if storage_type == 'iscsi': - hosts_service = self._connection.system_service().hosts_service() - host_id = get_id_by_name(hosts_service, self.param('host')) - if storage.get('target'): - hosts_service.host_service(host_id).iscsi_login( - iscsi=otypes.IscsiDetails( - username=storage.get('username'), - password=storage.get('password'), - address=storage.get('address'), - target=storage.get('target'), - ), - ) - elif storage.get('target_lun_map'): - for target in [m['target'] for m in storage.get('target_lun_map')]: - hosts_service.host_service(host_id).iscsi_login( - iscsi=otypes.IscsiDetails( - username=storage.get('username'), - password=storage.get('password'), - address=storage.get('address'), - target=target, - ), - ) - - def __target_lun_map(self, storage): - if storage.get('target'): - lun_ids = storage.get('lun_id') if isinstance(storage.get('lun_id'), list) else [(storage.get('lun_id'))] - return [(lun_id, storage.get('target')) for lun_id in lun_ids] - elif storage.get('target_lun_map'): - return [(target_map.get('lun_id'), target_map.get('target')) for target_map in storage.get('target_lun_map')] - else: - lun_ids = storage.get('lun_id') if isinstance(storage.get('lun_id'), list) else [(storage.get('lun_id'))] - return [(lun_id, None) for lun_id in lun_ids] - - def build_entity(self): - storage_type = self._get_storage_type() - storage = self._get_storage() - self._login(storage_type, storage) - - return otypes.StorageDomain( - name=self.param('name'), - description=self.param('description'), - comment=self.param('comment'), - wipe_after_delete=self.param('wipe_after_delete'), - backup=self.param('backup'), - critical_space_action_blocker=self.param('critical_space_action_blocker'), - warning_low_space_indicator=self.param('warning_low_space'), - import_=True if self.param('state') == 'imported' else None, - id=self.param('id') if self.param('state') == 'imported' else None, - type=otypes.StorageDomainType(storage_type if storage_type == 'managed_block_storage' else self.param('domain_function')), - host=otypes.Host(name=self.param('host')), - discard_after_delete=self.param('discard_after_delete'), - storage=otypes.HostStorage( - driver_options=[ - otypes.Property( - name=do.get('name'), - value=do.get('value') - ) for do in storage.get('driver_options') - ] if storage.get('driver_options') else None, - driver_sensitive_options=[ - otypes.Property( - name=dso.get('name'), - value=dso.get('value') - ) for dso in storage.get('driver_sensitive_options') - ] if storage.get('driver_sensitive_options') else None, - type=otypes.StorageType(storage_type), - logical_units=[ - otypes.LogicalUnit( - id=lun_id, - address=storage.get('address'), - port=int(storage.get('port', 3260)), - target=target, - username=storage.get('username'), - password=storage.get('password'), - ) for lun_id, target in self.__target_lun_map(storage) - ] if storage_type in ['iscsi', 'fcp'] else None, - override_luns=storage.get('override_luns'), - mount_options=storage.get('mount_options'), - vfs_type=( - 'glusterfs' - if storage_type in ['glusterfs'] else storage.get('vfs_type') - ), - address=storage.get('address'), - path=storage.get('path'), - nfs_retrans=storage.get('retrans'), - nfs_timeo=storage.get('timeout'), - nfs_version=otypes.NfsVersion( - storage.get('version') - ) if storage.get('version') else None, - ) if storage_type is not None else None - ) - - def _find_attached_datacenter_name(self, sd_name): - """ - Finds the name of the datacenter that a given - storage domain is attached to. - - Args: - sd_name (str): Storage Domain name - - Returns: - str: Data Center name - - Raises: - Exception: In case storage domain in not attached to - an active Datacenter - """ - dcs_service = self._connection.system_service().data_centers_service() - dc = search_by_attributes(dcs_service, storage=sd_name) - if dc is None: - raise Exception( - "Can't bring storage to state `%s`, because it seems that" - "it is not attached to any datacenter" - % self.param('state') - ) - else: - if dc.status == dcstatus.UP: - return dc.name - else: - raise Exception( - "Can't bring storage to state `%s`, because Datacenter " - "%s is not UP" % (self.param('state'), dc.name) - ) - - def _attached_sds_service(self, dc_name): - # Get data center object of the storage domain: - dcs_service = self._connection.system_service().data_centers_service() - - # Search the data_center name, if it does not exist, try to search by guid. - dc = search_by_name(dcs_service, dc_name) - if dc is None: - dc = get_entity(dcs_service.service(dc_name)) - if dc is None: - return None - - dc_service = dcs_service.data_center_service(dc.id) - return dc_service.storage_domains_service() - - def _attached_sd_service(self, storage_domain): - dc_name = self.param('data_center') - if not dc_name: - # Find the DC, where the storage resides: - dc_name = self._find_attached_datacenter_name(storage_domain.name) - attached_sds_service = self._attached_sds_service(dc_name) - attached_sd_service = attached_sds_service.storage_domain_service(storage_domain.id) - return attached_sd_service - - def _maintenance(self, storage_domain): - attached_sd_service = self._attached_sd_service(storage_domain) - attached_sd = get_entity(attached_sd_service) - - if attached_sd and attached_sd.status != sdstate.MAINTENANCE: - if not self._module.check_mode: - attached_sd_service.deactivate() - self.changed = True - - wait( - service=attached_sd_service, - condition=lambda sd: sd.status == sdstate.MAINTENANCE, - wait=self.param('wait'), - timeout=self.param('timeout'), - ) - - def _unattach(self, storage_domain): - attached_sd_service = self._attached_sd_service(storage_domain) - attached_sd = get_entity(attached_sd_service) - - if attached_sd and attached_sd.status == sdstate.MAINTENANCE: - if not self._module.check_mode: - # Detach the storage domain: - attached_sd_service.remove() - self.changed = True - # Wait until storage domain is detached: - wait( - service=attached_sd_service, - condition=lambda sd: sd is None, - wait=self.param('wait'), - timeout=self.param('timeout'), - ) - - def pre_remove(self, storage_domain): - # In case the user chose to destroy the storage domain there is no need to - # move it to maintenance or detach it, it should simply be removed from the DB. - # Also if storage domain in already unattached skip this step. - if storage_domain.status == sdstate.UNATTACHED or self.param('destroy'): - return - # Before removing storage domain we need to put it into maintenance state: - self._maintenance(storage_domain) - - # Before removing storage domain we need to detach it from data center: - self._unattach(storage_domain) - - def post_create_check(self, sd_id): - storage_domain = self._service.service(sd_id).get() - dc_name = self.param('data_center') - if not dc_name: - # Find the DC, where the storage resides: - dc_name = self._find_attached_datacenter_name(storage_domain.name) - self._service = self._attached_sds_service(dc_name) - - # If storage domain isn't attached, attach it: - attached_sd_service = self._service.service(storage_domain.id) - if get_entity(attached_sd_service) is None: - self._service.add( - otypes.StorageDomain( - id=storage_domain.id, - ), - ) - self.changed = True - # Wait until storage domain is in maintenance: - wait( - service=attached_sd_service, - condition=lambda sd: sd.status == sdstate.ACTIVE, - wait=self.param('wait'), - timeout=self.param('timeout'), - ) - - def unattached_pre_action(self, storage_domain): - dc_name = self.param('data_center') - if not dc_name: - # Find the DC, where the storage resides: - dc_name = self._find_attached_datacenter_name(storage_domain.name) - self._service = self._attached_sds_service(dc_name) - self._maintenance(storage_domain) - - def update_check(self, entity): - return ( - equal(self.param('comment'), entity.comment) and - equal(self.param('description'), entity.description) and - equal(self.param('backup'), entity.backup) and - equal(self.param('critical_space_action_blocker'), entity.critical_space_action_blocker) and - equal(self.param('discard_after_delete'), entity.discard_after_delete) and - equal(self.param('wipe_after_delete'), entity.wipe_after_delete) and - equal(self.param('warning_low_space_indicator'), entity.warning_low_space_indicator) - ) - - -def failed_state(sd): - return sd.status in [sdstate.UNKNOWN, sdstate.INACTIVE] - - -def control_state(sd_module): - sd = sd_module.search_entity() - if sd is None: - return - - sd_service = sd_module._service.service(sd.id) - - # In the case of no status returned, it's an attached storage domain. - # Redetermine the corresponding service and entity: - if sd.status is None: - sd_service = sd_module._attached_sd_service(sd) - sd = get_entity(sd_service) - - if sd.status == sdstate.LOCKED: - wait( - service=sd_service, - condition=lambda sd: sd.status != sdstate.LOCKED, - fail_condition=failed_state, - ) - - if failed_state(sd): - raise Exception("Not possible to manage storage domain '%s'." % sd.name) - elif sd.status == sdstate.ACTIVATING: - wait( - service=sd_service, - condition=lambda sd: sd.status == sdstate.ACTIVE, - fail_condition=failed_state, - ) - elif sd.status == sdstate.DETACHING: - wait( - service=sd_service, - condition=lambda sd: sd.status == sdstate.UNATTACHED, - fail_condition=failed_state, - ) - elif sd.status == sdstate.PREPARING_FOR_MAINTENANCE: - wait( - service=sd_service, - condition=lambda sd: sd.status == sdstate.MAINTENANCE, - fail_condition=failed_state, - ) - - -def main(): - argument_spec = ovirt_full_argument_spec( - state=dict( - choices=['present', 'absent', 'maintenance', 'unattached', 'imported', 'update_ovf_store'], - default='present', - ), - id=dict(default=None), - name=dict(default=None), - description=dict(default=None), - comment=dict(default=None), - data_center=dict(default=None), - domain_function=dict(choices=['data', 'iso', 'export'], default='data', aliases=['type']), - host=dict(default=None), - localfs=dict(default=None, type='dict'), - nfs=dict(default=None, type='dict'), - iscsi=dict(default=None, type='dict'), - managed_block_storage=dict(default=None, type='dict', options=dict( - driver_options=dict(type='list'), - driver_sensitive_options=dict(type='list', no_log=True))), - posixfs=dict(default=None, type='dict'), - glusterfs=dict(default=None, type='dict'), - fcp=dict(default=None, type='dict'), - wipe_after_delete=dict(type='bool', default=None), - backup=dict(type='bool', default=None), - critical_space_action_blocker=dict(type='int', default=None), - warning_low_space=dict(type='int', default=None), - destroy=dict(type='bool', default=None), - format=dict(type='bool', default=None), - discard_after_delete=dict(type='bool', default=None) - ) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - ) - - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - storage_domains_service = connection.system_service().storage_domains_service() - storage_domains_module = StorageDomainModule( - connection=connection, - module=module, - service=storage_domains_service, - ) - - state = module.params['state'] - control_state(storage_domains_module) - if state == 'absent': - # Pick random available host when host parameter is missing - host_param = module.params['host'] - if not host_param: - host = search_by_attributes(connection.system_service().hosts_service(), status='up') - if host is None: - raise Exception( - "Not possible to remove storage domain '%s' " - "because no host found with status `up`." % module.params['name'] - ) - host_param = host.name - ret = storage_domains_module.remove( - destroy=module.params['destroy'], - format=module.params['format'], - host=host_param, - ) - elif state == 'present' or state == 'imported': - sd_id = storage_domains_module.create()['id'] - storage_domains_module.post_create_check(sd_id) - ret = storage_domains_module.action( - action='activate', - action_condition=lambda s: s.status == sdstate.MAINTENANCE, - wait_condition=lambda s: s.status == sdstate.ACTIVE, - fail_condition=failed_state, - search_params={'id': sd_id} if state == 'imported' else None - ) - elif state == 'maintenance': - sd_id = storage_domains_module.create()['id'] - storage_domains_module.post_create_check(sd_id) - - ret = OvirtRetry.backoff(tries=5, delay=1, backoff=2)( - storage_domains_module.action - )( - action='deactivate', - action_condition=lambda s: s.status == sdstate.ACTIVE, - wait_condition=lambda s: s.status == sdstate.MAINTENANCE, - fail_condition=failed_state, - ) - elif state == 'unattached': - ret = storage_domains_module.create() - storage_domains_module.pre_remove( - storage_domain=storage_domains_service.service(ret['id']).get() - ) - ret['changed'] = storage_domains_module.changed - elif state == 'update_ovf_store': - ret = storage_domains_module.action( - action='update_ovf_store' - ) - module.exit_json(**ret) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_storage_domain_info.py b/lib/ansible/modules/cloud/ovirt/ovirt_storage_domain_info.py deleted file mode 100644 index 6e446e30c2..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_storage_domain_info.py +++ /dev/null @@ -1,120 +0,0 @@ -#!/usr/bin/python -# -*- 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 . -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_storage_domain_info -short_description: Retrieve information about one or more oVirt/RHV storage domains -author: "Ondra Machacek (@machacekondra)" -version_added: "2.3" -description: - - "Retrieve information about one or more oVirt/RHV storage domains." - - This module was called C(ovirt_storage_domain_facts) before Ansible 2.9, returning C(ansible_facts). - Note that the M(ovirt_storage_domain_info) module no longer returns C(ansible_facts)! -notes: - - "This module returns a variable C(ovirt_storage_domains), which - contains a list of storage domains. You need to register the result with - the I(register) keyword to use it." -options: - pattern: - description: - - "Search term which is accepted by oVirt/RHV search backend." - - "For example to search storage domain X from datacenter Y use following pattern: - name=X and datacenter=Y" -extends_documentation_fragment: ovirt_info -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Gather information about all storage domains which names start with C(data) and -# belong to data center C(west): -- ovirt_storage_domain_info: - pattern: name=data* and datacenter=west - register: result -- debug: - msg: "{{ result.ovirt_storage_domains }}" -''' - -RETURN = ''' -ovirt_storage_domains: - description: "List of dictionaries describing the storage domains. Storage_domain attributes are mapped to dictionary keys, - all storage domains attributes can be found at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/storage_domain." - returned: On success. - type: list -''' - -import traceback - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - check_sdk, - create_connection, - get_dict_of_struct, - ovirt_info_full_argument_spec, -) - - -def main(): - argument_spec = ovirt_info_full_argument_spec( - pattern=dict(default='', required=False), - ) - module = AnsibleModule(argument_spec) - is_old_facts = module._name == 'ovirt_storage_domain_facts' - if is_old_facts: - module.deprecate("The 'ovirt_storage_domain_facts' module has been renamed to 'ovirt_storage_domain_info', " - "and the renamed one no longer returns ansible_facts", version='2.13') - - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - storage_domains_service = connection.system_service().storage_domains_service() - storage_domains = storage_domains_service.list(search=module.params['pattern']) - result = dict( - ovirt_storage_domains=[ - get_dict_of_struct( - struct=c, - connection=connection, - fetch_nested=module.params.get('fetch_nested'), - attributes=module.params.get('nested_attributes'), - ) for c in storage_domains - ], - ) - if is_old_facts: - module.exit_json(changed=False, ansible_facts=result) - else: - module.exit_json(changed=False, **result) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_storage_template_info.py b/lib/ansible/modules/cloud/ovirt/ovirt_storage_template_info.py deleted file mode 100644 index 5118e419d4..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_storage_template_info.py +++ /dev/null @@ -1,138 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (c) 2017 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 . -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_storage_template_info -short_description: Retrieve information about one or more oVirt/RHV templates relate to a storage domain. -author: "Maor Lipchuk (@machacekondra)" -version_added: "2.4" -description: - - "Retrieve information about one or more oVirt/RHV templates relate to a storage domain." - - This module was called C(ovirt_storage_template_facts) before Ansible 2.9, returning C(ansible_facts). - Note that the M(ovirt_storage_template_info) module no longer returns C(ansible_facts)! -notes: - - "This module returns a variable C(ovirt_storage_templates), which - contains a list of templates. You need to register the result with - the I(register) keyword to use it." -options: - unregistered: - description: - - "Flag which indicates whether to get unregistered templates which contain one or more - disks which reside on a storage domain or diskless templates." - type: bool - default: false - max: - description: - - "Sets the maximum number of templates to return. If not specified all the templates are returned." - storage_domain: - description: - - "The storage domain name where the templates should be listed." -extends_documentation_fragment: ovirt_info -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Gather information about all Templates which relate to a storage domain and -# are unregistered: -- ovirt_storage_template_info: - unregistered=True - register: result -- debug: - msg: "{{ result.ovirt_storage_templates }}" -''' - -RETURN = ''' -ovirt_storage_templates: - description: "List of dictionaries describing the Templates. Template attributes are mapped to dictionary keys, - all Templates attributes can be found at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/template." - returned: On success. - type: list -''' - -import traceback - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - check_sdk, - create_connection, - get_dict_of_struct, - ovirt_info_full_argument_spec, - get_id_by_name -) - - -def main(): - argument_spec = ovirt_info_full_argument_spec( - storage_domain=dict(default=None), - max=dict(default=None, type='int'), - unregistered=dict(default=False, type='bool'), - ) - module = AnsibleModule(argument_spec) - is_old_facts = module._name == 'ovirt_storage_template_facts' - if is_old_facts: - module.deprecate("The 'ovirt_storage_template_facts' module has been renamed to 'ovirt_storage_template_info', " - "and the renamed one no longer returns ansible_facts", version='2.13') - - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - storage_domains_service = connection.system_service().storage_domains_service() - sd_id = get_id_by_name(storage_domains_service, module.params['storage_domain']) - storage_domain_service = storage_domains_service.storage_domain_service(sd_id) - templates_service = storage_domain_service.templates_service() - - # Find the unregistered Template we want to register: - if module.params.get('unregistered'): - templates = templates_service.list(unregistered=True) - else: - templates = templates_service.list(max=module.params['max']) - result = dict( - ovirt_storage_templates=[ - get_dict_of_struct( - struct=c, - connection=connection, - fetch_nested=module.params.get('fetch_nested'), - attributes=module.params.get('nested_attributes'), - ) for c in templates - ], - ) - if is_old_facts: - module.exit_json(changed=False, ansible_facts=result) - else: - module.exit_json(changed=False, **result) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_storage_vm_info.py b/lib/ansible/modules/cloud/ovirt/ovirt_storage_vm_info.py deleted file mode 100644 index 99a5248451..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_storage_vm_info.py +++ /dev/null @@ -1,138 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (c) 2017 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 . -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_storage_vm_info -short_description: Retrieve information about one or more oVirt/RHV virtual machines relate to a storage domain. -author: "Maor Lipchuk (@machacekondra)" -version_added: "2.4" -description: - - "Retrieve information about one or more oVirt/RHV virtual machines relate to a storage domain." - - This module was called C(ovirt_storage_vm_facts) before Ansible 2.9, returning C(ansible_facts). - Note that the M(ovirt_storage_vm_info) module no longer returns C(ansible_facts)! -notes: - - "This module returns a variable C(ovirt_storage_vms), which - contains a list of virtual machines. You need to register the result with - the I(register) keyword to use it." -options: - unregistered: - description: - - "Flag which indicates whether to get unregistered virtual machines which contain one or more - disks which reside on a storage domain or diskless virtual machines." - type: bool - default: false - max: - description: - - "Sets the maximum number of virtual machines to return. If not specified all the virtual machines are returned." - storage_domain: - description: - - "The storage domain name where the virtual machines should be listed." -extends_documentation_fragment: ovirt_info -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Gather information about all VMs which relate to a storage domain and -# are unregistered: -- ovirt_vms_info: - unregistered=True - register: result -- debug: - msg: "{{ result.ovirt_storage_vms }}" -''' - -RETURN = ''' -ovirt_storage_vms: - description: "List of dictionaries describing the VMs. VM attributes are mapped to dictionary keys, - all VMs attributes can be found at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/vm." - returned: On success. - type: list -''' - -import traceback - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - check_sdk, - create_connection, - get_dict_of_struct, - ovirt_info_full_argument_spec, - get_id_by_name -) - - -def main(): - argument_spec = ovirt_info_full_argument_spec( - storage_domain=dict(default=None), - max=dict(default=None, type='int'), - unregistered=dict(default=False, type='bool'), - ) - module = AnsibleModule(argument_spec) - is_old_facts = module._name == 'ovirt_storage_vm_facts' - if is_old_facts: - module.deprecate("The 'ovirt_storage_vm_facts' module has been renamed to 'ovirt_storage_vm_info', " - "and the renamed one no longer returns ansible_facts", version='2.13') - - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - storage_domains_service = connection.system_service().storage_domains_service() - sd_id = get_id_by_name(storage_domains_service, module.params['storage_domain']) - storage_domain_service = storage_domains_service.storage_domain_service(sd_id) - vms_service = storage_domain_service.vms_service() - - # Find the unregistered VM we want to register: - if module.params.get('unregistered'): - vms = vms_service.list(unregistered=True) - else: - vms = vms_service.list() - result = dict( - ovirt_storage_vms=[ - get_dict_of_struct( - struct=c, - connection=connection, - fetch_nested=module.params.get('fetch_nested'), - attributes=module.params.get('nested_attributes'), - ) for c in vms - ], - ) - if is_old_facts: - module.exit_json(changed=False, ansible_facts=result) - else: - module.exit_json(changed=False, **result) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_tag.py b/lib/ansible/modules/cloud/ovirt/ovirt_tag.py deleted file mode 100644 index 65992d0121..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_tag.py +++ /dev/null @@ -1,257 +0,0 @@ -#!/usr/bin/python -# -*- 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 . -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_tag -short_description: Module to manage tags in oVirt/RHV -version_added: "2.3" -author: "Ondra Machacek (@machacekondra)" -description: - - "This module manage tags in oVirt/RHV. It can also manage assignments - of those tags to entities." -options: - id: - description: - - "ID of the tag to manage." - version_added: "2.8" - name: - description: - - "Name of the tag to manage." - required: true - state: - description: - - "Should the tag be present/absent/attached/detached." - - "C(Note): I(attached) and I(detached) states are supported since version 2.4." - choices: ['present', 'absent', 'attached', 'detached'] - default: present - description: - description: - - "Description of the tag to manage." - parent: - description: - - "Name of the parent tag." - vms: - description: - - "List of the VMs names, which should have assigned this tag." - hosts: - description: - - "List of the hosts names, which should have assigned this tag." -extends_documentation_fragment: ovirt -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Create(if not exists) and assign tag to vms vm1 and vm2: -- ovirt_tag: - name: mytag - vms: - - vm1 - - vm2 - -# Attach a tag to VM 'vm3', keeping the rest already attached tags on VM: -- ovirt_tag: - name: mytag - state: attached - vms: - - vm3 - -# Detach a tag from VM 'vm3', keeping the rest already attached tags on VM: -- ovirt_tag: - name: mytag - state: detached - vms: - - vm3 - -# To detach all VMs from tag: -- ovirt_tag: - name: mytag - vms: [] - -# Remove tag -- ovirt_tag: - state: absent - name: mytag - -# Change Tag Name -- ovirt_tag: - id: 00000000-0000-0000-0000-000000000000 - name: "new_tag_name" -''' - -RETURN = ''' -id: - description: ID of the tag which is managed - returned: On success if tag is found. - type: str - sample: 7de90f31-222c-436c-a1ca-7e655bd5b60c -tag: - description: "Dictionary of all the tag attributes. Tag attributes can be found on your oVirt/RHV instance - at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/tag." - returned: On success if tag is found. - type: dict -''' - -import traceback - -try: - import ovirtsdk4.types as otypes -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - BaseModule, - check_sdk, - create_connection, - equal, - get_id_by_name, - ovirt_full_argument_spec, -) - - -class TagsModule(BaseModule): - - def build_entity(self): - return otypes.Tag( - id=self._module.params['id'], - name=self._module.params['name'], - description=self._module.params['description'], - parent=otypes.Tag( - name=self._module.params['parent'], - ) if self._module.params['parent'] else None, - ) - - def post_create(self, entity): - self.update_check(entity) - - def _update_tag_assignments(self, entity, name): - if self._module.params[name] is None: - return - - state = self.param('state') - entities_service = getattr(self._connection.system_service(), '%s_service' % name)() - current_vms = [ - vm.name - for vm in entities_service.list(search='tag=%s' % self._module.params['name']) - ] - # Assign tags: - if state in ['present', 'attached', 'detached']: - for entity_name in self._module.params[name]: - entity_id = get_id_by_name(entities_service, entity_name) - tags_service = entities_service.service(entity_id).tags_service() - current_tags = [tag.name for tag in tags_service.list()] - # Assign the tag: - if state in ['attached', 'present']: - if self._module.params['name'] not in current_tags: - if not self._module.check_mode: - tags_service.add( - tag=otypes.Tag( - name=self._module.params['name'], - ), - ) - self.changed = True - # Detach the tag: - elif state == 'detached': - if self._module.params['name'] in current_tags: - tag_id = get_id_by_name(tags_service, self.param('name')) - if not self._module.check_mode: - tags_service.tag_service(tag_id).remove() - self.changed = True - - # Unassign tags: - if state == 'present': - for entity_name in [e for e in current_vms if e not in self._module.params[name]]: - if not self._module.check_mode: - entity_id = get_id_by_name(entities_service, entity_name) - tags_service = entities_service.service(entity_id).tags_service() - tag_id = get_id_by_name(tags_service, self.param('name')) - tags_service.tag_service(tag_id).remove() - self.changed = True - - def _get_parent(self, entity): - parent = None - if entity.parent: - parent = self._connection.follow_link(entity.parent).name - return parent - - def update_check(self, entity): - self._update_tag_assignments(entity, 'vms') - self._update_tag_assignments(entity, 'hosts') - return ( - equal(self._module.params.get('description'), entity.description) and - equal(self._module.params.get('name'), entity.name) and - equal(self._module.params.get('parent'), self._get_parent(entity)) - ) - - -def main(): - argument_spec = ovirt_full_argument_spec( - state=dict( - choices=['present', 'absent', 'attached', 'detached'], - default='present', - ), - id=dict(default=None), - name=dict(required=True), - description=dict(default=None), - parent=dict(default=None), - vms=dict(default=None, type='list'), - hosts=dict(default=None, type='list'), - ) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - ) - - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - tags_service = connection.system_service().tags_service() - tags_module = TagsModule( - connection=connection, - module=module, - service=tags_service, - ) - - state = module.params['state'] - if state in ['present', 'attached', 'detached']: - ret = tags_module.create() - elif state == 'absent': - ret = tags_module.remove() - - module.exit_json(**ret) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_tag_info.py b/lib/ansible/modules/cloud/ovirt/ovirt_tag_info.py deleted file mode 100644 index 1ef257b13d..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_tag_info.py +++ /dev/null @@ -1,167 +0,0 @@ -#!/usr/bin/python -# -*- 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 . -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_tag_info -short_description: Retrieve information about one or more oVirt/RHV tags -author: "Ondra Machacek (@machacekondra)" -version_added: "2.3" -description: - - "Retrieve information about one or more oVirt/RHV tags." - - This module was called C(ovirt_tag_facts) before Ansible 2.9, returning C(ansible_facts). - Note that the M(ovirt_tag_info) module no longer returns C(ansible_facts)! -notes: - - "This module returns a variable C(ovirt_tags), which - contains a list of tags. You need to register the result with - the I(register) keyword to use it." -options: - name: - description: - - "Name of the tag which should be listed." - vm: - description: - - "Name of the VM, which tags should be listed." - host: - description: - - "Name of the host, which tags should be listed." -extends_documentation_fragment: ovirt_info -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Gather information about all tags, which names start with C(tag): -- ovirt_tag_info: - name: tag* - register: result -- debug: - msg: "{{ result.ovirt_tags }}" - -# Gather information about all tags, which are assigned to VM C(postgres): -- ovirt_tag_info: - vm: postgres - register: result -- debug: - msg: "{{ result.ovirt_tags }}" - -# Gather information about all tags, which are assigned to host C(west): -- ovirt_tag_info: - host: west - register: result -- debug: - msg: "{{ result.ovirt_tags }}" -''' - -RETURN = ''' -ovirt_tags: - description: "List of dictionaries describing the tags. Tags attributes are mapped to dictionary keys, - all tags attributes can be found at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/tag." - returned: On success. - type: list -''' - -import fnmatch -import traceback - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - check_sdk, - create_connection, - get_dict_of_struct, - ovirt_info_full_argument_spec, - search_by_name, -) - - -def main(): - argument_spec = ovirt_info_full_argument_spec( - name=dict(default=None), - host=dict(default=None), - vm=dict(default=None), - ) - module = AnsibleModule(argument_spec) - is_old_facts = module._name == 'ovirt_tag_facts' - if is_old_facts: - module.deprecate("The 'ovirt_tag_facts' module has been renamed to 'ovirt_tag_info', " - "and the renamed one no longer returns ansible_facts", version='2.13') - - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - tags_service = connection.system_service().tags_service() - tags = [] - all_tags = tags_service.list() - if module.params['name']: - tags.extend([ - t for t in all_tags - if fnmatch.fnmatch(t.name, module.params['name']) - ]) - if module.params['host']: - hosts_service = connection.system_service().hosts_service() - host = search_by_name(hosts_service, module.params['host']) - if host is None: - raise Exception("Host '%s' was not found." % module.params['host']) - tags.extend([ - tag for tag in hosts_service.host_service(host.id).tags_service().list() - ]) - if module.params['vm']: - vms_service = connection.system_service().vms_service() - vm = search_by_name(vms_service, module.params['vm']) - if vm is None: - raise Exception("Vm '%s' was not found." % module.params['vm']) - tags.extend([ - tag for tag in vms_service.vm_service(vm.id).tags_service().list() - ]) - - if not (module.params['vm'] or module.params['host'] or module.params['name']): - tags = all_tags - - result = dict( - ovirt_tags=[ - get_dict_of_struct( - struct=t, - connection=connection, - fetch_nested=module.params['fetch_nested'], - attributes=module.params['nested_attributes'], - ) for t in tags - ], - ) - if is_old_facts: - module.exit_json(changed=False, ansible_facts=result) - else: - module.exit_json(changed=False, **result) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_template.py b/lib/ansible/modules/cloud/ovirt/ovirt_template.py deleted file mode 100644 index eb62b316fa..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_template.py +++ /dev/null @@ -1,1087 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (c) 2016 Red Hat, Inc. -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_template -short_description: Module to manage virtual machine templates in oVirt/RHV -version_added: "2.3" -author: "Ondra Machacek (@machacekondra)" -description: - - "Module to manage virtual machine templates in oVirt/RHV." -options: - name: - description: - - "Name of the template to manage." - id: - description: - - "ID of the template to be registered." - version_added: "2.4" - state: - description: - - "Should the template be present/absent/exported/imported/registered. - When C(state) is I(registered) and the unregistered template's name - belongs to an already registered in engine template in the same DC - then we fail to register the unregistered template." - choices: ['present', 'absent', 'exported', 'imported', 'registered'] - default: present - vm: - description: - - "Name of the VM, which will be used to create template." - description: - description: - - "Description of the template." - cpu_profile: - description: - - "CPU profile to be set to template." - cluster: - description: - - "Name of the cluster, where template should be created/imported." - allow_partial_import: - description: - - "Boolean indication whether to allow partial registration of a template when C(state) is registered." - type: bool - version_added: "2.4" - vnic_profile_mappings: - description: - - "Mapper which maps an external virtual NIC profile to one that exists in the engine when C(state) is registered. - vnic_profile is described by the following dictionary:" - suboptions: - source_network_name: - description: - - The network name of the source network. - source_profile_name: - description: - - The profile name related to the source network. - target_profile_id: - description: - - The id of the target profile id to be mapped to in the engine. - version_added: "2.5" - cluster_mappings: - description: - - "Mapper which maps cluster name between Template's OVF and the destination cluster this Template should be registered to, - relevant when C(state) is registered. - Cluster mapping is described by the following dictionary:" - suboptions: - source_name: - description: - - The name of the source cluster. - dest_name: - description: - - The name of the destination cluster. - version_added: "2.5" - role_mappings: - description: - - "Mapper which maps role name between Template's OVF and the destination role this Template should be registered to, - relevant when C(state) is registered. - Role mapping is described by the following dictionary:" - suboptions: - source_name: - description: - - The name of the source role. - dest_name: - description: - - The name of the destination role. - version_added: "2.5" - domain_mappings: - description: - - "Mapper which maps aaa domain name between Template's OVF and the destination aaa domain this Template should be registered to, - relevant when C(state) is registered. - The aaa domain mapping is described by the following dictionary:" - suboptions: - source_name: - description: - - The name of the source aaa domain. - dest_name: - description: - - The name of the destination aaa domain. - version_added: "2.5" - exclusive: - description: - - "When C(state) is I(exported) this parameter indicates if the existing templates with the - same name should be overwritten." - type: bool - export_domain: - description: - - "When C(state) is I(exported) or I(imported) this parameter specifies the name of the - export storage domain." - image_provider: - description: - - "When C(state) is I(imported) this parameter specifies the name of the image provider to be used." - image_disk: - description: - - "When C(state) is I(imported) and C(image_provider) is used this parameter specifies the name of disk - to be imported as template." - aliases: ['glance_image_disk_name'] - io_threads: - description: - - "Number of IO threads used by virtual machine. I(0) means IO threading disabled." - version_added: "2.7" - template_image_disk_name: - description: - - "When C(state) is I(imported) and C(image_provider) is used this parameter specifies the new name for imported disk, - if omitted then I(image_disk) name is used by default. - This parameter is used only in case of importing disk image from Glance domain." - version_added: "2.4" - storage_domain: - description: - - "When C(state) is I(imported) this parameter specifies the name of the destination data storage domain. - When C(state) is I(registered) this parameter specifies the name of the data storage domain of the unregistered template." - clone_permissions: - description: - - "If I(True) then the permissions of the VM (only the direct ones, not the inherited ones) - will be copied to the created template." - - "This parameter is used only when C(state) I(present)." - type: bool - default: False - seal: - description: - - "'Sealing' is an operation that erases all machine-specific configurations from a filesystem: - This includes SSH keys, UDEV rules, MAC addresses, system ID, hostname, etc. - If I(true) subsequent virtual machines made from this template will avoid configuration inheritance." - - "This parameter is used only when C(state) I(present)." - default: False - type: bool - version_added: "2.5" - operating_system: - description: - - Operating system of the template. - - Default value is set by oVirt/RHV engine. - - "Possible values are: debian_7, freebsd, freebsdx64, other, other_linux, - other_linux_ppc64, other_ppc64, rhel_3, rhel_4, rhel_4x64, rhel_5, rhel_5x64, - rhel_6, rhel_6x64, rhel_6_ppc64, rhel_7x64, rhel_7_ppc64, sles_11, - sles_11_ppc64, ubuntu_12_04, ubuntu_12_10, ubuntu_13_04, ubuntu_13_10, - ubuntu_14_04, ubuntu_14_04_ppc64, windows_10, windows_10x64, windows_2003, - windows_2003x64, windows_2008, windows_2008x64, windows_2008r2x64, - windows_2008R2x64, windows_2012x64, windows_2012R2x64, - windows_7, windows_7x64, windows_8, windows_8x64, windows_xp" - version_added: "2.6" - memory: - description: - - Amount of memory of the template. Prefix uses IEC 60027-2 standard (for example 1GiB, 1024MiB). - version_added: "2.6" - memory_guaranteed: - description: - - Amount of minimal guaranteed memory of the template. - Prefix uses IEC 60027-2 standard (for example 1GiB, 1024MiB). - - C(memory_guaranteed) parameter can't be lower than C(memory) parameter. - version_added: "2.6" - memory_max: - description: - - Upper bound of template memory up to which memory hot-plug can be performed. - Prefix uses IEC 60027-2 standard (for example 1GiB, 1024MiB). - version_added: "2.6" - version: - description: - - "C(name) - The name of this version." - - "C(number) - The index of this version in the versions hierarchy of the template. Used for editing of sub template." - version_added: "2.8" - clone_name: - description: - - Name for importing Template from storage domain. - - If not defined, C(name) will be used. - version_added: "2.8" - usb_support: - description: - - "I(True) enable USB support, I(False) to disable it. By default is chosen by oVirt/RHV engine." - type: bool - version_added: "2.9" - timezone: - description: - - Sets time zone offset of the guest hardware clock. - - For example C(Etc/GMT) - version_added: "2.9" - sso: - description: - - "I(True) enable Single Sign On by Guest Agent, I(False) to disable it. By default is chosen by oVirt/RHV engine." - type: bool - version_added: "2.9" - soundcard_enabled: - description: - - "If I(true), the sound card is added to the virtual machine." - type: bool - version_added: "2.9" - smartcard_enabled: - description: - - "If I(true), use smart card authentication." - type: bool - version_added: "2.9" - cloud_init: - description: - - Dictionary with values for Unix-like Virtual Machine initialization using cloud init. - suboptions: - host_name: - description: - - Hostname to be set to Virtual Machine when deployed. - timezone: - description: - - Timezone to be set to Virtual Machine when deployed. - user_name: - description: - - Username to be used to set password to Virtual Machine when deployed. - root_password: - description: - - Password to be set for user specified by C(user_name) parameter. - authorized_ssh_keys: - description: - - Use this SSH keys to login to Virtual Machine. - regenerate_ssh_keys: - description: - - If I(True) SSH keys will be regenerated on Virtual Machine. - type: bool - custom_script: - description: - - Cloud-init script which will be executed on Virtual Machine when deployed. - - This is appended to the end of the cloud-init script generated by any other options. - dns_servers: - description: - - DNS servers to be configured on Virtual Machine. - dns_search: - description: - - DNS search domains to be configured on Virtual Machine. - nic_boot_protocol: - description: - - Set boot protocol of the network interface of Virtual Machine. - choices: ['none', 'dhcp', 'static'] - nic_ip_address: - description: - - If boot protocol is static, set this IP address to network interface of Virtual Machine. - nic_netmask: - description: - - If boot protocol is static, set this netmask to network interface of Virtual Machine. - nic_gateway: - description: - - If boot protocol is static, set this gateway to network interface of Virtual Machine. - nic_name: - description: - - Set name to network interface of Virtual Machine. - nic_on_boot: - description: - - If I(True) network interface will be set to start on boot. - type: bool - version_added: "2.9" - cloud_init_nics: - description: - - List of dictionaries representing network interfaces to be setup by cloud init. - - This option is used, when user needs to setup more network interfaces via cloud init. - - If one network interface is enough, user should use C(cloud_init) I(nic_*) parameters. C(cloud_init) I(nic_*) parameters - are merged with C(cloud_init_nics) parameters. - suboptions: - nic_boot_protocol: - description: - - Set boot protocol of the network interface of Virtual Machine. Can be one of C(none), C(dhcp) or C(static). - nic_ip_address: - description: - - If boot protocol is static, set this IP address to network interface of Virtual Machine. - nic_netmask: - description: - - If boot protocol is static, set this netmask to network interface of Virtual Machine. - nic_gateway: - description: - - If boot protocol is static, set this gateway to network interface of Virtual Machine. - nic_name: - description: - - Set name to network interface of Virtual Machine. - nic_on_boot: - description: - - If I(True) network interface will be set to start on boot. - type: bool - version_added: "2.9" - ballooning_enabled: - description: - - "If I(true), use memory ballooning." - - "Memory balloon is a guest device, which may be used to re-distribute / reclaim the host memory - based on VM needs in a dynamic way. In this way it's possible to create memory over commitment states." - type: bool - version_added: "2.9" - nics: - description: - - List of NICs, which should be attached to Virtual Machine. NIC is described by following dictionary. - suboptions: - name: - description: - - Name of the NIC. - profile_name: - description: - - Profile name where NIC should be attached. - interface: - description: - - Type of the network interface. - choices: ['virtio', 'e1000', 'rtl8139'] - default: 'virtio' - mac_address: - description: - - Custom MAC address of the network interface, by default it's obtained from MAC pool. - version_added: "2.9" - sysprep: - description: - - Dictionary with values for Windows Virtual Machine initialization using sysprep. - suboptions: - host_name: - description: - - Hostname to be set to Virtual Machine when deployed. - active_directory_ou: - description: - - Active Directory Organizational Unit, to be used for login of user. - org_name: - description: - - Organization name to be set to Windows Virtual Machine. - domain: - description: - - Domain to be set to Windows Virtual Machine. - timezone: - description: - - Timezone to be set to Windows Virtual Machine. - ui_language: - description: - - UI language of the Windows Virtual Machine. - system_locale: - description: - - System localization of the Windows Virtual Machine. - input_locale: - description: - - Input localization of the Windows Virtual Machine. - windows_license_key: - description: - - License key to be set to Windows Virtual Machine. - user_name: - description: - - Username to be used for set password to Windows Virtual Machine. - root_password: - description: - - Password to be set for username to Windows Virtual Machine. - version_added: "2.9" -extends_documentation_fragment: ovirt -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Create template from vm -- ovirt_template: - cluster: Default - name: mytemplate - vm: rhel7 - cpu_profile: Default - description: Test - -# Import template -- ovirt_template: - state: imported - name: mytemplate - export_domain: myexport - storage_domain: mystorage - cluster: mycluster - -# Remove template -- ovirt_template: - state: absent - name: mytemplate - -# Change Template Name -- ovirt_template: - id: 00000000-0000-0000-0000-000000000000 - name: "new_template_name" - -# Register template -- ovirt_template: - state: registered - storage_domain: mystorage - cluster: mycluster - name: mytemplate - -# Register template using id -- ovirt_template: - state: registered - storage_domain: mystorage - cluster: mycluster - id: 1111-1111-1111-1111 - -# Register template, allowing partial import -- ovirt_template: - state: registered - storage_domain: mystorage - allow_partial_import: "True" - cluster: mycluster - id: 1111-1111-1111-1111 - -# Register template with vnic profile mappings -- ovirt_template: - state: registered - storage_domain: mystorage - cluster: mycluster - id: 1111-1111-1111-1111 - vnic_profile_mappings: - - source_network_name: mynetwork - source_profile_name: mynetwork - target_profile_id: 3333-3333-3333-3333 - - source_network_name: mynetwork2 - source_profile_name: mynetwork2 - target_profile_id: 4444-4444-4444-4444 - -# Register template with mapping -- ovirt_template: - state: registered - storage_domain: mystorage - cluster: mycluster - id: 1111-1111-1111-1111 - role_mappings: - - source_name: Role_A - dest_name: Role_B - domain_mappings: - - source_name: Domain_A - dest_name: Domain_B - cluster_mappings: - - source_name: cluster_A - dest_name: cluster_B - -# Import image from Glance s a template -- ovirt_template: - state: imported - name: mytemplate - image_disk: "centos7" - template_image_disk_name: centos7_from_glance - image_provider: "glance_domain" - storage_domain: mystorage - cluster: mycluster - -# Edit template subversion -- ovirt_template: - cluster: mycluster - name: mytemplate - vm: rhel7 - version: - number: 2 - name: subversion - -# Create new template subversion -- ovirt_template: - cluster: mycluster - name: mytemplate - vm: rhel7 - version: - name: subversion - -- name: Template with cloud init - ovirt_template: - name: mytemplate - cluster: Default - memory: 1GiB - cloud_init: - nic_boot_protocol: static - nic_ip_address: 10.34.60.86 - nic_netmask: 255.255.252.0 - nic_gateway: 10.34.63.254 - nic_name: eth1 - nic_on_boot: true - host_name: example.com - custom_script: | - write_files: - - content: | - Hello, world! - path: /tmp/greeting.txt - permissions: '0644' - user_name: root - root_password: super_password - -- name: Template with cloud init, with multiple network interfaces - ovirt_template: - name: mytemplate - cluster: mycluster - cloud_init_nics: - - nic_name: eth0 - nic_boot_protocol: dhcp - nic_on_boot: true - - nic_name: eth1 - nic_boot_protocol: static - nic_ip_address: 10.34.60.86 - nic_netmask: 255.255.252.0 - nic_gateway: 10.34.63.254 - nic_on_boot: true - -- name: Template with timezone and nic - ovirt_template: - cluster: MyCluster - name: mytemplate - timezone: America/Godthab - memory_max: 2Gib - nics: - - name: nic1 - -- name: Template with sysprep - ovirt_vm: - name: windows2012R2_AD - cluster: Default - memory: 3GiB - sysprep: - host_name: windowsad.example.com - user_name: Administrator - root_password: SuperPassword123 -''' - -RETURN = ''' -id: - description: ID of the template which is managed - returned: On success if template is found. - type: str - sample: 7de90f31-222c-436c-a1ca-7e655bd5b60c -template: - description: "Dictionary of all the template attributes. Template attributes can be found on your oVirt/RHV instance - at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/template." - returned: On success if template is found. - type: dict -''' - -import time -import traceback - -try: - import ovirtsdk4.types as otypes -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - BaseModule, - check_sdk, - convert_to_bytes, - create_connection, - equal, - get_dict_of_struct, - get_link_name, - get_id_by_name, - ovirt_full_argument_spec, - search_by_attributes, - search_by_name, -) - - -class TemplatesModule(BaseModule): - - def __init__(self, *args, **kwargs): - super(TemplatesModule, self).__init__(*args, **kwargs) - self._initialization = None - - def build_entity(self): - return otypes.Template( - id=self._module.params['id'], - name=self._module.params['name'], - cluster=otypes.Cluster( - name=self._module.params['cluster'] - ) if self._module.params['cluster'] else None, - vm=otypes.Vm( - name=self._module.params['vm'] - ) if self._module.params['vm'] else None, - description=self._module.params['description'], - cpu_profile=otypes.CpuProfile( - id=search_by_name( - self._connection.system_service().cpu_profiles_service(), - self._module.params['cpu_profile'], - ).id - ) if self._module.params['cpu_profile'] else None, - display=otypes.Display( - smartcard_enabled=self.param('smartcard_enabled') - ) if self.param('smartcard_enabled') is not None else None, - os=otypes.OperatingSystem( - type=self.param('operating_system'), - ) if self.param('operating_system') else None, - memory=convert_to_bytes( - self.param('memory') - ) if self.param('memory') else None, - soundcard_enabled=self.param('soundcard_enabled'), - usb=( - otypes.Usb(enabled=self.param('usb_support')) - ) if self.param('usb_support') is not None else None, - sso=( - otypes.Sso( - methods=[otypes.Method(id=otypes.SsoMethod.GUEST_AGENT)] if self.param('sso') else [] - ) - ) if self.param('sso') is not None else None, - time_zone=otypes.TimeZone( - name=self.param('timezone'), - ) if self.param('timezone') else None, - version=otypes.TemplateVersion( - base_template=self._get_base_template(), - version_name=self.param('version').get('name'), - ) if self.param('version') else None, - memory_policy=otypes.MemoryPolicy( - guaranteed=convert_to_bytes(self.param('memory_guaranteed')), - ballooning=self.param('ballooning_enabled'), - max=convert_to_bytes(self.param('memory_max')), - ) if any(( - self.param('memory_guaranteed'), - self.param('ballooning_enabled'), - self.param('memory_max') - )) else None, - io=otypes.Io( - threads=self.param('io_threads'), - ) if self.param('io_threads') is not None else None, - initialization=self.get_initialization(), - ) - - def _get_base_template(self): - templates = self._connection.system_service().templates_service().list() - for template in templates: - if template.version.version_number == 1 and template.name == self.param('name'): - return otypes.Template( - id=template.id - ) - - def post_update(self, entity): - self.post_present(entity.id) - - def post_present(self, entity_id): - # After creation of the VM, attach disks and NICs: - entity = self._service.service(entity_id).get() - self.__attach_nics(entity) - - def __get_vnic_profile_id(self, nic): - """ - Return VNIC profile ID looked up by it's name, because there can be - more VNIC profiles with same name, other criteria of filter is cluster. - """ - vnics_service = self._connection.system_service().vnic_profiles_service() - clusters_service = self._connection.system_service().clusters_service() - cluster = search_by_name(clusters_service, self.param('cluster')) - profiles = [ - profile for profile in vnics_service.list() - if profile.name == nic.get('profile_name') - ] - cluster_networks = [ - net.id for net in self._connection.follow_link(cluster.networks) - ] - try: - return next( - profile.id for profile in profiles - if profile.network.id in cluster_networks - ) - except StopIteration: - raise Exception( - "Profile '%s' was not found in cluster '%s'" % ( - nic.get('profile_name'), - self.param('cluster') - ) - ) - - def __attach_nics(self, entity): - # Attach NICs to VM, if specified: - nics_service = self._service.service(entity.id).nics_service() - for nic in self.param('nics'): - if search_by_name(nics_service, nic.get('name')) is None: - if not self._module.check_mode: - nics_service.add( - otypes.Nic( - name=nic.get('name'), - interface=otypes.NicInterface( - nic.get('interface', 'virtio') - ), - vnic_profile=otypes.VnicProfile( - id=self.__get_vnic_profile_id(nic), - ) if nic.get('profile_name') else None, - mac=otypes.Mac( - address=nic.get('mac_address') - ) if nic.get('mac_address') else None, - ) - ) - self.changed = True - - def get_initialization(self): - if self._initialization is not None: - return self._initialization - - sysprep = self.param('sysprep') - cloud_init = self.param('cloud_init') - cloud_init_nics = self.param('cloud_init_nics') or [] - if cloud_init is not None: - cloud_init_nics.append(cloud_init) - - if cloud_init or cloud_init_nics: - self._initialization = otypes.Initialization( - nic_configurations=[ - otypes.NicConfiguration( - boot_protocol=otypes.BootProtocol( - nic.pop('nic_boot_protocol').lower() - ) if nic.get('nic_boot_protocol') else None, - name=nic.pop('nic_name', None), - on_boot=nic.pop('nic_on_boot', None), - ip=otypes.Ip( - address=nic.pop('nic_ip_address', None), - netmask=nic.pop('nic_netmask', None), - gateway=nic.pop('nic_gateway', None), - ) if ( - nic.get('nic_gateway') is not None or - nic.get('nic_netmask') is not None or - nic.get('nic_ip_address') is not None - ) else None, - ) - for nic in cloud_init_nics - if ( - nic.get('nic_gateway') is not None or - nic.get('nic_netmask') is not None or - nic.get('nic_ip_address') is not None or - nic.get('nic_boot_protocol') is not None or - nic.get('nic_on_boot') is not None - ) - ] if cloud_init_nics else None, - **cloud_init - ) - elif sysprep: - self._initialization = otypes.Initialization( - **sysprep - ) - return self._initialization - - def update_check(self, entity): - template_display = entity.display - return ( - equal(self._module.params.get('cluster'), get_link_name(self._connection, entity.cluster)) and - equal(self._module.params.get('description'), entity.description) and - equal(self.param('operating_system'), str(entity.os.type)) and - equal(self.param('name'), str(entity.name)) and - equal(self.param('smartcard_enabled'), getattr(template_display, 'smartcard_enabled', False)) and - equal(self.param('soundcard_enabled'), entity.soundcard_enabled) and - equal(self.param('ballooning_enabled'), entity.memory_policy.ballooning) and - equal(self.param('sso'), True if entity.sso.methods else False) and - equal(self.param('timezone'), getattr(entity.time_zone, 'name', None)) and - equal(self.param('usb_support'), entity.usb.enabled) and - equal(convert_to_bytes(self.param('memory_guaranteed')), entity.memory_policy.guaranteed) and - equal(convert_to_bytes(self.param('memory_max')), entity.memory_policy.max) and - equal(convert_to_bytes(self.param('memory')), entity.memory) and - equal(self._module.params.get('cpu_profile'), get_link_name(self._connection, entity.cpu_profile)) and - equal(self.param('io_threads'), entity.io.threads) - ) - - def _get_export_domain_service(self): - provider_name = self._module.params['export_domain'] or self._module.params['image_provider'] - export_sds_service = self._connection.system_service().storage_domains_service() - export_sd = search_by_name(export_sds_service, provider_name) - if export_sd is None: - raise ValueError( - "Export storage domain/Image Provider '%s' wasn't found." % provider_name - ) - - return export_sds_service.service(export_sd.id) - - def post_export_action(self, entity): - self._service = self._get_export_domain_service().templates_service() - - def post_import_action(self, entity): - self._service = self._connection.system_service().templates_service() - - -def _get_role_mappings(module): - roleMappings = list() - - for roleMapping in module.params['role_mappings']: - roleMappings.append( - otypes.RegistrationRoleMapping( - from_=otypes.Role( - name=roleMapping['source_name'], - ) if roleMapping['source_name'] else None, - to=otypes.Role( - name=roleMapping['dest_name'], - ) if roleMapping['dest_name'] else None, - ) - ) - return roleMappings - - -def _get_domain_mappings(module): - domainMappings = list() - - for domainMapping in module.params['domain_mappings']: - domainMappings.append( - otypes.RegistrationDomainMapping( - from_=otypes.Domain( - name=domainMapping['source_name'], - ) if domainMapping['source_name'] else None, - to=otypes.Domain( - name=domainMapping['dest_name'], - ) if domainMapping['dest_name'] else None, - ) - ) - return domainMappings - - -def _get_cluster_mappings(module): - clusterMappings = list() - - for clusterMapping in module.params['cluster_mappings']: - clusterMappings.append( - otypes.RegistrationClusterMapping( - from_=otypes.Cluster( - name=clusterMapping['source_name'], - ), - to=otypes.Cluster( - name=clusterMapping['dest_name'], - ), - ) - ) - return clusterMappings - - -def _get_vnic_profile_mappings(module): - vnicProfileMappings = list() - - for vnicProfileMapping in module.params['vnic_profile_mappings']: - vnicProfileMappings.append( - otypes.VnicProfileMapping( - source_network_name=vnicProfileMapping['source_network_name'], - source_network_profile_name=vnicProfileMapping['source_profile_name'], - target_vnic_profile=otypes.VnicProfile( - id=vnicProfileMapping['target_profile_id'], - ) if vnicProfileMapping['target_profile_id'] else None, - ) - ) - - return vnicProfileMappings - - -def find_subversion_template(module, templates_service): - version = module.params.get('version') - templates = templates_service.list() - for template in templates: - if version.get('number') == template.version.version_number and module.params.get('name') == template.name: - return template - - # when user puts version number which does not exist - raise ValueError( - "Template with name '%s' and version '%s' in cluster '%s' was not found'" % ( - module.params['name'], - module.params['version']['number'], - module.params['cluster'], - ) - ) - - -def searchable_attributes(module): - """ - Return all searchable template attributes passed to module. - """ - attributes = { - 'name': module.params.get('name'), - 'cluster': module.params.get('cluster'), - } - return dict((k, v) for k, v in attributes.items() if v is not None) - - -def main(): - argument_spec = ovirt_full_argument_spec( - state=dict( - choices=['present', 'absent', 'exported', 'imported', 'registered'], - default='present', - ), - id=dict(default=None), - name=dict(default=None), - vm=dict(default=None), - timezone=dict(type='str'), - description=dict(default=None), - sso=dict(type='bool'), - ballooning_enabled=dict(type='bool', default=None), - cluster=dict(default=None), - usb_support=dict(type='bool'), - allow_partial_import=dict(default=None, type='bool'), - cpu_profile=dict(default=None), - clone_permissions=dict(type='bool'), - export_domain=dict(default=None), - storage_domain=dict(default=None), - exclusive=dict(type='bool'), - clone_name=dict(default=None), - image_provider=dict(default=None), - soundcard_enabled=dict(type='bool', default=None), - smartcard_enabled=dict(type='bool', default=None), - image_disk=dict(default=None, aliases=['glance_image_disk_name']), - io_threads=dict(type='int', default=None), - template_image_disk_name=dict(default=None), - version=dict(default=None, type='dict'), - seal=dict(type='bool'), - vnic_profile_mappings=dict(default=[], type='list'), - cluster_mappings=dict(default=[], type='list'), - role_mappings=dict(default=[], type='list'), - domain_mappings=dict(default=[], type='list'), - operating_system=dict(type='str'), - memory=dict(type='str'), - memory_guaranteed=dict(type='str'), - memory_max=dict(type='str'), - nics=dict(type='list', default=[]), - cloud_init=dict(type='dict'), - cloud_init_nics=dict(type='list', default=[]), - sysprep=dict(type='dict'), - ) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - required_one_of=[['id', 'name']], - ) - - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - templates_service = connection.system_service().templates_service() - templates_module = TemplatesModule( - connection=connection, - module=module, - service=templates_service, - ) - - entity = None - if module.params['version'] is not None and module.params['version'].get('number') is not None: - entity = find_subversion_template(module, templates_service) - - state = module.params['state'] - if state == 'present': - force_create = False - if entity is None and module.params['version'] is not None: - force_create = True - - ret = templates_module.create( - entity=entity, - # When user want to create new template subversion, we must make sure - # template is force created as it already exists, but new version should be created. - force_create=force_create, - result_state=otypes.TemplateStatus.OK, - search_params=searchable_attributes(module), - clone_permissions=module.params['clone_permissions'], - seal=module.params['seal'], - ) - elif state == 'absent': - ret = templates_module.remove(entity=entity) - elif state == 'exported': - template = templates_module.search_entity() - if entity is not None: - template = entity - export_service = templates_module._get_export_domain_service() - export_template = search_by_attributes(export_service.templates_service(), id=template.id) - - ret = templates_module.action( - entity=template, - action='export', - action_condition=lambda t: export_template is None or module.params['exclusive'], - wait_condition=lambda t: t is not None, - post_action=templates_module.post_export_action, - storage_domain=otypes.StorageDomain(id=export_service.get().id), - exclusive=module.params['exclusive'], - ) - elif state == 'imported': - template = templates_module.search_entity() - if entity is not None: - template = entity - if template and module.params['clone_name'] is None: - ret = templates_module.create( - result_state=otypes.TemplateStatus.OK, - ) - else: - kwargs = {} - if module.params['image_provider']: - kwargs.update( - disk=otypes.Disk( - name=module.params['template_image_disk_name'] or module.params['image_disk'] - ), - template=otypes.Template( - name=module.params['name'] if module.params['clone_name'] is None else module.params['clone_name'], - ), - clone=True if module.params['clone_name'] is not None else False, - import_as_template=True, - ) - - if module.params['image_disk']: - # We need to refresh storage domain to get list of images: - templates_module._get_export_domain_service().images_service().list() - - glance_service = connection.system_service().openstack_image_providers_service() - image_provider = search_by_name(glance_service, module.params['image_provider']) - images_service = glance_service.service(image_provider.id).images_service() - else: - images_service = templates_module._get_export_domain_service().templates_service() - template_name = module.params['image_disk'] or module.params['name'] - entity = search_by_name(images_service, template_name) - if entity is None: - raise Exception("Image/template '%s' was not found." % template_name) - - images_service.service(entity.id).import_( - storage_domain=otypes.StorageDomain( - name=module.params['storage_domain'] - ) if module.params['storage_domain'] else None, - cluster=otypes.Cluster( - name=module.params['cluster'] - ) if module.params['cluster'] else None, - **kwargs - ) - # Wait for template to appear in system: - template = templates_module.wait_for_import( - condition=lambda t: t.status == otypes.TemplateStatus.OK - ) - if template is None: - raise TimeoutError("Image/template '%s' could not be imported. Try again with larger timeout." % template_name) - ret = templates_module.create(result_state=otypes.TemplateStatus.OK) - elif state == 'registered': - storage_domains_service = connection.system_service().storage_domains_service() - # Find the storage domain with unregistered template: - sd_id = get_id_by_name(storage_domains_service, module.params['storage_domain']) - storage_domain_service = storage_domains_service.storage_domain_service(sd_id) - templates_service = storage_domain_service.templates_service() - - # Find the unregistered Template we want to register: - templates = templates_service.list(unregistered=True) - template = next( - (t for t in templates if (t.id == module.params['id'] or t.name == module.params['name'])), - None - ) - changed = False - if template is None: - template = templates_module.search_entity() - if template is None: - raise ValueError( - "Template '%s(%s)' wasn't found." % (module.params['name'], module.params['id']) - ) - else: - # Register the template into the system: - changed = True - template_service = templates_service.template_service(template.id) - template_service.register( - allow_partial_import=module.params['allow_partial_import'], - cluster=otypes.Cluster( - name=module.params['cluster'] - ) if module.params['cluster'] else None, - vnic_profile_mappings=_get_vnic_profile_mappings(module) - if module.params['vnic_profile_mappings'] else None, - registration_configuration=otypes.RegistrationConfiguration( - cluster_mappings=_get_cluster_mappings(module), - role_mappings=_get_role_mappings(module), - domain_mappings=_get_domain_mappings(module), - ) if (module.params['cluster_mappings'] - or module.params['role_mappings'] - or module.params['domain_mappings']) else None - ) - - if module.params['wait']: - template = templates_module.wait_for_import() - else: - # Fetch template to initialize return. - template = template_service.get() - ret = templates_module.create(result_state=otypes.TemplateStatus.OK) - ret = { - 'changed': changed, - 'id': template.id, - 'template': get_dict_of_struct(template) - } - module.exit_json(**ret) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_template_info.py b/lib/ansible/modules/cloud/ovirt/ovirt_template_info.py deleted file mode 100644 index 72b8b1504a..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_template_info.py +++ /dev/null @@ -1,120 +0,0 @@ -#!/usr/bin/python -# -*- 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 . -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_template_info -short_description: Retrieve information about one or more oVirt/RHV templates -author: "Ondra Machacek (@machacekondra)" -version_added: "2.3" -description: - - "Retrieve information about one or more oVirt/RHV templates." - - This module was called C(ovirt_template_facts) before Ansible 2.9, returning C(ansible_facts). - Note that the M(ovirt_template_info) module no longer returns C(ansible_facts)! -notes: - - "This module returns a variable C(ovirt_templates), which - contains a list of templates. You need to register the result with - the I(register) keyword to use it." -options: - pattern: - description: - - "Search term which is accepted by oVirt/RHV search backend." - - "For example to search template X from datacenter Y use following pattern: - name=X and datacenter=Y" -extends_documentation_fragment: ovirt_info -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Gather information about all templates which names start with C(centos) and -# belongs to data center C(west): -- ovirt_template_info: - pattern: name=centos* and datacenter=west - register: result -- debug: - msg: "{{ result.ovirt_templates }}" -''' - -RETURN = ''' -ovirt_templates: - description: "List of dictionaries describing the templates. Template attributes are mapped to dictionary keys, - all templates attributes can be found at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/template." - returned: On success. - type: list -''' - -import traceback - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - check_sdk, - create_connection, - get_dict_of_struct, - ovirt_info_full_argument_spec, -) - - -def main(): - argument_spec = ovirt_info_full_argument_spec( - pattern=dict(default='', required=False), - ) - module = AnsibleModule(argument_spec) - is_old_facts = module._name == 'ovirt_template_facts' - if is_old_facts: - module.deprecate("The 'ovirt_template_facts' module has been renamed to 'ovirt_template_info', " - "and the renamed one no longer returns ansible_facts", version='2.13') - - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - templates_service = connection.system_service().templates_service() - templates = templates_service.list(search=module.params['pattern']) - result = dict( - ovirt_templates=[ - get_dict_of_struct( - struct=c, - connection=connection, - fetch_nested=module.params.get('fetch_nested'), - attributes=module.params.get('nested_attributes'), - ) for c in templates - ], - ) - if is_old_facts: - module.exit_json(changed=False, ansible_facts=result) - else: - module.exit_json(changed=False, **result) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_user.py b/lib/ansible/modules/cloud/ovirt/ovirt_user.py deleted file mode 100644 index dc37ff4d91..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_user.py +++ /dev/null @@ -1,176 +0,0 @@ -#!/usr/bin/python -# -*- 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 . -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_user -short_description: Module to manage users in oVirt/RHV -version_added: "2.3" -author: "Ondra Machacek (@machacekondra)" -description: - - "Module to manage users in oVirt/RHV." -options: - name: - description: - - "Name of the user to manage. In most LDAPs it's I(uid) of the user, but in Active Directory you must specify I(UPN) of the user." - required: true - state: - description: - - "Should the user be present/absent." - choices: ['present', 'absent'] - default: present - authz_name: - description: - - "Authorization provider of the user. In previous versions of oVirt/RHV known as domain." - required: true - aliases: ['domain'] - namespace: - description: - - "Namespace where the user resides. When using the authorization provider that stores users in the LDAP server, - this attribute equals the naming context of the LDAP server." -extends_documentation_fragment: ovirt -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Add user user1 from authorization provider example.com-authz -- ovirt_user: - name: user1 - domain: example.com-authz - -# Add user user1 from authorization provider example.com-authz -# In case of Active Directory specify UPN: -- ovirt_user: - name: user1@ad2.example.com - domain: example.com-authz - -# Remove user user1 with authorization provider example.com-authz -- ovirt_user: - state: absent - name: user1 - authz_name: example.com-authz -''' - -RETURN = ''' -id: - description: ID of the user which is managed - returned: On success if user is found. - type: str - sample: 7de90f31-222c-436c-a1ca-7e655bd5b60c -user: - description: "Dictionary of all the user attributes. User attributes can be found on your oVirt/RHV instance - at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/user." - returned: On success if user is found. - type: dict -''' - -import traceback - -try: - import ovirtsdk4.types as otypes -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - BaseModule, - check_sdk, - check_params, - create_connection, - ovirt_full_argument_spec, -) - - -def username(module): - return '{0}@{1}'.format(module.params['name'], module.params['authz_name']) - - -class UsersModule(BaseModule): - - def build_entity(self): - return otypes.User( - domain=otypes.Domain( - name=self._module.params['authz_name'] - ), - user_name=username(self._module), - principal=self._module.params['name'], - namespace=self._module.params['namespace'], - ) - - -def main(): - argument_spec = ovirt_full_argument_spec( - state=dict( - choices=['present', 'absent'], - default='present', - ), - name=dict(required=True), - authz_name=dict(required=True, aliases=['domain']), - namespace=dict(default=None), - ) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - ) - - check_sdk(module) - check_params(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - users_service = connection.system_service().users_service() - users_module = UsersModule( - connection=connection, - module=module, - service=users_service, - ) - - state = module.params['state'] - if state == 'present': - ret = users_module.create( - search_params={ - 'usrname': username(module), - } - ) - elif state == 'absent': - ret = users_module.remove( - search_params={ - 'usrname': username(module), - } - ) - - module.exit_json(**ret) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_user_info.py b/lib/ansible/modules/cloud/ovirt/ovirt_user_info.py deleted file mode 100644 index 117ddddb38..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_user_info.py +++ /dev/null @@ -1,118 +0,0 @@ -#!/usr/bin/python -# -*- 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 . -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_user_info -short_description: Retrieve information about one or more oVirt/RHV users -author: "Ondra Machacek (@machacekondra)" -version_added: "2.3" -description: - - "Retrieve information about one or more oVirt/RHV users." - - This module was called C(ovirt_user_facts) before Ansible 2.9, returning C(ansible_facts). - Note that the M(ovirt_user_info) module no longer returns C(ansible_facts)! -notes: - - "This module returns a variable C(ovirt_users), which - contains a list of users. You need to register the result with - the I(register) keyword to use it." -options: - pattern: - description: - - "Search term which is accepted by oVirt/RHV search backend." - - "For example to search user X use following pattern: name=X" -extends_documentation_fragment: ovirt_info -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Gather information about all users which first names start with C(john): -- ovirt_user_info: - pattern: name=john* - register: result -- debug: - msg: "{{ result.ovirt_users }}" -''' - -RETURN = ''' -ovirt_users: - description: "List of dictionaries describing the users. User attributes are mapped to dictionary keys, - all users attributes can be found at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/user." - returned: On success. - type: list -''' - -import traceback - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - check_sdk, - create_connection, - get_dict_of_struct, - ovirt_info_full_argument_spec, -) - - -def main(): - argument_spec = ovirt_info_full_argument_spec( - pattern=dict(default='', required=False), - ) - module = AnsibleModule(argument_spec) - is_old_facts = module._name == 'ovirt_user_facts' - if is_old_facts: - module.deprecate("The 'ovirt_user_facts' module has been renamed to 'ovirt_user_info', " - "and the renamed one no longer returns ansible_facts", version='2.13') - - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - users_service = connection.system_service().users_service() - users = users_service.list(search=module.params['pattern']) - result = dict( - ovirt_users=[ - get_dict_of_struct( - struct=c, - connection=connection, - fetch_nested=module.params.get('fetch_nested'), - attributes=module.params.get('nested_attributes'), - ) for c in users - ], - ) - if is_old_facts: - module.exit_json(changed=False, ansible_facts=result) - else: - module.exit_json(changed=False, **result) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_vm.py b/lib/ansible/modules/cloud/ovirt/ovirt_vm.py deleted file mode 100644 index 202bf9dfb1..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_vm.py +++ /dev/null @@ -1,2727 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2017, Ansible Project -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - -DOCUMENTATION = ''' ---- -module: ovirt_vm -short_description: Module to manage Virtual Machines in oVirt/RHV -version_added: "2.2" -author: -- Ondra Machacek (@machacekondra) -description: - - This module manages whole lifecycle of the Virtual Machine(VM) in oVirt/RHV. - - Since VM can hold many states in oVirt/RHV, this see notes to see how the states of the VM are handled. -options: - name: - description: - - Name of the Virtual Machine to manage. - - If VM don't exists C(name) is required. Otherwise C(id) or C(name) can be used. - id: - description: - - ID of the Virtual Machine to manage. - state: - description: - - Should the Virtual Machine be running/stopped/present/absent/suspended/next_run/registered/exported/reboot. - When C(state) is I(registered) and the unregistered VM's name - belongs to an already registered in engine VM in the same DC - then we fail to register the unregistered template. - - I(present) state will create/update VM and don't change its state if it already exists. - - I(running) state will create/update VM and start it. - - I(next_run) state updates the VM and if the VM has next run configuration it will be rebooted. - - Please check I(notes) to more detailed description of states. - - I(exported) state will export the VM to export domain or as OVA. - - I(registered) is supported since 2.4. - - I(reboot) is supported since 2.10, virtual machine is rebooted only if it's in up state. - choices: [ absent, next_run, present, registered, running, stopped, suspended, exported, reboot ] - default: present - cluster: - description: - - Name of the cluster, where Virtual Machine should be created. - - Required if creating VM. - allow_partial_import: - description: - - Boolean indication whether to allow partial registration of Virtual Machine when C(state) is registered. - type: bool - version_added: "2.4" - vnic_profile_mappings: - description: - - "Mapper which maps an external virtual NIC profile to one that exists in the engine when C(state) is registered. - vnic_profile is described by the following dictionary:" - suboptions: - source_network_name: - description: - - The network name of the source network. - source_profile_name: - description: - - The profile name related to the source network. - target_profile_id: - description: - - The id of the target profile id to be mapped to in the engine. - version_added: "2.5" - cluster_mappings: - description: - - "Mapper which maps cluster name between VM's OVF and the destination cluster this VM should be registered to, - relevant when C(state) is registered. - Cluster mapping is described by the following dictionary:" - suboptions: - source_name: - description: - - The name of the source cluster. - dest_name: - description: - - The name of the destination cluster. - version_added: "2.5" - role_mappings: - description: - - "Mapper which maps role name between VM's OVF and the destination role this VM should be registered to, - relevant when C(state) is registered. - Role mapping is described by the following dictionary:" - suboptions: - source_name: - description: - - The name of the source role. - dest_name: - description: - - The name of the destination role. - version_added: "2.5" - domain_mappings: - description: - - "Mapper which maps aaa domain name between VM's OVF and the destination aaa domain this VM should be registered to, - relevant when C(state) is registered. - The aaa domain mapping is described by the following dictionary:" - suboptions: - source_name: - description: - - The name of the source aaa domain. - dest_name: - description: - - The name of the destination aaa domain. - version_added: "2.5" - affinity_group_mappings: - description: - - "Mapper which maps affinity name between VM's OVF and the destination affinity this VM should be registered to, - relevant when C(state) is registered." - version_added: "2.5" - affinity_label_mappings: - description: - - "Mapper which maps affinity label name between VM's OVF and the destination label this VM should be registered to, - relevant when C(state) is registered." - version_added: "2.5" - lun_mappings: - description: - - "Mapper which maps lun between VM's OVF and the destination lun this VM should contain, relevant when C(state) is registered. - lun_mappings is described by the following dictionary: - - C(logical_unit_id): The logical unit number to identify a logical unit, - - C(logical_unit_port): The port being used to connect with the LUN disk. - - C(logical_unit_portal): The portal being used to connect with the LUN disk. - - C(logical_unit_address): The address of the block storage host. - - C(logical_unit_target): The iSCSI specification located on an iSCSI server - - C(logical_unit_username): Username to be used to connect to the block storage host. - - C(logical_unit_password): Password to be used to connect to the block storage host. - - C(storage_type): The storage type which the LUN reside on (iscsi or fcp)" - version_added: "2.5" - reassign_bad_macs: - description: - - "Boolean indication whether to reassign bad macs when C(state) is registered." - type: bool - version_added: "2.5" - template: - description: - - Name of the template, which should be used to create Virtual Machine. - - Required if creating VM. - - If template is not specified and VM doesn't exist, VM will be created from I(Blank) template. - template_version: - description: - - Version number of the template to be used for VM. - - By default the latest available version of the template is used. - version_added: "2.3" - use_latest_template_version: - description: - - Specify if latest template version should be used, when running a stateless VM. - - If this parameter is set to I(yes) stateless VM is created. - type: bool - version_added: "2.3" - storage_domain: - description: - - Name of the storage domain where all template disks should be created. - - This parameter is considered only when C(template) is provided. - - IMPORTANT - This parameter is not idempotent, if the VM exists and you specify different storage domain, - disk won't move. - version_added: "2.4" - disk_format: - description: - - Specify format of the disk. - - If C(cow) format is used, disk will by created as sparse, so space will be allocated for the volume as needed, also known as I(thin provision). - - If C(raw) format is used, disk storage will be allocated right away, also known as I(preallocated). - - Note that this option isn't idempotent as it's not currently possible to change format of the disk via API. - - This parameter is considered only when C(template) and C(storage domain) is provided. - choices: [ cow, raw ] - default: cow - version_added: "2.4" - memory: - description: - - Amount of memory of the Virtual Machine. Prefix uses IEC 60027-2 standard (for example 1GiB, 1024MiB). - - Default value is set by engine. - memory_guaranteed: - description: - - Amount of minimal guaranteed memory of the Virtual Machine. - Prefix uses IEC 60027-2 standard (for example 1GiB, 1024MiB). - - C(memory_guaranteed) parameter can't be lower than C(memory) parameter. - - Default value is set by engine. - memory_max: - description: - - Upper bound of virtual machine memory up to which memory hot-plug can be performed. - Prefix uses IEC 60027-2 standard (for example 1GiB, 1024MiB). - - Default value is set by engine. - version_added: "2.5" - cpu_shares: - description: - - Set a CPU shares for this Virtual Machine. - - Default value is set by oVirt/RHV engine. - cpu_cores: - description: - - Number of virtual CPUs cores of the Virtual Machine. - - Default value is set by oVirt/RHV engine. - cpu_sockets: - description: - - Number of virtual CPUs sockets of the Virtual Machine. - - Default value is set by oVirt/RHV engine. - cpu_threads: - description: - - Number of threads per core of the Virtual Machine. - - Default value is set by oVirt/RHV engine. - version_added: "2.5" - type: - description: - - Type of the Virtual Machine. - - Default value is set by oVirt/RHV engine. - - I(high_performance) is supported since Ansible 2.5 and oVirt/RHV 4.2. - choices: [ desktop, server, high_performance ] - quota_id: - description: - - "Virtual Machine quota ID to be used for disk. By default quota is chosen by oVirt/RHV engine." - version_added: "2.5" - operating_system: - description: - - Operating system of the Virtual Machine. - - Default value is set by oVirt/RHV engine. - - "Possible values: debian_7, freebsd, freebsdx64, other, other_linux, - other_linux_ppc64, other_ppc64, rhel_3, rhel_4, rhel_4x64, rhel_5, rhel_5x64, - rhel_6, rhel_6x64, rhel_6_ppc64, rhel_7x64, rhel_7_ppc64, sles_11, sles_11_ppc64, - ubuntu_12_04, ubuntu_12_10, ubuntu_13_04, ubuntu_13_10, ubuntu_14_04, ubuntu_14_04_ppc64, - windows_10, windows_10x64, windows_2003, windows_2003x64, windows_2008, windows_2008x64, - windows_2008r2x64, windows_2008R2x64, windows_2012x64, windows_2012R2x64, windows_7, - windows_7x64, windows_8, windows_8x64, windows_xp" - boot_devices: - description: - - List of boot devices which should be used to boot. For example C([ cdrom, hd ]). - - Default value is set by oVirt/RHV engine. - choices: [ cdrom, hd, network ] - boot_menu: - description: - - "I(True) enable menu to select boot device, I(False) to disable it. By default is chosen by oVirt/RHV engine." - type: bool - version_added: "2.5" - usb_support: - description: - - "I(True) enable USB support, I(False) to disable it. By default is chosen by oVirt/RHV engine." - type: bool - version_added: "2.5" - serial_console: - description: - - "I(True) enable VirtIO serial console, I(False) to disable it. By default is chosen by oVirt/RHV engine." - type: bool - version_added: "2.5" - sso: - description: - - "I(True) enable Single Sign On by Guest Agent, I(False) to disable it. By default is chosen by oVirt/RHV engine." - type: bool - version_added: "2.5" - host: - description: - - Specify host where Virtual Machine should be running. By default the host is chosen by engine scheduler. - - This parameter is used only when C(state) is I(running) or I(present). - high_availability: - description: - - If I(yes) Virtual Machine will be set as highly available. - - If I(no) Virtual Machine won't be set as highly available. - - If no value is passed, default value is set by oVirt/RHV engine. - type: bool - high_availability_priority: - description: - - Indicates the priority of the virtual machine inside the run and migration queues. - Virtual machines with higher priorities will be started and migrated before virtual machines with lower - priorities. The value is an integer between 0 and 100. The higher the value, the higher the priority. - - If no value is passed, default value is set by oVirt/RHV engine. - version_added: "2.5" - lease: - description: - - Name of the storage domain this virtual machine lease reside on. Pass an empty string to remove the lease. - - NOTE - Supported since oVirt 4.1. - version_added: "2.4" - custom_compatibility_version: - description: - - "Enables a virtual machine to be customized to its own compatibility version. If - 'C(custom_compatibility_version)' is set, it overrides the cluster's compatibility version - for this particular virtual machine." - version_added: "2.7" - host_devices: - description: - - Single Root I/O Virtualization - technology that allows single device to expose multiple endpoints that can be passed to VMs - - host_devices is an list which contain dictionary with name and state of device - version_added: "2.7" - delete_protected: - description: - - If I(yes) Virtual Machine will be set as delete protected. - - If I(no) Virtual Machine won't be set as delete protected. - - If no value is passed, default value is set by oVirt/RHV engine. - type: bool - stateless: - description: - - If I(yes) Virtual Machine will be set as stateless. - - If I(no) Virtual Machine will be unset as stateless. - - If no value is passed, default value is set by oVirt/RHV engine. - type: bool - clone: - description: - - If I(yes) then the disks of the created virtual machine will be cloned and independent of the template. - - This parameter is used only when C(state) is I(running) or I(present) and VM didn't exist before. - type: bool - default: 'no' - clone_permissions: - description: - - If I(yes) then the permissions of the template (only the direct ones, not the inherited ones) - will be copied to the created virtual machine. - - This parameter is used only when C(state) is I(running) or I(present) and VM didn't exist before. - type: bool - default: 'no' - cd_iso: - description: - - ISO file from ISO storage domain which should be attached to Virtual Machine. - - If you pass empty string the CD will be ejected from VM. - - If used with C(state) I(running) or I(present) and VM is running the CD will be attached to VM. - - If used with C(state) I(running) or I(present) and VM is down the CD will be attached to VM persistently. - force: - description: - - Please check to I(Synopsis) to more detailed description of force parameter, it can behave differently - in different situations. - type: bool - default: 'no' - nics: - description: - - List of NICs, which should be attached to Virtual Machine. NIC is described by following dictionary. - suboptions: - name: - description: - - Name of the NIC. - profile_name: - description: - - Profile name where NIC should be attached. - interface: - description: - - Type of the network interface. - choices: ['virtio', 'e1000', 'rtl8139'] - default: 'virtio' - mac_address: - description: - - Custom MAC address of the network interface, by default it's obtained from MAC pool. - - "NOTE - This parameter is used only when C(state) is I(running) or I(present) and is able to only create NICs. - To manage NICs of the VM in more depth please use M(ovirt_nic) module instead." - disks: - description: - - List of disks, which should be attached to Virtual Machine. Disk is described by following dictionary. - suboptions: - name: - description: - - Name of the disk. Either C(name) or C(id) is required. - id: - description: - - ID of the disk. Either C(name) or C(id) is required. - interface: - description: - - Interface of the disk. - choices: ['virtio', 'ide'] - default: 'virtio' - bootable: - description: - - I(True) if the disk should be bootable, default is non bootable. - type: bool - activate: - description: - - I(True) if the disk should be activated, default is activated. - - "NOTE - This parameter is used only when C(state) is I(running) or I(present) and is able to only attach disks. - To manage disks of the VM in more depth please use M(ovirt_disk) module instead." - type: bool - sysprep: - description: - - Dictionary with values for Windows Virtual Machine initialization using sysprep. - suboptions: - host_name: - description: - - Hostname to be set to Virtual Machine when deployed. - active_directory_ou: - description: - - Active Directory Organizational Unit, to be used for login of user. - org_name: - description: - - Organization name to be set to Windows Virtual Machine. - domain: - description: - - Domain to be set to Windows Virtual Machine. - timezone: - description: - - Timezone to be set to Windows Virtual Machine. - ui_language: - description: - - UI language of the Windows Virtual Machine. - system_locale: - description: - - System localization of the Windows Virtual Machine. - input_locale: - description: - - Input localization of the Windows Virtual Machine. - windows_license_key: - description: - - License key to be set to Windows Virtual Machine. - user_name: - description: - - Username to be used for set password to Windows Virtual Machine. - root_password: - description: - - Password to be set for username to Windows Virtual Machine. - cloud_init: - description: - - Dictionary with values for Unix-like Virtual Machine initialization using cloud init. - suboptions: - host_name: - description: - - Hostname to be set to Virtual Machine when deployed. - timezone: - description: - - Timezone to be set to Virtual Machine when deployed. - user_name: - description: - - Username to be used to set password to Virtual Machine when deployed. - root_password: - description: - - Password to be set for user specified by C(user_name) parameter. - authorized_ssh_keys: - description: - - Use this SSH keys to login to Virtual Machine. - regenerate_ssh_keys: - description: - - If I(True) SSH keys will be regenerated on Virtual Machine. - type: bool - custom_script: - description: - - Cloud-init script which will be executed on Virtual Machine when deployed. - - This is appended to the end of the cloud-init script generated by any other options. - dns_servers: - description: - - DNS servers to be configured on Virtual Machine. - dns_search: - description: - - DNS search domains to be configured on Virtual Machine. - nic_boot_protocol: - description: - - Set boot protocol of the network interface of Virtual Machine. - choices: ['none', 'dhcp', 'static'] - nic_ip_address: - description: - - If boot protocol is static, set this IP address to network interface of Virtual Machine. - nic_netmask: - description: - - If boot protocol is static, set this netmask to network interface of Virtual Machine. - nic_gateway: - description: - - If boot protocol is static, set this gateway to network interface of Virtual Machine. - nic_boot_protocol_v6: - description: - - Set boot protocol of the network interface of Virtual Machine. - choices: ['none', 'dhcp', 'static'] - version_added: "2.9" - nic_ip_address_v6: - description: - - If boot protocol is static, set this IP address to network interface of Virtual Machine. - version_added: "2.9" - nic_netmask_v6: - description: - - If boot protocol is static, set this netmask to network interface of Virtual Machine. - version_added: "2.9" - nic_gateway_v6: - description: - - If boot protocol is static, set this gateway to network interface of Virtual Machine. - - For IPv6 addresses the value is an integer in the range of 0-128, which represents the subnet prefix. - version_added: "2.9" - nic_name: - description: - - Set name to network interface of Virtual Machine. - nic_on_boot: - description: - - If I(True) network interface will be set to start on boot. - type: bool - cloud_init_nics: - description: - - List of dictionaries representing network interfaces to be setup by cloud init. - - This option is used, when user needs to setup more network interfaces via cloud init. - - If one network interface is enough, user should use C(cloud_init) I(nic_*) parameters. C(cloud_init) I(nic_*) parameters - are merged with C(cloud_init_nics) parameters. - suboptions: - nic_boot_protocol: - description: - - Set boot protocol of the network interface of Virtual Machine. Can be one of C(none), C(dhcp) or C(static). - nic_ip_address: - description: - - If boot protocol is static, set this IP address to network interface of Virtual Machine. - nic_netmask: - description: - - If boot protocol is static, set this netmask to network interface of Virtual Machine. - nic_gateway: - description: - - If boot protocol is static, set this gateway to network interface of Virtual Machine. - nic_boot_protocol_v6: - description: - - Set boot protocol of the network interface of Virtual Machine. Can be one of C(none), C(dhcp) or C(static). - version_added: "2.9" - nic_ip_address_v6: - description: - - If boot protocol is static, set this IP address to network interface of Virtual Machine. - version_added: "2.9" - nic_netmask_v6: - description: - - If boot protocol is static, set this netmask to network interface of Virtual Machine. - version_added: "2.9" - nic_gateway_v6: - description: - - If boot protocol is static, set this gateway to network interface of Virtual Machine. - - For IPv6 addresses the value is an integer in the range of 0-128, which represents the subnet prefix. - version_added: "2.9" - nic_name: - description: - - Set name to network interface of Virtual Machine. - nic_on_boot: - description: - - If I(True) network interface will be set to start on boot. - type: bool - version_added: "2.3" - cloud_init_persist: - description: - - "If I(yes) the C(cloud_init) or C(sysprep) parameters will be saved for the virtual machine - and the virtual machine won't be started as run-once." - type: bool - version_added: "2.5" - aliases: [ 'sysprep_persist' ] - default: 'no' - kernel_params_persist: - description: - - "If I(true) C(kernel_params), C(initrd_path) and C(kernel_path) will persist in virtual machine configuration, - if I(False) it will be used for run once." - type: bool - version_added: "2.8" - kernel_path: - description: - - Path to a kernel image used to boot the virtual machine. - - Kernel image must be stored on either the ISO domain or on the host's storage. - version_added: "2.3" - initrd_path: - description: - - Path to an initial ramdisk to be used with the kernel specified by C(kernel_path) option. - - Ramdisk image must be stored on either the ISO domain or on the host's storage. - version_added: "2.3" - kernel_params: - description: - - Kernel command line parameters (formatted as string) to be used with the kernel specified by C(kernel_path) option. - version_added: "2.3" - instance_type: - description: - - Name of virtual machine's hardware configuration. - - By default no instance type is used. - version_added: "2.3" - description: - description: - - Description of the Virtual Machine. - version_added: "2.3" - comment: - description: - - Comment of the Virtual Machine. - version_added: "2.3" - timezone: - description: - - Sets time zone offset of the guest hardware clock. - - For example C(Etc/GMT) - version_added: "2.3" - serial_policy: - description: - - Specify a serial number policy for the Virtual Machine. - - Following options are supported. - - C(vm) - Sets the Virtual Machine's UUID as its serial number. - - C(host) - Sets the host's UUID as the Virtual Machine's serial number. - - C(custom) - Allows you to specify a custom serial number in C(serial_policy_value). - choices: ['vm', 'host', 'custom'] - version_added: "2.3" - serial_policy_value: - description: - - Allows you to specify a custom serial number. - - This parameter is used only when C(serial_policy) is I(custom). - version_added: "2.3" - vmware: - description: - - Dictionary of values to be used to connect to VMware and import - a virtual machine to oVirt. - suboptions: - username: - description: - - The username to authenticate against the VMware. - password: - description: - - The password to authenticate against the VMware. - url: - description: - - The URL to be passed to the I(virt-v2v) tool for conversion. - - For example I(vpx://wmware_user@vcenter-host/DataCenter/Cluster/esxi-host?no_verify=1) - drivers_iso: - description: - - The name of the ISO containing drivers that can be used during the I(virt-v2v) conversion process. - sparse: - description: - - Specifies the disk allocation policy of the resulting virtual machine. I(true) for sparse, I(false) for preallocated. - type: bool - default: true - storage_domain: - description: - - Specifies the target storage domain for converted disks. This is required parameter. - version_added: "2.3" - xen: - description: - - Dictionary of values to be used to connect to XEN and import - a virtual machine to oVirt. - suboptions: - url: - description: - - The URL to be passed to the I(virt-v2v) tool for conversion. - - For example I(xen+ssh://root@zen.server). This is required parameter. - drivers_iso: - description: - - The name of the ISO containing drivers that can be used during the I(virt-v2v) conversion process. - sparse: - description: - - Specifies the disk allocation policy of the resulting virtual machine. I(true) for sparse, I(false) for preallocated. - type: bool - default: true - storage_domain: - description: - - Specifies the target storage domain for converted disks. This is required parameter. - version_added: "2.3" - kvm: - description: - - Dictionary of values to be used to connect to kvm and import - a virtual machine to oVirt. - suboptions: - name: - description: - - The name of the KVM virtual machine. - username: - description: - - The username to authenticate against the KVM. - password: - description: - - The password to authenticate against the KVM. - url: - description: - - The URL to be passed to the I(virt-v2v) tool for conversion. - - For example I(qemu:///system). This is required parameter. - drivers_iso: - description: - - The name of the ISO containing drivers that can be used during the I(virt-v2v) conversion process. - sparse: - description: - - Specifies the disk allocation policy of the resulting virtual machine. I(true) for sparse, I(false) for preallocated. - type: bool - default: true - storage_domain: - description: - - Specifies the target storage domain for converted disks. This is required parameter. - version_added: "2.3" - cpu_mode: - description: - - "CPU mode of the virtual machine. It can be some of the following: I(host_passthrough), I(host_model) or I(custom)." - - "For I(host_passthrough) CPU type you need to set C(placement_policy) to I(pinned)." - - "If no value is passed, default value is set by oVirt/RHV engine." - version_added: "2.5" - placement_policy: - description: - - "The configuration of the virtual machine's placement policy." - - "If no value is passed, default value is set by oVirt/RHV engine." - - "Placement policy can be one of the following values:" - suboptions: - migratable: - description: - - "Allow manual and automatic migration." - pinned: - description: - - "Do not allow migration." - user_migratable: - description: - - "Allow manual migration only." - version_added: "2.5" - ticket: - description: - - "If I(true), in addition return I(remote_vv_file) inside I(vm) dictionary, which contains compatible - content for remote-viewer application. Works only C(state) is I(running)." - version_added: "2.7" - type: bool - cpu_pinning: - description: - - "CPU Pinning topology to map virtual machine CPU to host CPU." - - "CPU Pinning topology is a list of dictionary which can have following values:" - suboptions: - cpu: - description: - - "Number of the host CPU." - vcpu: - description: - - "Number of the virtual machine CPU." - version_added: "2.5" - soundcard_enabled: - description: - - "If I(true), the sound card is added to the virtual machine." - type: bool - version_added: "2.5" - smartcard_enabled: - description: - - "If I(true), use smart card authentication." - type: bool - version_added: "2.5" - io_threads: - description: - - "Number of IO threads used by virtual machine. I(0) means IO threading disabled." - version_added: "2.5" - ballooning_enabled: - description: - - "If I(true), use memory ballooning." - - "Memory balloon is a guest device, which may be used to re-distribute / reclaim the host memory - based on VM needs in a dynamic way. In this way it's possible to create memory over commitment states." - type: bool - version_added: "2.5" - numa_tune_mode: - description: - - "Set how the memory allocation for NUMA nodes of this VM is applied (relevant if NUMA nodes are set for this VM)." - - "It can be one of the following: I(interleave), I(preferred) or I(strict)." - - "If no value is passed, default value is set by oVirt/RHV engine." - choices: ['interleave', 'preferred', 'strict'] - version_added: "2.6" - numa_nodes: - description: - - "List of vNUMA Nodes to set for this VM and pin them to assigned host's physical NUMA node." - - "Each vNUMA node is described by following dictionary:" - suboptions: - index: - description: - - "The index of this NUMA node." - required: True - memory: - description: - - "Memory size of the NUMA node in MiB." - required: True - cores: - description: - - "List of VM CPU cores indexes to be included in this NUMA node." - type: list - required: True - numa_node_pins: - description: - - "List of physical NUMA node indexes to pin this virtual NUMA node to." - type: list - version_added: "2.6" - rng_device: - description: - - "Random number generator (RNG). You can choose of one the following devices I(urandom), I(random) or I(hwrng)." - - "In order to select I(hwrng), you must have it enabled on cluster first." - - "/dev/urandom is used for cluster version >= 4.1, and /dev/random for cluster version <= 4.0" - version_added: "2.5" - custom_properties: - description: - - "Properties sent to VDSM to configure various hooks." - - "Custom properties is a list of dictionary which can have following values:" - suboptions: - name: - description: - - "Name of the custom property. For example: I(hugepages), I(vhost), I(sap_agent), etc." - regexp: - description: - - "Regular expression to set for custom property." - value: - description: - - "Value to set for custom property." - version_added: "2.5" - watchdog: - description: - - "Assign watchdog device for the virtual machine." - - "Watchdogs is a dictionary which can have following values:" - suboptions: - model: - description: - - "Model of the watchdog device. For example: I(i6300esb), I(diag288) or I(null)." - action: - description: - - "Watchdog action to be performed when watchdog is triggered. For example: I(none), I(reset), I(poweroff), I(pause) or I(dump)." - version_added: "2.5" - graphical_console: - description: - - "Assign graphical console to the virtual machine." - suboptions: - headless_mode: - description: - - If I(true) disable the graphics console for this virtual machine. - type: bool - protocol: - description: - - Graphical protocol, a list of I(spice), I(vnc), or both. - type: list - disconnect_action: - description: - - "Returns the action that will take place when the graphic console(SPICE only) is disconnected. The options are:" - - I(none) No action is taken. - - I(lock_screen) Locks the currently active user session. - - I(logout) Logs out the currently active user session. - - I(reboot) Initiates a graceful virtual machine reboot. - - I(shutdown) Initiates a graceful virtual machine shutdown. - type: str - version_added: "2.10" - keyboard_layout: - description: - - The keyboard layout to use with this graphic console. - - This option is only available for the VNC console type. - - If no keyboard is enabled then it won't be reported. - type: str - version_added: "2.10" - monitors: - description: - - The number of monitors opened for this graphic console. - - This option is only available for the SPICE protocol. - - Possible values are 1, 2 or 4. - type: int - version_added: "2.10" - version_added: "2.5" - exclusive: - description: - - "When C(state) is I(exported) this parameter indicates if the existing VM with the - same name should be overwritten." - version_added: "2.8" - type: bool - export_domain: - description: - - "When C(state) is I(exported)this parameter specifies the name of the export storage domain." - version_added: "2.8" - export_ova: - description: - - Dictionary of values to be used to export VM as OVA. - suboptions: - host: - description: - - The name of the destination host where the OVA has to be exported. - directory: - description: - - The name of the directory where the OVA has to be exported. - filename: - description: - - The name of the exported OVA file. - version_added: "2.8" - force_migrate: - description: - - If I(true), the VM will migrate when I(placement_policy=user-migratable) but not when I(placement_policy=pinned). - version_added: "2.8" - type: bool - migrate: - description: - - "If I(true), the VM will migrate to any available host." - version_added: "2.8" - type: bool - next_run: - description: - - "If I(true), the update will not be applied to the VM immediately and will be only applied when virtual machine is restarted." - - NOTE - If there are multiple next run configuration changes on the VM, the first change may get reverted if this option is not passed. - version_added: "2.8" - type: bool - snapshot_name: - description: - - "Snapshot to clone VM from." - - "Snapshot with description specified should exist." - - "You have to specify C(snapshot_vm) parameter with virtual machine name of this snapshot." - version_added: "2.9" - snapshot_vm: - description: - - "Source VM to clone VM from." - - "VM should have snapshot specified by C(snapshot)." - - "If C(snapshot_name) specified C(snapshot_vm) is required." - version_added: "2.9" - custom_emulated_machine: - description: - - "Sets the value of the custom_emulated_machine attribute." - version_added: "2.10" - -notes: - - If VM is in I(UNASSIGNED) or I(UNKNOWN) state before any operation, the module will fail. - If VM is in I(IMAGE_LOCKED) state before any operation, we try to wait for VM to be I(DOWN). - If VM is in I(SAVING_STATE) state before any operation, we try to wait for VM to be I(SUSPENDED). - If VM is in I(POWERING_DOWN) state before any operation, we try to wait for VM to be I(UP) or I(DOWN). VM can - get into I(UP) state from I(POWERING_DOWN) state, when there is no ACPI or guest agent running inside VM, or - if the shutdown operation fails. - When user specify I(UP) C(state), we always wait to VM to be in I(UP) state in case VM is I(MIGRATING), - I(REBOOTING), I(POWERING_UP), I(RESTORING_STATE), I(WAIT_FOR_LAUNCH). In other states we run start operation on VM. - When user specify I(stopped) C(state), and If user pass C(force) parameter set to I(true) we forcibly stop the VM in - any state. If user don't pass C(force) parameter, we always wait to VM to be in UP state in case VM is - I(MIGRATING), I(REBOOTING), I(POWERING_UP), I(RESTORING_STATE), I(WAIT_FOR_LAUNCH). If VM is in I(PAUSED) or - I(SUSPENDED) state, we start the VM. Then we gracefully shutdown the VM. - When user specify I(suspended) C(state), we always wait to VM to be in UP state in case VM is I(MIGRATING), - I(REBOOTING), I(POWERING_UP), I(RESTORING_STATE), I(WAIT_FOR_LAUNCH). If VM is in I(PAUSED) or I(DOWN) state, - we start the VM. Then we suspend the VM. - When user specify I(absent) C(state), we forcibly stop the VM in any state and remove it. - - "If you update a VM parameter that requires a reboot, the oVirt engine always creates a new snapshot for the VM, - and an Ansible playbook will report this as changed." -extends_documentation_fragment: ovirt -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -- name: Creates a new Virtual Machine from template named 'rhel7_template' - ovirt_vm: - state: present - name: myvm - template: rhel7_template - cluster: mycluster - -- name: Register VM - ovirt_vm: - state: registered - storage_domain: mystorage - cluster: mycluster - name: myvm - -- name: Register VM using id - ovirt_vm: - state: registered - storage_domain: mystorage - cluster: mycluster - id: 1111-1111-1111-1111 - -- name: Register VM, allowing partial import - ovirt_vm: - state: registered - storage_domain: mystorage - allow_partial_import: "True" - cluster: mycluster - id: 1111-1111-1111-1111 - -- name: Register VM with vnic profile mappings and reassign bad macs - ovirt_vm: - state: registered - storage_domain: mystorage - cluster: mycluster - id: 1111-1111-1111-1111 - vnic_profile_mappings: - - source_network_name: mynetwork - source_profile_name: mynetwork - target_profile_id: 3333-3333-3333-3333 - - source_network_name: mynetwork2 - source_profile_name: mynetwork2 - target_profile_id: 4444-4444-4444-4444 - reassign_bad_macs: "True" - -- name: Register VM with mappings - ovirt_vm: - state: registered - storage_domain: mystorage - cluster: mycluster - id: 1111-1111-1111-1111 - role_mappings: - - source_name: Role_A - dest_name: Role_B - domain_mappings: - - source_name: Domain_A - dest_name: Domain_B - lun_mappings: - - source_storage_type: iscsi - source_logical_unit_id: 1IET_000d0001 - source_logical_unit_port: 3260 - source_logical_unit_portal: 1 - source_logical_unit_address: 10.34.63.203 - source_logical_unit_target: iqn.2016-08-09.brq.str-01:omachace - dest_storage_type: iscsi - dest_logical_unit_id: 1IET_000d0002 - dest_logical_unit_port: 3260 - dest_logical_unit_portal: 1 - dest_logical_unit_address: 10.34.63.204 - dest_logical_unit_target: iqn.2016-08-09.brq.str-02:omachace - affinity_group_mappings: - - source_name: Affinity_A - dest_name: Affinity_B - affinity_label_mappings: - - source_name: Label_A - dest_name: Label_B - cluster_mappings: - - source_name: cluster_A - dest_name: cluster_B - -- name: Creates a stateless VM which will always use latest template version - ovirt_vm: - name: myvm - template: rhel7 - cluster: mycluster - use_latest_template_version: true - -# Creates a new server rhel7 Virtual Machine from Blank template -# on brq01 cluster with 2GiB memory and 2 vcpu cores/sockets -# and attach bootable disk with name rhel7_disk and attach virtio NIC -- ovirt_vm: - state: present - cluster: brq01 - name: myvm - memory: 2GiB - cpu_cores: 2 - cpu_sockets: 2 - cpu_shares: 1024 - type: server - operating_system: rhel_7x64 - disks: - - name: rhel7_disk - bootable: True - nics: - - name: nic1 - -# Change VM Name -- ovirt_vm: - id: 00000000-0000-0000-0000-000000000000 - name: "new_vm_name" - -- name: Run VM with cloud init - ovirt_vm: - name: rhel7 - template: rhel7 - cluster: Default - memory: 1GiB - high_availability: true - high_availability_priority: 50 # Available from Ansible 2.5 - cloud_init: - nic_boot_protocol: static - nic_ip_address: 10.34.60.86 - nic_netmask: 255.255.252.0 - nic_gateway: 10.34.63.254 - nic_name: eth1 - nic_on_boot: true - host_name: example.com - custom_script: | - write_files: - - content: | - Hello, world! - path: /tmp/greeting.txt - permissions: '0644' - user_name: root - root_password: super_password - -- name: Run VM with cloud init, with multiple network interfaces - ovirt_vm: - name: rhel7_4 - template: rhel7 - cluster: mycluster - cloud_init_nics: - - nic_name: eth0 - nic_boot_protocol: dhcp - nic_on_boot: true - - nic_name: eth1 - nic_boot_protocol: static - nic_ip_address: 10.34.60.86 - nic_netmask: 255.255.252.0 - nic_gateway: 10.34.63.254 - nic_on_boot: true - # IP version 6 parameters are supported since ansible 2.9 - - nic_name: eth2 - nic_boot_protocol_v6: static - nic_ip_address_v6: '2620:52:0:2282:b898:1f69:6512:36c5' - nic_gateway_v6: '2620:52:0:2282:b898:1f69:6512:36c9' - nic_netmask_v6: '120' - nic_on_boot: true - - nic_name: eth3 - nic_on_boot: true - nic_boot_protocol_v6: dhcp - -- name: Run VM with sysprep - ovirt_vm: - name: windows2012R2_AD - template: windows2012R2 - cluster: Default - memory: 3GiB - high_availability: true - sysprep: - host_name: windowsad.example.com - user_name: Administrator - root_password: SuperPassword123 - -- name: Migrate/Run VM to/on host named 'host1' - ovirt_vm: - state: running - name: myvm - host: host1 - -- name: Migrate VM to any available host - ovirt_vm: - state: running - name: myvm - migrate: true - -- name: Change VMs CD - ovirt_vm: - name: myvm - cd_iso: drivers.iso - -- name: Eject VMs CD - ovirt_vm: - name: myvm - cd_iso: '' - -- name: Boot VM from CD - ovirt_vm: - name: myvm - cd_iso: centos7_x64.iso - boot_devices: - - cdrom - -- name: Stop vm - ovirt_vm: - state: stopped - name: myvm - -- name: Upgrade memory to already created VM - ovirt_vm: - name: myvm - memory: 4GiB - -- name: Hot plug memory to already created and running VM (VM won't be restarted) - ovirt_vm: - name: myvm - memory: 4GiB - -# Create/update a VM to run with two vNUMA nodes and pin them to physical NUMA nodes as follows: -# vnuma index 0-> numa index 0, vnuma index 1-> numa index 1 -- name: Create a VM to run with two vNUMA nodes - ovirt_vm: - name: myvm - cluster: mycluster - numa_tune_mode: "interleave" - numa_nodes: - - index: 0 - cores: [0] - memory: 20 - numa_node_pins: [0] - - index: 1 - cores: [1] - memory: 30 - numa_node_pins: [1] - -- name: Update an existing VM to run without previously created vNUMA nodes (i.e. remove all vNUMA nodes+NUMA pinning setting) - ovirt_vm: - name: myvm - cluster: mycluster - state: "present" - numa_tune_mode: "interleave" - numa_nodes: - - index: -1 - -# When change on the VM needs restart of the VM, use next_run state, -# The VM will be updated and rebooted if there are any changes. -# If present state would be used, VM won't be restarted. -- ovirt_vm: - state: next_run - name: myvm - boot_devices: - - network - -- name: Import virtual machine from VMware - ovirt_vm: - state: stopped - cluster: mycluster - name: vmware_win10 - timeout: 1800 - poll_interval: 30 - vmware: - url: vpx://user@1.2.3.4/Folder1/Cluster1/2.3.4.5?no_verify=1 - name: windows10 - storage_domain: mynfs - username: user - password: password - -- name: Create vm from template and create all disks on specific storage domain - ovirt_vm: - name: vm_test - cluster: mycluster - template: mytemplate - storage_domain: mynfs - nics: - - name: nic1 - -- name: Remove VM, if VM is running it will be stopped - ovirt_vm: - state: absent - name: myvm - -# Defining a specific quota for a VM: -# Since Ansible 2.5 -- ovirt_quotas_facts: - data_center: Default - name: myquota -- ovirt_vm: - name: myvm - sso: False - boot_menu: True - usb_support: True - serial_console: True - quota_id: "{{ ovirt_quotas[0]['id'] }}" - -- name: Create a VM that has the console configured for both Spice and VNC - ovirt_vm: - name: myvm - template: mytemplate - cluster: mycluster - graphical_console: - protocol: - - spice - - vnc - -# Execute remote viewer to VM -- block: - - name: Create a ticket for console for a running VM - ovirt_vm: - name: myvm - ticket: true - state: running - register: myvm - - - name: Save ticket to file - copy: - content: "{{ myvm.vm.remote_vv_file }}" - dest: ~/vvfile.vv - - - name: Run remote viewer with file - command: remote-viewer ~/vvfile.vv - -# Default value of host_device state is present -- name: Attach host devices to virtual machine - ovirt_vm: - name: myvm - host: myhost - placement_policy: pinned - host_devices: - - name: pci_0000_00_06_0 - - name: pci_0000_00_07_0 - state: absent - - name: pci_0000_00_08_0 - state: present - -- name: Export the VM as OVA - ovirt_vm: - name: myvm - state: exported - cluster: mycluster - export_ova: - host: myhost - filename: myvm.ova - directory: /tmp/ - -- name: Clone VM from snapshot - ovirt_vm: - snapshot_vm: myvm - snapshot_name: myvm_snap - name: myvm_clone - state: present - -- name: Import external ova VM - ovirt_vm: - cluster: mycluster - name: myvm - host: myhost - timeout: 1800 - poll_interval: 30 - kvm: - name: myvm - url: ova:///path/myvm.ova - storage_domain: mystorage - -- name: Cpu pinning of 0#12_1#13_2#14_3#15 - ovirt_vm: - state: present - cluster: mycluster - name: myvm - cpu_pinning: - - cpu: 12 - vcpu: 0 - - cpu: 13 - vcpu: 1 - - cpu: 14 - vcpu: 2 - - cpu: 15 - vcpu: 3 -''' - - -RETURN = ''' -id: - description: ID of the VM which is managed - returned: On success if VM is found. - type: str - sample: 7de90f31-222c-436c-a1ca-7e655bd5b60c -vm: - description: "Dictionary of all the VM attributes. VM attributes can be found on your oVirt/RHV instance - at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/vm. - Additionally when user sent ticket=true, this module will return also remote_vv_file - parameter in vm dictionary, which contains remote-viewer compatible file to open virtual - machine console. Please note that this file contains sensible information." - returned: On success if VM is found. - type: dict -''' -import traceback - -try: - import ovirtsdk4.types as otypes -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - BaseModule, - check_params, - check_sdk, - convert_to_bytes, - create_connection, - equal, - get_dict_of_struct, - get_entity, - get_link_name, - get_id_by_name, - ovirt_full_argument_spec, - search_by_attributes, - search_by_name, - wait, -) - - -class VmsModule(BaseModule): - - def __init__(self, *args, **kwargs): - super(VmsModule, self).__init__(*args, **kwargs) - self._initialization = None - self._is_new = False - - def __get_template_with_version(self): - """ - oVirt/RHV in version 4.1 doesn't support search by template+version_number, - so we need to list all templates with specific name and then iterate - through it's version until we find the version we look for. - """ - template = None - templates_service = self._connection.system_service().templates_service() - if self._is_new: - if self.param('template'): - clusters_service = self._connection.system_service().clusters_service() - cluster = search_by_name(clusters_service, self.param('cluster')) - data_center = self._connection.follow_link(cluster.data_center) - templates = templates_service.list( - search='name=%s and datacenter=%s' % (self.param('template'), data_center.name) - ) - if self.param('template_version'): - templates = [ - t for t in templates - if t.version.version_number == self.param('template_version') - ] - if not templates: - raise ValueError( - "Template with name '%s' and version '%s' in data center '%s' was not found'" % ( - self.param('template'), - self.param('template_version'), - data_center.name - ) - ) - template = sorted(templates, key=lambda t: t.version.version_number, reverse=True)[0] - else: - # If template isn't specified and VM is about to be created specify default template: - template = templates_service.template_service('00000000-0000-0000-0000-000000000000').get() - - return template - - def __get_storage_domain_and_all_template_disks(self, template): - - if self.param('template') is None: - return None - - if self.param('storage_domain') is None: - return None - - disks = list() - - for att in self._connection.follow_link(template.disk_attachments): - disks.append( - otypes.DiskAttachment( - disk=otypes.Disk( - id=att.disk.id, - format=otypes.DiskFormat(self.param('disk_format')), - storage_domains=[ - otypes.StorageDomain( - id=get_id_by_name( - self._connection.system_service().storage_domains_service(), - self.param('storage_domain') - ) - ) - ] - ) - ) - ) - - return disks - - def __get_snapshot(self): - - if self.param('snapshot_vm') is None: - return None - - if self.param('snapshot_name') is None: - return None - - vms_service = self._connection.system_service().vms_service() - vm_id = get_id_by_name(vms_service, self.param('snapshot_vm')) - vm_service = vms_service.vm_service(vm_id) - - snaps_service = vm_service.snapshots_service() - snaps = snaps_service.list() - snap = next( - (s for s in snaps if s.description == self.param('snapshot_name')), - None - ) - return snap - - def __get_cluster(self): - if self.param('cluster') is not None: - return self.param('cluster') - elif self.param('snapshot_name') is not None and self.param('snapshot_vm') is not None: - vms_service = self._connection.system_service().vms_service() - vm = search_by_name(vms_service, self.param('snapshot_vm')) - return self._connection.system_service().clusters_service().cluster_service(vm.cluster.id).get().name - - def build_entity(self): - template = self.__get_template_with_version() - cluster = self.__get_cluster() - snapshot = self.__get_snapshot() - display = self.param('graphical_console') or dict() - - disk_attachments = self.__get_storage_domain_and_all_template_disks(template) - - return otypes.Vm( - id=self.param('id'), - name=self.param('name'), - cluster=otypes.Cluster( - name=cluster - ) if cluster else None, - disk_attachments=disk_attachments, - template=otypes.Template( - id=template.id, - ) if template else None, - use_latest_template_version=self.param('use_latest_template_version'), - stateless=self.param('stateless') or self.param('use_latest_template_version'), - delete_protected=self.param('delete_protected'), - custom_emulated_machine=self.param('custom_emulated_machine'), - bios=( - otypes.Bios(boot_menu=otypes.BootMenu(enabled=self.param('boot_menu'))) - ) if self.param('boot_menu') is not None else None, - console=( - otypes.Console(enabled=self.param('serial_console')) - ) if self.param('serial_console') is not None else None, - usb=( - otypes.Usb(enabled=self.param('usb_support')) - ) if self.param('usb_support') is not None else None, - sso=( - otypes.Sso( - methods=[otypes.Method(id=otypes.SsoMethod.GUEST_AGENT)] if self.param('sso') else [] - ) - ) if self.param('sso') is not None else None, - quota=otypes.Quota(id=self._module.params.get('quota_id')) if self.param('quota_id') is not None else None, - high_availability=otypes.HighAvailability( - enabled=self.param('high_availability'), - priority=self.param('high_availability_priority'), - ) if self.param('high_availability') is not None or self.param('high_availability_priority') else None, - lease=otypes.StorageDomainLease( - storage_domain=otypes.StorageDomain( - id=get_id_by_name( - service=self._connection.system_service().storage_domains_service(), - name=self.param('lease') - ) if self.param('lease') else None - ) - ) if self.param('lease') is not None else None, - cpu=otypes.Cpu( - topology=otypes.CpuTopology( - cores=self.param('cpu_cores'), - sockets=self.param('cpu_sockets'), - threads=self.param('cpu_threads'), - ) if any(( - self.param('cpu_cores'), - self.param('cpu_sockets'), - self.param('cpu_threads') - )) else None, - cpu_tune=otypes.CpuTune( - vcpu_pins=[ - otypes.VcpuPin(vcpu=int(pin['vcpu']), cpu_set=str(pin['cpu'])) for pin in self.param('cpu_pinning') - ], - ) if self.param('cpu_pinning') else None, - mode=otypes.CpuMode(self.param('cpu_mode')) if self.param('cpu_mode') else None, - ) if any(( - self.param('cpu_cores'), - self.param('cpu_sockets'), - self.param('cpu_threads'), - self.param('cpu_mode'), - self.param('cpu_pinning') - )) else None, - cpu_shares=self.param('cpu_shares'), - os=otypes.OperatingSystem( - type=self.param('operating_system'), - boot=otypes.Boot( - devices=[ - otypes.BootDevice(dev) for dev in self.param('boot_devices') - ], - ) if self.param('boot_devices') else None, - cmdline=self.param('kernel_params') if self.param('kernel_params_persist') else None, - initrd=self.param('initrd_path') if self.param('kernel_params_persist') else None, - kernel=self.param('kernel_path') if self.param('kernel_params_persist') else None, - ) if ( - self.param('operating_system') or self.param('boot_devices') or self.param('kernel_params_persist') - ) else None, - type=otypes.VmType( - self.param('type') - ) if self.param('type') else None, - memory=convert_to_bytes( - self.param('memory') - ) if self.param('memory') else None, - memory_policy=otypes.MemoryPolicy( - guaranteed=convert_to_bytes(self.param('memory_guaranteed')), - ballooning=self.param('ballooning_enabled'), - max=convert_to_bytes(self.param('memory_max')), - ) if any(( - self.param('memory_guaranteed'), - self.param('ballooning_enabled') is not None, - self.param('memory_max') - )) else None, - instance_type=otypes.InstanceType( - id=get_id_by_name( - self._connection.system_service().instance_types_service(), - self.param('instance_type'), - ), - ) if self.param('instance_type') else None, - custom_compatibility_version=otypes.Version( - major=self._get_major(self.param('custom_compatibility_version')), - minor=self._get_minor(self.param('custom_compatibility_version')), - ) if self.param('custom_compatibility_version') is not None else None, - description=self.param('description'), - comment=self.param('comment'), - time_zone=otypes.TimeZone( - name=self.param('timezone'), - ) if self.param('timezone') else None, - serial_number=otypes.SerialNumber( - policy=otypes.SerialNumberPolicy(self.param('serial_policy')), - value=self.param('serial_policy_value'), - ) if ( - self.param('serial_policy') is not None or - self.param('serial_policy_value') is not None - ) else None, - placement_policy=otypes.VmPlacementPolicy( - affinity=otypes.VmAffinity(self.param('placement_policy')), - hosts=[ - otypes.Host(name=self.param('host')), - ] if self.param('host') else None, - ) if self.param('placement_policy') else None, - soundcard_enabled=self.param('soundcard_enabled'), - display=otypes.Display( - smartcard_enabled=self.param('smartcard_enabled'), - disconnect_action=display.get('disconnect_action'), - keyboard_layout=display.get('keyboard_layout'), - monitors=display.get('monitors'), - ) if ( - self.param('smartcard_enabled') is not None or - display.get('disconnect_action') is not None or - display.get('keyboard_layout') is not None or - display.get('monitors') is not None - ) else None, - io=otypes.Io( - threads=self.param('io_threads'), - ) if self.param('io_threads') is not None else None, - numa_tune_mode=otypes.NumaTuneMode( - self.param('numa_tune_mode') - ) if self.param('numa_tune_mode') else None, - rng_device=otypes.RngDevice( - source=otypes.RngSource(self.param('rng_device')), - ) if self.param('rng_device') else None, - custom_properties=[ - otypes.CustomProperty( - name=cp.get('name'), - regexp=cp.get('regexp'), - value=str(cp.get('value')), - ) for cp in self.param('custom_properties') if cp - ] if self.param('custom_properties') is not None else None, - initialization=self.get_initialization() if self.param('cloud_init_persist') else None, - snapshots=[otypes.Snapshot(id=snapshot.id)] if snapshot is not None else None, - ) - - def _get_export_domain_service(self): - provider_name = self._module.params['export_domain'] - export_sds_service = self._connection.system_service().storage_domains_service() - export_sd_id = get_id_by_name(export_sds_service, provider_name) - return export_sds_service.service(export_sd_id) - - def post_export_action(self, entity): - self._service = self._get_export_domain_service().vms_service() - - def update_check(self, entity): - res = self._update_check(entity) - if entity.next_run_configuration_exists: - res = res and self._update_check(self._service.service(entity.id).get(next_run=True)) - - return res - - def _update_check(self, entity): - def check_cpu_pinning(): - if self.param('cpu_pinning'): - current = [] - if entity.cpu.cpu_tune: - current = [(str(pin.cpu_set), int(pin.vcpu)) for pin in entity.cpu.cpu_tune.vcpu_pins] - passed = [(str(pin['cpu']), int(pin['vcpu'])) for pin in self.param('cpu_pinning')] - return sorted(current) == sorted(passed) - return True - - def check_custom_properties(): - if self.param('custom_properties'): - current = [] - if entity.custom_properties: - current = [(cp.name, cp.regexp, str(cp.value)) for cp in entity.custom_properties] - passed = [(cp.get('name'), cp.get('regexp'), str(cp.get('value'))) for cp in self.param('custom_properties') if cp] - return sorted(current) == sorted(passed) - return True - - def check_host(): - if self.param('host') is not None: - return self.param('host') in [self._connection.follow_link(host).name for host in getattr(entity.placement_policy, 'hosts', None) or []] - return True - - def check_custom_compatibility_version(): - if self.param('custom_compatibility_version') is not None: - return (self._get_minor(self.param('custom_compatibility_version')) == self._get_minor(entity.custom_compatibility_version) and - self._get_major(self.param('custom_compatibility_version')) == self._get_major(entity.custom_compatibility_version)) - return True - - cpu_mode = getattr(entity.cpu, 'mode') - vm_display = entity.display - provided_vm_display = self.param('graphical_console') or dict() - return ( - check_cpu_pinning() and - check_custom_properties() and - check_host() and - check_custom_compatibility_version() and - not self.param('cloud_init_persist') and - not self.param('kernel_params_persist') and - equal(self.param('cluster'), get_link_name(self._connection, entity.cluster)) and equal(convert_to_bytes(self.param('memory')), entity.memory) and - equal(convert_to_bytes(self.param('memory_guaranteed')), entity.memory_policy.guaranteed) and - equal(convert_to_bytes(self.param('memory_max')), entity.memory_policy.max) and - equal(self.param('cpu_cores'), entity.cpu.topology.cores) and - equal(self.param('cpu_sockets'), entity.cpu.topology.sockets) and - equal(self.param('cpu_threads'), entity.cpu.topology.threads) and - equal(self.param('cpu_mode'), str(cpu_mode) if cpu_mode else None) and - equal(self.param('type'), str(entity.type)) and - equal(self.param('name'), str(entity.name)) and - equal(self.param('operating_system'), str(entity.os.type)) and - equal(self.param('boot_menu'), entity.bios.boot_menu.enabled) and - equal(self.param('soundcard_enabled'), entity.soundcard_enabled) and - equal(self.param('smartcard_enabled'), getattr(vm_display, 'smartcard_enabled', False)) and - equal(self.param('io_threads'), entity.io.threads) and - equal(self.param('ballooning_enabled'), entity.memory_policy.ballooning) and - equal(self.param('serial_console'), getattr(entity.console, 'enabled', None)) and - equal(self.param('usb_support'), entity.usb.enabled) and - equal(self.param('sso'), True if entity.sso.methods else False) and - equal(self.param('quota_id'), getattr(entity.quota, 'id', None)) and - equal(self.param('high_availability'), entity.high_availability.enabled) and - equal(self.param('high_availability_priority'), entity.high_availability.priority) and - equal(self.param('lease'), get_link_name(self._connection, getattr(entity.lease, 'storage_domain', None))) and - equal(self.param('stateless'), entity.stateless) and - equal(self.param('cpu_shares'), entity.cpu_shares) and - equal(self.param('delete_protected'), entity.delete_protected) and - equal(self.param('custom_emulated_machine'), entity.custom_emulated_machine) and - equal(self.param('use_latest_template_version'), entity.use_latest_template_version) and - equal(self.param('boot_devices'), [str(dev) for dev in getattr(entity.os.boot, 'devices', [])]) and - equal(self.param('instance_type'), get_link_name(self._connection, entity.instance_type), ignore_case=True) and - equal(self.param('description'), entity.description) and - equal(self.param('comment'), entity.comment) and - equal(self.param('timezone'), getattr(entity.time_zone, 'name', None)) and - equal(self.param('serial_policy'), str(getattr(entity.serial_number, 'policy', None))) and - equal(self.param('serial_policy_value'), getattr(entity.serial_number, 'value', None)) and - equal(self.param('placement_policy'), str(entity.placement_policy.affinity) if entity.placement_policy else None) and - equal(self.param('numa_tune_mode'), str(entity.numa_tune_mode)) and - equal(self.param('rng_device'), str(entity.rng_device.source) if entity.rng_device else None) and - equal(provided_vm_display.get('monitors'), getattr(vm_display, 'monitors', None)) and - equal(provided_vm_display.get('keyboard_layout'), getattr(vm_display, 'keyboard_layout', None)) and - equal(provided_vm_display.get('disconnect_action'), getattr(vm_display, 'disconnect_action', None), ignore_case=True) - ) - - def pre_create(self, entity): - # Mark if entity exists before touching it: - if entity is None: - self._is_new = True - - def post_update(self, entity): - self.post_present(entity.id) - - def post_present(self, entity_id): - # After creation of the VM, attach disks and NICs: - entity = self._service.service(entity_id).get() - self.__attach_disks(entity) - self.__attach_nics(entity) - self._attach_cd(entity) - self.changed = self.__attach_numa_nodes(entity) - self.changed = self.__attach_watchdog(entity) - self.changed = self.__attach_graphical_console(entity) - self.changed = self.__attach_host_devices(entity) - - def pre_remove(self, entity): - # Forcibly stop the VM, if it's not in DOWN state: - if entity.status != otypes.VmStatus.DOWN: - if not self._module.check_mode: - self.changed = self.action( - action='stop', - action_condition=lambda vm: vm.status != otypes.VmStatus.DOWN, - wait_condition=lambda vm: vm.status == otypes.VmStatus.DOWN, - )['changed'] - - def __suspend_shutdown_common(self, vm_service): - if vm_service.get().status in [ - otypes.VmStatus.MIGRATING, - otypes.VmStatus.POWERING_UP, - otypes.VmStatus.REBOOT_IN_PROGRESS, - otypes.VmStatus.WAIT_FOR_LAUNCH, - otypes.VmStatus.UP, - otypes.VmStatus.RESTORING_STATE, - ]: - self._wait_for_UP(vm_service) - - def _pre_shutdown_action(self, entity): - vm_service = self._service.vm_service(entity.id) - self.__suspend_shutdown_common(vm_service) - if entity.status in [otypes.VmStatus.SUSPENDED, otypes.VmStatus.PAUSED]: - vm_service.start() - self._wait_for_UP(vm_service) - return vm_service.get() - - def _pre_suspend_action(self, entity): - vm_service = self._service.vm_service(entity.id) - self.__suspend_shutdown_common(vm_service) - if entity.status in [otypes.VmStatus.PAUSED, otypes.VmStatus.DOWN]: - vm_service.start() - self._wait_for_UP(vm_service) - return vm_service.get() - - def _post_start_action(self, entity): - vm_service = self._service.service(entity.id) - self._wait_for_UP(vm_service) - self._attach_cd(vm_service.get()) - - def _attach_cd(self, entity): - cd_iso = self.param('cd_iso') - if cd_iso is not None: - vm_service = self._service.service(entity.id) - current = vm_service.get().status == otypes.VmStatus.UP and self.param('state') == 'running' - cdroms_service = vm_service.cdroms_service() - cdrom_device = cdroms_service.list()[0] - cdrom_service = cdroms_service.cdrom_service(cdrom_device.id) - cdrom = cdrom_service.get(current=current) - if getattr(cdrom.file, 'id', '') != cd_iso: - if not self._module.check_mode: - cdrom_service.update( - cdrom=otypes.Cdrom( - file=otypes.File(id=cd_iso) - ), - current=current, - ) - self.changed = True - - return entity - - def _migrate_vm(self, entity): - vm_host = self.param('host') - vm_service = self._service.vm_service(entity.id) - # In case VM is preparing to be UP, wait to be up, to migrate it: - if entity.status == otypes.VmStatus.UP: - if vm_host is not None: - hosts_service = self._connection.system_service().hosts_service() - current_vm_host = hosts_service.host_service(entity.host.id).get().name - if vm_host != current_vm_host: - if not self._module.check_mode: - vm_service.migrate(host=otypes.Host(name=vm_host), force=self.param('force_migrate')) - self._wait_for_UP(vm_service) - self.changed = True - elif self.param('migrate'): - if not self._module.check_mode: - vm_service.migrate(force=self.param('force_migrate')) - self._wait_for_UP(vm_service) - self.changed = True - return entity - - def _wait_for_UP(self, vm_service): - wait( - service=vm_service, - condition=lambda vm: vm.status == otypes.VmStatus.UP, - wait=self.param('wait'), - timeout=self.param('timeout'), - ) - - def _wait_for_vm_disks(self, vm_service): - disks_service = self._connection.system_service().disks_service() - for da in vm_service.disk_attachments_service().list(): - disk_service = disks_service.disk_service(da.disk.id) - wait( - service=disk_service, - condition=lambda disk: disk.status == otypes.DiskStatus.OK if disk.storage_type == otypes.DiskStorageType.IMAGE else True, - wait=self.param('wait'), - timeout=self.param('timeout'), - ) - - def wait_for_down(self, vm): - """ - This function will first wait for the status DOWN of the VM. - Then it will find the active snapshot and wait until it's state is OK for - stateless VMs and stateless snapshot is removed. - """ - vm_service = self._service.vm_service(vm.id) - wait( - service=vm_service, - condition=lambda vm: vm.status == otypes.VmStatus.DOWN, - wait=self.param('wait'), - timeout=self.param('timeout'), - ) - if vm.stateless: - snapshots_service = vm_service.snapshots_service() - snapshots = snapshots_service.list() - snap_active = [ - snap for snap in snapshots - if snap.snapshot_type == otypes.SnapshotType.ACTIVE - ][0] - snap_stateless = [ - snap for snap in snapshots - if snap.snapshot_type == otypes.SnapshotType.STATELESS - ] - # Stateless snapshot may be already removed: - if snap_stateless: - """ - We need to wait for Active snapshot ID, to be removed as it's current - stateless snapshot. Then we need to wait for staless snapshot ID to - be read, for use, because it will become active snapshot. - """ - wait( - service=snapshots_service.snapshot_service(snap_active.id), - condition=lambda snap: snap is None, - wait=self.param('wait'), - timeout=self.param('timeout'), - ) - wait( - service=snapshots_service.snapshot_service(snap_stateless[0].id), - condition=lambda snap: snap.snapshot_status == otypes.SnapshotStatus.OK, - wait=self.param('wait'), - timeout=self.param('timeout'), - ) - return True - - def __attach_graphical_console(self, entity): - graphical_console = self.param('graphical_console') - if not graphical_console: - return False - - vm_service = self._service.service(entity.id) - gcs_service = vm_service.graphics_consoles_service() - graphical_consoles = gcs_service.list() - - # Remove all graphical consoles if there are any: - if bool(graphical_console.get('headless_mode')): - if not self._module.check_mode: - for gc in graphical_consoles: - gcs_service.console_service(gc.id).remove() - return len(graphical_consoles) > 0 - - # If there are not gc add any gc to be added: - protocol = graphical_console.get('protocol') - current_protocols = [str(gc.protocol) for gc in graphical_consoles] - if not current_protocols: - if not self._module.check_mode: - for p in protocol: - gcs_service.add( - otypes.GraphicsConsole( - protocol=otypes.GraphicsType(p), - ) - ) - return True - - # Update consoles: - if sorted(protocol) != sorted(current_protocols): - if not self._module.check_mode: - for gc in graphical_consoles: - gcs_service.console_service(gc.id).remove() - for p in protocol: - gcs_service.add( - otypes.GraphicsConsole( - protocol=otypes.GraphicsType(p), - ) - ) - return True - - def __attach_disks(self, entity): - if not self.param('disks'): - return - - vm_service = self._service.service(entity.id) - disks_service = self._connection.system_service().disks_service() - disk_attachments_service = vm_service.disk_attachments_service() - - self._wait_for_vm_disks(vm_service) - for disk in self.param('disks'): - # If disk ID is not specified, find disk by name: - disk_id = disk.get('id') - if disk_id is None: - disk_id = getattr( - search_by_name( - service=disks_service, - name=disk.get('name') - ), - 'id', - None - ) - - # Attach disk to VM: - disk_attachment = disk_attachments_service.attachment_service(disk_id) - if get_entity(disk_attachment) is None: - if not self._module.check_mode: - disk_attachments_service.add( - otypes.DiskAttachment( - disk=otypes.Disk( - id=disk_id, - ), - active=disk.get('activate', True), - interface=otypes.DiskInterface( - disk.get('interface', 'virtio') - ), - bootable=disk.get('bootable', False), - ) - ) - self.changed = True - - def __get_vnic_profile_id(self, nic): - """ - Return VNIC profile ID looked up by it's name, because there can be - more VNIC profiles with same name, other criteria of filter is cluster. - """ - vnics_service = self._connection.system_service().vnic_profiles_service() - clusters_service = self._connection.system_service().clusters_service() - cluster = search_by_name(clusters_service, self.param('cluster')) - profiles = [ - profile for profile in vnics_service.list() - if profile.name == nic.get('profile_name') - ] - cluster_networks = [ - net.id for net in self._connection.follow_link(cluster.networks) - ] - try: - return next( - profile.id for profile in profiles - if profile.network.id in cluster_networks - ) - except StopIteration: - raise Exception( - "Profile '%s' was not found in cluster '%s'" % ( - nic.get('profile_name'), - self.param('cluster') - ) - ) - - def __get_numa_serialized(self, numa): - return sorted([(x.index, - [y.index for y in x.cpu.cores] if x.cpu else [], - x.memory, - [y.index for y in x.numa_node_pins] if x.numa_node_pins else [] - ) for x in numa], key=lambda x: x[0]) - - def __attach_numa_nodes(self, entity): - numa_nodes_service = self._service.service(entity.id).numa_nodes_service() - existed_numa_nodes = numa_nodes_service.list() - if len(self.param('numa_nodes')) > 0: - # Remove all existing virtual numa nodes before adding new ones - for current_numa_node in sorted(existed_numa_nodes, reverse=True, key=lambda x: x.index): - numa_nodes_service.node_service(current_numa_node.id).remove() - - for numa_node in self.param('numa_nodes'): - if numa_node is None or numa_node.get('index') is None or numa_node.get('cores') is None or numa_node.get('memory') is None: - continue - - numa_nodes_service.add( - otypes.VirtualNumaNode( - index=numa_node.get('index'), - memory=numa_node.get('memory'), - cpu=otypes.Cpu( - cores=[ - otypes.Core( - index=core - ) for core in numa_node.get('cores') - ], - ), - numa_node_pins=[ - otypes.NumaNodePin( - index=pin - ) for pin in numa_node.get('numa_node_pins') - ] if numa_node.get('numa_node_pins') is not None else None, - ) - ) - return self.__get_numa_serialized(numa_nodes_service.list()) != self.__get_numa_serialized(existed_numa_nodes) - - def __attach_watchdog(self, entity): - watchdogs_service = self._service.service(entity.id).watchdogs_service() - watchdog = self.param('watchdog') - if watchdog is not None: - current_watchdog = next(iter(watchdogs_service.list()), None) - if watchdog.get('model') is None and current_watchdog: - watchdogs_service.watchdog_service(current_watchdog.id).remove() - return True - elif watchdog.get('model') is not None and current_watchdog is None: - watchdogs_service.add( - otypes.Watchdog( - model=otypes.WatchdogModel(watchdog.get('model').lower()), - action=otypes.WatchdogAction(watchdog.get('action')), - ) - ) - return True - elif current_watchdog is not None: - if ( - str(current_watchdog.model).lower() != watchdog.get('model').lower() or - str(current_watchdog.action).lower() != watchdog.get('action').lower() - ): - watchdogs_service.watchdog_service(current_watchdog.id).update( - otypes.Watchdog( - model=otypes.WatchdogModel(watchdog.get('model')), - action=otypes.WatchdogAction(watchdog.get('action')), - ) - ) - return True - return False - - def __attach_nics(self, entity): - # Attach NICs to VM, if specified: - nics_service = self._service.service(entity.id).nics_service() - for nic in self.param('nics'): - if search_by_name(nics_service, nic.get('name')) is None: - if not self._module.check_mode: - nics_service.add( - otypes.Nic( - name=nic.get('name'), - interface=otypes.NicInterface( - nic.get('interface', 'virtio') - ), - vnic_profile=otypes.VnicProfile( - id=self.__get_vnic_profile_id(nic), - ) if nic.get('profile_name') else None, - mac=otypes.Mac( - address=nic.get('mac_address') - ) if nic.get('mac_address') else None, - ) - ) - self.changed = True - - def get_initialization(self): - if self._initialization is not None: - return self._initialization - - sysprep = self.param('sysprep') - cloud_init = self.param('cloud_init') - cloud_init_nics = self.param('cloud_init_nics') or [] - if cloud_init is not None: - cloud_init_nics.append(cloud_init) - - if cloud_init or cloud_init_nics: - self._initialization = otypes.Initialization( - nic_configurations=[ - otypes.NicConfiguration( - boot_protocol=otypes.BootProtocol( - nic.pop('nic_boot_protocol').lower() - ) if nic.get('nic_boot_protocol') else None, - ipv6_boot_protocol=otypes.BootProtocol( - nic.pop('nic_boot_protocol_v6').lower() - ) if nic.get('nic_boot_protocol_v6') else None, - name=nic.pop('nic_name', None), - on_boot=nic.pop('nic_on_boot', None), - ip=otypes.Ip( - address=nic.pop('nic_ip_address', None), - netmask=nic.pop('nic_netmask', None), - gateway=nic.pop('nic_gateway', None), - version=otypes.IpVersion('v4') - ) if ( - nic.get('nic_gateway') is not None or - nic.get('nic_netmask') is not None or - nic.get('nic_ip_address') is not None - ) else None, - ipv6=otypes.Ip( - address=nic.pop('nic_ip_address_v6', None), - netmask=nic.pop('nic_netmask_v6', None), - gateway=nic.pop('nic_gateway_v6', None), - version=otypes.IpVersion('v6') - ) if ( - nic.get('nic_gateway_v6') is not None or - nic.get('nic_netmask_v6') is not None or - nic.get('nic_ip_address_v6') is not None - ) else None, - ) - for nic in cloud_init_nics - if ( - nic.get('nic_boot_protocol_v6') is not None or - nic.get('nic_ip_address_v6') is not None or - nic.get('nic_gateway_v6') is not None or - nic.get('nic_netmask_v6') is not None or - nic.get('nic_gateway') is not None or - nic.get('nic_netmask') is not None or - nic.get('nic_ip_address') is not None or - nic.get('nic_boot_protocol') is not None or - nic.get('nic_on_boot') is not None - ) - ] if cloud_init_nics else None, - **cloud_init - ) - elif sysprep: - self._initialization = otypes.Initialization( - **sysprep - ) - return self._initialization - - def __attach_host_devices(self, entity): - vm_service = self._service.service(entity.id) - host_devices_service = vm_service.host_devices_service() - host_devices = self.param('host_devices') - updated = False - if host_devices: - device_names = [dev.name for dev in host_devices_service.list()] - for device in host_devices: - device_name = device.get('name') - state = device.get('state', 'present') - if state == 'absent' and device_name in device_names: - updated = True - if not self._module.check_mode: - device_id = get_id_by_name(host_devices_service, device.get('name')) - host_devices_service.device_service(device_id).remove() - - elif state == 'present' and device_name not in device_names: - updated = True - if not self._module.check_mode: - host_devices_service.add( - otypes.HostDevice( - name=device.get('name'), - ) - ) - - return updated - - -def _get_role_mappings(module): - roleMappings = list() - for roleMapping in module.params['role_mappings']: - roleMappings.append( - otypes.RegistrationRoleMapping( - from_=otypes.Role( - name=roleMapping['source_name'], - ) if roleMapping['source_name'] else None, - to=otypes.Role( - name=roleMapping['dest_name'], - ) if roleMapping['dest_name'] else None, - ) - ) - return roleMappings - - -def _get_affinity_group_mappings(module): - affinityGroupMappings = list() - - for affinityGroupMapping in module.params['affinity_group_mappings']: - affinityGroupMappings.append( - otypes.RegistrationAffinityGroupMapping( - from_=otypes.AffinityGroup( - name=affinityGroupMapping['source_name'], - ) if affinityGroupMapping['source_name'] else None, - to=otypes.AffinityGroup( - name=affinityGroupMapping['dest_name'], - ) if affinityGroupMapping['dest_name'] else None, - ) - ) - return affinityGroupMappings - - -def _get_affinity_label_mappings(module): - affinityLabelMappings = list() - - for affinityLabelMapping in module.params['affinity_label_mappings']: - affinityLabelMappings.append( - otypes.RegistrationAffinityLabelMapping( - from_=otypes.AffinityLabel( - name=affinityLabelMapping['source_name'], - ) if affinityLabelMapping['source_name'] else None, - to=otypes.AffinityLabel( - name=affinityLabelMapping['dest_name'], - ) if affinityLabelMapping['dest_name'] else None, - ) - ) - return affinityLabelMappings - - -def _get_domain_mappings(module): - domainMappings = list() - - for domainMapping in module.params['domain_mappings']: - domainMappings.append( - otypes.RegistrationDomainMapping( - from_=otypes.Domain( - name=domainMapping['source_name'], - ) if domainMapping['source_name'] else None, - to=otypes.Domain( - name=domainMapping['dest_name'], - ) if domainMapping['dest_name'] else None, - ) - ) - return domainMappings - - -def _get_lun_mappings(module): - lunMappings = list() - for lunMapping in module.params['lun_mappings']: - lunMappings.append( - otypes.RegistrationLunMapping( - from_=otypes.Disk( - lun_storage=otypes.HostStorage( - type=otypes.StorageType(lunMapping['source_storage_type']) - if (lunMapping['source_storage_type'] in - ['iscsi', 'fcp']) else None, - logical_units=[ - otypes.LogicalUnit( - id=lunMapping['source_logical_unit_id'], - ) - ], - ), - ) if lunMapping['source_logical_unit_id'] else None, - to=otypes.Disk( - lun_storage=otypes.HostStorage( - type=otypes.StorageType(lunMapping['dest_storage_type']) - if (lunMapping['dest_storage_type'] in - ['iscsi', 'fcp']) else None, - logical_units=[ - otypes.LogicalUnit( - id=lunMapping.get('dest_logical_unit_id'), - port=lunMapping.get('dest_logical_unit_port'), - portal=lunMapping.get('dest_logical_unit_portal'), - address=lunMapping.get('dest_logical_unit_address'), - target=lunMapping.get('dest_logical_unit_target'), - password=lunMapping.get('dest_logical_unit_password'), - username=lunMapping.get('dest_logical_unit_username'), - ) - ], - ), - ) if lunMapping['dest_logical_unit_id'] else None, - ), - ), - return lunMappings - - -def _get_cluster_mappings(module): - clusterMappings = list() - - for clusterMapping in module.params['cluster_mappings']: - clusterMappings.append( - otypes.RegistrationClusterMapping( - from_=otypes.Cluster( - name=clusterMapping['source_name'], - ), - to=otypes.Cluster( - name=clusterMapping['dest_name'], - ) if clusterMapping['dest_name'] else None, - ) - ) - return clusterMappings - - -def _get_vnic_profile_mappings(module): - vnicProfileMappings = list() - - for vnicProfileMapping in module.params['vnic_profile_mappings']: - vnicProfileMappings.append( - otypes.VnicProfileMapping( - source_network_name=vnicProfileMapping['source_network_name'], - source_network_profile_name=vnicProfileMapping['source_profile_name'], - target_vnic_profile=otypes.VnicProfile( - id=vnicProfileMapping['target_profile_id'], - ) if vnicProfileMapping['target_profile_id'] else None, - ) - ) - - return vnicProfileMappings - - -def import_vm(module, connection): - vms_service = connection.system_service().vms_service() - if search_by_name(vms_service, module.params['name']) is not None: - return False - - events_service = connection.system_service().events_service() - last_event = events_service.list(max=1)[0] - - external_type = [ - tmp for tmp in ['kvm', 'xen', 'vmware'] - if module.params[tmp] is not None - ][0] - - external_vm = module.params[external_type] - imports_service = connection.system_service().external_vm_imports_service() - imported_vm = imports_service.add( - otypes.ExternalVmImport( - vm=otypes.Vm( - name=module.params['name'] - ), - name=external_vm.get('name'), - username=external_vm.get('username', 'test'), - password=external_vm.get('password', 'test'), - provider=otypes.ExternalVmProviderType(external_type), - url=external_vm.get('url'), - cluster=otypes.Cluster( - name=module.params['cluster'], - ) if module.params['cluster'] else None, - storage_domain=otypes.StorageDomain( - name=external_vm.get('storage_domain'), - ) if external_vm.get('storage_domain') else None, - sparse=external_vm.get('sparse', True), - host=otypes.Host( - name=module.params['host'], - ) if module.params['host'] else None, - ) - ) - - # Wait until event with code 1152 for our VM don't appear: - vms_service = connection.system_service().vms_service() - wait( - service=vms_service.vm_service(imported_vm.vm.id), - condition=lambda vm: len([ - event - for event in events_service.list( - from_=int(last_event.id), - search='type=1152 and vm.id=%s' % vm.id, - ) - ]) > 0 if vm is not None else False, - fail_condition=lambda vm: vm is None, - timeout=module.params['timeout'], - poll_interval=module.params['poll_interval'], - ) - return True - - -def control_state(vm, vms_service, module): - if vm is None: - return - - force = module.params['force'] - state = module.params['state'] - - vm_service = vms_service.vm_service(vm.id) - if vm.status == otypes.VmStatus.IMAGE_LOCKED: - wait( - service=vm_service, - condition=lambda vm: vm.status == otypes.VmStatus.DOWN, - ) - elif vm.status == otypes.VmStatus.SAVING_STATE: - # Result state is SUSPENDED, we should wait to be suspended: - wait( - service=vm_service, - condition=lambda vm: vm.status == otypes.VmStatus.SUSPENDED, - ) - elif ( - vm.status == otypes.VmStatus.UNASSIGNED or - vm.status == otypes.VmStatus.UNKNOWN - ): - # Invalid states: - module.fail_json(msg="Not possible to control VM, if it's in '{0}' status".format(vm.status)) - elif vm.status == otypes.VmStatus.POWERING_DOWN: - if (force and state == 'stopped') or state == 'absent': - vm_service.stop() - wait( - service=vm_service, - condition=lambda vm: vm.status == otypes.VmStatus.DOWN, - ) - else: - # If VM is powering down, wait to be DOWN or UP. - # VM can end in UP state in case there is no GA - # or ACPI on the VM or shutdown operation crashed: - wait( - service=vm_service, - condition=lambda vm: vm.status in [otypes.VmStatus.DOWN, otypes.VmStatus.UP], - ) - - -def main(): - argument_spec = ovirt_full_argument_spec( - state=dict(type='str', default='present', choices=[ - 'absent', 'next_run', 'present', 'registered', 'running', 'stopped', 'suspended', 'exported', 'reboot' - ]), - name=dict(type='str'), - id=dict(type='str'), - cluster=dict(type='str'), - allow_partial_import=dict(type='bool'), - template=dict(type='str'), - template_version=dict(type='int'), - use_latest_template_version=dict(type='bool'), - storage_domain=dict(type='str'), - disk_format=dict(type='str', default='cow', choices=['cow', 'raw']), - disks=dict(type='list', default=[]), - memory=dict(type='str'), - memory_guaranteed=dict(type='str'), - memory_max=dict(type='str'), - cpu_sockets=dict(type='int'), - cpu_cores=dict(type='int'), - cpu_shares=dict(type='int'), - cpu_threads=dict(type='int'), - type=dict(type='str', choices=['server', 'desktop', 'high_performance']), - operating_system=dict(type='str'), - cd_iso=dict(type='str'), - boot_devices=dict(type='list', choices=['cdrom', 'hd', 'network']), - vnic_profile_mappings=dict(default=[], type='list'), - cluster_mappings=dict(default=[], type='list'), - role_mappings=dict(default=[], type='list'), - affinity_group_mappings=dict(default=[], type='list'), - affinity_label_mappings=dict(default=[], type='list'), - lun_mappings=dict(default=[], type='list'), - domain_mappings=dict(default=[], type='list'), - reassign_bad_macs=dict(default=None, type='bool'), - boot_menu=dict(type='bool'), - serial_console=dict(type='bool'), - usb_support=dict(type='bool'), - sso=dict(type='bool'), - quota_id=dict(type='str'), - high_availability=dict(type='bool'), - high_availability_priority=dict(type='int'), - lease=dict(type='str'), - stateless=dict(type='bool'), - delete_protected=dict(type='bool'), - custom_emulated_machine=dict(type='str'), - force=dict(type='bool', default=False), - nics=dict(type='list', default=[]), - cloud_init=dict(type='dict'), - cloud_init_nics=dict(type='list', default=[]), - cloud_init_persist=dict(type='bool', default=False, aliases=['sysprep_persist']), - kernel_params_persist=dict(type='bool', default=False), - sysprep=dict(type='dict'), - host=dict(type='str'), - clone=dict(type='bool', default=False), - clone_permissions=dict(type='bool', default=False), - kernel_path=dict(type='str'), - initrd_path=dict(type='str'), - kernel_params=dict(type='str'), - instance_type=dict(type='str'), - description=dict(type='str'), - comment=dict(type='str'), - timezone=dict(type='str'), - serial_policy=dict(type='str', choices=['vm', 'host', 'custom']), - serial_policy_value=dict(type='str'), - vmware=dict(type='dict'), - xen=dict(type='dict'), - kvm=dict(type='dict'), - cpu_mode=dict(type='str'), - placement_policy=dict(type='str'), - custom_compatibility_version=dict(type='str'), - ticket=dict(type='bool', default=None), - cpu_pinning=dict(type='list'), - soundcard_enabled=dict(type='bool', default=None), - smartcard_enabled=dict(type='bool', default=None), - io_threads=dict(type='int', default=None), - ballooning_enabled=dict(type='bool', default=None), - rng_device=dict(type='str'), - numa_tune_mode=dict(type='str', choices=['interleave', 'preferred', 'strict']), - numa_nodes=dict(type='list', default=[]), - custom_properties=dict(type='list'), - watchdog=dict(type='dict'), - host_devices=dict(type='list'), - graphical_console=dict( - type='dict', - options=dict( - headless_mode=dict(type='bool'), - protocol=dict(type='list'), - disconnect_action=dict(type='str'), - keyboard_layout=dict(type='str'), - monitors=dict(type='int'), - ) - ), - exclusive=dict(type='bool'), - export_domain=dict(default=None), - export_ova=dict(type='dict'), - force_migrate=dict(type='bool'), - migrate=dict(type='bool', default=None), - next_run=dict(type='bool'), - snapshot_name=dict(type='str'), - snapshot_vm=dict(type='str'), - ) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - required_one_of=[['id', 'name']], - required_if=[ - ('state', 'registered', ['storage_domain']), - ], - required_together=[['snapshot_name', 'snapshot_vm']] - ) - - check_sdk(module) - check_params(module) - - try: - state = module.params['state'] - auth = module.params.pop('auth') - connection = create_connection(auth) - vms_service = connection.system_service().vms_service() - vms_module = VmsModule( - connection=connection, - module=module, - service=vms_service, - ) - vm = vms_module.search_entity(list_params={'all_content': True}) - - # Boolean variable to mark if vm existed before module was executed - vm_existed = True if vm else False - control_state(vm, vms_service, module) - if state in ('present', 'running', 'next_run'): - if module.params['xen'] or module.params['kvm'] or module.params['vmware']: - vms_module.changed = import_vm(module, connection) - - # In case of wait=false and state=running, waits for VM to be created - # In case VM don't exist, wait for VM DOWN state, - # otherwise don't wait for any state, just update VM: - ret = vms_module.create( - entity=vm, - result_state=otypes.VmStatus.DOWN if vm is None else None, - update_params={'next_run': module.params['next_run']} if module.params['next_run'] is not None else None, - clone=module.params['clone'], - clone_permissions=module.params['clone_permissions'], - _wait=True if not module.params['wait'] and state == 'running' else module.params['wait'], - ) - # If VM is going to be created and check_mode is on, return now: - if module.check_mode and ret.get('id') is None: - module.exit_json(**ret) - - vms_module.post_present(ret['id']) - # Run the VM if it was just created, else don't run it: - if state == 'running': - def kernel_persist_check(): - return (module.params.get('kernel_params') or - module.params.get('initrd_path') or - module.params.get('kernel_path') - and not module.params.get('cloud_init_persist')) - initialization = vms_module.get_initialization() - ret = vms_module.action( - action='start', - post_action=vms_module._post_start_action, - action_condition=lambda vm: ( - vm.status not in [ - otypes.VmStatus.MIGRATING, - otypes.VmStatus.POWERING_UP, - otypes.VmStatus.REBOOT_IN_PROGRESS, - otypes.VmStatus.WAIT_FOR_LAUNCH, - otypes.VmStatus.UP, - otypes.VmStatus.RESTORING_STATE, - ] - ), - wait_condition=lambda vm: vm.status == otypes.VmStatus.UP, - # Start action kwargs: - use_cloud_init=True if not module.params.get('cloud_init_persist') and module.params.get('cloud_init') else None, - use_sysprep=True if not module.params.get('cloud_init_persist') and module.params.get('sysprep') else None, - vm=otypes.Vm( - placement_policy=otypes.VmPlacementPolicy( - hosts=[otypes.Host(name=module.params['host'])] - ) if module.params['host'] else None, - initialization=initialization, - os=otypes.OperatingSystem( - cmdline=module.params.get('kernel_params'), - initrd=module.params.get('initrd_path'), - kernel=module.params.get('kernel_path'), - ) if (kernel_persist_check()) else None, - ) if ( - kernel_persist_check() or - module.params.get('host') or - initialization is not None - and not module.params.get('cloud_init_persist') - ) else None, - ) - - if module.params['ticket']: - vm_service = vms_service.vm_service(ret['id']) - graphics_consoles_service = vm_service.graphics_consoles_service() - graphics_console = graphics_consoles_service.list()[0] - console_service = graphics_consoles_service.console_service(graphics_console.id) - ticket = console_service.remote_viewer_connection_file() - if ticket: - ret['vm']['remote_vv_file'] = ticket - - if state == 'next_run': - # Apply next run configuration, if needed: - vm = vms_service.vm_service(ret['id']).get() - if vm.next_run_configuration_exists: - ret = vms_module.action( - action='reboot', - entity=vm, - action_condition=lambda vm: vm.status == otypes.VmStatus.UP, - wait_condition=lambda vm: vm.status == otypes.VmStatus.UP, - ) - # Allow migrate vm when state present. - if vm_existed: - vms_module._migrate_vm(vm) - ret['changed'] = vms_module.changed - elif state == 'stopped': - if module.params['xen'] or module.params['kvm'] or module.params['vmware']: - vms_module.changed = import_vm(module, connection) - - ret = vms_module.create( - entity=vm, - result_state=otypes.VmStatus.DOWN if vm is None else None, - clone=module.params['clone'], - clone_permissions=module.params['clone_permissions'], - ) - if module.params['force']: - ret = vms_module.action( - action='stop', - action_condition=lambda vm: vm.status != otypes.VmStatus.DOWN, - wait_condition=vms_module.wait_for_down, - ) - else: - ret = vms_module.action( - action='shutdown', - pre_action=vms_module._pre_shutdown_action, - action_condition=lambda vm: vm.status != otypes.VmStatus.DOWN, - wait_condition=vms_module.wait_for_down, - ) - vms_module.post_present(ret['id']) - elif state == 'suspended': - ret = vms_module.create( - entity=vm, - result_state=otypes.VmStatus.DOWN if vm is None else None, - clone=module.params['clone'], - clone_permissions=module.params['clone_permissions'], - ) - vms_module.post_present(ret['id']) - ret = vms_module.action( - action='suspend', - pre_action=vms_module._pre_suspend_action, - action_condition=lambda vm: vm.status != otypes.VmStatus.SUSPENDED, - wait_condition=lambda vm: vm.status == otypes.VmStatus.SUSPENDED, - ) - elif state == 'absent': - ret = vms_module.remove() - elif state == 'registered': - storage_domains_service = connection.system_service().storage_domains_service() - - # Find the storage domain with unregistered VM: - sd_id = get_id_by_name(storage_domains_service, module.params['storage_domain']) - storage_domain_service = storage_domains_service.storage_domain_service(sd_id) - vms_service = storage_domain_service.vms_service() - - # Find the unregistered VM we want to register: - vms = vms_service.list(unregistered=True) - vm = next( - (vm for vm in vms if (vm.id == module.params['id'] or vm.name == module.params['name'])), - None - ) - changed = False - if vm is None: - vm = vms_module.search_entity() - if vm is None: - raise ValueError( - "VM '%s(%s)' wasn't found." % (module.params['name'], module.params['id']) - ) - else: - # Register the vm into the system: - changed = True - vm_service = vms_service.vm_service(vm.id) - vm_service.register( - allow_partial_import=module.params['allow_partial_import'], - cluster=otypes.Cluster( - name=module.params['cluster'] - ) if module.params['cluster'] else None, - vnic_profile_mappings=_get_vnic_profile_mappings(module) - if module.params['vnic_profile_mappings'] else None, - reassign_bad_macs=module.params['reassign_bad_macs'] - if module.params['reassign_bad_macs'] is not None else None, - registration_configuration=otypes.RegistrationConfiguration( - cluster_mappings=_get_cluster_mappings(module), - role_mappings=_get_role_mappings(module), - domain_mappings=_get_domain_mappings(module), - lun_mappings=_get_lun_mappings(module), - affinity_group_mappings=_get_affinity_group_mappings(module), - affinity_label_mappings=_get_affinity_label_mappings(module), - ) if (module.params['cluster_mappings'] - or module.params['role_mappings'] - or module.params['domain_mappings'] - or module.params['lun_mappings'] - or module.params['affinity_group_mappings'] - or module.params['affinity_label_mappings']) else None - ) - - if module.params['wait']: - vm = vms_module.wait_for_import() - else: - # Fetch vm to initialize return. - vm = vm_service.get() - ret = { - 'changed': changed, - 'id': vm.id, - 'vm': get_dict_of_struct(vm) - } - elif state == 'exported': - if module.params['export_domain']: - export_service = vms_module._get_export_domain_service() - export_vm = search_by_attributes(export_service.vms_service(), id=vm.id) - - ret = vms_module.action( - entity=vm, - action='export', - action_condition=lambda t: export_vm is None or module.params['exclusive'], - wait_condition=lambda t: t is not None, - post_action=vms_module.post_export_action, - storage_domain=otypes.StorageDomain(id=export_service.get().id), - exclusive=module.params['exclusive'], - ) - elif module.params['export_ova']: - export_vm = module.params['export_ova'] - ret = vms_module.action( - entity=vm, - action='export_to_path_on_host', - host=otypes.Host(name=export_vm.get('host')), - directory=export_vm.get('directory'), - filename=export_vm.get('filename'), - ) - elif state == 'reboot': - ret = vms_module.action( - action='reboot', - entity=vm, - action_condition=lambda vm: vm.status == otypes.VmStatus.UP, - wait_condition=lambda vm: vm.status == otypes.VmStatus.UP, - ) - - module.exit_json(**ret) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_vm_info.py b/lib/ansible/modules/cloud/ovirt/ovirt_vm_info.py deleted file mode 100644 index 9e5a1edff2..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_vm_info.py +++ /dev/null @@ -1,160 +0,0 @@ -#!/usr/bin/python -# -*- 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 . -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_vm_info -short_description: Retrieve information about one or more oVirt/RHV virtual machines -author: "Ondra Machacek (@machacekondra)" -version_added: "2.3" -description: - - "Retrieve information about one or more oVirt/RHV virtual machines." - - This module was called C(ovirt_vm_facts) before Ansible 2.9, returning C(ansible_facts). - Note that the M(ovirt_vm_info) module no longer returns C(ansible_facts)! -notes: - - "This module returns a variable C(ovirt_vms), which - contains a list of virtual machines. You need to register the result with - the I(register) keyword to use it." -options: - pattern: - description: - - "Search term which is accepted by oVirt/RHV search backend." - - "For example to search VM X from cluster Y use following pattern: - name=X and cluster=Y" - all_content: - description: - - "If I(true) all the attributes of the virtual machines should be - included in the response." - type: bool - case_sensitive: - description: - - "If I(true) performed search will take case into account." - type: bool - default: true - max: - description: - - "The maximum number of results to return." - next_run: - description: - - "Indicates if the returned result describes the virtual machine as it is currently running or if describes - the virtual machine with the modifications that have already been performed but that will only come into - effect when the virtual machine is restarted. By default the value is set by engine." - type: bool - version_added: "2.8" -extends_documentation_fragment: ovirt_info -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Gather information about all VMs which names start with C(centos) and -# belong to cluster C(west): -- ovirt_vm_info: - pattern: name=centos* and cluster=west - register: result -- debug: - msg: "{{ result.ovirt_vms }}" - -# Gather info about next run configuration of virtual machine named myvm -- ovirt_vm_info: - pattern: name=myvm - next_run: true - register: result -- debug: - msg: "{{ result.ovirt_vms[0] }}" -''' - -RETURN = ''' -ovirt_vms: - description: "List of dictionaries describing the VMs. VM attributes are mapped to dictionary keys, - all VMs attributes can be found at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/vm." - returned: On success. - type: list -''' - -import traceback - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - check_sdk, - create_connection, - get_dict_of_struct, - ovirt_info_full_argument_spec, -) - - -def main(): - argument_spec = ovirt_info_full_argument_spec( - pattern=dict(default='', required=False), - all_content=dict(default=False, type='bool'), - next_run=dict(default=None, type='bool'), - case_sensitive=dict(default=True, type='bool'), - max=dict(default=None, type='int'), - ) - module = AnsibleModule(argument_spec) - is_old_facts = module._name == 'ovirt_vm_facts' - if is_old_facts: - module.deprecate("The 'ovirt_vm_facts' module has been renamed to 'ovirt_vm_info', " - "and the renamed one no longer returns ansible_facts", version='2.13') - - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - vms_service = connection.system_service().vms_service() - vms = vms_service.list( - search=module.params['pattern'], - all_content=module.params['all_content'], - case_sensitive=module.params['case_sensitive'], - max=module.params['max'], - ) - if module.params['next_run']: - vms = [vms_service.vm_service(vm.id).get(next_run=True) for vm in vms] - - result = dict( - ovirt_vms=[ - get_dict_of_struct( - struct=c, - connection=connection, - fetch_nested=module.params.get('fetch_nested'), - attributes=module.params.get('nested_attributes'), - ) for c in vms - ], - ) - if is_old_facts: - module.exit_json(changed=False, ansible_facts=result) - else: - module.exit_json(changed=False, **result) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_vmpool.py b/lib/ansible/modules/cloud/ovirt/ovirt_vmpool.py deleted file mode 100644 index 88a689ca6e..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_vmpool.py +++ /dev/null @@ -1,485 +0,0 @@ -#!/usr/bin/python -# -*- 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 . -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_vmpool -short_description: Module to manage VM pools in oVirt/RHV -version_added: "2.3" -author: "Ondra Machacek (@machacekondra)" -description: - - "Module to manage VM pools in oVirt/RHV." -options: - id: - description: - - "ID of the vmpool to manage." - version_added: "2.8" - name: - description: - - "Name of the VM pool to manage." - required: true - comment: - description: - - Comment of the Virtual Machine pool. - state: - description: - - "Should the VM pool be present/absent." - - "Note that when C(state) is I(absent) all VMs in VM pool are stopped and removed." - choices: ['present', 'absent'] - default: present - template: - description: - - "Name of the template, which will be used to create VM pool." - description: - description: - - "Description of the VM pool." - cluster: - description: - - "Name of the cluster, where VM pool should be created." - type: - description: - - "Type of the VM pool. Either manual or automatic." - - "C(manual) - The administrator is responsible for explicitly returning the virtual machine to the pool. - The virtual machine reverts to the original base image after the administrator returns it to the pool." - - "C(Automatic) - When the virtual machine is shut down, it automatically reverts to its base image and - is returned to the virtual machine pool." - - "Default value is set by engine." - choices: ['manual', 'automatic'] - vm_per_user: - description: - - "Maximum number of VMs a single user can attach to from this pool." - - "Default value is set by engine." - prestarted: - description: - - "Number of pre-started VMs defines the number of VMs in run state, that are waiting - to be attached to Users." - - "Default value is set by engine." - vm_count: - description: - - "Number of VMs in the pool." - - "Default value is set by engine." - vm: - description: - - "For creating vm pool without editing template." - - "Note: You can use C(vm) only for creating vm pool." - type: dict - suboptions: - comment: - description: - - Comment of the Virtual Machine. - timezone: - description: - - Sets time zone offset of the guest hardware clock. - - For example C(Etc/GMT) - memory: - description: - - Amount of memory of the Virtual Machine. Prefix uses IEC 60027-2 standard (for example 1GiB, 1024MiB). - - Default value is set by engine. - memory_guaranteed: - description: - - Amount of minimal guaranteed memory of the Virtual Machine. - Prefix uses IEC 60027-2 standard (for example 1GiB, 1024MiB). - - C(memory_guaranteed) parameter can't be lower than C(memory) parameter. - - Default value is set by engine. - memory_max: - description: - - Upper bound of virtual machine memory up to which memory hot-plug can be performed. - Prefix uses IEC 60027-2 standard (for example 1GiB, 1024MiB). - - Default value is set by engine. - cloud_init: - description: - - Dictionary with values for Unix-like Virtual Machine initialization using cloud init. - - C(host_name) - Hostname to be set to Virtual Machine when deployed. - - C(timezone) - Timezone to be set to Virtual Machine when deployed. - - C(user_name) - Username to be used to set password to Virtual Machine when deployed. - - C(root_password) - Password to be set for user specified by C(user_name) parameter. - - C(authorized_ssh_keys) - Use this SSH keys to login to Virtual Machine. - - C(regenerate_ssh_keys) - If I(True) SSH keys will be regenerated on Virtual Machine. - - C(custom_script) - Cloud-init script which will be executed on Virtual Machine when deployed. This is appended to the end of the - cloud-init script generated by any other options. - - C(dns_servers) - DNS servers to be configured on Virtual Machine. - - C(dns_search) - DNS search domains to be configured on Virtual Machine. - - C(nic_boot_protocol) - Set boot protocol of the network interface of Virtual Machine. Can be one of C(none), C(dhcp) or C(static). - - C(nic_ip_address) - If boot protocol is static, set this IP address to network interface of Virtual Machine. - - C(nic_netmask) - If boot protocol is static, set this netmask to network interface of Virtual Machine. - - C(nic_gateway) - If boot protocol is static, set this gateway to network interface of Virtual Machine. - - C(nic_name) - Set name to network interface of Virtual Machine. - - C(nic_on_boot) - If I(True) network interface will be set to start on boot. - sso: - description: - - "I(True) enable Single Sign On by Guest Agent, I(False) to disable it. By default is chosen by oVirt/RHV engine." - type: bool - smartcard_enabled: - description: - - "If I(true), use smart card authentication." - type: bool - nics: - description: - - List of NICs, which should be attached to Virtual Machine. NIC is described by following dictionary. - - C(name) - Name of the NIC. - - C(profile_name) - Profile name where NIC should be attached. - - C(interface) - Type of the network interface. One of following I(virtio), I(e1000), I(rtl8139), default is I(virtio). - - C(mac_address) - Custom MAC address of the network interface, by default it's obtained from MAC pool. - - NOTE - This parameter is used only when C(state) is I(running) or I(present) and is able to only create NICs. - - To manage NICs of the VM in more depth please use M(ovirt_nics) module instead. - version_added: "2.9" -extends_documentation_fragment: ovirt -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -- name: Create VM pool from template - ovirt_vmpool: - cluster: mycluster - name: myvmpool - template: rhel7 - vm_count: 2 - prestarted: 2 - vm_per_user: 1 - -- name: Remove vmpool, note that all VMs in pool will be stopped and removed - ovirt_vmpool: - state: absent - name: myvmpool - -- name: Change Pool Name - ovirt_vmpool: - id: 00000000-0000-0000-0000-000000000000 - name: "new_pool_name" - -- name: Create vm pool and override the pool values - ovirt_vmpool: - cluster: mycluster - name: vmpool - template: blank - vm_count: 2 - prestarted: 1 - vm_per_user: 1 - vm: - memory: 4GiB - memory_guaranteed: 4GiB - memory_max: 10GiB - comment: vncomment - cloud_init: - nic_boot_protocol: static - nic_ip_address: 10.34.60.86 - nic_netmask: 255.255.252.0 - nic_gateway: 10.34.63.254 - nic_name: eth1 - nic_on_boot: true - host_name: example.com - custom_script: | - write_files: - - content: | - Hello, world! - path: /tmp/greeting.txt - permissions: '0644' - user_name: root - root_password: super_password - nics: - - name: nicname - interface: virtio - profile_name: network - -''' - -RETURN = ''' -id: - description: ID of the VM pool which is managed - returned: On success if VM pool is found. - type: str - sample: 7de90f31-222c-436c-a1ca-7e655bd5b60c -vm_pool: - description: "Dictionary of all the VM pool attributes. VM pool attributes can be found on your oVirt/RHV instance - at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/vm_pool." - returned: On success if VM pool is found. - type: dict -''' - -try: - import ovirtsdk4.types as otypes -except ImportError: - pass - -import traceback - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - BaseModule, - check_params, - check_sdk, - create_connection, - equal, - get_link_name, - ovirt_full_argument_spec, - wait, - convert_to_bytes, - search_by_name, -) - - -class VmPoolsModule(BaseModule): - def __init__(self, *args, **kwargs): - super(VmPoolsModule, self).__init__(*args, **kwargs) - self._initialization = None - - def build_entity(self): - vm = self.param('vm') - return otypes.VmPool( - id=self._module.params['id'], - name=self._module.params['name'], - description=self._module.params['description'], - comment=self._module.params['comment'], - cluster=otypes.Cluster( - name=self._module.params['cluster'] - ) if self._module.params['cluster'] else None, - template=otypes.Template( - name=self._module.params['template'] - ) if self._module.params['template'] else None, - max_user_vms=self._module.params['vm_per_user'], - prestarted_vms=self._module.params['prestarted'], - size=self._module.params['vm_count'], - type=otypes.VmPoolType( - self._module.params['type'] - ) if self._module.params['type'] else None, - vm=self.build_vm(vm) if self._module.params['vm'] else None, - ) - - def build_vm(self, vm): - return otypes.Vm( - comment=vm.get('comment'), - memory=convert_to_bytes( - vm.get('memory') - ) if vm.get('memory') else None, - memory_policy=otypes.MemoryPolicy( - guaranteed=convert_to_bytes(vm.get('memory_guaranteed')), - max=convert_to_bytes(vm.get('memory_max')), - ) if any(( - vm.get('memory_guaranteed'), - vm.get('memory_max') - )) else None, - initialization=self.get_initialization(vm), - display=otypes.Display( - smartcard_enabled=vm.get('smartcard_enabled') - ) if vm.get('smartcard_enabled') is not None else None, - sso=( - otypes.Sso( - methods=[otypes.Method(id=otypes.SsoMethod.GUEST_AGENT)] if vm.get('sso') else [] - ) - ) if vm.get('sso') is not None else None, - time_zone=otypes.TimeZone( - name=vm.get('timezone'), - ) if vm.get('timezone') else None, - ) - - def get_initialization(self, vm): - if self._initialization is not None: - return self._initialization - - sysprep = vm.get('sysprep') - cloud_init = vm.get('cloud_init') - cloud_init_nics = vm.get('cloud_init_nics') or [] - if cloud_init is not None: - cloud_init_nics.append(cloud_init) - - if cloud_init or cloud_init_nics: - self._initialization = otypes.Initialization( - nic_configurations=[ - otypes.NicConfiguration( - boot_protocol=otypes.BootProtocol( - nic.pop('nic_boot_protocol').lower() - ) if nic.get('nic_boot_protocol') else None, - name=nic.pop('nic_name', None), - on_boot=nic.pop('nic_on_boot', None), - ip=otypes.Ip( - address=nic.pop('nic_ip_address', None), - netmask=nic.pop('nic_netmask', None), - gateway=nic.pop('nic_gateway', None), - ) if ( - nic.get('nic_gateway') is not None or - nic.get('nic_netmask') is not None or - nic.get('nic_ip_address') is not None - ) else None, - ) - for nic in cloud_init_nics - if ( - nic.get('nic_gateway') is not None or - nic.get('nic_netmask') is not None or - nic.get('nic_ip_address') is not None or - nic.get('nic_boot_protocol') is not None or - nic.get('nic_on_boot') is not None - ) - ] if cloud_init_nics else None, - **cloud_init - ) - elif sysprep: - self._initialization = otypes.Initialization( - **sysprep - ) - return self._initialization - - def get_vms(self, entity): - vms = self._connection.system_service().vms_service().list() - resp = [] - for vm in vms: - if vm.vm_pool is not None and vm.vm_pool.id == entity.id: - resp.append(vm) - return resp - - def post_create(self, entity): - vm_param = self.param('vm') - if vm_param is not None and vm_param.get('nics') is not None: - vms = self.get_vms(entity) - for vm in vms: - self.__attach_nics(vm, vm_param) - - def __attach_nics(self, entity, vm_param): - # Attach NICs to VM, if specified: - vms_service = self._connection.system_service().vms_service() - nics_service = vms_service.service(entity.id).nics_service() - for nic in vm_param.get('nics'): - if search_by_name(nics_service, nic.get('name')) is None: - if not self._module.check_mode: - nics_service.add( - otypes.Nic( - name=nic.get('name'), - interface=otypes.NicInterface( - nic.get('interface', 'virtio') - ), - vnic_profile=otypes.VnicProfile( - id=self.__get_vnic_profile_id(nic), - ) if nic.get('profile_name') else None, - mac=otypes.Mac( - address=nic.get('mac_address') - ) if nic.get('mac_address') else None, - ) - ) - self.changed = True - - def __get_vnic_profile_id(self, nic): - """ - Return VNIC profile ID looked up by it's name, because there can be - more VNIC profiles with same name, other criteria of filter is cluster. - """ - vnics_service = self._connection.system_service().vnic_profiles_service() - clusters_service = self._connection.system_service().clusters_service() - cluster = search_by_name(clusters_service, self.param('cluster')) - profiles = [ - profile for profile in vnics_service.list() - if profile.name == nic.get('profile_name') - ] - cluster_networks = [ - net.id for net in self._connection.follow_link(cluster.networks) - ] - try: - return next( - profile.id for profile in profiles - if profile.network.id in cluster_networks - ) - except StopIteration: - raise Exception( - "Profile '%s' was not found in cluster '%s'" % ( - nic.get('profile_name'), - self.param('cluster') - ) - ) - - def update_check(self, entity): - return ( - equal(self._module.params.get('name'), entity.name) and - equal(self._module.params.get('cluster'), get_link_name(self._connection, entity.cluster)) and - equal(self._module.params.get('description'), entity.description) and - equal(self._module.params.get('comment'), entity.comment) and - equal(self._module.params.get('vm_per_user'), entity.max_user_vms) and - equal(self._module.params.get('prestarted'), entity.prestarted_vms) and - equal(self._module.params.get('vm_count'), entity.size) - ) - - -def main(): - argument_spec = ovirt_full_argument_spec( - id=dict(default=None), - state=dict( - choices=['present', 'absent'], - default='present', - ), - name=dict(required=True), - template=dict(default=None), - cluster=dict(default=None), - description=dict(default=None), - vm=dict(default=None, type='dict'), - comment=dict(default=None), - vm_per_user=dict(default=None, type='int'), - prestarted=dict(default=None, type='int'), - vm_count=dict(default=None, type='int'), - type=dict(default=None, choices=['automatic', 'manual']), - ) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - ) - - check_sdk(module) - check_params(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - vm_pools_service = connection.system_service().vm_pools_service() - vm_pools_module = VmPoolsModule( - connection=connection, - module=module, - service=vm_pools_service, - ) - - state = module.params['state'] - if state == 'present': - ret = vm_pools_module.create() - - # Wait for all VM pool VMs to be created: - if module.params['wait']: - vms_service = connection.system_service().vms_service() - for vm in vms_service.list(search='pool=%s' % module.params['name']): - wait( - service=vms_service.service(vm.id), - condition=lambda vm: vm.status in [otypes.VmStatus.DOWN, otypes.VmStatus.UP], - timeout=module.params['timeout'], - ) - - elif state == 'absent': - ret = vm_pools_module.remove() - - module.exit_json(**ret) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_vmpool_info.py b/lib/ansible/modules/cloud/ovirt/ovirt_vmpool_info.py deleted file mode 100644 index 52f2a5e494..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_vmpool_info.py +++ /dev/null @@ -1,118 +0,0 @@ -#!/usr/bin/python -# -*- 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 . -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_vmpool_info -short_description: Retrieve information about one or more oVirt/RHV vmpools -author: "Ondra Machacek (@machacekondra)" -version_added: "2.3" -description: - - "Retrieve information about one or more oVirt/RHV vmpools." - - This module was called C(ovirt_vmpool_facts) before Ansible 2.9, returning C(ansible_facts). - Note that the M(ovirt_vmpool_info) module no longer returns C(ansible_facts)! -notes: - - "This module returns a variable C(ovirt_vmpools), which - contains a list of vmpools. You need to register the result with - the I(register) keyword to use it." -options: - pattern: - description: - - "Search term which is accepted by oVirt/RHV search backend." - - "For example to search vmpool X: name=X" -extends_documentation_fragment: ovirt_info -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Gather information about all vm pools which names start with C(centos): -- ovirt_vmpool_info: - pattern: name=centos* - register: result -- debug: - msg: "{{ result.ovirt_vm_pools }}" -''' - -RETURN = ''' -ovirt_vm_pools: - description: "List of dictionaries describing the vmpools. Vm pool attributes are mapped to dictionary keys, - all vmpools attributes can be found at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/vm_pool." - returned: On success. - type: list -''' - -import traceback - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - check_sdk, - create_connection, - get_dict_of_struct, - ovirt_info_full_argument_spec, -) - - -def main(): - argument_spec = ovirt_info_full_argument_spec( - pattern=dict(default='', required=False), - ) - module = AnsibleModule(argument_spec) - is_old_facts = module._name == 'ovirt_vmpool_facts' - if is_old_facts: - module.deprecate("The 'ovirt_vmpool_facts' module has been renamed to 'ovirt_vmpool_info', " - "and the renamed one no longer returns ansible_facts", version='2.13') - - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - vmpools_service = connection.system_service().vm_pools_service() - vmpools = vmpools_service.list(search=module.params['pattern']) - result = dict( - ovirt_vm_pools=[ - get_dict_of_struct( - struct=c, - connection=connection, - fetch_nested=module.params.get('fetch_nested'), - attributes=module.params.get('nested_attributes'), - ) for c in vmpools - ], - ) - if is_old_facts: - module.exit_json(changed=False, ansible_facts=result) - else: - module.exit_json(changed=False, **result) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_vnic_profile.py b/lib/ansible/modules/cloud/ovirt/ovirt_vnic_profile.py deleted file mode 100644 index 6013e3de46..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_vnic_profile.py +++ /dev/null @@ -1,321 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2017, Ansible Project -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - -DOCUMENTATION = ''' ---- -module: ovirt_vnic_profile -short_description: Module to manage vNIC profile of network in oVirt/RHV -version_added: "2.8" -author: -- "Ondra Machacek (@machacekondra)" -- "Martin Necas (@mnecas)" -description: - - "Module to manage vNIC profile of network in oVirt/RHV" -options: - name: - description: - - "A human-readable name in plain text." - required: true - state: - description: - - "Should the vNIC be absent/present." - choices: ['absent', 'present'] - default: present - description: - description: - - "A human-readable description in plain text." - data_center: - description: - - "Datacenter name where network reside." - required: true - network: - description: - - "Name of network to which is vNIC attached." - required: true - network_filter: - description: - - "The network filter enables to filter packets send to/from the VM's nic according to defined rules." - custom_properties: - description: - - "Custom properties applied to the vNIC profile." - - "Custom properties is a list of dictionary which can have following values:" - suboptions: - name: - description: - - "Name of the custom property. For example: I(hugepages), I(vhost), I(sap_agent), etc." - regexp: - description: - - Regular expression to set for custom property. - value: - description: - - Value to set for custom property. - qos: - description: - - "Quality of Service attributes regulate inbound and outbound network traffic of the NIC." - port_mirroring: - description: - - "Enables port mirroring." - type: bool - pass_through: - description: - - "Enables passthrough to an SR-IOV-enabled host NIC." - - "When enabled C(qos) and C(network_filter) are automatically set to None and C(port_mirroring) to False." - - "When enabled and C(migratable) not specified then C(migratable) is enabled." - - "Port mirroring, QoS and network filters are not supported on passthrough profiles." - choices: ['disabled', 'enabled'] - migratable: - description: - - "Marks whether pass_through NIC is migratable or not." - type: bool -extends_documentation_fragment: ovirt -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: -- name: Add vNIC - ovirt_vnic_profile: - name: myvnic - network: mynetwork - state: present - data_center: datacenter - -- name: Editing vNICs network_filter, custom_properties, qos - ovirt_vnic_profile: - name: myvnic - network: mynetwork - data_center: datacenter - qos: myqos - custom_properties: - - name: SecurityGroups - value: 9bd9bde9-39da-44a8-9541-aa39e1a81c9d - network_filter: allow-dhcp - -- name: Remove vNICs network_filter, custom_properties, qos - ovirt_vnic_profile: - name: myvnic - network: mynetwork - data_center: datacenter - qos: "" - custom_properties: "" - network_filter: "" - -- name: Dont use migratable - ovirt_vnic_profile: - name: myvnic - network: mynetwork - data_center: datacenter - migratable: False - pass_through: enabled - -- name: Remove vNIC - ovirt_vnic_profile: - name: myvnic - network: mynetwork - state: absent - data_center: datacenter -''' - -RETURN = ''' -id: - description: ID of the vNIC profile which is managed - returned: On success if vNIC profile is found. - type: str - sample: 7de90f31-222c-436c-a1ca-7e655bd5b60c -vnic: - description: "Dictionary of all the vNIC profile attributes. Network interface attributes can be found on your oVirt/RHV instance - at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/nic." - returned: On success if vNIC profile is found. - type: dict -''' - -try: - import ovirtsdk4.types as otypes -except ImportError: - pass - -import traceback - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - BaseModule, - check_sdk, - create_connection, - equal, - get_link_name, - ovirt_full_argument_spec, - search_by_name, - get_id_by_name -) - - -class EntityVnicPorfileModule(BaseModule): - - def __init__(self, *args, **kwargs): - super(EntityVnicPorfileModule, self).__init__(*args, **kwargs) - - def _get_dcs_service(self): - return self._connection.system_service().data_centers_service() - - def _get_dcs_id(self): - return get_id_by_name(self._get_dcs_service(), self.param('data_center')) - - def _get_network_id(self): - networks_service = self._get_dcs_service().service(self._get_dcs_id()).networks_service() - return get_id_by_name(networks_service, self.param('network')) - - def _get_qos_id(self): - if self.param('qos'): - qoss_service = self._get_dcs_service().service(self._get_dcs_id()).qoss_service() - return get_id_by_name(qoss_service, self.param('qos')) if self.param('qos') else None - return None - - def _get_network_filter_id(self): - nf_service = self._connection.system_service().network_filters_service() - return get_id_by_name(nf_service, self.param('network_filter')) if self.param('network_filter') else None - - def _get_network_filter(self): - network_filter = None - # The order of these condition is necessary. - # When would network_filter and pass_through specified it would try to create and network_filter and fail on engine. - if self.param('network_filter') == '' or self.param('pass_through') == 'enabled': - network_filter = otypes.NetworkFilter() - elif self.param('network_filter'): - network_filter = otypes.NetworkFilter(id=self._get_network_filter_id()) - return network_filter - - def _get_qos(self): - qos = None - # The order of these condition is necessary. When would qos and pass_through specified it would try to create and qos and fail on engine. - if self.param('qos') == '' or self.param('pass_through') == 'enabled': - qos = otypes.Qos() - elif self.param('qos'): - qos = otypes.Qos(id=self._get_qos_id()) - return qos - - def _get_port_mirroring(self): - if self.param('pass_through') == 'enabled': - return False - return self.param('port_mirroring') - - def _get_migratable(self): - if self.param('migratable') is not None: - return self.param('migratable') - if self.param('pass_through') == 'enabled': - return True - - def build_entity(self): - return otypes.VnicProfile( - name=self.param('name'), - network=otypes.Network(id=self._get_network_id()), - description=self.param('description') if self.param('description') is not None else None, - pass_through=otypes.VnicPassThrough(mode=otypes.VnicPassThroughMode(self.param('pass_through'))) if self.param('pass_through') else None, - custom_properties=[ - otypes.CustomProperty( - name=cp.get('name'), - regexp=cp.get('regexp'), - value=str(cp.get('value')), - ) for cp in self.param('custom_properties') if cp - ] if self.param('custom_properties') else None, - migratable=self._get_migratable(), - qos=self._get_qos(), - port_mirroring=self._get_port_mirroring(), - network_filter=self._get_network_filter() - ) - - def update_check(self, entity): - def check_custom_properties(): - if self.param('custom_properties'): - current = [] - if entity.custom_properties: - current = [(cp.name, cp.regexp, str(cp.value)) for cp in entity.custom_properties] - passed = [(cp.get('name'), cp.get('regexp'), str(cp.get('value'))) for cp in self.param('custom_properties') if cp] - return sorted(current) == sorted(passed) - return True - - pass_through = getattr(entity.pass_through.mode, 'name', None) - return ( - check_custom_properties() and - # The reason why we can't use equal method, is we get None from _get_network_filter_id or _get_qos_id method, when passing empty string. - # And when first param of equal method is None it returns true. - self._get_network_filter_id() == getattr(entity.network_filter, 'id', None) and - self._get_qos_id() == getattr(entity.qos, 'id', None) and - equal(self.param('migratable'), getattr(entity, 'migratable', None)) and - equal(self.param('pass_through'), pass_through.lower() if pass_through else None) and - equal(self.param('description'), entity.description) and - equal(self.param('port_mirroring'), getattr(entity, 'port_mirroring', None)) - ) - - -def get_entity(vnic_services, entitynics_module): - vnic_profiles = vnic_services.list() - network_id = entitynics_module._get_network_id() - for vnic in vnic_profiles: - # When vNIC already exist update it, when not create it - if vnic.name == entitynics_module.param('name') and network_id == vnic.network.id: - return vnic - - -def check_params(module): - if (module.params.get('port_mirroring') or module.params.get('network_filter') or module.params.get('qos'))\ - and module.params.get('pass_through') == 'enabled': - module.fail_json(msg="Cannot edit VM network interface profile. 'Port Mirroring,'Qos' and 'Network Filter' are not supported on passthrough profiles.") - - -def main(): - argument_spec = ovirt_full_argument_spec( - state=dict(type='str', default='present', choices=['absent', 'present']), - network=dict(type='str', required=True), - data_center=dict(type='str', required=True), - description=dict(type='str'), - name=dict(type='str', required=True), - network_filter=dict(type='str'), - custom_properties=dict(type='list'), - qos=dict(type='str'), - pass_through=dict(type='str', choices=['disabled', 'enabled']), - port_mirroring=dict(type='bool'), - migratable=dict(type='bool'), - ) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - - ) - check_sdk(module) - check_params(module) - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - - vnic_services = connection.system_service().vnic_profiles_service() - - entitynics_module = EntityVnicPorfileModule( - connection=connection, - module=module, - service=vnic_services, - ) - state = module.params['state'] - entity = get_entity(vnic_services, entitynics_module) - if state == 'present': - ret = entitynics_module.create(entity=entity, force_create=entity is None) - elif state == 'absent': - if entity is not None: - ret = entitynics_module.remove(entity=entity) - else: - raise Exception("Vnic profile '%s' in network '%s' was not found." % (module.params['name'], module.params['network'])) - module.exit_json(**ret) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_vnic_profile_info.py b/lib/ansible/modules/cloud/ovirt/ovirt_vnic_profile_info.py deleted file mode 100644 index 8fda8b5b10..0000000000 --- a/lib/ansible/modules/cloud/ovirt/ovirt_vnic_profile_info.py +++ /dev/null @@ -1,119 +0,0 @@ -#!/usr/bin/python -# -*- 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 . -# - -from __future__ import absolute_import, division, print_function -__metaclass__ = type - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: ovirt_vnic_profile_info -short_description: Retrieve information about one or more oVirt/RHV vnic profiles -author: "Martin Necas (@mnecas)" -version_added: "2.10" -description: - - "Retrieve information about one or more oVirt/RHV vnic profiles." -notes: - - "This module returns a variable C(ovirt_vnic_profiles), which - contains a list of vnic profiles. You need to register the result with - the I(register) keyword to use it." -options: - max: - description: - - "The maximum number of results to return." - type: int - name: - description: - - "Name of vnic profile." - type: str -extends_documentation_fragment: ovirt_info -''' - -EXAMPLES = ''' -# Examples don't contain auth parameter for simplicity, -# look at ovirt_auth module to see how to reuse authentication: - -# Gather information 10 vnic profiles -- ovirt_vnic_profile_info: - max: 10 - register: result -- debug: - msg: "{{ result.ovirt_vnic_profiles }}" -''' - -RETURN = ''' -ovirt_vnic_profiles: - description: "List of dictionaries describing the vnic profiles. Vnic_profile attributes are mapped to dictionary keys, - all vnic profiles attributes can be found at following url: http://ovirt.github.io/ovirt-engine-api-model/master/#types/vnic_profile." - returned: On success. - type: list -''' - -import traceback - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ovirt import ( - check_sdk, - create_connection, - get_dict_of_struct, - ovirt_info_full_argument_spec, -) - - -def main(): - argument_spec = ovirt_info_full_argument_spec( - max=dict(default=None, type='int'), - name=dict(default=None), - ) - module = AnsibleModule(argument_spec) - check_sdk(module) - - try: - auth = module.params.pop('auth') - connection = create_connection(auth) - vnic_profiles_service = connection.system_service().vnic_profiles_service() - vnic_profiles = vnic_profiles_service.list(max=module.params.get('max')) - if module.params.get('name') and vnic_profiles: - vnic_profiles = [vnic_profile for vnic_profile in vnic_profiles if vnic_profile.name == module.params.get("name")] - - result = dict( - ovirt_vnic_profiles=[ - get_dict_of_struct( - struct=c, - connection=connection, - fetch_nested=module.params.get('fetch_nested'), - attributes=module.params.get('nested_attributes'), - ) for c in vnic_profiles - ], - ) - module.exit_json(changed=False, **result) - except Exception as e: - module.fail_json(msg=str(e), exception=traceback.format_exc()) - finally: - connection.close(logout=auth.get('token') is None) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/plugins/doc_fragments/ovirt.py b/lib/ansible/plugins/doc_fragments/ovirt.py deleted file mode 100644 index 3667b7d886..0000000000 --- a/lib/ansible/plugins/doc_fragments/ovirt.py +++ /dev/null @@ -1,102 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright: (c) 2016, Red Hat, Inc. -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - - -class ModuleDocFragment(object): - - # Standard oVirt documentation fragment - DOCUMENTATION = r''' -options: - wait: - description: - - "C(yes) if the module should wait for the entity to get into desired state." - type: bool - default: yes - 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 specifying C(nested_attributes)." - type: bool - 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)." - type: list - version_added: "2.3" - auth: - description: - - "Dictionary with values needed to create HTTP/HTTPS connection to oVirt:" - suboptions: - username: - description: - - The name of the user, something like I(admin@internal). - - Default value is set by C(OVIRT_USERNAME) environment variable. - type: str - required: true - password: - description: - - The password of the user. - - Default value is set by C(OVIRT_PASSWORD) environment variable. - type: str - required: true - url: - description: - - A string containing the API URL of the server, usually something like `I(https://server.example.com/ovirt-engine/api)`. - - Default value is set by C(OVIRT_URL) environment variable. - - Either C(url) or C(hostname) is required. - type: str - hostname: - description: - - A string containing the hostname of the server, usually something like `I(server.example.com)`. - - Default value is set by C(OVIRT_HOSTNAME) environment variable. - - Either C(url) or C(hostname) is required. - type: str - token: - description: - - Token to be used instead of login with username/password. - - Default value is set by C(OVIRT_TOKEN) environment variable. - type: str - insecure: - description: - - A boolean flag that indicates if the server TLS certificate and host name should be checked. - type: bool - ca_file: - description: - - 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. - - Default value is set by C(OVIRT_CAFILE) environment variable. - type: str - kerberos: - description: - - A boolean flag indicating if Kerberos authentication should be used instead of the default basic authentication. - type: bool - headers: - description: - - Dictionary of HTTP headers to be added to each API call. - type: dict - type: dict - required: true - timeout: - description: - - "The amount of time in seconds the module should wait for the instance to - get into desired state." - type: int - default: 180 - poll_interval: - description: - - "Number of the seconds the module waits until another poll request on entity status is sent." - type: int - default: 3 -requirements: - - python >= 2.7 - - ovirt-engine-sdk-python >= 4.3.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: - I(pip: name=ovirt-engine-sdk-python version=4.3.0)" -''' diff --git a/lib/ansible/plugins/doc_fragments/ovirt_info.py b/lib/ansible/plugins/doc_fragments/ovirt_info.py deleted file mode 100644 index b16356a230..0000000000 --- a/lib/ansible/plugins/doc_fragments/ovirt_info.py +++ /dev/null @@ -1,57 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright: (c) 2016, Red Hat, Inc. -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - - -class ModuleDocFragment(object): - - # info standard oVirt documentation fragment - DOCUMENTATION = r''' -options: - fetch_nested: - description: - - If I(yes) the module will fetch additional data from the API. - - It will fetch only IDs of nested entity. It doesn't fetch multiple levels of nested attributes. - Only the attributes of the current entity. User can configure to fetch other - attributes of the nested entities by specifying C(nested_attributes). - type: bool - 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). - type: list - version_added: "2.3" - auth: - 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). - Default value is set by I(OVIRT_USERNAME) environment variable. - - "C(password)[I(required)] - The password of the user. Default value is set by I(OVIRT_PASSWORD) environment variable." - - "C(url)- A string containing the API URL of the server, usually - something like `I(https://server.example.com/ovirt-engine/api)`. Default value is set by I(OVIRT_URL) environment variable. - Either C(url) or C(hostname) is required." - - "C(hostname) - A string containing the hostname of the server, usually - something like `I(server.example.com)`. Default value is set by I(OVIRT_HOSTNAME) environment variable. - Either C(url) or C(hostname) is required." - - "C(token) - Token to be used instead of login with username/password. Default value is set by I(OVIRT_TOKEN) environment variable." - - "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. Default value is set by I(OVIRT_CAFILE) environment variable." - - "C(kerberos) - A boolean flag indicating if Kerberos authentication - should be used instead of the default basic authentication." - - "C(headers) - Dictionary of HTTP headers to be added to each API call." - type: dict - required: true -requirements: - - python >= 2.7 - - ovirt-engine-sdk-python >= 4.3.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.3.0" -''' diff --git a/test/sanity/ignore.txt b/test/sanity/ignore.txt index 596b11fd39..700646dc5c 100644 --- a/test/sanity/ignore.txt +++ b/test/sanity/ignore.txt @@ -94,8 +94,6 @@ lib/ansible/module_utils/network/skydive/api.py future-import-boilerplate lib/ansible/module_utils/network/skydive/api.py metaclass-boilerplate lib/ansible/module_utils/network/vyos/vyos.py future-import-boilerplate lib/ansible/module_utils/network/vyos/vyos.py metaclass-boilerplate -lib/ansible/module_utils/ovirt.py future-import-boilerplate -lib/ansible/module_utils/ovirt.py metaclass-boilerplate lib/ansible/module_utils/parsing/convert_bool.py future-import-boilerplate lib/ansible/module_utils/parsing/convert_bool.py metaclass-boilerplate lib/ansible/module_utils/powershell/Ansible.ModuleUtils.ArgvParser.psm1 pslint:PSUseApprovedVerbs @@ -1016,256 +1014,6 @@ lib/ansible/modules/cloud/google/gcp_tpu_node_info.py validate-modules:parameter lib/ansible/modules/cloud/hcloud/hcloud_network_info.py validate-modules:return-syntax-error lib/ansible/modules/cloud/hcloud/hcloud_server.py validate-modules:parameter-list-no-elements lib/ansible/modules/cloud/hcloud/hcloud_server_network.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_affinity_group.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_affinity_group.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_affinity_group.py validate-modules:doc-required-mismatch -lib/ansible/modules/cloud/ovirt/ovirt_affinity_group.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_affinity_group.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/ovirt/ovirt_affinity_label.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_affinity_label.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_affinity_label.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_affinity_label.py validate-modules:no-default-for-required-parameter -lib/ansible/modules/cloud/ovirt/ovirt_affinity_label.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_affinity_label.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/ovirt/ovirt_affinity_label_info.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_affinity_label_info.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_affinity_label_info.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_affinity_label_info.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_api_info.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_auth.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_auth.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_auth.py validate-modules:doc-default-does-not-match-spec -lib/ansible/modules/cloud/ovirt/ovirt_auth.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_auth.py validate-modules:invalid-ansiblemodule-schema -lib/ansible/modules/cloud/ovirt/ovirt_auth.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/ovirt/ovirt_auth.py validate-modules:undocumented-parameter -lib/ansible/modules/cloud/ovirt/ovirt_cluster.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_cluster.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_cluster.py validate-modules:doc-choices-do-not-match-spec -lib/ansible/modules/cloud/ovirt/ovirt_cluster.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_cluster.py validate-modules:no-default-for-required-parameter -lib/ansible/modules/cloud/ovirt/ovirt_cluster.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_cluster.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/ovirt/ovirt_cluster.py validate-modules:undocumented-parameter -lib/ansible/modules/cloud/ovirt/ovirt_cluster_info.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_cluster_info.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_cluster_info.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_cluster_info.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_datacenter.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_datacenter.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_datacenter.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_datacenter.py validate-modules:no-default-for-required-parameter -lib/ansible/modules/cloud/ovirt/ovirt_datacenter.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_datacenter_info.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_datacenter_info.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_datacenter_info.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_datacenter_info.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_disk.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_disk.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_disk.py validate-modules:doc-choices-do-not-match-spec -lib/ansible/modules/cloud/ovirt/ovirt_disk.py validate-modules:doc-default-does-not-match-spec -lib/ansible/modules/cloud/ovirt/ovirt_disk.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_disk.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_disk.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/ovirt/ovirt_disk.py validate-modules:undocumented-parameter -lib/ansible/modules/cloud/ovirt/ovirt_disk_info.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_disk_info.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_disk_info.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_disk_info.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_event.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_event_info.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_external_provider.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_external_provider.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_external_provider.py validate-modules:doc-default-does-not-match-spec -lib/ansible/modules/cloud/ovirt/ovirt_external_provider.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_external_provider.py validate-modules:doc-required-mismatch -lib/ansible/modules/cloud/ovirt/ovirt_external_provider.py validate-modules:no-default-for-required-parameter -lib/ansible/modules/cloud/ovirt/ovirt_external_provider.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_external_provider.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/ovirt/ovirt_external_provider.py validate-modules:undocumented-parameter -lib/ansible/modules/cloud/ovirt/ovirt_external_provider_info.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_external_provider_info.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_external_provider_info.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_external_provider_info.py validate-modules:no-default-for-required-parameter -lib/ansible/modules/cloud/ovirt/ovirt_external_provider_info.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_external_provider_info.py validate-modules:undocumented-parameter -lib/ansible/modules/cloud/ovirt/ovirt_group.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_group.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_group.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_group.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_group_info.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_group_info.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_group_info.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_group_info.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_host.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_host.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_host.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_host.py validate-modules:implied-parameter-type-mismatch -lib/ansible/modules/cloud/ovirt/ovirt_host.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_host.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/ovirt/ovirt_host_info.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_host_info.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_host_info.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_host_info.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_host_network.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_host_network.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_host_network.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_host_network.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_host_network.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/ovirt/ovirt_host_pm.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_host_pm.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_host_pm.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_host_pm.py validate-modules:no-default-for-required-parameter -lib/ansible/modules/cloud/ovirt/ovirt_host_pm.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_host_pm.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/ovirt/ovirt_host_storage_info.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_host_storage_info.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_host_storage_info.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_host_storage_info.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_host_storage_info.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/ovirt/ovirt_instance_type.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_instance_type.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_instance_type.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_instance_type.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/ovirt/ovirt_job.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_job.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_job.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_job.py validate-modules:doc-required-mismatch -lib/ansible/modules/cloud/ovirt/ovirt_job.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_mac_pool.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_mac_pool.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_mac_pool.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_mac_pool.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_mac_pool.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/ovirt/ovirt_network.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_network.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_network.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_network.py validate-modules:doc-required-mismatch -lib/ansible/modules/cloud/ovirt/ovirt_network.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_network.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/ovirt/ovirt_network_info.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_network_info.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_network_info.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_network_info.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_nic.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_nic.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_nic.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_nic.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_nic.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/ovirt/ovirt_nic_info.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_nic_info.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_nic_info.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_nic_info.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_permission.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_permission.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_permission.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_permission.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/ovirt/ovirt_permission_info.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_permission_info.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_permission_info.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_permission_info.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_quota.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_quota.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_quota.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_quota.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_quota.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/ovirt/ovirt_quota_info.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_quota_info.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_quota_info.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_quota_info.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_role.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_role.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_role.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_role.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_role.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/ovirt/ovirt_scheduling_policy_info.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_scheduling_policy_info.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_scheduling_policy_info.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_scheduling_policy_info.py validate-modules:doc-required-mismatch -lib/ansible/modules/cloud/ovirt/ovirt_scheduling_policy_info.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_snapshot.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_snapshot.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_snapshot.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_snapshot.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_snapshot.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/ovirt/ovirt_snapshot_info.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_snapshot_info.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_snapshot_info.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_snapshot_info.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_storage_connection.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_storage_connection.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_storage_connection.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_storage_connection.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_storage_connection.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/ovirt/ovirt_storage_domain.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_storage_domain.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_storage_domain.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_storage_domain.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_storage_domain.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/ovirt/ovirt_storage_domain_info.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_storage_domain_info.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_storage_domain_info.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_storage_domain_info.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_storage_template_info.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_storage_template_info.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_storage_template_info.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_storage_template_info.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_storage_template_info.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/ovirt/ovirt_storage_vm_info.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_storage_vm_info.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_storage_vm_info.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_storage_vm_info.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_storage_vm_info.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/ovirt/ovirt_tag.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_tag.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_tag.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_tag.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_tag.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/ovirt/ovirt_tag_info.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_tag_info.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_tag_info.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_tag_info.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_template.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_template.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_template.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_template.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_template.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/ovirt/ovirt_template_info.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_template_info.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_template_info.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_template_info.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_user.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_user.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_user.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_user.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_user_info.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_user_info.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_user_info.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_user_info.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_vm.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_vm.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_vm.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_vm.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_vm.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/ovirt/ovirt_vm_info.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_vm_info.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_vm_info.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_vm_info.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_vm_info.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/ovirt/ovirt_vmpool.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_vmpool.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_vmpool.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_vmpool.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_vmpool.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/ovirt/ovirt_vmpool_info.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_vmpool_info.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_vmpool_info.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/ovirt/ovirt_vmpool_info.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_vnic_profile.py future-import-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_vnic_profile.py metaclass-boilerplate -lib/ansible/modules/cloud/ovirt/ovirt_vnic_profile.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/ovirt/ovirt_vnic_profile.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/ovirt/ovirt_vnic_profile_info.py validate-modules:parameter-list-no-elements lib/ansible/modules/commands/command.py validate-modules:doc-missing-type lib/ansible/modules/commands/command.py validate-modules:nonexistent-parameter-documented lib/ansible/modules/commands/command.py validate-modules:parameter-list-no-elements @@ -1667,10 +1415,6 @@ lib/ansible/plugins/doc_fragments/hcloud.py future-import-boilerplate lib/ansible/plugins/doc_fragments/hcloud.py metaclass-boilerplate lib/ansible/plugins/doc_fragments/inventory_cache.py future-import-boilerplate lib/ansible/plugins/doc_fragments/inventory_cache.py metaclass-boilerplate -lib/ansible/plugins/doc_fragments/ovirt.py future-import-boilerplate -lib/ansible/plugins/doc_fragments/ovirt.py metaclass-boilerplate -lib/ansible/plugins/doc_fragments/ovirt_info.py future-import-boilerplate -lib/ansible/plugins/doc_fragments/ovirt_info.py metaclass-boilerplate lib/ansible/plugins/doc_fragments/return_common.py future-import-boilerplate lib/ansible/plugins/doc_fragments/return_common.py metaclass-boilerplate lib/ansible/plugins/doc_fragments/shell_common.py future-import-boilerplate -- cgit v1.2.1