Coverage for plugins/modules/purefb_info.py: 64%

677 statements  

« prev     ^ index     » next       coverage.py v7.14.1, created at 2026-10-30 17:06 -0400

1#!/usr/bin/python 

2# -*- coding: utf-8 -*- 

3 

4# (c) 2019, Simon Dodsley (simon@everpuredata.com) 

5# GNU General Public License v3.0+ (see COPYING or 

6# https://www.gnu.org/licenses/gpl-3.0.txt) 

7 

8from __future__ import absolute_import, division, print_function 

9 

10__metaclass__ = type 

11 

12ANSIBLE_METADATA = { 

13 "metadata_version": "1.1", 

14 "status": ["preview"], 

15 "supported_by": "community", 

16} 

17 

18DOCUMENTATION = r""" 

19--- 

20module: purefb_info 

21version_added: '1.0.0' 

22short_description: Collect information from Everpure FlashBlade 

23description: 

24 - Collect information from a Everpure FlashBlade running the 

25 Purity//FB operating system. By default, the module will collect basic 

26 information including hosts, host groups, protection 

27 groups and volume counts. Additional information can be collected 

28 based on the configured set of arguements. 

29author: 

30 - Everpure Ansible Team (@sdodsley) <pure-ansible-team@everpuredata.com> 

31options: 

32 gather_subset: 

33 description: 

34 - When supplied, this argument will define the information to be collected. 

35 Possible values for this include all, minimum, config, performance, 

36 capacity, network, subnets, lags, filesystems, snapshots, buckets, 

37 replication, policies, arrays, accounts, admins, ad, kerberos, 

38 drives, servers, fleet and realms. 

39 - The C(filesystems) subset surfaces the legacy file system keys 

40 C(nfs_rules), C(export_policy), C(smb_client_policy) and 

41 C(smb_share_policy). Purity//FB marks the underlying fields as 

42 deprecated in favour of File System Exports, so these keys may 

43 return C(null) in future releases. Read export policy 

44 assignments from the per-filesystem C(file_system_exports) 

45 list (and the top-level C(file_system_exports) view under 

46 C(subset=filesystems)/C(subset=all)) instead. These keys will 

47 be removed from this module in 2.0.0. 

48 required: false 

49 type: list 

50 elements: str 

51 default: minimum 

52extends_documentation_fragment: 

53 - everpure.flashblade.everpure.fb 

54""" 

55 

56EXAMPLES = r""" 

57- name: collect default set of info 

58 everpure.flashblade.purefb_info: 

59 fb_url: 10.10.10.2 

60 api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641 

61 register: blade_info 

62- name: show default information 

63 debug: 

64 msg: "{{ blade_info['purefb_info']['default'] }}" 

65 

66- name: collect configuration and capacity info 

67 everpure.flashblade.purefb_info: 

68 gather_subset: 

69 - config 

70 fb_url: 10.10.10.2 

71 api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641 

72 register: blade_info 

73- name: show config information 

74 debug: 

75 msg: "{{ blade_info['purefb_info']['config'] }}" 

76 

77- name: collect all info 

78 everpure.flashblade.purefb_info: 

79 gather_subset: 

80 - all 

81 fb_url: 10.10.10.2 

82 api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641 

83 register: blade_info 

84- name: show all information 

85 debug: 

86 msg: "{{ blade_info['purefb_info'] }}" 

87""" 

88 

89RETURN = r""" 

90purefb_info: 

91 description: Returns the information collected from the FlashBlade 

92 returned: always 

93 type: dict 

94""" 

95 

96 

97from ansible.module_utils.basic import AnsibleModule 

98from ansible_collections.everpure.flashblade.plugins.module_utils.purefb import ( 

99 get_system, 

100 purefb_argument_spec, 

101) 

102from ansible_collections.everpure.flashblade.plugins.module_utils.version import ( 

103 LooseVersion, 

104) 

105from ansible_collections.everpure.flashblade.plugins.module_utils.common import ( 

106 get_rest_api_version, 

107) 

108from ansible_collections.everpure.flashblade.plugins.module_utils.time_utils import ( 

109 milliseconds_to_time, 

110) 

111from datetime import datetime, timezone 

112import time 

113 

114KMIP_API_VERSION = "2.1" 

115DRIVES_API_VERSION = "2.5" 

116SECURITY_API_VERSION = "2.7" 

117BUCKET_API_VERSION = "2.8" 

118SMB_CLIENT_API_VERSION = "2.10" 

119SPACE_API_VERSION = "2.11" 

120PUBLIC_API_VERSION = "2.12" 

121NAP_API_VERSION = "2.13" 

122RA_DURATION_API_VERSION = "2.14" 

123SMTP_ENCRYPT_API_VERSION = "2.15" 

124WORM_API_VERSION = "2.15" 

125SERVERS_API_VERSION = "2.16" 

126PASSWORD_POLICY_API_VERSION = "2.16" 

127FLEET_API_VERSION = "2.17" 

128TLS_API_VERSION = "2.17" 

129REALMS_API_VERSION = "2.19" 

130S3_EXPORT_API_VERSION = "2.20" 

131 

132 

133def _bytes_to_human(bytes_number): 

134 if bytes_number: 

135 labels = ["B/s", "KB/s", "MB/s", "GB/s", "TB/s", "PB/s"] 

136 i = 0 

137 double_bytes = bytes_number 

138 while i < len(labels) and bytes_number >= 1024: 

139 double_bytes = bytes_number / 1024.0 

140 i += 1 

141 bytes_number = bytes_number / 1024 

142 return str(round(double_bytes, 2)) + " " + labels[i] 

143 return None 

144 

145 

146def generate_default_dict(blade): 

147 default_info = {} 

148 # NOTE(latent bug): this previously read list(blade.get_versions().items)[0] 

149 # - a single version string - so the SECURITY/NAP/RA_DURATION gates below 

150 # were substring checks that could never match as intended. The 

151 # get_rest_api_version()/LooseVersion migration makes these gates evaluate 

152 # correctly, so the gated sections can now appear where they never did. 

153 api_version = get_rest_api_version(blade) 

154 defaults = list(blade.get_arrays().items)[0] 

155 default_info["flashblade_name"] = defaults.name 

156 default_info["purity_version"] = defaults.version 

157 # the login (MOTD) banner, so purefb_banner changes can be read back 

158 default_info["banner"] = getattr(defaults, "banner", None) 

159 default_info["filesystems"] = blade.get_file_systems().total_item_count 

160 default_info["snapshots"] = blade.get_file_system_snapshots().total_item_count 

161 default_info["buckets"] = blade.get_buckets().total_item_count 

162 default_info["object_store_users"] = blade.get_object_store_users().total_item_count 

163 default_info["object_store_accounts"] = ( 

164 blade.get_object_store_accounts().total_item_count 

165 ) 

166 default_info["blades"] = blade.get_blades().total_item_count 

167 default_info["certificates"] = blade.get_certificates().total_item_count 

168 default_info["total_capacity"] = list(blade.get_arrays_space().items)[0].capacity 

169 default_info["api_versions"] = api_version 

170 default_info["policies"] = blade.get_policies_all().total_item_count 

171 # Count policies by type 

172 all_policies = list(blade.get_policies_all().items) 

173 default_info["snapshot_policies"] = sum( 

174 1 for p in all_policies if p.policy_type == "snapshot" 

175 ) 

176 default_info["access_policies"] = sum( 

177 1 for p in all_policies if p.policy_type == "access" 

178 ) 

179 default_info["nfs_policies"] = sum( 

180 1 for p in all_policies if p.policy_type == "nfs" 

181 ) 

182 default_info["smb_share_policies"] = sum( 

183 1 for p in all_policies if p.policy_type == "smb_share" 

184 ) 

185 default_info["smb_client_policies"] = sum( 

186 1 for p in all_policies if p.policy_type == "smb_client" 

187 ) 

188 default_info["network_policies"] = sum( 

189 1 for p in all_policies if p.policy_type == "network" 

190 ) 

191 default_info["worm_policies"] = sum( 

192 1 for p in all_policies if p.policy_type == "worm" 

193 ) 

194 default_info["telemetry_metrics_policies"] = sum( 

195 1 for p in all_policies if p.policy_type == "telemetry-metrics" 

196 ) 

197 default_info["certificate_groups"] = blade.get_certificate_groups().total_item_count 

198 default_info["fs_replicas"] = blade.get_file_system_replica_links().total_item_count 

199 default_info["remote_credentials"] = ( 

200 blade.get_object_store_remote_credentials().total_item_count 

201 ) 

202 default_info["bucket_replicas"] = blade.get_bucket_replica_links().total_item_count 

203 default_info["connected_arrays"] = blade.get_array_connections().total_item_count 

204 default_info["targets"] = blade.get_targets().total_item_count 

205 default_info["kerberos_keytabs"] = blade.get_keytabs().total_item_count 

206 default_info["syslog_servers"] = len(blade.get_syslog_servers().items) 

207 default_info["object_store_virtual_hosts"] = len( 

208 blade.get_object_store_virtual_hosts().items 

209 ) 

210 default_info["api_clients"] = len(blade.get_api_clients().items) 

211 default_info["idle_timeout"] = int(defaults.idle_timeout / 60000) 

212 if list(blade.get_arrays_eula().items)[0].signature.accepted: 

213 default_info["EULA"] = "Signed" 

214 else: 

215 default_info["EULA"] = "Not Signed" 

216 admin_settings = list(blade.get_admins_settings().items)[0] 

217 default_info["max_login_attempts"] = admin_settings.max_login_attempts 

218 default_info["min_password_length"] = admin_settings.min_password_length 

219 if admin_settings.lockout_duration: 

220 default_info["lockout_duration"] = ( 

221 str(admin_settings.lockout_duration / 1000) + " seconds" 

222 ) 

223 default_info["smb_mode"] = getattr(defaults, "smb_mode", None) 

224 default_info["timezone"] = defaults.time_zone 

225 default_info["product_type"] = getattr(defaults, "product_type", "Unknown") 

226 if LooseVersion(SECURITY_API_VERSION) <= LooseVersion(api_version): 

227 dar = defaults.encryption.data_at_rest 

228 default_info["encryption"] = { 

229 "data_at_rest_enabled": dar.enabled, 

230 "data_at_rest_algorithms": dar.algorithms, 

231 "data_at_rest_entropy_source": dar.entropy_source, 

232 } 

233 keys = list(blade.get_support_verification_keys().items) 

234 default_info["support_keys"] = {} 

235 for key in keys: 

236 keyname = key.name 

237 default_info["support_keys"][keyname] = {key.verification_key} 

238 default_info["security_update"] = getattr(defaults, "security_update", None) 

239 if LooseVersion(NAP_API_VERSION) <= LooseVersion(api_version): 

240 default_info["network_access_protocol"] = getattr( 

241 defaults.network_access_policy, "name", "None" 

242 ) 

243 ra_info = list(blade.get_support().items)[0] 

244 if ra_info.remote_assist_active: 

245 ra_expires = datetime.fromtimestamp( 

246 int(ra_info.remote_assist_expires) / 1000 

247 ).strftime("%Y-%m-%d %H:%M:%S") 

248 ra_opened = datetime.fromtimestamp( 

249 int(ra_info.remote_assist_opened) / 1000 

250 ).strftime("%Y-%m-%d %H:%M:%S") 

251 else: 

252 ra_expires = ra_opened = None 

253 default_info["remote_assist"] = { 

254 "phonehome_enabled": ra_info.phonehome_enabled, 

255 "proxy": ra_info.proxy, 

256 "ra_active": ra_info.remote_assist_active, 

257 "ra_expires": ra_expires, 

258 "ra_opened": ra_opened, 

259 "ra_status": ra_info.remote_assist_status, 

260 } 

261 if LooseVersion(RA_DURATION_API_VERSION) <= LooseVersion(api_version): 

262 default_info["remote_assist"]["ra_duration"] = ra_info.remote_assist_duration 

263 return default_info 

264 

265 

266def generate_perf_dict(blade): 

267 perf_info = {} 

268 total_perf = list(blade.get_arrays_performance().items)[0] 

269 http_perf = list(blade.get_arrays_performance(protocol="http").items)[0] 

270 s3_perf = list(blade.get_arrays_performance(protocol="s3").items)[0] 

271 nfs_perf = list(blade.get_arrays_performance(protocol="nfs").items)[0] 

272 perf_info["aggregate"] = { 

273 "bytes_per_op": total_perf.bytes_per_op, 

274 "bytes_per_read": total_perf.bytes_per_read, 

275 "bytes_per_write": total_perf.bytes_per_write, 

276 "read_bytes_per_sec": total_perf.read_bytes_per_sec, 

277 "reads_per_sec": total_perf.reads_per_sec, 

278 "usec_per_other_op": total_perf.usec_per_other_op, 

279 "usec_per_read_op": total_perf.usec_per_read_op, 

280 "usec_per_write_op": total_perf.usec_per_write_op, 

281 "write_bytes_per_sec": total_perf.write_bytes_per_sec, 

282 "writes_per_sec": total_perf.writes_per_sec, 

283 } 

284 perf_info["http"] = { 

285 "bytes_per_op": http_perf.bytes_per_op, 

286 "bytes_per_read": http_perf.bytes_per_read, 

287 "bytes_per_write": http_perf.bytes_per_write, 

288 "read_bytes_per_sec": http_perf.read_bytes_per_sec, 

289 "reads_per_sec": http_perf.reads_per_sec, 

290 "usec_per_other_op": http_perf.usec_per_other_op, 

291 "usec_per_read_op": http_perf.usec_per_read_op, 

292 "usec_per_write_op": http_perf.usec_per_write_op, 

293 "write_bytes_per_sec": http_perf.write_bytes_per_sec, 

294 "writes_per_sec": http_perf.writes_per_sec, 

295 } 

296 perf_info["s3"] = { 

297 "bytes_per_op": s3_perf.bytes_per_op, 

298 "bytes_per_read": s3_perf.bytes_per_read, 

299 "bytes_per_write": s3_perf.bytes_per_write, 

300 "read_bytes_per_sec": s3_perf.read_bytes_per_sec, 

301 "reads_per_sec": s3_perf.reads_per_sec, 

302 "usec_per_other_op": s3_perf.usec_per_other_op, 

303 "usec_per_read_op": s3_perf.usec_per_read_op, 

304 "usec_per_write_op": s3_perf.usec_per_write_op, 

305 "write_bytes_per_sec": s3_perf.write_bytes_per_sec, 

306 "writes_per_sec": s3_perf.writes_per_sec, 

307 } 

308 perf_info["nfs"] = { 

309 "bytes_per_op": nfs_perf.bytes_per_op, 

310 "bytes_per_read": nfs_perf.bytes_per_read, 

311 "bytes_per_write": nfs_perf.bytes_per_write, 

312 "read_bytes_per_sec": nfs_perf.read_bytes_per_sec, 

313 "reads_per_sec": nfs_perf.reads_per_sec, 

314 "usec_per_other_op": nfs_perf.usec_per_other_op, 

315 "usec_per_read_op": nfs_perf.usec_per_read_op, 

316 "usec_per_write_op": nfs_perf.usec_per_write_op, 

317 "write_bytes_per_sec": nfs_perf.write_bytes_per_sec, 

318 "writes_per_sec": nfs_perf.writes_per_sec, 

319 } 

320 if blade.get_array_connections_performance_replication().total_item_count > 0: 

321 file_repl_perf = list( 

322 blade.get_array_connections_performance_replication( 

323 type="file-system" 

324 ).items 

325 )[0] 

326 obj_repl_perf = list( 

327 blade.get_array_connections_performance_replication( 

328 type="object-store" 

329 ).items 

330 )[0] 

331 perf_info["file_replication"] = { 

332 "received_bytes_per_sec": getattr( 

333 file_repl_perf.periodic, "received_bytes_per_sec", None 

334 ), 

335 "transmitted_bytes_per_sec": getattr( 

336 file_repl_perf.periodic, "transmitted_bytes_per_sec", None 

337 ), 

338 } 

339 perf_info["object_replication"] = { 

340 "received_bytes_per_sec": getattr( 

341 obj_repl_perf.periodic, "received_bytes_per_sec", None 

342 ), 

343 "transmitted_bytes_per_sec": getattr( 

344 obj_repl_perf.periodic, "transmitted_bytes_per_sec", None 

345 ), 

346 } 

347 return perf_info 

348 

349 

350def generate_config_dict(blade): 

351 config_info = {} 

352 api_version = get_rest_api_version(blade) 

353 config_info["dns"] = {} 

354 dns_configs = list(blade.get_dns().items) 

355 for config in dns_configs: 

356 config_info["dns"][config.name] = { 

357 "nameservers": config.nameservers, 

358 "domain": config.domain, 

359 "services": getattr(config, "services", None), 

360 } 

361 if hasattr(config, "sources"): 

362 # sources is a list of references (at most one), not a reference 

363 sources = getattr(config, "sources", None) 

364 if isinstance(sources, list): 

365 source = getattr(sources[0], "name", None) if sources else None 

366 else: 

367 source = getattr(sources, "name", None) 

368 config_info["dns"][config.name]["source"] = source 

369 smtp_config = list(blade.get_smtp_servers().items) 

370 config_info["smtp"] = {} 

371 for config in smtp_config: 

372 config_info["smtp"][config.name] = { 

373 "relay_host": getattr(config, "relay_host", None), 

374 "sender_domain": getattr(config, "sender_domain", None), 

375 "encryption_mode": getattr(config, "encryption_mode", None), 

376 } 

377 alert_config = list(blade.get_alert_watchers().items) 

378 config_info["alert_watchers"] = {} 

379 for config in alert_config: 

380 config_info["alert_watchers"][config.name] = { 

381 "enabled": config.enabled, 

382 "minimum_notification_severity": config.minimum_notification_severity, 

383 } 

384 directory_services = list(blade.get_directory_services().items) 

385 for ds_service in directory_services: 

386 if ds_service.name in {"management", "nfs", "smb"}: 

387 key = f"{ds_service.name}_directory_service" 

388 config_info[key] = { 

389 "base_dn": ds_service.base_dn, 

390 "bind_user": ds_service.bind_user, 

391 "ca_certificate": ds_service.ca_certificate.name, 

392 "ca_certificate_group": ds_service.ca_certificate_group.name, 

393 "enabled": ds_service.enabled, 

394 "management": { 

395 "user_login_attribute": ds_service.management.user_login_attribute, 

396 "user_object_class": ds_service.management.user_object_class, 

397 }, 

398 "nis_servers": ds_service.nfs.nis_servers, 

399 "nis_domains": ds_service.nfs.nis_domains, 

400 "services": ds_service.services, 

401 "join_ou": ds_service.smb.join_ou, 

402 "uris": ds_service.uris, 

403 } 

404 # Forward backwards compatability 

405 config_info["array_management"] = config_info["management_directory_service"] 

406 

407 config_info["directory_service_roles"] = {} 

408 roles = list(blade.get_directory_services_roles().items) 

409 for ds_role in roles: 

410 role_name = ds_role.name 

411 config_info["directory_service_roles"][role_name] = { 

412 "group": ds_role.group, 

413 "group_base": ds_role.group_base, 

414 "role": ds_role.role.name, 

415 } 

416 config_info["ntp"] = list(blade.get_arrays().items)[0].ntp_servers 

417 certs = list(blade.get_certificates().items) 

418 config_info["ssl_certs"] = {} 

419 for cert in certs: 

420 cert_name = cert.name 

421 valid_from = time.strftime( 

422 "%a, %d %b %Y %H:%M:%S %Z", 

423 time.localtime(cert.valid_from / 1000), 

424 ) 

425 valid_to = time.strftime( 

426 "%a, %d %b %Y %H:%M:%S %Z", 

427 time.localtime(cert.valid_to / 1000), 

428 ) 

429 config_info["ssl_certs"][cert_name] = { 

430 "certificate": getattr(cert, "certificate", None), 

431 "certificate_type": getattr(cert, "certificate_type", None), 

432 "common_name": getattr(cert, "common_name", None), 

433 "country": getattr(cert, "country", None), 

434 "email": getattr(cert, "email", None), 

435 "intermediate_certificate": getattr(cert, "intermediate_certificate", None), 

436 "issued_by": getattr(cert, "issued_by", None), 

437 "issued_to": getattr(cert, "issued_to", None), 

438 "key_size": getattr(cert, "key_size", None), 

439 "locality": getattr(cert, "locality", None), 

440 "organization": getattr(cert, "organization", None), 

441 "organizational_unit": getattr(cert, "organizational_unit", None), 

442 "state": getattr(cert, "state", None), 

443 "status": getattr(cert, "status", None), 

444 "subject_alternative_names": getattr( 

445 cert, "subject_alternative_names", None 

446 ), 

447 "valid_from": valid_from, 

448 "valid_to": valid_to, 

449 } 

450 crt_grps = list(blade.get_certificate_groups().items) 

451 config_info["certificate_groups"] = [] 

452 for crt_grp in crt_grps: 

453 config_info["certificate_groups"].append(crt_grp.name) 

454 config_info["syslog_servers"] = {} 

455 syslog_servers = list(blade.get_syslog_servers().items) 

456 for server in syslog_servers: 

457 server_name = server.name 

458 config_info["syslog_servers"][server_name] = { 

459 "uri": server.uri, 

460 "services": getattr(server, "services", None), 

461 } 

462 snmp_agents = list(blade.get_snmp_agents().items) 

463 config_info["snmp_agents"] = {} 

464 for agent in snmp_agents: 

465 agent_name = agent.name 

466 config_info["snmp_agents"][agent_name] = { 

467 "version": agent.version, 

468 "engine_id": agent.engine_id, 

469 } 

470 if config_info["snmp_agents"][agent_name]["version"] == "v3": 

471 config_info["snmp_agents"][agent_name]["auth_protocol"] = getattr( 

472 agent.v3, "auth_protocol", None 

473 ) 

474 config_info["snmp_agents"][agent_name]["privacy_protocol"] = getattr( 

475 agent.v3, "privacy_protocol", None 

476 ) 

477 config_info["snmp_agents"][agent_name]["user"] = getattr( 

478 agent.v3, "user", None 

479 ) 

480 config_info["snmp_managers"] = {} 

481 snmp_managers = list(blade.get_snmp_managers().items) 

482 for manager in snmp_managers: 

483 mgr_name = manager.name 

484 config_info["snmp_managers"][mgr_name] = { 

485 "version": manager.version, 

486 "host": manager.host, 

487 "notification": manager.notification, 

488 } 

489 if config_info["snmp_managers"][mgr_name]["version"] == "v3": 

490 config_info["snmp_managers"][mgr_name]["auth_protocol"] = getattr( 

491 manager.v3, "auth_protocol", None 

492 ) 

493 config_info["snmp_managers"][mgr_name]["privacy_protocol"] = getattr( 

494 manager.v3, "privacy_protocol", None 

495 ) 

496 config_info["snmp_managers"][mgr_name]["user"] = getattr( 

497 manager.v3, "user", None 

498 ) 

499 if LooseVersion(KMIP_API_VERSION) <= LooseVersion(api_version): 

500 config_info["kmip"] = {} 

501 for kmip in list(blade.get_kmip().items): 

502 config_info["kmip"][kmip.name] = { 

503 "uris": getattr(kmip, "uris", None), 

504 "ca_certificate": getattr( 

505 getattr(kmip, "ca_certificate", None), "name", None 

506 ), 

507 "ca_certificate_group": getattr( 

508 getattr(kmip, "ca_certificate_group", None), "name", None 

509 ), 

510 } 

511 if LooseVersion(SMTP_ENCRYPT_API_VERSION) <= LooseVersion(api_version): 

512 config_info["saml2sso"] = {} 

513 saml2 = list(blade.get_sso_saml2_idps().items) 

514 if saml2: 

515 config_info["saml2sso"] = { 

516 "enabled": saml2[0].enabled, 

517 "array_url": saml2[0].array_url, 

518 "name": saml2[0].name, 

519 "idp": { 

520 "url": getattr(saml2[0].idp, "url", None), 

521 "encrypt_enabled": saml2[0].idp.encrypt_assertion_enabled, 

522 "sign_enabled": saml2[0].idp.sign_request_enabled, 

523 "metadata_url": saml2[0].idp.metadata_url, 

524 }, 

525 "sp": { 

526 "decrypt_cred": getattr( 

527 saml2[0].sp.decryption_credential, "name", None 

528 ), 

529 "sign_cred": getattr(saml2[0].sp.signing_credential, "name", None), 

530 }, 

531 } 

532 return config_info 

533 

534 

535def generate_subnet_dict(blade): 

536 sub_info = {} 

537 subnets = list(blade.get_subnets().items) 

538 for sub in subnets: 

539 sub_name = sub.name 

540 if sub.enabled: 

541 sub_info[sub_name] = { 

542 "gateway": sub.gateway, 

543 "mtu": sub.mtu, 

544 "vlan": sub.vlan, 

545 "prefix": sub.prefix, 

546 "services": sub.services, 

547 } 

548 # Subnets on an array in Layer 3 (BGP) mode have no LAG 

549 sub_info[sub_name]["lag"] = getattr( 

550 sub.link_aggregation_group, "name", None 

551 ) 

552 sub_info[sub_name]["interfaces"] = [] 

553 for iface in sub.interfaces or []: 

554 sub_info[sub_name]["interfaces"].append({"name": iface.name}) 

555 return sub_info 

556 

557 

558def generate_lag_dict(blade): 

559 lag_info = {} 

560 res = blade.get_link_aggregation_groups() 

561 if res.status_code != 200: 

562 # An array in Layer 3 (BGP) mode has no link aggregation groups 

563 # and the endpoint returns an error rather than an empty list 

564 return lag_info 

565 for groupcnt in list(res.items): 

566 lag_name = groupcnt.name 

567 lag_info[lag_name] = { 

568 "lag_speed": groupcnt.lag_speed, 

569 "port_speed": groupcnt.port_speed, 

570 "mac_address": getattr(groupcnt, "mac_address", None), 

571 "status": groupcnt.status, 

572 } 

573 lag_info[lag_name]["ports"] = [] 

574 for port in groupcnt.ports or []: 

575 lag_info[lag_name]["ports"].append({"name": port.name}) 

576 return lag_info 

577 

578 

579def generate_admin_dict(blade): 

580 admin_info = {} 

581 admins = list(blade.get_admins().items) 

582 for admin in admins: 

583 admin_name = admin.name 

584 admin_info[admin_name] = { 

585 "public_key": admin.public_key, 

586 "local": admin.is_local, 

587 "role": admin.role.name, 

588 "locked": admin.locked, 

589 "lockout_remaining": getattr(admin, "lockout_remaining", None), 

590 } 

591 if hasattr(admin.api_token, "expires_at"): 

592 if admin.api_token.expires_at: 

593 admin_info[admin_name]["token_expires"] = datetime.fromtimestamp( 

594 admin.api_token.expires_at / 1000 

595 ).strftime("%Y-%m-%d %H:%M:%S") 

596 else: 

597 admin_info[admin_name]["token_expires"] = None 

598 if hasattr(admin.api_token, "created_at"): 

599 if admin.api_token.created_at: 

600 admin_info[admin_name]["token_created"] = datetime.fromtimestamp( 

601 admin.api_token.created_at / 1000 

602 ).strftime("%Y-%m-%d %H:%M:%S") 

603 else: 

604 admin_info[admin_name]["token_created"] = None 

605 return admin_info 

606 

607 

608def generate_targets_dict(blade): 

609 targets_info = {} 

610 targets = list(blade.get_targets().items) 

611 for target in targets: 

612 target_name = target.name 

613 targets_info[target_name] = { 

614 "address": target.address, 

615 "status": target.status, 

616 "status_details": target.status_details, 

617 "ca_certificate_group": getattr( 

618 getattr(target, "ca_certificate_group", None), "name", None 

619 ), 

620 } 

621 return targets_info 

622 

623 

624def generate_remote_creds_dict(blade): 

625 remote_creds_info = {} 

626 remote_creds = list(blade.get_object_store_remote_credentials().items) 

627 for remote_cred in remote_creds: 

628 cred_name = remote_cred.name 

629 remote_creds_info[cred_name] = { 

630 "access_key": remote_cred.access_key_id, 

631 "remote_array": remote_cred.remote.name, 

632 "secret_access_key": remote_cred.secret_access_key, 

633 } 

634 return remote_creds_info 

635 

636 

637def generate_file_repl_dict(blade): 

638 file_repl_info = {} 

639 file_links = list(blade.get_file_system_replica_links().items) 

640 for file_link in file_links: 

641 fs_name = file_link.local_file_system.name 

642 file_repl_info[fs_name] = { 

643 "direction": file_link.direction, 

644 "link_type": file_link.link_type, 

645 "lag": file_link.lag, 

646 "status": file_link.status, 

647 # the SDK model calls this status_details; the key is kept for 

648 # backwards compatibility 

649 "status_detail": getattr(file_link, "status_details", None), 

650 "remote_fs": file_link.remote.name 

651 + ":" 

652 + file_link.remote_file_system.name, 

653 "recovery_point": file_link.recovery_point, 

654 } 

655 file_repl_info[fs_name]["policies"] = [] 

656 for policy_cnt in file_link.policies: 

657 file_repl_info[fs_name]["policies"].append(policy_cnt.display_name) 

658 return file_repl_info 

659 

660 

661def generate_bucket_repl_dict(blade): 

662 bucket_repl_info = {} 

663 bucket_links = list(blade.get_bucket_replica_links().items) 

664 for bucket_link in bucket_links: 

665 bucket_name = bucket_link.local_bucket.name 

666 bucket_repl_info[bucket_name] = { 

667 "direction": bucket_link.direction, 

668 "lag": bucket_link.lag, 

669 "paused": bucket_link.paused, 

670 "status": bucket_link.status, 

671 "status_details": bucket_link.status_details, 

672 "remote_bucket": bucket_link.remote_bucket.name, 

673 "remote_array": bucket_link.remote.name, 

674 "remote_credentials": bucket_link.remote_credentials.name, 

675 "recovery_point": bucket_link.recovery_point, 

676 "object_backlog": { 

677 "bytes_count": bucket_link.object_backlog.bytes_count, 

678 "delete_ops_count": bucket_link.object_backlog.delete_ops_count, 

679 "other_ops_count": bucket_link.object_backlog.other_ops_count, 

680 "put_ops_count": bucket_link.object_backlog.put_ops_count, 

681 }, 

682 "cascading_enabled": bucket_link.cascading_enabled, 

683 } 

684 return bucket_repl_info 

685 

686 

687def generate_network_dict(blade): 

688 net_info = {} 

689 ports = list(blade.get_network_interfaces().items) 

690 for port in ports: 

691 int_name = port.name 

692 # attached_servers is a list of references on the API even though an 

693 # interface carries at most one server; the subnet comes back as a 

694 # plain dict on current SDKs and as a reference on older ones. 

695 attached = getattr(port, "attached_servers", None) or [] 

696 if not isinstance(attached, list): 

697 attached = [] 

698 attached_names = [getattr(srv, "name", None) for srv in attached] 

699 subnet = getattr(port, "subnet", None) 

700 if isinstance(subnet, dict): 

701 subnet_name = subnet.get("name") 

702 else: 

703 subnet_name = getattr(subnet, "name", None) 

704 net_info[int_name] = { 

705 "type": getattr(port, "type", None), 

706 "mtu": getattr(port, "mtu", None), 

707 "vlan": getattr(port, "vlan", None), 

708 "address": getattr(port, "address", None), 

709 "services": getattr(port, "services", None), 

710 "gateway": getattr(port, "gateway", None), 

711 "netmask": getattr(port, "netmask", None), 

712 "server": attached_names[0] if attached_names else None, 

713 "attached_servers": attached_names, 

714 "subnet": subnet_name, 

715 "enabled": port.enabled, 

716 } 

717 return net_info 

718 

719 

720def generate_capacity_dict(blade): 

721 capacity_info = {} 

722 total_cap = list(blade.get_arrays_space().items)[0] 

723 file_cap = list(blade.get_arrays_space(type="file-system").items)[0] 

724 object_cap = list(blade.get_arrays_space(type="object-store").items)[0] 

725 capacity_info["total"] = total_cap.capacity 

726 capacity_info["aggregate"] = { 

727 "data_reduction": total_cap.space.data_reduction, 

728 "snapshots": total_cap.space.snapshots, 

729 "total_physical": total_cap.space.total_physical, 

730 "unique": total_cap.space.unique, 

731 "virtual": total_cap.space.virtual, 

732 "total_provisioned": total_cap.space.total_provisioned, 

733 "available_provisioned": total_cap.space.available_provisioned, 

734 "available_ratio": total_cap.space.available_ratio, 

735 "destroyed": total_cap.space.destroyed, 

736 "destroyed_virtual": total_cap.space.destroyed_virtual, 

737 "shared": getattr(total_cap.space, "shared", None), 

738 } 

739 capacity_info["file-system"] = { 

740 "data_reduction": file_cap.space.data_reduction, 

741 "snapshots": file_cap.space.snapshots, 

742 "total_physical": file_cap.space.total_physical, 

743 "unique": file_cap.space.unique, 

744 "virtual": file_cap.space.virtual, 

745 "total_provisioned": total_cap.space.total_provisioned, 

746 "available_provisioned": total_cap.space.available_provisioned, 

747 "available_ratio": total_cap.space.available_ratio, 

748 "destroyed": total_cap.space.destroyed, 

749 "destroyed_virtual": total_cap.space.destroyed_virtual, 

750 "shared": getattr(total_cap.space, "shared", None), 

751 } 

752 capacity_info["object-store"] = { 

753 "data_reduction": object_cap.space.data_reduction, 

754 "snapshots": object_cap.space.snapshots, 

755 "total_physical": object_cap.space.total_physical, 

756 "unique": object_cap.space.unique, 

757 "virtual": file_cap.space.virtual, 

758 "total_provisioned": total_cap.space.total_provisioned, 

759 "available_provisioned": total_cap.space.available_provisioned, 

760 "available_ratio": total_cap.space.available_ratio, 

761 "destroyed": total_cap.space.destroyed, 

762 "destroyed_virtual": total_cap.space.destroyed_virtual, 

763 "shared": getattr(total_cap.space, "shared", None), 

764 } 

765 

766 return capacity_info 

767 

768 

769def generate_snap_dict(blade): 

770 snap_info = {} 

771 snaps = list(blade.get_file_system_snapshots().items) 

772 api_version = get_rest_api_version(blade) 

773 for snap in snaps: 

774 snapshot = snap.name 

775 snap_info[snapshot] = { 

776 "destroyed": snap.destroyed, 

777 "source": snap.source.location.name, 

778 "suffix": snap.suffix, 

779 "created": datetime.fromtimestamp( 

780 snap.created / 1000, 

781 tz=timezone.utc, 

782 ).strftime("%Y-%m-%dT%H:%M:%SZ"), 

783 "time_remaining": getattr(snap, "time_remaining", None), 

784 "policy": getattr(getattr(snap, "policy", None), "name", None), 

785 "owner": snap.owner.name, 

786 "owner_destroyed": snap.owner_destroyed, 

787 "source_display_name": snap.source.display_name, 

788 "source_is_local": snap.source.is_local, 

789 "source_location": snap.source.location.name, 

790 "policies": [], 

791 } 

792 if LooseVersion(PUBLIC_API_VERSION) <= LooseVersion(api_version): 

793 if hasattr(snap, "policies"): 

794 for policy in snap.policies: 

795 snap_info[snapshot]["policies"].append( 

796 { 

797 "name": policy.name, 

798 "location": policy.location.name, 

799 } 

800 ) 

801 return snap_info 

802 

803 

804def generate_snap_transfer_dict(blade): 

805 snap_transfer_info = {} 

806 snap_transfers = list(blade.get_file_system_snapshots_transfer().items) 

807 for snap_transfer in snap_transfers: 

808 transfer = snap_transfer.name 

809 snap_transfer_info[transfer] = { 

810 "completed": snap_transfer.completed, 

811 "data_transferred": snap_transfer.data_transferred, 

812 "progress": snap_transfer.progress, 

813 "direction": snap_transfer.direction, 

814 "remote": snap_transfer.remote.name, 

815 "remote_snapshot": snap_transfer.remote_snapshot.name, 

816 "started": snap_transfer.started, 

817 "status": snap_transfer.status, 

818 } 

819 return snap_transfer_info 

820 

821 

822def generate_array_conn_dict(blade): 

823 array_conn_info = {} 

824 arrays = list(blade.get_array_connections().items) 

825 for array in arrays: 

826 # Keep the connection object intact: rebinding `array` to the remote 

827 # name here made every attribute read below fail with AttributeError. 

828 remote_name = array.remote.name 

829 array_conn_info[remote_name] = { 

830 "encrypted": array.encrypted, 

831 "replication_addresses": array.replication_addresses, 

832 "management_address": array.management_address, 

833 "status": array.status, 

834 "version": array.version, 

835 "ca_certificate_group": getattr( 

836 getattr(array, "ca_certificate_group", None), "name", None 

837 ), 

838 "throttle": { 

839 "default_limit": _bytes_to_human( 

840 getattr(array.throttle, "default_limit", None) 

841 ), 

842 "window_limit": _bytes_to_human( 

843 getattr(array.throttle, "window_limit", None) 

844 ), 

845 "window_start": ( 

846 milliseconds_to_time(getattr(array.throttle.window, "start", None)) 

847 if getattr(array.throttle.window, "start", None) 

848 else None 

849 ), 

850 "window_end": ( 

851 milliseconds_to_time(getattr(array.throttle.window, "end", None)) 

852 if getattr(array.throttle.window, "end", None) 

853 else None 

854 ), 

855 }, 

856 } 

857 return array_conn_info 

858 

859 

860def generate_policies_dict(blade): 

861 policies_info = {} 

862 policies = list(blade.get_policies().items) 

863 for policy in policies: 

864 policy_name = policy.name 

865 policies_info[policy_name] = { 

866 "enabled": policy.enabled, 

867 "retention_lock": getattr(policy, "retention_lock", None), 

868 "policy_type": policy.policy_type, 

869 "rules": {}, 

870 } 

871 rules = getattr(policy, "rules", None) 

872 if rules: 

873 policies_info[policy_name]["rules"] = { 

874 "at": getattr(rules[0], "at", None), 

875 "every": getattr(rules[0], "every", None), 

876 "keep_for": getattr(rules[0], "keep_for", None), 

877 "time_zone": getattr(rules[0], "time_zone", None), 

878 } 

879 return policies_info 

880 

881 

882def generate_all_policies_dict(blade): 

883 policies_info = {} 

884 policies = list(blade.get_policies_all().items) 

885 for policy in policies: 

886 policy_name = policy.name 

887 policies_info[policy_name] = { 

888 "id": policy.id, 

889 "enabled": policy.enabled, 

890 "is_local": getattr(policy, "is_local", None), 

891 "location": getattr(getattr(policy, "location", None), "name", None), 

892 "policy_type": policy.policy_type, 

893 } 

894 return policies_info 

895 

896 

897def generate_bucket_dict(blade): 

898 bucket_info = {} 

899 buckets = list(blade.get_buckets().items) 

900 for bucket in buckets: 

901 bucket_name = bucket.name 

902 bucket_info[bucket_name] = { 

903 "versioning": bucket.versioning, 

904 "bucket_type": getattr(bucket, "bucket_type", None), 

905 "object_count": bucket.object_count, 

906 "id": bucket.id, 

907 "account_name": bucket.account.name, 

908 "data_reduction": getattr(bucket.space, "data_reduction", None), 

909 "snapshot_space": bucket.space.snapshots, 

910 "total_physical_space": bucket.space.total_physical, 

911 "unique_space": bucket.space.unique, 

912 "virtual_space": bucket.space.virtual, 

913 "total_provisioned_space": getattr(bucket.space, "total_provisioned", None), 

914 "available_provisioned_space": getattr( 

915 bucket.space, "available_provisioned", None 

916 ), 

917 "available_ratio": getattr(bucket.space, "available_ratio", None), 

918 "destroyed_space": getattr(bucket.space, "destroyed", None), 

919 "destroyed_virtual_space": getattr(bucket.space, "destroyed_virtual", None), 

920 "created": bucket.created, 

921 "destroyed": bucket.destroyed, 

922 "time_remaining": getattr(bucket, "time_remaining", None), 

923 "time_remaining_status": getattr(bucket, "time_remaining_status", None), 

924 "retention_lock": bucket.retention_lock, 

925 "quota_limit": bucket.quota_limit, 

926 "object_lock_config": { 

927 "enabled": bucket.object_lock_config.enabled, 

928 "freeze_locked_objects": bucket.object_lock_config.freeze_locked_objects, 

929 "default_retention": getattr( 

930 bucket.object_lock_config, "default_retention", None 

931 ), 

932 "default_retention_mode": getattr( 

933 bucket.object_lock_config, 

934 "default_retention_mode", 

935 None, 

936 ), 

937 }, 

938 "eradication_config": { 

939 "eradication_delay": getattr( 

940 bucket.eradication_config, "eradication_delay", None 

941 ), 

942 "eradication_mode": getattr( 

943 bucket.eradication_config, "eradication_mode", None 

944 ), 

945 "manual_eradication": bucket.eradication_config.manual_eradication, 

946 }, 

947 "public_status": getattr(bucket, "public_status", None), 

948 "public_access_config": { 

949 "block_new_public_policies": getattr( 

950 getattr(bucket, "public_access_config", None), 

951 "block_new_public_policies", 

952 None, 

953 ), 

954 "block_public_access": getattr( 

955 getattr(bucket, "public_access_config", None), 

956 "block_public_access", 

957 None, 

958 ), 

959 }, 

960 "lifecycle_rules": {}, 

961 } 

962 if not bucket.destroyed: 

963 all_rules = list(blade.get_lifecycle_rules(bucket_ids=[bucket.id]).items) 

964 for rule in all_rules: 

965 bucket_name = rule.bucket.name 

966 rule_id = rule.rule_id 

967 if rule.keep_previous_version_for: 

968 keep_previous_version_for = int( 

969 rule.keep_previous_version_for / 86400000 

970 ) 

971 else: 

972 keep_previous_version_for = None 

973 if rule.keep_current_version_for: 

974 keep_current_version_for = int( 

975 rule.keep_current_version_for / 86400000 

976 ) 

977 else: 

978 keep_current_version_for = None 

979 if rule.abort_incomplete_multipart_uploads_after: 

980 abort_incomplete_multipart_uploads_after = int( 

981 rule.abort_incomplete_multipart_uploads_after / 86400000 

982 ) 

983 else: 

984 abort_incomplete_multipart_uploads_after = None 

985 if rule.keep_current_version_until: 

986 keep_current_version_until = datetime.fromtimestamp( 

987 rule.keep_current_version_until / 1000 

988 ).strftime("%Y-%m-%d") 

989 else: 

990 keep_current_version_until = None 

991 bucket_info[bucket_name]["lifecycle_rules"][rule_id] = { 

992 "keep_previous_version_for (days)": keep_previous_version_for, 

993 "keep_current_version_for (days)": keep_current_version_for, 

994 "keep_current_version_until": keep_current_version_until, 

995 "prefix": rule.prefix, 

996 "enabled": rule.enabled, 

997 "abort_incomplete_multipart_uploads_after (days)": abort_incomplete_multipart_uploads_after, 

998 "cleanup_expired_object_delete_marker": rule.cleanup_expired_object_delete_marker, 

999 } 

1000 

1001 return bucket_info 

1002 

1003 

1004def generate_kerb_dict(blade): 

1005 kerb_info = {} 

1006 

1007 for keytab in blade.get_keytabs().items: 

1008 prefix = keytab.prefix 

1009 suffix = keytab.suffix 

1010 

1011 if prefix not in kerb_info: 

1012 kerb_info[prefix] = {} 

1013 

1014 kerb_info[prefix][suffix] = { 

1015 "fqdn": keytab.fqdn, 

1016 "kvno": keytab.kvno, 

1017 "principal": keytab.principal, 

1018 "realm": keytab.realm, 

1019 "encryption_type": keytab.encryption_type, 

1020 "server": getattr(getattr(keytab, "server", None), "name", None), 

1021 "source": getattr(getattr(keytab, "source", None), "name", None), 

1022 } 

1023 

1024 return kerb_info 

1025 

1026 

1027def generate_ad_dict(blade): 

1028 ad_info = {} 

1029 

1030 active_directory = blade.get_active_directory() 

1031 if active_directory.total_item_count == 0: 

1032 return ad_info 

1033 

1034 for ad in active_directory.items: 

1035 ad_info[ad.name] = { 

1036 "computer": ad.computer_name, 

1037 "domain": ad.domain, 

1038 "directory_servers": ad.directory_servers, 

1039 "kerberos_servers": ad.kerberos_servers, 

1040 "service_principals": ad.service_principal_names, 

1041 "join_ou": ad.join_ou, 

1042 "encryption_types": ad.encryption_types, 

1043 "global_catalog_servers": getattr(ad, "global_catalog_servers", None), 

1044 "server": getattr(getattr(ad, "server", None), "name", None), 

1045 } 

1046 

1047 return ad_info 

1048 

1049 

1050def generate_bucket_access_policies_dict(blade): 

1051 policies_info = {} 

1052 

1053 for bucket in blade.get_buckets().items: 

1054 res = blade.get_buckets_bucket_access_policies(bucket_names=[bucket.name]) 

1055 

1056 if res.status_code == 200 and res.total_item_count != 0: 

1057 for policy in res.items: 

1058 policies_info[policy.name] = { 

1059 # BucketAccessPolicy has no description field, unlike the 

1060 # object store access policy reported further down. 

1061 "description": getattr(policy, "description", None), 

1062 "enabled": policy.enabled, 

1063 "local": policy.is_local, 

1064 "rules": [], 

1065 } 

1066 

1067 for rule in policy.rules: 

1068 policies_info[policy.name]["rules"].append( 

1069 { 

1070 "actions": rule.actions, 

1071 "resources": rule.resources, 

1072 "all_principals": rule.principals.all, 

1073 "effect": rule.effect, 

1074 "name": rule.name, 

1075 } 

1076 ) 

1077 

1078 return policies_info 

1079 

1080 

1081def generate_bucket_cross_object_policies_dict(blade): 

1082 policies_info = {} 

1083 

1084 for bucket in blade.get_buckets().items: 

1085 res = blade.get_buckets_cross_origin_resource_sharing_policies( 

1086 bucket_names=[bucket.name] 

1087 ) 

1088 if res.status_code != 200: 

1089 continue 

1090 

1091 for policy in res.items: 

1092 # The allowed_* lists live on the rules, not on the policy. 

1093 policies_info[policy.name] = { 

1094 "enabled": getattr(policy, "enabled", None), 

1095 "local": getattr(policy, "is_local", None), 

1096 "rules": [], 

1097 } 

1098 rules = blade.get_buckets_cross_origin_resource_sharing_policies_rules( 

1099 policy_names=[policy.name] 

1100 ) 

1101 if rules.status_code != 200: 

1102 continue 

1103 for rule in rules.items: 

1104 policies_info[policy.name]["rules"].append( 

1105 { 

1106 "name": rule.name, 

1107 "allowed_headers": getattr(rule, "allowed_headers", None), 

1108 "allowed_methods": getattr(rule, "allowed_methods", None), 

1109 "allowed_origins": getattr(rule, "allowed_origins", None), 

1110 } 

1111 ) 

1112 

1113 return policies_info 

1114 

1115 

1116def generate_object_store_access_policies_dict(blade): 

1117 policies_info = {} 

1118 

1119 for policy in blade.get_object_store_access_policies().items: 

1120 policy_name = policy.name 

1121 policies_info[policy_name] = { 

1122 "ARN": policy.arn, 

1123 "description": policy.description, 

1124 "enabled": policy.enabled, 

1125 "local": policy.is_local, 

1126 "rules": [], 

1127 } 

1128 

1129 for rule in policy.rules: 

1130 policies_info[policy_name]["rules"].append( 

1131 { 

1132 "actions": rule.actions, 

1133 "conditions": { 

1134 "source_ips": rule.conditions.source_ips, 

1135 "s3_delimiters": rule.conditions.s3_delimiters, 

1136 "s3_prefixes": rule.conditions.s3_prefixes, 

1137 }, 

1138 "effect": rule.effect, 

1139 "name": rule.name, 

1140 } 

1141 ) 

1142 

1143 return policies_info 

1144 

1145 

1146def generate_nfs_export_policies_dict(blade): 

1147 policies_info = {} 

1148 

1149 for policy in blade.get_nfs_export_policies().items: 

1150 policy_name = policy.name 

1151 policies_info[policy_name] = { 

1152 "local": policy.is_local, 

1153 "enabled": policy.enabled, 

1154 "rules": [], 

1155 } 

1156 

1157 for rule in policy.rules: 

1158 policies_info[policy_name]["rules"].append( 

1159 { 

1160 "access": rule.access, 

1161 "anongid": rule.anongid, 

1162 "anonuid": rule.anonuid, 

1163 "atime": rule.atime, 

1164 "client": rule.client, 

1165 "fileid_32bit": rule.fileid_32bit, 

1166 "permission": rule.permission, 

1167 "secure": rule.secure, 

1168 "security": rule.security, 

1169 "index": rule.index, 

1170 } 

1171 ) 

1172 

1173 return policies_info 

1174 

1175 

1176def generate_smb_client_policies_dict(blade): 

1177 policies_info = {} 

1178 

1179 for policy in blade.get_smb_client_policies().items: 

1180 policy_name = policy.name 

1181 policies_info[policy_name] = { 

1182 "local": policy.is_local, 

1183 "enabled": policy.enabled, 

1184 "version": policy.version, 

1185 "rules": [], 

1186 } 

1187 

1188 for rule in policy.rules: 

1189 policies_info[policy_name]["rules"].append( 

1190 { 

1191 "name": rule.name, 

1192 "change": getattr(rule, "change", None), 

1193 "full_control": getattr(rule, "full_control", None), 

1194 "principal": getattr(rule, "principal", None), 

1195 "read": getattr(rule, "read", None), 

1196 "client": getattr(rule, "client", None), 

1197 "index": getattr(rule, "index", None), 

1198 "policy_version": getattr(rule, "policy_version", None), 

1199 "encryption": getattr(rule, "encryption", None), 

1200 "permission": getattr(rule, "permission", None), 

1201 } 

1202 ) 

1203 

1204 return policies_info 

1205 

1206 

1207def generate_smb_share_policies_dict(blade): 

1208 policies_info = {} 

1209 

1210 for policy in blade.get_smb_share_policies().items: 

1211 policy_name = policy.name 

1212 policies_info[policy_name] = { 

1213 "local": getattr(policy, "is_local", None), 

1214 "enabled": getattr(policy, "enabled", None), 

1215 "rules": [], 

1216 } 

1217 

1218 for rule in getattr(policy, "rules", None) or []: 

1219 policies_info[policy_name]["rules"].append( 

1220 { 

1221 "name": rule.name, 

1222 "principal": getattr(rule, "principal", None), 

1223 "change": getattr(rule, "change", None), 

1224 "full_control": getattr(rule, "full_control", None), 

1225 "read": getattr(rule, "read", None), 

1226 } 

1227 ) 

1228 

1229 return policies_info 

1230 

1231 

1232def generate_network_access_policies_dict(blade): 

1233 policies_info = {} 

1234 

1235 for policy in blade.get_network_access_policies().items: 

1236 policy_name = policy.name 

1237 policies_info[policy_name] = { 

1238 "local": getattr(policy, "is_local", None), 

1239 "enabled": getattr(policy, "enabled", None), 

1240 "version": getattr(policy, "version", None), 

1241 "rules": [], 

1242 } 

1243 

1244 for rule in getattr(policy, "rules", None) or []: 

1245 policies_info[policy_name]["rules"].append( 

1246 { 

1247 "name": rule.name, 

1248 "client": getattr(rule, "client", None), 

1249 "effect": getattr(rule, "effect", None), 

1250 "interfaces": getattr(rule, "interfaces", None), 

1251 "index": getattr(rule, "index", None), 

1252 } 

1253 ) 

1254 

1255 return policies_info 

1256 

1257 

1258def generate_worm_data_policies_dict(blade): 

1259 policies_info = {} 

1260 

1261 for policy in blade.get_worm_data_policies().items: 

1262 policies_info[policy.name] = { 

1263 "local": getattr(policy, "is_local", None), 

1264 "enabled": getattr(policy, "enabled", None), 

1265 "mode": getattr(policy, "mode", None), 

1266 "retention_lock": getattr(policy, "retention_lock", None), 

1267 "default_retention": getattr(policy, "default_retention", None), 

1268 "min_retention": getattr(policy, "min_retention", None), 

1269 "max_retention": getattr(policy, "max_retention", None), 

1270 "members": [], 

1271 } 

1272 

1273 for member in blade.get_worm_data_policies_members().items: 

1274 policy_name = getattr(getattr(member, "policy", None), "name", None) 

1275 if policy_name in policies_info: 

1276 policies_info[policy_name]["members"].append( 

1277 getattr(getattr(member, "member", None), "name", None) 

1278 ) 

1279 

1280 return policies_info 

1281 

1282 

1283def generate_tls_policies_dict(blade): 

1284 policies_info = {} 

1285 

1286 for policy in blade.get_tls_policies().items: 

1287 policies_info[policy.name] = { 

1288 "local": getattr(policy, "is_local", None), 

1289 "enabled": getattr(policy, "enabled", None), 

1290 "appliance_certificate": getattr( 

1291 getattr(policy, "appliance_certificate", None), "name", None 

1292 ), 

1293 "min_tls_version": getattr(policy, "min_tls_version", None), 

1294 "enabled_tls_ciphers": getattr(policy, "enabled_tls_ciphers", None), 

1295 "disabled_tls_ciphers": getattr(policy, "disabled_tls_ciphers", None), 

1296 "client_certificates_required": getattr( 

1297 policy, "client_certificates_required", None 

1298 ), 

1299 "verify_client_certificate_trust": getattr( 

1300 policy, "verify_client_certificate_trust", None 

1301 ), 

1302 "trusted_client_certificate_authority": getattr( 

1303 getattr(policy, "trusted_client_certificate_authority", None), 

1304 "name", 

1305 None, 

1306 ), 

1307 "network_interfaces": [], 

1308 } 

1309 

1310 for member in blade.get_tls_policies_network_interfaces().items: 

1311 policy_name = getattr(getattr(member, "policy", None), "name", None) 

1312 if policy_name in policies_info: 

1313 policies_info[policy_name]["network_interfaces"].append( 

1314 getattr(getattr(member, "member", None), "name", None) 

1315 ) 

1316 

1317 return policies_info 

1318 

1319 

1320def generate_s3_export_policies_dict(blade): 

1321 policies_info = {} 

1322 

1323 for policy in blade.get_s3_export_policies().items: 

1324 policy_name = policy.name 

1325 policies_info[policy_name] = { 

1326 "local": getattr(policy, "is_local", None), 

1327 "enabled": getattr(policy, "enabled", None), 

1328 "rules": [], 

1329 } 

1330 

1331 for rule in getattr(policy, "rules", None) or []: 

1332 policies_info[policy_name]["rules"].append( 

1333 { 

1334 "name": rule.name, 

1335 "actions": getattr(rule, "actions", None), 

1336 "effect": getattr(rule, "effect", None), 

1337 "resources": getattr(rule, "resources", None), 

1338 } 

1339 ) 

1340 

1341 return policies_info 

1342 

1343 

1344def generate_object_store_account_exports_dict(blade): 

1345 exports_info = {} 

1346 

1347 for export in blade.get_object_store_account_exports().items: 

1348 exports_info[export.name] = { 

1349 "enabled": getattr(export, "enabled", None), 

1350 "account": getattr(getattr(export, "member", None), "name", None), 

1351 "policy": getattr(getattr(export, "policy", None), "name", None), 

1352 "server": getattr(getattr(export, "server", None), "name", None), 

1353 } 

1354 

1355 return exports_info 

1356 

1357 

1358def generate_object_store_virtual_hosts_dict(blade): 

1359 vhosts_info = {} 

1360 

1361 for vhost in blade.get_object_store_virtual_hosts().items: 

1362 attached = getattr(vhost, "attached_servers", None) or [] 

1363 if not isinstance(attached, list): 

1364 attached = [] 

1365 vhosts_info[vhost.name] = { 

1366 # Before REST 2.20 the name is the hostname 

1367 "hostname": getattr(vhost, "hostname", None) or vhost.name, 

1368 "attached_servers": [getattr(srv, "name", None) for srv in attached], 

1369 } 

1370 

1371 return vhosts_info 

1372 

1373 

1374def generate_realms_dict(blade): 

1375 realms_info = {} 

1376 

1377 for realm in blade.get_realms().items: 

1378 space = getattr(realm, "space", None) 

1379 created = getattr(realm, "created", None) 

1380 realms_info[realm.name] = { 

1381 "created": ( 

1382 datetime.fromtimestamp(created / 1000).strftime("%Y-%m-%d %H:%M:%S") 

1383 if created 

1384 else None 

1385 ), 

1386 "destroyed": getattr(realm, "destroyed", None), 

1387 "time_remaining": getattr(realm, "time_remaining", None), 

1388 "default_inbound_tls_policy": getattr( 

1389 getattr(realm, "default_inbound_tls_policy", None), "name", None 

1390 ), 

1391 "space": { 

1392 "data_reduction": getattr(space, "data_reduction", None), 

1393 "snapshots": getattr(space, "snapshots", None), 

1394 "total_physical": getattr(space, "total_physical", None), 

1395 "total_used": getattr(space, "total_used", None), 

1396 "unique": getattr(space, "unique", None), 

1397 "virtual": getattr(space, "virtual", None), 

1398 "total_provisioned": getattr(space, "total_provisioned", None), 

1399 "available_provisioned": getattr(space, "available_provisioned", None), 

1400 "available_ratio": getattr(space, "available_ratio", None), 

1401 "destroyed": getattr(space, "destroyed", None), 

1402 "destroyed_virtual": getattr(space, "destroyed_virtual", None), 

1403 }, 

1404 } 

1405 

1406 return realms_info 

1407 

1408 

1409def generate_resource_accesses_dict(blade): 

1410 accesses_info = [] 

1411 

1412 for access in blade.get_resource_accesses().items: 

1413 resource = getattr(access, "resource", None) 

1414 scope = getattr(access, "scope", None) 

1415 accesses_info.append( 

1416 { 

1417 "id": getattr(access, "id", None), 

1418 "resource": getattr(resource, "name", None), 

1419 "resource_type": getattr(resource, "resource_type", None), 

1420 "scope": getattr(scope, "name", None), 

1421 "scope_type": getattr(scope, "resource_type", None), 

1422 } 

1423 ) 

1424 

1425 return accesses_info 

1426 

1427 

1428def generate_password_policies_dict(blade): 

1429 policies_info = {} 

1430 policies = list(blade.get_password_policies().items) 

1431 for policy in policies: 

1432 # Rules disabled on the array (set to 0) read back as absent and 

1433 # are reported as null. Durations are reported in seconds, matching 

1434 # the purefb_password_policy module and the admin settings values 

1435 # in the default subset; the API stores milliseconds. 

1436 lockout = getattr(policy, "lockout_duration", None) 

1437 min_age = getattr(policy, "min_password_age", None) 

1438 max_age = getattr(policy, "max_password_age", None) 

1439 policies_info[policy.name] = { 

1440 "enabled": getattr(policy, "enabled", None), 

1441 "min_password_length": getattr(policy, "min_password_length", None), 

1442 "max_login_attempts": getattr(policy, "max_login_attempts", None), 

1443 "lockout_duration": (int(lockout / 1000) if lockout is not None else None), 

1444 "password_history": getattr(policy, "password_history", None), 

1445 "min_password_age": (int(min_age / 1000) if min_age is not None else None), 

1446 "max_password_age": (int(max_age / 1000) if max_age is not None else None), 

1447 "min_character_groups": getattr(policy, "min_character_groups", None), 

1448 "min_characters_per_group": getattr( 

1449 policy, "min_characters_per_group", None 

1450 ), 

1451 "enforce_username_check": getattr(policy, "enforce_username_check", None), 

1452 "enforce_dictionary_check": getattr( 

1453 policy, "enforce_dictionary_check", None 

1454 ), 

1455 } 

1456 return policies_info 

1457 

1458 

1459def generate_object_store_accounts_dict(blade): 

1460 account_info = {} 

1461 

1462 for account in blade.get_object_store_accounts().items: 

1463 acc_name = account.name 

1464 space = account.space 

1465 

1466 account_info[acc_name] = { 

1467 "object_count": account.object_count, 

1468 "data_reduction": space.data_reduction, 

1469 "snapshots_space": space.snapshots, 

1470 "total_physical_space": space.total_physical, 

1471 "unique_space": space.unique, 

1472 "virtual_space": space.virtual, 

1473 "total_provisioned_space": getattr(space, "total_provisioned", None), 

1474 "available_provisioned_space": getattr( 

1475 space, "available_provisioned", None 

1476 ), 

1477 "available_ratio": getattr(space, "available_ratio", None), 

1478 "destroyed_space": getattr(space, "destroyed", None), 

1479 "destroyed_virtual_space": getattr(space, "destroyed_virtual", None), 

1480 "quota_limit": getattr(account, "quota_limit", None), 

1481 "hard_limit_enabled": getattr(account, "hard_limit_enabled", None), 

1482 "total_provisioned": getattr(space, "total_provisioned", None), 

1483 "users": {}, 

1484 "bucket_defaults": { 

1485 "hard_limit_enabled": getattr( 

1486 getattr(account, "bucket_defaults", None), 

1487 "hard_limit_enabled", 

1488 None, 

1489 ), 

1490 "quota_limit": getattr( 

1491 getattr(account, "bucket_defaults", None), 

1492 "quota_limit", 

1493 None, 

1494 ), 

1495 }, 

1496 "public_access_config": { 

1497 "block_new_public_policies": getattr( 

1498 getattr(account, "public_access_config", None), 

1499 "block_new_public_policies", 

1500 None, 

1501 ), 

1502 "block_public_access": getattr( 

1503 getattr(account, "public_access_config", None), 

1504 "block_public_access", 

1505 None, 

1506 ), 

1507 }, 

1508 } 

1509 

1510 # Users for this account 

1511 acc_users = blade.get_object_store_users(filter=f'name="{acc_name}/*"').items 

1512 

1513 for acc_user in acc_users: 

1514 user_name = acc_user.name.split("/")[1] 

1515 account_info[acc_name]["users"][user_name] = { 

1516 "keys": [], 

1517 "policies": [], 

1518 } 

1519 

1520 # Access Keys 

1521 keys_res = blade.get_object_store_access_keys( 

1522 filter=f'user.name="{acc_user.name}"' 

1523 ) 

1524 if keys_res.total_item_count != 0: 

1525 for key in keys_res.items: 

1526 account_info[acc_name]["users"][user_name]["keys"].append( 

1527 { 

1528 "name": key.name, 

1529 "enabled": bool(key.enabled), 

1530 } 

1531 ) 

1532 

1533 # Policies 

1534 policies_res = blade.get_object_store_access_policies_object_store_users( 

1535 member_names=[acc_user.name] 

1536 ) 

1537 if policies_res.total_item_count != 0: 

1538 for policy in policies_res.items: 

1539 account_info[acc_name]["users"][user_name]["policies"].append( 

1540 policy.policy.name 

1541 ) 

1542 

1543 return account_info 

1544 

1545 

1546def generate_fs_dict(blade, exports=None): 

1547 fs_info = {} 

1548 by_fs = {} 

1549 for e in exports or []: 

1550 by_fs.setdefault(e.get("filesystem"), []).append(e) 

1551 for fsystem in blade.get_file_systems().items: 

1552 share = fsystem.name 

1553 

1554 nfs = getattr(fsystem, "nfs", None) 

1555 smb = getattr(fsystem, "smb", None) 

1556 multi = getattr(fsystem, "multi_protocol", None) 

1557 source = getattr(fsystem, "source", None) 

1558 location = getattr(fsystem, "location", None) 

1559 

1560 fs_info[share] = { 

1561 "fast_remove": fsystem.fast_remove_directory_enabled, 

1562 "snapshot_enabled": fsystem.snapshot_directory_enabled, 

1563 "provisioned": fsystem.provisioned, 

1564 "destroyed": fsystem.destroyed, 

1565 "nfs_rules": getattr(nfs, "rules", None), 

1566 "nfs_v3": getattr(nfs, "v3_enabled", False), 

1567 "nfs_v4_1": getattr(nfs, "v4_1_enabled", False), 

1568 "user_quotas": {}, 

1569 "group_quotas": {}, 

1570 "http": fsystem.http.enabled, 

1571 "smb_mode": getattr(smb, "acl_mode", None), 

1572 "multi_protocol": { 

1573 # safegaurd_acls is kept for backwards compatibility 

1574 "safegaurd_acls": getattr(multi, "safeguard_acls", None), 

1575 "safeguard_acls": getattr(multi, "safeguard_acls", None), 

1576 "access_control_style": getattr(multi, "access_control_style", None), 

1577 }, 

1578 "hard_limit": fsystem.hard_limit_enabled, 

1579 "promotion_status": fsystem.promotion_status, 

1580 "requested_promotion_state": fsystem.requested_promotion_state, 

1581 "writable": fsystem.writable, 

1582 "source": { 

1583 "is_local": getattr(source, "is_local", None), 

1584 "name": getattr(source, "name", None), 

1585 "location": getattr(location, "name", None), 

1586 }, 

1587 "default_group_quota": fsystem.default_group_quota, 

1588 "default_user_quota": fsystem.default_user_quota, 

1589 "export_policy": getattr(getattr(nfs, "export_policy", None), "name", None), 

1590 "smb_client_policy": getattr( 

1591 getattr(smb, "client_policy", None), "name", None 

1592 ), 

1593 "smb_share_policy": getattr( 

1594 getattr(smb, "share_policy", None), "name", None 

1595 ), 

1596 "smb_continuous_availability_enabled": getattr( 

1597 smb, "continuous_availability_enabled", False 

1598 ), 

1599 "multi_protocol_access_control_style": getattr( 

1600 multi, "access_control_style", None 

1601 ), 

1602 "multi_protocol_safeguard_acls": getattr(multi, "safeguard_acls", None), 

1603 } 

1604 if exports is not None: 

1605 fs_info[share]["file_system_exports"] = by_fs.get(share, []) 

1606 

1607 # Group quotas 

1608 for group_quota in blade.get_quotas_groups(file_system_names=[share]).items: 

1609 group_name = group_quota.name.rsplit("/", 1)[1] 

1610 fs_info[share]["group_quotas"][group_name] = { 

1611 "group_id": getattr(group_quota.group, "id", None), 

1612 "group_name": getattr(group_quota.group, "name", None), 

1613 "quota": group_quota.quota, 

1614 "usage": group_quota.usage, 

1615 } 

1616 

1617 # User quotas 

1618 for user_quota in blade.get_quotas_users(file_system_names=[share]).items: 

1619 user_name = user_quota.name.rsplit("/", 1)[1] 

1620 fs_info[share]["user_quotas"][user_name] = { 

1621 "user_id": getattr(user_quota.user, "id", None), 

1622 "user_name": getattr(user_quota.user, "name", None), 

1623 "quota": user_quota.quota, 

1624 "usage": user_quota.usage, 

1625 } 

1626 

1627 return fs_info 

1628 

1629 

1630def generate_drives_dict(blade): 

1631 """ 

1632 Drives information is only available for the Legend chassis. 

1633 The Legend chassis product_name has // in it so only bother if 

1634 that is the case. 

1635 """ 

1636 drives_info = {} 

1637 arrays = list(blade.get_arrays().items) 

1638 if not arrays: 

1639 return drives_info 

1640 

1641 product_type = getattr(arrays[0], "product_type", "") 

1642 

1643 if "//" not in product_type: 

1644 return drives_info 

1645 

1646 for drive in blade.get_drives().items: 

1647 drives_info[drive.name] = { 

1648 "progress": getattr(drive, "progress", None), 

1649 "raw_capacity": getattr(drive, "raw_capacity", None), 

1650 "status": getattr(drive, "status", None), 

1651 "details": getattr(drive, "details", None), 

1652 "type": getattr(drive, "type", None), 

1653 } 

1654 return drives_info 

1655 

1656 

1657def generate_servers_dict(blade): 

1658 servers_info = {} 

1659 for server in blade.get_servers().items: 

1660 servers_info[server.name] = { 

1661 "created": datetime.fromtimestamp(server.created / 1000).strftime( 

1662 "%Y-%m-%d %H:%M:%S" 

1663 ), 

1664 "dns": [dns.name for dns in server.dns], 

1665 "directory_services": [ds.name for ds in server.directory_services], 

1666 } 

1667 return servers_info 

1668 

1669 

1670def generate_file_system_exports_dict(blade): 

1671 """Return the list of File System Exports for the whole array. 

1672 

1673 Requires REST API 2.16+ (SERVERS_API_VERSION). Callers must gate on 

1674 the API version before invoking; this helper does not check. 

1675 """ 

1676 exports = [] 

1677 for exp in blade.get_file_system_exports().items: 

1678 member = getattr(exp, "member", None) 

1679 server = getattr(exp, "server", None) 

1680 policy = getattr(exp, "policy", None) 

1681 share_policy = getattr(exp, "share_policy", None) 

1682 ptype = getattr(exp, "policy_type", None) 

1683 exports.append( 

1684 { 

1685 "export_name": getattr(exp, "export_name", None), 

1686 "type": ptype, 

1687 "filesystem": getattr(member, "name", None), 

1688 "server": getattr(server, "name", None), 

1689 "export_policy": ( 

1690 getattr(policy, "name", None) if ptype == "NFS" else None 

1691 ), 

1692 "client_policy": ( 

1693 getattr(policy, "name", None) if ptype == "SMB" else None 

1694 ), 

1695 "share_policy": ( 

1696 getattr(share_policy, "name", None) if ptype == "SMB" else None 

1697 ), 

1698 } 

1699 ) 

1700 return exports 

1701 

1702 

1703def generate_fleet_dict(blade): 

1704 fleet_items = list(blade.get_fleets().items) 

1705 if not fleet_items: 

1706 return {} 

1707 

1708 fleet_name = fleet_items[0].name 

1709 members = blade.get_fleets_members().items 

1710 

1711 fleet_info = { 

1712 fleet_name: { 

1713 "members": { 

1714 member.member.name: { 

1715 "status": member.status, 

1716 "status_details": member.status_details, 

1717 } 

1718 for member in members 

1719 } 

1720 } 

1721 } 

1722 return fleet_info 

1723 

1724 

1725def main(): 

1726 argument_spec = purefb_argument_spec() 

1727 argument_spec.update( 

1728 dict(gather_subset=dict(default="minimum", type="list", elements="str")) 

1729 ) 

1730 

1731 module = AnsibleModule(argument_spec, supports_check_mode=True) 

1732 

1733 blade = get_system(module) 

1734 api_version = get_rest_api_version(blade) 

1735 

1736 if not module.params["gather_subset"]: 

1737 module.params["gather_subset"] = ["minimum"] 

1738 subset = [test.lower() for test in module.params["gather_subset"]] 

1739 valid_subsets = ( 

1740 "all", 

1741 "minimum", 

1742 "config", 

1743 "performance", 

1744 "capacity", 

1745 "network", 

1746 "subnets", 

1747 "lags", 

1748 "filesystems", 

1749 "snapshots", 

1750 "buckets", 

1751 "arrays", 

1752 "replication", 

1753 "policies", 

1754 "accounts", 

1755 "admins", 

1756 "ad", 

1757 "kerberos", 

1758 "drives", 

1759 "servers", 

1760 "fleet", 

1761 "realms", 

1762 ) 

1763 subset_test = (test in valid_subsets for test in subset) 

1764 if not all(subset_test): 

1765 module.fail_json( 

1766 msg="value must gather_subset must be one or more of: %s, got: %s" 

1767 % (",".join(valid_subsets), ",".join(subset)) 

1768 ) 

1769 

1770 info = {} 

1771 

1772 if "minimum" in subset or "all" in subset: 

1773 info["default"] = generate_default_dict(blade) 

1774 if "performance" in subset or "all" in subset: 

1775 info["performance"] = generate_perf_dict(blade) 

1776 if "config" in subset or "all" in subset: 

1777 info["config"] = generate_config_dict(blade) 

1778 if "capacity" in subset or "all" in subset: 

1779 info["capacity"] = generate_capacity_dict(blade) 

1780 if "lags" in subset or "all" in subset: 

1781 info["lag"] = generate_lag_dict(blade) 

1782 if "network" in subset or "all" in subset: 

1783 info["network"] = generate_network_dict(blade) 

1784 if "subnets" in subset or "all" in subset: 

1785 info["subnet"] = generate_subnet_dict(blade) 

1786 if "filesystems" in subset or "all" in subset: 

1787 exports_list = None 

1788 if LooseVersion(SERVERS_API_VERSION) <= LooseVersion(api_version): 

1789 exports_list = generate_file_system_exports_dict(blade) 

1790 info["file_system_exports"] = exports_list 

1791 info["filesystems"] = generate_fs_dict(blade, exports_list) 

1792 if "admins" in subset or "all" in subset: 

1793 info["admins"] = generate_admin_dict(blade) 

1794 if "snapshots" in subset or "all" in subset: 

1795 info["snapshots"] = generate_snap_dict(blade) 

1796 if "buckets" in subset or "all" in subset: 

1797 info["buckets"] = generate_bucket_dict(blade) 

1798 info["object_store_virtual_hosts"] = generate_object_store_virtual_hosts_dict( 

1799 blade 

1800 ) 

1801 if "policies" in subset or "all" in subset: 

1802 info["policies"] = generate_all_policies_dict(blade) 

1803 info["snapshot_policies"] = generate_policies_dict(blade) 

1804 if "arrays" in subset or "all" in subset: 

1805 info["arrays"] = generate_array_conn_dict(blade) 

1806 if "replication" in subset or "all" in subset: 

1807 info["file_replication"] = generate_file_repl_dict(blade) 

1808 info["bucket_replication"] = generate_bucket_repl_dict(blade) 

1809 info["snap_transfers"] = generate_snap_transfer_dict(blade) 

1810 info["remote_credentials"] = generate_remote_creds_dict(blade) 

1811 info["targets"] = generate_targets_dict(blade) 

1812 if "accounts" in subset or "all" in subset: 

1813 info["accounts"] = generate_object_store_accounts_dict(blade) 

1814 if LooseVersion(S3_EXPORT_API_VERSION) <= LooseVersion(api_version): 

1815 info["object_store_account_exports"] = ( 

1816 generate_object_store_account_exports_dict(blade) 

1817 ) 

1818 if "ad" in subset or "all" in subset: 

1819 info["active_directory"] = generate_ad_dict(blade) 

1820 if "kerberos" in subset or "all" in subset: 

1821 info["kerberos"] = generate_kerb_dict(blade) 

1822 if "policies" in subset or "all" in subset: 

1823 info["access_policies"] = generate_object_store_access_policies_dict(blade) 

1824 if LooseVersion(PUBLIC_API_VERSION) <= LooseVersion(api_version): 

1825 info["bucket_access_policies"] = generate_bucket_access_policies_dict(blade) 

1826 info["bucket_cross_origin_policies"] = ( 

1827 generate_bucket_cross_object_policies_dict(blade) 

1828 ) 

1829 info["export_policies"] = generate_nfs_export_policies_dict(blade) 

1830 if LooseVersion(SMB_CLIENT_API_VERSION) <= LooseVersion(api_version): 

1831 # share_policies has always held the SMB *client* policies; it is 

1832 # kept for backwards compatibility alongside the correct key. 

1833 info["smb_client_policies"] = generate_smb_client_policies_dict(blade) 

1834 info["share_policies"] = info["smb_client_policies"] 

1835 info["smb_share_policies"] = generate_smb_share_policies_dict(blade) 

1836 if LooseVersion(NAP_API_VERSION) <= LooseVersion(api_version): 

1837 info["network_access_policies"] = generate_network_access_policies_dict( 

1838 blade 

1839 ) 

1840 if LooseVersion(WORM_API_VERSION) <= LooseVersion(api_version): 

1841 info["worm_data_policies"] = generate_worm_data_policies_dict(blade) 

1842 if LooseVersion(PASSWORD_POLICY_API_VERSION) <= LooseVersion(api_version): 

1843 info["password_policies"] = generate_password_policies_dict(blade) 

1844 if LooseVersion(FLEET_API_VERSION) <= LooseVersion(api_version): 

1845 info["fleet"] = generate_fleet_dict(blade) 

1846 if LooseVersion(TLS_API_VERSION) <= LooseVersion(api_version): 

1847 info["tls_policies"] = generate_tls_policies_dict(blade) 

1848 if LooseVersion(S3_EXPORT_API_VERSION) <= LooseVersion(api_version): 

1849 info["s3_export_policies"] = generate_s3_export_policies_dict(blade) 

1850 if ("realms" in subset or "all" in subset) and LooseVersion( 

1851 REALMS_API_VERSION 

1852 ) <= LooseVersion(api_version): 

1853 info["realms"] = generate_realms_dict(blade) 

1854 info["resource_accesses"] = generate_resource_accesses_dict(blade) 

1855 if ("drives" in subset or "all" in subset) and LooseVersion( 

1856 DRIVES_API_VERSION 

1857 ) <= LooseVersion(api_version): 

1858 info["drives"] = generate_drives_dict(blade) 

1859 # `fleet` is a documented subset of its own; until now the data was only 

1860 # produced as part of `policies`, so gather_subset=fleet returned nothing. 

1861 if ("fleet" in subset or "all" in subset) and LooseVersion( 

1862 FLEET_API_VERSION 

1863 ) <= LooseVersion(api_version): 

1864 info["fleet"] = generate_fleet_dict(blade) 

1865 if ("servers" in subset or "all" in subset) and LooseVersion( 

1866 SERVERS_API_VERSION 

1867 ) <= LooseVersion(api_version): 

1868 info["servers"] = generate_servers_dict(blade) 

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

1870 

1871 

1872if __name__ == "__main__": 

1873 main()