New module: AWS storage gateway facts (#39491)

* Add a module to get storage gateway facts

* Review fixes

* Last review fixes

* Add filtering gathering & some fixes

* doc fix

* API error handling

* Remove ec2_argument_spec import

Use imported BotoCoreError and ClientError rather than botocore.exceptions
pull/39622/merge
Loïc Blot 6 years ago committed by Ryan Brown
parent f872b70449
commit 88df583af7

@ -0,0 +1,354 @@
#!/usr/bin/python
# Copyright (c) 2018 Loic BLOT <loic.blot@unix-experience.fr>
# This module is sponsored by E.T.A.I. (www.etai.fr)
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: aws_sgw_facts
short_description: Fetch AWS Storage Gateway facts
description:
- Fetch AWS Storage Gateway facts
version_added: "2.6"
requirements: [ boto3 ]
author: "Loic Blot <loic.blot@unix-experience.fr>"
options:
gather_local_disks:
description:
- Gather local disks attached to the storage gateway.
type: bool
required: false
default: true
gather_tapes:
description:
- Gather tape information for storage gateways in tape mode.
type: bool
required: false
default: true
gather_file_shares:
description:
- Gather file share information for storage gateways in s3 mode.
type: bool
required: false
default: true
gather_volumes:
description:
- Gather volume information for storage gateways in iSCSI (cached & stored) modes.
type: bool
required: false
default: true
extends_documentation_fragment:
- aws
- ec2
'''
RETURN = '''
gateways:
description: list of gateway objects
returned: always
type: complex
contains:
gateway_arn:
description: "Storage Gateway ARN"
returned: always
type: string
sample: "arn:aws:storagegateway:eu-west-1:367709993819:gateway/sgw-9999F888"
gateway_id:
description: "Storage Gateway ID"
returned: always
type: string
sample: "sgw-9999F888"
gateway_name:
description: "Storage Gateway friendly name"
returned: always
type: string
sample: "my-sgw-01"
gateway_operational_state:
description: "Storage Gateway operational state"
returned: always
type: string
sample: "ACTIVE"
gateway_type:
description: "Storage Gateway type"
returned: always
type: string
sample: "FILE_S3"
file_shares:
description: "Storage gateway file shares"
returned: when gateway_type == "FILE_S3"
type: complex
contains:
file_share_arn:
description: "File share ARN"
returned: always
type: string
sample: "arn:aws:storagegateway:eu-west-1:399805793479:share/share-AF999C88"
file_share_id:
description: "File share ID"
returned: always
type: string
sample: "share-AF999C88"
file_share_status:
description: "File share status"
returned: always
type: string
sample: "AVAILABLE"
tapes:
description: "Storage Gateway tapes"
returned: when gateway_type == "VTL"
type: complex
contains:
tape_arn:
description: "Tape ARN"
returned: always
type: string
sample: "arn:aws:storagegateway:eu-west-1:399805793479:tape/tape-AF999C88"
tape_barcode:
description: "Tape ARN"
returned: always
type: string
sample: "tape-AF999C88"
tape_size_in_bytes:
description: "Tape ARN"
returned: always
type: integer
sample: 555887569
tape_status:
description: "Tape ARN"
returned: always
type: string
sample: "AVAILABLE"
local_disks:
description: "Storage gateway local disks"
returned: always
type: complex
contains:
disk_allocation_type:
description: "Disk allocation type"
returned: always
type: string
sample: "CACHE STORAGE"
disk_id:
description: "Disk ID on the system"
returned: always
type: string
sample: "pci-0000:00:1f.0"
disk_node:
description: "Disk parent block device"
returned: always
type: string
sample: "/dev/sdb"
disk_path:
description: "Disk path used for the cache"
returned: always
type: string
sample: "/dev/nvme1n1"
disk_size_in_bytes:
description: "Disk size in bytes"
returned: always
type: integer
sample: 107374182400
disk_status:
description: "Disk status"
returned: always
type: string
sample: "present"
'''
EXAMPLES = '''
# Note: These examples do not set authentication details, see the AWS Guide for details.
- name: "Get AWS storage gateway facts"
aws_sgw_facts:
- name: "Get AWS storage gateway facts for region eu-west-3"
aws_sgw_facts:
region: eu-west-3
'''
from ansible.module_utils.aws.core import AnsibleAWSModule
from ansible.module_utils.ec2 import camel_dict_to_snake_dict
try:
from botocore.exceptions import BotoCoreError, ClientError
except ImportError:
pass # caught by imported HAS_BOTO3
class SGWFactsManager(object):
def __init__(self, client, module):
self.client = client
self.module = module
self.name = self.module.params.get('name')
def fetch(self):
gateways = self.list_gateways()
for gateway in gateways:
if self.module.params.get('gather_local_disks'):
self.list_local_disks(gateway)
# File share gateway
if gateway["gateway_type"] == "FILE_S3" and self.module.params.get('gather_file_shares'):
self.list_gateway_file_shares(gateway)
# Volume tape gateway
elif gateway["gateway_type"] == "VTL" and self.module.params.get('gather_tapes'):
self.list_gateway_vtl(gateway)
# iSCSI gateway
elif gateway["gateway_type"] in ["CACHED", "STORED"] and self.module.params.get('gather_volumes'):
self.list_gateway_volumes(gateway)
self.module.exit_json(gateways=gateways)
"""
List all storage gateways for the AWS endpoint.
"""
def list_gateways(self):
try:
paginator = self.client.get_paginator('list_gateways')
response = paginator.paginate(
PaginationConfig={
'PageSize': 100,
}
).build_full_result()
gateways = []
for gw in response["Gateways"]:
gateways.append(camel_dict_to_snake_dict(gw))
return gateways
except (BotoCoreError, ClientError) as e:
self.module.fail_json_aws(e, msg="Couldn't list storage gateways")
"""
Read file share objects from AWS API response.
Drop the gateway_arn attribute from response, as it will be duplicate with parent object.
"""
@staticmethod
def _read_gateway_fileshare_response(fileshares, aws_reponse):
for share in aws_reponse["FileShareInfoList"]:
share_obj = camel_dict_to_snake_dict(share)
if "gateway_arn" in share_obj:
del share_obj["gateway_arn"]
fileshares.append(share_obj)
return aws_reponse["NextMarker"] if "NextMarker" in aws_reponse else None
"""
List file shares attached to AWS storage gateway when in S3 mode.
"""
def list_gateway_file_shares(self, gateway):
try:
response = self.client.list_file_shares(
GatewayARN=gateway["gateway_arn"],
Limit=100
)
gateway["file_shares"] = []
marker = self._read_gateway_fileshare_response(gateway["file_shares"], response)
while marker is not None:
response = self.client.list_file_shares(
GatewayARN=gateway["gateway_arn"],
Marker=marker,
Limit=100
)
marker = self._read_gateway_fileshare_response(gateway["file_shares"], response)
except (BotoCoreError, ClientError) as e:
self.module.fail_json_aws(e, msg="Couldn't list gateway file shares")
"""
List storage gateway local disks
"""
def list_local_disks(self, gateway):
try:
gateway['local_disks'] = [camel_dict_to_snake_dict(disk) for disk in
self.client.list_local_disks(GatewayARN=gateway["gateway_arn"])['Disks']]
except (BotoCoreError, ClientError) as e:
self.module.fail_json_aws(e, msg="Couldn't list storage gateway local disks")
"""
Read tape objects from AWS API response.
Drop the gateway_arn attribute from response, as it will be duplicate with parent object.
"""
@staticmethod
def _read_gateway_tape_response(tapes, aws_response):
for tape in aws_response["TapeInfos"]:
tape_obj = camel_dict_to_snake_dict(tape)
if "gateway_arn" in tape_obj:
del tape_obj["gateway_arn"]
tapes.append(tape_obj)
return aws_response["Marker"] if "Marker" in aws_response else None
"""
List VTL & VTS attached to AWS storage gateway in VTL mode
"""
def list_gateway_vtl(self, gateway):
try:
response = self.client.list_tapes(
Limit=100
)
gateway["tapes"] = []
marker = self._read_gateway_tape_response(gateway["tapes"], response)
while marker is not None:
response = self.client.list_tapes(
Marker=marker,
Limit=100
)
marker = self._read_gateway_tape_response(gateway["tapes"], response)
except (BotoCoreError, ClientError) as e:
self.module.fail_json_aws(e, msg="Couldn't list storage gateway tapes")
"""
List volumes attached to AWS storage gateway in CACHED or STORAGE mode
"""
def list_gateway_volumes(self, gateway):
try:
paginator = self.client.get_paginator('list_volumes')
response = paginator.paginate(
GatewayARN=gateway["gateway_arn"],
PaginationConfig={
'PageSize': 100,
}
).build_full_result()
gateway["volumes"] = []
for volume in response["VolumeInfos"]:
volume_obj = camel_dict_to_snake_dict(volume)
if "gateway_arn" in volume_obj:
del volume_obj["gateway_arn"]
if "gateway_id" in volume_obj:
del volume_obj["gateway_id"]
gateway["volumes"].append(volume_obj)
except (BotoCoreError, ClientError) as e:
self.module.fail_json_aws(e, msg="Couldn't list storage gateway volumes")
def main():
argument_spec = dict(
gather_local_disks=dict(type='bool', default=True),
gather_tapes=dict(type='bool', default=True),
gather_file_shares=dict(type='bool', default=True),
gather_volumes=dict(type='bool', default=True)
)
module = AnsibleAWSModule(argument_spec=argument_spec)
client = module.client('storagegateway')
if client is None: # this should never happen
module.fail_json(msg='Unknown error, failed to create storagegateway client, no information from boto.')
SGWFactsManager(client, module).fetch()
if __name__ == '__main__':
main()
Loading…
Cancel
Save