Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
ansible / purestorage / flashblade / plugins / modules / purefb_info.py
Size: Mime:
#!/usr/bin/python
# -*- coding: utf-8 -*-

# (c) 2019, Simon Dodsley (simon@purestorage.com)
# GNU General Public License v3.0+ (see COPYING or
# https://www.gnu.org/licenses/gpl-3.0.txt)

from __future__ import absolute_import, division, print_function

__metaclass__ = type

ANSIBLE_METADATA = {
    "metadata_version": "1.1",
    "status": ["preview"],
    "supported_by": "community",
}

DOCUMENTATION = r"""
---
module: purefb_info
version_added: '1.0.0'
short_description: Collect information from Pure Storage FlashBlade
description:
  - Collect information from a Pure Storage FlashBlade running the
    Purity//FB operating system. By default, the module will collect basic
    information including hosts, host groups, protection
    groups and volume counts. Additional information can be collected
    based on the configured set of arguements.
author:
  - Pure Storage Ansible Team (@sdodsley) <pure-ansible-team@purestorage.com>
options:
  gather_subset:
    description:
      - When supplied, this argument will define the information to be collected.
        Possible values for this include all, minimum, config, performance,
        capacity, network, subnets, lags, filesystems, snapshots, buckets,
        replication, policies, arrays, accounts, admins, ad and kerberos.
    required: false
    type: list
    elements: str
    default: minimum
extends_documentation_fragment:
  - purestorage.flashblade.purestorage.fb
"""

EXAMPLES = r"""
- name: collect default set of info
  purefb_info:
    fb_url: 10.10.10.2
    api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641
  register: blade_info
- name: show default information
  debug:
    msg: "{{ blade_info['purefb_info']['default'] }}"

- name: collect configuration and capacity info
  purefb_info:
    gather_subset:
      - config
    fb_url: 10.10.10.2
    api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641
  register: blade_info
- name: show config information
  debug:
    msg: "{{ blade_info['purefb_info']['config'] }}"

- name: collect all info
  purefb_info:
    gather_subset:
      - all
    fb_url: 10.10.10.2
    api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641
  register: blade_info
- name: show all information
  debug:
    msg: "{{ blade_info['purefb_info'] }}"
"""

RETURN = r"""
purefb_info:
  description: Returns the information collected from the FlashBlade
  returned: always
  type: complex
  sample: {
        "admins": {
            "pureuser": {
                "api_token_timeout": null,
                "local": true,
                "public_key": null
            },
            "another_user": {
                "api_token_timeout": null,
                "local": false,
                "public_key": null
            },
        },
        "buckets": {
            "central": {
                "account_name": "jake",
                "created": 1628900154000,
                "data_reduction": null,
                "destroyed": false,
                "id": "43758f09-9e71-7bf7-5757-2028a95a2b65",
                "lifecycle_rules": {},
                "object_count": 0,
                "snapshot_space": 0,
                "time_remaining": null,
                "total_physical_space": 0,
                "unique_space": 0,
                "versioning": "none",
                "virtual_space": 0
            },
            "test": {
                "account_name": "acme",
                "created": 1630591952000,
                "data_reduction": 3.6,
                "destroyed": false,
                "id": "d5f6149c-fbef-f3c5-58b6-8fd143110ba9",
                "lifecycle_rules": {
                    "test": {
                        "abort_incomplete_multipart_uploads_after (days)": 1,
                        "cleanup_expired_object_delete_marker": true,
                        "enabled": true,
                        "keep_current_version_for (days)": null,
                        "keep_current_version_until": "2023-12-21",
                        "keep_previous_version_for (days)": null,
                        "prefix": "foo"
                    }
                },
            },
        },
        "capacity": {
            "aggregate": {
                "data_reduction": 1.1179228,
                "snapshots": 0,
                "total_physical": 17519748439,
                "unique": 17519748439,
                "virtual": 19585726464
            },
            "file-system": {
                "data_reduction": 1.3642412,
                "snapshots": 0,
                "total_physical": 4748219708,
                "unique": 4748219708,
                "virtual": 6477716992
            },
            "object-store": {
                "data_reduction": 1.0263462,
                "snapshots": 0,
                "total_physical": 12771528731,
                "unique": 12771528731,
                "virtual": 6477716992
            },
            "total": 83359896948925
        },
        "config": {
            "alert_watchers": {
                "enabled": true,
                "name": "notify@acmestorage.com"
            },
            "array_management": {
                "base_dn": null,
                "bind_password": null,
                "bind_user": null,
                "enabled": false,
                "name": "management",
                "services": [
                    "management"
                ],
                "uris": []
            },
            "directory_service_roles": {
                "array_admin": {
                    "group": null,
                    "group_base": null
                },
                "ops_admin": {
                    "group": null,
                    "group_base": null
                },
                "readonly": {
                    "group": null,
                    "group_base": null
                },
                "storage_admin": {
                    "group": null,
                    "group_base": null
                }
            },
            "dns": {
                "domain": "demo.acmestorage.com",
                "name": "demo-fb-1",
                "nameservers": [
                    "8.8.8.8"
                ],
                "search": [
                    "demo.acmestorage.com"
                ]
            },
            "nfs_directory_service": {
                "base_dn": null,
                "bind_password": null,
                "bind_user": null,
                "enabled": false,
                "name": "nfs",
                "services": [
                    "nfs"
                ],
                "uris": []
            },
            "ntp": [
                "0.ntp.pool.org"
            ],
            "smb_directory_service": {
                "base_dn": null,
                "bind_password": null,
                "bind_user": null,
                "enabled": false,
                "name": "smb",
                "services": [
                    "smb"
                ],
                "uris": []
            },
            "smtp": {
                "name": "demo-fb-1",
                "relay_host": null,
                "sender_domain": "acmestorage.com"
            },
            "ssl_certs": {
                "certificate": "-----BEGIN CERTIFICATE-----\n\n-----END CERTIFICATE-----",
                "common_name": "Acme Storage",
                "country": "US",
                "email": null,
                "intermediate_certificate": null,
                "issued_by": "Acme Storage",
                "issued_to": "Acme Storage",
                "key_size": 4096,
                "locality": null,
                "name": "global",
                "organization": "Acme Storage",
                "organizational_unit": "Acme Storage",
                "passphrase": null,
                "private_key": null,
                "state": null,
                "status": "self-signed",
                "valid_from": "1508433967000",
                "valid_to": "2458833967000"
            }
        },
        "default": {
            "blades": 15,
            "buckets": 7,
            "filesystems": 2,
            "flashblade_name": "demo-fb-1",
            "object_store_accounts": 1,
            "object_store_users": 1,
            "purity_version": "2.2.0",
            "snapshots": 1,
            "total_capacity": 83359896948925,
            "smb_mode": "native"
        },
        "filesystems": {
            "k8s-pvc-d24b1357-579e-11e8-811f-ecf4bbc88f54": {
                "destroyed": false,
                "fast_remove": false,
                "hard_limit": true,
                "nfs_rules": "10.21.255.0/24(rw,no_root_squash)",
                "provisioned": 21474836480,
                "snapshot_enabled": false
            },
            "z": {
                "destroyed": false,
                "fast_remove": false,
                "hard_limit": false,
                "provisioned": 1073741824,
                "snapshot_enabled": false
            }
        },
        "lag": {
            "uplink": {
                "lag_speed": 0,
                "port_speed": 40000000000,
                "ports": [
                    {
                        "name": "CH1.FM1.ETH1.1"
                    },
                    {
                        "name": "CH1.FM1.ETH1.2"
                    },
                ],
                "status": "healthy"
            }
        },
        "network": {
            "fm1.admin0": {
                "address": "10.10.100.6",
                "gateway": "10.10.100.1",
                "mtu": 1500,
                "netmask": "255.255.255.0",
                "services": [
                    "support"
                ],
                "type": "vip",
                "vlan": 2200
            },
            "fm2.admin0": {
                "address": "10.10.100.7",
                "gateway": "10.10.100.1",
                "mtu": 1500,
                "netmask": "255.255.255.0",
                "services": [
                    "support"
                ],
                "type": "vip",
                "vlan": 2200
            },
            "nfs1": {
                "address": "10.10.100.4",
                "gateway": "10.10.100.1",
                "mtu": 1500,
                "netmask": "255.255.255.0",
                "services": [
                    "data"
                ],
                "type": "vip",
                "vlan": 2200
            },
            "vir0": {
                "address": "10.10.100.5",
                "gateway": "10.10.100.1",
                "mtu": 1500,
                "netmask": "255.255.255.0",
                "services": [
                    "management"
                ],
                "type": "vip",
                "vlan": 2200
            }
        },
        "performance": {
            "aggregate": {
                "bytes_per_op": 0,
                "bytes_per_read": 0,
                "bytes_per_write": 0,
                "read_bytes_per_sec": 0,
                "reads_per_sec": 0,
                "usec_per_other_op": 0,
                "usec_per_read_op": 0,
                "usec_per_write_op": 0,
                "write_bytes_per_sec": 0,
                "writes_per_sec": 0
            },
            "http": {
                "bytes_per_op": 0,
                "bytes_per_read": 0,
                "bytes_per_write": 0,
                "read_bytes_per_sec": 0,
                "reads_per_sec": 0,
                "usec_per_other_op": 0,
                "usec_per_read_op": 0,
                "usec_per_write_op": 0,
                "write_bytes_per_sec": 0,
                "writes_per_sec": 0
            },
            "nfs": {
                "bytes_per_op": 0,
                "bytes_per_read": 0,
                "bytes_per_write": 0,
                "read_bytes_per_sec": 0,
                "reads_per_sec": 0,
                "usec_per_other_op": 0,
                "usec_per_read_op": 0,
                "usec_per_write_op": 0,
                "write_bytes_per_sec": 0,
                "writes_per_sec": 0
            },
            "s3": {
                "bytes_per_op": 0,
                "bytes_per_read": 0,
                "bytes_per_write": 0,
                "read_bytes_per_sec": 0,
                "reads_per_sec": 0,
                "usec_per_other_op": 0,
                "usec_per_read_op": 0,
                "usec_per_write_op": 0,
                "write_bytes_per_sec": 0,
                "writes_per_sec": 0
            }
        },
        "snapshots": {
            "z.188": {
                "destroyed": false,
                "source": "z",
                "source_destroyed": false,
                "suffix": "188"
            }
        },
        "subnet": {
            "new-mgmt": {
                "gateway": "10.10.100.1",
                "interfaces": [
                    {
                        "name": "fm1.admin0"
                    },
                    {
                        "name": "fm2.admin0"
                    },
                    {
                        "name": "nfs1"
                    },
                    {
                        "name": "vir0"
                    }
                ],
                "lag": "uplink",
                "mtu": 1500,
                "prefix": "10.10.100.0/24",
                "services": [
                    "data",
                    "management",
                    "support"
                ],
                "vlan": 2200
            }
        }
    }
"""


from ansible.module_utils.basic import AnsibleModule
from ansible_collections.purestorage.flashblade.plugins.module_utils.purefb import (
    get_blade,
    get_system,
    purefb_argument_spec,
)
from datetime import datetime


MIN_REQUIRED_API_VERSION = "1.3"
HARD_LIMIT_API_VERSION = "1.4"
POLICIES_API_VERSION = "1.5"
CERT_GROUPS_API_VERSION = "1.8"
REPLICATION_API_VERSION = "1.9"
MULTIPROTOCOL_API_VERSION = "1.11"
MIN_32_API = "2.0"
LIFECYCLE_API_VERSION = "2.1"
SMB_MODE_API_VERSION = "2.2"
NFS_POLICY_API_VERSION = "2.3"


def _millisecs_to_time(millisecs):
    if millisecs:
        return (str(int(millisecs / 3600000 % 24)).zfill(2) + ":00",)
    return None


def _bytes_to_human(bytes_number):
    if bytes_number:
        labels = ["B/s", "KB/s", "MB/s", "GB/s", "TB/s", "PB/s"]
        i = 0
        double_bytes = bytes_number
        while i < len(labels) and bytes_number >= 1024:
            double_bytes = bytes_number / 1024.0
            i += 1
            bytes_number = bytes_number / 1024
        return str(round(double_bytes, 2)) + " " + labels[i]
    return None


def generate_default_dict(module, blade):
    default_info = {}
    defaults = blade.arrays.list_arrays().items[0]
    default_info["flashblade_name"] = defaults.name
    default_info["purity_version"] = defaults.version
    default_info["filesystems"] = len(blade.file_systems.list_file_systems().items)
    default_info["snapshots"] = len(
        blade.file_system_snapshots.list_file_system_snapshots().items
    )
    default_info["buckets"] = len(blade.buckets.list_buckets().items)
    default_info["object_store_users"] = len(
        blade.object_store_users.list_object_store_users().items
    )
    default_info["object_store_accounts"] = len(
        blade.object_store_accounts.list_object_store_accounts().items
    )
    default_info["blades"] = len(blade.blade.list_blades().items)
    default_info["certificates"] = len(blade.certificates.list_certificates().items)
    default_info["total_capacity"] = blade.arrays.list_arrays_space().items[0].capacity
    api_version = blade.api_version.list_versions().versions
    if POLICIES_API_VERSION in api_version:
        default_info["policies"] = len(blade.policies.list_policies().items)
    if CERT_GROUPS_API_VERSION in api_version:
        default_info["certificate_groups"] = len(
            blade.certificate_groups.list_certificate_groups().items
        )
    if REPLICATION_API_VERSION in api_version:
        default_info["fs_replicas"] = len(
            blade.file_system_replica_links.list_file_system_replica_links().items
        )
        default_info["remote_credentials"] = len(
            blade.object_store_remote_credentials.list_object_store_remote_credentials().items
        )
        default_info["bucket_replicas"] = len(
            blade.bucket_replica_links.list_bucket_replica_links().items
        )
        default_info["connected_arrays"] = len(
            blade.array_connections.list_array_connections().items
        )
        default_info["targets"] = len(blade.targets.list_targets().items)
        default_info["kerberos_keytabs"] = len(blade.keytabs.list_keytabs().items)
    # This section is just for REST 2.x features
    if MIN_32_API in api_version:
        blade = get_system(module)
        blade_info = list(blade.get_arrays().items)[0]
        default_info["object_store_virtual_hosts"] = len(
            blade.get_object_store_virtual_hosts().items
        )
        default_info["api_clients"] = len(blade.get_api_clients().items)
        default_info["idle_timeout"] = int(blade_info.idle_timeout / 60000)
        if list(blade.get_arrays_eula().items)[0].signature.accepted:
            default_info["EULA"] = "Signed"
        else:
            default_info["EULA"] = "Not Signed"
        if NFS_POLICY_API_VERSION in api_version:
            admin_settings = list(blade.get_admins_settings().items)[0]
            default_info["max_login_attempts"] = admin_settings.max_login_attempts
            default_info["min_password_length"] = admin_settings.min_password_length
            if admin_settings.lockout_duration:
                default_info["lockout_duration"] = (
                    str(admin_settings.lockout_duration / 1000) + " seconds"
                )
        if NFS_POLICY_API_VERSION in api_version:
            default_info["smb_mode"] = blade_info.smb_mode

    return default_info


def generate_perf_dict(blade):
    perf_info = {}
    total_perf = blade.arrays.list_arrays_performance()
    http_perf = blade.arrays.list_arrays_performance(protocol="http")
    s3_perf = blade.arrays.list_arrays_performance(protocol="s3")
    nfs_perf = blade.arrays.list_arrays_performance(protocol="nfs")
    perf_info["aggregate"] = {
        "bytes_per_op": total_perf.items[0].bytes_per_op,
        "bytes_per_read": total_perf.items[0].bytes_per_read,
        "bytes_per_write": total_perf.items[0].bytes_per_write,
        "read_bytes_per_sec": total_perf.items[0].read_bytes_per_sec,
        "reads_per_sec": total_perf.items[0].reads_per_sec,
        "usec_per_other_op": total_perf.items[0].usec_per_other_op,
        "usec_per_read_op": total_perf.items[0].usec_per_read_op,
        "usec_per_write_op": total_perf.items[0].usec_per_write_op,
        "write_bytes_per_sec": total_perf.items[0].write_bytes_per_sec,
        "writes_per_sec": total_perf.items[0].writes_per_sec,
    }
    perf_info["http"] = {
        "bytes_per_op": http_perf.items[0].bytes_per_op,
        "bytes_per_read": http_perf.items[0].bytes_per_read,
        "bytes_per_write": http_perf.items[0].bytes_per_write,
        "read_bytes_per_sec": http_perf.items[0].read_bytes_per_sec,
        "reads_per_sec": http_perf.items[0].reads_per_sec,
        "usec_per_other_op": http_perf.items[0].usec_per_other_op,
        "usec_per_read_op": http_perf.items[0].usec_per_read_op,
        "usec_per_write_op": http_perf.items[0].usec_per_write_op,
        "write_bytes_per_sec": http_perf.items[0].write_bytes_per_sec,
        "writes_per_sec": http_perf.items[0].writes_per_sec,
    }
    perf_info["s3"] = {
        "bytes_per_op": s3_perf.items[0].bytes_per_op,
        "bytes_per_read": s3_perf.items[0].bytes_per_read,
        "bytes_per_write": s3_perf.items[0].bytes_per_write,
        "read_bytes_per_sec": s3_perf.items[0].read_bytes_per_sec,
        "reads_per_sec": s3_perf.items[0].reads_per_sec,
        "usec_per_other_op": s3_perf.items[0].usec_per_other_op,
        "usec_per_read_op": s3_perf.items[0].usec_per_read_op,
        "usec_per_write_op": s3_perf.items[0].usec_per_write_op,
        "write_bytes_per_sec": s3_perf.items[0].write_bytes_per_sec,
        "writes_per_sec": s3_perf.items[0].writes_per_sec,
    }
    perf_info["nfs"] = {
        "bytes_per_op": nfs_perf.items[0].bytes_per_op,
        "bytes_per_read": nfs_perf.items[0].bytes_per_read,
        "bytes_per_write": nfs_perf.items[0].bytes_per_write,
        "read_bytes_per_sec": nfs_perf.items[0].read_bytes_per_sec,
        "reads_per_sec": nfs_perf.items[0].reads_per_sec,
        "usec_per_other_op": nfs_perf.items[0].usec_per_other_op,
        "usec_per_read_op": nfs_perf.items[0].usec_per_read_op,
        "usec_per_write_op": nfs_perf.items[0].usec_per_write_op,
        "write_bytes_per_sec": nfs_perf.items[0].write_bytes_per_sec,
        "writes_per_sec": nfs_perf.items[0].writes_per_sec,
    }
    api_version = blade.api_version.list_versions().versions
    if REPLICATION_API_VERSION in api_version:
        file_repl_perf = (
            blade.array_connections.list_array_connections_performance_replication(
                type="file-system"
            )
        )
        obj_repl_perf = (
            blade.array_connections.list_array_connections_performance_replication(
                type="object-store"
            )
        )
        if len(file_repl_perf.total):
            perf_info["file_replication"] = {
                "received_bytes_per_sec": file_repl_perf.total[
                    0
                ].periodic.received_bytes_per_sec,
                "transmitted_bytes_per_sec": file_repl_perf.total[
                    0
                ].periodic.transmitted_bytes_per_sec,
            }
        if len(obj_repl_perf.total):
            perf_info["object_replication"] = {
                "received_bytes_per_sec": obj_repl_perf.total[
                    0
                ].periodic.received_bytes_per_sec,
                "transmitted_bytes_per_sec": obj_repl_perf.total[
                    0
                ].periodic.transmitted_bytes_per_sec,
            }
    return perf_info


def generate_config_dict(blade):
    config_info = {}
    config_info["dns"] = blade.dns.list_dns().items[0].to_dict()
    config_info["smtp"] = blade.smtp.list_smtp().items[0].to_dict()
    try:
        config_info["alert_watchers"] = (
            blade.alert_watchers.list_alert_watchers().items[0].to_dict()
        )
    except Exception:
        config_info["alert_watchers"] = ""
    api_version = blade.api_version.list_versions().versions
    if HARD_LIMIT_API_VERSION in api_version:
        config_info["array_management"] = (
            blade.directory_services.list_directory_services(names=["management"])
            .items[0]
            .to_dict()
        )
        config_info["directory_service_roles"] = {}
        roles = blade.directory_services.list_directory_services_roles()
        for role in range(0, len(roles.items)):
            role_name = roles.items[role].name
            config_info["directory_service_roles"][role_name] = {
                "group": roles.items[role].group,
                "group_base": roles.items[role].group_base,
            }
    config_info["nfs_directory_service"] = (
        blade.directory_services.list_directory_services(names=["nfs"])
        .items[0]
        .to_dict()
    )
    config_info["smb_directory_service"] = (
        blade.directory_services.list_directory_services(names=["smb"])
        .items[0]
        .to_dict()
    )
    config_info["ntp"] = blade.arrays.list_arrays().items[0].ntp_servers
    config_info["ssl_certs"] = blade.certificates.list_certificates().items[0].to_dict()
    api_version = blade.api_version.list_versions().versions
    if CERT_GROUPS_API_VERSION in api_version:
        try:
            config_info["certificate_groups"] = (
                blade.certificate_groups.list_certificate_groups().items[0].to_dict()
            )
        except Exception:
            config_info["certificate_groups"] = ""
    if REPLICATION_API_VERSION in api_version:
        config_info["snmp_agents"] = {}
        snmp_agents = blade.snmp_agents.list_snmp_agents()
        for agent in range(0, len(snmp_agents.items)):
            agent_name = snmp_agents.items[agent].name
            config_info["snmp_agents"][agent_name] = {
                "version": snmp_agents.items[agent].version,
                "engine_id": snmp_agents.items[agent].engine_id,
            }
            if config_info["snmp_agents"][agent_name]["version"] == "v3":
                config_info["snmp_agents"][agent_name][
                    "auth_protocol"
                ] = snmp_agents.items[agent].v3.auth_protocol
                config_info["snmp_agents"][agent_name][
                    "privacy_protocol"
                ] = snmp_agents.items[agent].v3.privacy_protocol
                config_info["snmp_agents"][agent_name]["user"] = snmp_agents.items[
                    agent
                ].v3.user
        config_info["snmp_managers"] = {}
        snmp_managers = blade.snmp_managers.list_snmp_managers()
        for manager in range(0, len(snmp_managers.items)):
            mgr_name = snmp_managers.items[manager].name
            config_info["snmp_managers"][mgr_name] = {
                "version": snmp_managers.items[manager].version,
                "host": snmp_managers.items[manager].host,
                "notification": snmp_managers.items[manager].notification,
            }
            if config_info["snmp_managers"][mgr_name]["version"] == "v3":
                config_info["snmp_managers"][mgr_name][
                    "auth_protocol"
                ] = snmp_managers.items[manager].v3.auth_protocol
                config_info["snmp_managers"][mgr_name][
                    "privacy_protocol"
                ] = snmp_managers.items[manager].v3.privacy_protocol
                config_info["snmp_managers"][mgr_name]["user"] = snmp_managers.items[
                    manager
                ].v3.user
    return config_info


def generate_subnet_dict(blade):
    sub_info = {}
    subnets = blade.subnets.list_subnets()
    for sub in range(0, len(subnets.items)):
        sub_name = subnets.items[sub].name
        if subnets.items[sub].enabled:
            sub_info[sub_name] = {
                "gateway": subnets.items[sub].gateway,
                "mtu": subnets.items[sub].mtu,
                "vlan": subnets.items[sub].vlan,
                "prefix": subnets.items[sub].prefix,
                "services": subnets.items[sub].services,
            }
            sub_info[sub_name]["lag"] = subnets.items[sub].link_aggregation_group.name
            sub_info[sub_name]["interfaces"] = []
            for iface in range(0, len(subnets.items[sub].interfaces)):
                sub_info[sub_name]["interfaces"].append(
                    {"name": subnets.items[sub].interfaces[iface].name}
                )
    return sub_info


def generate_lag_dict(blade):
    lag_info = {}
    groups = blade.link_aggregation_groups.list_link_aggregation_groups()
    for groupcnt in range(0, len(groups.items)):
        lag_name = groups.items[groupcnt].name
        lag_info[lag_name] = {
            "lag_speed": groups.items[groupcnt].lag_speed,
            "port_speed": groups.items[groupcnt].port_speed,
            "status": groups.items[groupcnt].status,
        }
        lag_info[lag_name]["ports"] = []
        for port in range(0, len(groups.items[groupcnt].ports)):
            lag_info[lag_name]["ports"].append(
                {"name": groups.items[groupcnt].ports[port].name}
            )
    return lag_info


def generate_admin_dict(module, blade):
    admin_info = {}
    api_version = blade.api_version.list_versions().versions
    if MULTIPROTOCOL_API_VERSION in api_version:
        admins = blade.admins.list_admins()
        for admin in range(0, len(admins.items)):
            admin_name = admins.items[admin].name
            admin_info[admin_name] = {
                "api_token_timeout": admins.items[admin].api_token_timeout,
                "public_key": admins.items[admin].public_key,
                "local": admins.items[admin].is_local,
            }

    if MIN_32_API in api_version:
        bladev2 = get_system(module)
        admins = list(bladev2.get_admins().items)
        for admin in range(0, len(admins)):
            admin_name = admins[admin].name
            if admins[admin].api_token.expires_at:
                admin_info[admin_name]["token_expires"] = datetime.fromtimestamp(
                    admins[admin].api_token.expires_at / 1000
                ).strftime("%Y-%m-%d %H:%M:%S")
            else:
                admin_info[admin_name]["token_expires"] = None
            admin_info[admin_name]["token_created"] = datetime.fromtimestamp(
                admins[admin].api_token.created_at / 1000
            ).strftime("%Y-%m-%d %H:%M:%S")
            admin_info[admin_name]["role"] = admins[admin].role.name
            if NFS_POLICY_API_VERSION in api_version:
                admin_info[admin_name]["locked"] = admins[admin].locked
                admin_info[admin_name]["lockout_remaining"] = admins[
                    admin
                ].lockout_remaining
    return admin_info


def generate_targets_dict(blade):
    targets_info = {}
    targets = blade.targets.list_targets()
    for target in range(0, len(targets.items)):
        target_name = targets.items[target].name
        targets_info[target_name] = {
            "address": targets.items[target].address,
            "status": targets.items[target].status,
            "status_details": targets.items[target].status_details,
        }
    return targets_info


def generate_remote_creds_dict(blade):
    remote_creds_info = {}
    remote_creds = (
        blade.object_store_remote_credentials.list_object_store_remote_credentials()
    )
    for cred_cnt in range(0, len(remote_creds.items)):
        cred_name = remote_creds.items[cred_cnt].name
        remote_creds_info[cred_name] = {
            "access_key": remote_creds.items[cred_cnt].access_key_id,
            "remote_array": remote_creds.items[cred_cnt].remote.name,
        }
    return remote_creds_info


def generate_file_repl_dict(blade):
    file_repl_info = {}
    file_links = blade.file_system_replica_links.list_file_system_replica_links()
    for linkcnt in range(0, len(file_links.items)):
        fs_name = file_links.items[linkcnt].local_file_system.name
        file_repl_info[fs_name] = {
            "direction": file_links.items[linkcnt].direction,
            "lag": file_links.items[linkcnt].lag,
            "status": file_links.items[linkcnt].status,
            "remote_fs": file_links.items[linkcnt].remote.name
            + ":"
            + file_links.items[linkcnt].remote_file_system.name,
            "recovery_point": file_links.items[linkcnt].recovery_point,
        }
        file_repl_info[fs_name]["policies"] = []
        for policy_cnt in range(0, len(file_links.items[linkcnt].policies)):
            file_repl_info[fs_name]["policies"].append(
                file_links.items[linkcnt].policies[policy_cnt].display_name
            )
    return file_repl_info


def generate_bucket_repl_dict(module, blade):
    bucket_repl_info = {}
    bucket_links = blade.bucket_replica_links.list_bucket_replica_links()
    for linkcnt in range(0, len(bucket_links.items)):
        bucket_name = bucket_links.items[linkcnt].local_bucket.name
        bucket_repl_info[bucket_name] = {
            "direction": bucket_links.items[linkcnt].direction,
            "lag": bucket_links.items[linkcnt].lag,
            "paused": bucket_links.items[linkcnt].paused,
            "status": bucket_links.items[linkcnt].status,
            "remote_bucket": bucket_links.items[linkcnt].remote_bucket.name,
            "remote_credentials": bucket_links.items[linkcnt].remote_credentials.name,
            "recovery_point": bucket_links.items[linkcnt].recovery_point,
            "object_backlog": {},
        }
    api_version = blade.api_version.list_versions().versions
    if SMB_MODE_API_VERSION in api_version:
        blade = get_system(module)
        bucket_links = list(blade.get_bucket_replica_links().items)
        for linkcnt in range(0, len(bucket_links)):
            bucket_name = bucket_links[linkcnt].local_bucket.name
            bucket_repl_info[bucket_name]["object_backlog"] = {
                "bytes_count": bucket_links[linkcnt].object_backlog.bytes_count,
                "delete_ops_count": bucket_links[
                    linkcnt
                ].object_backlog.delete_ops_count,
                "other_ops_count": bucket_links[linkcnt].object_backlog.other_ops_count,
                "put_ops_count": bucket_links[linkcnt].object_backlog.put_ops_count,
            }
            bucket_repl_info[bucket_name]["cascading_enabled"] = bucket_links[
                linkcnt
            ].cascading_enabled
    return bucket_repl_info


def generate_network_dict(blade):
    net_info = {}
    ports = blade.network_interfaces.list_network_interfaces()
    for portcnt in range(0, len(ports.items)):
        int_name = ports.items[portcnt].name
        if ports.items[portcnt].enabled:
            net_info[int_name] = {
                "type": ports.items[portcnt].type,
                "mtu": ports.items[portcnt].mtu,
                "vlan": ports.items[portcnt].vlan,
                "address": ports.items[portcnt].address,
                "services": ports.items[portcnt].services,
                "gateway": ports.items[portcnt].gateway,
                "netmask": ports.items[portcnt].netmask,
            }
    return net_info


def generate_capacity_dict(blade):
    capacity_info = {}
    total_cap = blade.arrays.list_arrays_space()
    file_cap = blade.arrays.list_arrays_space(type="file-system")
    object_cap = blade.arrays.list_arrays_space(type="object-store")
    capacity_info["total"] = total_cap.items[0].capacity
    capacity_info["aggregate"] = {
        "data_reduction": total_cap.items[0].space.data_reduction,
        "snapshots": total_cap.items[0].space.snapshots,
        "total_physical": total_cap.items[0].space.total_physical,
        "unique": total_cap.items[0].space.unique,
        "virtual": total_cap.items[0].space.virtual,
    }
    capacity_info["file-system"] = {
        "data_reduction": file_cap.items[0].space.data_reduction,
        "snapshots": file_cap.items[0].space.snapshots,
        "total_physical": file_cap.items[0].space.total_physical,
        "unique": file_cap.items[0].space.unique,
        "virtual": file_cap.items[0].space.virtual,
    }
    capacity_info["object-store"] = {
        "data_reduction": object_cap.items[0].space.data_reduction,
        "snapshots": object_cap.items[0].space.snapshots,
        "total_physical": object_cap.items[0].space.total_physical,
        "unique": object_cap.items[0].space.unique,
        "virtual": file_cap.items[0].space.virtual,
    }

    return capacity_info


def generate_snap_dict(blade):
    snap_info = {}
    snaps = blade.file_system_snapshots.list_file_system_snapshots()
    api_version = blade.api_version.list_versions().versions
    for snap in range(0, len(snaps.items)):
        snapshot = snaps.items[snap].name
        snap_info[snapshot] = {
            "destroyed": snaps.items[snap].destroyed,
            "source": snaps.items[snap].source,
            "suffix": snaps.items[snap].suffix,
            "source_destroyed": snaps.items[snap].source_destroyed,
        }
        if REPLICATION_API_VERSION in api_version:
            snap_info[snapshot]["owner"] = snaps.items[snap].owner.name
            snap_info[snapshot]["owner_destroyed"] = snaps.items[snap].owner_destroyed
            snap_info[snapshot]["source_display_name"] = snaps.items[
                snap
            ].source_display_name
            snap_info[snapshot]["source_is_local"] = snaps.items[snap].source_is_local
            snap_info[snapshot]["source_location"] = snaps.items[
                snap
            ].source_location.name
    return snap_info


def generate_snap_transfer_dict(blade):
    snap_transfer_info = {}
    snap_transfers = blade.file_system_snapshots.list_file_system_snapshots_transfer()
    for snap_transfer in range(0, len(snap_transfers.items)):
        transfer = snap_transfers.items[snap_transfer].name
        snap_transfer_info[transfer] = {
            "completed": snap_transfers.items[snap_transfer].completed,
            "data_transferred": snap_transfers.items[snap_transfer].data_transferred,
            "progress": snap_transfers.items[snap_transfer].progress,
            "direction": snap_transfers.items[snap_transfer].direction,
            "remote": snap_transfers.items[snap_transfer].remote.name,
            "remote_snapshot": snap_transfers.items[snap_transfer].remote_snapshot.name,
            "started": snap_transfers.items[snap_transfer].started,
            "status": snap_transfers.items[snap_transfer].status,
        }
    return snap_transfer_info


def generate_array_conn_dict(module, blade):
    array_conn_info = {}
    arraysv2 = {}
    api_version = blade.api_version.list_versions().versions
    arrays = blade.array_connections.list_array_connections()
    if NFS_POLICY_API_VERSION in api_version:
        bladev2 = get_system(module)
        arraysv2 = list(bladev2.get_array_connections().items)
    for arraycnt in range(0, len(arrays.items)):
        array = arrays.items[arraycnt].remote.name
        array_conn_info[array] = {
            "encrypted": arrays.items[arraycnt].encrypted,
            "replication_addresses": arrays.items[arraycnt].replication_addresses,
            "management_address": arrays.items[arraycnt].management_address,
            "status": arrays.items[arraycnt].status,
            "version": arrays.items[arraycnt].version,
            "throttle": [],
        }
        if arrays.items[arraycnt].encrypted:
            array_conn_info[array]["ca_certificate_group"] = arrays.items[
                arraycnt
            ].ca_certificate_group.name
        for v2array in range(0, len(arraysv2)):
            if arraysv2[v2array].remote.name == array:
                array_conn_info[array]["throttle"] = {
                    "default_limit": _bytes_to_human(
                        arraysv2[v2array].throttle.default_limit
                    ),
                    "window_limit": _bytes_to_human(
                        arraysv2[v2array].throttle.window_limit
                    ),
                    "window_start": _millisecs_to_time(
                        arraysv2[v2array].throttle.window.start
                    ),
                    "window_end": _millisecs_to_time(
                        arraysv2[v2array].throttle.window.end
                    ),
                }
    return array_conn_info


def generate_policies_dict(blade):
    policies_info = {}
    policies = blade.policies.list_policies()
    for policycnt in range(0, len(policies.items)):
        policy = policies.items[policycnt].name
        policies_info[policy] = {}
        policies_info[policy]["enabled"] = policies.items[policycnt].enabled
        if policies.items[policycnt].rules:
            policies_info[policy]["rules"] = (
                policies.items[policycnt].rules[0].to_dict()
            )
    return policies_info


def generate_bucket_dict(module, blade):
    bucket_info = {}
    buckets = blade.buckets.list_buckets()
    for bckt in range(0, len(buckets.items)):
        bucket = buckets.items[bckt].name
        bucket_info[bucket] = {
            "versioning": buckets.items[bckt].versioning,
            "object_count": buckets.items[bckt].object_count,
            "id": buckets.items[bckt].id,
            "account_name": buckets.items[bckt].account.name,
            "data_reduction": buckets.items[bckt].space.data_reduction,
            "snapshot_space": buckets.items[bckt].space.snapshots,
            "total_physical_space": buckets.items[bckt].space.total_physical,
            "unique_space": buckets.items[bckt].space.unique,
            "virtual_space": buckets.items[bckt].space.virtual,
            "created": buckets.items[bckt].created,
            "destroyed": buckets.items[bckt].destroyed,
            "time_remaining": buckets.items[bckt].time_remaining,
            "lifecycle_rules": {},
        }
    api_version = blade.api_version.list_versions().versions
    if LIFECYCLE_API_VERSION in api_version:
        blade = get_system(module)
        all_rules = list(blade.get_lifecycle_rules().items)
        for rule in range(0, len(all_rules)):
            bucket_name = all_rules[rule].bucket.name
            rule_id = all_rules[rule].rule_id
            if all_rules[rule].keep_previous_version_for:
                keep_previous_version_for = int(
                    all_rules[rule].keep_previous_version_for / 86400000
                )
            else:
                keep_previous_version_for = None
            if all_rules[rule].keep_current_version_for:
                keep_current_version_for = int(
                    all_rules[rule].keep_current_version_for / 86400000
                )
            else:
                keep_current_version_for = None
            if all_rules[rule].abort_incomplete_multipart_uploads_after:
                abort_incomplete_multipart_uploads_after = int(
                    all_rules[rule].abort_incomplete_multipart_uploads_after / 86400000
                )
            else:
                abort_incomplete_multipart_uploads_after = None
            if all_rules[rule].keep_current_version_until:
                keep_current_version_until = datetime.fromtimestamp(
                    all_rules[rule].keep_current_version_until / 1000
                ).strftime("%Y-%m-%d")
            else:
                keep_current_version_until = None
            bucket_info[bucket_name]["lifecycle_rules"][rule_id] = {
                "keep_previous_version_for (days)": keep_previous_version_for,
                "keep_current_version_for (days)": keep_current_version_for,
                "keep_current_version_until": keep_current_version_until,
                "prefix": all_rules[rule].prefix,
                "enabled": all_rules[rule].enabled,
                "abort_incomplete_multipart_uploads_after (days)": abort_incomplete_multipart_uploads_after,
                "cleanup_expired_object_delete_marker": all_rules[
                    rule
                ].cleanup_expired_object_delete_marker,
            }
    return bucket_info


def generate_kerb_dict(blade):
    kerb_info = {}
    keytabs = list(blade.get_keytabs().items)
    for ktab in range(0, len(keytabs)):
        keytab_name = keytabs[ktab].prefix
        kerb_info[keytab_name] = {}
        for key in range(0, len(keytabs)):
            if keytabs[key].prefix == keytab_name:
                kerb_info[keytab_name][keytabs[key].suffix] = {
                    "fqdn": keytabs[key].fqdn,
                    "kvno": keytabs[key].kvno,
                    "principal": keytabs[key].principal,
                    "realm": keytabs[key].realm,
                    "encryption_type": keytabs[key].encryption_type,
                }
    return kerb_info


def generate_ad_dict(blade):
    ad_info = {}
    active_directory = blade.get_active_directory()
    if active_directory.total_item_count != 0:
        ad_account = list(active_directory.items)[0]
        ad_info[ad_account.name] = {
            "computer": ad_account.computer_name,
            "domain": ad_account.domain,
            "directory_servers": ad_account.directory_servers,
            "kerberos_servers": ad_account.kerberos_servers,
            "service_principals": ad_account.service_principal_names,
            "join_ou": ad_account.join_ou,
            "encryption_types": ad_account.encryption_types,
        }
    return ad_info


def generate_object_store_access_policies_dict(blade):
    policies_info = {}
    policies = list(blade.get_object_store_access_policies().items)
    for policy in range(0, len(policies)):
        policy_name = policies[policy].name
        policies_info[policy_name] = {
            "ARN": policies[policy].arn,
            "description": policies[policy].description,
            "enabled": policies[policy].enabled,
            "local": policies[policy].is_local,
            "rules": [],
        }
        for rule in range(0, len(policies[policy].rules)):
            policies_info[policy_name]["rules"].append(
                {
                    "actions": policies[policy].rules[rule].actions,
                    "conditions": {
                        "source_ips": policies[policy]
                        .rules[rule]
                        .conditions.source_ips,
                        "s3_delimiters": policies[policy]
                        .rules[rule]
                        .conditions.s3_delimiters,
                        "s3_prefixes": policies[policy]
                        .rules[rule]
                        .conditions.s3_prefixes,
                    },
                    "effect": policies[policy].rules[rule].effect,
                    "name": policies[policy].rules[rule].name,
                }
            )
    return policies_info


def generate_nfs_export_policies_dict(blade):
    policies_info = {}
    policies = list(blade.get_nfs_export_policies().items)
    for policy in range(0, len(policies)):
        policy_name = policies[policy].name
        policies_info[policy_name] = {
            "local": policies[policy].is_local,
            "enabled": policies[policy].enabled,
            "rules": [],
        }
        for rule in range(0, len(policies[policy].rules)):
            policies_info[policy_name]["rules"].append(
                {
                    "access": policies[policy].rules[rule].access,
                    "anongid": policies[policy].rules[rule].anongid,
                    "anonuid": policies[policy].rules[rule].anonuid,
                    "atime": policies[policy].rules[rule].atime,
                    "client": policies[policy].rules[rule].client,
                    "fileid_32bit": policies[policy].rules[rule].fileid_32bit,
                    "permission": policies[policy].rules[rule].permission,
                    "secure": policies[policy].rules[rule].secure,
                    "security": policies[policy].rules[rule].security,
                    "index": policies[policy].rules[rule].index,
                }
            )
    return policies_info


def generate_object_store_accounts_dict(blade):
    account_info = {}
    accounts = list(blade.get_object_store_accounts().items)
    for account in range(0, len(accounts)):
        acc_name = accounts[account].name
        account_info[acc_name] = {
            "object_count": accounts[account].object_count,
            "data_reduction": accounts[account].space.data_reduction,
            "snapshots_space": accounts[account].space.snapshots,
            "total_physical_space": accounts[account].space.total_physical,
            "unique_space": accounts[account].space.unique,
            "virtual_space": accounts[account].space.virtual,
            "users": {},
        }
        acc_users = list(
            blade.get_object_store_users(filter='name="' + acc_name + '/*"').items
        )
        for acc_user in range(0, len(acc_users)):
            user_name = acc_users[acc_user].name.split("/")[1]
            account_info[acc_name]["users"][user_name] = {"keys": [], "policies": []}
            if (
                blade.get_object_store_access_keys(
                    filter='user.name="' + acc_users[acc_user].name + '"'
                ).total_item_count
                != 0
            ):
                access_keys = list(
                    blade.get_object_store_access_keys(
                        filter='user.name="' + acc_users[acc_user].name + '"'
                    ).items
                )
                for key in range(0, len(access_keys)):
                    account_info[acc_name]["users"][user_name]["keys"].append(
                        {
                            "name": access_keys[key].name,
                            "enabled": bool(access_keys[key].enabled),
                        }
                    )
            if (
                blade.get_object_store_access_policies_object_store_users(
                    member_names=[acc_users[acc_user].name]
                ).total_item_count
                != 0
            ):
                policies = list(
                    blade.get_object_store_access_policies_object_store_users(
                        member_names=[acc_users[acc_user].name]
                    ).items
                )
                for policy in range(0, len(policies)):
                    account_info[acc_name]["users"][user_name]["policies"].append(
                        policies[policy].policy.name
                    )
    return account_info


def generate_fs_dict(module, blade):
    api_version = blade.api_version.list_versions().versions
    if NFS_POLICY_API_VERSION in api_version:
        bladev2 = get_system(module)
        fsys_v2 = list(bladev2.get_file_systems().items)
    fs_info = {}
    fsys = blade.file_systems.list_file_systems()
    for fsystem in range(0, len(fsys.items)):
        share = fsys.items[fsystem].name
        fs_info[share] = {
            "fast_remove": fsys.items[fsystem].fast_remove_directory_enabled,
            "snapshot_enabled": fsys.items[fsystem].snapshot_directory_enabled,
            "provisioned": fsys.items[fsystem].provisioned,
            "destroyed": fsys.items[fsystem].destroyed,
            "nfs_rules": fsys.items[fsystem].nfs.rules,
            "nfs_v3": getattr(fsys.items[fsystem].nfs, "v3_enabled", False),
            "nfs_v4_1": getattr(fsys.items[fsystem].nfs, "v4_1_enabled", False),
        }
        if fsys.items[fsystem].http.enabled:
            fs_info[share]["http"] = fsys.items[fsystem].http.enabled
        if fsys.items[fsystem].smb.enabled:
            fs_info[share]["smb_mode"] = fsys.items[fsystem].smb.acl_mode
        api_version = blade.api_version.list_versions().versions
        if MULTIPROTOCOL_API_VERSION in api_version:
            fs_info[share]["multi_protocol"] = {
                "safegaurd_acls": fsys.items[fsystem].multi_protocol.safeguard_acls,
                "access_control_style": fsys.items[
                    fsystem
                ].multi_protocol.access_control_style,
            }
        if HARD_LIMIT_API_VERSION in api_version:
            fs_info[share]["hard_limit"] = fsys.items[fsystem].hard_limit_enabled
        if REPLICATION_API_VERSION in api_version:
            fs_info[share]["promotion_status"] = fsys.items[fsystem].promotion_status
            fs_info[share]["requested_promotion_state"] = fsys.items[
                fsystem
            ].requested_promotion_state
            fs_info[share]["writable"] = fsys.items[fsystem].writable
            fs_info[share]["source"] = {
                "is_local": fsys.items[fsystem].source.is_local,
                "name": fsys.items[fsystem].source.name,
            }
            if NFS_POLICY_API_VERSION in api_version:
                for v2fs in range(0, len(fsys_v2)):
                    if fsys_v2[v2fs].name == share:
                        fs_info[share]["export_policy"] = fsys_v2[
                            v2fs
                        ].nfs.export_policy.name
    return fs_info


def main():
    argument_spec = purefb_argument_spec()
    argument_spec.update(
        dict(gather_subset=dict(default="minimum", type="list", elements="str"))
    )

    module = AnsibleModule(argument_spec, supports_check_mode=True)

    blade = get_blade(module)
    versions = blade.api_version.list_versions().versions

    if MIN_REQUIRED_API_VERSION not in versions:
        module.fail_json(
            msg="Minimum FlashBlade REST version required: {0}".format(
                MIN_REQUIRED_API_VERSION
            )
        )
    if not module.params["gather_subset"]:
        module.params["gather_subset"] = ["minimum"]
    subset = [test.lower() for test in module.params["gather_subset"]]
    valid_subsets = (
        "all",
        "minimum",
        "config",
        "performance",
        "capacity",
        "network",
        "subnets",
        "lags",
        "filesystems",
        "snapshots",
        "buckets",
        "arrays",
        "replication",
        "policies",
        "accounts",
        "admins",
        "ad",
        "kerberos",
    )
    subset_test = (test in valid_subsets for test in subset)
    if not all(subset_test):
        module.fail_json(
            msg="value must gather_subset must be one or more of: %s, got: %s"
            % (",".join(valid_subsets), ",".join(subset))
        )

    info = {}

    api_version = blade.api_version.list_versions().versions
    if "minimum" in subset or "all" in subset:
        info["default"] = generate_default_dict(module, blade)
    if "performance" in subset or "all" in subset:
        info["performance"] = generate_perf_dict(blade)
    if "config" in subset or "all" in subset:
        info["config"] = generate_config_dict(blade)
    if "capacity" in subset or "all" in subset:
        info["capacity"] = generate_capacity_dict(blade)
    if "lags" in subset or "all" in subset:
        info["lag"] = generate_lag_dict(blade)
    if "network" in subset or "all" in subset:
        info["network"] = generate_network_dict(blade)
    if "subnets" in subset or "all" in subset:
        info["subnet"] = generate_subnet_dict(blade)
    if "filesystems" in subset or "all" in subset:
        info["filesystems"] = generate_fs_dict(module, blade)
    if "admins" in subset or "all" in subset:
        info["admins"] = generate_admin_dict(module, blade)
    if "snapshots" in subset or "all" in subset:
        info["snapshots"] = generate_snap_dict(blade)
    if "buckets" in subset or "all" in subset:
        info["buckets"] = generate_bucket_dict(module, blade)
    if POLICIES_API_VERSION in api_version:
        if "policies" in subset or "all" in subset:
            info["policies"] = generate_policies_dict(blade)
            info["snapshot_policies"] = generate_policies_dict(blade)
    if REPLICATION_API_VERSION in api_version:
        if "arrays" in subset or "all" in subset:
            info["arrays"] = generate_array_conn_dict(module, blade)
        if "replication" in subset or "all" in subset:
            info["file_replication"] = generate_file_repl_dict(blade)
            info["bucket_replication"] = generate_bucket_repl_dict(module, blade)
            info["snap_transfers"] = generate_snap_transfer_dict(blade)
            info["remote_credentials"] = generate_remote_creds_dict(blade)
            info["targets"] = generate_targets_dict(blade)
    if MIN_32_API in api_version:
        # Calls for data only available from Purity//FB 3.2 and higher
        blade = get_system(module)
        if "accounts" in subset or "all" in subset:
            info["accounts"] = generate_object_store_accounts_dict(blade)
        if "ad" in subset or "all" in subset:
            info["active_directory"] = generate_ad_dict(blade)
        if "kerberos" in subset or "all" in subset:
            info["kerberos"] = generate_kerb_dict(blade)
        if "policies" in subset or "all" in subset:
            if SMB_MODE_API_VERSION in api_version:
                info["access_policies"] = generate_object_store_access_policies_dict(
                    blade
                )
            if NFS_POLICY_API_VERSION in api_version:
                info["export_policies"] = generate_nfs_export_policies_dict(blade)

    module.exit_json(changed=False, purefb_info=info)


if __name__ == "__main__":
    main()