From 523ee28670c6b02111317fa1807192db0f7a31ee Mon Sep 17 00:00:00 2001 From: Pavan-Mudunuri Date: Tue, 13 Dec 2022 16:17:56 +0530 Subject: [PATCH] Ansible modules for PowerStore release version 1.8.0 --- .github/CODEOWNERS | 16 +- CHANGELOG.rst | 148 ++ ChangeLog.md | 63 - README.md | 92 +- changelogs/.plugin-cache.yaml | 177 ++ changelogs/changelog.yaml | 171 ++ changelogs/config.yaml | 33 + docs/BRANCHING.md | 8 +- docs/CONTRIBUTING.md | 8 +- docs/INSTALLATION.md | 4 +- docs/ISSUE_TRIAGE.md | 24 +- docs/MAINTAINERS.md | 1 + docs/MAINTAINER_GUIDE.md | 4 +- docs/Product Guide.md | 1600 +++++------------ docs/Release Notes.md | 8 +- docs/SECURITY.md | 2 +- galaxy.yml | 9 +- meta/runtime.yml | 2 +- plugins/doc_fragments/powerstore.py | 2 +- plugins/module_utils/storage/dell/utils.py | 2 +- plugins/modules/certificate.py | 2 +- plugins/modules/cluster.py | 2 +- plugins/modules/dns.py | 2 +- plugins/modules/email.py | 10 +- plugins/modules/filesystem.py | 2 +- plugins/modules/filesystem_snapshot.py | 2 +- plugins/modules/host.py | 112 +- plugins/modules/hostgroup.py | 92 +- plugins/modules/info.py | 2 +- plugins/modules/job.py | 2 +- plugins/modules/ldap_account.py | 2 +- plugins/modules/ldap_domain.py | 2 +- plugins/modules/local_user.py | 2 +- plugins/modules/nasserver.py | 2 +- plugins/modules/network.py | 2 +- plugins/modules/nfs.py | 2 +- plugins/modules/ntp.py | 2 +- plugins/modules/protectionpolicy.py | 2 +- plugins/modules/quota.py | 2 +- plugins/modules/remote_support.py | 2 +- plugins/modules/remote_support_contact.py | 2 +- plugins/modules/remotesystem.py | 2 +- plugins/modules/replicationrule.py | 2 +- plugins/modules/replicationsession.py | 50 +- plugins/modules/role.py | 2 +- plugins/modules/security_config.py | 2 +- plugins/modules/smbshare.py | 2 +- plugins/modules/smtp_config.py | 2 +- plugins/modules/snapshot.py | 2 +- plugins/modules/snapshotrule.py | 2 +- plugins/modules/volume.py | 678 ++++++- plugins/modules/volumegroup.py | 5 +- .../module_utils/mock_api_exception.py | 4 +- .../plugins/module_utils/mock_host_api.py | 7 +- .../module_utils/mock_hostgroup_api.py | 5 +- .../mock_replicationsession_api.py | 78 +- .../plugins/module_utils/mock_volume_api.py | 108 ++ tests/unit/plugins/modules/test_host.py | 2 + tests/unit/plugins/modules/test_hostgroup.py | 3 +- .../modules/test_replicationsession.py | 42 + tests/unit/plugins/modules/test_volume.py | 285 +++ 61 files changed, 2391 insertions(+), 1516 deletions(-) create mode 100644 CHANGELOG.rst delete mode 100644 ChangeLog.md create mode 100644 changelogs/.plugin-cache.yaml create mode 100644 changelogs/changelog.yaml create mode 100644 changelogs/config.yaml diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 3884068..68c45e8 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -7,13 +7,13 @@ # be requested for review when someone opens a pull request. # order is alphabetical for easier maintenance. # -# Akash Shendge (shenda1) -# Arindam Datta (dattaarindam) -# Bhavneet Sharma(Bhavneet-Sharma) -# Prabhulinga Revur (prabhu-dell) -# Rajshree Khare (khareRajshree) -# Srinivas P Rao (srinivas-rao5) -# Trisha Datta(trisha-dell) +# Ananthu Kuttattu (ananthu-kuttattu) +# Bhavneet Sharma (Bhavneet-Sharma) +# Jennifer John (Jennifer-John) +# Meenakshi Dembi (meenakshidembi691) +# Pavan Mudunuri (Pavan-Mudunuri) +# Previnkumar G (Previnkumar-G) +# Trisha Datta (trisha-dell) # for all files: -* @shenda1 @dattaarindam @Bhavneet-Sharma @prabhu-dell @khareRajshree @srinivas-rao5 @trisha-dell +* @kuttattz @Bhavneet-Sharma @Jennifer-John @meenakshidembi691 @Pavan-Mudunuri @Previnkumar-G @trisha-dell diff --git a/CHANGELOG.rst b/CHANGELOG.rst new file mode 100644 index 0000000..a299b45 --- /dev/null +++ b/CHANGELOG.rst @@ -0,0 +1,148 @@ +================================ +Dellemc.Powerstore Change Logs +================================ + +.. contents:: Topics + + +v1.8.0 +====== + +Minor Changes +------------- + +- Added support for PowerStore version 3.2.0.0. +- Added support for host connectivity option to host and host group. +- Added support to clone, refresh and restore a volume. +- Added support to configure/remove the metro relationship for volume. +- Added support to modify the role of replication sessions. +- Updated modules to adhere with ansible community guidelines. + +v1.7.0 +====== + +Minor Changes +------------- + +- Added support for cluster creation and validating cluster creation attributes. +- Added support to associate/disassociate protection policy to/from a NAS server. +- Added support to clone, refresh and restore a volume group. +- Added support to handle filesystem and NAS server replication sessions. + +v1.6.0 +====== + +Minor Changes +------------- + +- Added execution environment manifest file to support building an execution environment with ansible-builder. +- Enabled the check_mode support for info module. +- Info module is enhanced to list ldap domain, ldap accounts. + +New Modules +----------- + +- dellemc.powerstore.ldap_account - Manage LDAP account on Dell PowerStore +- dellemc.powerstore.ldap_domain - Manage LDAP domain on Dell PowerStore + +v1.5.0 +====== + +Minor Changes +------------- + +- Info module is enhanced to list dns servers, email notification destinations, NTP servers, remote support configuration, remote support contacts and SMTP configuration. +- Remote support module is added to get the details, modify the attributes, verify the connection and send a test alert. + +New Modules +----------- + +- dellemc.powerstore.dns - Manage DNS on Dell PowerStore +- dellemc.powerstore.email - Manage email on Dell PowerStore +- dellemc.powerstore.ntp - Manage NTP on Dell PowerStore +- dellemc.powerstore.remote_support - Manage Remote support on Dell PowerStore +- dellemc.powerstore.remote_support_contact - Manage Remote support contact on Dell PowerStore +- dellemc.powerstore.smtp_config - Manage SMTP config on Dell PowerStore + +v1.4.0 +====== + +Minor Changes +------------- + +- Host module is enhanced to provide support for NVMe initiators. +- Info module is enhanced to list certificates, AD/LDAP providers and security configuration. +- Names of previously released modules have been changed from dellemc_powerstore_\ to \. + +New Modules +----------- + +- dellemc.powerstore.certificate - Manage Certificates on Dell PowerStore +- dellemc.powerstore.remotesystem - Manage Remote system on Dell PowerStore +- dellemc.powerstore.security_config - Manage Security config on Dell PowerStore + +v1.3.0 +====== + +Minor Changes +------------- + +- Added dual licensing. +- Gather facts module is enhanced to list users, roles, networks and appliances. + +New Modules +----------- + +- dellemc.powerstore.cluster - Manage Cluster on Dell PowerStore +- dellemc.powerstore.job - Manage Job on Dell PowerStore +- dellemc.powerstore.local_user - Manage local user on Dell PowerStore +- dellemc.powerstore.network - Manage Network operations on Dell PowerStore +- dellemc.powerstore.role - Manage Roles on Dell PowerStore + +v1.2.0 +====== + +Minor Changes +------------- + +- Gather facts module is enhanced to list remote systems, replication rules and replication sessions. +- Protection policy module is enhanced to add/remove replication rule to/from protection policy. + +New Modules +----------- + +- dellemc.powerstore.replicationrule - Manage Replication Rules on Dell PowerStore +- dellemc.powerstore.replicationsession - Manage Replication Session on Dell PowerStore + +v1.1.0 +====== + +Minor Changes +------------- + +- Gather facts module is enhanced to list filesystems, NAS servers, NFS exports, SMB shares, tree quotas, user quotas. + +New Modules +----------- + +- dellemc.powerstore.filesystem - Manage File System on Dell PowerStore +- dellemc.powerstore.filesystem_snapshot - Manage Filesystem Snapshot on Dell PowerStore +- dellemc.powerstore.nasserver - Manage NAS server on Dell PowerStore +- dellemc.powerstore.nfs - Manage NFS Export on Dell PowerStore +- dellemc.powerstore.quota - Manage Quota on Dell PowerStore +- dellemc.powerstore.smbshare - Manage SMB Share on Dell PowerStore +- dellemc.powerstore.snapshot - Manage Snapshot on Dell PowerStore + +v1.0.0 +====== + +New Modules +----------- + +- dellemc.powerstore.host - Managing Dell PowerStore host +- dellemc.powerstore.hostgroup - Manage host group on Dell PowerStore +- dellemc.powerstore.info - Gathering information about Dell PowerStore +- dellemc.powerstore.protectionpolicy - Manage Protection policies on Dell PowerStore +- dellemc.powerstore.snapshotrule - Manage Snapshot Rule on Dell PowerStore +- dellemc.powerstore.volume - Manage volumes on Dell PowerStore +- dellemc.powerstore.volumegroup - Manage volume group on Dell PowerStore diff --git a/ChangeLog.md b/ChangeLog.md deleted file mode 100644 index bf63292..0000000 --- a/ChangeLog.md +++ /dev/null @@ -1,63 +0,0 @@ -# ansible-powerstore Change Log -## Version 1.7.0 - released on 27/09/2022 -- Added support for cluster creation and validating cluster creation attributes. -- Added support to associate/disassociate protection policy to/from a NAS server. -- Added support to handle filesystem and NAS server replication sessions. -- Added support to clone, refresh and restore a volume group. - -## Version 1.6.0 - released on 28/06/2022 -- Added CRUD operations for LDAP domain and LDAP account. -- Added execution environment manifest file to support building an execution environment with ansible-builder. -- Info module is enhanced to list ldap domain, ldap accounts. -- Enabled the check_mode support for info module. - -## Version 1.5.0 - released on 25/03/2022 -- Added CRUD operations and sending test email for email module. -- DNS module is added to get the details and add/remove addresses. -- NTP module is added to get the details and add/remove addresses. -- Remote support module is added to get the details, modify the attributes, verify the connection and send a test alert. -- Remote support contact module is added to get the details and modify the attributes. -- SMTP config module is added to get the details, modify the attributes and send a test email. -- Info module is enhanced to list dns servers, email notification destinations, NTP servers, remote support configuration, remote support contacts and SMTP configuration. - -## Version 1.4.0 - released on 16/12/2021 -- Added CRUD operations for remote system. -- Certificate module is added to get the details, add/import a certificate, exchange certificate, reset certificates and modify attributes of network. -- Security config module is added to get the details and modify attributes of a security configuration. -- Host module is enhanced to provide support for NVMe initiators. -- Info module is enhanced to list certificates, AD/LDAP providers and security configuration. -- Names of previously released modules have been changed from dellemc_powerstore_\ to \. - -## Version 1.3.0 - released on 28/09/2021 -- Added dual licensing. -- Added CRUD operations for local user. -- Network module is added to get the details and modify attributes of network. -- Cluster module is added to get the details and modify attributes of cluster. -- Job module is added to get the details of given job ID. -- Role module is added to get the details of given role name or role ID. -- Gather facts module is enhanced to list users, roles, networks and appliances. - -## Version 1.2.0 - released on 25/06/2021 -- Added CRUD operations for replication rule. -- Replication session module is added to get the details and modify state of replication session. -- Protection policy module is enhanced to add/remove replication rule to/from protection policy. -- Gather facts module is enhanced to list remote systems, replication rules and replication sessions. - -## Version 1.1.0 - released on 25/09/2020 -- Added CRUD operations for filesystem. -- Added CRUD operations for NFS export. -- Added CRUD operations for SMB share. -- Added CRUD operations for quota. -- Added CRUD operations for filesystem snapshot. -- NAS server module is added to get and modify NAS server attributes. -- Gather facts module is enhanced to list filesystems, NAS servers, NFS exports, SMB shares, tree quotas, user quotas. - -## Version 1.0.0 - released on 06/05/2020 -- Added CRUD operations for volume. -- Added CRUD operations for volume group. -- Added CRUD operations for host. -- Added CRUD operations for host group. -- Added CRUD operations for volume and volume group snapshot. -- Added CRUD operations for snapshot rule. -- Added CRUD operations for protection policy. -- Gather facts module is added to list nodes, volumes, volume groups, hosts, host groups, snapshot rules, protection policies. diff --git a/README.md b/README.md index db3ed2f..b7bafee 100644 --- a/README.md +++ b/README.md @@ -4,29 +4,29 @@ The Ansible Modules for Dell Technologies (Dell) PowerStore allow Data Center an The capabilities of the Ansible modules are managing volumes, volume groups, hosts, host groups, snapshots, snapshot rules, replication rules, replication sessions, protection policies, file systems, NAS servers, SMB shares, user and tree quotas, file system snapshots, NFS exports, Clusters, Networks, Local users, Jobs, Roles, Certificates, Remote systems, security configuration, DNS server, Email notification destination, NTP server, Remote support configuration, Remote support contacts, SMTP configuration, LDAP accounts and LDAP domain configuration. It also allows gathering high level info from the array. The options available for each are list, show, create, modify and delete. These tasks can be executed by running simple playbooks written in yaml syntax. The modules are written so that all the operations are idempotent, so making multiple identical requests has the same effect as making a single request. ## Table of contents -* [Code of conduct](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/CODE_OF_CONDUCT.md) -* [Maintainer guide](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/MAINTAINER_GUIDE.md) -* [Committer guide](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/COMMITTER_GUIDE.md) -* [Contributing guide](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/CONTRIBUTING.md) -* [Branching strategy](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/BRANCHING.md) -* [List of adopters](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/ADOPTERS.md) -* [Maintainers](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/MAINTAINERS.md) -* [Support](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/SUPPORT.md) +* [Code of conduct](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/CODE_OF_CONDUCT.md) +* [Maintainer guide](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/MAINTAINER_GUIDE.md) +* [Committer guide](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/COMMITTER_GUIDE.md) +* [Contributing guide](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/CONTRIBUTING.md) +* [Branching strategy](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/BRANCHING.md) +* [List of adopters](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/ADOPTERS.md) +* [Maintainers](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/MAINTAINERS.md) +* [Support](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/SUPPORT.md) * [License](#license) -* [Security](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/SECURITY.md) +* [Security](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/SECURITY.md) * [Prerequisites](#prerequisites) * [List of Ansible modules for Dell PowerStore](#list-of-ansible-modules-for-dell-powerstore) * [Installation and execution of Ansible modules for Dell PowerStore](#installation-and-execution-of-ansible-modules-for-dell-powerstore) * [Maintenance](#maintenance) ## License -The Ansible collection for PowerStore is released and licensed under the GPL-3.0 license. See [LICENSE](https://github.com/dell/ansible-powerstore/blob/1.7.0/LICENSE) for the full terms. Ansible modules and modules utilities that are part of the Ansible collection for PowerStore are released and licensed under the Apache 2.0 license. See [MODULE-LICENSE](https://github.com/dell/ansible-powerstore/blob/1.7.0/MODULE-LICENSE) for the full terms. +The Ansible collection for PowerStore is released and licensed under the GPL-3.0 license. See [LICENSE](https://github.com/dell/ansible-powerstore/blob/1.8.0/LICENSE) for the full terms. Ansible modules and modules utilities that are part of the Ansible collection for PowerStore are released and licensed under the Apache 2.0 license. See [MODULE-LICENSE](https://github.com/dell/ansible-powerstore/blob/1.8.0/MODULE-LICENSE) for the full terms. ## Prerequisites - | **Ansible Modules** | **PowerStore Version** | **Red Hat Enterprise Linux**| **SDK version** | **Python version** | **Ansible** | -|---------------------|-----------------------|------------------------------|-----------------|--------------------|--------------------------| -| v1.7.0 | 2.0.x
2.1.x
3.0.x |7.9
8.4
8.5| 1.8.0 | 3.8.x
3.9.x
3.10.x | 2.11
2.12
2.13 | + | **Ansible Modules** | **PowerStore Version** | **SDK version** | **Python version** | **Ansible** | +|---------------------|-----------------------|-----------------|--------------------|--------------------------| +| v1.8.0 | 2.1.x
3.0.x
3.2.x | 1.9.0 | 3.9.x
3.10.x
3.11.x | 2.12
2.13
2.14 | * Please follow PyPowerStore installation instructions on [PyPowerStore Documentation](https://github.com/dell/python-powerstore) @@ -35,41 +35,41 @@ The Ansible collection for PowerStore is released and licensed under the GPL-3.0 The modules are written in such a way that all requests are idempotent and hence fault-tolerant. It essentially means that the result of a successfully performed request is independent of the number of times it is executed. ## List of Ansible Modules for Dell PowerStore -* [Volume module](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/Product%20Guide.md#volume-module) -* [Volume group module](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/Product%20Guide.md#volume-group-module) -* [Host module](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/Product%20Guide.md#host-module) -* [Host group module](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/Product%20Guide.md#host-group-module) -* [Snapshot module](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/Product%20Guide.md#snapshot-module) -* [Snapshot rule module](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/Product%20Guide.md#snapshot-rule-module) -* [Replication rule module](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/Product%20Guide.md#replication-rule-module) -* [Replication session module](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/Product%20Guide.md#replication-session-module) -* [Protection policy module](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/Product%20Guide.md#protection-policy-module) -* [Info module](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/Product%20Guide.md#info-module) -* [File system module](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/Product%20Guide.md#file-system-module) -* [NAS server module](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/Product%20Guide.md#nas-server-module) -* [SMB share module](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/Product%20Guide.md#smb-share-module) -* [Quota module](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/Product%20Guide.md#quota-module) -* [File system snapshot module](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/Product%20Guide.md#filesystem-snapshot-module) -* [NFS export module](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/Product%20Guide.md#nfs-export-module) -* [Cluster module](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/Product%20Guide.md#cluster-module) -* [Network module](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/Product%20Guide.md#network-module) -* [Local user module](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/Product%20Guide.md#local-user-module) -* [Role module](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/Product%20Guide.md#role-module) -* [Job module](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/Product%20Guide.md#job-module) -* [Certificate module](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/Product%20Guide.md#certificate-module) -* [Remote system module](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/Product%20Guide.md#remote-system-module) -* [Security config module](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/Product%20Guide.md#security-config-module) -* [DNS module](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/Product%20Guide.md#dns-module) -* [Email module](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/Product%20Guide.md#email-module) -* [NTP module](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/Product%20Guide.md#ntp-module) -* [Remote support module](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/Product%20Guide.md#remote-support-module) -* [Remote support contact module](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/Product%20Guide.md#remote-support-contact-module) -* [SMTP config module](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/Product%20Guide.md#smtp-config-module) -* [LDAP Account module](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/Product%20Guide.md#ldap-account-module) -* [LDAP Domain module](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/Product%20Guide.md#ldap-domain-module) +* [Volume module](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/Product%20Guide.md#volume-module) +* [Volume group module](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/Product%20Guide.md#volume-group-module) +* [Host module](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/Product%20Guide.md#host-module) +* [Host group module](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/Product%20Guide.md#host-group-module) +* [Snapshot module](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/Product%20Guide.md#snapshot-module) +* [Snapshot rule module](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/Product%20Guide.md#snapshot-rule-module) +* [Replication rule module](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/Product%20Guide.md#replication-rule-module) +* [Replication session module](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/Product%20Guide.md#replication-session-module) +* [Protection policy module](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/Product%20Guide.md#protection-policy-module) +* [Info module](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/Product%20Guide.md#info-module) +* [File system module](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/Product%20Guide.md#file-system-module) +* [NAS server module](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/Product%20Guide.md#nas-server-module) +* [SMB share module](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/Product%20Guide.md#smb-share-module) +* [Quota module](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/Product%20Guide.md#quota-module) +* [File system snapshot module](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/Product%20Guide.md#filesystem-snapshot-module) +* [NFS export module](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/Product%20Guide.md#nfs-export-module) +* [Cluster module](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/Product%20Guide.md#cluster-module) +* [Network module](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/Product%20Guide.md#network-module) +* [Local user module](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/Product%20Guide.md#local-user-module) +* [Role module](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/Product%20Guide.md#role-module) +* [Job module](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/Product%20Guide.md#job-module) +* [Certificate module](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/Product%20Guide.md#certificate-module) +* [Remote system module](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/Product%20Guide.md#remote-system-module) +* [Security config module](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/Product%20Guide.md#security-config-module) +* [DNS module](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/Product%20Guide.md#dns-module) +* [Email module](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/Product%20Guide.md#email-module) +* [NTP module](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/Product%20Guide.md#ntp-module) +* [Remote support module](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/Product%20Guide.md#remote-support-module) +* [Remote support contact module](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/Product%20Guide.md#remote-support-contact-module) +* [SMTP config module](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/Product%20Guide.md#smtp-config-module) +* [LDAP Account module](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/Product%20Guide.md#ldap-account-module) +* [LDAP Domain module](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/Product%20Guide.md#ldap-domain-module) ## Installation and execution of Ansible modules for Dell PowerStore -The installation and execution steps of Ansible modules for Dell PowerStore can be found [here](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/INSTALLATION.md) +The installation and execution steps of Ansible modules for Dell PowerStore can be found [here](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/INSTALLATION.md) ## Maintenance Ansible Modules for Dell Technologies PowerStore deprecation cycle is aligned with [Ansible](https://docs.ansible.com/ansible/latest/dev_guide/module_lifecycle.html). \ No newline at end of file diff --git a/changelogs/.plugin-cache.yaml b/changelogs/.plugin-cache.yaml new file mode 100644 index 0000000..a8b8f46 --- /dev/null +++ b/changelogs/.plugin-cache.yaml @@ -0,0 +1,177 @@ +objects: + role: {} +plugins: + become: {} + cache: {} + callback: {} + cliconf: {} + connection: {} + httpapi: {} + inventory: {} + lookup: {} + module: + certificate: + description: Certificate operations for PowerStore Storage System + name: certificate + namespace: '' + version_added: 1.4.0 + cluster: + description: Manage cluster related operations on PowerStore + name: cluster + namespace: '' + version_added: 1.3.0 + dns: + description: DNS operations on a PowerStore storage system + name: dns + namespace: '' + version_added: 1.5.0 + email: + description: Destination Email operations on a PowerStore storage system + name: email + namespace: '' + version_added: 1.5.0 + filesystem: + description: Filesystem operations for PowerStore Storage system + name: filesystem + namespace: '' + version_added: 1.1.0 + filesystem_snapshot: + description: Manage Filesystem Snapshots for PowerStore + name: filesystem_snapshot + namespace: '' + version_added: 1.1.0 + host: + description: Manage host on PowerStore storage system + name: host + namespace: '' + version_added: 1.0.0 + hostgroup: + description: Manage host group on PowerStore Storage System + name: hostgroup + namespace: '' + version_added: 1.0.0 + info: + description: Gathers information about PowerStore Storage entities + name: info + namespace: '' + version_added: 1.0.0 + job: + description: Manage jobs for PowerStore + name: job + namespace: '' + version_added: 1.3.0 + ldap_account: + description: Manage LDAP Account for PowerStore + name: ldap_account + namespace: '' + version_added: 1.6.0 + ldap_domain: + description: Manage LDAP domain for PowerStore + name: ldap_domain + namespace: '' + version_added: 1.6.0 + local_user: + description: Local user operations for PowerStore Storage System + name: local_user + namespace: '' + version_added: 1.3.0 + nasserver: + description: NAS Server operations for PowerStore Storage system + name: nasserver + namespace: '' + version_added: 1.1.0 + network: + description: Manage networks for PowerStore + name: network + namespace: '' + version_added: 1.3.0 + nfs: + description: Manage NFS exports for PowerStore + name: nfs + namespace: '' + version_added: 1.1.0 + ntp: + description: NTP operations on a PowerStore storage system + name: ntp + namespace: '' + version_added: 1.5.0 + protectionpolicy: + description: Perform Protection policy operations for PowerStore storage system + name: protectionpolicy + namespace: '' + version_added: 1.0.0 + quota: + description: Manage Tree Quotas and User Quotas on PowerStore + name: quota + namespace: '' + version_added: 1.1.0 + remote_support: + description: Remote Support operations on a PowerStore storage system + name: remote_support + namespace: '' + version_added: 1.5.0 + remote_support_contact: + description: Remote Support Contact operations on a PowerStore storage system + name: remote_support_contact + namespace: '' + version_added: 1.5.0 + remotesystem: + description: Remote system operations on a PowerStore storage system + name: remotesystem + namespace: '' + version_added: 1.4.0 + replicationrule: + description: Replication rule operations on a PowerStore storage system + name: replicationrule + namespace: '' + version_added: 1.2.0 + replicationsession: + description: Replication session operations on a PowerStore storage system + name: replicationsession + namespace: '' + version_added: 1.2.0 + role: + description: Get details of the roles present on the PowerStore storage system + name: role + namespace: '' + version_added: 1.3.0 + security_config: + description: Security configuration operations for PowerStore Storage System + name: security_config + namespace: '' + version_added: 1.4.0 + smbshare: + description: Manage SMB shares on a PowerStore storage system + name: smbshare + namespace: '' + version_added: 1.1.0 + smtp_config: + description: SMTP configuration operations on a PowerStore storage system + name: smtp_config + namespace: '' + version_added: 1.5.0 + snapshot: + description: Manage Snapshots for PowerStore + name: snapshot + namespace: '' + version_added: 1.0.0 + snapshotrule: + description: Snapshot Rule operations on a PowerStore storage system + name: snapshotrule + namespace: '' + version_added: 1.0.0 + volume: + description: Manage volumes on a PowerStore storage system + name: volume + namespace: '' + version_added: 1.0.0 + volumegroup: + description: Manage volume groups on a PowerStore Storage System + name: volumegroup + namespace: '' + version_added: 1.0.0 + netconf: {} + shell: {} + strategy: {} + vars: {} +version: 1.8.0 diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml new file mode 100644 index 0000000..d051755 --- /dev/null +++ b/changelogs/changelog.yaml @@ -0,0 +1,171 @@ +ancestor: null +releases: + 1.0.0: + modules: + - description: Managing Dell PowerStore host + name: host + namespace: '' + - description: Manage host group on Dell PowerStore + name: hostgroup + namespace: '' + - description: Gathering information about Dell PowerStore + name: info + namespace: '' + - description: Manage Protection policies on Dell PowerStore + name: protectionpolicy + namespace: '' + - description: Manage Snapshot Rule on Dell PowerStore + name: snapshotrule + namespace: '' + - description: Manage volumes on Dell PowerStore + name: volume + namespace: '' + - description: Manage volume group on Dell PowerStore + name: volumegroup + namespace: '' + release_date: '2020-05-06' + 1.1.0: + changes: + minor_changes: + - Gather facts module is enhanced to list filesystems, NAS servers, NFS exports, + SMB shares, tree quotas, user quotas. + modules: + - description: Manage File System on Dell PowerStore + name: filesystem + namespace: '' + - description: Manage Filesystem Snapshot on Dell PowerStore + name: filesystem_snapshot + namespace: '' + - description: Manage NAS server on Dell PowerStore + name: nasserver + namespace: '' + - description: Manage NFS Export on Dell PowerStore + name: nfs + namespace: '' + - description: Manage Quota on Dell PowerStore + name: quota + namespace: '' + - description: Manage SMB Share on Dell PowerStore + name: smbshare + namespace: '' + - description: Manage Snapshot on Dell PowerStore + name: snapshot + namespace: '' + release_date: '2020-09-25' + 1.2.0: + changes: + minor_changes: + - Gather facts module is enhanced to list remote systems, replication rules + and replication sessions. + - Protection policy module is enhanced to add/remove replication rule to/from + protection policy. + modules: + - description: Manage Replication Rules on Dell PowerStore + name: replicationrule + namespace: '' + - description: Manage Replication Session on Dell PowerStore + name: replicationsession + namespace: '' + release_date: '2021-06-25' + 1.3.0: + changes: + minor_changes: + - Added dual licensing. + - Gather facts module is enhanced to list users, roles, networks and appliances. + modules: + - description: Manage Cluster on Dell PowerStore + name: cluster + namespace: '' + - description: Manage Job on Dell PowerStore + name: job + namespace: '' + - description: Manage local user on Dell PowerStore + name: local_user + namespace: '' + - description: Manage Network operations on Dell PowerStore + name: network + namespace: '' + - description: Manage Roles on Dell PowerStore + name: role + namespace: '' + release_date: '2021-09-28' + 1.4.0: + changes: + minor_changes: + - Host module is enhanced to provide support for NVMe initiators. + - Info module is enhanced to list certificates, AD/LDAP providers and security + configuration. + - Names of previously released modules have been changed from dellemc_powerstore_\ to \. + modules: + - description: Manage Certificates on Dell PowerStore + name: certificate + namespace: '' + - description: Manage Remote system on Dell PowerStore + name: remotesystem + namespace: '' + - description: Manage Security config on Dell PowerStore + name: security_config + namespace: '' + release_date: '2021-12-16' + 1.5.0: + changes: + minor_changes: + - Info module is enhanced to list dns servers, email notification destinations, + NTP servers, remote support configuration, remote support contacts and SMTP + configuration. + - Remote support module is added to get the details, modify the attributes, + verify the connection and send a test alert. + modules: + - description: Manage DNS on Dell PowerStore + name: dns + namespace: '' + - description: Manage email on Dell PowerStore + name: email + namespace: '' + - description: Manage NTP on Dell PowerStore + name: ntp + namespace: '' + - description: Manage Remote support on Dell PowerStore + name: remote_support + namespace: '' + - description: Manage Remote support contact on Dell PowerStore + name: remote_support_contact + namespace: '' + - description: Manage SMTP config on Dell PowerStore + name: smtp_config + namespace: '' + release_date: '2021-03-25' + 1.6.0: + changes: + minor_changes: + - Added execution environment manifest file to support building an execution + environment with ansible-builder. + - Enabled the check_mode support for info module. + - Info module is enhanced to list ldap domain, ldap accounts. + modules: + - description: Manage LDAP account on Dell PowerStore + name: ldap_account + namespace: '' + - description: Manage LDAP domain on Dell PowerStore + name: ldap_domain + namespace: '' + release_date: '2022-06-28' + 1.7.0: + changes: + minor_changes: + - Added support for cluster creation and validating cluster creation attributes. + - Added support to associate/disassociate protection policy to/from a NAS server. + - Added support to clone, refresh and restore a volume group. + - Added support to handle filesystem and NAS server replication sessions. + release_date: '2022-09-27' + 1.8.0: + changes: + minor_changes: + - Added support for PowerStore version 3.2.0.0. + - Added support for host connectivity option to host and host group. + - Added support to clone, refresh and restore a volume. + - Added support to configure/remove the metro relationship for volume. + - Added support to modify the role of replication sessions. + - Updated modules to adhere with ansible community guidelines. + release_date: '2022-12-21' diff --git a/changelogs/config.yaml b/changelogs/config.yaml new file mode 100644 index 0000000..b8d29ad --- /dev/null +++ b/changelogs/config.yaml @@ -0,0 +1,33 @@ +--- +changelog_filename_template: ../CHANGELOG.rst +changelog_filename_version_depth: 0 +changes_file: changelog.yaml +changes_format: combined +ignore_other_fragment_extensions: true +keep_fragments: false +mention_ancestor: true +new_plugins_after_name: removed_features +notesdir: fragments +prelude_section_name: release_summary +prelude_section_title: Release Summary +sanitize_changelog: true +sections: + - - major_changes + - Major Changes + - - minor_changes + - Minor Changes + - - breaking_changes + - Breaking Changes / Porting Guide + - - deprecated_features + - Deprecated Features + - - removed_features + - Removed Features (previously deprecated) + - - security_fixes + - Security Fixes + - - bugfixes + - Bugfixes + - - known_issues + - Known Issues +title: Dellemc.Powerstore +trivial_section_name: trivial +use_fqcn: true diff --git a/docs/BRANCHING.md b/docs/BRANCHING.md index a2c1b79..acf63a2 100644 --- a/docs/BRANCHING.md +++ b/docs/BRANCHING.md @@ -16,7 +16,7 @@ Ansible modules for Dell PowerStore follows a scaled trunk branching strategy wh | Branch Type | Example | Comment | |--------------|-----------------------------------|-------------------------------------------| -| master | master | | +| main | main | | | Release | release-1.0 | hotfix: release-1.1 patch: release-1.0.1 | | Feature | feature-9-vol-support | "9" referring to GitHub issue ID | | Bug Fix | bugfix-110-fix-duplicates-issue | "110" referring to GitHub issue ID | @@ -25,8 +25,8 @@ Ansible modules for Dell PowerStore follows a scaled trunk branching strategy wh ## Steps for working on a release branch 1. Fork the repository. -2. Create a branch off of the master branch. The branch name should follow [branch naming convention](#branch-naming-convention). +2. Create a branch off of the main branch. The branch name should follow [branch naming convention](#branch-naming-convention). 3. Make your changes and commit them to your branch. -4. If other code changes have merged into the upstream master branch, perform a rebase of those changes into your branch. -5. Open a [pull request](https://github.com/dell/ansible-powerstore/pulls) between your branch and the upstream master branch. +4. If other code changes have merged into the upstream main branch, perform a rebase of those changes into your branch. +5. Open a [pull request](https://github.com/dell/ansible-powerstore/pulls) between your branch and the upstream main branch. 6. Once your pull request has merged, your branch can be deleted. diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 9e7292d..a83458f 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -10,7 +10,7 @@ You may obtain a copy of the License at # How to contribute -Become one of the contributors to this project! We thrive to build a welcoming and open community for anyone who wants to use the project or contribute to it. There are just a few small guidelines you need to follow. To help us create a safe and positive community experience for all, we require all participants to adhere to the [Code of Conduct](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/CODE_OF_CONDUCT.md). +Become one of the contributors to this project! We thrive to build a welcoming and open community for anyone who wants to use the project or contribute to it. There are just a few small guidelines you need to follow. To help us create a safe and positive community experience for all, we require all participants to adhere to the [Code of Conduct](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/CODE_OF_CONDUCT.md). ## Table of contents @@ -76,7 +76,7 @@ Triage helps ensure that issues resolve quickly by: If you don't have the knowledge or time to code, consider helping with _issue triage_. The Ansible modules for Dell PowerStore community will thank you for saving them time by spending some of yours. -Read more about the ways you can [Triage issues](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/ISSUE_TRIAGE.md). +Read more about the ways you can [Triage issues](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/ISSUE_TRIAGE.md). ## Your first contribution @@ -89,7 +89,7 @@ When you're ready to contribute, it's time to create a pull request. ## Branching -* [Branching Strategy for Ansible modules for Dell PowerStore](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/BRANCHING.md) +* [Branching Strategy for Ansible modules for Dell PowerStore](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/BRANCHING.md) ## Signing your commits @@ -144,7 +144,7 @@ Make sure that the title for your pull request uses the same format as the subje ### Quality gates for pull requests -GitHub Actions are used to enforce quality gates when a pull request is created or when any commit is made to the pull request. These GitHub Actions enforce our minimum code quality requirement for any code that get checked into the repository. If any of the quality gates fail, it is expected that the contributor will look into the check log, understand the problem and resolve the issue. If help is needed, please feel free to reach out the maintainers of the project for [support](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/SUPPORT.md). +GitHub Actions are used to enforce quality gates when a pull request is created or when any commit is made to the pull request. These GitHub Actions enforce our minimum code quality requirement for any code that get checked into the repository. If any of the quality gates fail, it is expected that the contributor will look into the check log, understand the problem and resolve the issue. If help is needed, please feel free to reach out the maintainers of the project for [support](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/SUPPORT.md). #### Code sanitization diff --git a/docs/INSTALLATION.md b/docs/INSTALLATION.md index 4a04766..da027ff 100644 --- a/docs/INSTALLATION.md +++ b/docs/INSTALLATION.md @@ -41,7 +41,7 @@ You may obtain a copy of the License at * Download the latest tar build from any of the available distribution channel [Ansible Galaxy](https://galaxy.ansible.com/dellemc/powerstore) /[Automation Hub](https://console.redhat.com/ansible/automation-hub/repo/published/dellemc/powerstore) and use this command to install the collection anywhere in your system: - ansible-galaxy collection install dellemc-powerstore-1.7.0.tar.gz -p + ansible-galaxy collection install dellemc-powerstore-1.8.0.tar.gz -p * Set the environment variable: @@ -68,7 +68,7 @@ You may obtain a copy of the License at ## Ansible modules execution -The Ansible server must be configured with Python library for PowerStore to run the Ansible playbooks. The [Documents](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/) provide information on different Ansible modules along with their functions and syntax. The parameters table in the Product Guide provides information on various parameters which needs to be configured before running the modules. +The Ansible server must be configured with Python library for PowerStore to run the Ansible playbooks. The [Documents](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/) provide information on different Ansible modules along with their functions and syntax. The parameters table in the Product Guide provides information on various parameters which needs to be configured before running the modules. ## SSL certificate validation diff --git a/docs/ISSUE_TRIAGE.md b/docs/ISSUE_TRIAGE.md index e5d08a9..dcaf66a 100644 --- a/docs/ISSUE_TRIAGE.md +++ b/docs/ISSUE_TRIAGE.md @@ -41,10 +41,10 @@ This section describes the various issue templates and the expected content. Should explain what happened, what was expected and how to reproduce it together with any additional information that may help giving a complete picture of what happened such as screenshots, output and any environment related information that's applicable and/or maybe related to the reported problem: - - Ansible Version: [e.g. 2.13] - - Python Version [e.g. 3.10] - - Ansible modules for Dell PowerStore Version: [e.g. 1.7.0] - - PowerStore SDK version: [e.g. PyPowerStore 1.8.0] + - Ansible Version: [e.g. 2.14] + - Python Version [e.g. 3.11] + - Ansible modules for Dell PowerStore Version: [e.g. 1.8.0] + - PowerStore SDK version: [e.g. PyPowerStore 1.9.0] - Any other additional information... #### Feature requests @@ -118,7 +118,7 @@ If it's not perfectly clear that it's an actual bug, quickly try to reproduce it In general bugs and feature request issues should be labeled with a priority. -This is the most difficult thing with triaging issues since it requires a lot of knowledge, context and experience before being able to think of and start feel comfortable adding a certain priority label. +Adding priority levels can be difficult. Ensure you have the knowledge, context, and the experience before prioritizing any issues. If you have any uncertainty as to which priority level to assign, please ask the maintainers for help. The key here is asking for help and discuss issues to understand how more experienced project members think and reason. By doing that you learn more and eventually be more and more comfortable with prioritizing issues. @@ -126,13 +126,13 @@ In case there is an uncertainty around the prioritization of an issue, please as | Label | Description | | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | -| `priority/critical` | Highest priority. Must be actively worked on as someone's top priority right now. | +| `priority/critical` | Highest priority. Must be actively worked on as someone's top priority immediately. | | `priority/high` | Must be worked on soon, ideally in time for the next release. | | `priority/low` | Lowest priority. Possibly useful, but not yet enough interest in it. | ### Critical priority -1. If an issue has been categorized and any of this criteria apply, the issue should be labeled as critical and must be actively worked on as someone's top priority right now. +1. If an issue has been categorized and any of this criteria apply, the issue should be labeled as critical and must be actively worked on as someone's top priority immediately. - Results in any data loss - Critical security or performance issues @@ -141,7 +141,7 @@ In case there is an uncertainty around the prioritization of an issue, please as 2. Label the issue `priority/critical`. 3. Escalate the problem to the maintainers. -4. Assign or ask a maintainer for help assigning someone to make this issue their top priority right now. +4. Assign or ask a maintainer for help assigning someone to make this issue their top priority immediately. 5. Add the issue to the next upcoming release milestone. ### High priority @@ -154,7 +154,7 @@ In case there is an uncertainty around the prioritization of an issue, please as ### Low priority 1. If the issue is deemed possibly useful but a low priority label the issue `priority/low`. -2. The amount of interest in the issue will determine if the priority changes to be higher. +2. The amount of interest in the issue will determine if the priority elevated. 3. Consider requesting [help from the community](#5-requesting-help-from-the-community). ## 5. Requesting help from the community @@ -163,9 +163,9 @@ Depending on the issue and/or priority, it's always a good idea to consider sign In many cases the issue author or community as a whole is more suitable to contribute changes since they're experts in their domain. It's also quite common that someone has tried to get something to work using the documentation without success and made an effort to get it to work and/or reached out to the community to get the missing information. -1. Kindly and politely add a comment to signal to users subscribed to updates of the issue. - - Explain that the issue would be nice to get resolved, but it isn't prioritized to work on by maintainers for an unforeseen future. - - If possible or applicable, try to help contributors getting starting by adding pointers and references to what code/files need to be changed and/or ideas of a good way to solve/implement the issue. +1. Kindly and politely add a comment to alert update subscribers. + - Explain the issue and the need for resolution. Be sure and detail that the issue has not been prioritized and that the issue has not been scheduled for work by the maintainers. + - If possible or applicable, add pointers and references to the code/files that need to be revised. Provide any ideas as to the solution. This will help the maintainers get started on resolving the issue. 2. Label the issue with `help wanted`. 3. If applicable, label the issue with `beginner friendly` to denote that the issue is suitable for a beginner to work on. diff --git a/docs/MAINTAINERS.md b/docs/MAINTAINERS.md index 72fac72..201e1d9 100644 --- a/docs/MAINTAINERS.md +++ b/docs/MAINTAINERS.md @@ -15,3 +15,4 @@ You may obtain a copy of the License at * @jennifer-john * @pavan-mudunuri * @trisha-datta +* @Previnkumar_G \ No newline at end of file diff --git a/docs/MAINTAINER_GUIDE.md b/docs/MAINTAINER_GUIDE.md index 2846ae7..c75f83d 100644 --- a/docs/MAINTAINER_GUIDE.md +++ b/docs/MAINTAINER_GUIDE.md @@ -10,7 +10,7 @@ You may obtain a copy of the License at # Maintainer guidelines -As a Maintainer of this project you have the responsibility of keeping true to the vision of the project with unprecedented quality. Being part of this group is a privilege that requires dedication and time to attend to the daily activities that are associated with the maintenance of this project. +As a Maintainer of this project you have the responsibility of keeping true to the vision of the project with high-degree quality. Being part of this group is a privilege that requires dedication and time to attend to the daily activities that are associated with the maintenance of this project. ## Becoming a maintainer @@ -27,7 +27,7 @@ If a candidate is approved, a Maintainer contacts the candidate to invite them t ## Maintainer policies * Lead by example -* Follow the [Code of Conduct](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/CODE_OF_CONDUCT.md) and the guidelines in the [Contributing](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/CONTRIBUTING.md) and [Committer](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/COMMITTER_GUIDE.md) guides +* Follow the [Code of Conduct](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/CODE_OF_CONDUCT.md) and the guidelines in the [Contributing](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/CONTRIBUTING.md) and [Committer](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/COMMITTER_GUIDE.md) guides * Promote a friendly and collaborative environment within our community * Be actively engaged in discussions, answering questions, updating defects, and reviewing pull requests * Criticize code, not people. Ideally, tell the contributor a better way to do what they need. diff --git a/docs/Product Guide.md b/docs/Product Guide.md index 581d38b..daeca89 100644 --- a/docs/Product Guide.md +++ b/docs/Product Guide.md @@ -1,6 +1,6 @@ # Ansible Modules for Dell Technologies PowerStore -## Product Guide 1.7.0 -© 2022 Dell Inc. or its subsidiaries. All rights reserved. Dell, and other trademarks are trademarks of Dell Inc. or its subsidiaries. Other trademarks may be trademarks of their respective owners. +## Product Guide 1.8.0 +© 2022 Dell Inc. or its subsidiaries. All rights reserved. Dell and other trademarks are trademarks of Dell Inc. or its subsidiaries. Other trademarks may be trademarks of their respective owners. -------------- ## Contents @@ -393,7 +393,7 @@ Certificate operations for PowerStore Storage System * Reset operation can reset more than one certificate at a time. * Add/import, modify and reset are supported for PowerStore versions 2.0 and above only. * The check_mode is not supported. -* The modules present in this collection named as 'dellemc.powerstore' are built to support the Dell PowerStore storage platform. +* Refer module documentation for more sample playbooks. ### Examples ``` @@ -415,19 +415,6 @@ Certificate operations for PowerStore Storage System service: "VASA_HTTP" state: "present" -- name: Exchange certificates - dellemc.powerstore.certificate: - array_ip: "{{array_ip}}" - user: "{{user}}" - password: "{{password}}" - verifycert: "{{verifycert}}" - service: "Replication_HTTP" - remote_address: "{{remote_array_ip}}" - remote_port: 443 - remote_user: "{{remote_user}}" - remote_password: "{{remote_password}}" - state: "present" - - name: Add/import a certificate dellemc.powerstore.certificate: array_ip: "{{array_ip}}" @@ -439,16 +426,6 @@ Certificate operations for PowerStore Storage System certificate: "{{certificate_string}}" is_current: True state: "present" - -- name: Modify certificate - dellemc.powerstore.certificate: - array_ip: "{{array_ip}}" - user: "{{user}}" - password: "{{password}}" - verifycert: "{{verifycert}}" - certificate_id: "37b76535-612b-456a-a694-1389f17632c7" - is_current: True - state: "present" ``` ### Return Values @@ -1161,7 +1138,7 @@ Manage cluster related operations on PowerStore * Minimum 3 and 5 addresses are required for management network for PowerStore T and X model respectively. * The File_Mobility purpose is supported only in FootHills Prime and above. * Parameter is_http_redirect_enabled is supported only in PowerStore FootHills Prime and above. -* The modules present in this collection named as 'dellemc.powerstore' are built to support the Dell PowerStore storage platform. +* Refer module documentation for more sample playbooks. ### Examples ``` @@ -1188,45 +1165,6 @@ Manage cluster related operations on PowerStore new_name: "new_RT-D1320" state: "present" -- name: Validate create cluster - dellemc.powerstore.cluster: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - cluster_name: "RT-D1320" - ignore_network_warnings: True - appliances: - - link_local_address: "1.2.x.x" - name: "Ansible_cluster" - derive_failure_tolerance_level: "Double" - dns_servers: - - "1.1.x.x" - ntp_servers: - - "1.3.x.x" - networks: - - type: "Management" - vlan_id: 0 - prefix_length: 24 - gateway: "1.x.x.x" - cluster_mgmt_address: "1.x.x.x" - addresses: - - "2.x.x.x" - - "3.x.x.x" - - type: "Storage" - vlan_id: 0 - prefix_length: 42 - gateway: "1.x.x.x" - storage_discovery_address: "1.x.x.x" - addresses: - - "2.x.x.x" - - "3.x.x.x" - purpose: - - "ISCSI" - is_http_redirect_enabled: True - validate_create: True - state: "present" - - name: Create cluster dellemc.powerstore.cluster: array_ip: "{{array_ip}}" @@ -1621,7 +1559,7 @@ DNS operations on a PowerStore storage system * Parameters dns_addresses and dns_address_state are required together. * Creation and deletion of DNS is not supported. * The check_mode is not supported. -* The modules present in this collection named as 'dellemc.powerstore' are built to support the Dell PowerStore storage platform. +* Refer module documentation for more sample playbooks. ### Examples ``` @@ -1646,18 +1584,6 @@ DNS operations on a PowerStore storage system - "YY.YY.YY.YY" dns_address_state: "present-in-dns" state: "present" - - - name: Remove addresses from DNS instance - dellemc.powerstore.dns: - array_ip: "{{array_ip}}" - user: "{{user}}" - password: "{{password}}" - verifycert: "{{verifycert}}" - dns_id: "DNS1" - dns_addresses: - - "YY.YY.YY.YY" - dns_address_state: "absent-in-dns" - state: "present" ``` ### Return Values @@ -1859,7 +1785,7 @@ Destination Email operations on a PowerStore storage system ### Notes * Idempotency is not supported for Test operation of Email module. * The check_mode is not supported. -* The modules present in this collection named as 'dellemc.powerstore' are built to support the Dell PowerStore storage platform. +* Refer module documentation for more sample playbooks. ### Examples ``` @@ -1872,15 +1798,6 @@ Destination Email operations on a PowerStore storage system email_id: "780b6220-2d0b-4b9f-a485-4ae7f673bd98" state: "present" - - name: Get details of destination email with email_address - dellemc.powerstore.email: - array_ip: "{{array_ip}}" - user: "{{user}}" - password: "{{password}}" - verifycert: "{{verifycert}}" - email_address: "abc@dell.com" - state: "present" - - name: Create destination email dellemc.powerstore.email: array_ip: "{{array_ip}}" @@ -1894,19 +1811,6 @@ Destination Email operations on a PowerStore storage system major: False state: "present" - - name: Modify destination email - dellemc.powerstore.email: - array_ip: "{{array_ip}}" - user: "{{user}}" - password: "{{password}}" - verifycert: "{{verifycert}}" - email_address: "abc_xyz@dell.com" - new_address: "def_pqr@dell.com" - notify: - info: False - major: False - state: "present" - - name: Send a test mail to the destination email with email_id dellemc.powerstore.email: array_ip: "{{array_ip}}" @@ -1916,15 +1820,6 @@ Destination Email operations on a PowerStore storage system email_id: "780b6220-2d0b-4b9f-a485-4ae7f673bd98" send_test_email: True state: "present" - - - name: Delete destination email - dellemc.powerstore.email: - array_ip: "{{array_ip}}" - user: "{{user}}" - password: "{{password}}" - verifycert: "{{verifycert}}" - email_address: "def_pqr@dell.com" - state: "absent" ``` ### Return Values @@ -2281,7 +2176,7 @@ Filesystem operations for PowerStore Storage system ### Notes * It is recommended to remove the protection policy before deleting the filesystem. * The check_mode is not supported. -* The modules present in this collection named as 'dellemc.powerstore' are built to support the Dell PowerStore storage platform. +* Refer module documentation for more sample playbooks. ### Examples ``` @@ -2310,24 +2205,6 @@ Filesystem operations for PowerStore Storage system protection_policy: "{{protection_policy_id}}" state: "present" - - name: Modify File System by id - dellemc.powerstore.filesystem: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - filesystem_id: "{{fs_id}}" - folder_rename_policy: "ALL_ALLOWED" - smb_properties: - is_smb_op_locks_enabled: True - smb_notify_on_change_dir_depth: 3 - quota_defaults: - grace_period: 2 - grace_period_unit: 'weeks' - default_hard_limit: 2 - default_soft_limit: 1 - state: "present" - - name: Get File System details by id dellemc.powerstore.filesystem: array_ip: "{{array_ip}}" @@ -2650,7 +2527,7 @@ Manage Filesystem Snapshots for PowerStore ### Notes * The check_mode is not supported. -* The modules present in this collection named as 'dellemc.powerstore' are built to support the Dell PowerStore storage platform. +* Refer module documentation for more sample playbooks. ### Examples ``` @@ -2676,18 +2553,6 @@ Manage Filesystem Snapshots for PowerStore snapshot_id: "{{fs_snapshot_id}}" state: "present" -- name: Modify the filesystem snapshot - dellemc.powerstore.filesystem_snapshot: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - snapshot_name: "sample_filesystem_snapshot" - nas_server: "ansible_nas_server" - description: "modify description" - expiration_timestamp: "" - state: "present" - - name: Delete filesystem snapshot dellemc.powerstore.filesystem_snapshot: array_ip: "{{array_ip}}" @@ -2830,7 +2695,7 @@ Manage host on PowerStore storage system Managing host on PowerStore storage system includes create host with a set of initiators, add/remove initiators from host, rename host and delete host. ### Parameters - + @@ -2957,6 +2822,14 @@ Manage host on PowerStore storage system + + + + + + + + @@ -3013,24 +2886,12 @@ Manage host on PowerStore storage system * The parameters initiators and detailed_initiators are mutually exclusive. * For mutual CHAP authentication, single CHAP credentials are mandatory. * Support of NVMe type of initiators is for PowerStore 2.0 and beyond. +* The host_connectivity is supported only in PowerStore 3.0.0.0 and above. * The check_mode is not supported. -* The modules present in this collection named as 'dellemc.powerstore' are built to support the Dell PowerStore storage platform. +* Refer module documentation for more sample playbooks. ### Examples ``` - - name: Create host with FC initiator - dellemc.powerstore.host: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - host_name: "ansible-test-host-1" - os_type: 'Windows' - initiators: - - 21:00:00:24:ff:31:e9:fc - state: 'present' - initiator_state: 'present-in-host' - - name: Create host with iSCSI initiator and its details dellemc.powerstore.host: array_ip: "{{array_ip}}" @@ -3044,10 +2905,6 @@ Manage host on PowerStore storage system port_type: 'iSCSI' chap_single_username: 'chapuserSingle' chap_single_password: 'chappasswd12345' - - port_name: 'iqn.1998-01.com.vmware:imn198248-5b06fb37' - port_type: 'iSCSI' - chap_mutual_username: 'chapuserMutual' - chap_mutual_password: 'chappasswd12345' state: 'present' initiator_state: 'present-in-host' @@ -3060,15 +2917,6 @@ Manage host on PowerStore storage system host_name: "ansible-test-host-1" state: 'present' - - name: Get host details by id - dellemc.powerstore.host: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - host_id: "5c1e869b-ed8a-4845-abae-b102bc249d41" - state: 'present' - - name: Add initiators to host by name dellemc.powerstore.host: array_ip: "{{array_ip}}" @@ -3081,68 +2929,6 @@ Manage host on PowerStore storage system initiator_state: 'present-in-host' state: 'present' - - name: Add initiators to host by id - dellemc.powerstore.host: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - host_id: "5c1e869b-ed8a-4845-abae-b102bc249d41" - detailed_initiators: - - port_name: 'iqn.1998-01.com.vmware:imn198248-5b06fb37' - port_type: 'iSCSI' - chap_mutual_username: 'chapuserMutual' - chap_mutual_password: 'chappasswd12345' - initiator_state: 'present-in-host' - state: 'present' - - - name: Remove initiators from host by name - dellemc.powerstore.host: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - host_name: "ansible-test-host-2" - detailed_initiators: - - port_name: 'iqn.1998-01.com.vmware:imn198248-5b06fb37' - port_type: 'iSCSI' - chap_mutual_username: 'chapuserMutual' - chap_mutual_password: 'chappasswd12345' - initiator_state: 'absent-in-host' - state: 'present' - - - name: Remove initiators from by id - dellemc.powerstore.host: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - host_id: "8c1e869b-fe8a-4845-hiae-h802bc249d41" - initiators: - - 21:00:00:24:ff:31:e9:ee - initiator_state: 'absent-in-host' - state: 'present' - - - name: Rename host by name - dellemc.powerstore.host: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - host_name: "ansible-test-host-1" - new_name: "ansible-test-host-1-new" - state: 'present' - - - name: Rename host by id - dellemc.powerstore.host: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - host_id: "5c1e869b-ed8a-4845-abae-b102bc249d41" - new_name: "ansible-test-host-2-new" - state: 'present' - - name: Delete host dellemc.powerstore.host: array_ip: "{{array_ip}}" @@ -3151,19 +2937,10 @@ Manage host on PowerStore storage system password: "{{password}}" host_name: "ansible-test-host-1-new" state: 'absent' - - - name: Delete host by id - dellemc.powerstore.host: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - host_id: "5c1e869b-ed8a-4845-abae-b102bc249d41" - state: 'absent' ``` ### Return Values - +
Parameter
The new name of host for renaming function. This value must contain 128 or fewer printable Unicode characters.
Cannot be specified when creating a host.
host_connectivity str
  • Local_Only
  • Metro_Optimize_Both
  • Metro_Optimize_Local
  • Metro_Optimize_Remote

Connectivity type for host.
If any of metro connectivity options specified, a metro host must exists in both cluster provide connectivity to a metro volume from both cluster.
array_ip
@@ -3189,6 +2966,13 @@ Manage host on PowerStore storage system + + + + + + + @@ -3362,7 +3146,7 @@ Manage host group on PowerStore Storage System Deletion of a host group results in deletion of the containing hosts as well. Remove hosts from the host group first to retain them. ### Parameters - +
Key str success Description about the host.
  host_connectivity str success Connectivity type for host. It was added in 3.0.0.0.
 
@@ -3419,6 +3203,14 @@ Manage host group on PowerStore Storage System + + + + + + + + @@ -3472,11 +3264,12 @@ Manage host group on PowerStore Storage System ### Notes * The check_mode is not supported. -* The modules present in this collection named as 'dellemc.powerstore' are built to support the Dell PowerStore storage platform. +* The host_connectivity is supported only PowerStore 3.0.0.0 and above. +* Refer module documentation for more sample playbooks. ### Examples ``` - - name: Create host group with hosts using host name + - name: Create host group with hosts dellemc.powerstore.hostgroup: array_ip: "{{array_ip}}" verifycert: "{{verifycert}}" @@ -3485,18 +3278,6 @@ Manage host group on PowerStore Storage System hostgroup_name: "{{hostgroup_name}}" hosts: - host1 - - host2 - state: 'present' - host_state: 'present-in-group' - - - name: Create host group with hosts using host ID - dellemc.powerstore.hostgroup: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - hostgroup_name: "{{hostgroup_name}}" - hosts: - c17fc987-bf82-480c-af31-9307b89923c3 state: 'present' host_state: 'present-in-group' @@ -3510,15 +3291,6 @@ Manage host group on PowerStore Storage System hostgroup_name: "{{hostgroup_name}}" state: 'present' - - name: Get host group details using ID - dellemc.powerstore.hostgroup: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - hostgroup_id: "{{host group_id}}" - state: 'present' - - name: Add hosts to host group dellemc.powerstore.hostgroup: array_ip: "{{array_ip}}" @@ -3531,28 +3303,6 @@ Manage host group on PowerStore Storage System host_state: 'present-in-group' state: 'present' - - name: Remove hosts from host group - dellemc.powerstore.hostgroup: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - hostgroup_name: "{{hostgroup_name}}" - hosts: - - host3 - host_state: 'absent-in-group' - state: 'present' - - - name: Rename host group - dellemc.powerstore.hostgroup: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - hostgroup_name: "{{hostgroup_name}}" - new_name: "{{new_hostgroup_name}}" - state: 'present' - - name: Delete host group dellemc.powerstore.hostgroup: array_ip: "{{array_ip}}" @@ -3564,7 +3314,7 @@ Manage host group on PowerStore Storage System ``` ### Return Values - +
Parameter
The new name for host group renaming function. This value must contain 128 or fewer printable Unicode characters.
host_connectivity str
  • Local_Only
  • Metro_Optimize_Both
  • Metro_Optimize_Local
  • Metro_Optimize_Remote

Connectivity type for host group.
If any of metro connectivity options specified, a metro host group must exists in both cluster provide connectivity to a metro volume from both cluster.
array_ip
@@ -3590,6 +3340,13 @@ Manage host group on PowerStore Storage System + + + + + + + @@ -3761,11 +3518,11 @@ Gathers information about PowerStore Storage entities ### Notes * Pagination is not supported for role, local user, security configs, LDAP accounts and LDAP domain. If all_pages is passed, it will be ignored. * The check_mode is supported. -* The modules present in this collection named as 'dellemc.powerstore' are built to support the Dell PowerStore storage platform. +* Refer module documentation for more sample playbooks. ### Examples ``` -- name: Get list of volumes, volume groups, hosts, host groups and node +- name: Get list of different attributes dellemc.powerstore.info: array_ip: "{{array_ip}}" verifycert: "{{verifycert}}" @@ -3777,212 +3534,65 @@ Gathers information about PowerStore Storage entities - host - hg - node - -- name: Get list of replication related entities - dellemc.powerstore.info: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - gather_subset: + - tree_quota + - user_quota + - file_system - replication_rule - replication_session - remote_system - -- name: Get list of volumes whose state notequal to ready - dellemc.powerstore.info: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - gather_subset: - - vol - filters: - - filter_key: "state" - filter_operator: "notequal" - filter_value: "ready" - -- name: Get list of protection policies and snapshot rules - dellemc.powerstore.info: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - gather_subset: - protection_policy - snapshot_rule - -- name: Get list of snapshot rules whose desired_retention between 101-499 - dellemc.powerstore.info: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - gather_subset: - - snapshot_rule - filters: - - filter_key: "desired_retention" - filter_operator: "greater" - filter_value: "100" - - filter_key: "desired_retention" - filter_operator: "lesser" - filter_value: "500" - -- name: Get list of nas server, nfs_export and smb share - dellemc.powerstore.info: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - gather_subset: - nas_server - nfs_export - smb_share - -- name: Get list of tree quota, user quota and file system - dellemc.powerstore.info: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - gather_subset: - - tree_quota - - user_quota - - file_system - -- name: Get list of nas server whose name equal to 'nas_server' - dellemc.powerstore.info: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - gather_subset: - - nas_server - filters: - - filter_key: "name" - filter_operator: "equal" - filter_value: "nas_server" - -- name: Get list of smb share whose name contains 'share' - dellemc.powerstore.info: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - gather_subset: - - nas_server - filters: - - filter_key: "name" - filter_operator: "like" - filter_value: "*share*" - -- name: Get list of user, role, network and appliances - dellemc.powerstore.info: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - gather_subset: - user - role - network - appliance - -- name: Get list of ad, certificate, security config and ldaps - dellemc.powerstore.info: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - gather_subset: - - ad - - ldap - - certificate - - security_config - -- name: Get list of networks whose name contains 'Management' - dellemc.powerstore.info: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - gather_subset: - - network - filters: - - filter_key: "name" - filter_operator: "like" - filter_value: "*Management*" - -- name: Get list of dns, email notification, ntp, remote support, remote support contact and smtp config - dellemc.powerstore.info: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - gather_subset: - dns - email_notification - ntp - remote_support - remote_support_contact - smtp_config - -- name: Get list of emails which receives minor notifications - dellemc.powerstore.info: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - gather_subset: - - email_notification - filters: - - filter_key: 'notify_minor' - filter_operator: 'equal' - filter_value: 'False' - -- name: Get list of LDAP accounts - dellemc.powerstore.info: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - gather_subset: + - ad + - ldap + - certificate + - security_config - ldap_account + - ldap_domain -- name: Get list of LDAP accounts with type as "User" +- name: Get list of volumes whose state notequal to ready dellemc.powerstore.info: array_ip: "{{array_ip}}" verifycert: "{{verifycert}}" user: "{{user}}" password: "{{password}}" gather_subset: - - ldap_account + - vol filters: - - filter_key: 'type' - filter_operator: 'equal' - filter_value: 'User' - -- name: Get list of LDAP domain - dellemc.powerstore.info: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - gather_subset: - - ldap_domain + - filter_key: "state" + filter_operator: "notequal" + filter_value: "ready" -- name: Get list of LDAP domain with protocol as "LDAPS" +- name: Get list of snapshot rules whose desired_retention between 101-499 and name contains 'share' dellemc.powerstore.info: array_ip: "{{array_ip}}" verifycert: "{{verifycert}}" user: "{{user}}" password: "{{password}}" gather_subset: - - ldap_domain + - snapshot_rule filters: - - filter_key: 'protocol' - filter_operator: 'equal' - filter_value: 'LDAPS' + - filter_key: "desired_retention" + filter_operator: "greater" + filter_value: "100" + - filter_key: "desired_retention" + filter_operator: "lesser" + filter_value: "500" + - filter_key: "name" + filter_operator: "like" + filter_value: "*share*" ``` ### Return Values @@ -4829,7 +4439,6 @@ Manage jobs for PowerStore ### Notes * The check_mode is not supported. -* The modules present in this collection named as 'dellemc.powerstore' are built to support the Dell PowerStore storage platform. ### Examples ``` @@ -5181,7 +4790,7 @@ Manage LDAP Account for PowerStore ### Notes * The check_mode is supported. -* The modules present in this collection named as 'dellemc.powerstore' are built to support the Dell PowerStore storage platform. +* Refer module documentation for more sample playbooks. ### Examples ``` @@ -5206,25 +4815,6 @@ Manage LDAP Account for PowerStore ldap_account_name: "ldap_user_account_1" state: "present" -- name: Get the details of the LDAP account by id - dellemc.powerstore.ldap_account: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - ldap_account_id: "3" - state: "present" - -- name: Modify an LDAP account - dellemc.powerstore.ldap_account: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - ldap_account_name: "ldap_user_account_1" - role_name: "2" - state: "present" - - name: Delete an LDAP account dellemc.powerstore.ldap_account: array_ip: "{{array_ip}}" @@ -5569,29 +5159,10 @@ Manage LDAP domain for PowerStore * To use LDAPS protocol, the pre-requisite is to upload the certificate of LDAP server on PowerStore array. * Verify operation does not support idempotency. * The check_mode is supported. -* The modules present in this collection named as 'dellemc.powerstore' are built to support the Dell PowerStore storage platform. +* Refer module documentation for more sample playbooks. ### Examples ``` -- name: Create LDAP domain - dellemc.powerstore.ldap_domain: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - domain_name: "{{domain_name}}" - ldap_servers: ["10.xxx.xx.xx"] - protocol: "LDAP" - ldap_server_type: "OpenLDAP" - bind_user: "{{bind_user}}" - bind_password: "{{bind_password}}" - ldap_domain_user_settings: - user_search_path: "cn=Users" - ldap_domain_group_settings: - group_search_path: "cn=Users" - ldap_server_state: "present-in-domain" - state: "present" - - name: Get LDAP domain details using ID dellemc.powerstore.ldap_domain: array_ip: "{{array_ip}}" @@ -5601,34 +5172,6 @@ Manage LDAP domain for PowerStore ldap_domain_id: 4 state: "present" -- name: Get LDAP domain details using name - dellemc.powerstore.ldap_domain: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - ldap_domain_name: "{{ldap_domain_name}}" - state: "present" - -- name: Verify LDAP domain configuration - dellemc.powerstore.ldap_domain: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - ldap_domain_id: 4 - verify_configuration: True - state: "present" - -- name: Delete LDAP domain configuration - dellemc.powerstore.ldap_domain: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - ldap_domain_id: 4 - state: "absent" - - name: Create LDAP domain with AD server type dellemc.powerstore.ldap_domain: array_ip: "{{array_ip}}" @@ -5651,15 +5194,6 @@ Manage LDAP domain for PowerStore group_search_path: "" state: "present" -- name: Get LDAP domain details using domain name - dellemc.powerstore.ldap_domain: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - ldap_domain_name: "{{domain_name}}" - state: "present" - - name: Delete LDAP domain using domain name dellemc.powerstore.ldap_domain: array_ip: "{{array_ip}}" @@ -5964,7 +5498,7 @@ Local user operations for PowerStore Storage System ### Notes * The check_mode is not supported. -* The modules present in this collection named as 'dellemc.powerstore' are built to support the Dell PowerStore storage platform. +* Refer module documentation for more sample playbooks. ### Examples ``` @@ -5980,15 +5514,6 @@ Local user operations for PowerStore Storage System is_locked: False state: "present" -- name: Get the details local user with user id - dellemc.powerstore.local_user: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - user_id: "{{user_id}}" - state: "present" - - name: Get the details local user with user name dellemc.powerstore.local_user: array_ip: "{{array_ip}}" @@ -5998,19 +5523,6 @@ Local user operations for PowerStore Storage System user_name: "ansible_user_1" state: "present" -- name: Modify attributes of local user - dellemc.powerstore.local_user: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - user_name: "ansible_user_1" - user_password: "Password123#" - new_password: "Ansible123#" - role_id: 4 - is_locked: True - state: "present" - - name: Delete local user dellemc.powerstore.local_user: array_ip: "{{array_ip}}" @@ -6256,7 +5768,7 @@ NAS Server operations for PowerStore Storage system ### Notes * The check_mode is not supported. * Adding/Removing protection policy to/from a NAS server is supported for PowerStore version 3.0.0 and above. -* The modules present in this collection named as 'dellemc.powerstore' are built to support the Dell PowerStore storage platform. +* Refer module documentation for more sample playbooks. ### Examples ``` @@ -6269,25 +5781,6 @@ NAS Server operations for PowerStore Storage system nas_server_name: "{{nas_server_name}}" state: "present" - - name: Get Details of NAS Server by ID - dellemc.powerstore.nasserver: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - nas_server_id: "{{nas_id}}" - state: "present" - - - name: Rename NAS Server by Name - dellemc.powerstore.nasserver: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - nas_server_name: "{{nas_server_name}}" - nas_server_new_name : "{{nas_server_new_name}}" - state: "present" - - name: Modify NAS Server attributes by ID dellemc.powerstore.nasserver: array_ip: "{{array_ip}}" @@ -6727,7 +6220,7 @@ Manage networks for PowerStore * Idempotency is not supported for vasa_provider_credentials and esxi_credentials. * For PowerStore X model, vasa_provider_credentials has to be specified along with new_cluster_mgmt_address. * The check_mode is not supported. -* The modules present in this collection named as 'dellemc.powerstore' are built to support the Dell PowerStore storage platform. +* Refer module documentation for more sample playbooks. ### Examples ``` @@ -6740,94 +6233,37 @@ Manage networks for PowerStore network_id: "NW1" state: "present" -- name: Get network details using name - dellemc.powerstore.network: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - network_name: "Default Management Network" - state: "present" - -- name: Rename the storage network +- name: Map port to the storage network dellemc.powerstore.network: array_ip: "{{array_ip}}" verifycert: "{{verifycert}}" user: "{{user}}" password: "{{password}}" network_name: "Default Storage Network" - new_name: "iSCSI Network" wait_for_completion: True + ports: + - "IP1" + port_state: "present-in-network" state: "present" -- name: Replace the IP's in the management network and re-register VASA vendor provider +- name: Replace the IP's in the management network and re-register VASA vendor + provider for X model dellemc.powerstore.network: - array_ip: "{{array_ip}}" + array_ip: "{{array_ip1}}" verifycert: "{{verifycert}}" user: "{{user}}" password: "{{password}}" network_id: "NW1" + vlan_id: 0 + gateway: "100.231.x.x" + mtu: 1500 + prefix_length: 24 addresses: - current_address: "100.230.x.x" - new_address: "100.230.x.x" - - current_address: "100.230.x.x" - new_address: "100.230.x.x" + new_address: "100.231.x.x" - current_address: "100.230.x.x" - new_address: "100.230.x.x" - new_cluster_mgmt_address: "100.230.x.x" - vasa_provider_credentials: - username: "vmadmin" - password: "{{vm_password}}" - state: "present" - -- name: Map port to the storage network - dellemc.powerstore.network: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - network_id: "NW6" - ports: - - "IP1" - port_state: "present-in-network" - state: "present" - -- name: Unmap port from the storage network - dellemc.powerstore.network: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - network_id: "NW6" - ports: - - "IP1" - port_state: "absent-in-network" - state: "present" - -- name: Replace the IP's in the management network and re-register VASA vendor - provider for X model - dellemc.powerstore.network: - array_ip: "{{array_ip1}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - network_id: "NW1" - vlan_id: 0 - gateway: "100.231.x.x" - mtu: 1500 - prefix_length: 24 - addresses: - - current_address: "100.230.x.x" - new_address: "100.231.x.x" - - current_address: "100.230.x.x" - new_address: "100.231.x.x" - - current_address: "100.230.x.x" - new_address: "100.231.x.x" - - current_address: "100.230.x.x" - new_address: "100.231.x.x" - - current_address: "100.230.x.x" - new_address: "100.231.x.x" - new_cluster_mgmt_address: "100.231.x.x" + new_address: "100.231.x.x" + new_cluster_mgmt_address: "100.231.x.x" vasa_provider_credentials: username: "vmadmin" password: "{{vm_password}}" @@ -7329,7 +6765,7 @@ Manage NFS exports for PowerStore ### Notes * The check_mode is not supported. -* The modules present in this collection named as 'dellemc.powerstore' are built to support the Dell PowerStore storage platform. +* Refer module documentation for more sample playbooks. ### Examples ``` @@ -7362,18 +6798,6 @@ Manage NFS exports for PowerStore host_state: "present-in-export" state: "present" -- name: Create NFS export Create NFS export for filesystem snapshot with mandatory parameters - dellemc.powerstore.nfs: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - nfs_export_name: "{{export_name2}}" - snapshot: "{{snapshot}}" - nas_server: "{{nas_server}}" - path: "{{path2}}" - state: "present" - - name: Get NFS export details using ID dellemc.powerstore.nfs: array_ip: "{{array_ip}}" @@ -7383,13 +6807,15 @@ Manage NFS exports for PowerStore nfs_export_id: "{{export_id}}" state: "present" -- name: Add Read-Only and Read-Write hosts to NFS export +- name: Modify the attributes of NFS export, add Read-Only and Read-Write hosts to NFS export dellemc.powerstore.nfs: array_ip: "{{array_ip}}" verifycert: "{{verifycert}}" user: "{{user}}" password: "{{password}}" nfs_export_id: "{{export_id}}" + description: "modify description" + default_access: "ROOT" read_only_hosts: - "{{host5}}" read_write_hosts: @@ -7397,31 +6823,6 @@ Manage NFS exports for PowerStore host_state: "present-in-export" state: "present" -- name: Remove Read-Only and Read-Write hosts from NFS export - dellemc.powerstore.nfs: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - nfs_export_id: "{{export_id}}" - read_only_hosts: - - "{{host1}}" - read_write_hosts: - - "{{host3}}" - host_state: "absent-in-export" - state: "present" - -- name: Modify the attributes of NFS export - dellemc.powerstore.nfs: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - nfs_export_id: "{{export_id}}" - description: "modify description" - default_access: "ROOT" - state: "present" - - name: Delete NFS export using name dellemc.powerstore.nfs: array_ip: "{{array_ip}}" @@ -7720,7 +7121,7 @@ NTP operations on a PowerStore storage system * Parameters ntp_addresses and ntp_address_state are required together. * Creation and deletion of NTP is not supported. * The check_mode is not supported. -* The modules present in this collection named as 'dellemc.powerstore' are built to support the Dell PowerStore storage platform. +* Refer module documentation for more sample playbooks. ### Examples ``` @@ -7745,18 +7146,6 @@ NTP operations on a PowerStore storage system - "YY.YY.YY.YY" ntp_address_state: "present-in-ntp" state: "present" - - - name: Remove addresses from NTP instance - dellemc.powerstore.ntp: - array_ip: "{{array_ip}}" - user: "{{user}}" - password: "{{password}}" - verifycert: "{{verifycert}}" - ntp_id: "NTP1" - ntp_addresses: - - "YY.YY.YY.YY" - ntp_address_state: "absent-in-ntp" - state: "present" ``` ### Return Values @@ -7936,7 +7325,7 @@ Perform Protection policy operations for PowerStore storage system * Before deleting a protection policy, the replication rule has to be removed from the protection policy. * In PowerStore version 3.0.0.0, protection policy without snapshot rule/replication rule is not allowed. * The check_mode is not supported. -* The modules present in this collection named as 'dellemc.powerstore' are built to support the Dell PowerStore storage platform. +* Refer module documentation for more sample playbooks. ### Examples ``` @@ -7954,19 +7343,7 @@ Perform Protection policy operations for PowerStore storage system snapshotrule_state: "present-in-policy" state: "present" - -- name : Modify protection policy, change name - dellemc.powerstore.protectionpolicy: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - name: "{{name}}" - new_name: "{{new_name}}" - state: "present" - - -- name : Modify protection policy, add snapshot rule +- name : Modify protection policy, add snapshot rule and remove replication rule dellemc.powerstore.protectionpolicy: array_ip: "{{array_ip}}" verifycert: "{{verifycert}}" @@ -7976,17 +7353,6 @@ Perform Protection policy operations for PowerStore storage system snapshotrules: - "Ansible_test_snaprule_1" snapshotrule_state: "present-in-policy" - state: "present" - -- name : Modify protection policy, remove snapshot rule, replication rule - dellemc.powerstore.protectionpolicy: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - name: "{{name}}" - snapshotrules: - - "Ansible_test_to_be_removed" replicationrule: "" snapshotrule_state: "absent-in-policy" state: "present" @@ -8000,15 +7366,6 @@ Perform Protection policy operations for PowerStore storage system name: "{{name}}" state: "present" -- name : Get details of protection policy by ID - dellemc.powerstore.protectionpolicy: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - protectionpolicy_id: "{{protectionpolicy_id}}" - state: "present" - - name : Delete protection policy dellemc.powerstore.protectionpolicy: array_ip: "{{array_ip}}" @@ -8321,7 +7678,7 @@ Manage Tree Quotas and User Quotas on PowerStore * If a user quota is to be created on a tree quota, then the user quotas will be enabled automatically in a tree quota. * Delete User Quota operation is not supported. * The check_mode is not supported. -* The modules present in this collection named as 'dellemc.powerstore' are built to support the Dell PowerStore storage platform. +* Refer module documentation for more sample playbooks. ### Examples ``` @@ -8341,22 +7698,6 @@ Manage Tree Quotas and User Quotas on PowerStore cap_unit: "TB" state: "present" - - name: Create a Tree Quota - dellemc.powerstore.quota: - array_ip: "{{array_ip}}" - verifycert: "{{verify_cert}}" - user: "{{user}}" - password: "{{password}}" - quota_type: "tree" - path: "/home" - filesystem: "sample_fs" - nas_server: "sample_nas_server" - quota: - soft_limit: 5 - hard_limit: 10 - cap_unit: "TB" - state: "present" - - name: Modify attributes for Tree Quota dellemc.powerstore.quota: array_ip: "{{array_ip}}" @@ -8382,15 +7723,6 @@ Manage Tree Quotas and User Quotas on PowerStore filesystem: "{{filesystem_id}}" state: "present" - - name: Get details of Tree Quota - dellemc.powerstore.quota: - array_ip: "{{array_ip}}" - verifycert: "{{verify_cert}}" - user: "{{user}}" - password: "{{password}}" - quota_id: "{{quota_id}}" - state: "present" - - name: Delete a Tree Quota dellemc.powerstore.quota: array_ip: "{{array_ip}}" @@ -8828,7 +8160,7 @@ Remote Support operations on a PowerStore storage system * Creation and deletion of remote support configuration is not supported. * Support for check_mode is not available for this module. * Verify and send test alert operations do not support idempotency. -* The modules present in this collection named as 'dellemc.powerstore' are built to support the Dell PowerStore storage platform. +* Refer module documentation for more sample playbooks. ### Examples ``` @@ -8862,33 +8194,6 @@ Remote Support operations on a PowerStore storage system timeout: 300 state: "present" - - name: Modify remote support configuration - SRS_Integrated_Tier2 - dellemc.powerstore.remote_support: - array_ip: "{{array_ip}}" - user: "{{user}}" - password: "{{password}}" - verifycert: "{{verifycert}}" - remote_support_id: 0 - support_type: "SRS_Integrated_Tier2" - proxy_address: "10.XX.XX.ZZ" - proxy_port: 3128 - proxy_username: "user" - proxy_password: "password" - timeout: 300 - state: "present" - - - name: Verify remote support configuration - dellemc.powerstore.remote_support: - array_ip: "{{array_ip}}" - user: "{{user}}" - password: "{{password}}" - verifycert: "{{verifycert}}" - remote_support_id: 0 - support_type: "SRS_Integrated_Tier3" - timeout: 300 - verify_connection: True - state: "present" - - name: Send a test alert dellemc.powerstore.remote_support: array_ip: "{{array_ip}}" @@ -9169,7 +8474,6 @@ Remote Support Contact operations on a PowerStore storage system * Creation and deletion of remote support contact is not supported. * Parameters first_name, last_name, email and phone can be removed by passing empty string. * The check_mode is not supported. -* The modules present in this collection named as 'dellemc.powerstore' are built to support the Dell PowerStore storage platform. ### Examples ``` @@ -9422,7 +8726,7 @@ Remote system operations on a PowerStore storage system * If wait_for_completion is set to True then the connection will be terminated after the timeout is exceeded. User can tweak timeout and pass it in the playbook task. * By default, the timeout is set to 120 seconds. * The check_mode is not supported. -* The modules present in this collection named as 'dellemc.powerstore' are built to support the Dell PowerStore storage platform. +* Refer module documentation for more sample playbooks. ### Examples ``` @@ -9440,20 +8744,6 @@ Remote system operations on a PowerStore storage system decription: "Adding a new remote system" state: "present" -- name: Modify attributes of remote system using remote_id - dellemc.powerstore.remotesystem: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - remote_id: "7d7e7917-735b-3eef-8cc3-1302001c08e7" - remote_address: "xxx.xxx.xxx.xxx" - network_latency: "Low" - wait_for_completion: True - timeout: 300 - decription: "Updating the description" - state: "present" - - name: Get details of remote system using remote_id dellemc.powerstore.remotesystem: array_ip: "{{array_ip}}" @@ -9778,7 +9068,7 @@ Replication rule operations on a PowerStore storage system ### Notes * The check_mode is not supported. -* The modules present in this collection named as 'dellemc.powerstore' are built to support the Dell PowerStore storage platform. +* Refer module documentation for more sample playbooks. ### Examples ``` @@ -9794,19 +9084,6 @@ Replication rule operations on a PowerStore storage system remote_system: "WN-D8877" state: "present" -- name: Modify existing replication rule - dellemc.powerstore.replicationrule: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - replication_rule_name: "sample_replication_rule" - new_name: "new_sample_replication_rule" - rpo: "One_Hour" - alert_threshold: "60" - remote_system: "WN-D0517" - state: "present" - - name: Get details of replication rule dellemc.powerstore.replicationrule: array_ip: "{{array_ip}}" @@ -9904,7 +9181,7 @@ Replication session operations on a PowerStore storage system This module supports get details of an existing replication session. Updating the state of the replication session. ### Parameters - +
Key str success Description about the host group.
  host_connectivity str success Connectivity type for host group. It was added in 3.0.0.0.
 
@@ -9961,6 +9238,14 @@ Replication session operations on a PowerStore storage system + + + + + + + + @@ -10017,29 +9302,11 @@ Replication session operations on a PowerStore storage system * When the current state of the replication session is 'OK' and in the playbook task 'synchronizing', then it will return "changed" as False. * The changed as False in above scenario is because of there is a scheduled synchronization in place with the associated replication rule's RPO in the protection policy. * The check_mode is not supported. -* nas_server and filesystem parameters are supported only for PowerStore version 3.0.0. and above. -* The modules present in this collection named as 'dellemc.powerstore' are built to support the Dell PowerStore storage platform. +* Parameter nas_server, filesystem, and role parameters are supported only for PowerStore version 3.0.0. and above. +* Refer module documentation for more sample playbooks. ### Examples ``` -- name: Pause a replication session - dellemc.powerstore.replicationsession: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - volume: "sample_volume_1" - session_state: "paused" - -- name: Synchronize a replication session - dellemc.powerstore.replicationsession: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - volume: "sample_volume_1" - session_state: "synchronizing" - - name: Get details of a replication session dellemc.powerstore.replicationsession: array_ip: "{{array_ip}}" @@ -10048,7 +9315,7 @@ Replication session operations on a PowerStore storage system password: "{{password}}" volume: "sample_volume_1" -- name: Fail over a replication session +- name: Modify a replication session dellemc.powerstore.replicationsession: array_ip: "{{array_ip}}" verifycert: "{{verifycert}}" @@ -10265,7 +9532,6 @@ Get details of the roles present on the PowerStore storage system * Only getting the details of the role is supported by the ansible module. * Creation, modification and deletion of roles is not supported by the ansible modules. * The check_mode is not supported. -* The modules present in this collection named as 'dellemc.powerstore' are built to support the Dell PowerStore storage platform. ### Examples ``` @@ -10277,15 +9543,6 @@ Get details of the roles present on the PowerStore storage system password: "{{password}}" role_name: "Administrator" state: "present" - -- name: Get the details of role by id - dellemc.powerstore.role: - array_ip: "{{array_ip}}" - verifycert: "{{verify_cert}}" - user: "{{user}}" - password: "{{password}}" - role_id: "1" - state: "present" ``` ### Return Values @@ -10439,7 +9696,7 @@ Security configuration operations for PowerStore Storage System * Creation and deletion of security configs is not supported by Ansible modules. * Modification of protocol mode is only supported for PowerStore v2.0.0.0 and above. * The check_mode is not supported. -* The modules present in this collection named as 'dellemc.powerstore' are built to support the Dell PowerStore storage platform. +* Refer module documentation for more sample playbooks. ### Examples ``` @@ -10695,7 +9952,7 @@ Manage SMB shares on a PowerStore storage system * When the ID of the filesystem/snapshot is passed then nas_server is not required. If passed, then the filesystem/snapshot should exist for the nas_server, else the task will fail. * Multiple SMB shares can be created for the same local path. * The check_mode is not supported. -* The modules present in this collection named as 'dellemc.powerstore' are built to support the Dell PowerStore storage platform. +* Refer module documentation for more sample playbooks. ### Examples ``` @@ -10717,39 +9974,6 @@ Manage SMB shares on a PowerStore storage system is_encryption_enabled: True state: "present" -- name: Modify Attributes of SMB share for a filesystem - dellemc.powerstore.smbshare: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - share_name: "sample_smb_share" - nas_server: "sample_nas_server" - description: "Sample SMB share attributes updated" - is_abe_enabled: False - is_branch_cache_enabled: False - offline_availability: "MANUAL" - is_continuous_availability_enabled: False - is_encryption_enabled: False - umask: "022" - state: "present" - -- name: Create SMB share for a snapshot - dellemc.powerstore.smbshare: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - share_name: "sample_snap_smb_share" - snapshot: "sample_snapshot" - nas_server: "{{nas_server_id}}" - path: "{{path}}" - description: "Sample SMB share created for snapshot" - is_abe_enabled: True - is_branch_cache_enabled: True - is_continuous_availability_enabled: True - state: "present" - - name: Modify Attributes of SMB share for a snapshot dellemc.powerstore.smbshare: array_ip: "{{array_ip}}" @@ -10766,15 +9990,6 @@ Manage SMB shares on a PowerStore storage system umask: "022" state: "present" -- name: Get details of SMB share - dellemc.powerstore.smbshare: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - share_id: "{{smb_share_id}}" - state: "present" - - name: Delete SMB share dellemc.powerstore.smbshare: array_ip: "{{array_ip}}" @@ -11021,7 +10236,7 @@ SMTP configuration operations on a PowerStore storage system * Idempotency is not supported for test operation for smtp_config module. * Creation and deletion of SMTP configuration is not supported. * The check_mode is not supported. -* The modules present in this collection named as 'dellemc.powerstore' are built to support the Dell PowerStore storage platform. +* Refer module documentation for more sample playbooks. ### Examples ``` @@ -11044,16 +10259,6 @@ SMTP configuration operations on a PowerStore storage system smtp_address: "sample.smtp.com" source_email: "def@dell.com" state: "present" - - - name: Send a test mail through the SMTP server - dellemc.powerstore.smtp_config: - array_ip: "{{array_ip}}" - user: "{{user}}" - password: "{{password}}" - verifycert: "{{verifycert}}" - smtp_id: "0" - destination_email: "abc@dell.com" - state: "present" ``` ### Return Values @@ -11262,7 +10467,7 @@ Manage Snapshots for PowerStore ### Notes * The check_mode is not supported. -* The modules present in this collection named as 'dellemc.powerstore' are built to support the Dell PowerStore storage platform. +* Refer module documentation for more sample playbooks. ### Examples ``` @@ -11279,47 +10484,26 @@ Manage Snapshots for PowerStore retention_unit: "{{retention_unit_days}}" state: "{{state_present}}" - - name: Get details of a volume snapshot + - name: Delete volume snapshot dellemc.powerstore.snapshot: array_ip: "{{mgmt_ip}}" verifycert: "{{verifycert}}" user: "{{user}}" password: "{{password}}" - snapshot_name: "{{snapshot_name}}" + snapshot_name: "{{new_snapshot_name}}" volume: "{{volume}}" - state: "{{state_present}}" + state: "{{state_absent}}" - - name: Rename volume snapshot + - name: Create a volume group snapshot on PowerStore dellemc.powerstore.snapshot: array_ip: "{{mgmt_ip}}" verifycert: "{{verifycert}}" user: "{{user}}" password: "{{password}}" snapshot_name: "{{snapshot_name}}" - new_snapshot_name: "{{new_snapshot_name}}" - volume: "{{volume}}" - state: "{{state_present}}" - - - name: Delete volume snapshot - dellemc.powerstore.snapshot: - array_ip: "{{mgmt_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - snapshot_name: "{{new_snapshot_name}}" - volume: "{{volume}}" - state: "{{state_absent}}" - - - name: Create a volume group snapshot on PowerStore - dellemc.powerstore.snapshot: - array_ip: "{{mgmt_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - snapshot_name: "{{snapshot_name}}" - volume_group: "{{volume_group}}" - description: "{{description}}" - expiration_timestamp: "{{expiration_timestamp}}" + volume_group: "{{volume_group}}" + description: "{{description}}" + expiration_timestamp: "{{expiration_timestamp}}" state: "{{state_present}}" - name: Get details of a volume group snapshot @@ -11332,29 +10516,6 @@ Manage Snapshots for PowerStore volume_group: "{{volume_group}}" state: "{{state_present}}" - - name: Modify volume group snapshot expiration timestamp - dellemc.powerstore.snapshot: - array_ip: "{{mgmt_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - snapshot_name: "{{snapshot_name}}" - volume_group: "{{volume_group}}" - description: "{{description}}" - expiration_timestamp: "{{expiration_timestamp_new}}" - state: "{{state_present}}" - - - name: Rename volume group snapshot - dellemc.powerstore.snapshot: - array_ip: "{{mgmt_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - snapshot_name: "{{snapshot_name}}" - new_snapshot_name: "{{new_snapshot_name}}" - volume_group: "{{volume_group}}" - state: "{{state_present}}" - - name: Delete volume group snapshot dellemc.powerstore.snapshot: array_ip: "{{mgmt_ip}}" @@ -11666,19 +10827,10 @@ Snapshot Rule operations on a PowerStore storage system ### Notes * The check_mode is not supported. -* The modules present in this collection named as 'dellemc.powerstore' are built to support the Dell PowerStore storage platform. +* Refer module documentation for more sample playbooks. ### Examples ``` -- name: Get details of an existing snapshot rule by name - dellemc.powerstore.snapshotrule: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - name: "{{name}}" - state: "present" - - name: Get details of an existing snapshot rule by id dellemc.powerstore.snapshotrule: array_ip: "{{array_ip}}" @@ -11688,20 +10840,6 @@ Snapshot Rule operations on a PowerStore storage system snapshotrule_id: "{{snapshotrule_id}}" state: "present" -- name: Create new snapshot rule by interval - dellemc.powerstore.snapshotrule: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - name: "{{name}}" - interval: "{{interval}}" - days_of_week: - - Monday - desired_retention: "{{desired_retention}}" - state: "present" - - - name: Create new snapshot rule by time_of_day and days_of_week dellemc.powerstore.snapshotrule: array_ip: "{{array_ip}}" @@ -11728,20 +10866,9 @@ Snapshot Rule operations on a PowerStore storage system - Monday - Wednesday - Friday - - Sunday time_of_day: "{{time_of_day}}" state: "present" -- name: Modify existing snapshot rule to interval - dellemc.powerstore.snapshotrule: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - name: "{{name}}" - interval: "{{interval}}" - state: "present" - - name: Delete an existing snapshot rule by name dellemc.powerstore.snapshotrule: array_ip: "{{array_ip}}" @@ -11850,12 +10977,13 @@ Manage volumes on a PowerStore storage system ### Synopsis Managing volume on PowerStore storage system includes create volume, get details of volume, modify volume attributes, map or unmap volume to host/host group, and delete volume. + Volume module also supports start or end of a metro configuration for a volume, clone, refresh and restore a volume. ### Parameters - +
Parameter
  • failed_over
  • paused
  • synchronizing

State in which the replication session is present after performing the task.
role str
  • Metro_Preferred
  • Metro_Non_Preferred

Role of the metro replication session.
array_ip
- + @@ -11863,7 +10991,7 @@ Manage volumes on a PowerStore storage system - + @@ -11871,7 +10999,7 @@ Manage volumes on a PowerStore storage system - + @@ -11879,7 +11007,7 @@ Manage volumes on a PowerStore storage system - + @@ -11887,7 +11015,7 @@ Manage volumes on a PowerStore storage system - + @@ -11895,7 +11023,7 @@ Manage volumes on a PowerStore storage system - + @@ -11903,7 +11031,7 @@ Manage volumes on a PowerStore storage system - + @@ -11911,7 +11039,7 @@ Manage volumes on a PowerStore storage system - + @@ -11919,7 +11047,7 @@ Manage volumes on a PowerStore storage system - + @@ -11927,7 +11055,7 @@ Manage volumes on a PowerStore storage system - + @@ -11935,7 +11063,7 @@ Manage volumes on a PowerStore storage system - + @@ -11943,7 +11071,7 @@ Manage volumes on a PowerStore storage system - + @@ -11951,7 +11079,7 @@ Manage volumes on a PowerStore storage system - + @@ -11959,7 +11087,7 @@ Manage volumes on a PowerStore storage system - + @@ -11967,7 +11095,146 @@ Manage volumes on a PowerStore storage system - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -11975,7 +11242,39 @@ Manage volumes on a PowerStore storage system - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -11983,7 +11282,7 @@ Manage volumes on a PowerStore storage system - + @@ -11991,7 +11290,7 @@ Manage volumes on a PowerStore storage system - + @@ -11999,7 +11298,7 @@ Manage volumes on a PowerStore storage system - + @@ -12007,7 +11306,7 @@ Manage volumes on a PowerStore storage system - + @@ -12015,7 +11314,7 @@ Manage volumes on a PowerStore storage system - + @@ -12030,22 +11329,12 @@ Manage volumes on a PowerStore storage system * The size is a required parameter for expand volume. * Clones or Snapshots of a deleted production volume or a clone are not deleted. * A volume that is attached to a host/host group, or that is part of a volume group cannot be deleted. +* If volume in metro session, volume can only be modified, refreshed and restored when session is in the pause state. * The Check_mode is not supported. -* The modules present in this collection named as 'dellemc.powerstore' are built to support the Dell PowerStore storage platform. +* Refer module documentation for more sample playbooks. ### Examples ``` -- name: Create stand-alone volume - dellemc.powerstore.volume: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - vol_name: "{{vol_name}}" - size: 1 - cap_unit: "{{cap_unit}}" - state: 'present' - - name: Create stand-alone volume with performance and protection policy dellemc.powerstore.volume: array_ip: "{{array_ip}}" @@ -12059,96 +11348,98 @@ Manage volumes on a PowerStore storage system description: 'Description' performance_policy: 'low' protection_policy: 'protection_policy_name' - -- name: Create volume and assign to a volume group - dellemc.powerstore.volume: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - vol_name: "{{vol_name}}" vg_name: "{{vg_name}}" - size: 1 - cap_unit: "{{cap_unit}}" - state: 'present' + mapping_state: 'mapped' + host: "{{host_name}}" -- name: Create volume and map it to a host +- name: Get volume details using ID dellemc.powerstore.volume: array_ip: "{{array_ip}}" verifycert: "{{verifycert}}" user: "{{user}}" password: "{{password}}" - vol_name: "{{vol_name}}" - size: 1 - cap_unit: "{{cap_unit}}" - mapping_state: 'mapped' - host: "{{host_name}}" - state: 'present' + vol_id: "{{result.volume_details.id}}" + state: "present" -- name: Get volume details using ID +- name: Modify volume size, name, description, protection and performance policy dellemc.powerstore.volume: array_ip: "{{array_ip}}" verifycert: "{{verifycert}}" user: "{{user}}" password: "{{password}}" - vol_id: "{{result.volume_details.id}}" + new_name: "{{new_name}}" + vol_name: "{{vol_name}}" state: "present" + size: 2 + performance_policy: 'high' + description: 'new description' + protection_policy: '' -- name: Get volume details using name +- name: Map volume to a host with HLU dellemc.powerstore.volume: array_ip: "{{array_ip}}" verifycert: "{{verifycert}}" user: "{{user}}" password: "{{password}}" vol_name: "{{vol_name}}" - state: "present" + state: 'present' + mapping_state: 'mapped' + host: 'host1' + hlu: 12 -- name: Modify volume size, name, description and performance policy +- name: Clone a volume dellemc.powerstore.volume: array_ip: "{{array_ip}}" verifycert: "{{verifycert}}" user: "{{user}}" password: "{{password}}" - new_name: "{{new_name}}" vol_name: "{{vol_name}}" + clone_volume: + name: 'test_name' + description: 'test description' + host: 'test_host' + host_group: 'test_host_group' + logical_unit_number: 1 + protection_policy: 'TEST_PP' + performance_policy: 'low' state: "present" - size: 2 - performance_policy: 'high' - description: 'new description' -- name: Remove protection policy from Volume +- name: Restore a volume dellemc.powerstore.volume: array_ip: "{{array_ip}}" verifycert: "{{verifycert}}" user: "{{user}}" password: "{{password}}" - new_name: "{{new_name}}" vol_name: "{{vol_name}}" + source_snap: 'refresh_backup_snap' + create_backup_snap: true + backup_snap_profile: + name: 'restore_snap_2' + description: 'test backup snap' + expiration_timestamp: '2022-12-23T01:20:00Z' + performance_policy: 'low' state: "present" - protection_policy: "" -- name: Map volume to a host with HLU +- name: Configure a metro volume dellemc.powerstore.volume: array_ip: "{{array_ip}}" verifycert: "{{verifycert}}" user: "{{user}}" password: "{{password}}" vol_name: "{{vol_name}}" - state: 'present' - mapping_state: 'mapped' - host: 'host1' - hlu: 12 + remote_system: "remote-D123" + state: "present" -- name: Map volume to a host without HLU +- name: End a metro volume configuration dellemc.powerstore.volume: array_ip: "{{array_ip}}" verifycert: "{{verifycert}}" user: "{{user}}" password: "{{password}}" vol_name: "{{vol_name}}" - state: 'present' - mapping_state: 'mapped' - host: 'host2' + end_metro_config: True + delete_remote_volume: True + state: "present" - name: Delete volume dellemc.powerstore.volume: @@ -12161,36 +11452,54 @@ Manage volumes on a PowerStore storage system ``` ### Return Values - +
ParameterParameter Type Required DefaultDescription
vol_name vol_name str
Unique name of the volume. This value must contain 128 or fewer printable unicode characters.
Required when creating a volume. All other functionalities on a volume are supported using volume name or ID.
vg_name vg_name str
The name of the volume group. A volume can optionally be assigned to a volume group at the time of creation.
Use the Volume Group Module for modification of the assignment.
vol_id vol_id str
The 36 character long ID of the volume, automatically generated when a volume is created.
Cannot be used while creating a volume. All other functionalities on a volume are supported using volume name or ID.
size size float
Size of the volume. Minimum volume size is 1MB. Maximum volume size is 256TB. Size must be a multiple of 8192.
Required in case of create and expand volume.
cap_unit cap_unit str
Volume size unit.
Used to signify unit of the size provided for creation and expansion of volume.
It defaults to 'GB', if not specified.
new_name new_name str
The new volume name for the volume, used in case of rename functionality.
description description str
Description for the volume.
Optional parameter when creating a volume.
To modify, pass the new value in description field.
protection_policy protection_policy str
The protection_policy of the volume.
To represent policy, both name or ID can be used interchangably. The module will detect both.
A volume can be assigned a protection policy at the time of creation of volume or later as well.
The policy can also be changed for a given volume by simply passing the new value.
The policy can be removed by passing an empty string.
Check examples for more clarity.
performance_policy performance_policy str
The performance_policy for the volume.
A volume can be assigned a performance policy at the time of creation of the volume, or later as well.
The policy can also be changed for a given volume, by simply passing the new value.
Check examples for more clarity.
If not given, performance policy will be 'medium'.
host host str
Host to be mapped/unmapped to a volume. If not specified, an unmapped volume is created. Only one of the host or host group can be supplied in one call.
To represent host, both name or ID can be used interchangeably. The module will detect both.
hostgroup hostgroup str
Hostgroup to be mapped/unmapped to a volume. If not specified, an unmapped volume is created.
Only one of the host or host group can be mapped in one call.
To represent a hostgroup, both name or ID can be used interchangeably. The module will detect both.
mapping_state mapping_state str
Define whether the volume should be mapped to a host or hostgroup.
Value mapped - indicates that the volume should be mapped to the host or host group.
Value unmapped - indicates that the volume should not be mapped to the host or host group.
Only one of a host or host group can be supplied in one call.
hlu hlu int
Logical unit number for the host/host group volume access.
Optional parameter when mapping a volume to host/host group.
HLU modification is not supported.
state clone_volume dict
Details of the volume clone.
  name str
Name of the clone set to be created.
  description str
Description of the clone.
  host str
Unique identifier or name of the host to be attached to the clone.
  host_group str
Unique identifier or name of the host group to be attached to the clone.
  logical_unit_number int
logical unit number when creating a mapped volume.
If no host_id or host_group_id is specified, logical_unit_number is ignored.
  protection_policy str
The protection policy of the clone set to be created.
  performance_policy str
  • high
  • medium
  • low

The performance policy of the clone set to be created.
source_volume str
Unique identifier or name of the volume to refresh from.
source_snap str
Unique identifier or name of the source snapshot that will be used for the restore operation.
create_backup_snap bool
Indicates whether a backup snapshot of the target volume will be created or not.
backup_snap_profile dict
Details of the backup snapshot set to be created.
  name str
Name of the backup snapshot set to be created.
The default name of the volume snapshot is the date and time when the snapshot is taken.
  description str
Description of the backup snapshot set.
  performance_policy str
  • high
  • medium
  • low

Performance policy assigned to the snapshot.
  expiration_timestamp str
Time after which the snapshot set can be auto-purged.
state str True
Define whether the volume should exist or not.
Value present - indicates that the volume should exist on the system.
Value absent - indicates that the volume should not exist on the system.
array_ip remote_system str
The remote system to which metro relationship will be established.
The remote system must support metro volume.
This is mandatory while configuring a metro volume.
To represent remote system, both name and ID are interchangeable.
This parameter is added in PowerStore version 3.0.0.0.
remote_appliance_id str
A remote system appliance ID to which volume will be assigned.
This parameter is added in PowerStore version 3.0.0.0.
end_metro_config bool False
Whether to end the metro session from a volume.
This is mandatory for end metro configuration operation.
delete_remote_volume bool
Whether to delete the remote volume during removal of metro session.
This is parameter is added in the PowerStore version 3.0.0.0.
array_ip str True
IP or FQDN of the PowerStore management system.
verifycert verifycert bool True
Boolean variable to specify whether to validate SSL certificate or not.
True - indicates that the SSL certificate should be verified. Set the environment variable REQUESTS_CA_BUNDLE to the path of the SSL certificate.
False - indicates that the SSL certificate should not be verified.
user user str True
The username of the PowerStore host.
password password str True
The password of the PowerStore host.
timeout timeout int 120
Time after which the connection will get terminated.
It is to be mentioned in seconds.
port port int
- + - + - + + + + + + + + + + + + + + + + + + + - + - + @@ -12198,7 +11507,7 @@ Manage volumes on a PowerStore storage system - + @@ -12206,7 +11515,7 @@ Manage volumes on a PowerStore storage system - + @@ -12214,7 +11523,7 @@ Manage volumes on a PowerStore storage system - + @@ -12222,14 +11531,14 @@ Manage volumes on a PowerStore storage system - + - + @@ -12237,7 +11546,7 @@ Manage volumes on a PowerStore storage system - + @@ -12245,14 +11554,14 @@ Manage volumes on a PowerStore storage system - + - + @@ -12260,7 +11569,7 @@ Manage volumes on a PowerStore storage system - + @@ -12268,21 +11577,21 @@ Manage volumes on a PowerStore storage system - + - + - + @@ -12290,7 +11599,7 @@ Manage volumes on a PowerStore storage system - + @@ -12298,63 +11607,93 @@ Manage volumes on a PowerStore storage system - + - + + + + + + + + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + @@ -12362,7 +11701,7 @@ Manage volumes on a PowerStore storage system - + @@ -12370,14 +11709,14 @@ Manage volumes on a PowerStore storage system - + - + @@ -12387,6 +11726,8 @@ Manage volumes on a PowerStore storage system ### Authors * Ambuj Dubey (@AmbujDube) * Manisha Agrawal (@agrawm3) +* Ananthu S Kuttattu (@kuttattz) +* Bhavneet Sharma (@Bhavneet-Sharma) -------------------------------- # Volume Group Module @@ -12508,7 +11849,7 @@ Manage volume groups on a PowerStore Storage System - + @@ -12630,7 +11971,7 @@ Manage volume groups on a PowerStore Storage System * A volume can be a member of at most one volume group. * Specifying "protection_policy" as empty string or "" removes the existing protection policy from a volume group. * The check_mode is not supported. -* The modules present in this collection named as 'dellemc.powerstore' are built to support the Dell PowerStore storage platform. +* Refer module documentation for more sample playbooks. ### Examples ``` @@ -12663,43 +12004,9 @@ Manage volume groups on a PowerStore Storage System state: "present" volumes: - "7f879569-676c-4749-a06f-c2c30e09b295" - - "68e4dad5-5de5-4644-a98f-6d4fb916e169" - "Ansible_Testing" vol_state: "present-in-group" -- name: Remove volumes from volume group - dellemc.powerstore.volumegroup: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - vg_name: "{{vg_name}}" - state: "present" - volumes: - - "7f879569-676c-4749-a06f-c2c30e09b295" - - "Ansible_Testing" - vol_state: "absent-in-group" - -- name: Rename volume group and change is_write_order_consistent flag - dellemc.powerstore.volumegroup: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - vg_name: "{{vg_name}}" - new_vg_name: "{{new_vg_name}}" - is_write_order_consistent: False - state: "present" - -- name: Get details of volume group by ID - dellemc.powerstore.volumegroup: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - vg_id: "{{vg_id}}" - state: "present" - - name: Delete volume group dellemc.powerstore.volumegroup: array_ip: "{{array_ip}}" @@ -12709,19 +12016,6 @@ Manage volume groups on a PowerStore Storage System name: "{{new_vg_name}}" state: "absent" -- name: Refresh a volume group - dellemc.powerstore.volumegroup: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - vg_name: "ansible_vg" - source_vg: "vg_source" - create_backup_snap: True - backup_snap_profile: - name: "test_snap" - state: "present" - - name: Restore a volume group dellemc.powerstore.volumegroup: array_ip: "{{array_ip}}" diff --git a/docs/Release Notes.md b/docs/Release Notes.md index 7036ed3..65ad06f 100644 --- a/docs/Release Notes.md +++ b/docs/Release Notes.md @@ -1,6 +1,6 @@ **Ansible Modules for Dell Technologies PowerStore** ========================================= -### Release Notes 1.7.0 +### Release Notes 1.8.0 > © 2022 Dell Inc. or its subsidiaries. All rights reserved. Dell, > and other trademarks are trademarks of Dell Inc. or its @@ -28,7 +28,7 @@ Table 1. Revision history | Revision | Date | Description | |----------|-----------|-----------------------------------------------------------| -| 01 | September 2022 | Current release of Ansible Modules for Dell PowerStore 1.7.0 | +| 01 | December 2022 | Current release of Ansible Modules for Dell PowerStore 1.8.0 | Product Description ------------------- @@ -63,11 +63,11 @@ Limitations Distribution ---------------- The software package is available for download from the [Ansible Modules -for PowerStore GitHub](https://github.com/dell/ansible-powerstore/tree/1.7.0) page. +for PowerStore GitHub](https://github.com/dell/ansible-powerstore/tree/1.8.0) page. Documentation ------------- -The documentation is available on [Ansible Modules for PowerStore GitHub](https://github.com/dell/ansible-powerstore/tree/1.7.0/docs) +The documentation is available on [Ansible Modules for PowerStore GitHub](https://github.com/dell/ansible-powerstore/tree/1.8.0/docs) page. It includes these: - README - Release Notes (this document) diff --git a/docs/SECURITY.md b/docs/SECURITY.md index c4327b5..0c38c52 100644 --- a/docs/SECURITY.md +++ b/docs/SECURITY.md @@ -12,7 +12,7 @@ You may obtain a copy of the License at The Ansible modules for Dell PowerStore repository are inspected for security vulnerabilities via blackduck scans and static code analysis. -In addition to this, there are various security checks that get executed against a branch when a pull request is created/updated. Please refer to [pull request](https://github.com/dell/ansible-powerstore/blob/1.7.0/docs/CONTRIBUTING.md#Pull-requests) for more information. +In addition to this, there are various security checks that get executed against a branch when a pull request is created/updated. Please refer to [pull request](https://github.com/dell/ansible-powerstore/blob/1.8.0/docs/CONTRIBUTING.md#Pull-requests) for more information. ## Reporting a vulnerability diff --git a/galaxy.yml b/galaxy.yml index 575e598..6a9e5a8 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -9,7 +9,7 @@ namespace: dellemc name: powerstore # The version of the collection. Must be compatible with semantic versioning -version: 1.7.0 +version: 1.8.0 # The path to the Markdown (.md) readme file. This path is relative to the root of the collection readme: README.md @@ -26,6 +26,7 @@ authors: - Rajshree Khare - Bhavneet Sharma - Trisha Datta +- Ananthu S Kuttattu ### OPTIONAL but strongly recommended # A short summary description of the collection @@ -52,13 +53,13 @@ tags: [storage] dependencies: {} # The URL of the originating SCM repository -repository: https://github.com/dell/ansible-powerstore/tree/1.7.0 +repository: https://github.com/dell/ansible-powerstore/tree/1.8.0 # The URL to any online docs -documentation: https://github.com/dell/ansible-powerstore/tree/1.7.0/docs +documentation: https://github.com/dell/ansible-powerstore/tree/1.8.0/docs # The URL to the homepage of the collection/project -homepage: https://github.com/dell/ansible-powerstore/tree/1.7.0 +homepage: https://github.com/dell/ansible-powerstore/tree/1.8.0 # The URL to the collection issue tracker issues: https://www.dell.com/community/Automation/bd-p/Automation diff --git a/meta/runtime.yml b/meta/runtime.yml index 1b2ff1d..91da9fd 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -1,5 +1,5 @@ --- -requires_ansible: ">=2.10" +requires_ansible: ">=2.12" plugin_routing: modules: dellemc_powerstore_gatherfacts: diff --git a/plugins/doc_fragments/powerstore.py b/plugins/doc_fragments/powerstore.py index feb1441..9970763 100644 --- a/plugins/doc_fragments/powerstore.py +++ b/plugins/doc_fragments/powerstore.py @@ -49,7 +49,7 @@ class ModuleDocFragment(object): type: int requirements: - - A Dell PowerStore Storage System. Ansible 2.11, 2.12 or 2.13 + - A Dell PowerStore Storage System. Ansible 2.12, 2.13 or 2.14 notes: - The modules present in this collection named as 'dellemc.powerstore' are built to support the Dell PowerStore storage platform. diff --git a/plugins/module_utils/storage/dell/utils.py b/plugins/module_utils/storage/dell/utils.py index fd0bb8b..d1da3ec 100644 --- a/plugins/module_utils/storage/dell/utils.py +++ b/plugins/module_utils/storage/dell/utils.py @@ -63,7 +63,7 @@ def py4ps_version_check(): "'pkg_resources', please install" \ " the required package" else: - min_ver = '1.8.0' + min_ver = '1.9.0' curr_version = PyPowerStore.__version__ unsupported_version_message = "PyPowerStore {0} is not supported " \ "by this module. Minimum supported" \ diff --git a/plugins/modules/certificate.py b/plugins/modules/certificate.py index 70f87a6..61b8eb6 100644 --- a/plugins/modules/certificate.py +++ b/plugins/modules/certificate.py @@ -262,7 +262,7 @@ VERSION_ERROR = py4ps_version['unsupported_version_message'] # Application type -APPLICATION_TYPE = 'Ansible/1.7.0' +APPLICATION_TYPE = 'Ansible/1.8.0' class PowerStoreCertificate(object): diff --git a/plugins/modules/cluster.py b/plugins/modules/cluster.py index ffb1da8..b169665 100644 --- a/plugins/modules/cluster.py +++ b/plugins/modules/cluster.py @@ -628,7 +628,7 @@ VERSION_ERROR = py4ps_version['unsupported_version_message'] # Application type -APPLICATION_TYPE = 'Ansible/1.7.0' +APPLICATION_TYPE = 'Ansible/1.8.0' class PowerStoreCluster(object): diff --git a/plugins/modules/dns.py b/plugins/modules/dns.py index d52fcf3..de4cf21 100644 --- a/plugins/modules/dns.py +++ b/plugins/modules/dns.py @@ -129,7 +129,7 @@ VERSION_ERROR = py4ps_version['unsupported_version_message'] # Application type -APPLICATION_TYPE = 'Ansible/1.7.0' +APPLICATION_TYPE = 'Ansible/1.8.0' class PowerstoreDns(object): diff --git a/plugins/modules/email.py b/plugins/modules/email.py index 032b077..9e78571 100644 --- a/plugins/modules/email.py +++ b/plugins/modules/email.py @@ -213,7 +213,7 @@ VERSION_ERROR = py4ps_version['unsupported_version_message'] # Application type -APPLICATION_TYPE = 'Ansible/1.7.0' +APPLICATION_TYPE = 'Ansible/1.8.0' class PowerstoreEmail(object): @@ -301,11 +301,11 @@ def create_destination_email(self, email_address): create_params = dict() create_params['email_address'] = email_address + notification_levels = ['critical', 'major', 'minor', 'info'] if self.module.params['notify'] is not None: - create_params['notify_critical'] = self.module.params['notify']['critical'] - create_params['notify_major'] = self.module.params['notify']['major'] - create_params['notify_minor'] = self.module.params['notify']['minor'] - create_params['notify_info'] = self.module.params['notify']['info'] + for level in notification_levels: + if self.module.params['notify'][level] is not None: + create_params['notify_' + level] = self.module.params['notify'][level] resp = self.configuration.create_destination_email( create_params=create_params) diff --git a/plugins/modules/filesystem.py b/plugins/modules/filesystem.py index 8dbda19..52e68b9 100644 --- a/plugins/modules/filesystem.py +++ b/plugins/modules/filesystem.py @@ -370,7 +370,7 @@ VERSION_ERROR = py4ps_version['unsupported_version_message'] # Application type -APPLICATION_TYPE = 'Ansible/1.7.0' +APPLICATION_TYPE = 'Ansible/1.8.0' class PowerStoreFileSystem(object): diff --git a/plugins/modules/filesystem_snapshot.py b/plugins/modules/filesystem_snapshot.py index d93df28..75c1506 100644 --- a/plugins/modules/filesystem_snapshot.py +++ b/plugins/modules/filesystem_snapshot.py @@ -253,7 +253,7 @@ VERSION_ERROR = py4ps_version['unsupported_version_message'] # Application type -APPLICATION_TYPE = 'Ansible/1.7.0' +APPLICATION_TYPE = 'Ansible/1.8.0' class PowerStoreFilesystemSnapshot(object): diff --git a/plugins/modules/host.py b/plugins/modules/host.py index 1b0b321..c1f38b3 100644 --- a/plugins/modules/host.py +++ b/plugins/modules/host.py @@ -125,6 +125,16 @@ or fewer printable Unicode characters. - Cannot be specified when creating a host. type: str + host_connectivity: + description: + - Connectivity type for host. + - If any of metro connectivity options specified, a metro host must + exists in both cluster provide connectivity to a metro volume from both + cluster. + choices: ['Local_Only', 'Metro_Optimize_Both', 'Metro_Optimize_Local', + 'Metro_Optimize_Remote'] + type: str + required: False notes: - Only completely and correctly configured iSCSI initiators can be associated @@ -132,6 +142,7 @@ - The parameters initiators and detailed_initiators are mutually exclusive. - For mutual CHAP authentication, single CHAP credentials are mandatory. - Support of NVMe type of initiators is for PowerStore 2.0 and beyond. +- The host_connectivity is supported only in PowerStore 3.0.0.0 and above. - The check_mode is not supported. ''' EXAMPLES = r''' @@ -143,6 +154,7 @@ password: "{{password}}" host_name: "ansible-test-host-1" os_type: 'Windows' + host_connectivity: "Metro_Optimize_Local" initiators: - 21:00:00:24:ff:31:e9:fc state: 'present' @@ -168,15 +180,6 @@ state: 'present' initiator_state: 'present-in-host' - - name: Get host details by name - dellemc.powerstore.host: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - host_name: "ansible-test-host-1" - state: 'present' - - name: Get host details by id dellemc.powerstore.host: array_ip: "{{array_ip}}" @@ -213,21 +216,6 @@ initiator_state: 'present-in-host' state: 'present' - - name: Remove initiators from host by name - dellemc.powerstore.host: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - host_name: "ansible-test-host-2" - detailed_initiators: - - port_name: 'iqn.1998-01.com.vmware:imn198248-5b06fb37' - port_type: 'iSCSI' - chap_mutual_username: 'chapuserMutual' - chap_mutual_password: 'chappasswd12345' - initiator_state: 'absent-in-host' - state: 'present' - - name: Remove initiators from by id dellemc.powerstore.host: array_ip: "{{array_ip}}" @@ -240,7 +228,7 @@ initiator_state: 'absent-in-host' state: 'present' - - name: Rename host by name + - name: Modify host by name dellemc.powerstore.host: array_ip: "{{array_ip}}" verifycert: "{{verifycert}}" @@ -248,16 +236,7 @@ password: "{{password}}" host_name: "ansible-test-host-1" new_name: "ansible-test-host-1-new" - state: 'present' - - - name: Rename host by id - dellemc.powerstore.host: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - host_id: "5c1e869b-ed8a-4845-abae-b102bc249d41" - new_name: "ansible-test-host-2-new" + host_connectivity: "Metro_Optimize_Remote" state: 'present' - name: Delete host @@ -268,15 +247,6 @@ password: "{{password}}" host_name: "ansible-test-host-1-new" state: 'absent' - - - name: Delete host by id - dellemc.powerstore.host: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - host_id: "5c1e869b-ed8a-4845-abae-b102bc249d41" - state: 'absent' ''' RETURN = r''' @@ -365,6 +335,9 @@ name: description: Name of the volume. type: str + host_connectivity: + description: Connectivity type for host. It was added in 3.0.0.0. + type: str sample: { "description": null, "host_group_id": null, @@ -381,6 +354,7 @@ "mapped_hosts": [], "name": "sample_host", "os_type": "ESXi", + "host_connectivity": "Local_Only", "os_type_l10n": "ESXi" } ''' @@ -401,7 +375,7 @@ VERSION_ERROR = py4ps_version['unsupported_version_message'] # Application type -APPLICATION_TYPE = 'Ansible/1.7.0' +APPLICATION_TYPE = 'Ansible/1.8.0' # DO NOT CHANGE BELOW PORT_TYPES SEQUENCE AS ITS USED IN SCRIPT USING INDEX PORT_TYPES = ["iSCSI", "FC", "NVMe"] @@ -487,6 +461,7 @@ def create_host(self, host_name): try: initiators = self.module.params['initiators'] detailed_initiators = self.module.params['detailed_initiators'] + host_connectivity = self.module.params['host_connectivity'] os_type = self.module.params['os_type'] if os_type is None: @@ -525,7 +500,8 @@ def create_host(self, host_name): list_of_initiators) resp = self.conn.provisioning.create_host( name=host_name, os_type=os_type, - initiators=list_of_initiators) + initiators=list_of_initiators, + host_connectivity=host_connectivity) else: for initiator in detailed_initiators: if initiator['port_type'] is None: @@ -540,7 +516,8 @@ def create_host(self, host_name): detailed_initiators) resp = self.conn.provisioning.create_host( name=host_name, os_type=os_type, - initiators=detailed_initiators) + initiators=detailed_initiators, + host_connectivity=host_connectivity) LOG.info("The response is %s", resp) return True @@ -697,9 +674,10 @@ def remove_host_initiators(self, host): LOG.error(error_msg) self.module.fail_json(msg=error_msg, **utils.failure_codes(e)) - def rename_host(self, host, new_name): + def update_host(self, host, new_name=None, host_connectivity=None): try: - self.conn.provisioning.modify_host(host['id'], name=new_name) + self.conn.provisioning.modify_host( + host['id'], name=new_name, host_connectivity=host_connectivity) return True except Exception as e: error_msg = 'Renaming of host {0} failed with error {1}'.format( @@ -738,7 +716,7 @@ def validate_initiators(self, detailed_initiators): def _create_result_dict(self, changed, host_id): self.result['changed'] = changed if self.module.params['state'] == 'absent': - self.result['host_details'] = {} + self.result['host_details'] = dict() else: self.result['host_details'] = self.get_host(host_id) @@ -755,6 +733,7 @@ def perform_module_operation(self): detailed_initiators = self.module.params['detailed_initiators'] new_name = self.module.params['new_name'] os_type = self.module.params['os_type'] + host_connectivity = self.module.params['host_connectivity'] if host_name: host_id = self.get_host_id_by_name(host_name) @@ -819,9 +798,11 @@ def perform_module_operation(self): LOG.info('Removing initiators from host %s', host_id) changed = (self.remove_host_initiators(host) or changed) - if state == 'present' and host and new_name and host_name != new_name: - LOG.info('Renaming host %s to %s', host_name, new_name) - changed = self.rename_host(host, new_name) + if state == 'present' and host and (new_name or host_connectivity): + modify_flag = is_modify_required(host, new_name, host_connectivity) + if modify_flag: + changed = self.update_host(host=host, new_name=new_name, + host_connectivity=host_connectivity) if state == 'absent' and host: LOG.info('Delete host %s ', host['name']) @@ -833,6 +814,18 @@ def perform_module_operation(self): self.module.exit_json(**self.result) +def is_modify_required(host, new_name, host_connectivity): + """ Check whether modification for host is required or not.""" + + modify_flag = False + if new_name is not None and host['name'] != new_name: + modify_flag = True + if host_connectivity is not None and \ + host['host_connectivity'] != host_connectivity: + modify_flag = True + return modify_flag + + def get_powerstore_host_parameters(): """This method provides the parameters required for the ansible host module on PowerStore""" @@ -862,12 +855,13 @@ def get_powerstore_host_parameters(): 'present-in-host'], type='str'), new_name=dict(required=False, type='str'), - os_type=dict(required=False, type='str', choices=['Windows', - 'Linux', - 'ESXi', - 'AIX', - 'HP-UX', - 'Solaris']) + os_type=dict( + required=False, type='str', + choices=['Windows', 'Linux', 'ESXi', 'AIX', 'HP-UX', 'Solaris']), + host_connectivity=dict( + required=False, type='str', + choices=['Local_Only', 'Metro_Optimize_Both', + 'Metro_Optimize_Local', 'Metro_Optimize_Remote']) ) diff --git a/plugins/modules/hostgroup.py b/plugins/modules/hostgroup.py index a499c5d..5b9cb10 100644 --- a/plugins/modules/hostgroup.py +++ b/plugins/modules/hostgroup.py @@ -75,14 +75,25 @@ - The new name for host group renaming function. This value must contain 128 or fewer printable Unicode characters. type: str + host_connectivity: + description: + - Connectivity type for host group. + - If any of metro connectivity options specified, a metro host group must + exists in both cluster provide connectivity to a metro volume from both + cluster. + choices: ['Local_Only', 'Metro_Optimize_Both', 'Metro_Optimize_Local', + 'Metro_Optimize_Remote'] + type: str + required: False notes: - The check_mode is not supported. +- The host_connectivity is supported only PowerStore 3.0.0.0 and above. ''' EXAMPLES = r''' - - name: Create host group with hosts using host name + - name: Create host group with hosts dellemc.powerstore.hostgroup: array_ip: "{{array_ip}}" verifycert: "{{verifycert}}" @@ -91,31 +102,10 @@ hostgroup_name: "{{hostgroup_name}}" hosts: - host1 - - host2 - state: 'present' - host_state: 'present-in-group' - - - name: Create host group with hosts using host ID - dellemc.powerstore.hostgroup: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - hostgroup_name: "{{hostgroup_name}}" - hosts: - c17fc987-bf82-480c-af31-9307b89923c3 state: 'present' host_state: 'present-in-group' - - name: Get host group details - dellemc.powerstore.hostgroup: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - hostgroup_name: "{{hostgroup_name}}" - state: 'present' - - name: Get host group details using ID dellemc.powerstore.hostgroup: array_ip: "{{array_ip}}" @@ -149,13 +139,14 @@ host_state: 'absent-in-group' state: 'present' - - name: Rename host group + - name: Modify host group dellemc.powerstore.hostgroup: array_ip: "{{array_ip}}" verifycert: "{{verifycert}}" user: "{{user}}" password: "{{password}}" hostgroup_name: "{{hostgroup_name}}" + host_connectivity: "Metro_Optimize_Both" new_name: "{{new_hostgroup_name}}" state: 'present' @@ -201,6 +192,9 @@ name: description: The name of the host. type: str + host_connectivity: + description: Connectivity type for host group. It was added in 3.0.0.0. + type: str sample: { "description": null, "hosts": [ @@ -210,6 +204,7 @@ } ], "id": "80fc96fa-227e-4796-84b8-c6452c5b8f64", + "host_connectivity": "Local_Only", "name": "sample_host_group" } ''' @@ -230,7 +225,7 @@ VERSION_ERROR = py4ps_version['unsupported_version_message'] # Application type -APPLICATION_TYPE = 'Ansible/1.7.0' +APPLICATION_TYPE = 'Ansible/1.8.0' class PowerStoreHostgroup(object): @@ -282,7 +277,11 @@ def get_powerstore_hostgroup_parameters(self): host_state=dict(required=False, choices=['absent-in-group', 'present-in-group'], type='str'), - new_name=dict(required=False, type='str') + new_name=dict(required=False, type='str'), + host_connectivity=dict( + required=False, type='str', + choices=['Local_Only', 'Metro_Optimize_Both', + 'Metro_Optimize_Local', 'Metro_Optimize_Remote']) ) def get_hostgroup(self, hostgroup_id): @@ -490,14 +489,17 @@ def remove_hostgroup_hosts(self, hostgroup, hosts): LOG.error(error_msg) self.module.fail_json(msg=error_msg, **utils.failure_codes(e)) - def rename_hostgroup(self, hostgroup, new_name): + def modify_host_group(self, hostgroup, new_name=None, + host_connectivity=None): + """ Modify the host group""" try: self.conn.provisioning.modify_host_group( - hostgroup['id'], name=new_name) + hostgroup['id'], name=new_name, + host_connectivity=host_connectivity) return True except Exception as e: - error_msg = 'Renaming of host group {0} failed with error {1}'.format( - hostgroup['name'], str(e)) + error_msg = 'Modifying host group {0} failed with error ' \ + '{1}'.format(hostgroup['name'], str(e)) LOG.error(error_msg) self.module.fail_json(msg=error_msg, **utils.failure_codes(e)) @@ -518,7 +520,7 @@ def delete_hostgroup(self, hostgroup): def _create_result_dict(self, changed, hostgroup_id): self.result['changed'] = changed if self.module.params['state'] == 'absent': - self.result['hostgroup_details'] = {} + self.result['hostgroup_details'] = dict() else: self.result['hostgroup_details'] = self.get_hostgroup( hostgroup_id) @@ -534,13 +536,15 @@ def perform_module_operation(self): hostgroup_id = self.module.params['hostgroup_id'] hosts = self.module.params['hosts'] new_name = self.module.params['new_name'] + host_connectivity = self.module.params['host_connectivity'] + + hostgroup = None if hostgroup_name: hostgroup_id = self.get_hostgroup_id_by_name(hostgroup_name) if hostgroup_id: hostgroup = self.get_hostgroup(hostgroup_id) - else: - hostgroup = None + changed = False host_ids_list = [] if hosts: @@ -570,11 +574,13 @@ def perform_module_operation(self): hostgroup, hosts=host_ids_list) or changed) - if state == 'present' and hostgroup and new_name and \ - hostgroup['name'] != new_name: - LOG.info('Renaming host group %s to %s', hostgroup['name'], - new_name) - changed = self.rename_hostgroup(hostgroup, new_name) + if state == 'present' and hostgroup and (new_name or host_connectivity): + modify_flag = is_modify_required(hostgroup, new_name, + host_connectivity) + if modify_flag: + changed = self.modify_host_group( + hostgroup=hostgroup, new_name=new_name, + host_connectivity=host_connectivity) if state == 'absent' and hostgroup: LOG.info('Deleting host group %s ', hostgroup['name']) @@ -586,6 +592,18 @@ def perform_module_operation(self): self.module.exit_json(**self.result) +def is_modify_required(hostgroup, new_name, host_connectivity): + """ Check whether modification for host group is required or not.""" + + modify_flag = False + if new_name is not None and hostgroup['name'] != new_name: + modify_flag = True + if host_connectivity is not None and \ + hostgroup['host_connectivity'] != host_connectivity: + modify_flag = True + return modify_flag + + def main(): ''' Create PowerStore host group object and perform action on it based on user input from playbook''' diff --git a/plugins/modules/info.py b/plugins/modules/info.py index d284ef6..46cc46f 100644 --- a/plugins/modules/info.py +++ b/plugins/modules/info.py @@ -1003,7 +1003,7 @@ VERSION_ERROR = py4ps_version['unsupported_version_message'] # Application type -APPLICATION_TYPE = 'Ansible/1.7.0' +APPLICATION_TYPE = 'Ansible/1.8.0' class PowerstoreInfo(object): diff --git a/plugins/modules/job.py b/plugins/modules/job.py index 0edeb93..656f805 100644 --- a/plugins/modules/job.py +++ b/plugins/modules/job.py @@ -174,7 +174,7 @@ VERSION_ERROR = py4ps_version['unsupported_version_message'] # Application type -APPLICATION_TYPE = 'Ansible/1.7.0' +APPLICATION_TYPE = 'Ansible/1.8.0' class PowerStoreJob(object): diff --git a/plugins/modules/ldap_account.py b/plugins/modules/ldap_account.py index 259cf64..4dbf3a4 100644 --- a/plugins/modules/ldap_account.py +++ b/plugins/modules/ldap_account.py @@ -173,7 +173,7 @@ VERSION_ERROR = py4ps_version['unsupported_version_message'] # Application type -APPLICATION_TYPE = 'Ansible/1.7.0' +APPLICATION_TYPE = 'Ansible/1.8.0' class PowerStoreLDAPAccount(object): diff --git a/plugins/modules/ldap_domain.py b/plugins/modules/ldap_domain.py index d8a1df9..5462443 100644 --- a/plugins/modules/ldap_domain.py +++ b/plugins/modules/ldap_domain.py @@ -354,7 +354,7 @@ VERSION_ERROR = py4ps_version['unsupported_version_message'] # Application type -APPLICATION_TYPE = 'Ansible/1.7.0' +APPLICATION_TYPE = 'Ansible/1.8.0' class PowerStoreLDAPDomain(object): diff --git a/plugins/modules/local_user.py b/plugins/modules/local_user.py index c46487f..fc929bb 100644 --- a/plugins/modules/local_user.py +++ b/plugins/modules/local_user.py @@ -185,7 +185,7 @@ VERSION_ERROR = py4ps_version['unsupported_version_message'] # Application type -APPLICATION_TYPE = 'Ansible/1.7.0' +APPLICATION_TYPE = 'Ansible/1.8.0' class PowerStoreLocalUser(object): diff --git a/plugins/modules/nasserver.py b/plugins/modules/nasserver.py index 04a9fe2..e18ea9d 100644 --- a/plugins/modules/nasserver.py +++ b/plugins/modules/nasserver.py @@ -299,7 +299,7 @@ VERSION_ERROR = py4ps_version['unsupported_version_message'] # Application type -APPLICATION_TYPE = 'Ansible/1.7.0' +APPLICATION_TYPE = 'Ansible/1.8.0' class PowerStoreNasServer(object): diff --git a/plugins/modules/network.py b/plugins/modules/network.py index 90ac86f..03de570 100644 --- a/plugins/modules/network.py +++ b/plugins/modules/network.py @@ -498,7 +498,7 @@ VERSION_ERROR = py4ps_version['unsupported_version_message'] # Application type -APPLICATION_TYPE = 'Ansible/1.7.0' +APPLICATION_TYPE = 'Ansible/1.8.0' class PowerStoreNetwork(object): diff --git a/plugins/modules/nfs.py b/plugins/modules/nfs.py index 37a9e82..98a91f5 100644 --- a/plugins/modules/nfs.py +++ b/plugins/modules/nfs.py @@ -381,7 +381,7 @@ VERSION_ERROR = py4ps_version['unsupported_version_message'] # Application type -APPLICATION_TYPE = 'Ansible/1.7.0' +APPLICATION_TYPE = 'Ansible/1.8.0' class PowerStoreNfsExport(object): diff --git a/plugins/modules/ntp.py b/plugins/modules/ntp.py index 29f95c0..2f784e5 100644 --- a/plugins/modules/ntp.py +++ b/plugins/modules/ntp.py @@ -130,7 +130,7 @@ VERSION_ERROR = py4ps_version['unsupported_version_message'] # Application type -APPLICATION_TYPE = 'Ansible/1.7.0' +APPLICATION_TYPE = 'Ansible/1.8.0' class PowerstoreNtp(object): diff --git a/plugins/modules/protectionpolicy.py b/plugins/modules/protectionpolicy.py index 7cfbe21..baee35b 100644 --- a/plugins/modules/protectionpolicy.py +++ b/plugins/modules/protectionpolicy.py @@ -246,7 +246,7 @@ VERSION_ERROR = py4ps_version['unsupported_version_message'] # Application type -APPLICATION_TYPE = 'Ansible/1.7.0' +APPLICATION_TYPE = 'Ansible/1.8.0' class PowerstoreProtectionpolicy(object): diff --git a/plugins/modules/quota.py b/plugins/modules/quota.py index 26624f9..131616f 100644 --- a/plugins/modules/quota.py +++ b/plugins/modules/quota.py @@ -364,7 +364,7 @@ VERSION_ERROR = py4ps_version['unsupported_version_message'] # Application type -APPLICATION_TYPE = 'Ansible/1.7.0' +APPLICATION_TYPE = 'Ansible/1.8.0' class PowerStoreQuota(object): diff --git a/plugins/modules/remote_support.py b/plugins/modules/remote_support.py index ed92014..399baad 100644 --- a/plugins/modules/remote_support.py +++ b/plugins/modules/remote_support.py @@ -371,7 +371,7 @@ VERSION_ERROR = py4ps_version['unsupported_version_message'] # Application type -APPLICATION_TYPE = 'Ansible/1.7.0' +APPLICATION_TYPE = 'Ansible/1.8.0' class PowerstoreRemoteSupport(object): diff --git a/plugins/modules/remote_support_contact.py b/plugins/modules/remote_support_contact.py index 6f8ea3b..92f88fc 100644 --- a/plugins/modules/remote_support_contact.py +++ b/plugins/modules/remote_support_contact.py @@ -141,7 +141,7 @@ VERSION_ERROR = py4ps_version['unsupported_version_message'] # Application type -APPLICATION_TYPE = 'Ansible/1.7.0' +APPLICATION_TYPE = 'Ansible/1.8.0' class PowerstoreRemoteSupportContact(object): diff --git a/plugins/modules/remotesystem.py b/plugins/modules/remotesystem.py index 6f305ce..b4656f3 100644 --- a/plugins/modules/remotesystem.py +++ b/plugins/modules/remotesystem.py @@ -318,7 +318,7 @@ VERSION_ERROR = py4ps_version['unsupported_version_message'] # Application type -APPLICATION_TYPE = 'Ansible/1.7.0' +APPLICATION_TYPE = 'Ansible/1.8.0' class PowerstoreRemoteSystem(object): diff --git a/plugins/modules/replicationrule.py b/plugins/modules/replicationrule.py index 4939d3d..65f1f8b 100644 --- a/plugins/modules/replicationrule.py +++ b/plugins/modules/replicationrule.py @@ -201,7 +201,7 @@ VERSION_ERROR = py4ps_version['unsupported_version_message'] # Application type -APPLICATION_TYPE = 'Ansible/1.7.0' +APPLICATION_TYPE = 'Ansible/1.8.0' class PowerstoreReplicationRule(object): diff --git a/plugins/modules/replicationsession.py b/plugins/modules/replicationsession.py index d95ccfb..3e4edb2 100644 --- a/plugins/modules/replicationsession.py +++ b/plugins/modules/replicationsession.py @@ -59,6 +59,12 @@ required: False choices: [ 'failed_over', 'paused', 'synchronizing'] type: str + role: + description: + - Role of the metro replication session. + required: False + choices: ['Metro_Preferred', 'Metro_Non_Preferred'] + type: str notes: - Manual synchronization for a replication session is not supported through the Ansible module. @@ -68,11 +74,11 @@ synchronization in place with the associated replication rule's RPO in the protection policy. - The check_mode is not supported. -- nas_server and filesystem parameters are supported only for PowerStore version 3.0.0. and above. +- Parameter nas_server, filesystem, and role parameters are supported only for + PowerStore version 3.0.0. and above. ''' EXAMPLES = r''' - - name: Pause a replication session dellemc.powerstore.replicationsession: array_ip: "{{array_ip}}" @@ -82,14 +88,14 @@ volume: "sample_volume_1" session_state: "paused" -- name: Synchronize a replication session +- name: Modify a replication session dellemc.powerstore.replicationsession: array_ip: "{{array_ip}}" verifycert: "{{verifycert}}" user: "{{user}}" password: "{{password}}" volume: "sample_volume_1" - session_state: "synchronizing" + role: "Metro_Preferred" - name: Get details of a replication session dellemc.powerstore.replicationsession: @@ -220,7 +226,7 @@ VERSION_ERROR = py4ps_version['unsupported_version_message'] # Application type -APPLICATION_TYPE = 'Ansible/1.7.0' +APPLICATION_TYPE = 'Ansible/1.8.0' """ =============================================================================== Idempotency table for the replication session ansible module on the basis of @@ -237,7 +243,7 @@ synchronizing |paused | issue a pause sdk call |failed_over | issue a failed_over sdk call ------------------------------------------------------------------------------- - |synchronizing | resume and sync sdk calls + |synchronizing | resume or sync sdk calls paused |paused | idempotency case |failed_over | issue a failed_over sdk call ------------------------------------------------------------------------------- @@ -602,11 +608,15 @@ def change_state_from_paused(self, session_state, current_state, try: session_id = rep_session_details['id'] role = rep_session_details['role'].lower() + session_type = rep_session_details['type'] if session_state == 'synchronizing': # As the current state is paused so first the session has to be # resumed then it can be synced - if role == "source": + if session_type == "Metro_Active_Active": + self.protection.resume_replication_session(session_id) + return True + elif role == "source": self.protection.resume_replication_session(session_id) self.protection.sync_replication_session(session_id) return True @@ -758,6 +768,18 @@ def change_state_from_remaining_states(self, current_state): " ansible module.".format(current_state) self.module.fail_json(msg=err_msg) + def modify_replication_session(self, session_id, role): + """ Modify the role of the replication session""" + try: + self.protection.modify_replication_session( + session_id=session_id, role=role) + return True + except Exception as e: + err_msg = "Modifying the role {0} of replication session {1}" \ + " failed with error {2}".format(role, session_id, str(e)) + LOG.error(err_msg) + self.module.fail_json(msg=err_msg, **utils.failure_codes(e)) + def perform_module_operation(self): """collect input""" vol = self.module.params['volume'] @@ -766,6 +788,7 @@ def perform_module_operation(self): nas_server = self.module.params['nas_server'] session_id = self.module.params['session_id'] session_state = self.module.params['session_state'] + role = self.module.params['role'] result = dict() changed = False @@ -829,7 +852,8 @@ def perform_module_operation(self): changed = self.change_state_from_failing_over( session_state, current_state, rep_session_details, err_msg) - transitioning_states = ['resuming', 'reprotecting', 'initializing'] + transitioning_states = ['resuming', 'reprotecting', 'initializing', + 'fractured', 'switching_to_metro_sync'] if session_state and current_state in transitioning_states: self.change_state_from_transitioning_states( session_state, current_state) @@ -840,6 +864,11 @@ def perform_module_operation(self): if session_state and current_state in remaining_states: self.change_state_from_remaining_states(current_state) + if rep_session_details and role is not None and \ + rep_session_details['role'] != role: + changed = self.modify_replication_session( + rep_session_details['id'], role) + result['changed'] = changed result['replication_session_details'] = self.show_output(session_id) self.module.exit_json(**result) @@ -899,7 +928,10 @@ def get_powerstore_rep_session_parameters(): volume_group=dict(), volume=dict(), filesystem=dict(), nas_server=dict(), session_id=dict(), session_state=dict(type='str', choices=['synchronizing', 'paused', - 'failed_over']) + 'failed_over']), + role=dict( + required=False, type='str', + choices=['Metro_Preferred', 'Metro_Non_Preferred']) ) diff --git a/plugins/modules/role.py b/plugins/modules/role.py index 480bbd2..3df1f88 100644 --- a/plugins/modules/role.py +++ b/plugins/modules/role.py @@ -113,7 +113,7 @@ VERSION_ERROR = py4ps_version['unsupported_version_message'] # Application type -APPLICATION_TYPE = 'Ansible/1.7.0' +APPLICATION_TYPE = 'Ansible/1.8.0' class PowerStoreRole(object): diff --git a/plugins/modules/security_config.py b/plugins/modules/security_config.py index 907271f..f2bff21 100644 --- a/plugins/modules/security_config.py +++ b/plugins/modules/security_config.py @@ -116,7 +116,7 @@ VERSION_ERROR = py4ps_version['unsupported_version_message'] # Application type -APPLICATION_TYPE = 'Ansible/1.7.0' +APPLICATION_TYPE = 'Ansible/1.8.0' class PowerStoreSecurityConfig(object): diff --git a/plugins/modules/smbshare.py b/plugins/modules/smbshare.py index aa060e4..62ebb8c 100644 --- a/plugins/modules/smbshare.py +++ b/plugins/modules/smbshare.py @@ -311,7 +311,7 @@ VERSION_ERROR = py4ps_version['unsupported_version_message'] # Application type -APPLICATION_TYPE = 'Ansible/1.7.0' +APPLICATION_TYPE = 'Ansible/1.8.0' class PowerStoreSMBShare(object): diff --git a/plugins/modules/smtp_config.py b/plugins/modules/smtp_config.py index f01e008..c138ecc 100644 --- a/plugins/modules/smtp_config.py +++ b/plugins/modules/smtp_config.py @@ -143,7 +143,7 @@ VERSION_ERROR = py4ps_version['unsupported_version_message'] # Application type -APPLICATION_TYPE = 'Ansible/1.7.0' +APPLICATION_TYPE = 'Ansible/1.8.0' class PowerstoreSmtpConfig(object): diff --git a/plugins/modules/snapshot.py b/plugins/modules/snapshot.py index be775d3..a254403 100644 --- a/plugins/modules/snapshot.py +++ b/plugins/modules/snapshot.py @@ -344,7 +344,7 @@ VERSION_ERROR = py4ps_version['unsupported_version_message'] # Application type -APPLICATION_TYPE = 'Ansible/1.7.0' +APPLICATION_TYPE = 'Ansible/1.8.0' class PowerStoreSnapshot(object): diff --git a/plugins/modules/snapshotrule.py b/plugins/modules/snapshotrule.py index 05ed783..003b0c2 100644 --- a/plugins/modules/snapshotrule.py +++ b/plugins/modules/snapshotrule.py @@ -258,7 +258,7 @@ VERSION_ERROR = py4ps_version['unsupported_version_message'] # Application type -APPLICATION_TYPE = 'Ansible/1.7.0' +APPLICATION_TYPE = 'Ansible/1.8.0' class PowerstoreSnapshotrule(object): diff --git a/plugins/modules/volume.py b/plugins/modules/volume.py index cf698d2..1ac240c 100644 --- a/plugins/modules/volume.py +++ b/plugins/modules/volume.py @@ -15,9 +15,13 @@ - Managing volume on PowerStore storage system includes create volume, get details of volume, modify volume attributes, map or unmap volume to host/host group, and delete volume. +- Volume module also supports start or end of a metro configuration for a + volume, clone, refresh and restore a volume. author: - Ambuj Dubey (@AmbujDube) - Manisha Agrawal (@agrawm3) +- Ananthu S Kuttattu (@kuttattz) +- Bhavneet Sharma (@Bhavneet-Sharma) extends_documentation_fragment: - dellemc.powerstore.powerstore options: @@ -122,6 +126,76 @@ - HLU modification is not supported. required: False type: int + clone_volume: + description: + - Details of the volume clone. + type: dict + suboptions: + name: + description: + - Name of the clone set to be created. + type: str + description: + description: + - Description of the clone. + type: str + host: + description: + - Unique identifier or name of the host to be attached to the clone. + type: str + host_group: + description: + - Unique identifier or name of the host group to be attached to the clone. + type: str + logical_unit_number: + description: + - logical unit number when creating a mapped volume. + - If no host_id or host_group_id is specified, logical_unit_number is ignored. + type: int + protection_policy: + description: + - The protection policy of the clone set to be created. + type: str + performance_policy: + description: + - The performance policy of the clone set to be created. + choices: ['high', 'medium', 'low'] + type: str + source_volume: + description: + - Unique identifier or name of the volume to refresh from. + type: str + source_snap: + description: + - Unique identifier or name of the source snapshot that will be used for the restore operation. + type: str + create_backup_snap: + description: + - Indicates whether a backup snapshot of the target volume will be created or not. + type: bool + backup_snap_profile: + description: + - Details of the backup snapshot set to be created. + type: dict + suboptions: + name: + description: + - Name of the backup snapshot set to be created. + - The default name of the volume snapshot is the date and time when the snapshot is taken. + type: str + description: + description: + - Description of the backup snapshot set. + type: str + performance_policy: + description: + - Performance policy assigned to the snapshot. + choices: ['high', 'medium', 'low'] + type: str + expiration_timestamp: + description: + - Time after which the snapshot set can be auto-purged. + type: str state: description: - Define whether the volume should exist or not. @@ -130,6 +204,34 @@ required: true choices: [absent, present] type: str + remote_system: + description: + - The remote system to which metro relationship will be established. + - The remote system must support metro volume. + - This is mandatory while configuring a metro volume. + - To represent remote system, both name and ID are interchangeable. + - This parameter is added in PowerStore version 3.0.0.0. + required: False + type: str + remote_appliance_id: + description: + - A remote system appliance ID to which volume will be assigned. + - This parameter is added in PowerStore version 3.0.0.0. + required: False + type: str + end_metro_config: + description: + - Whether to end the metro session from a volume. + - This is mandatory for end metro configuration operation. + required: False + type: bool + default: False + delete_remote_volume: + description: + - Whether to delete the remote volume during removal of metro session. + - This is parameter is added in the PowerStore version 3.0.0.0. + required: False + type: bool notes: - To create a new volume, vol_name and size is required. cap_unit, @@ -141,22 +243,13 @@ deleted. - A volume that is attached to a host/host group, or that is part of a volume group cannot be deleted. +- If volume in metro session, volume can only be modified, refreshed and + restored when session is in the pause state. - The Check_mode is not supported. ''' EXAMPLES = r''' -- name: Create stand-alone volume - dellemc.powerstore.volume: - array_ip: "{{array_ip}}" - verifycert: "{{verifycert}}" - user: "{{user}}" - password: "{{password}}" - vol_name: "{{vol_name}}" - size: 1 - cap_unit: "{{cap_unit}}" - state: 'present' - -- name: Create stand-alone volume with performance and protection policy +- name: Create volume dellemc.powerstore.volume: array_ip: "{{array_ip}}" verifycert: "{{verifycert}}" @@ -169,96 +262,114 @@ description: 'Description' performance_policy: 'low' protection_policy: 'protection_policy_name' + vg_name: "{{vg_name}}" + mapping_state: 'mapped' + host: "{{host_name}}" -- name: Create volume and assign to a volume group +- name: Get volume details using ID dellemc.powerstore.volume: array_ip: "{{array_ip}}" verifycert: "{{verifycert}}" user: "{{user}}" password: "{{password}}" - vol_name: "{{vol_name}}" - vg_name: "{{vg_name}}" - size: 1 - cap_unit: "{{cap_unit}}" - state: 'present' + vol_id: "{{result.volume_details.id}}" + state: "present" -- name: Create volume and map it to a host +- name: Modify volume size, name, description, protection and performance policy dellemc.powerstore.volume: array_ip: "{{array_ip}}" verifycert: "{{verifycert}}" user: "{{user}}" password: "{{password}}" + new_name: "{{new_name}}" vol_name: "{{vol_name}}" - size: 1 - cap_unit: "{{cap_unit}}" - mapping_state: 'mapped' - host: "{{host_name}}" - state: 'present' + state: "present" + size: 2 + performance_policy: 'high' + description: 'new description' + protection_policy: '' -- name: Get volume details using ID +- name: Map volume to a host with HLU dellemc.powerstore.volume: array_ip: "{{array_ip}}" verifycert: "{{verifycert}}" user: "{{user}}" password: "{{password}}" - vol_id: "{{result.volume_details.id}}" - state: "present" + vol_name: "{{vol_name}}" + state: 'present' + mapping_state: 'mapped' + host: 'host1' + hlu: 12 -- name: Get volume details using name +- name: Clone a volume dellemc.powerstore.volume: array_ip: "{{array_ip}}" verifycert: "{{verifycert}}" user: "{{user}}" password: "{{password}}" vol_name: "{{vol_name}}" + clone_volume: + name: 'test_name' + description: 'test description' + host: 'test_host' + host_group: 'test_host_group' + logical_unit_number: 1 + protection_policy: 'TEST_PP' + performance_policy: 'low' state: "present" -- name: Modify volume size, name, description and performance policy +- name: Refresh a volume dellemc.powerstore.volume: array_ip: "{{array_ip}}" verifycert: "{{verifycert}}" user: "{{user}}" password: "{{password}}" - new_name: "{{new_name}}" vol_name: "{{vol_name}}" + source_volume_name: 'test1' + create_backup_snap: true + backup_snap_profile: + name: 'refresh_backup_snap' + description: 'test refresh_backup_snap' + expiration_timestamp: '2022-12-23T01:20:00Z' + performance_policy: 'low' state: "present" - size: 2 - performance_policy: 'high' - description: 'new description' -- name: Remove protection policy from Volume +- name: Restore a volume dellemc.powerstore.volume: array_ip: "{{array_ip}}" verifycert: "{{verifycert}}" user: "{{user}}" password: "{{password}}" - new_name: "{{new_name}}" vol_name: "{{vol_name}}" + source_snap: 'refresh_backup_snap' + create_backup_snap: true + backup_snap_profile: + name: 'restore_snap_2' + description: 'test backup snap' + expiration_timestamp: '2022-12-23T01:20:00Z' + performance_policy: 'low' state: "present" - protection_policy: "" -- name: Map volume to a host with HLU +- name: Configure a metro volume dellemc.powerstore.volume: array_ip: "{{array_ip}}" verifycert: "{{verifycert}}" user: "{{user}}" password: "{{password}}" vol_name: "{{vol_name}}" - state: 'present' - mapping_state: 'mapped' - host: 'host1' - hlu: 12 + remote_system: "remote-D123" + state: "present" -- name: Map volume to a host without HLU +- name: End a metro volume configuration dellemc.powerstore.volume: array_ip: "{{array_ip}}" verifycert: "{{verifycert}}" user: "{{user}}" password: "{{password}}" vol_name: "{{vol_name}}" - state: 'present' - mapping_state: 'mapped' - host: 'host2' + end_metro_config: True + delete_remote_volume: True + state: "present" - name: Delete volume dellemc.powerstore.volume: @@ -277,7 +388,21 @@ returned: always type: bool sample: "false" - +is_volume_cloned: + description: Whether or not the clone of volume is created. + returned: always + type: bool + sample: "false" +is_volume_refreshed: + description: Whether or not the volume is refreshed. + returned: always + type: bool + sample: "false" +is_volume_restored: + description: Whether or not the volume is restored. + returned: always + type: bool + sample: "false" volume_details: description: Details of the volume. returned: When volume exists @@ -301,6 +426,16 @@ protection_policy_id: description: The protection policy of the volume. type: str + snapshots: + description: List of snapshot associated with the volume. + type: complex + contains: + id: + description: The system generated ID given to the snapshot. + type: str + name: + description: Name of the snapshot. + type: str volume_groups: description: The volume group details of the volume. type: complex @@ -364,6 +499,10 @@ description: This attribute shows which node will be advertised as the optimized IO path to the volume. type: str + metro_replication_session_id: + description: The ID of the metro replication session assigned to + volume. + type: str mapped_volumes: description: This is the inverse of the resource type host_volume_mapping association. @@ -416,6 +555,12 @@ "id": "4bbb6333-59e4-489c-9015-c618d3e8384b", "name": "sample_protection_policy" }, + "snapshots": [ + { + "id": "2a07be43-xxxx-4fd0-xxxx-18eaa4081bd9", + "name": "sample_snap_2" + } + ], "protection_policy_id": 4bbb6333-59e4-489c-9015-c618d3e8384b, "size": 1073741824, "state": "Ready", @@ -443,7 +588,7 @@ VERSION_ERROR = py4ps_version['unsupported_version_message'] # Application type -APPLICATION_TYPE = 'Ansible/1.7.0' +APPLICATION_TYPE = 'Ansible/1.8.0' class PowerStoreVolume(object): @@ -480,13 +625,14 @@ def __init__(self): self.conn = utils.get_powerstore_connection( self.module.params, application_type=APPLICATION_TYPE) self.provisioning = self.conn.provisioning + self.protection = self.conn.protection self.performance_policy_dict = { 'low': 'default_low', 'medium': 'default_medium', 'high': 'default_high' } - LOG.info('Got Py4Ps instance for provisioning on PowerStore %s', - self.conn) + LOG.info('Got Py4Ps instance for provisioning and protection on ' + 'PowerStore %s', self.conn) def get_volume(self, vol_id=None, vol_name=None): """Get volume details""" @@ -694,6 +840,262 @@ def delete_volume(self, volume): LOG.error(error_msg) self.module.fail_json(msg=error_msg, **utils.failure_codes(e)) + def validate_clone_details(self, clone_details): + """ + Validate clone details + :param clone_details: Clone details. + :return: Validated clone details. + """ + clone_details['performance_policy_id'] = None + clone_details['protection_policy_id'] = None + if clone_details['performance_policy'] is not None: + clone_details['performance_policy_id'] = self.get_performance_policy(clone_details['performance_policy']) + if clone_details['protection_policy'] is not None: + clone_details['protection_policy_id'] = self.get_protection_policy_id_by_name(clone_details['protection_policy']) + clone_details['host_id'] = None + clone_details['host_group_id'] = None + if clone_details['host'] is not None: + clone_details['host_id'] = self.get_host_id_by_name(clone_details['host']) + if clone_details['host_group'] is not None: + clone_details['host_group_id'] = self.get_host_group_id_by_name(clone_details['host_group']) + if clone_details['host_id'] is None and clone_details['host_group_id'] is None and clone_details['logical_unit_number'] is not None: + errormsg = "Either of host identifier or host group identifier is required along with logical_unit_number." + LOG.error(errormsg) + self.module.fail_json(msg=errormsg) + return clone_details + + def clone_volume(self, vol_id, clone_details): + """ + Clone volume + :param vol_id: Unique volume identifier. + :param clone_details: Clone details. + :return: True + """ + try: + LOG.info("Cloning volume") + vol_details = self.get_volume(vol_name=clone_details['name']) + if vol_details: + return False + clone_details = self.validate_clone_details(clone_details) + clone_payload = { + 'volume_id': vol_id, + 'name': clone_details['name'], + 'description': clone_details['description'], + 'host_id': clone_details['host_id'], + 'host_group_id': clone_details['host_group_id'], + 'logical_unit_number': clone_details['logical_unit_number'], + 'protection_policy_id': clone_details['protection_policy_id'], + 'performance_policy_id': clone_details['performance_policy_id'] + } + clone_result = self.provisioning.clone_volume(**clone_payload) + LOG.debug(clone_result) + return True + except Exception as e: + errormsg = "Cloning volume %s failed with error %s" % (vol_id, str(e)) + LOG.error(errormsg) + self.module.fail_json(msg=errormsg, **utils.failure_codes(e)) + + def get_volume_snapshots(self, vol_id, snap_name_or_id=None, all_snapshots=False): + """ + Get volume snapshots + :param vol_id: Unique volume identifier. + :param snap_name_or_id: Existing snapshot name or id + :param all_snapshots: Whether to retrieve all snapshots or not + :return: Retrieve all snapshots of volume or given snapshot + """ + try: + LOG.info("Getting volume snapshots") + vol_snapshots_list = self.provisioning.get_volumes(filter_dict={'type': 'eq.Snapshot', 'protection_data->>family_id': 'eq.' + vol_id}) + LOG.debug(vol_snapshots_list) + if all_snapshots: + return True, vol_snapshots_list + for snap in vol_snapshots_list: + if snap['name'] == snap_name_or_id or snap['id'] == snap_name_or_id: + return True, snap + return False, None + except Exception as e: + errormsg = "Getting volume snapshots failed with error %s" % (str(e)) + LOG.error(errormsg) + self.module.fail_json(msg=errormsg, **utils.failure_codes(e)) + + def validate_refresh_op_params(self, data): + """ + Validate refresh details + :param data: Refresh details. + :return: Validated refresh data. + """ + if utils.name_or_id(data['source_volume']) == "NAME": + vol_details = self.get_volume(vol_name=data['source_volume']) + else: + vol_details = self.get_volume(vol_id=data['source_volume']) + if vol_details is None: + errormsg = "Source volume does not exist." + LOG.error(errormsg) + self.module.fail_json(msg=errormsg) + if vol_details['protection_data']['family_id'] != data['volume_family_id']: + errormsg = "Source volume does not belong to the family of the current volume." + LOG.error(errormsg) + self.module.fail_json(msg=errormsg) + data['source_volume_id'] = vol_details['id'] + + return data + + def validate_restore_op_params(self, data): + """ + Validate restore details + :param data: Restore details. + :return: Validated restore data. + """ + exists, snap_details = self.get_volume_snapshots(data['volume_family_id'], snap_name_or_id=data['source_snap']) + if not exists: + errormsg = "source snapshot does not exists." + LOG.error(errormsg) + self.module.fail_json(msg=errormsg) + data['source_snap_id'] = snap_details['id'] + + return data + + def validate_refresh_restore_details(self, operation, data): + """ + Validate refresh and restore details + :param data: Refresh details or Restore details. + :return: Validated data. + """ + if operation == 'refresh': + self.validate_refresh_op_params(data) + if operation == 'restore': + self.validate_restore_op_params(data) + if data['backup_snap_profile'] is not None: + if not data['create_backup_snap']: + errormsg = "Specify create_back_snap as True to set backup_snap_profile." + LOG.error(errormsg) + self.module.fail_json(msg=errormsg) + if data['backup_snap_profile']['performance_policy'] is not None: + data['backup_snap_profile']['performance_policy_id'] = self.get_performance_policy(data['backup_snap_profile']['performance_policy']) + if data['backup_snap_profile']['expiration_timestamp'] is not None and \ + not utils.validate_timestamp(data['backup_snap_profile']['expiration_timestamp']): + errormsg = 'Incorrect date format, should be YYYY-MM-DDTHH:MM:SSZ' + LOG.error(errormsg) + self.module.fail_json(msg=errormsg) + return data + + def refresh_volume(self, volume, refresh_details): + """ + Refresh volume + :param volume: Volume details. + :param refresh_details: Refresh details. + :return: True + """ + try: + LOG.info("Refreshing volume") + refresh_details['volume_family_id'] = volume['protection_data']['family_id'] + vol_id = volume['id'] + if 'backup_snap_profile' in refresh_details and refresh_details['backup_snap_profile'] \ + and refresh_details['backup_snap_profile']['name'] is not None: + exists, snap_details = self.get_volume_snapshots(refresh_details['volume_family_id'], + snap_name_or_id=refresh_details['backup_snap_profile']['name']) + LOG.debug(snap_details) + if exists: + return False + refresh_details = self.validate_refresh_restore_details('refresh', refresh_details) + refresh_payload = { + 'volume_id': vol_id, + 'volume_id_to_refresh_from': refresh_details['source_volume_id'], + 'create_backup_snap': refresh_details['create_backup_snap'] + } + refresh_payload.update(get_backupsnap_profile_details(refresh_details)) + refresh_result = self.provisioning.refresh_volume(**refresh_payload) + LOG.debug(refresh_result) + return True + except Exception as e: + errormsg = "Refreshing volume %s failed with error %s" % (vol_id, str(e)) + LOG.error(errormsg) + self.module.fail_json(msg=errormsg, **utils.failure_codes(e)) + + def restore_volume(self, volume, restore_details): + """ + Restore volume + :param vol_id: Unique volume identifier. + :param restore_volume: Restore details. + :return: True + """ + try: + LOG.info("Restoring volume") + restore_details['volume_family_id'] = volume['protection_data']['family_id'] + vol_id = volume['id'] + if 'backup_snap_profile' in restore_details and restore_details['backup_snap_profile'] and \ + restore_details['backup_snap_profile']['name'] is not None: + exists, snap_details = self.get_volume_snapshots(restore_details['volume_family_id'], + snap_name_or_id=restore_details['backup_snap_profile']['name']) + LOG.debug(snap_details) + if exists: + return False + restore_details = self.validate_refresh_restore_details('restore', restore_details) + restore_payload = { + 'volume_id': vol_id, + 'snap_id_to_restore_from': restore_details['source_snap_id'], + 'create_backup_snap': restore_details['create_backup_snap'] + } + restore_payload.update(get_backupsnap_profile_details(restore_details)) + restore_result = self.provisioning.restore_volume(**restore_payload) + LOG.debug(restore_result) + return True + except Exception as e: + errormsg = "Restoring volume %s failed with error %s" % (vol_id, str(e)) + LOG.error(errormsg) + self.module.fail_json(msg=errormsg, **utils.failure_codes(e)) + + def configure_metro_volume(self, volume, remote_system, + remote_appliance_id=None): + """Configure a metro volume + :param volume: Volume details + :type volume: dict + :param remote_system: Remote system with which metro relationship will + be established + :type remote_system: str + :param remote_appliance_id: A specific remote system appliance to which + volume will be configured + :type remote_appliance_id: str + :return: True if metro configuration is successful + :rtype: bool + """ + try: + msg = "Establish a metro configuration for volume {0} to remote" \ + " system {1}".format(volume['name'], remote_system) + LOG.info(msg) + self.provisioning.configure_metro_volume( + volume_id=volume['id'], remote_system_id=remote_system, + remote_appliance_id=remote_appliance_id) + return True + except Exception as e: + err_msg = "Failed to configure metro for volume {0} with error" \ + " {1}".format(volume['name'], str(e)) + LOG.error(err_msg) + self.module.fail_json(msg=err_msg, **utils.failure_codes(e)) + + def end_metro_volume(self, volume, delete_remote_volume=None): + """Remove the metro configuration for volume + :param volume: Details of the volume + :type volume: dict + :param delete_remote_volume: Whether to delete the remote volume + during metro removal + :type delete_remote_volume: bool + return: True if removal of metro config is successful + :rtype: bool + """ + try: + msg = "Removing the metro configuration for volume %s" % volume['name'] + LOG.info(msg) + self.provisioning.end_volume_metro_config( + volume_id=volume['id'], + delete_remote_volume=delete_remote_volume) + return True + except Exception as e: + err_msg = "Failed to remove the metro configuration for volume " \ + "{0} with error {1}".format(volume['name'], str(e)) + LOG.error(err_msg) + self.module.fail_json(msg=err_msg, **utils.failure_codes(e)) + def perform_module_operation(self): """ Perform different actions on volume based on user parameters @@ -717,8 +1119,22 @@ def perform_module_operation(self): hostgroup = self.get_host_group_id_by_name( self.module.params['hostgroup']) hlu = self.module.params['hlu'] + clone_volume = self.module.params['clone_volume'] + source_volume = self.module.params['source_volume'] + source_snap = self.module.params['source_snap'] + create_backup_snap = self.module.params['create_backup_snap'] + backup_snap_profile = self.module.params['backup_snap_profile'] + remote_system = self.get_remote_system_id( + self.module.params['remote_system']) + remote_appliance_id = self.get_remote_appliance_id( + remote_system, self.module.params['remote_appliance_id']) + end_metro_config = self.module.params['end_metro_config'] + delete_remote_volume = self.module.params['delete_remote_volume'] changed = False + is_volume_refreshed = False + is_volume_cloned = False + is_volume_restored = False volume = self.get_volume(vol_id, vol_name) # fetching the volume id from volume details if volume is not None: @@ -867,6 +1283,46 @@ def perform_module_operation(self): changed = self.map_unmap_volume_to_hostgroup( volume, hostgroup, mapping_state) or changed + if state == 'present' and clone_volume is not None: + changed = self.clone_volume(vol_id, clone_volume) + is_volume_cloned = changed + + if state == 'present' and source_volume is not None: + refresh_details = { + 'source_volume': source_volume, + 'create_backup_snap': create_backup_snap, + 'backup_snap_profile': backup_snap_profile + } + changed = self.refresh_volume(volume, refresh_details) + is_volume_refreshed = changed + + if state == 'present' and source_snap is not None: + restore_details = { + 'source_snap': source_snap, + 'create_backup_snap': create_backup_snap, + 'backup_snap_profile': backup_snap_profile + } + changed = self.restore_volume(volume, restore_details) + is_volume_restored = changed + + if state == "present" and volume and remote_system is not None: + if 'metro_replication_session_id' in volume \ + and volume['metro_replication_session_id'] is not None: + session_id = volume['metro_replication_session_id'] + is_metro_exists = self.is_metro_configured( + session_id, remote_system) + changed = is_metro_exists + elif 'metro_replication_session_id' in volume and \ + volume['metro_replication_session_id'] is None: + changed = self.configure_metro_volume( + volume, remote_system, remote_appliance_id) + + if state == "present" and volume and end_metro_config is not None \ + and end_metro_config and \ + 'metro_replication_session_id' in volume and \ + volume['metro_replication_session_id'] is not None: + changed = self.end_metro_volume(volume, delete_remote_volume) + if state == 'absent' and volume: LOG.info('Deleting volume %s ', volume['name']) changed = self.delete_volume(volume) or changed @@ -876,10 +1332,33 @@ def perform_module_operation(self): ''' self.result["changed"] = changed + self.result["is_volume_cloned"] = is_volume_cloned + self.result["is_volume_refreshed"] = is_volume_refreshed + self.result["is_volume_restored"] = is_volume_restored if state == 'present': self.result["volume_details"] = self.get_volume(vol_id=vol_id) + if self.result["volume_details"]: + self.result["volume_details"].update( + snapshots=self.get_volume_snapshots(self.result["volume_details"]['id'], all_snapshots=True)[1]) self.module.exit_json(**self.result) + def is_metro_configured(self, session_id, remote_system): + """Check whether metro is configured for volume""" + try: + session_details = self.protection.\ + get_replication_session_details(session_id=session_id) + if session_details['remote_system_id'] == remote_system: + return False + msg = "Metro session is already configured for the volume." + LOG.error(msg) + self.module.fail_json(msg=msg) + + except Exception as e: + error_msg = "Get metro replication session {0} details failed " \ + "with error: {1}".format(session_id, str(e)) + LOG.error(error_msg) + self.module.fail_json(msg=error_msg, **utils.failure_codes(e)) + def get_volume_id_by_name(self, volume_name): try: volume_info = self.provisioning.get_volume_by_name(volume_name) @@ -1019,6 +1498,60 @@ def get_host_group_id_by_name(self, host_group_name): LOG.error(error_msg) self.module.fail_json(msg=error_msg, **utils.failure_codes(e)) + def get_remote_system_id(self, remote_system): + """ Fetch the remote system ID.""" + try: + if remote_system is None: + return None + elif utils.name_or_id(remote_system) == "NAME": + remote_system_info = self.protection.\ + get_remote_system_by_name(name=remote_system) + + if remote_system_info and len(remote_system_info) == 1: + return remote_system_info[0]['id'] + elif remote_system_info and len(remote_system_info) > 1: + err_msg = "Multiple remote system found with same name." + LOG.error(err_msg) + self.module.fail_json(msg=err_msg) + + elif self.protection.get_remote_system_details( + remote_system_id=remote_system): + return remote_system + er_msg = "Remote system %s not found." % remote_system + LOG.error(er_msg) + self.module.fail_json(msg=er_msg) + + except Exception as e: + error_msg = "Fetching remote system {0} failed with error " \ + "{1}".format(remote_system, str(e)) + LOG.error(error_msg) + self.module.fail_json(msg=error_msg, **utils.failure_codes(e)) + + def get_remote_appliance_id(self, remote_system, remote_appliance_id): + """ Fetch the remote appliance ID.""" + try: + if remote_appliance_id is None: + return None + else: + remote_app_details = self.protection.\ + get_remote_system_appliance_details(remote_system_id=remote_system) + + if remote_app_details is not None: + for apps in remote_app_details['remote_appliances']: + if apps['id'] == remote_appliance_id: + return remote_appliance_id + + er_msg = "No remote appliance {0} found in remote system {1}.".\ + format(remote_appliance_id, remote_system) + LOG.error(er_msg) + self.module.fail_json(msg=er_msg) + + except Exception as e: + error_msg = "Fetching remote appliance {0} failed with error " \ + "{1}".format(remote_system, str(e)) + LOG.error(error_msg) + self.module.fail_json(msg=error_msg, **utils.failure_codes(e)) + def get_performance_policy(self, performance_policy): if performance_policy is None: return None @@ -1093,6 +1626,32 @@ def check_for_hlu_modification(volume, hlu, host=None, hostgroup=None): return True, "" +def get_backup_profile_parameters(): + """ + This method provide parameter required for the backup_profile + """ + return dict(type='dict', options=dict(name=dict(type='str'), + description=dict(type='str'), + performance_policy=dict(required=False, choices=['high', 'medium', 'low'], type='str'), + expiration_timestamp=dict(type='str'))) + + +def get_backupsnap_profile_details(data): + """ + Get backupsnap profile details + :param data: Refresh details or Restore details. + :return: backupsnap profil edetails. + """ + backup_snap_profile = {} + if data['backup_snap_profile']: + backup_snap_profile['backup_snap_name'] = data['backup_snap_profile']['name'] + backup_snap_profile['backup_snap_description'] = data['backup_snap_profile']['description'] + backup_snap_profile['backup_snap_expiration_timestamp'] = data['backup_snap_profile']['expiration_timestamp'] + if 'performance_policy_id' in data['backup_snap_profile']: + backup_snap_profile['backup_snap_performance_policy_id'] = data['backup_snap_profile']['performance_policy_id'] + return backup_snap_profile + + def get_powerstore_volume_parameters(): """ This method provide parameter required for the ansible volume @@ -1117,7 +1676,26 @@ def get_powerstore_volume_parameters(): type='str'), host=dict(required=False, type='str'), hostgroup=dict(required=False, type='str'), - hlu=dict(required=False, type='int') + hlu=dict(required=False, type='int'), + clone_volume=dict( + type='dict', options=dict( + name=dict(type='str'), + description=dict(type='str'), + host=dict(type='str'), + host_group=dict(type='str'), + logical_unit_number=dict(type='int'), + protection_policy=dict(type='str'), + performance_policy=dict(required=False, choices=['high', 'medium', 'low'], type='str') + ) + ), + source_volume=dict(type='str'), + source_snap=dict(type='str'), + create_backup_snap=dict(type='bool'), + backup_snap_profile=get_backup_profile_parameters(), + remote_system=dict(required=False, type='str'), + remote_appliance_id=dict(required=False, type='str'), + end_metro_config=dict(required=False, type='bool', default=False), + delete_remote_volume=dict(required=False, type='bool') ) diff --git a/plugins/modules/volumegroup.py b/plugins/modules/volumegroup.py index 9999651..ce8836f 100644 --- a/plugins/modules/volumegroup.py +++ b/plugins/modules/volumegroup.py @@ -96,7 +96,6 @@ description: - Name of snapshot set to be created. type: str - required: True description: description: - Description of the snapshot set. @@ -403,7 +402,7 @@ VERSION_ERROR = py4ps_version['unsupported_version_message'] # Application type -APPLICATION_TYPE = 'Ansible/1.7.0' +APPLICATION_TYPE = 'Ansible/1.8.0' class PowerStoreVolumeGroup(object): @@ -1067,7 +1066,7 @@ def get_powerstore_volume_group_parameters(): create_backup_snap=dict(type='bool'), backup_snap_profile=dict( type='dict', options=dict( - name=dict(type='str', required=True), + name=dict(type='str'), description=dict(type='str'), expiration_timestamp=dict(type='str') ) diff --git a/tests/unit/plugins/module_utils/mock_api_exception.py b/tests/unit/plugins/module_utils/mock_api_exception.py index 6b85620..8019744 100644 --- a/tests/unit/plugins/module_utils/mock_api_exception.py +++ b/tests/unit/plugins/module_utils/mock_api_exception.py @@ -10,5 +10,7 @@ class MockApiException(Exception): + HTTP_ERR = "1" + err_code = "1" + status_code = "500" body = "PyPowerStore Error message" - status = "500" diff --git a/tests/unit/plugins/module_utils/mock_host_api.py b/tests/unit/plugins/module_utils/mock_host_api.py index 37159f4..799daed 100644 --- a/tests/unit/plugins/module_utils/mock_host_api.py +++ b/tests/unit/plugins/module_utils/mock_host_api.py @@ -13,6 +13,7 @@ class MockHostApi: MODULE_PATH = 'ansible_collections.dellemc.powerstore.plugins.modules.host.PowerStoreHost' MODULE_UTILS_PATH = 'ansible_collections.dellemc.powerstore.plugins.module_utils.storage.dell.utils' iscsi_initiator = "iqn.1998-01.com.vmware:losat106-0eab2afe" + HOST_CONN_1 = "Metro_Optimize_Both" HOST_COMMON_ARGS = { 'array_ip': '**.***.**.***', 'host_id': None, @@ -22,7 +23,8 @@ class MockHostApi: 'detailed_initiators': None, 'initiator_state': None, 'new_name': None, - 'os_type': None + 'os_type': None, + 'host_connectivity': None } HOST_NAME_1 = "Sample_host_1" HOST_DETAILS = { @@ -41,7 +43,8 @@ class MockHostApi: "mapped_hosts": [], "name": "Sample_host_1", "os_type": "ESXi", - "os_type_l10n": "ESXi" + "os_type_l10n": "ESXi", + "host_connectivity": "Local_Only" } HOST_DETAILS_2 = { diff --git a/tests/unit/plugins/module_utils/mock_hostgroup_api.py b/tests/unit/plugins/module_utils/mock_hostgroup_api.py index e6b023e..0c2caf8 100644 --- a/tests/unit/plugins/module_utils/mock_hostgroup_api.py +++ b/tests/unit/plugins/module_utils/mock_hostgroup_api.py @@ -13,6 +13,7 @@ class MockHostGroupApi: MODULE_PATH = 'ansible_collections.dellemc.powerstore.plugins.modules.hostgroup.PowerStoreHostgroup' MODULE_UTILS_PATH = 'ansible_collections.dellemc.powerstore.plugins.module_utils.storage.dell.utils' iscsi_initiator = "iqn.1998-01.com.vmware:losatxxx-0xxxxxfe" + HOST_CONNECTIVITY = "Metro_Optimize_Both" HOSTGROUP_COMMON_ARGS = { 'array_ip': '**.***.**.***', 'hostgroup_id': None, @@ -21,6 +22,7 @@ class MockHostGroupApi: 'state': None, 'host_state': None, 'new_name': None, + 'host_connectivity': None } HOSTGROUP_NAME_1 = "Sample_hostgroup_1" @@ -44,7 +46,8 @@ class MockHostGroupApi: } ], "id": "d21beab9-15fa-4cee-9651-e3b740ceaa7c", - "name": "Sample_hostgroup_1" + "name": "Sample_hostgroup_1", + "host_connectivity": "Local_Only" } HOSTGROUP_DETAILS_BY_NAME = [{ diff --git a/tests/unit/plugins/module_utils/mock_replicationsession_api.py b/tests/unit/plugins/module_utils/mock_replicationsession_api.py index c2fe356..dd97762 100644 --- a/tests/unit/plugins/module_utils/mock_replicationsession_api.py +++ b/tests/unit/plugins/module_utils/mock_replicationsession_api.py @@ -14,6 +14,7 @@ class MockReplicationSessionApi: MODULE_UTILS_PATH = 'ansible_collections.dellemc.powerstore.plugins.module_utils.storage.dell.utils' local_time = "2022-01-06T06:55:01.870946+00:00" vg = "Volume Group" + ID = "b05b5108-26b6-4567-a1d8-1c7795b2e6bc" REPLICATION_SESSION_COMMON_ARGS = { 'array_ip': '**.***.**.***', @@ -22,13 +23,14 @@ class MockReplicationSessionApi: 'nas_server': None, 'filesystem': None, 'session_id': None, - 'session_state': None + 'session_state': None, + 'role': None } REPLICATION_SESSION_DETAILS = [ { "estimated_completion_timestamp": None, - "id": "b05b5108-26b6-4567-a1d8-1c7795b2e6bc", + "id": ID, "last_sync_timestamp": local_time, "local_resource_id": "634e4b95-e7bd-49e7-957b-6dc932642464", "local_resource_name": "sample_volume", @@ -99,7 +101,7 @@ class MockReplicationSessionApi: REPLICATION_SESSION_DETAILS_SRC = [ { "estimated_completion_timestamp": None, - "id": "b05b5108-26b6-4567-a1d8-1c7795b2e6bc", + "id": ID, "last_sync_timestamp": local_time, "local_resource_id": "634e4b95-e7bd-49e7-957b-6dc932642464", "local_resource_name": "sample_volume", @@ -170,7 +172,7 @@ class MockReplicationSessionApi: REPLICATION_SESSION_DETAILS_VG = [ { "estimated_completion_timestamp": None, - "id": "b05b5108-26b6-4567-a1d8-1c7795b2e6bc", + "id": ID, "last_sync_timestamp": local_time, "local_resource_id": "634e4b95-e7bd-49e7-957b-6dc932642464", "local_resource_name": "sample_volume_group", @@ -303,7 +305,7 @@ class MockReplicationSessionApi: ] SESSION_IDS_VOLUME = [ - {'id': "b05b5108-26b6-4567-a1d8-1c7795b2e6bc"} + {'id': ID} ] SESSION_IDS_VOLUME_GROUP = [ @@ -494,7 +496,7 @@ class MockReplicationSessionApi: REPLICATION_SESSION_DETAILS_SYNC = [ { "estimated_completion_timestamp": None, - "id": "b05b5108-26b6-4567-a1d8-1c7795b2e6bc", + "id": ID, "last_sync_timestamp": local_time, "local_resource_id": "634e4b95-e7bd-49e7-957b-6dc932642464", "local_resource_name": "sample_volume", @@ -531,7 +533,7 @@ class MockReplicationSessionApi: REPLICATION_SESSION_DETAILS_SYNC_SRC = [ { "estimated_completion_timestamp": None, - "id": "b05b5108-26b6-4567-a1d8-1c7795b2e6bc", + "id": ID, "last_sync_timestamp": local_time, "local_resource_id": "634e4b95-e7bd-49e7-957b-6dc932642464", "local_resource_name": "sample_volume", @@ -568,7 +570,7 @@ class MockReplicationSessionApi: REPLICATION_SESSION_DETAILS_PAUSED = [ { "estimated_completion_timestamp": None, - "id": "b05b5108-26b6-4567-a1d8-1c7795b2e6bc", + "id": ID, "last_sync_timestamp": local_time, "local_resource_id": "634e4b95-e7bd-49e7-957b-6dc932642464", "local_resource_name": "sample_volume", @@ -598,14 +600,53 @@ class MockReplicationSessionApi: "replication_shadow_id": None, "storage_element_type": "volume" } - ] + ], + "type": "Asynchronous", + } + ] + + METRO_SESSION_DETAILS_PAUSED = [ + { + "estimated_completion_timestamp": None, + "id": ID, + "last_sync_timestamp": local_time, + "local_resource_id": "634e4b95-e7bd-49e7-957b-6dc932642464", + "local_resource_name": "sample_volume", + "migration_session": None, + "progress_percentage": None, + "remote_resource_id": "c1535ab7-e874-42eb-8692-7aa12aa4346e", + "remote_system": { + "id": "b5f62edd-f7aa-483a-afaa-4364ab6fcd3a", + "name": "WN-D8989" + }, + "remote_system_id": "b5f62edd-f7aa-483a-afaa-4364ab6fcd3a", + "replication_rule": { + "id": "05777d33-b2fb-4e65-8202-208ff4fe5878", + "name": "sample_replication_rule" + }, + "replication_rule_id": "05777d33-b2fb-4e65-8202-208ff4fe5878", + "resource_type": "Volume", + "resource_type_l10n": "Volume", + "role": "Source", + "role_l10n": "Source", + "state": "paused", + "state_l10n": "paused", + "storage_element_pairs": [ + { + "local_storage_element_id": "b0acb8de-446b-48e4-82ae-89ed05a35d01", + "remote_storage_element_id": "c1535ab7-e874-42eb-8692-7aa12aa4346e", + "replication_shadow_id": None, + "storage_element_type": "volume" + } + ], + "type": "Metro_Active_Active", } ] REPLICATION_SESSION_DETAILS_PAUSED_DES = [ { "estimated_completion_timestamp": None, - "id": "b05b5108-26b6-4567-a1d8-1c7795b2e6bc", + "id": ID, "last_sync_timestamp": local_time, "local_resource_id": "634e4b95-e7bd-49e7-957b-6dc932642464", "local_resource_name": "sample_volume", @@ -635,14 +676,15 @@ class MockReplicationSessionApi: "replication_shadow_id": None, "storage_element_type": "volume" } - ] + ], + "type": "Asynchronous", } ] REPLICATION_SESSION_DETAILS_FAILING_OVER = [ { "estimated_completion_timestamp": None, - "id": "b05b5108-26b6-4567-a1d8-1c7795b2e6bc", + "id": ID, "last_sync_timestamp": local_time, "local_resource_id": "634e4b95-e7bd-49e7-957b-6dc932642464", "local_resource_name": "sample_volume", @@ -679,7 +721,7 @@ class MockReplicationSessionApi: REPLICATION_SESSION_DETAILS_FAILED_OVER = [ { "estimated_completion_timestamp": None, - "id": "b05b5108-26b6-4567-a1d8-1c7795b2e6bc", + "id": ID, "last_sync_timestamp": local_time, "local_resource_id": "634e4b95-e7bd-49e7-957b-6dc932642464", "local_resource_name": "sample_volume", @@ -716,7 +758,7 @@ class MockReplicationSessionApi: REPLICATION_SESSION_DETAILS_FAILED_OVER_DES = [ { "estimated_completion_timestamp": None, - "id": "b05b5108-26b6-4567-a1d8-1c7795b2e6bc", + "id": ID, "last_sync_timestamp": local_time, "local_resource_id": "634e4b95-e7bd-49e7-957b-6dc932642464", "local_resource_name": "sample_volume", @@ -753,7 +795,7 @@ class MockReplicationSessionApi: REPLICATION_SESSION_DETAILS_RESUMING = [ { "estimated_completion_timestamp": None, - "id": "b05b5108-26b6-4567-a1d8-1c7795b2e6bc", + "id": ID, "last_sync_timestamp": local_time, "local_resource_id": "634e4b95-e7bd-49e7-957b-6dc932642464", "local_resource_name": "sample_volume", @@ -790,7 +832,7 @@ class MockReplicationSessionApi: REPLICATION_SESSION_DETAILS_SYSTEM_PAUSED = [ { "estimated_completion_timestamp": None, - "id": "b05b5108-26b6-4567-a1d8-1c7795b2e6bc", + "id": ID, "last_sync_timestamp": local_time, "local_resource_id": "634e4b95-e7bd-49e7-957b-6dc932642464", "local_resource_name": "sample_volume", @@ -860,3 +902,7 @@ def paused_to_sync_dest_error_failed_msg(): @staticmethod def volume_not_found_failed_msg(): return "not found" + + @staticmethod + def modify_role_failed_msg(): + return "Modifying the role Metro_Preferred of replication session b05b5108-26b6-4567-a1d8-1c7795b2e6bc failed with error" diff --git a/tests/unit/plugins/module_utils/mock_volume_api.py b/tests/unit/plugins/module_utils/mock_volume_api.py index d795b60..410e2cc 100644 --- a/tests/unit/plugins/module_utils/mock_volume_api.py +++ b/tests/unit/plugins/module_utils/mock_volume_api.py @@ -28,6 +28,15 @@ class MockVolumeApi: 'hostgroup': None, 'mapping_state': None, 'hlu': None, + 'clone_volume': None, + 'source_volume': None, + 'source_snap': None, + 'create_backup_snap': None, + 'backup_snap_profile': None, + 'remote_system': None, + 'remote_appliance_id': None, + 'end_metro_config': None, + 'delete_remote_volume': None, 'state': None } @@ -36,6 +45,13 @@ class MockVolumeApi: NODE_AFFINITY1 = 'System_Select_At_Attach' WWN_1 = 'naa.68ccf09800ac8ab0e2506d99bee29e40' NODE_AFFINITY_2 = 'System Select At Attach' + EXPIRATION_TIMESTAMP = '2022-12-23T01:20:00Z' + PERFORMANCE_POLICY_LOW = 'default_low' + SAMPLE_ADDRESS = "xx.xx.xx.xx" + REMOTE_SYSTEM_ID = "5ccc6333-59f4-4239c-9215-c6181de8384b" + REMOTE_SYSTEM_ID_1 = "24dc6333-59f4-4239c-9205-c6181ea8184b" + REMOTE_SYSTEM_ID_2 = "87dc6677-59a4-4239d-9221-a2524ae9389c" + ID_1 = "434f534e-7009-4e60-8e1e-5cf721ae40df" VG_1 = [{ "description": "Volume group created", @@ -148,6 +164,7 @@ class MockVolumeApi: "name": "sample_protection_policy" }, "protection_policy_id": "4bbb6333-59e4-489c-9015-c618d3e8384b", + "metro_replication_session_id": None, "size": 1073741824, "state": "Ready", "state_l10n": "Ready", @@ -163,6 +180,13 @@ class MockVolumeApi: } ] + VOL1_SNAPSHOT_LIST = [ + { + 'id': 'fd44444-3333-2222-1111-0000000', + 'name': 'refresh_backup_snap_1' + } + ] + MODIFY_VOL_DETAILS1 = [ { "appliance_id": "A1", @@ -225,6 +249,7 @@ class MockVolumeApi: "name": "sample_protection_policy" }, "protection_policy_id": "4bbb6333-59e4-489c-9015-c618d3e8384b", + "metro_replication_session_id": REMOTE_SYSTEM_ID, "size": 1073741824, "state": "Ready", "state_l10n": "Ready", @@ -277,6 +302,7 @@ class MockVolumeApi: }, "protection_policy": None, "protection_policy_id": None, + "metro_replication_session_id": REMOTE_SYSTEM_ID_1, "size": 2147483648, "state": "Ready", "state_l10n": "Ready", @@ -378,6 +404,37 @@ class MockVolumeApi: } ] + REMOTE_SYSTEM_DETAILS = [{ + "id": REMOTE_SYSTEM_ID, + "management_address": SAMPLE_ADDRESS, + "appliance_details": [{ + "appliance_id": "A2" + }], + "name": "remote-system" + }] + + REMOTE_SYSTEM_DETAILS_1 = [ + { + "id": REMOTE_SYSTEM_ID, + "management_address": SAMPLE_ADDRESS, + "appliance_details": [{ + "appliance_id": "A2" + }], + "name": "remote-system" + }, + { + "id": REMOTE_SYSTEM_ID_2, + "management_address": SAMPLE_ADDRESS, + "appliance_details": [{ + "appliance_id": "A2" + }], + "name": "remote-system" + }] + + REP_SESSION_DETAILS = [{ + "remote_system_id": REMOTE_SYSTEM_ID + }] + @staticmethod def get_volume_more_than_one_failed_msg(): return "Multiple volumes by the same name found" @@ -405,3 +462,54 @@ def shrink_volume_failed_msg(): @staticmethod def map_without_mapping_state_failed_msg(): return "Mapping state not provided, mandatory for mapping" + + @staticmethod + def get_fail_msg_for_clone_volume(msg_type=None): + if msg_type == 'exception': + return "Cloning volume %s failed with error " % (MockVolumeApi.VOL_DETAILS1[0]['id']) + elif msg_type == 'log_unit_error': + return "Either of host identifier or host group identifier is required along with logical_unit_number." + + @staticmethod + def get_fail_msg_for_refresh_volume(msg_type=None): + if msg_type == 'exception': + return "Refreshing volume %s failed with error " % (MockVolumeApi.VOL_DETAILS1[0]['id']) + elif msg_type == 'backup_snap_error': + return "Specify create_back_snap as True to set backup_snap_profile." + elif msg_type == 'expiration_timestamp_error': + return 'Incorrect date format, should be YYYY-MM-DDTHH:MM:SSZ' + + @staticmethod + def get_fail_msg_for_restore_volume(msg_type=None): + if msg_type == 'exception': + return "Restoring volume %s failed with error " % (MockVolumeApi.VOL_DETAILS1[0]['id']) + elif msg_type == 'snap_exception': + return "Restoring volume %s failed with error cannot unpack non-iterable NoneType object" % (MockVolumeApi.VOL_DETAILS1[0]['id']) + + @staticmethod + def configure_metro_fail_msg(): + return "Failed to configure metro for volume sample_volume_1" + + @staticmethod + def rep_session_fail_msg(): + return "Get metro replication session %s details failed with error:" % (MockVolumeApi.REMOTE_SYSTEM_ID) + + @staticmethod + def exisiting_metro_session_fail_msg(): + return "Metro session is already configured for the volume" + + @staticmethod + def no_appliance_fail_msg(): + return "No remote appliance A2 found in remote system" + + @staticmethod + def remote_system_fail_msg(): + return "Fetching remote system %s failed with error" % (MockVolumeApi.ID_1) + + @staticmethod + def remote_app_fail_msg(): + return "Fetching remote appliance None failed with error" + + @staticmethod + def end_metro_fail_msg(): + return "Failed to remove the metro configuration for volume sample_volume_2 with error" diff --git a/tests/unit/plugins/modules/test_host.py b/tests/unit/plugins/modules/test_host.py index 9808a98..1b16c97 100644 --- a/tests/unit/plugins/modules/test_host.py +++ b/tests/unit/plugins/modules/test_host.py @@ -91,6 +91,7 @@ def test_create_host(self, host_module_mock): 'chap_single_username': 'chapuserSingle', 'chap_single_password': 'chappasswd12345'}], 'state': 'present', + 'host_connectivity': 'Local_Only', 'initiator_state': 'present-in-host' }) host_module_mock.module.params = self.get_module_args @@ -310,6 +311,7 @@ def test_modify_os_type(self, host_module_mock): self.get_module_args.update({ 'host_id': "4d56e60-fc10-4f51-a698-84a664562f0d", 'os_type': 'Windows', + "host_connectivity": MockHostApi.HOST_CONN_1, 'state': 'present' }) host_module_mock.module.params = self.get_module_args diff --git a/tests/unit/plugins/modules/test_hostgroup.py b/tests/unit/plugins/modules/test_hostgroup.py index ef3d660..b20a63f 100644 --- a/tests/unit/plugins/modules/test_hostgroup.py +++ b/tests/unit/plugins/modules/test_hostgroup.py @@ -298,10 +298,11 @@ def test_remove_host_hostgroup_no_hosts(self, hostgroup_module_mock): hostgroup_module_mock.perform_module_operation() hostgroup_module_mock.conn.provisioning.get_host_group_details.assert_called() - def test_rename_hostgroup(self, hostgroup_module_mock): + def test_modify_hostgroup(self, hostgroup_module_mock): self.get_module_args.update({ 'hostgroup_id': "d21beab9-15fa-4cee-9651-e3b740ceaa7c", 'new_name': "Hostgroup_new_name", + 'host_connectivity': MockHostGroupApi.HOST_CONNECTIVITY, 'state': 'present' }) hostgroup_module_mock.module.params = self.get_module_args diff --git a/tests/unit/plugins/modules/test_replicationsession.py b/tests/unit/plugins/modules/test_replicationsession.py index 2c00c12..cb67ac2 100644 --- a/tests/unit/plugins/modules/test_replicationsession.py +++ b/tests/unit/plugins/modules/test_replicationsession.py @@ -494,3 +494,45 @@ def test_get_replication_session_multi_cluster(self, replicationsession_module_m replicationsession_module_mock.perform_module_operation() assert self.get_module_args['session_id'] == replicationsession_module_mock.module.exit_json.call_args[1]['replication_session_details']['id'] replicationsession_module_mock.conn.protection.get_replication_session_details.assert_called() + + def test_modify_role_replicatio_session(self, replicationsession_module_mock): + self.get_module_args.update({ + 'session_id': "b05b5108-26b6-4567-a1d8-1c7795b2e6bc", + 'role': "Metro_Preferred" + }) + replicationsession_module_mock.module.params = self.get_module_args + replicationsession_module_mock.conn.protection.get_replication_session_details = MagicMock( + return_value=MockReplicationSessionApi.REPLICATION_SESSION_DETAILS[0]) + replicationsession_module_mock.perform_module_operation() + assert replicationsession_module_mock.module.exit_json.call_args[1]['changed'] is True + replicationsession_module_mock.conn.protection.modify_replication_session.assert_called() + + def test_modify_metro_paused_to_sync_response(self, replicationsession_module_mock): + self.get_module_args.update({ + 'session_id': "b05b5108-26b6-4567-a1d8-1c7795b2e6bc", + 'session_state': "synchronizing" + }) + replicationsession_module_mock.module.params = self.get_module_args + replicationsession_module_mock.conn.protection.get_replication_session_details = MagicMock( + return_value=MockReplicationSessionApi.METRO_SESSION_DETAILS_PAUSED[0]) + replicationsession_module_mock.perform_module_operation() + replicationsession_module_mock.conn.protection.resume_replication_session.assert_called() + + def test_modify_role_replicatio_session_exception(self, replicationsession_module_mock): + MockApiException.HTTP_ERR = "1" + MockApiException.err_code = "1" + MockApiException.status_code = "404" + self.get_module_args.update({ + 'session_id': "b05b5108-26b6-4567-a1d8-1c7795b2e6bc", + 'role': "Metro_Preferred" + }) + replicationsession_module_mock.module.params = self.get_module_args + replicationsession_module_mock.provisioning.get_cluster_list = MagicMock(return_value=MockReplicationSessionApi.CLUSTER_DETAILS) + replicationsession_module_mock.conn.protection.get_replication_session_details = MagicMock( + return_value=MockReplicationSessionApi.REPLICATION_SESSION_DETAILS[0]) + replicationsession_module_mock.conn.protection.modify_replication_session = MagicMock( + side_effect=MockApiException) + replicationsession_module_mock.perform_module_operation() + replicationsession_module_mock.conn.protection.modify_replication_session.assert_called() + assert MockReplicationSessionApi.modify_role_failed_msg() in \ + replicationsession_module_mock.module.fail_json.call_args[1]['msg'] diff --git a/tests/unit/plugins/modules/test_volume.py b/tests/unit/plugins/modules/test_volume.py index 4e15568..3ce5b69 100644 --- a/tests/unit/plugins/modules/test_volume.py +++ b/tests/unit/plugins/modules/test_volume.py @@ -590,3 +590,288 @@ def test_unmap_non_existing_host_group_from_volume(self, volume_module_mock): return_value=MockVolumeApi.VOL_DETAILS1[0]) volume_module_mock.perform_module_operation() assert volume_module_mock.module.exit_json.call_args[1]['changed'] is False + + def perform_operation(self, volume_module_mock): + volume_module_mock.provisioning.get_volume_details = MagicMock(return_value=MockVolumeApi.VOL_DETAILS1[0]) + volume_module_mock.perform_module_operation() + + def operation_before_clone_volume(self, volume_module_mock): + self.get_module_args.update({ + 'vol_name': "sample_volume_1", + 'clone_volume': { + 'name': 'test_name_3', + 'description': 'test description 1', + 'host': 'hst_nm_1', + 'host_group': 'hst_gp_1', + 'logical_unit_number': 13, + 'protection_policy': 'PP1', + 'performance_policy': 'low' + }, + 'state': "present" + }) + volume_module_mock.module.params = self.get_module_args + volume_module_mock.provisioning.get_volume_by_name = MagicMock(return_value=MockVolumeApi.VOL_DETAILS1) + volume_module_mock.get_volume = MagicMock(side_effect=[MockVolumeApi.VOL_DETAILS1[0], None, MockVolumeApi.VOL_DETAILS1[0]]) + volume_module_mock.get_performance_policy = MagicMock(return_value=MockVolumeApi.PERFORMANCE_POLICY_LOW) + volume_module_mock.get_protection_policy_id_by_name = MagicMock(return_value='PP_ID_1') + volume_module_mock.get_host_id_by_name = MagicMock(return_value='HD_ID_1') + volume_module_mock.get_host_group_id_by_name = MagicMock(return_value='HD_GP_ID_1') + + def test_clone_volume(self, volume_module_mock): + self.operation_before_clone_volume(volume_module_mock) + volume_module_mock.provisioning.clone_volume = MagicMock(return_value='vol_id_3') + self.perform_operation(volume_module_mock) + assert volume_module_mock.module.exit_json.call_args[1]['changed'] is True + volume_module_mock.provisioning.clone_volume.assert_called() + + def test_clone_volume_log_unit_error(self, volume_module_mock): + self.operation_before_clone_volume(volume_module_mock) + self.get_module_args['clone_volume']['host'] = None + self.get_module_args['clone_volume']['host_group'] = None + volume_module_mock.module.params = self.get_module_args + volume_module_mock.provisioning.clone_volume = MagicMock(return_value='vol_id_3') + self.perform_operation(volume_module_mock) + assert volume_module_mock.module.fail_json.call_args[1]['msg'] == MockVolumeApi.get_fail_msg_for_clone_volume('log_unit_error') + + def test_clone_volume_exception(self, volume_module_mock): + self.operation_before_clone_volume(volume_module_mock) + volume_module_mock.provisioning.clone_volume = MagicMock(side_effect=MockApiException) + self.perform_operation(volume_module_mock) + assert volume_module_mock.module.fail_json.call_args[1]['msg'] == MockVolumeApi.get_fail_msg_for_clone_volume('exception') + + def operation_before_refresh_volume(self, volume_module_mock): + self.get_module_args.update({ + 'vol_name': "sample_volume_1", + 'source_volume': 'test_name_1', + 'create_backup_snap': True, + 'backup_snap_profile': { + 'name': 'refresh_backup_snap_2', + 'description': 'test refresh_backup_snap', + 'expiration_timestamp': MockVolumeApi.EXPIRATION_TIMESTAMP, + 'performance_policy': 'low' + }, + 'state': "present" + }) + volume_module_mock.module.params = self.get_module_args + volume_module_mock.provisioning.get_volume_by_name = MagicMock(return_value=MockVolumeApi.VOL_DETAILS1) + volume_module_mock.provisioning.get_volumes = MagicMock(return_value=MockVolumeApi.VOL1_SNAPSHOT_LIST) + volume_module_mock.get_volume = MagicMock(return_value=MockVolumeApi.VOL_DETAILS1[0]) + volume_module_mock.get_performance_policy = MagicMock(return_value=MockVolumeApi.PERFORMANCE_POLICY_LOW) + + def test_refresh_volume(self, volume_module_mock): + self.operation_before_refresh_volume(volume_module_mock) + volume_module_mock.provisioning.refresh_volume = MagicMock(return_value='snap_id_3') + self.perform_operation(volume_module_mock) + assert volume_module_mock.module.exit_json.call_args[1]['changed'] is True + volume_module_mock.provisioning.refresh_volume.assert_called() + + def test_refresh_volume_exception(self, volume_module_mock): + self.operation_before_refresh_volume(volume_module_mock) + volume_module_mock.provisioning.refresh_volume = MagicMock(side_effect=MockApiException) + self.perform_operation(volume_module_mock) + assert volume_module_mock.module.fail_json.call_args[1]['msg'] == MockVolumeApi.get_fail_msg_for_refresh_volume('exception') + + def test_refresh_volume_backup_snap_error(self, volume_module_mock): + self.operation_before_refresh_volume(volume_module_mock) + self.get_module_args['create_backup_snap'] = None + volume_module_mock.module.params = self.get_module_args + volume_module_mock.provisioning.refresh_volume = MagicMock(return_value='snap_id_3') + self.perform_operation(volume_module_mock) + assert volume_module_mock.module.fail_json.call_args[1]['msg'] == MockVolumeApi.get_fail_msg_for_refresh_volume('backup_snap_error') + + def test_refresh_volume_expiration_timestamp_error(self, volume_module_mock): + self.operation_before_refresh_volume(volume_module_mock) + self.get_module_args['backup_snap_profile']['expiration_timestamp'] = '2022-23T01:20:00Z' + volume_module_mock.module.params = self.get_module_args + volume_module_mock.provisioning.refresh_volume = MagicMock(return_value='snap_id_3') + self.perform_operation(volume_module_mock) + assert volume_module_mock.module.fail_json.call_args[1]['msg'] == MockVolumeApi.get_fail_msg_for_refresh_volume('expiration_timestamp_error') + + def operation_before_restore_volume(self, volume_module_mock): + self.get_module_args.update({ + 'vol_name': "sample_volume_1", + 'source_snap': 'refresh_backup_snap_1', + 'create_backup_snap': True, + 'backup_snap_profile': { + 'name': 'restore_snap_2', + 'description': 'test backup snap', + 'expiration_timestamp': MockVolumeApi.EXPIRATION_TIMESTAMP, + 'performance_policy': 'low' + }, + 'state': "present" + }) + volume_module_mock.module.params = self.get_module_args + volume_module_mock.get_volume = MagicMock(return_value=MockVolumeApi.VOL_DETAILS1[0]) + volume_module_mock.provisioning.get_volume_by_name = MagicMock(return_value=MockVolumeApi.VOL_DETAILS1) + volume_module_mock.provisioning.get_volumes = MagicMock(return_value=MockVolumeApi.VOL1_SNAPSHOT_LIST) + volume_module_mock.get_performance_policy = MagicMock(return_value=MockVolumeApi.PERFORMANCE_POLICY_LOW) + + def test_restore_volume(self, volume_module_mock): + self.operation_before_restore_volume(volume_module_mock) + volume_module_mock.provisioning.restore_volume = MagicMock(return_value='snap_id_4') + self.perform_operation(volume_module_mock) + assert volume_module_mock.module.exit_json.call_args[1]['changed'] is True + volume_module_mock.provisioning.restore_volume.assert_called() + + def test_restore_volume_exception(self, volume_module_mock): + self.operation_before_restore_volume(volume_module_mock) + volume_module_mock.provisioning.restore_volume = MagicMock(side_effect=MockApiException) + self.perform_operation(volume_module_mock) + assert volume_module_mock.module.fail_json.call_args[1]['msg'] == MockVolumeApi.get_fail_msg_for_restore_volume('exception') + + def test_restore_volume_snap_exception(self, volume_module_mock): + self.operation_before_restore_volume(volume_module_mock) + volume_module_mock.provisioning.get_volumes = MagicMock(side_effect=[MockApiException, MockVolumeApi.VOL1_SNAPSHOT_LIST]) + volume_module_mock.provisioning.restore_volume = MagicMock(return_value='snap_id_3') + self.perform_operation(volume_module_mock) + assert volume_module_mock.module.fail_json.call_args[1]['msg'] == MockVolumeApi.get_fail_msg_for_restore_volume('snap_exception') + + def operation_before_configure_metro(self, volume_module_mock): + self.get_module_args.update({ + 'vol_name': "sample_volume_1", + 'remote_system': 'remote-system', + 'remote_appliance_id': 'A2', + 'state': "present" + }) + volume_module_mock.module.params = self.get_module_args + volume_module_mock.protection.get_remote_system_by_name = MagicMock( + return_value=MockVolumeApi.REMOTE_SYSTEM_DETAILS) + volume_module_mock.protection.get_remote_system_details = MagicMock( + return_value=MockVolumeApi.REMOTE_SYSTEM_DETAILS[0]) + + def test_configure_metro_volume(self, volume_module_mock): + self.operation_before_configure_metro(volume_module_mock) + volume_module_mock.provisioning.get_volume_by_name = MagicMock( + return_value=MockVolumeApi.VOL_DETAILS1) + volume_module_mock.provisioning.configure_metro_volume = MagicMock( + return_value=True) + volume_module_mock.perform_module_operation() + assert volume_module_mock.module.exit_json.call_args[1]['changed'] is True + volume_module_mock.provisioning.configure_metro_volume.assert_called() + + def test_configure_metro_volume_exception(self, volume_module_mock): + MockApiException.HTTP_ERR = "1" + MockApiException.err_code = "1" + MockApiException.status_code = "400" + self.operation_before_configure_metro(volume_module_mock) + volume_module_mock.provisioning.get_volume_by_name = MagicMock( + return_value=MockVolumeApi.VOL_DETAILS1) + volume_module_mock.provisioning.configure_metro_volume = MagicMock( + side_effect=MockApiException) + volume_module_mock.perform_module_operation() + assert MockVolumeApi.configure_metro_fail_msg() in \ + volume_module_mock.module.fail_json.call_args[1]['msg'] + volume_module_mock.provisioning.configure_metro_volume.assert_called() + + def test_rep_session_exception(self, volume_module_mock): + MockApiException.HTTP_ERR = "1" + MockApiException.err_code = "1" + MockApiException.status_code = "400" + self.operation_before_configure_metro(volume_module_mock) + volume_module_mock.provisioning.get_volume_by_name = MagicMock( + return_value=MockVolumeApi.MODIFY_VOL_DETAILS1) + volume_module_mock.protection.get_replication_session_details = MagicMock( + side_effect=MockApiException) + volume_module_mock.perform_module_operation() + assert MockVolumeApi.rep_session_fail_msg() in \ + volume_module_mock.module.fail_json.call_args[1]['msg'] + volume_module_mock.protection.get_replication_session_details.assert_called() + + def test_existing_metro_exception(self, volume_module_mock): + self.operation_before_configure_metro(volume_module_mock) + volume_module_mock.provisioning.get_volume_by_name = MagicMock( + return_value=MockVolumeApi.VOL_DETAILS2) + volume_module_mock.protection.get_replication_session_details = MagicMock( + return_values=MockVolumeApi.REP_SESSION_DETAILS[0]) + volume_module_mock.perform_module_operation() + assert MockVolumeApi.exisiting_metro_session_fail_msg() in \ + volume_module_mock.module.fail_json.call_args[1]['msg'] + volume_module_mock.protection.get_replication_session_details.assert_called() + + def test_multiple_remote_system_exception(self, volume_module_mock): + self.get_module_args.update({ + 'vol_name': "sample_volume_1", + 'remote_system': 'remote-system', + 'remote_appliance_id': 'A2', + 'state': "present" + }) + volume_module_mock.module.params = self.get_module_args + volume_module_mock.protection.get_remote_system_by_name = MagicMock( + return_value=MockVolumeApi.REMOTE_SYSTEM_DETAILS_1) + volume_module_mock.perform_module_operation() + assert MockVolumeApi.no_appliance_fail_msg() in \ + volume_module_mock.module.fail_json.call_args[1]['msg'] + volume_module_mock.protection.get_remote_system_by_name.assert_called() + + def test_remote_system_exception(self, volume_module_mock): + MockApiException.HTTP_ERR = "1" + MockApiException.err_code = "1" + MockApiException.status_code = "400" + self.get_module_args.update({ + 'vol_name': "sample_volume_1", + 'remote_system': MockVolumeApi.ID_1, + 'state': "present" + }) + volume_module_mock.module.params = self.get_module_args + volume_module_mock.protection.get_remote_system_details = MagicMock( + side_effect=MockApiException) + volume_module_mock.perform_module_operation() + assert MockVolumeApi.remote_system_fail_msg() in \ + volume_module_mock.module.fail_json.call_args[1]['msg'] + volume_module_mock.protection.get_remote_system_details.assert_called() + + def test_remote_system_app_exception(self, volume_module_mock): + MockApiException.HTTP_ERR = "1" + MockApiException.err_code = "1" + MockApiException.status_code = "400" + self.get_module_args.update({ + 'vol_name': "sample_volume_1", + 'remote_system': MockVolumeApi.REMOTE_SYSTEM_ID, + 'remote_appliance_id': 'A2', + 'state': "present" + }) + volume_module_mock.module.params = self.get_module_args + volume_module_mock.protection.get_remote_system_details = MagicMock( + return_value=MockVolumeApi.REMOTE_SYSTEM_DETAILS[0]) + volume_module_mock.protection.get_remote_system_appliance_details = MagicMock( + side_effect=MockApiException) + volume_module_mock.perform_module_operation() + assert MockVolumeApi.remote_app_fail_msg() in \ + volume_module_mock.module.fail_json.call_args[1]['msg'] + volume_module_mock.protection.get_remote_system_appliance_details.assert_called() + + def test_end_metro(self, volume_module_mock): + self.get_module_args.update({ + 'vol_name': "sample_volume_1", + 'end_metro_config': True, + 'delete_remote_volume': True, + 'state': "present" + }) + volume_module_mock.module.params = self.get_module_args + volume_module_mock.provisioning.get_volume_by_name = MagicMock( + return_value=MockVolumeApi.VOL_DETAILS2) + volume_module_mock.provisioning.end_volume_metro_config = MagicMock( + return_value=True) + volume_module_mock.perform_module_operation() + assert volume_module_mock.module.exit_json.call_args[1]['changed'] is True + volume_module_mock.provisioning.end_volume_metro_config.assert_called() + + def test_end_metro_exception(self, volume_module_mock): + MockApiException.HTTP_ERR = "1" + MockApiException.err_code = "1" + MockApiException.status_code = "400" + self.get_module_args.update({ + 'vol_name': "sample_volume_1", + 'end_metro_config': True, + 'delete_remote_volume': True, + 'state': "present" + }) + volume_module_mock.module.params = self.get_module_args + volume_module_mock.provisioning.get_volume_by_name = MagicMock( + return_value=MockVolumeApi.VOL_DETAILS2) + volume_module_mock.provisioning.end_volume_metro_config = MagicMock( + side_effect=MockApiException) + volume_module_mock.perform_module_operation() + assert MockVolumeApi.end_metro_fail_msg() in \ + volume_module_mock.module.fail_json.call_args[1]['msg'] + volume_module_mock.provisioning.end_volume_metro_config.assert_called()
KeyKey Type Returned Description
changed changed bool always Whether or not the resource has changed.
volume_details is_volume_cloned bool always Whether or not the clone of volume is created.
is_volume_refreshed bool always Whether or not the volume is refreshed.
is_volume_restored bool always Whether or not the volume is restored.
volume_details complex When volume exists Details of the volume.
  description description str success description about the volume.
  hlu_details hlu_details complex success HLU details for mapped host/host group.
    host_group_id host_group_id str success The host group ID mapped to the volume.
    host_id host_id str success The host ID mapped to the volume.
    id id str success The HLU ID.
    logical_unit_number logical_unit_number int success Logical unit number for the host/host group volume access.
  host host complex success Hosts details mapped to the volume.
    id id str success The host ID mapped to the volume.
    name name str success Name of the Host mapped to the volume.
  host_group host_group complex success Host groups details mapped to the volume.
    id id str success The host group ID mapped to the volume.
    name name str success Name of the Host group mapped to the volume.
  id id str success The system generated ID given to the volume.
  mapped_volumes mapped_volumes complex success This is the inverse of the resource type host_volume_mapping association.
    id id str success Unique identifier of a mapping between a host and a volume.
    logical_unit_number logical_unit_number int success Logical unit number for the host volume access.
  name metro_replication_session_id str success The ID of the metro replication session assigned to volume.
  name str success Name of the volume.
  nguid nguid int success NVMe Namespace globally unique identifier. Used for volumes attached to NVMEoF hosts.
  node_affinity node_affinity str success This attribute shows which node will be advertised as the optimized IO path to the volume.
  nsid nsid int success NVMe Namespace unique identifier in the NVME subsystem. Used for volumes attached to NVMEoF hosts.
  performance_policy_id performance_policy_id str success The performance policy for the volume.
  protection_policy_id protection_policy_id str success The protection policy of the volume.
  size size int success Size of the volume.
  volume_groups snapshots complex success List of snapshot associated with the volume.
   id str success The system generated ID given to the snapshot.
   name str success Name of the snapshot.
  volume_groups complex success The volume group details of the volume.
    id id str success The system generated ID given to the volume group.
    name name str success Name of the volume group.
  wwn wwn str success The world wide name of the volume.   name str True
Name of snapshot set to be created.