1#!/usr/bin/python 2 3# Copyright: (c) 2018, Loic BLOT (@nerzhul) <loic.blot@unix-experience.fr> 4# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 6# This module is sponsored by E.T.A.I. (www.etai.fr) 7 8ANSIBLE_METADATA = {'metadata_version': '1.1', 9 'status': ['preview'], 10 'supported_by': 'community'} 11 12DOCUMENTATION = ''' 13--- 14module: aws_sgw_info 15short_description: Fetch AWS Storage Gateway information 16description: 17 - Fetch AWS Storage Gateway information 18 - This module was called C(aws_sgw_facts) before Ansible 2.9. The usage did not change. 19version_added: "2.6" 20requirements: [ boto3 ] 21author: Loic Blot (@nerzhul) <loic.blot@unix-experience.fr> 22options: 23 gather_local_disks: 24 description: 25 - Gather local disks attached to the storage gateway. 26 type: bool 27 required: false 28 default: true 29 gather_tapes: 30 description: 31 - Gather tape information for storage gateways in tape mode. 32 type: bool 33 required: false 34 default: true 35 gather_file_shares: 36 description: 37 - Gather file share information for storage gateways in s3 mode. 38 type: bool 39 required: false 40 default: true 41 gather_volumes: 42 description: 43 - Gather volume information for storage gateways in iSCSI (cached & stored) modes. 44 type: bool 45 required: false 46 default: true 47extends_documentation_fragment: 48 - aws 49 - ec2 50''' 51 52RETURN = ''' 53gateways: 54 description: list of gateway objects 55 returned: always 56 type: complex 57 contains: 58 gateway_arn: 59 description: "Storage Gateway ARN" 60 returned: always 61 type: str 62 sample: "arn:aws:storagegateway:eu-west-1:367709993819:gateway/sgw-9999F888" 63 gateway_id: 64 description: "Storage Gateway ID" 65 returned: always 66 type: str 67 sample: "sgw-9999F888" 68 gateway_name: 69 description: "Storage Gateway friendly name" 70 returned: always 71 type: str 72 sample: "my-sgw-01" 73 gateway_operational_state: 74 description: "Storage Gateway operational state" 75 returned: always 76 type: str 77 sample: "ACTIVE" 78 gateway_type: 79 description: "Storage Gateway type" 80 returned: always 81 type: str 82 sample: "FILE_S3" 83 file_shares: 84 description: "Storage gateway file shares" 85 returned: when gateway_type == "FILE_S3" 86 type: complex 87 contains: 88 file_share_arn: 89 description: "File share ARN" 90 returned: always 91 type: str 92 sample: "arn:aws:storagegateway:eu-west-1:399805793479:share/share-AF999C88" 93 file_share_id: 94 description: "File share ID" 95 returned: always 96 type: str 97 sample: "share-AF999C88" 98 file_share_status: 99 description: "File share status" 100 returned: always 101 type: str 102 sample: "AVAILABLE" 103 tapes: 104 description: "Storage Gateway tapes" 105 returned: when gateway_type == "VTL" 106 type: complex 107 contains: 108 tape_arn: 109 description: "Tape ARN" 110 returned: always 111 type: str 112 sample: "arn:aws:storagegateway:eu-west-1:399805793479:tape/tape-AF999C88" 113 tape_barcode: 114 description: "Tape ARN" 115 returned: always 116 type: str 117 sample: "tape-AF999C88" 118 tape_size_in_bytes: 119 description: "Tape ARN" 120 returned: always 121 type: int 122 sample: 555887569 123 tape_status: 124 description: "Tape ARN" 125 returned: always 126 type: str 127 sample: "AVAILABLE" 128 local_disks: 129 description: "Storage gateway local disks" 130 returned: always 131 type: complex 132 contains: 133 disk_allocation_type: 134 description: "Disk allocation type" 135 returned: always 136 type: str 137 sample: "CACHE STORAGE" 138 disk_id: 139 description: "Disk ID on the system" 140 returned: always 141 type: str 142 sample: "pci-0000:00:1f.0" 143 disk_node: 144 description: "Disk parent block device" 145 returned: always 146 type: str 147 sample: "/dev/sdb" 148 disk_path: 149 description: "Disk path used for the cache" 150 returned: always 151 type: str 152 sample: "/dev/nvme1n1" 153 disk_size_in_bytes: 154 description: "Disk size in bytes" 155 returned: always 156 type: int 157 sample: 107374182400 158 disk_status: 159 description: "Disk status" 160 returned: always 161 type: str 162 sample: "present" 163''' 164 165EXAMPLES = ''' 166# Note: These examples do not set authentication details, see the AWS Guide for details. 167 168- name: "Get AWS storage gateway information" 169 aws_sgw_info: 170 171- name: "Get AWS storage gateway information for region eu-west-3" 172 aws_sgw_info: 173 region: eu-west-3 174''' 175 176from ansible.module_utils.aws.core import AnsibleAWSModule 177from ansible.module_utils.ec2 import camel_dict_to_snake_dict 178 179try: 180 from botocore.exceptions import BotoCoreError, ClientError 181except ImportError: 182 pass # caught by imported HAS_BOTO3 183 184 185class SGWInformationManager(object): 186 def __init__(self, client, module): 187 self.client = client 188 self.module = module 189 self.name = self.module.params.get('name') 190 191 def fetch(self): 192 gateways = self.list_gateways() 193 for gateway in gateways: 194 if self.module.params.get('gather_local_disks'): 195 self.list_local_disks(gateway) 196 # File share gateway 197 if gateway["gateway_type"] == "FILE_S3" and self.module.params.get('gather_file_shares'): 198 self.list_gateway_file_shares(gateway) 199 # Volume tape gateway 200 elif gateway["gateway_type"] == "VTL" and self.module.params.get('gather_tapes'): 201 self.list_gateway_vtl(gateway) 202 # iSCSI gateway 203 elif gateway["gateway_type"] in ["CACHED", "STORED"] and self.module.params.get('gather_volumes'): 204 self.list_gateway_volumes(gateway) 205 206 self.module.exit_json(gateways=gateways) 207 208 """ 209 List all storage gateways for the AWS endpoint. 210 """ 211 def list_gateways(self): 212 try: 213 paginator = self.client.get_paginator('list_gateways') 214 response = paginator.paginate( 215 PaginationConfig={ 216 'PageSize': 100, 217 } 218 ).build_full_result() 219 220 gateways = [] 221 for gw in response["Gateways"]: 222 gateways.append(camel_dict_to_snake_dict(gw)) 223 224 return gateways 225 226 except (BotoCoreError, ClientError) as e: 227 self.module.fail_json_aws(e, msg="Couldn't list storage gateways") 228 229 """ 230 Read file share objects from AWS API response. 231 Drop the gateway_arn attribute from response, as it will be duplicate with parent object. 232 """ 233 @staticmethod 234 def _read_gateway_fileshare_response(fileshares, aws_reponse): 235 for share in aws_reponse["FileShareInfoList"]: 236 share_obj = camel_dict_to_snake_dict(share) 237 if "gateway_arn" in share_obj: 238 del share_obj["gateway_arn"] 239 fileshares.append(share_obj) 240 241 return aws_reponse["NextMarker"] if "NextMarker" in aws_reponse else None 242 243 """ 244 List file shares attached to AWS storage gateway when in S3 mode. 245 """ 246 def list_gateway_file_shares(self, gateway): 247 try: 248 response = self.client.list_file_shares( 249 GatewayARN=gateway["gateway_arn"], 250 Limit=100 251 ) 252 253 gateway["file_shares"] = [] 254 marker = self._read_gateway_fileshare_response(gateway["file_shares"], response) 255 256 while marker is not None: 257 response = self.client.list_file_shares( 258 GatewayARN=gateway["gateway_arn"], 259 Marker=marker, 260 Limit=100 261 ) 262 263 marker = self._read_gateway_fileshare_response(gateway["file_shares"], response) 264 except (BotoCoreError, ClientError) as e: 265 self.module.fail_json_aws(e, msg="Couldn't list gateway file shares") 266 267 """ 268 List storage gateway local disks 269 """ 270 def list_local_disks(self, gateway): 271 try: 272 gateway['local_disks'] = [camel_dict_to_snake_dict(disk) for disk in 273 self.client.list_local_disks(GatewayARN=gateway["gateway_arn"])['Disks']] 274 except (BotoCoreError, ClientError) as e: 275 self.module.fail_json_aws(e, msg="Couldn't list storage gateway local disks") 276 277 """ 278 Read tape objects from AWS API response. 279 Drop the gateway_arn attribute from response, as it will be duplicate with parent object. 280 """ 281 @staticmethod 282 def _read_gateway_tape_response(tapes, aws_response): 283 for tape in aws_response["TapeInfos"]: 284 tape_obj = camel_dict_to_snake_dict(tape) 285 if "gateway_arn" in tape_obj: 286 del tape_obj["gateway_arn"] 287 tapes.append(tape_obj) 288 289 return aws_response["Marker"] if "Marker" in aws_response else None 290 291 """ 292 List VTL & VTS attached to AWS storage gateway in VTL mode 293 """ 294 def list_gateway_vtl(self, gateway): 295 try: 296 response = self.client.list_tapes( 297 Limit=100 298 ) 299 300 gateway["tapes"] = [] 301 marker = self._read_gateway_tape_response(gateway["tapes"], response) 302 303 while marker is not None: 304 response = self.client.list_tapes( 305 Marker=marker, 306 Limit=100 307 ) 308 309 marker = self._read_gateway_tape_response(gateway["tapes"], response) 310 except (BotoCoreError, ClientError) as e: 311 self.module.fail_json_aws(e, msg="Couldn't list storage gateway tapes") 312 313 """ 314 List volumes attached to AWS storage gateway in CACHED or STORAGE mode 315 """ 316 def list_gateway_volumes(self, gateway): 317 try: 318 paginator = self.client.get_paginator('list_volumes') 319 response = paginator.paginate( 320 GatewayARN=gateway["gateway_arn"], 321 PaginationConfig={ 322 'PageSize': 100, 323 } 324 ).build_full_result() 325 326 gateway["volumes"] = [] 327 for volume in response["VolumeInfos"]: 328 volume_obj = camel_dict_to_snake_dict(volume) 329 if "gateway_arn" in volume_obj: 330 del volume_obj["gateway_arn"] 331 if "gateway_id" in volume_obj: 332 del volume_obj["gateway_id"] 333 334 gateway["volumes"].append(volume_obj) 335 except (BotoCoreError, ClientError) as e: 336 self.module.fail_json_aws(e, msg="Couldn't list storage gateway volumes") 337 338 339def main(): 340 argument_spec = dict( 341 gather_local_disks=dict(type='bool', default=True), 342 gather_tapes=dict(type='bool', default=True), 343 gather_file_shares=dict(type='bool', default=True), 344 gather_volumes=dict(type='bool', default=True) 345 ) 346 347 module = AnsibleAWSModule(argument_spec=argument_spec) 348 if module._name == 'aws_sgw_facts': 349 module.deprecate("The 'aws_sgw_facts' module has been renamed to 'aws_sgw_info'", version='2.13') 350 client = module.client('storagegateway') 351 352 if client is None: # this should never happen 353 module.fail_json(msg='Unknown error, failed to create storagegateway client, no information from boto.') 354 355 SGWInformationManager(client, module).fetch() 356 357 358if __name__ == '__main__': 359 main() 360