diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-18 05:52:22 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-18 05:52:22 +0000 |
commit | 38b7c80217c4e72b1d8988eb1e60bb6e77334114 (patch) | |
tree | 356e9fd3762877d07cde52d21e77070aeff7e789 /ansible_collections/dellemc/powerflex/plugins/modules/info.py | |
parent | Adding upstream version 7.7.0+dfsg. (diff) | |
download | ansible-38b7c80217c4e72b1d8988eb1e60bb6e77334114.tar.xz ansible-38b7c80217c4e72b1d8988eb1e60bb6e77334114.zip |
Adding upstream version 9.4.0+dfsg.upstream/9.4.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ansible_collections/dellemc/powerflex/plugins/modules/info.py')
-rw-r--r-- | ansible_collections/dellemc/powerflex/plugins/modules/info.py | 818 |
1 files changed, 794 insertions, 24 deletions
diff --git a/ansible_collections/dellemc/powerflex/plugins/modules/info.py b/ansible_collections/dellemc/powerflex/plugins/modules/info.py index ff1401d63..33f3a8ad8 100644 --- a/ansible_collections/dellemc/powerflex/plugins/modules/info.py +++ b/ansible_collections/dellemc/powerflex/plugins/modules/info.py @@ -1,6 +1,6 @@ -#!/usr/bin/python +# !/usr/bin/python -# Copyright: (c) 2021, Dell Technologies +# Copyright: (c) 2024, Dell Technologies # Apache License version 2.0 (see MODULE-LICENSE or http://www.apache.org/licenses/LICENSE-2.0.txt) """Ansible module for Gathering information about Dell Technologies (Dell) PowerFlex""" @@ -21,12 +21,16 @@ description: - Gathering information about Dell PowerFlex storage system includes getting the api details, list of volumes, SDSs, SDCs, storage pools, protection domains, snapshot policies, and devices. +- Gathering information about Dell PowerFlex Manager includes getting the + list of managed devices, deployments and service templates. extends_documentation_fragment: - dellemc.powerflex.powerflex author: - Arindam Datta (@dattaarindam) <ansible.team@dell.com> +- Trisha Datta (@trisha-dell) <ansible.team@dell.com> +- Jennifer John (@Jennifer-John) <ansible.team@dell.com> options: gather_subset: @@ -42,8 +46,13 @@ options: - Devices - C(device). - Replication consistency groups - C(rcg). - Replication pairs - C(replication_pair). + - Fault Sets - C(fault_set). + - Service templates - C(service_template). + - Managed devices - C(managed_device). + - Deployments - C(deployment). choices: [vol, storage_pool, protection_domain, sdc, sds, - snapshot_policy, device, rcg, replication_pair] + snapshot_policy, device, rcg, replication_pair, + fault_set, service_template, managed_device, deployment] type: list elements: str filters: @@ -62,16 +71,63 @@ options: filter_operator: description: - Operation to be performed on filter key. + - Choice I('contains') is supported for gather_subset keys I(service_template), I(managed_device), I(deployment). type: str - choices: [equal] + choices: [equal, contains] required: true filter_value: description: - Value of the filter key. type: str required: true + limit: + description: + - Page limit. + - Supported for gather_subset keys I(service_template), I(managed_device), I(deployment). + type: int + default: 50 + offset: + description: + - Pagination offset. + - Supported for gather_subset keys I(service_template), I(managed_device), I(deployment). + type: int + default: 0 + sort: + description: + - Sort the returned components based on specified field. + - Supported for gather_subset keys I(service_template), I(managed_device), I(deployment). + - The supported sort keys for the gather_subset can be referred from PowerFlex Manager API documentation in developer.dell.com. + type: str + include_devices: + description: + - Include devices in response. + - Applicable when gather_subset is I(deployment). + type: bool + default: true + include_template: + description: + - Include service templates in response. + - Applicable when gather_subset is I(deployment). + type: bool + default: true + full: + description: + - Specify if response is full or brief. + - Applicable when gather_subset is I(deployment), I(service_template). + - For I(deployment) specify to use full templates including resources in response. + type: bool + default: false + include_attachments: + description: + - Include attachments. + - Applicable when gather_subset is I(service_template). + type: bool + default: true notes: - The I(check_mode) is supported. + - The supported filter keys for the gather_subset can be referred from PowerFlex Manager API documentation in developer.dell.com. + - The I(filter), I(sort), I(limit) and I(offset) options will be ignored when more than one I(gather_subset) is specified along with + I(service_template), I(managed_device) or I(deployment). ''' EXAMPLES = r''' @@ -91,6 +147,7 @@ EXAMPLES = r''' - device - rcg - replication_pair + - fault_set - name: Get a subset list of PowerFlex volumes dellemc.powerflex.info: @@ -104,6 +161,35 @@ EXAMPLES = r''' - filter_key: "name" filter_operator: "equal" filter_value: "ansible_test" + +- name: Get deployment and resource provisioning info + dellemc.powerflex.info: + hostname: "{{hostname}}" + username: "{{username}}" + password: "{{password}}" + validate_certs: "{{validate_certs}}" + gather_subset: + - managed_device + - deployment + - service_template + +- name: Get deployment with filter, sort, pagination + dellemc.powerflex.info: + hostname: "{{hostname}}" + username: "{{username}}" + password: "{{password}}" + validate_certs: "{{validate_certs}}" + gather_subset: + - deployment + filters: + - filter_key: "name" + filter_operator: "contains" + filter_value: "partial" + sort: name + limit: 10 + offset: 10 + include_devices: true + include_template: true ''' RETURN = r''' @@ -1147,19 +1233,557 @@ Replication_pairs: "replicationConsistencyGroupId": "e2ce036b00000002", "userRequestedPauseTransmitInitCopy": false } +Fault_Sets: + description: Details of fault sets. + returned: always + type: list + contains: + protectionDomainId: + description: The ID of the protection domain. + type: str + name: + description: device name. + type: str + id: + description: device id. + type: str + sample: [ + { + "protectionDomainId": "da721a8300000000", + "protectionDomainName": "fault_set_1", + "name": "at1zbs1t6cp2sds1d1fs1", + "SDS": [], + "id": "eb44b70500000000", + "links": [ + { "rel": "self", "href": "/api/instances/FaultSet::eb44b70500000000" }, + { + "rel": "/api/FaultSet/relationship/Statistics", + "href": "/api/instances/FaultSet::eb44b70500000000/relationships/Statistics" + }, + { + "rel": "/api/FaultSet/relationship/Sds", + "href": "/api/instances/FaultSet::eb44b70500000000/relationships/Sds" + }, + { + "rel": "/api/parent/relationship/protectionDomainId", + "href": "/api/instances/ProtectionDomain::da721a8300000000" + } + ] + }, + { + "protectionDomainId": "da721a8300000000", + "protectionDomainName": "fault_set_2", + "name": "at1zbs1t6cp2sds1d1fs3", + "SDS": [], + "id": "eb44b70700000002", + "links": [ + { "rel": "self", "href": "/api/instances/FaultSet::eb44b70700000002" }, + { + "rel": "/api/FaultSet/relationship/Statistics", + "href": "/api/instances/FaultSet::eb44b70700000002/relationships/Statistics" + }, + { + "rel": "/api/FaultSet/relationship/Sds", + "href": "/api/instances/FaultSet::eb44b70700000002/relationships/Sds" + }, + { + "rel": "/api/parent/relationship/protectionDomainId", + "href": "/api/instances/ProtectionDomain::da721a8300000000" + } + ] + } + ] +ManagedDevices: + description: Details of all devices from inventory. + returned: when I(gather_subset) is I(managed_device) + type: list + contains: + deviceType: + description: Device Type. + type: str + serviceTag: + description: Service Tag. + type: str + serverTemplateId: + description: The ID of the server template. + type: str + state: + description: The state of the device. + type: str + managedState: + description: The managed state of the device. + type: str + compliance: + description: The compliance state of the device. + type: str + systemId: + description: The system ID. + type: str + sample: [{ + "refId": "softwareOnlyServer-10.1.1.1", + "refType": null, + "ipAddress": "10.1.1.1", + "currentIpAddress": "10.1.1.1", + "serviceTag": "VMware-42 15 a5 f9 65 e6 63 0e-36 79 59 73 7b 3a 68 cd-SW", + "model": "VMware Virtual Platform", + "deviceType": "SoftwareOnlyServer", + "discoverDeviceType": "SOFTWAREONLYSERVER_CENTOS", + "displayName": "vpi1011-c1n1", + "managedState": "UNMANAGED", + "state": "READY", + "inUse": false, + "serviceReferences": [], + "statusMessage": null, + "firmwareName": "Default Catalog - PowerFlex 4.5.0.0", + "customFirmware": false, + "needsAttention": false, + "manufacturer": "VMware, Inc.", + "systemId": null, + "health": "RED", + "healthMessage": "Inventory run failed.", + "operatingSystem": "N/A", + "numberOfCPUs": 0, + "cpuType": null, + "nics": 0, + "memoryInGB": 0, + "infraTemplateDate": null, + "infraTemplateId": null, + "serverTemplateDate": null, + "serverTemplateId": null, + "inventoryDate": null, + "complianceCheckDate": "2024-02-05T18:31:31.213+00:00", + "discoveredDate": "2024-02-05T18:31:30.992+00:00", + "deviceGroupList": { + "paging": null, + "deviceGroup": [ + { + "link": null, + "groupSeqId": -1, + "groupName": "Global", + "groupDescription": null, + "createdDate": null, + "createdBy": "admin", + "updatedDate": null, + "updatedBy": null, + "managedDeviceList": null, + "groupUserList": null + } + ] + }, + "detailLink": { + "title": "softwareOnlyServer-10.1.1.1", + "href": "/AsmManager/ManagedDevice/softwareOnlyServer-10.1.1.1", + "rel": "describedby", + "type": null + }, + "credId": "bc97cefb-5eb4-4c20-8e39-d1a2b809c9f5", + "compliance": "NONCOMPLIANT", + "failuresCount": 0, + "chassisId": null, + "parsedFacts": null, + "config": null, + "hostname": "vpi1011-c1n1", + "osIpAddress": null, + "osAdminCredential": null, + "osImageType": null, + "lastJobs": null, + "puppetCertName": "red_hat-10.1.1.1", + "svmAdminCredential": null, + "svmName": null, + "svmIpAddress": null, + "svmImageType": null, + "flexosMaintMode": 0, + "esxiMaintMode": 0, + "vmList": [] + }] +Deployments: + description: Details of all deployments. + returned: when I(gather_subset) is I(deployment) + type: list + contains: + id: + description: Deployment ID. + type: str + deploymentName: + description: Deployment name. + type: str + status: + description: The status of deployment. + type: str + firmwareRepository: + description: The firmware repository. + type: dict + contains: + signature: + description: The signature details. + type: str + downloadStatus: + description: The download status. + type: str + rcmapproved: + description: If RCM approved. + type: bool + sample: [{ + "id": "8aaa80658cd602e0018cda8b257f78ce", + "deploymentName": "Test-Update - K", + "deploymentDescription": "Test-Update - K", + "deploymentValid": null, + "retry": false, + "teardown": false, + "teardownAfterCancel": false, + "removeService": false, + "createdDate": "2024-01-05T16:53:21.407+00:00", + "createdBy": "admin", + "updatedDate": "2024-02-11T17:00:05.657+00:00", + "updatedBy": "system", + "deploymentScheduledDate": null, + "deploymentStartedDate": "2024-01-05T16:53:22.886+00:00", + "deploymentFinishedDate": null, + "serviceTemplate": { + "id": "8aaa80658cd602e0018cda8b257f78ce", + "templateName": "block-only (8aaa80658cd602e0018cda8b257f78ce)", + "templateDescription": "Storage - Software Only deployment", + "templateType": "VxRack FLEX", + "templateVersion": "4.5.0.0", + "templateValid": { + "valid": true, + "messages": [] + }, + "originalTemplateId": "c44cb500-020f-4562-9456-42ec1eb5f9b2", + "templateLocked": false, + "draft": false, + "inConfiguration": false, + "createdDate": "2024-01-05T16:53:22.083+00:00", + "createdBy": null, + "updatedDate": "2024-02-09T06:00:09.602+00:00", + "lastDeployedDate": null, + "updatedBy": null, + "components": [ + { + "id": "6def7edd-bae2-4420-93bf-9ceb051bbb65", + "componentID": "component-scaleio-gateway-1", + "identifier": null, + "componentValid": { + "valid": true, + "messages": [] + }, + "puppetCertName": "scaleio-block-legacy-gateway", + "osPuppetCertName": null, + "name": "block-legacy-gateway", + "type": "SCALEIO", + "subType": "STORAGEONLY", + "teardown": false, + "helpText": null, + "managementIpAddress": null, + "configFile": null, + "serialNumber": null, + "asmGUID": "scaleio-block-legacy-gateway", + "relatedComponents": { + "625b0e17-9b91-4bc0-864c-d0111d42d8d0": "Node (Software Only)", + "961a59eb-80c3-4a3a-84b7-2101e9831527": "Node (Software Only)-2", + "bca710a5-7cdf-481e-b729-0b53e02873ee": "Node (Software Only)-3" + }, + "resources": [], + "refId": null, + "cloned": false, + "clonedFromId": null, + "manageFirmware": false, + "brownfield": false, + "instances": 1, + "clonedFromAsmGuid": null, + "ip": null + } + ], + "category": "block-only", + "allUsersAllowed": true, + "assignedUsers": [], + "manageFirmware": true, + "useDefaultCatalog": false, + "firmwareRepository": null, + "licenseRepository": null, + "configuration": null, + "serverCount": 3, + "storageCount": 1, + "clusterCount": 1, + "serviceCount": 0, + "switchCount": 0, + "vmCount": 0, + "sdnasCount": 0, + "brownfieldTemplateType": "NONE", + "networks": [ + { + "id": "8aaa80648cd5fb9b018cda46e4e50000", + "name": "mgmt", + "description": "", + "type": "SCALEIO_MANAGEMENT", + "vlanId": 850, + "static": true, + "staticNetworkConfiguration": { + "gateway": "10.1.1.1", + "subnet": "1.1.1.0", + "primaryDns": "10.1.1.1", + "secondaryDns": "10.1.1.1", + "dnsSuffix": null, + "ipRange": [ + { + "id": "8aaa80648cd5fb9b018cda46e5080001", + "startingIp": "10.1.1.1", + "endingIp": "10.1.1.1", + "role": null + } + ], + "ipAddress": null, + "staticRoute": null + }, + "destinationIpAddress": "10.1.1.1" + } + ], + "blockServiceOperationsMap": { + "scaleio-block-legacy-gateway": { + "blockServiceOperationsMap": {} + } + } + }, + "scheduleDate": null, + "status": "complete", + "compliant": true, + "deploymentDevice": [ + { + "refId": "scaleio-block-legacy-gateway", + "refType": null, + "logDump": null, + "status": null, + "statusEndTime": null, + "statusStartTime": null, + "deviceHealth": "GREEN", + "healthMessage": "OK", + "compliantState": "COMPLIANT", + "brownfieldStatus": "NOT_APPLICABLE", + "deviceType": "scaleio", + "deviceGroupName": null, + "ipAddress": "block-legacy-gateway", + "currentIpAddress": "10.1.1.1", + "serviceTag": "block-legacy-gateway", + "componentId": null, + "statusMessage": null, + "model": "PowerFlex Gateway", + "cloudLink": false, + "dasCache": false, + "deviceState": "READY", + "puppetCertName": "scaleio-block-legacy-gateway", + "brownfield": false + } + ], + "vms": null, + "updateServerFirmware": true, + "useDefaultCatalog": false, + "firmwareRepository": { + "id": "8aaa80658cd602e0018cd996a1c91bdc", + "name": "Intelligent Catalog 45.373.00", + "sourceLocation": null, + "sourceType": null, + "diskLocation": null, + "filename": null, + "md5Hash": null, + "username": null, + "password": null, + "downloadStatus": null, + "createdDate": null, + "createdBy": null, + "updatedDate": null, + "updatedBy": null, + "defaultCatalog": false, + "embedded": false, + "state": null, + "softwareComponents": [], + "softwareBundles": [], + "deployments": [], + "bundleCount": 0, + "componentCount": 0, + "userBundleCount": 0, + "minimal": false, + "downloadProgress": 0, + "extractProgress": 0, + "fileSizeInGigabytes": null, + "signedKeySourceLocation": null, + "signature": null, + "custom": false, + "needsAttention": false, + "jobId": null, + "rcmapproved": false + }, + "firmwareRepositoryId": "8aaa80658cd602e0018cd996a1c91bdc", + "licenseRepository": null, + "licenseRepositoryId": null, + "individualTeardown": false, + "deploymentHealthStatusType": "green", + "assignedUsers": [], + "allUsersAllowed": true, + "owner": "admin", + "noOp": false, + "firmwareInit": false, + "disruptiveFirmware": false, + "preconfigureSVM": false, + "preconfigureSVMAndUpdate": false, + "servicesDeployed": "NONE", + "precalculatedDeviceHealth": null, + "lifecycleModeReasons": [], + "jobDetails": null, + "numberOfDeployments": 0, + "operationType": "NONE", + "operationStatus": null, + "operationData": null, + "deploymentValidationResponse": null, + "currentStepCount": null, + "totalNumOfSteps": null, + "currentStepMessage": null, + "customImage": "os_sles", + "originalDeploymentId": null, + "currentBatchCount": null, + "totalBatchCount": null, + "templateValid": true, + "lifecycleMode": false, + "vds": false, + "scaleUp": false, + "brownfield": false, + "configurationChange": false + }] +ServiceTemplates: + description: Details of all service templates. + returned: when I(gather_subset) is I(service_template) + type: list + contains: + templateName: + description: Template name. + type: str + templateDescription: + description: Template description. + type: str + templateType: + description: Template type. + type: str + templateVersion: + description: Template version. + type: str + category: + description: The template category. + type: str + serverCount: + description: Server count. + type: int + sample: [{ + "id": "2434144f-7795-4245-a04b-6fcb771697d7", + "templateName": "Storage- 100Gb", + "templateDescription": "Storage Only 4 Node deployment with 100Gb networking", + "templateType": "VxRack FLEX", + "templateVersion": "4.5-213", + "templateValid": { + "valid": true, + "messages": [] + }, + "originalTemplateId": "ff80808177f880fc0177f883bf1e0027", + "templateLocked": true, + "draft": false, + "inConfiguration": false, + "createdDate": "2024-01-04T19:47:23.534+00:00", + "createdBy": "system", + "updatedDate": null, + "lastDeployedDate": null, + "updatedBy": null, + "components": [ + { + "id": "43dec024-85a9-4901-9e8e-fa0d3c417f7b", + "componentID": "component-scaleio-gateway-1", + "identifier": null, + "componentValid": { + "valid": true, + "messages": [] + }, + "puppetCertName": null, + "osPuppetCertName": null, + "name": "PowerFlex Cluster", + "type": "SCALEIO", + "subType": "STORAGEONLY", + "teardown": false, + "helpText": null, + "managementIpAddress": null, + "configFile": null, + "serialNumber": null, + "asmGUID": null, + "relatedComponents": { + "c5c46733-012c-4dca-af9b-af46d73d045a": "Storage Only Node" + }, + "resources": [], + "refId": null, + "cloned": false, + "clonedFromId": null, + "manageFirmware": false, + "brownfield": false, + "instances": 1, + "clonedFromAsmGuid": null, + "ip": null + } + ], + "category": "Sample Templates", + "allUsersAllowed": false, + "assignedUsers": [], + "manageFirmware": true, + "useDefaultCatalog": true, + "firmwareRepository": null, + "licenseRepository": null, + "configuration": null, + "serverCount": 4, + "storageCount": 0, + "clusterCount": 1, + "serviceCount": 0, + "switchCount": 0, + "vmCount": 0, + "sdnasCount": 0, + "brownfieldTemplateType": "NONE", + "networks": [ + { + "id": "ff80808177f8823b0177f8bb82d80005", + "name": "flex-data2", + "description": "", + "type": "SCALEIO_DATA", + "vlanId": 105, + "static": true, + "staticNetworkConfiguration": { + "gateway": null, + "subnet": "1.1.1.0", + "primaryDns": null, + "secondaryDns": null, + "dnsSuffix": null, + "ipRange": null, + "ipAddress": null, + "staticRoute": null + }, + "destinationIpAddress": "1.1.1.0" + } + ], + "blockServiceOperationsMap": {} + }] ''' from ansible.module_utils.basic import AnsibleModule from ansible_collections.dellemc.powerflex.plugins.module_utils.storage.dell \ import utils +from ansible_collections.dellemc.powerflex.plugins.module_utils.storage.dell.libraries.configuration \ + import Configuration +import re LOG = utils.get_logger('info') +UNSUPPORTED_SUBSET_FOR_VERSION = 'One or more specified subset is not supported for the PowerFlex version.' +POWERFLEX_MANAGER_GATHER_SUBSET = {'managed_device', 'deployment', 'service_template'} +MIN_SUPPORTED_POWERFLEX_MANAGER_VERSION = 4.0 +ERROR_CODES = r'PARSE002|FILTER002|FILTER003' + class PowerFlexInfo(object): """Class with Info operations""" - filter_mapping = {'equal': 'eq.'} + filter_mapping = {'equal': 'eq', 'contains': 'co'} def __init__(self): """ Define all parameters required by this module""" @@ -1265,7 +1889,7 @@ class PowerFlexInfo(object): return result_list(sds) except Exception as e: - msg = 'Get sds list from powerflex array failed with' \ + msg = 'Get SDS list from powerflex array failed with' \ ' error %s' % (str(e)) LOG.error(msg) self.module.fail_json(msg=msg) @@ -1395,19 +2019,24 @@ class PowerFlexInfo(object): system """ try: - LOG.info('Getting snapshot schedules list ') + LOG.info('Getting snapshot policies list ') if filter_dict: - snapshot_schedules = \ + snapshot_policies = \ self.powerflex_conn.snapshot_policy.get( filter_fields=filter_dict) else: - snapshot_schedules = \ + snapshot_policies = \ self.powerflex_conn.snapshot_policy.get() - return result_list(snapshot_schedules) + if snapshot_policies: + statistics_map = self.powerflex_conn.utility.get_statistics_for_all_snapshot_policies() + list_of_snap_pol_ids_in_statistics = statistics_map.keys() + for item in snapshot_policies: + item['statistics'] = statistics_map[item['id']] if item['id'] in list_of_snap_pol_ids_in_statistics else {} + return result_list(snapshot_policies) except Exception as e: - msg = 'Get snapshot schedules list from powerflex array failed ' \ + msg = 'Get snapshot policies list from powerflex array failed ' \ 'with error %s' % (str(e)) LOG.error(msg) self.module.fail_json(msg=msg) @@ -1431,6 +2060,114 @@ class PowerFlexInfo(object): LOG.error(msg) self.module.fail_json(msg=msg) + def get_fault_sets_list(self, filter_dict=None): + """ Get the list of fault sets on a given PowerFlex storage + system """ + + try: + LOG.info('Getting fault set list ') + filter_pd = [] + if filter_dict: + if 'protectionDomainName' in filter_dict.keys(): + filter_pd = filter_dict['protectionDomainName'] + del filter_dict['protectionDomainName'] + fault_sets = self.powerflex_conn.fault_set.get(filter_fields=filter_dict) + else: + fault_sets = self.powerflex_conn.fault_set.get() + + fault_set_final = [] + if fault_sets: + for fault_set in fault_sets: + fault_set['protectionDomainName'] = Configuration(self.powerflex_conn, self.module).get_protection_domain( + protection_domain_id=fault_set["protectionDomainId"])["name"] + fault_set["SDS"] = Configuration(self.powerflex_conn, self.module).get_associated_sds( + fault_set_id=fault_set['id']) + fault_set_final.append(fault_set) + fault_sets = [] + for fault_set in fault_set_final: + if fault_set['protectionDomainName'] in filter_pd: + fault_sets.append(fault_set) + if len(filter_pd) != 0: + return result_list(fault_sets) + return result_list(fault_set_final) + + except Exception as e: + msg = 'Get fault set list from powerflex array failed ' \ + 'with error %s' % (str(e)) + LOG.error(msg) + self.module.fail_json(msg=msg) + + def get_managed_devices_list(self): + """ Get the list of managed devices on a given PowerFlex Manager system """ + try: + LOG.info('Getting managed devices list ') + devices = self.powerflex_conn.managed_device.get(filters=self.populate_filter_list(), + limit=self.get_param_value('limit'), + offset=self.get_param_value('offset'), + sort=self.get_param_value('sort')) + return devices + except Exception as e: + msg = f'Get managed devices from PowerFlex Manager failed with error {str(e)}' + return self.handle_error_exit(msg) + + def get_deployments_list(self): + """ Get the list of deployments on a given PowerFlex Manager system """ + try: + LOG.info('Getting deployments list ') + deployments = self.powerflex_conn.deployment.get(filters=self.populate_filter_list(), + sort=self.get_param_value('sort'), + limit=self.get_param_value('limit'), + offset=self.get_param_value('offset'), + include_devices=self.get_param_value('include_devices'), + include_template=self.get_param_value('include_template'), + full=self.get_param_value('full')) + return deployments + except Exception as e: + msg = f'Get deployments from PowerFlex Manager failed with error {str(e)}' + return self.handle_error_exit(msg) + + def get_service_templates_list(self): + """ Get the list of service templates on a given PowerFlex Manager system """ + try: + LOG.info('Getting service templates list ') + service_templates = self.powerflex_conn.service_template.get(filters=self.populate_filter_list(), + sort=self.get_param_value('sort'), + offset=self.get_param_value('offset'), + limit=self.get_param_value('limit'), + full=self.get_param_value('full'), + include_attachments=self.get_param_value('include_attachments')) + return service_templates + except Exception as e: + msg = f'Get service templates from PowerFlex Manager failed with error {str(e)}' + return self.handle_error_exit(msg) + + def handle_error_exit(self, detailed_message): + match = re.search(r"displayMessage=([^']+)", detailed_message) + error_message = match.group(1) if match else detailed_message + LOG.error(error_message) + if re.search(ERROR_CODES, detailed_message): + return [] + self.module.fail_json(msg=error_message) + + def get_param_value(self, param): + """ + Get the value of the given parameter. + Args: + param (str): The parameter to get the value for. + Returns: + The value of the parameter if it is different from the default value, + The value of the parameter if int and greater than 0 + otherwise None. + """ + if param in ('sort', 'offset', 'limit') and len(self.module.params.get('gather_subset')) > 1: + return None + + default_value = self.module_params.get(param).get('default') + param_value = self.module.params.get(param) + if (default_value != param_value) and (param_value >= 0 if isinstance(param_value, int) else True): + return param_value + return None + def validate_filter(self, filter_dict): """ Validate given filter_dict """ @@ -1447,6 +2184,16 @@ class PowerFlexInfo(object): LOG.error(msg) self.module.fail_json(msg=msg) + def populate_filter_list(self): + """Populate the filter list""" + if len(self.module.params.get('gather_subset')) > 1: + return [] + filters = self.module.params.get('filters') or [] + return [ + f'{self.filter_mapping.get(filter_dict["filter_operator"])},{filter_dict["filter_key"]},{filter_dict["filter_value"]}' + for filter_dict in filters + ] + def get_filters(self, filters): """Get the filters to be applied""" @@ -1454,7 +2201,7 @@ class PowerFlexInfo(object): for item in filters: self.validate_filter(item) f_op = item['filter_operator'] - if self.filter_mapping.get(f_op): + if self.filter_mapping.get(f_op) == self.filter_mapping.get("equal"): f_key = item['filter_key'] f_val = item['filter_value'] if f_key in filter_dict: @@ -1468,15 +2215,12 @@ class PowerFlexInfo(object): filter_dict[f_key] = [filter_dict[f_key], f_val] else: filter_dict[f_key] = f_val - else: - msg = "Given filter operator '{0}' is not supported." \ - "supported operators are : '{1}'".format( - f_op, - list(self.filter_mapping.keys())) - LOG.error(msg) - self.module.fail_json(msg=msg) return filter_dict + def validate_subset(self, api_version, subset): + if float(api_version) < MIN_SUPPORTED_POWERFLEX_MANAGER_VERSION and subset and set(subset).issubset(POWERFLEX_MANAGER_GATHER_SUBSET): + self.module.exit_json(msg=UNSUPPORTED_SUBSET_FOR_VERSION, skipped=True) + def perform_module_operation(self): """ Perform different actions on info based on user input in the playbook """ @@ -1498,8 +2242,13 @@ class PowerFlexInfo(object): device = [] rcgs = [] replication_pair = [] + fault_sets = [] + service_template = [] + managed_device = [] + deployment = [] subset = self.module.params['gather_subset'] + self.validate_subset(api_version, subset) if subset is not None: if 'sdc' in subset: sdc = self.get_sdc_list(filter_dict=filter_dict) @@ -1519,6 +2268,14 @@ class PowerFlexInfo(object): rcgs = self.get_replication_consistency_group_list(filter_dict=filter_dict) if 'replication_pair' in subset: replication_pair = self.get_replication_pair_list(filter_dict=filter_dict) + if 'fault_set' in subset: + fault_sets = self.get_fault_sets_list(filter_dict=filter_dict) + if 'managed_device' in subset: + managed_device = self.get_managed_devices_list() + if 'service_template' in subset: + service_template = self.get_service_templates_list() + if 'deployment' in subset: + deployment = self.get_deployments_list() self.module.exit_json( Array_Details=array_details, @@ -1531,7 +2288,11 @@ class PowerFlexInfo(object): Protection_Domains=protection_domain, Devices=device, Replication_Consistency_Groups=rcgs, - Replication_Pairs=replication_pair + Replication_Pairs=replication_pair, + Fault_Sets=fault_sets, + ManagedDevices=managed_device, + ServiceTemplates=service_template, + Deployments=deployment ) @@ -1556,15 +2317,24 @@ def get_powerflex_info_parameters(): return dict( gather_subset=dict(type='list', required=False, elements='str', choices=['vol', 'storage_pool', - 'protection_domain', 'sdc', 'sds', - 'snapshot_policy', 'device', 'rcg', 'replication_pair']), + 'protection_domain', 'sdc', 'sds', 'snapshot_policy', + 'device', 'rcg', 'replication_pair', 'fault_set', + 'service_template', 'managed_device', 'deployment']), filters=dict(type='list', required=False, elements='dict', options=dict(filter_key=dict(type='str', required=True, no_log=False), filter_operator=dict( type='str', required=True, - choices=['equal']), + choices=['equal', 'contains']), filter_value=dict(type='str', required=True) - ))) + )), + sort=dict(type='str'), + limit=dict(type='int', default=50), + offset=dict(type='int', default=0), + include_devices=dict(type='bool', default=True), + include_template=dict(type='bool', default=True), + full=dict(type='bool', default=False), + include_attachments=dict(type='bool', default=True) + ) def main(): |