diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-05 16:18:34 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-05 16:18:34 +0000 |
commit | 3667197efb7b18ec842efd504785965911f8ac4b (patch) | |
tree | 0b986a4bc6879d080b100666a97cdabbc9ca1f28 /ansible_collections/netapp/azure/plugins | |
parent | Adding upstream version 9.5.1+dfsg. (diff) | |
download | ansible-3667197efb7b18ec842efd504785965911f8ac4b.tar.xz ansible-3667197efb7b18ec842efd504785965911f8ac4b.zip |
Adding upstream version 10.0.0+dfsg.upstream/10.0.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ansible_collections/netapp/azure/plugins')
9 files changed, 0 insertions, 1925 deletions
diff --git a/ansible_collections/netapp/azure/plugins/doc_fragments/azure.py b/ansible_collections/netapp/azure/plugins/doc_fragments/azure.py deleted file mode 100644 index 49467db70..000000000 --- a/ansible_collections/netapp/azure/plugins/doc_fragments/azure.py +++ /dev/null @@ -1,129 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright: (c) 2016 Matt Davis, <mdavis@ansible.com> -# Copyright: (c) 2016 Chris Houseknecht, <house@redhat.com> -# 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 - - -class ModuleDocFragment(object): - - # Azure doc fragment - DOCUMENTATION = r''' - -options: - ad_user: - description: - - Active Directory username. Use when authenticating with an Active Directory user rather than service - principal. - type: str - password: - description: - - Active Directory user password. Use when authenticating with an Active Directory user rather than service - principal. - type: str - profile: - description: - - Security profile found in ~/.azure/credentials file. - type: str - subscription_id: - description: - - Your Azure subscription Id. - type: str - client_id: - description: - - Azure client ID. Use when authenticating with a Service Principal. - type: str - secret: - description: - - Azure client secret. Use when authenticating with a Service Principal. - type: str - tenant: - description: - - Azure tenant ID. Use when authenticating with a Service Principal. - type: str - cloud_environment: - description: - - For cloud environments other than the US public cloud, the environment name (as defined by Azure Python SDK, eg, C(AzureChinaCloud), - C(AzureUSGovernment)), or a metadata discovery endpoint URL (required for Azure Stack). Can also be set via credential file profile or - the C(AZURE_CLOUD_ENVIRONMENT) environment variable. - type: str - default: AzureCloud - version_added: '0.0.1' - adfs_authority_url: - description: - - Azure AD authority url. Use when authenticating with Username/password, and has your own ADFS authority. - type: str - version_added: '0.0.1' - cert_validation_mode: - description: - - Controls the certificate validation behavior for Azure endpoints. By default, all modules will validate the server certificate, but - when an HTTPS proxy is in use, or against Azure Stack, it may be necessary to disable this behavior by passing C(ignore). Can also be - set via credential file profile or the C(AZURE_CERT_VALIDATION) environment variable. - type: str - choices: [ ignore, validate ] - version_added: '0.0.1' - auth_source: - description: - - Controls the source of the credentials to use for authentication. - - Can also be set via the C(ANSIBLE_AZURE_AUTH_SOURCE) environment variable. - - When set to C(auto) (the default) the precedence is module parameters -> C(env) -> C(credential_file) -> C(cli). - - When set to C(env), the credentials will be read from the environment variables - - When set to C(credential_file), it will read the profile from C(~/.azure/credentials). - - When set to C(cli), the credentials will be sources from the Azure CLI profile. C(subscription_id) or the environment variable - C(AZURE_SUBSCRIPTION_ID) can be used to identify the subscription ID if more than one is present otherwise the default - az cli subscription is used. - - When set to C(msi), the host machine must be an azure resource with an enabled MSI extension. C(subscription_id) or the - environment variable C(AZURE_SUBSCRIPTION_ID) can be used to identify the subscription ID if the resource is granted - access to more than one subscription, otherwise the first subscription is chosen. - - The C(msi) was added in Ansible 2.6. - type: str - default: auto - choices: - - auto - - cli - - credential_file - - env - - msi - version_added: '0.0.1' - api_profile: - description: - - Selects an API profile to use when communicating with Azure services. Default value of C(latest) is appropriate for public clouds; - future values will allow use with Azure Stack. - type: str - default: latest - version_added: '0.0.1' - log_path: - description: - - Parent argument. - type: str - log_mode: - description: - - Parent argument. - type: str -requirements: - - python >= 2.7 - - The host that executes this module must have the azure.azcollection collection installed via galaxy - - All python packages listed in collection's requirements-azure.txt must be installed via pip on the host that executes modules from azure.azcollection - - Full installation instructions may be found https://galaxy.ansible.com/azure/azcollection - -notes: - - For authentication with Azure you can pass parameters, set environment variables, use a profile stored - in ~/.azure/credentials, or log in before you run your tasks or playbook with C(az login). - - Authentication is also possible using a service principal or Active Directory user. - - To authenticate via service principal, pass subscription_id, client_id, secret and tenant or set environment - variables AZURE_SUBSCRIPTION_ID, AZURE_CLIENT_ID, AZURE_SECRET and AZURE_TENANT. - - To authenticate via Active Directory user, pass ad_user and password, or set AZURE_AD_USER and - AZURE_PASSWORD in the environment. - - "Alternatively, credentials can be stored in ~/.azure/credentials. This is an ini file containing - a [default] section and the following keys: subscription_id, client_id, secret and tenant or - subscription_id, ad_user and password. It is also possible to add additional profiles. Specify the profile - by passing profile or setting AZURE_PROFILE in the environment." - -seealso: - - name: Sign in with Azure CLI - link: https://docs.microsoft.com/en-us/cli/azure/authenticate-azure-cli?view=azure-cli-latest - description: How to authenticate using the C(az login) command. - ''' diff --git a/ansible_collections/netapp/azure/plugins/doc_fragments/azure_tags.py b/ansible_collections/netapp/azure/plugins/doc_fragments/azure_tags.py deleted file mode 100644 index 8edb80eed..000000000 --- a/ansible_collections/netapp/azure/plugins/doc_fragments/azure_tags.py +++ /dev/null @@ -1,31 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright: (c) 2016, Matt Davis, <mdavis@ansible.com> -# Copyright: (c) 2016, Chris Houseknecht, <house@redhat.com> -# 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 - - -class ModuleDocFragment(object): - - # Azure doc fragment - DOCUMENTATION = r''' -options: - tags: - description: - - Dictionary of string:string pairs to assign as metadata to the object. - - Metadata tags on the object will be updated with any provided values. - - To remove tags set append_tags option to false. - - Currently, Azure DNS zones and Traffic Manager services also don't allow the use of spaces in the tag. - - Azure Front Door doesn't support the use of # in the tag name. - - Azure Automation and Azure CDN only support 15 tags on resources. - type: dict - append_tags: - description: - - Use to control if tags field is canonical or just appends to existing tags. - - When canonical, any tags not found in the tags parameter will be removed from the object's metadata. - type: bool - default: yes - ''' diff --git a/ansible_collections/netapp/azure/plugins/doc_fragments/netapp.py b/ansible_collections/netapp/azure/plugins/doc_fragments/netapp.py deleted file mode 100644 index 18e9cc2a2..000000000 --- a/ansible_collections/netapp/azure/plugins/doc_fragments/netapp.py +++ /dev/null @@ -1,43 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright: (c) 2019, NetApp Ansible Team ng-ansibleteam@netapp.com -# 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 - - -class ModuleDocFragment(object): - - DOCUMENTATION = r''' -options: - - See respective platform section for more details -requirements: - - See respective platform section for more details -notes: - - Ansible modules are available for the following NetApp Storage Platforms: E-Series, ONTAP, SolidFire -''' - - # Documentation fragment for Cloud Volume Services on Azure NetApp (azure_rm_netapp) - AZURE_RM_NETAPP = r''' -options: - resource_group: - description: - - Name of the resource group. - required: true - type: str -requirements: - - python >= 2.7 - - azure >= 2.0.0 - - Python azure-mgmt. Install using 'pip install azure-mgmt' - - Python azure-mgmt-netapp. Install using 'pip install azure-mgmt-netapp' - - For authentication with Azure NetApp log in before you run your tasks or playbook with C(az login). - -notes: - - The modules prefixed with azure_rm_netapp are built to support the Cloud Volume Services for Azure NetApp Files. - -seealso: - - name: Sign in with Azure CLI - link: https://docs.microsoft.com/en-us/cli/azure/authenticate-azure-cli?view=azure-cli-latest - description: How to authenticate using the C(az login) command. - ''' diff --git a/ansible_collections/netapp/azure/plugins/module_utils/azure_rm_netapp_common.py b/ansible_collections/netapp/azure/plugins/module_utils/azure_rm_netapp_common.py deleted file mode 100644 index 166327088..000000000 --- a/ansible_collections/netapp/azure/plugins/module_utils/azure_rm_netapp_common.py +++ /dev/null @@ -1,163 +0,0 @@ -# (c) 2019, NetApp, Inc -# GNU General Public License v3.0+ -# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' -azure_rm_netapp_common -Wrapper around AzureRMModuleBase base class -''' - -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -import sys - -HAS_AZURE_COLLECTION = True -NEW_STYLE = None -COLLECTION_VERSION = "21.10.1" -IMPORT_ERRORS = [] -SDK_VERSION = "0.0.0" - -if 'pytest' in sys.modules: - from ansible_collections.netapp.azure.plugins.module_utils.netapp_module import AzureRMModuleBaseMock as AzureRMModuleBase -else: - try: - from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase - except ImportError as exc: - IMPORT_ERRORS.append(str(exc)) - HAS_AZURE_COLLECTION = False - - class AzureRMModuleBase: - def __init__(self, derived_arg_spec, required_if=None, supports_check_mode=False, supports_tags=True, **kwargs): - raise ImportError(IMPORT_ERRORS) - - except SyntaxError as exc: - # importing Azure collection fails with python 2.6 - if sys.version_info < (2, 8): - IMPORT_ERRORS.append(str(exc)) - from ansible_collections.netapp.azure.plugins.module_utils.netapp_module import AzureRMModuleBaseMock as AzureRMModuleBase - HAS_AZURE_COLLECTION = False - else: - raise - -try: - from azure.mgmt.netapp import NetAppManagementClient # 1.0.0 or newer - NEW_STYLE = True -except ImportError as exc: - IMPORT_ERRORS.append(str(exc)) - -if NEW_STYLE is None: - try: - from azure.mgmt.netapp import AzureNetAppFilesManagementClient # 0.10.0 or older - NEW_STYLE = False - except ImportError as exc: - IMPORT_ERRORS.append(str(exc)) - -try: - from azure.mgmt.netapp import VERSION as SDK_VERSION -except ImportError as exc: - IMPORT_ERRORS.append(str(exc)) - - -class AzureRMNetAppModuleBase(AzureRMModuleBase): - ''' Wrapper around AzureRMModuleBase base class ''' - def __init__(self, derived_arg_spec, required_if=None, supports_check_mode=False, supports_tags=True): - self._netapp_client = None - self._new_style = NEW_STYLE - self._sdk_version = SDK_VERSION - super(AzureRMNetAppModuleBase, self).__init__(derived_arg_spec=derived_arg_spec, - required_if=required_if, - supports_check_mode=supports_check_mode, - supports_tags=supports_tags) - if not HAS_AZURE_COLLECTION: - self.fail_when_import_errors(IMPORT_ERRORS) - - def get_mgmt_svc_client(self, client_type, base_url=None, api_version=None): - if not self._new_style: - return super(AzureRMNetAppModuleBase, self).get_mgmt_svc_client(client_type, base_url, api_version) - self.log('Getting management service client NetApp {0}'.format(client_type.__name__)) - self.check_client_version(client_type) - - if not base_url: - # most things are resource_manager, don't make everyone specify - base_url = self.azure_auth._cloud_environment.endpoints.resource_manager - - client_kwargs = dict(credential=self.azure_auth.azure_credentials, subscription_id=self.azure_auth.subscription_id, base_url=base_url) - - return client_type(**client_kwargs) - - @property - def netapp_client(self): - self.log('Getting netapp client') - if self._new_style is None: - # note that we always have at least one import error - self.fail_when_import_errors(IMPORT_ERRORS) - if self._netapp_client is None: - if self._new_style: - self._netapp_client = self.get_mgmt_svc_client(NetAppManagementClient) - else: - self._netapp_client = self.get_mgmt_svc_client(AzureNetAppFilesManagementClient, - base_url=self._cloud_environment.endpoints.resource_manager, - api_version='2018-05-01') - return self._netapp_client - - @property - def new_style(self): - return self._new_style - - @property - def sdk_version(self): - return self._sdk_version - - def get_method(self, category, name): - try: - methods = getattr(self.netapp_client, category) - except AttributeError as exc: - self.module.fail_json('Error: category %s not found for netapp_client: %s' % (category, str(exc))) - - if self._new_style: - name = 'begin_' + name - try: - method = getattr(methods, name) - except AttributeError as exc: - self.module.fail_json('Error: method %s not found for netapp_client category: %s - %s' % (name, category, str(exc))) - return method - - def fail_when_import_errors(self, import_errors, has_azure_mgmt_netapp=True): - if has_azure_mgmt_netapp and not import_errors: - return - msg = '' - if not has_azure_mgmt_netapp: - msg = "The python azure-mgmt-netapp package is required. " - if hasattr(self, 'module'): - msg += 'Import errors: %s' % str(import_errors) - self.module.fail_json(msg=msg) - msg += str(import_errors) - raise ImportError(msg) - - def has_feature(self, feature_name): - feature = self.get_feature(feature_name) - if isinstance(feature, bool): - return feature - self.module.fail_json(msg="Error: expected bool type for feature flag: %s" % feature_name) - - def get_feature(self, feature_name): - ''' if the user has configured the feature, use it - otherwise, use our default - ''' - default_flags = dict( - # TODO: review need for these - # trace_apis=False, # if true, append REST requests/responses to /tmp/azure_apis.log - # check_required_params_for_none=True, - # deprecation_warning=True, - # show_modified=True, - # - # preview features in ANF - ignore_change_ownership_mode=True - ) - - if self.parameters.get('feature_flags') is not None and feature_name in self.parameters['feature_flags']: - return self.parameters['feature_flags'][feature_name] - if feature_name in default_flags: - return default_flags[feature_name] - self.module.fail_json(msg="Internal error: unexpected feature flag: %s" % feature_name) diff --git a/ansible_collections/netapp/azure/plugins/module_utils/netapp_module.py b/ansible_collections/netapp/azure/plugins/module_utils/netapp_module.py deleted file mode 100644 index 9ee758c01..000000000 --- a/ansible_collections/netapp/azure/plugins/module_utils/netapp_module.py +++ /dev/null @@ -1,271 +0,0 @@ -# This code is part of Ansible, but is an independent component. -# This particular file snippet, and this file snippet only, is BSD licensed. -# Modules you write using this snippet, which is embedded dynamically by Ansible -# still belong to the author of the module, and may assign their own license -# to the complete work. -# -# Copyright (c) 2018, Laurent Nicolas <laurentn@netapp.com> -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE -# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -''' Support class for NetApp ansible modules ''' - -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -from ansible.module_utils import basic - - -class AzureRMModuleBaseMock(): - ''' Mock for sanity tests when azcollection is not installed ''' - def __init__(self, derived_arg_spec, required_if=None, supports_check_mode=False, supports_tags=True, **kwargs): - if supports_tags: - derived_arg_spec.update(dict(tags=dict())) - self.module = basic.AnsibleModule( - argument_spec=derived_arg_spec, - required_if=required_if, - supports_check_mode=supports_check_mode - ) - self.module.warn('Running in Unit Test context!') - # the following is done in exec_module() - self.parameters = dict([item for item in self.module.params.items() if item[1] is not None]) - # remove values with a default of None (not required) - self.module_arg_spec = dict([item for item in self.module_arg_spec.items() if item[0] in self.parameters]) - - def update_tags(self, tags): - self.module.log('update_tags called with:', tags) - return None, None - - -def cmp(obj1, obj2): - """ - Python 3 does not have a cmp function, this will do the cmp. - :param a: first object to check - :param b: second object to check - :return: - """ - # convert to lower case for string comparison. - if obj1 is None: - return -1 - if isinstance(obj1, str) and isinstance(obj2, str): - obj1 = obj1.lower() - obj2 = obj2.lower() - # if list has string element, convert string to lower case. - if isinstance(obj1, list) and isinstance(obj2, list): - obj1 = [x.lower() if isinstance(x, str) else x for x in obj1] - obj2 = [x.lower() if isinstance(x, str) else x for x in obj2] - obj1.sort() - obj2.sort() - if isinstance(obj1, dict) and isinstance(obj2, dict): - return 0 if obj1 == obj2 else 1 - return (obj1 > obj2) - (obj1 < obj2) - - -class NetAppModule(): - ''' - Common class for NetApp modules - set of support functions to derive actions based - on the current state of the system, and a desired state - ''' - - def __init__(self): - self.log = [] - self.changed = False - self.parameters = {'name': 'not intialized'} - self.zapi_string_keys = dict() - self.zapi_bool_keys = dict() - self.zapi_list_keys = {} - self.zapi_int_keys = {} - self.zapi_required = {} - - def set_parameters(self, ansible_params): - self.parameters = {} - for param in ansible_params: - if ansible_params[param] is not None: - self.parameters[param] = ansible_params[param] - return self.parameters - - def get_cd_action(self, current, desired): - ''' takes a desired state and a current state, and return an action: - create, delete, None - eg: - is_present = 'absent' - some_object = self.get_object(source) - if some_object is not None: - is_present = 'present' - action = cd_action(current=is_present, desired = self.desired.state()) - ''' - desired_state = desired['state'] if 'state' in desired else 'present' - if current is None and desired_state == 'absent': - return None - if current is not None and desired_state == 'present': - return None - # change in state - self.changed = True - if current is not None: - return 'delete' - return 'create' - - def compare_and_update_values(self, current, desired, keys_to_compare): - updated_values = {} - is_changed = False - for key in keys_to_compare: - if key in current: - if key in desired and desired[key] is not None: - if current[key] != desired[key]: - updated_values[key] = desired[key] - is_changed = True - else: - updated_values[key] = current[key] - else: - updated_values[key] = current[key] - - return updated_values, is_changed - - @staticmethod - def check_keys(current, desired): - ''' TODO: raise an error if keys do not match - with the exception of: - new_name, state in desired - ''' - - @staticmethod - def compare_lists(current, desired, get_list_diff): - ''' compares two lists and return a list of elements that are either the desired elements or elements that are - modified from the current state depending on the get_list_diff flag - :param: current: current item attribute in ONTAP - :param: desired: attributes from playbook - :param: get_list_diff: specifies whether to have a diff of desired list w.r.t current list for an attribute - :return: list of attributes to be modified - :rtype: list - ''' - desired_diff_list = [item for item in desired if item not in current] # get what in desired and not in current - current_diff_list = [item for item in current if item not in desired] # get what in current but not in desired - - if desired_diff_list or current_diff_list: - # there are changes - if get_list_diff: - return desired_diff_list - else: - return desired - else: - return [] - - def get_modified_attributes(self, current, desired, get_list_diff=False): - ''' takes two dicts of attributes and return a dict of attributes that are - not in the current state - It is expected that all attributes of interest are listed in current and - desired. - :param: current: current attributes in ONTAP - :param: desired: attributes from playbook - :param: get_list_diff: specifies whether to have a diff of desired list w.r.t current list for an attribute - :return: dict of attributes to be modified - :rtype: dict - - NOTE: depending on the attribute, the caller may need to do a modify or a - different operation (eg move volume if the modified attribute is an - aggregate name) - ''' - # if the object does not exist, we can't modify it - modified = {} - if current is None: - return modified - - # error out if keys do not match - self.check_keys(current, desired) - - # collect changed attributes - for key, value in current.items(): - if key in desired and desired[key] is not None: - if isinstance(value, list): - modified_list = self.compare_lists(value, desired[key], get_list_diff) # get modified list from current and desired - if modified_list: - modified[key] = modified_list - elif cmp(value, desired[key]) != 0: - modified[key] = desired[key] - if modified: - self.changed = True - return modified - - def is_rename_action(self, source, target): - ''' takes a source and target object, and returns True - if a rename is required - eg: - source = self.get_object(source_name) - target = self.get_object(target_name) - action = is_rename_action(source, target) - :return: None for error, True for rename action, False otherwise - ''' - if source is None and target is None: - # error, do nothing - # cannot rename an non existent resource - # alternatively we could create B - return None - if source is not None and target is not None: - # error, do nothing - # idempotency (or) new_name_is_already_in_use - # alternatively we could delete B and rename A to B - return False - if source is None: - # do nothing, maybe the rename was already done - return False - # source is not None and target is None: - # rename is in order - self.changed = True - return True - - def filter_out_none_entries(self, list_or_dict): - """take a dict or list as input and return a dict/list without keys/elements whose values are None - skip empty dicts or lists. - """ - - if isinstance(list_or_dict, dict): - result = {} - for key, value in list_or_dict.items(): - if isinstance(value, (list, dict)): - sub = self.filter_out_none_entries(value) - if sub: - # skip empty dict or list - result[key] = sub - elif value is not None: - # skip None value - result[key] = value - return result - - if isinstance(list_or_dict, list): - alist = [] - for item in list_or_dict: - if isinstance(item, (list, dict)): - sub = self.filter_out_none_entries(item) - if sub: - # skip empty dict or list - alist.append(sub) - elif item is not None: - # skip None value - alist.append(item) - return alist - - raise TypeError('unexpected type %s' % type(list_or_dict)) - - @staticmethod - def get_not_none_values_from_dict(parameters, keys): - # python 2.6 does not support dict comprehension using k: v - return dict((key, value) for key, value in parameters.items() if key in keys and value is not None) diff --git a/ansible_collections/netapp/azure/plugins/modules/azure_rm_netapp_account.py b/ansible_collections/netapp/azure/plugins/modules/azure_rm_netapp_account.py deleted file mode 100644 index c09ade0df..000000000 --- a/ansible_collections/netapp/azure/plugins/modules/azure_rm_netapp_account.py +++ /dev/null @@ -1,404 +0,0 @@ -#!/usr/bin/python -# -# (c) 2019, NetApp, Inc -# GNU General Public License v3.0+ -# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' -azure_rm_netapp_account -''' - -from __future__ import absolute_import, division, print_function -__metaclass__ = type - -DOCUMENTATION = ''' ---- -module: azure_rm_netapp_account - -short_description: Manage NetApp Azure Files Account -version_added: 19.10.0 -author: NetApp Ansible Team (@carchi8py) <ng-ansibleteam@netapp.com> - -description: - - Create and delete NetApp Azure account. - Provide the Resource group name for the NetApp account to be created. -extends_documentation_fragment: - - netapp.azure.azure - - netapp.azure.azure_tags - - netapp.azure.netapp.azure_rm_netapp - -options: - name: - description: - - The name of the NetApp account. - required: true - type: str - location: - description: - - Resource location. - - Required for create. - type: str - - active_directories: - description: - - list of active directory dictionaries. - - The list is currently limited to a single active directory (ANF or Azure limit of one AD per subscription). - type: list - elements: dict - version_added: 21.2.0 - suboptions: - active_directory_id: - description: not used for create. Not needed for join. - type: str - dns: - description: list of DNS addresses. Required for create or join. - type: list - elements: str - domain: - description: Fully Qualified Active Directory DNS Domain Name. Required for create or join. - type: str - site: - description: The Active Directory site the service will limit Domain Controller discovery to. - type: str - smb_server_name: - description: Prefix for creating the SMB server's computer account name in the Active Directory domain. Required for create or join. - type: str - organizational_unit: - description: LDAP Path for the Organization Unit where SMB Server machine accounts will be created (i.e. OU=SecondLevel,OU=FirstLevel). - type: str - username: - description: Credentials that have permissions to create SMB server machine account in the AD domain. Required for create or join. - type: str - password: - description: see username. If password is present, the module is not idempotent, as we cannot check the current value. Required for create or join. - type: str - aes_encryption: - description: If enabled, AES encryption will be enabled for SMB communication. - type: bool - ldap_signing: - description: Specifies whether or not the LDAP traffic needs to be signed. - type: bool - ad_name: - description: Name of the active directory machine. Used only while creating kerberos volume. - type: str - version_added: 21.3.0 - kdc_ip: - description: kdc server IP addresses for the active directory machine. Used only while creating kerberos volume. - type: str - version_added: 21.3.0 - server_root_ca_certificate: - description: - - When LDAP over SSL/TLS is enabled, the LDAP client is required to have base64 encoded Active Directory Certificate Service's - self-signed root CA certificate, this optional parameter is used only for dual protocol with LDAP user-mapping volumes. - type: str - version_added: 21.3.0 - state: - description: - - State C(present) will check that the NetApp account exists with the requested configuration. - - State C(absent) will delete the NetApp account. - default: present - choices: - - absent - - present - type: str - debug: - description: output details about current account if it exists. - type: bool - default: false - -''' -EXAMPLES = ''' - -- name: Create NetApp Azure Account - netapp.azure.azure_rm_netapp_account: - resource_group: myResourceGroup - name: testaccount - location: eastus - tags: {'abc': 'xyz', 'cba': 'zyx'} - -- name: Modify Azure NetApp account (Join AD) - netapp.azure.azure_rm_netapp_account: - resource_group: myResourceGroup - name: testaccount - location: eastus - active_directories: - - site: ln - dns: 10.10.10.10 - domain: domain.com - smb_server_name: dummy - password: xxxxxx - username: laurentn - -- name: Delete NetApp Azure Account - netapp.azure.azure_rm_netapp_account: - state: absent - resource_group: myResourceGroup - name: testaccount - location: eastus - -- name: Create Azure NetApp account (with AD) - netapp.azure.azure_rm_netapp_account: - resource_group: laurentngroupnodash - name: tests-netapp11 - location: eastus - tags: - creator: laurentn - use: Ansible - active_directories: - - site: ln - dns: 10.10.10.10 - domain: domain.com - smb_server_name: dummy - password: xxxxxx - username: laurentn -''' - -RETURN = ''' -''' - -import traceback - -HAS_AZURE_MGMT_NETAPP = False -IMPORT_ERRORS = list() - -try: - from msrestazure.azure_exceptions import CloudError - from azure.core.exceptions import AzureError, ResourceNotFoundError -except ImportError as exc: - IMPORT_ERRORS.append(str(exc)) - -try: - from azure.mgmt.netapp.models import NetAppAccount, NetAppAccountPatch, ActiveDirectory - HAS_AZURE_MGMT_NETAPP = True -except ImportError as exc: - IMPORT_ERRORS.append(str(exc)) - -from ansible.module_utils.basic import to_native -from ansible_collections.netapp.azure.plugins.module_utils.azure_rm_netapp_common import AzureRMNetAppModuleBase -from ansible_collections.netapp.azure.plugins.module_utils.netapp_module import NetAppModule - - -class AzureRMNetAppAccount(AzureRMNetAppModuleBase): - ''' create, modify, delete account, including joining AD domain - ''' - def __init__(self): - - self.module_arg_spec = dict( - resource_group=dict(type='str', required=True), - name=dict(type='str', required=True), - location=dict(type='str', required=False), - state=dict(choices=['present', 'absent'], default='present', type='str'), - active_directories=dict(type='list', elements='dict', options=dict( - active_directory_id=dict(type='str'), - dns=dict(type='list', elements='str'), - domain=dict(type='str'), - site=dict(type='str'), - smb_server_name=dict(type='str'), - organizational_unit=dict(type='str'), - username=dict(type='str'), - password=dict(type='str', no_log=True), - aes_encryption=dict(type='bool'), - ldap_signing=dict(type='bool'), - ad_name=dict(type='str'), - kdc_ip=dict(type='str'), - server_root_ca_certificate=dict(type='str', no_log=True), - )), - debug=dict(type='bool', default=False) - ) - - self.na_helper = NetAppModule() - self.parameters = dict() - self.debug = list() - self.warnings = list() - - # import errors are handled in AzureRMModuleBase - super(AzureRMNetAppAccount, self).__init__(derived_arg_spec=self.module_arg_spec, - required_if=[('state', 'present', ['location'])], - supports_check_mode=True) - - def get_azure_netapp_account(self): - """ - Returns NetApp Account object for an existing account - Return None if account does not exist - """ - try: - account_get = self.netapp_client.accounts.get(self.parameters['resource_group'], self.parameters['name']) - except (CloudError, ResourceNotFoundError): # account does not exist - return None - account = vars(account_get) - ads = None - if account.get('active_directories') is not None: - ads = list() - for each_ad in account.get('active_directories'): - ad_dict = vars(each_ad) - dns = ad_dict.get('dns') - if dns is not None: - ad_dict['dns'] = sorted(dns.split(',')) - ads.append(ad_dict) - account['active_directories'] = ads - return account - - def create_account_request_body(self, modify=None): - """ - Create an Azure NetApp Account Request Body - :return: None - """ - options = dict() - location = None - for attr in ('location', 'tags', 'active_directories'): - value = self.parameters.get(attr) - if attr == 'location' and modify is None: - location = value - continue - if value is not None: - if modify is None or attr in modify: - if attr == 'active_directories': - ads = list() - for ad_dict in value: - if ad_dict.get('dns') is not None: - # API expects a string of comma separated elements - ad_dict['dns'] = ','.join(ad_dict['dns']) - ads.append(ActiveDirectory(**self.na_helper.filter_out_none_entries(ad_dict))) - value = ads - options[attr] = value - if modify is None: - if location is None: - self.module.fail_json(msg="Error: 'location' is a required parameter") - return NetAppAccount(location=location, **options) - return NetAppAccountPatch(**options) - - def create_azure_netapp_account(self): - """ - Create an Azure NetApp Account - :return: None - """ - account_body = self.create_account_request_body() - try: - response = self.get_method('accounts', 'create_or_update')(body=account_body, - resource_group_name=self.parameters['resource_group'], - account_name=self.parameters['name']) - while response.done() is not True: - response.result(10) - except (CloudError, AzureError) as error: - self.module.fail_json(msg='Error creating Azure NetApp account %s: %s' - % (self.parameters['name'], to_native(error)), - exception=traceback.format_exc()) - - def update_azure_netapp_account(self, modify): - """ - Create an Azure NetApp Account - :return: None - """ - account_body = self.create_account_request_body(modify) - try: - response = self.get_method('accounts', 'update')(body=account_body, - resource_group_name=self.parameters['resource_group'], - account_name=self.parameters['name']) - while response.done() is not True: - response.result(10) - except (CloudError, AzureError) as error: - self.module.fail_json(msg='Error creating Azure NetApp account %s: %s' - % (self.parameters['name'], to_native(error)), - exception=traceback.format_exc()) - - def delete_azure_netapp_account(self): - """ - Delete an Azure NetApp Account - :return: None - """ - try: - response = self.get_method('accounts', 'delete')(resource_group_name=self.parameters['resource_group'], - account_name=self.parameters['name']) - while response.done() is not True: - response.result(10) - except (CloudError, AzureError) as error: - self.module.fail_json(msg='Error deleting Azure NetApp account %s: %s' - % (self.parameters['name'], to_native(error)), - exception=traceback.format_exc()) - - def get_changes_in_ads(self, current, desired): - c_ads = current.get('active_directories') - d_ads = desired.get('active_directories') - if not c_ads: - return desired.get('active_directories'), None - if not d_ads: - return None, current.get('active_directories') - if len(c_ads) > 1 or len(d_ads) > 1: - msg = 'Error checking for AD, currently only one AD is supported.' - if len(c_ads) > 1: - msg += ' Current: %s.' % str(c_ads) - if len(d_ads) > 1: - msg += ' Desired: %s.' % str(d_ads) - self.module.fail_json(msg='Error checking for AD, currently only one AD is supported') - changed = False - d_ad = d_ads[0] - c_ad = c_ads[0] - for key, value in c_ad.items(): - if key == 'password': - if d_ad.get(key) is None: - continue - self.warnings.append("module is not idempotent if 'password:' is present") - if d_ad.get(key) is None: - d_ad[key] = value - elif d_ad.get(key) != value: - changed = True - self.debug.append("key: %s, value %s" % (key, value)) - if changed: - return [d_ad], None - return None, None - - def exec_module(self, **kwargs): - - # unlikely - self.fail_when_import_errors(IMPORT_ERRORS, HAS_AZURE_MGMT_NETAPP) - - # set up parameters according to our initial list - for key in list(self.module_arg_spec): - self.parameters[key] = kwargs[key] - # and common parameter - for key in ['tags']: - if key in kwargs: - self.parameters[key] = kwargs[key] - - current = self.get_azure_netapp_account() - modify = None - cd_action = self.na_helper.get_cd_action(current, self.parameters) - self.debug.append('current: %s' % str(current)) - if current is not None and cd_action is None: - ads_to_add, ads_to_delete = self.get_changes_in_ads(current, self.parameters) - self.parameters.pop('active_directories', None) - if ads_to_add: - self.parameters['active_directories'] = ads_to_add - if ads_to_delete: - self.module.fail_json(msg="Error: API does not support unjoining an AD", debug=self.debug) - modify = self.na_helper.get_modified_attributes(current, self.parameters) - if 'tags' in modify: - dummy, modify['tags'] = self.update_tags(current.get('tags')) - - if self.na_helper.changed: - if self.module.check_mode: - pass - else: - if cd_action == 'create': - self.create_azure_netapp_account() - elif cd_action == 'delete': - self.delete_azure_netapp_account() - elif modify: - self.update_azure_netapp_account(modify) - results = dict( - changed=self.na_helper.changed, - modify=modify - ) - if self.warnings: - results['warnings'] = self.warnings - if self.parameters['debug']: - results['debug'] = self.debug - self.module.exit_json(**results) - - -def main(): - AzureRMNetAppAccount() - - -if __name__ == '__main__': - main() diff --git a/ansible_collections/netapp/azure/plugins/modules/azure_rm_netapp_capacity_pool.py b/ansible_collections/netapp/azure/plugins/modules/azure_rm_netapp_capacity_pool.py deleted file mode 100644 index 9d099a03f..000000000 --- a/ansible_collections/netapp/azure/plugins/modules/azure_rm_netapp_capacity_pool.py +++ /dev/null @@ -1,259 +0,0 @@ -#!/usr/bin/python -# -# (c) 2019, NetApp, Inc -# GNU General Public License v3.0+ -# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -""" -azure_rm_netapp_capacity_pool -""" - -from __future__ import absolute_import, division, print_function -__metaclass__ = type - -DOCUMENTATION = ''' ---- -module: azure_rm_netapp_capacity_pool - -short_description: Manage NetApp Azure Files capacity pool -version_added: 19.10.0 -author: NetApp Ansible Team (@carchi8py) <ng-ansibleteam@netapp.com> - -description: - - Create and delete NetApp Azure capacity pool. - Provide the Resource group name for the capacity pool to be created. - - Resize NetApp Azure capacity pool -extends_documentation_fragment: - - netapp.azure.azure - - netapp.azure.azure_tags - - netapp.azure.netapp.azure_rm_netapp - -options: - name: - description: - - The name of the capacity pool. - required: true - type: str - account_name: - description: - - The name of the NetApp account. - required: true - type: str - location: - description: - - Resource location. - - Required for create. - type: str - size: - description: - - Provisioned size of the pool (in chunks). Allowed values are in 4TiB chunks. - - Provide number to be multiplied to 4TiB. - - Required for create. - default: 1 - type: int - service_level: - description: - - The service level of the file system. - - Required for create. - choices: ['Standard', 'Premium', 'Ultra'] - type: str - version_added: "20.5.0" - state: - description: - - State C(present) will check that the capacity pool exists with the requested configuration. - - State C(absent) will delete the capacity pool. - default: present - choices: ['present', 'absent'] - type: str - -''' -EXAMPLES = ''' - -- name: Create Azure NetApp capacity pool - netapp.azure.azure_rm_netapp_capacity_pool: - resource_group: myResourceGroup - account_name: tests-netapp - name: tests-pool - location: eastus - size: 2 - service_level: Standard - -- name: Resize Azure NetApp capacity pool - netapp.azure.azure_rm_netapp_capacity_pool: - resource_group: myResourceGroup - account_name: tests-netapp - name: tests-pool - location: eastus - size: 3 - service_level: Standard - -- name: Delete Azure NetApp capacity pool - netapp.azure.azure_rm_netapp_capacity_pool: - state: absent - resource_group: myResourceGroup - account_name: tests-netapp - name: tests-pool - -''' - -RETURN = ''' -''' - -import traceback - -AZURE_OBJECT_CLASS = 'NetAppAccount' -HAS_AZURE_MGMT_NETAPP = False -IMPORT_ERRORS = list() -SIZE_POOL = 4398046511104 - -try: - from msrestazure.azure_exceptions import CloudError - from azure.core.exceptions import AzureError, ResourceNotFoundError -except ImportError as exc: - IMPORT_ERRORS.append(str(exc)) - -try: - from azure.mgmt.netapp.models import CapacityPool - HAS_AZURE_MGMT_NETAPP = True -except ImportError as exc: - IMPORT_ERRORS.append(str(exc)) - -from ansible.module_utils.basic import to_native -from ansible_collections.netapp.azure.plugins.module_utils.azure_rm_netapp_common import AzureRMNetAppModuleBase -from ansible_collections.netapp.azure.plugins.module_utils.netapp_module import NetAppModule - - -class AzureRMNetAppCapacityPool(AzureRMNetAppModuleBase): - """ create, modify, delete a capacity pool """ - def __init__(self): - - self.module_arg_spec = dict( - resource_group=dict(type='str', required=True), - name=dict(type='str', required=True), - account_name=dict(type='str', required=True), - location=dict(type='str', required=False), - state=dict(choices=['present', 'absent'], default='present', type='str'), - size=dict(type='int', required=False, default=1), - service_level=dict(type='str', required=False, choices=['Standard', 'Premium', 'Ultra']), - ) - - self.na_helper = NetAppModule() - self.parameters = dict() - - # import errors are handled in AzureRMModuleBase - super(AzureRMNetAppCapacityPool, self).__init__(derived_arg_spec=self.module_arg_spec, - required_if=[('state', 'present', ['location', 'service_level'])], - supports_check_mode=True) - - def get_azure_netapp_capacity_pool(self): - """ - Returns capacity pool object for an existing pool - Return None if capacity pool does not exist - """ - try: - capacity_pool_get = self.netapp_client.pools.get(self.parameters['resource_group'], - self.parameters['account_name'], self.parameters['name']) - except (CloudError, ResourceNotFoundError): # capacity pool does not exist - return None - return capacity_pool_get - - def create_azure_netapp_capacity_pool(self): - """ - Create a capacity pool for the given Azure NetApp Account - :return: None - """ - options = self.na_helper.get_not_none_values_from_dict(self.parameters, ['location', 'service_level', 'size', 'tags']) - capacity_pool_body = CapacityPool(**options) - try: - response = self.get_method('pools', 'create_or_update')(body=capacity_pool_body, resource_group_name=self.parameters['resource_group'], - account_name=self.parameters['account_name'], - pool_name=self.parameters['name']) - while response.done() is not True: - response.result(10) - - except (CloudError, AzureError) as error: - self.module.fail_json(msg='Error creating capacity pool %s for Azure NetApp account %s: %s' - % (self.parameters['name'], self.parameters['account_name'], to_native(error)), - exception=traceback.format_exc()) - - def modify_azure_netapp_capacity_pool(self, modify): - """ - Modify a capacity pool for the given Azure NetApp Account - :return: None - """ - options = self.na_helper.get_not_none_values_from_dict(self.parameters, ['location', 'service_level', 'size', 'tags']) - capacity_pool_body = CapacityPool(**options) - try: - response = self.get_method('pools', 'update')(body=capacity_pool_body, resource_group_name=self.parameters['resource_group'], - account_name=self.parameters['account_name'], - pool_name=self.parameters['name']) - while response.done() is not True: - response.result(10) - - except (CloudError, AzureError) as error: - self.module.fail_json(msg='Error modifying capacity pool %s for Azure NetApp account %s: %s' - % (self.parameters['name'], self.parameters['account_name'], to_native(error)), - exception=traceback.format_exc()) - - def delete_azure_netapp_capacity_pool(self): - """ - Delete a capacity pool for the given Azure NetApp Account - :return: None - """ - try: - response = self.get_method('pools', 'delete')(resource_group_name=self.parameters['resource_group'], - account_name=self.parameters['account_name'], pool_name=self.parameters['name']) - while response.done() is not True: - response.result(10) - - except (CloudError, AzureError) as error: - self.module.fail_json(msg='Error deleting capacity pool %s for Azure NetApp account %s: %s' - % (self.parameters['name'], self.parameters['name'], to_native(error)), - exception=traceback.format_exc()) - - def exec_module(self, **kwargs): - - # unlikely - self.fail_when_import_errors(IMPORT_ERRORS, HAS_AZURE_MGMT_NETAPP) - - # set up parameters according to our initial list - for key in list(self.module_arg_spec): - self.parameters[key] = kwargs[key] - # and common parameter - for key in ['tags']: - if key in kwargs: - self.parameters[key] = kwargs[key] - if 'size' in self.parameters: - self.parameters['size'] *= SIZE_POOL - - modify = {} - current = self.get_azure_netapp_capacity_pool() - cd_action = self.na_helper.get_cd_action(current, self.parameters) - if cd_action is None and self.parameters['state'] == 'present': - current = vars(current) - # get_azure_netapp_capacity_pool() returns pool name with account name appended in front of it like 'account/pool' - current['name'] = self.parameters['name'] - modify = self.na_helper.get_modified_attributes(current, self.parameters) - if 'tags' in modify: - dummy, modify['tags'] = self.update_tags(current.get('tags')) - - if self.na_helper.changed: - if self.module.check_mode: - pass - else: - if cd_action == 'create': - self.create_azure_netapp_capacity_pool() - elif cd_action == 'delete': - self.delete_azure_netapp_capacity_pool() - elif modify: - self.modify_azure_netapp_capacity_pool(modify) - - self.module.exit_json(changed=self.na_helper.changed, modify=modify) - - -def main(): - AzureRMNetAppCapacityPool() - - -if __name__ == '__main__': - main() diff --git a/ansible_collections/netapp/azure/plugins/modules/azure_rm_netapp_snapshot.py b/ansible_collections/netapp/azure/plugins/modules/azure_rm_netapp_snapshot.py deleted file mode 100644 index 212f10861..000000000 --- a/ansible_collections/netapp/azure/plugins/modules/azure_rm_netapp_snapshot.py +++ /dev/null @@ -1,226 +0,0 @@ -#!/usr/bin/python -# -# (c) 2019, NetApp, Inc -# GNU General Public License v3.0+ -# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -""" -azure_rm_netapp_snapshot -""" - -from __future__ import absolute_import, division, print_function -__metaclass__ = type - -DOCUMENTATION = ''' ---- -module: azure_rm_netapp_snapshot - -short_description: Manage NetApp Azure Files Snapshot -version_added: 19.10.0 -author: NetApp Ansible Team (@carchi8py) <ng-ansibleteam@netapp.com> - -description: - - Create and delete NetApp Azure Snapshot. -extends_documentation_fragment: - - netapp.azure.azure - - netapp.azure.netapp.azure_rm_netapp - -options: - name: - description: - - The name of the snapshot. - required: true - type: str - volume_name: - description: - - The name of the volume. - required: true - type: str - pool_name: - description: - - The name of the capacity pool. - required: true - type: str - account_name: - description: - - The name of the NetApp account. - required: true - type: str - location: - description: - - Resource location. - - Required for create. - type: str - state: - description: - - State C(present) will check that the snapshot exists with the requested configuration. - - State C(absent) will delete the snapshot. - default: present - choices: - - absent - - present - type: str - -''' -EXAMPLES = ''' - -- name: Create Azure NetApp Snapshot - netapp.azure.azure_rm_netapp_snapshot: - resource_group: myResourceGroup - account_name: tests-netapp - pool_name: tests-pool - volume_name: tests-volume2 - name: tests-snapshot - location: eastus - -- name: Delete Azure NetApp Snapshot - netapp.azure.azure_rm_netapp_snapshot: - state: absent - resource_group: myResourceGroup - account_name: tests-netapp - pool_name: tests-pool - volume_name: tests-volume2 - name: tests-snapshot - -''' - -RETURN = ''' -''' - -import traceback - -AZURE_OBJECT_CLASS = 'NetAppAccount' -HAS_AZURE_MGMT_NETAPP = False -IMPORT_ERRORS = list() - -try: - from msrestazure.azure_exceptions import CloudError - from azure.core.exceptions import AzureError, ResourceNotFoundError -except ImportError as exc: - IMPORT_ERRORS.append(str(exc)) - -try: - from azure.mgmt.netapp.models import Snapshot - HAS_AZURE_MGMT_NETAPP = True -except ImportError as exc: - IMPORT_ERRORS.append(str(exc)) - -from ansible.module_utils.basic import to_native -from ansible_collections.netapp.azure.plugins.module_utils.azure_rm_netapp_common import AzureRMNetAppModuleBase -from ansible_collections.netapp.azure.plugins.module_utils.netapp_module import NetAppModule - - -class AzureRMNetAppSnapshot(AzureRMNetAppModuleBase): - """ crate or delete snapshots """ - def __init__(self): - - self.module_arg_spec = dict( - resource_group=dict(type='str', required=True), - name=dict(type='str', required=True), - volume_name=dict(type='str', required=True), - pool_name=dict(type='str', required=True), - account_name=dict(type='str', required=True), - location=dict(type='str', required=False), - state=dict(choices=['present', 'absent'], default='present', type='str') - ) - self.na_helper = NetAppModule() - self.parameters = dict() - - # import errors are handled in AzureRMModuleBase - super(AzureRMNetAppSnapshot, self).__init__(derived_arg_spec=self.module_arg_spec, - required_if=[('state', 'present', ['location'])], - supports_check_mode=True, - supports_tags=False) - - def get_azure_netapp_snapshot(self): - """ - Returns snapshot object for an existing snapshot - Return None if snapshot does not exist - """ - try: - snapshot_get = self.netapp_client.snapshots.get(self.parameters['resource_group'], self.parameters['account_name'], - self.parameters['pool_name'], self.parameters['volume_name'], - self.parameters['name']) - except (CloudError, ResourceNotFoundError): # snapshot does not exist - return None - return snapshot_get - - def create_azure_netapp_snapshot(self): - """ - Create a snapshot for the given Azure NetApp Account - :return: None - """ - kw_args = dict( - resource_group_name=self.parameters['resource_group'], - account_name=self.parameters['account_name'], - pool_name=self.parameters['pool_name'], - volume_name=self.parameters['volume_name'], - snapshot_name=self.parameters['name'] - ) - if self.new_style: - kw_args['body'] = Snapshot( - location=self.parameters['location'] - ) - else: - kw_args['location'] = self.parameters['location'] - try: - result = self.get_method('snapshots', 'create')(**kw_args) - # waiting till the status turns Succeeded - while result.done() is not True: - result.result(10) - - except (CloudError, AzureError) as error: - self.module.fail_json(msg='Error creating snapshot %s for Azure NetApp account %s: %s' - % (self.parameters['name'], self.parameters['account_name'], to_native(error)), - exception=traceback.format_exc()) - - def delete_azure_netapp_snapshot(self): - """ - Delete a snapshot for the given Azure NetApp Account - :return: None - """ - try: - result = self.get_method('snapshots', 'delete')(resource_group_name=self.parameters['resource_group'], - account_name=self.parameters['account_name'], - pool_name=self.parameters['pool_name'], - volume_name=self.parameters['volume_name'], - snapshot_name=self.parameters['name']) - # waiting till the status turns Succeeded - while result.done() is not True: - result.result(10) - - except (CloudError, AzureError) as error: - self.module.fail_json(msg='Error deleting snapshot %s for Azure NetApp account %s: %s' - % (self.parameters['name'], self.parameters['account_name'], to_native(error)), - exception=traceback.format_exc()) - - def exec_module(self, **kwargs): - - # unlikely - self.fail_when_import_errors(IMPORT_ERRORS, HAS_AZURE_MGMT_NETAPP) - - # set up parameters according to our initial list - for key in list(self.module_arg_spec): - self.parameters[key] = kwargs[key] - - current = self.get_azure_netapp_snapshot() - cd_action = self.na_helper.get_cd_action(current, self.parameters) - - if self.na_helper.changed: - if self.module.check_mode: - pass - else: - if cd_action == 'create': - self.create_azure_netapp_snapshot() - elif cd_action == 'delete': - self.delete_azure_netapp_snapshot() - - self.module.exit_json(changed=self.na_helper.changed) - - -def main(): - AzureRMNetAppSnapshot() - - -if __name__ == '__main__': - main() diff --git a/ansible_collections/netapp/azure/plugins/modules/azure_rm_netapp_volume.py b/ansible_collections/netapp/azure/plugins/modules/azure_rm_netapp_volume.py deleted file mode 100644 index 487787ee7..000000000 --- a/ansible_collections/netapp/azure/plugins/modules/azure_rm_netapp_volume.py +++ /dev/null @@ -1,399 +0,0 @@ -#!/usr/bin/python -# -# (c) 2019, NetApp, Inc -# GNU General Public License v3.0+ -# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' -azure_rm_netapp_volume -''' - -from __future__ import absolute_import, division, print_function -__metaclass__ = type - -DOCUMENTATION = ''' ---- -module: azure_rm_netapp_volume - -short_description: Manage NetApp Azure Files Volume -version_added: 19.10.0 -author: NetApp Ansible Team (@carchi8py) <ng-ansibleteam@netapp.com> - -description: - - Create and delete NetApp Azure volume. -extends_documentation_fragment: - - netapp.azure.azure - - netapp.azure.azure_tags - - netapp.azure.netapp.azure_rm_netapp - -options: - name: - description: - - The name of the volume. - required: true - type: str - file_path: - description: - - A unique file path for the volume. Used when creating mount targets. - type: str - pool_name: - description: - - The name of the capacity pool. - required: true - type: str - account_name: - description: - - The name of the NetApp account. - required: true - type: str - location: - description: - - Resource location. - - Required for create. - type: str - subnet_name: - description: - - Azure resource name for a delegated subnet. Must have the delegation Microsoft.NetApp/volumes. - - Provide name of the subnet ID. - - Required for create. - type: str - aliases: ['subnet_id'] - version_added: 21.1.0 - virtual_network: - description: - - The name of the virtual network required for the subnet to create a volume. - - Required for create. - type: str - service_level: - description: - - The service level of the file system. - - default is Premium. - type: str - choices: ['Premium', 'Standard', 'Ultra'] - vnet_resource_group_for_subnet: - description: - - Only required if virtual_network to be used is of different resource_group. - - Name of the resource group for virtual_network and subnet_name to be used. - type: str - version_added: "20.5.0" - size: - description: - - Provisioned size of the volume (in GiB). - - Minimum size is 100 GiB. Upper limit is 100TiB - - default is 100GiB. - version_added: "20.5.0" - type: int - protocol_types: - description: - - Protocol types - NFSv3, NFSv4.1, CIFS (for SMB). - type: list - elements: str - version_added: 21.2.0 - state: - description: - - State C(present) will check that the volume exists with the requested configuration. - - State C(absent) will delete the volume. - default: present - choices: ['present', 'absent'] - type: str - feature_flags: - description: - - Enable or disable a new feature. - - This can be used to enable an experimental feature or disable a new feature that breaks backward compatibility. - - Supported keys and values are subject to change without notice. Unknown keys are ignored. - type: dict - version_added: 21.9.0 -notes: - - feature_flags is setting ignore_change_ownership_mode to true by default to bypass a 'change ownership mode' issue with azure-mgmt-netapp 4.0.0. -''' -EXAMPLES = ''' - -- name: Create Azure NetApp volume - netapp.azure.azure_rm_netapp_volume: - resource_group: myResourceGroup - account_name: tests-netapp - pool_name: tests-pool - name: tests-volume2 - location: eastus - file_path: tests-volume2 - virtual_network: myVirtualNetwork - vnet_resource_group_for_subnet: myVirtualNetworkResourceGroup - subnet_name: test - service_level: Ultra - size: 100 - -- name: Delete Azure NetApp volume - netapp.azure.azure_rm_netapp_volume: - state: absent - resource_group: myResourceGroup - account_name: tests-netapp - pool_name: tests-pool - name: tests-volume2 - -''' - -RETURN = ''' -mount_path: - description: Returns mount_path of the Volume - returned: always - type: str - -''' - -import traceback - -AZURE_OBJECT_CLASS = 'NetAppAccount' -HAS_AZURE_MGMT_NETAPP = False -IMPORT_ERRORS = [] -ONE_GIB = 1073741824 - -try: - from msrestazure.azure_exceptions import CloudError - from msrest.exceptions import ValidationError - from azure.core.exceptions import AzureError, ResourceNotFoundError -except ImportError as exc: - IMPORT_ERRORS.append(str(exc)) - -try: - from azure.mgmt.netapp.models import Volume, ExportPolicyRule, VolumePropertiesExportPolicy, VolumePatch - HAS_AZURE_MGMT_NETAPP = True -except ImportError as exc: - IMPORT_ERRORS.append(str(exc)) - -from ansible.module_utils.basic import to_native -from ansible_collections.netapp.azure.plugins.module_utils.azure_rm_netapp_common import AzureRMNetAppModuleBase -from ansible_collections.netapp.azure.plugins.module_utils.netapp_module import NetAppModule - - -class AzureRMNetAppVolume(AzureRMNetAppModuleBase): - ''' create or delete a volume ''' - - def __init__(self): - - self.module_arg_spec = dict( - resource_group=dict(type='str', required=True), - name=dict(type='str', required=True), - file_path=dict(type='str', required=False), - pool_name=dict(type='str', required=True), - account_name=dict(type='str', required=True), - location=dict(type='str', required=False), - state=dict(choices=['present', 'absent'], default='present', type='str'), - subnet_name=dict(type='str', required=False, aliases=['subnet_id']), - virtual_network=dict(type='str', required=False), - size=dict(type='int', required=False), - vnet_resource_group_for_subnet=dict(type='str', required=False), - service_level=dict(type='str', required=False, choices=['Premium', 'Standard', 'Ultra']), - protocol_types=dict(type='list', elements='str'), - feature_flags=dict(type='dict') - ) - self.na_helper = NetAppModule() - self.parameters = {} - - # import errors are handled in AzureRMModuleBase - super(AzureRMNetAppVolume, self).__init__(derived_arg_spec=self.module_arg_spec, - required_if=[('state', 'present', ['location', 'file_path', 'subnet_name', 'virtual_network']), - ], - supports_check_mode=True) - - @staticmethod - def dict_from_volume_object(volume_object): - - def replace_list_of_objects_with_list_of_dicts(adict, key): - if adict.get(key): - adict[key] = [vars(x) for x in adict[key]] - - current_dict = vars(volume_object) - attr = 'subnet_id' - if attr in current_dict: - current_dict['subnet_name'] = current_dict.pop(attr).split('/')[-1] - attr = 'mount_targets' - replace_list_of_objects_with_list_of_dicts(current_dict, attr) - attr = 'export_policy' - if current_dict.get(attr): - attr_dict = vars(current_dict[attr]) - replace_list_of_objects_with_list_of_dicts(attr_dict, 'rules') - current_dict[attr] = attr_dict - return current_dict - - def get_azure_netapp_volume(self): - """ - Returns volume object for an existing volume - Return None if volume does not exist - """ - try: - volume_get = self.netapp_client.volumes.get(self.parameters['resource_group'], self.parameters['account_name'], - self.parameters['pool_name'], self.parameters['name']) - except (CloudError, ResourceNotFoundError): # volume does not exist - return None - return self.dict_from_volume_object(volume_get) - - def get_export_policy_rules(self): - # ExportPolicyRule(rule_index: int=None, unix_read_only: bool=None, unix_read_write: bool=None, - # kerberos5_read_only: bool=False, kerberos5_read_write: bool=False, kerberos5i_read_only: bool=False, - # kerberos5i_read_write: bool=False, kerberos5p_read_only: bool=False, kerberos5p_read_write: bool=False, - # cifs: bool=None, nfsv3: bool=None, nfsv41: bool=None, allowed_clients: str=None, has_root_access: bool=True - ptypes = self.parameters.get('protocol_types') - if ptypes is None: - return None - ptypes = [x.lower() for x in ptypes] - if 'nfsv4.1' in ptypes: - ptypes.append('nfsv41') - # only create a policy when NFSv4 is used (for now) - if 'nfsv41' not in ptypes: - return None - options = dict( - rule_index=1, - allowed_clients='0.0.0.0/0', - unix_read_write=True) - if self.has_feature('ignore_change_ownership_mode') and self.sdk_version >= '4.0.0': - # https://github.com/Azure/azure-sdk-for-python/issues/20356 - options['chown_mode'] = None - for protocol in ('cifs', 'nfsv3', 'nfsv41'): - options[protocol] = protocol in ptypes - return VolumePropertiesExportPolicy(rules=[ExportPolicyRule(**options)]) - - def create_azure_netapp_volume(self): - """ - Create a volume for the given Azure NetApp Account - :return: None - """ - options = self.na_helper.get_not_none_values_from_dict(self.parameters, ['protocol_types', 'service_level', 'tags', 'usage_threshold']) - rules = self.get_export_policy_rules() - if rules is not None: - # TODO: other options to expose ? - # options['throughput_mibps'] = 1.6 - # options['encryption_key_source'] = 'Microsoft.NetApp' - # options['security_style'] = 'Unix' - # options['unix_permissions'] = '0770' - # required for NFSv4 - options['export_policy'] = rules - subnet_id = '/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Network/virtualNetworks/%s/subnets/%s'\ - % (self.azure_auth.subscription_id, - self.parameters['resource_group'] if self.parameters.get('vnet_resource_group_for_subnet') is None - else self.parameters['vnet_resource_group_for_subnet'], - self.parameters['virtual_network'], - self.parameters['subnet_name']) - volume_body = Volume( - location=self.parameters['location'], - creation_token=self.parameters['file_path'], - subnet_id=subnet_id, - **options - ) - try: - result = self.get_method('volumes', 'create_or_update')(body=volume_body, resource_group_name=self.parameters['resource_group'], - account_name=self.parameters['account_name'], - pool_name=self.parameters['pool_name'], volume_name=self.parameters['name']) - # waiting till the status turns Succeeded - while result.done() is not True: - result.result(10) - except (CloudError, ValidationError, AzureError) as error: - self.module.fail_json(msg='Error creating volume %s for Azure NetApp account %s and subnet ID %s: %s' - % (self.parameters['name'], self.parameters['account_name'], subnet_id, to_native(error)), - exception=traceback.format_exc()) - - def modify_azure_netapp_volume(self): - """ - Modify a volume for the given Azure NetApp Account - :return: None - """ - options = self.na_helper.get_not_none_values_from_dict(self.parameters, ['tags', 'usage_threshold']) - volume_body = VolumePatch( - **options - ) - try: - result = self.get_method('volumes', 'update')(body=volume_body, resource_group_name=self.parameters['resource_group'], - account_name=self.parameters['account_name'], - pool_name=self.parameters['pool_name'], volume_name=self.parameters['name']) - # waiting till the status turns Succeeded - while result.done() is not True: - result.result(10) - except (CloudError, ValidationError, AzureError) as error: - self.module.fail_json(msg='Error modifying volume %s for Azure NetApp account %s: %s' - % (self.parameters['name'], self.parameters['account_name'], to_native(error)), - exception=traceback.format_exc()) - - def delete_azure_netapp_volume(self): - """ - Delete a volume for the given Azure NetApp Account - :return: None - """ - try: - result = self.get_method('volumes', 'delete')(resource_group_name=self.parameters['resource_group'], - account_name=self.parameters['account_name'], - pool_name=self.parameters['pool_name'], volume_name=self.parameters['name']) - # waiting till the status turns Succeeded - while result.done() is not True: - result.result(10) - except (CloudError, AzureError) as error: - self.module.fail_json(msg='Error deleting volume %s for Azure NetApp account %s: %s' - % (self.parameters['name'], self.parameters['account_name'], to_native(error)), - exception=traceback.format_exc()) - - def validate_modify(self, modify, current): - disallowed = dict(modify) - disallowed.pop('tags', None) - disallowed.pop('usage_threshold', None) - if disallowed: - self.module.fail_json(msg="Error: the following properties cannot be modified: %s. Current: %s" % (repr(disallowed), repr(current))) - - def exec_module(self, **kwargs): - - # unlikely - self.fail_when_import_errors(IMPORT_ERRORS, HAS_AZURE_MGMT_NETAPP) - - # set up parameters according to our initial list - for key in list(self.module_arg_spec): - self.parameters[key] = kwargs[key] - # and common parameter - for key in ['tags']: - if key in kwargs: - self.parameters[key] = kwargs[key] - - # API is using 'usage_threshold' for 'size', and the unit is bytes - if self.parameters.get('size') is not None: - self.parameters['usage_threshold'] = ONE_GIB * self.parameters.pop('size') - - modify = None - current = self.get_azure_netapp_volume() - cd_action = self.na_helper.get_cd_action(current, self.parameters) - if cd_action is None and current: - # ignore change in name - name = current.pop('name', None) - modify = self.na_helper.get_modified_attributes(current, self.parameters) - if name is not None: - current['name'] = name - if 'tags' in modify: - dummy, modify['tags'] = self.update_tags(current.get('tags')) - self.validate_modify(modify, current) - - if self.na_helper.changed and not self.module.check_mode: - if cd_action == 'create': - self.create_azure_netapp_volume() - elif cd_action == 'delete': - self.delete_azure_netapp_volume() - elif modify: - self.modify_azure_netapp_volume() - - def get_mount_info(return_info): - if return_info is not None and return_info.get('mount_targets'): - return '%s:/%s' % (return_info['mount_targets'][0]['ip_address'], return_info['creation_token']) - return None - - mount_info = '' - if self.parameters['state'] == 'present': - return_info = self.get_azure_netapp_volume() - if return_info is None and not self.module.check_mode: - self.module.fail_json(msg='Error: volume %s was created successfully, but cannot be found.' % self.parameters['name']) - mount_info = get_mount_info(return_info) - if mount_info is None and not self.module.check_mode: - self.module.fail_json(msg='Error: volume %s was created successfully, but mount target(s) cannot be found - volume details: %s.' - % (self.parameters['name'], str(return_info))) - self.module.exit_json(changed=self.na_helper.changed, mount_path=mount_info, modify=modify) - - -def main(): - AzureRMNetAppVolume() - - -if __name__ == '__main__': - main() |