summaryrefslogtreecommitdiffstats
path: root/ansible_collections/netapp/azure/plugins
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-05 16:18:34 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-05 16:18:34 +0000
commit3667197efb7b18ec842efd504785965911f8ac4b (patch)
tree0b986a4bc6879d080b100666a97cdabbc9ca1f28 /ansible_collections/netapp/azure/plugins
parentAdding upstream version 9.5.1+dfsg. (diff)
downloadansible-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')
-rw-r--r--ansible_collections/netapp/azure/plugins/doc_fragments/azure.py129
-rw-r--r--ansible_collections/netapp/azure/plugins/doc_fragments/azure_tags.py31
-rw-r--r--ansible_collections/netapp/azure/plugins/doc_fragments/netapp.py43
-rw-r--r--ansible_collections/netapp/azure/plugins/module_utils/azure_rm_netapp_common.py163
-rw-r--r--ansible_collections/netapp/azure/plugins/module_utils/netapp_module.py271
-rw-r--r--ansible_collections/netapp/azure/plugins/modules/azure_rm_netapp_account.py404
-rw-r--r--ansible_collections/netapp/azure/plugins/modules/azure_rm_netapp_capacity_pool.py259
-rw-r--r--ansible_collections/netapp/azure/plugins/modules/azure_rm_netapp_snapshot.py226
-rw-r--r--ansible_collections/netapp/azure/plugins/modules/azure_rm_netapp_volume.py399
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()