Coverage for plugins/modules/purefb_fs.py: 80%
440 statements
« prev ^ index » next coverage.py v7.14.1, created at 2026-10-30 17:06 -0400
« prev ^ index » next coverage.py v7.14.1, created at 2026-10-30 17:06 -0400
1#!/usr/bin/python
2# -*- coding: utf-8 -*-
4# (c) 2017, Simon Dodsley (simon@everpuredata.com)
5# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
7from __future__ import absolute_import, division, print_function
9__metaclass__ = type
12ANSIBLE_METADATA = {
13 "metadata_version": "1.1",
14 "status": ["preview"],
15 "supported_by": "community",
16}
19DOCUMENTATION = """
20---
21module: purefb_fs
22version_added: "1.0.0"
23short_description: Manage filesystemon Everpure FlashBlade`
24description:
25 - This module manages filesystems on Everpure FlashBlade.
26author: Everpure Ansible Team (@sdodsley) <pure-ansible-team@everpuredata.com>
27options:
28 name:
29 description:
30 - Filesystem Name.
31 required: true
32 type: str
33 state:
34 description:
35 - Create, delete or modifies a filesystem.
36 required: false
37 default: present
38 type: str
39 choices: [ "present", "absent" ]
40 eradicate:
41 description:
42 - Define whether to eradicate the filesystem on delete or leave in trash.
43 required: false
44 type: bool
45 default: false
46 size:
47 description:
48 - Volume size in M, G, T or P units. See examples.
49 - If size is not set at filesystem creation time the filesystem size becomes unlimited.
50 type: str
51 required: false
52 nfsv3:
53 description:
54 - Define whether to NFSv3 protocol is enabled for the filesystem.
55 required: false
56 type: bool
57 default: true
58 nfsv4:
59 description:
60 - Define whether to NFSv4.1 protocol is enabled for the filesystem.
61 required: false
62 type: bool
63 default: true
64 nfs_rules:
65 description:
66 - Define the NFS client export rules for the filesystem, for example
67 C(10.21.200.0/24(rw,no_root_squash)).
68 - Deprecated. Use the M(everpure.flashblade.purefb_export) module to
69 attach NFS export policies via the File System Exports endpoints.
70 This parameter will be removed in 2.0.0.
71 - Only honoured when explicitly set, and only for non-realm
72 filesystems. It is ignored for filesystems in a realm.
73 required: false
74 type: str
75 smb:
76 description:
77 - Define whether to SMB protocol is enabled for the filesystem.
78 - Defaults to C(false) when the filesystem is created. On an existing
79 filesystem the protocol is only changed when this option is set.
80 required: false
81 type: bool
82 smb_aclmode:
83 description:
84 - Specify the ACL mode for the SMB protocol.
85 - Deprecated from Purity//FB 3.1.1. Use I(access_control) instead.
86 required: false
87 type: str
88 default: shared
89 choices: [ "shared", "native" ]
90 http:
91 description:
92 - Define whether to HTTP/HTTPS protocol is enabled for the filesystem.
93 - Defaults to C(false) when the filesystem is created. On an existing
94 filesystem the protocol is only changed when this option is set.
95 required: false
96 type: bool
97 snapshot:
98 description:
99 - Define whether a snapshot directory is enabled for the filesystem.
100 - Defaults to C(false) when the filesystem is created. On an existing
101 filesystem the setting is only changed when this option is set.
102 required: false
103 type: bool
104 writable:
105 description:
106 - Define if a filesystem is writable.
107 required: false
108 type: bool
109 promote:
110 description:
111 - Promote/demote a filesystem.
112 - Can only demote the file-system if it is in a replica-link relationship.
113 required: false
114 type: bool
115 fastremove:
116 description:
117 - Define whether the fast remove directory is enabled for the filesystem.
118 - Defaults to C(false) when the filesystem is created. On an existing
119 filesystem the setting is only changed when this option is set.
120 required: false
121 type: bool
122 hard_limit:
123 description:
124 - Define whether the capacity for a filesystem is a hard limit.
125 - CAUTION This will cause the filesystem to go Read-Only if the
126 capacity has already exceeded the logical size of the filesystem.
127 - Defaults to C(false) when the filesystem is created. On an existing
128 filesystem the setting is only changed when this option is set.
129 required: false
130 type: bool
131 user_quota:
132 description:
133 - Default quota in M, G, T or P units for a user under this file system.
134 required: false
135 type: str
136 group_quota:
137 description:
138 - Default quota in M, G, T or P units for a group under this file system.
139 required: false
140 type: str
141 policy:
142 description:
143 - Filesystem policy to assign to or remove from a filesystem.
144 required: false
145 type: str
146 policy_state:
147 description:
148 - Add or delete a policy from a filesystem
149 required: false
150 default: present
151 type: str
152 choices: [ "absent", "present" ]
153 delete_link:
154 description:
155 - Define if the filesystem can be deleted even if it has a replica link
156 required: false
157 default: false
158 type: bool
159 discard_snaps:
160 description:
161 - Allow a filesystem to be demoted.
162 required: false
163 default: false
164 type: bool
165 access_control:
166 description:
167 - The access control style that is utilized for client actions such
168 as setting file and directory ACLs.
169 type: str
170 default: shared
171 choices: [ 'nfs', 'smb', 'shared', 'independent', 'mode-bits' ]
172 safeguard_acls:
173 description:
174 - Safeguards ACLs on a filesystem.
175 - Performs different roles depending on the filesystem protocol enabled.
176 - See Purity//FB documentation for detailed description.
177 - Defaults to C(true) when the filesystem is created. On an existing
178 filesystem the setting is only changed when this option is set.
179 type: bool
180 export_policy:
181 description:
182 - Name of NFS export policy to assign to filesystem.
183 - Deprecated. This writes the legacy C(nfs.export_policy) field
184 on the filesystem, which Purity//FB marks as deprecated. Use the
185 M(everpure.flashblade.purefb_export) module's C(export_policy)
186 option to attach NFS export policies via the dedicated File
187 System Exports endpoints.
188 This parameter will be removed in 2.0.0.
189 type: str
190 version_added: "1.9.0"
191 share_policy:
192 description:
193 - Name of SMB share policy to assign to filesystem
194 - Only valid with REST 2.10 or higher
195 - Remove policy with empty string
196 - Deprecated. This writes the legacy C(smb.share_policy) field
197 on the filesystem, which Purity//FB marks as deprecated. Use the
198 M(everpure.flashblade.purefb_export) module's C(share_policy)
199 option to attach SMB share policies via the dedicated File
200 System Exports endpoints.
201 This parameter will be removed in 2.0.0.
202 type: str
203 version_added: "1.12.0"
204 client_policy:
205 description:
206 - Name of SMB client policy to assign to filesystem
207 - Only valid with REST 2.10 or higher
208 - Remove policy with empty string
209 - Deprecated. This writes the legacy C(smb.client_policy) field
210 on the filesystem, which Purity//FB marks as deprecated. Use the
211 M(everpure.flashblade.purefb_export) module's C(client_policy)
212 option to attach SMB client policies via the dedicated File
213 System Exports endpoints.
214 This parameter will be removed in 2.0.0.
215 type: str
216 version_added: "1.12.0"
217 continuous_availability:
218 description:
219 - Defines if the file system will be continuously available during
220 disruptive scenarios such as network disruption, blades failover, etc
221 type: bool
222 default: true
223 version_added: "1.15.0"
224 group_ownership:
225 description:
226 - The group ownership for new files and directories in a file system
227 type: str
228 choices: [ 'creator', 'parent-directory' ]
229 default: creator
230 version_added: "1.17.0"
231 ignore_usage:
232 description:
233 - Allow update operations that lead to a hard_limit_enabled file
234 system with usage over its limiting value
235 type: bool
236 default: false
237 version_added: "1.22.0"
238 cancel_in_progress:
239 description:
240 - Whether to cancel any existing storage class transitons that are in progress
241 if the file system is requested to changed to another storage class
242 type: bool
243 default: false
244 version_added: "1.22.0"
245 storage_class:
246 description:
247 - Name of storage class in Fusion fleet file system is associated with
248 type: str
249 version_added: "1.22.0"
250 context:
251 description:
252 - Name of fleet member on which to perform the operation.
253 - This requires the array receiving the request is a member of a fleet
254 and the context name to be a member of the same fleet.
255 type: str
256 default: ""
257 version_added: "1.22.0"
258 realm:
259 description:
260 - Name of the realm to associate the filesystem with.
261 - Requires Purity//FB 4.6.1+ (REST API 2.19+).
262 - Can only be set at filesystem creation time.
263 - To move a filesystem to a different realm, the filesystem must be destroyed and recreated.
264 - If the realm has a QoS policy, the filesystem will inherit it unless overridden.
265 type: str
266 version_added: "1.25.0"
267extends_documentation_fragment:
268 - everpure.flashblade.everpure.fb
269"""
271EXAMPLES = """
272- name: Create new filesystem named foo
273 everpure.flashblade.purefb_fs:
274 name: foo
275 size: 1T
276 state: present
277 fb_url: 10.10.10.2
278 api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641
280- name: Create new filesystem in realm
281 everpure.flashblade.purefb_fs:
282 name: prod-fs
283 size: 5T
284 realm: production-realm
285 state: present
286 fb_url: 10.10.10.2
287 api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641
288 # Filesystem will be created as 'production-realm::prod-fs'
290- name: Modify filesystem that belongs to a realm
291 everpure.flashblade.purefb_fs:
292 name: production-realm::prod-fs
293 size: 10T
294 nfsv4: false
295 state: present
296 fb_url: 10.10.10.2
297 api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641
298 # Note: Use full realm::filesystem name for modifications
299 # Realm association cannot be changed after creation
301- name: Delete filesystem named foo
302 everpure.flashblade.purefb_fs:
303 name: foo
304 state: absent
305 fb_url: 10.10.10.2
306 api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641
308- name: Recover filesystem named foo
309 everpure.flashblade.purefb_fs:
310 name: foo
311 state: present
312 fb_url: 10.10.10.2
313 api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641
315- name: the iss that ven thou hth ansible Eradicate filesystem named foo
316 everpure.flashblade.purefb_fs:
317 name: foo
318 state: absent
319 eradicate: true
320 fb_url: 10.10.10.2
321 api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641
323- name: Promote filesystem named foo ready for failover
324 everpure.flashblade.purefb_fs:
325 name: foo
326 promote: true
327 fb_url: 10.10.10.2
328 api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641
330- name: Demote filesystem named foo after failover
331 everpure.flashblade.purefb_fs:
332 name: foo
333 promote: false
334 fb_url: 10.10.10.2
335 api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641
337- name: Modify attributes of an existing filesystem named foo
338 everpure.flashblade.purefb_fs:
339 name: foo
340 size: 2T
341 nfsv3: false
342 nfsv4: true
343 user_quota: 10K
344 group_quota: 25M
345 snapshot: true
346 fastremove: true
347 hard_limit: true
348 smb: true
349 state: present
350 fb_url: 10.10.10.2
351 api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641
353- name: Attach export_policy to filesystem foo (deprecated - prefer purefb_export)
354 everpure.flashblade.purefb_fs:
355 name: foo
356 export_policy: nfs_pol1
357 state: present
358 fb_url: 10.10.10.2
359 api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641
361- name: Create filesystem foo (modern workflow - attach policies via purefb_export)
362 everpure.flashblade.purefb_fs:
363 name: foo
364 size: 1T
365 smb: true
366 state: present
367 fb_url: 10.10.10.2
368 api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641
370- name: Attach NFS export policy to filesystem foo via purefb_export
371 everpure.flashblade.purefb_export:
372 name: foo_nfs
373 filesystem: foo
374 type: NFS
375 export_policy: nfs_pol1
376 state: present
377 fb_url: 10.10.10.2
378 api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641
380- name: Attach SMB share and client policies to filesystem foo via purefb_export
381 everpure.flashblade.purefb_export:
382 name: foo_smb
383 filesystem: foo
384 type: SMB
385 share_policy: smb_share_pol1
386 client_policy: smb_client_pol1
387 state: present
388 fb_url: 10.10.10.2
389 api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641
390"""
392RETURN = """
393"""
395HAS_PYPURECLIENT = True
396try:
397 from pypureclient.flashblade import (
398 FileSystemPatch,
399 NfsPatch,
400 Reference,
401 Smb,
402 FileSystemPost,
403 Nfs,
404 SmbPost,
405 Http,
406 MultiProtocolPost,
407 MultiProtocol,
408 StorageClassInfo,
409 )
410except ImportError:
411 HAS_PYPURECLIENT = False
413from ansible.module_utils.basic import AnsibleModule, human_to_bytes
414from ansible_collections.everpure.flashblade.plugins.module_utils.purefb import (
415 get_system,
416 purefb_argument_spec,
417)
418from ansible_collections.everpure.flashblade.plugins.module_utils.version import (
419 LooseVersion,
420)
421from ansible_collections.everpure.flashblade.plugins.module_utils.common import (
422 get_error_message,
423 get_filesystem,
424 get_rest_api_version,
425)
427EXPORT_POLICY_API_VERSION = "2.3"
428SMB_POLICY_API_VERSION = "2.10"
429CA_API_VERSION = "2.12"
430GOWNER_API_VERSION = "2.13"
431CONTEXT_API_VERSION = "2.17"
432REALM_API_VERSION = "2.19"
435def _item_count(res):
436 """Return the number of items in a successful SDK response.
438 A membership GET returns 200 with an empty item list when nothing
439 matches, so the status code alone does not say whether a member exists.
440 """
441 if getattr(res, "status_code", None) != 200:
442 return 0
443 count = getattr(res, "total_item_count", None)
444 if isinstance(count, int):
445 return count
446 try:
447 return len(list(res.items))
448 except TypeError:
449 return 0
452def create_fs(module, blade):
453 """Create Filesystem"""
454 changed = True
455 api_version = get_rest_api_version(blade)
456 if not module.check_mode:
457 # Boolean flags default to None so that modify_fs only touches them
458 # when the caller sets them. At creation time None means the array
459 # default (safeguard_acls on, every other flag off).
460 safeguard_acls = module.params["safeguard_acls"]
461 if safeguard_acls is None:
462 safeguard_acls = True
463 # Determine realm from either realm parameter or name prefix (realm::fs)
464 realm_name = None
465 if module.params.get("realm"):
466 realm_name = module.params["realm"]
467 elif "::" in module.params["name"]:
468 # Extract realm from name (e.g., "production::prod-fs" -> "production")
469 realm_name = module.params["name"].split("::")[0]
471 # Validate realm if present
472 if realm_name:
473 if LooseVersion(REALM_API_VERSION) > LooseVersion(api_version):
474 module.fail_json(
475 msg="Realm support requires Purity//FB 4.6.1+ (REST API 2.19+)"
476 )
477 # Check realm exists
478 realm_check = blade.get_realms(destroyed=False, names=[realm_name])
479 if realm_check.status_code != 200:
480 module.fail_json(msg="Realm '{0}' does not exist".format(realm_name))
482 if module.params["size"]:
483 size = human_to_bytes(module.params["size"])
484 else:
485 size = 0
487 if module.params["user_quota"]:
488 user_quota = human_to_bytes(module.params["user_quota"])
489 else:
490 user_quota = None
491 if module.params["group_quota"]:
492 group_quota = human_to_bytes(module.params["group_quota"])
493 else:
494 group_quota = None
496 if module.params["access_control"] == "nfs" and not (
497 module.params["nfsv3"] or module.params["nfsv4"]
498 ):
499 module.fail_json(
500 msg="Cannot set access_control to nfs when NFS is not enabled."
501 )
502 if (
503 module.params["access_control"] in ["smb", "independent"]
504 and not module.params["smb"]
505 ):
506 module.fail_json(
507 msg="Cannot set access_control to smb or independent when SMB is not enabled."
508 )
509 if safeguard_acls and (
510 module.params["access_control"] in ["mode-bits", "independent"]
511 ):
512 module.fail_json(
513 msg="ACL Safeguarding cannot be enabled if access_control is mode-bits or independent."
514 )
515 # Determine if this is a realm filesystem
516 realm_name = None
517 if module.params.get("realm"):
518 realm_name = module.params["realm"]
519 elif "::" in module.params["name"]:
520 realm_name = module.params["name"].split("::")[0]
522 # nfs_rules is deprecated in favour of export_policy. It is still
523 # honoured for non-realm filesystems for backwards compatibility, but
524 # only when explicitly supplied.
525 nfs_kwargs = {
526 "v3_enabled": module.params["nfsv3"],
527 "v4_1_enabled": module.params["nfsv4"],
528 }
529 if module.params["nfs_rules"] is not None:
530 module.deprecate(
531 "nfs_rules is deprecated. Use the purefb_export module to attach "
532 "NFS export policies via the File System Exports endpoints.",
533 version="2.0.0",
534 collection_name="everpure.flashblade",
535 )
536 if realm_name:
537 module.warn(
538 "nfs_rules is not supported for realm filesystems and "
539 "will be ignored."
540 )
541 else:
542 nfs_kwargs["rules"] = module.params["nfs_rules"]
543 if module.params["export_policy"] is not None:
544 module.deprecate(
545 "export_policy is deprecated. Use the purefb_export "
546 "module's export_policy option to attach NFS export "
547 "policies via the dedicated File System Exports "
548 "endpoints.",
549 version="2.0.0",
550 collection_name="everpure.flashblade",
551 )
552 if module.params["share_policy"] is not None:
553 module.deprecate(
554 "share_policy is deprecated. Use the purefb_export "
555 "module's share_policy option to attach SMB share "
556 "policies via the dedicated File System Exports "
557 "endpoints.",
558 version="2.0.0",
559 collection_name="everpure.flashblade",
560 )
561 if module.params["client_policy"] is not None:
562 module.deprecate(
563 "client_policy is deprecated. Use the purefb_export "
564 "module's client_policy option to attach SMB client "
565 "policies via the dedicated File System Exports "
566 "endpoints.",
567 version="2.0.0",
568 collection_name="everpure.flashblade",
569 )
571 # Build FileSystemPost object
572 fs_obj = FileSystemPost(
573 provisioned=size,
574 fast_remove_directory_enabled=bool(module.params["fastremove"]),
575 hard_limit_enabled=bool(module.params["hard_limit"]),
576 snapshot_directory_enabled=bool(module.params["snapshot"]),
577 nfs=Nfs(**nfs_kwargs),
578 smb=SmbPost(enabled=bool(module.params["smb"])),
579 http=Http(enabled=bool(module.params["http"])),
580 multi_protocol=MultiProtocolPost(
581 safeguard_acls=safeguard_acls,
582 access_control_style=module.params["access_control"],
583 ),
584 default_user_quota=user_quota,
585 default_group_quota=group_quota,
586 )
587 # Construct filesystem name - if realm provided, prepend realm::
588 fs_name = module.params["name"]
589 if realm_name and "::" not in fs_name:
590 fs_name = "{0}::{1}".format(realm_name, fs_name)
592 # Build post_file_systems call with optional parameters
593 post_kwargs = {
594 "names": [fs_name],
595 "file_system": fs_obj,
596 }
598 # Add context if API supports it
599 if (
600 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
601 and module.params["context"]
602 ):
603 post_kwargs["context_names"] = [module.params["context"]]
605 # Add default_exports=[""] for realm filesystems (empty string)
606 if realm_name:
607 post_kwargs["default_exports"] = ["''"]
609 res = blade.post_file_systems(**post_kwargs)
610 if res.status_code != 200:
611 module.fail_json(
612 msg="Failed to create filesystem {0}. Error: {1}".format(
613 fs_name, get_error_message(res)
614 )
615 )
616 if module.params["policy"]:
617 if (
618 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
619 and module.params["context"]
620 ):
621 res = blade.get_policies(
622 names=[module.params["policy"]],
623 context_names=[module.params["context"]],
624 )
625 else:
626 res = blade.get_policies(names=[module.params["policy"]])
627 if res.status_code != 200:
628 _delete_fs(module, blade)
629 module.fail_json(
630 msg="Policy {0} doesn't exist.".format(module.params["policy"])
631 )
632 if (
633 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
634 and module.params["context"]
635 ):
636 res = blade.post_policies_file_systems(
637 policy_names=[module.params["policy"]],
638 member_names=[fs_name],
639 context_names=[module.params["context"]],
640 )
641 else:
642 res = blade.post_policies_file_systems(
643 policy_names=[module.params["policy"]],
644 member_names=[fs_name],
645 )
646 if res.status_code != 200:
647 _delete_fs(module, blade)
648 module.fail_json(
649 msg="Failed to apply policy {0} when creating filesystem {1}. Error: {2}".format(
650 module.params["policy"],
651 fs_name,
652 get_error_message(res),
653 )
654 )
655 if (
656 LooseVersion(EXPORT_POLICY_API_VERSION) <= LooseVersion(api_version)
657 and module.params["export_policy"]
658 and (module.params["nfsv3"] or module.params["nfsv4"])
659 ):
660 export_attr = FileSystemPatch(
661 nfs=NfsPatch(
662 export_policy=Reference(name=module.params["export_policy"])
663 )
664 )
665 if (
666 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
667 and module.params["context"]
668 ):
669 res = blade.patch_file_systems(
670 names=[fs_name],
671 file_system=export_attr,
672 context_names=[module.params["context"]],
673 )
674 else:
675 res = blade.patch_file_systems(names=[fs_name], file_system=export_attr)
676 if res.status_code != 200:
677 module.fail_json(
678 msg="Filesystem {0} created, but failed to assign export "
679 "policy {1}. Error: {2}".format(
680 fs_name,
681 module.params["export_policy"],
682 get_error_message(res),
683 )
684 )
685 if (
686 LooseVersion(SMB_POLICY_API_VERSION) <= LooseVersion(api_version)
687 and module.params["smb"]
688 ):
689 if module.params["client_policy"]:
690 export_attr = FileSystemPatch(
691 smb=Smb(
692 client_policy=Reference(name=module.params["client_policy"])
693 )
694 )
695 if (
696 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
697 and module.params["context"]
698 ):
699 res = blade.patch_file_systems(
700 names=[fs_name],
701 file_system=export_attr,
702 context_names=[module.params["context"]],
703 )
704 else:
705 res = blade.patch_file_systems(
706 names=[fs_name], file_system=export_attr
707 )
708 if res.status_code != 200:
709 module.fail_json(
710 msg="Filesystem {0} created, but failed to assign client "
711 "policy {1}. Error: {2}".format(
712 fs_name,
713 module.params["client_policy"],
714 get_error_message(res),
715 )
716 )
717 if module.params["share_policy"]:
718 export_attr = FileSystemPatch(
719 smb=Smb(share_policy=Reference(name=module.params["share_policy"]))
720 )
721 if (
722 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
723 and module.params["context"]
724 ):
725 res = blade.patch_file_systems(
726 names=[fs_name],
727 file_system=export_attr,
728 context_names=[module.params["context"]],
729 )
730 else:
731 res = blade.patch_file_systems(
732 names=[fs_name],
733 file_system=export_attr,
734 )
735 if res.status_code != 200:
736 module.fail_json(
737 msg="Filesystem {0} created, but failed to assign share "
738 "policy {1}. Error: {2}".format(
739 fs_name,
740 module.params["share_policy"],
741 get_error_message(res),
742 )
743 )
744 if LooseVersion(CA_API_VERSION) <= LooseVersion(api_version):
745 ca_attr = FileSystemPatch(
746 smb=Smb(
747 continuous_availability_enabled=module.params[
748 "continuous_availability"
749 ]
750 )
751 )
752 if (
753 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
754 and module.params["context"]
755 ):
756 res = blade.patch_file_systems(
757 names=[fs_name],
758 file_system=ca_attr,
759 context_names=[module.params["context"]],
760 )
761 else:
762 res = blade.patch_file_systems(names=[fs_name], file_system=ca_attr)
763 if res.status_code != 200:
764 module.fail_json(
765 msg="Filesystem {0} created, but failed to set continuous availability. "
766 "Error: {1}".format(
767 fs_name,
768 get_error_message(res),
769 )
770 )
771 # group_ownership and storage_class are not SMB attributes, so they
772 # are applied whether or not SMB is enabled.
773 if (
774 LooseVersion(GOWNER_API_VERSION) <= LooseVersion(api_version)
775 and module.params["group_ownership"]
776 ):
777 go_attr = FileSystemPatch(group_ownership=module.params["group_ownership"])
778 if (
779 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
780 and module.params["context"]
781 ):
782 res = blade.patch_file_systems(
783 names=[fs_name],
784 file_system=go_attr,
785 context_names=[module.params["context"]],
786 )
787 else:
788 res = blade.patch_file_systems(names=[fs_name], file_system=go_attr)
789 if res.status_code != 200:
790 module.fail_json(
791 msg="Filesystem {0} created, but failed to set group ownership. "
792 "Error: {1}".format(
793 fs_name,
794 get_error_message(res),
795 )
796 )
797 if (
798 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
799 and module.params["storage_class"]
800 ):
801 sc_patch = {
802 "names": [fs_name],
803 "file_system": FileSystemPatch(
804 storage_class=StorageClassInfo(name=module.params["storage_class"])
805 ),
806 "cancel_in_progress_storage_class_transition": False,
807 }
808 if module.params["context"]:
809 sc_patch["context_names"] = [module.params["context"]]
810 res = blade.patch_file_systems(**sc_patch)
811 if res.status_code != 200:
812 module.fail_json(
813 msg="Filesystem {0} created, but failed to set storage class. "
814 "Error: {1}".format(
815 fs_name,
816 get_error_message(res),
817 )
818 )
820 module.exit_json(changed=changed)
823def modify_fs(module, blade):
824 """Modify Filesystem"""
825 changed = False
826 change_client = False
827 change_export = False
828 change_share = False
829 change_ca = False
830 change_go = False
831 change_sc = False
832 change_rules = False
833 mod_fs = False
834 # Determine if this is a realm filesystem
835 realm_name = None
836 if module.params.get("realm"):
837 realm_name = module.params["realm"]
838 elif "::" in module.params["name"]:
839 realm_name = module.params["name"].split("::")[0]
840 # Construct filesystem name - if realm provided, prepend realm::
841 fs_name = module.params["name"]
842 if realm_name and "::" not in fs_name:
843 fs_name = "{0}::{1}".format(realm_name, fs_name)
844 api_version = get_rest_api_version(blade)
845 if module.params["policy"] and module.params["policy_state"] == "present":
846 if (
847 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
848 and module.params["context"]
849 ):
850 res = blade.get_policies(
851 names=[module.params["policy"]],
852 context_names=[module.params["context"]],
853 )
854 else:
855 res = blade.get_policies(names=[module.params["policy"]])
856 if res.status_code != 200:
857 module.fail_json(
858 msg="Policy {0} doesn't exist.".format(module.params["policy"])
859 )
860 if (
861 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
862 and module.params["context"]
863 ):
864 res = blade.get_policies_file_systems(
865 policy_names=[module.params["policy"]],
866 member_names=[fs_name],
867 context_names=[module.params["context"]],
868 )
869 else:
870 res = blade.get_policies_file_systems(
871 policy_names=[module.params["policy"]],
872 member_names=[fs_name],
873 )
874 if not _item_count(res):
875 if (
876 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
877 and module.params["context"]
878 ):
879 res = blade.post_policies_file_systems(
880 policy_names=[module.params["policy"]],
881 member_names=[fs_name],
882 context_names=[module.params["context"]],
883 )
884 else:
885 res = blade.post_policies_file_systems(
886 policy_names=[module.params["policy"]],
887 member_names=[fs_name],
888 )
889 mod_fs = True
890 if res.status_code != 200:
891 module.fail_json(
892 msg="Failed to add filesystem {0} to policy {1}. Error: {2}".format(
893 fs_name,
894 module.params["policy"],
895 get_error_message(res),
896 )
897 )
898 if module.params["policy"] and module.params["policy_state"] == "absent":
899 if (
900 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
901 and module.params["context"]
902 ):
903 res = blade.get_policies(
904 names=[module.params["policy"]],
905 context_names=[module.params["context"]],
906 )
907 else:
908 res = blade.get_policies(names=[module.params["policy"]])
909 if res.status_code == 200:
910 if (
911 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
912 and module.params["context"]
913 ):
914 res = blade.get_policies_file_systems(
915 policy_names=[module.params["policy"]],
916 member_names=[fs_name],
917 context_names=[module.params["context"]],
918 )
919 else:
920 res = blade.get_policies_file_systems(
921 policy_names=[module.params["policy"]],
922 member_names=[fs_name],
923 )
924 # A 200 with no items means the policy is not attached, so a
925 # second policy_state=absent run must be a no-op.
926 if _item_count(res):
927 if (
928 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
929 and module.params["context"]
930 ):
931 res = blade.delete_policies_file_systems(
932 policy_names=[module.params["policy"]],
933 member_names=[fs_name],
934 context_names=[module.params["context"]],
935 )
936 else:
937 res = blade.delete_policies_file_systems(
938 policy_names=[module.params["policy"]],
939 member_names=[fs_name],
940 )
941 mod_fs = True
942 if res.status_code != 200:
943 module.fail_json(
944 msg="Failed to remove filesystem {0} from policy {1}. Error: {2}".format(
945 fs_name,
946 module.params["policy"],
947 get_error_message(res),
948 )
949 )
950 if module.params["user_quota"]:
951 user_quota = human_to_bytes(module.params["user_quota"])
952 if module.params["group_quota"]:
953 group_quota = human_to_bytes(module.params["group_quota"])
954 fsys = get_filesystem(module, blade)
955 new_fsys = {
956 "destroyed": fsys.destroyed,
957 "provisioned": fsys.provisioned,
958 "nfsv3": fsys.nfs.v3_enabled,
959 "nfsv4": fsys.nfs.v4_1_enabled,
960 "default_user_quota": fsys.default_user_quota,
961 "default_group_quota": fsys.default_group_quota,
962 "group_ownership": fsys.group_ownership,
963 "smb": fsys.smb.enabled,
964 "http": fsys.http.enabled,
965 "snapshot": fsys.snapshot_directory_enabled,
966 "fastremove": fsys.fast_remove_directory_enabled,
967 "hardlimit": fsys.hard_limit_enabled,
968 "safeguard_acls": fsys.multi_protocol.safeguard_acls,
969 "acs": fsys.multi_protocol.access_control_style,
970 "writable": fsys.writable,
971 "promotion_status": fsys.promotion_status,
972 "requested_promotion_state": fsys.requested_promotion_state,
973 "storage_class": getattr(getattr(fsys, "storage_class", None), "name", None),
974 }
975 if fsys.destroyed:
976 new_fsys["destroyed"] = False
977 mod_fs = True
978 if module.params["size"]:
979 if human_to_bytes(module.params["size"]) != fsys.provisioned:
980 new_fsys["provisioned"] = human_to_bytes(module.params["size"])
981 mod_fs = True
982 if module.params["nfsv3"] != fsys.nfs.v3_enabled:
983 new_fsys["nfsv3"] = module.params["nfsv3"]
984 mod_fs = True
985 if module.params["nfsv4"] != fsys.nfs.v4_1_enabled:
986 new_fsys["nfsv4"] = module.params["nfsv4"]
987 mod_fs = True
988 if module.params["user_quota"] and user_quota != fsys.default_user_quota:
989 new_fsys["default_user_quota"] = user_quota
990 mod_fs = True
991 if module.params["group_quota"] and group_quota != fsys.default_group_quota:
992 new_fsys["default_group_quota"] = group_quota
993 mod_fs = True
994 # Boolean flags are only compared when the caller set them, and then in
995 # both directions, so an explicit false turns the setting off.
996 bool_flags = [
997 ("smb", "smb", fsys.smb.enabled),
998 ("http", "http", fsys.http.enabled),
999 ("snapshot", "snapshot", fsys.snapshot_directory_enabled),
1000 ("fastremove", "fastremove", fsys.fast_remove_directory_enabled),
1001 ("hard_limit", "hardlimit", fsys.hard_limit_enabled),
1002 ("safeguard_acls", "safeguard_acls", fsys.multi_protocol.safeguard_acls),
1003 ]
1004 for param, key, current in bool_flags:
1005 if module.params[param] is not None and module.params[param] != current:
1006 new_fsys[key] = module.params[param]
1007 mod_fs = True
1008 if module.params["access_control"] != fsys.multi_protocol.access_control_style:
1009 new_fsys["acs"] = module.params["access_control"]
1010 mod_fs = True
1011 if module.params["writable"] is not None:
1012 if not module.params["writable"] and fsys.writable:
1013 new_fsys["writable"] = module.params["writable"]
1014 mod_fs = True
1015 if (
1016 module.params["writable"]
1017 and not fsys.writable
1018 and fsys.promotion_status == "promoted"
1019 ):
1020 new_fsys["writable"] = module.params["writable"]
1021 mod_fs = True
1022 if module.params["promote"] is not None:
1023 if module.params["promote"] and fsys.promotion_status != "promoted":
1024 new_fsys["requested_promotion_state"] = "promoted"
1025 mod_fs = True
1026 if not module.params["promote"] and fsys.promotion_status == "promoted":
1027 # Demotion only allowed on filesystems in a replica-link
1028 if (
1029 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
1030 and module.params["context"]
1031 ):
1032 res = blade.get_file_system_replica_links(
1033 local_file_system_names=[fs_name],
1034 context_names=[module.params["context"]],
1035 )
1036 else:
1037 res = blade.get_file_system_replica_links(
1038 local_file_system_names=[fs_name]
1039 )
1040 if res.status_code != 200:
1041 module.fail_json(
1042 msg="Filesystem {0} not demoted. Not in a replica-link".format(
1043 fs_name
1044 )
1045 )
1046 new_fsys["requested_promotion_state"] = "demoted"
1047 mod_fs = True
1048 if mod_fs:
1049 changed = True
1050 if not module.check_mode:
1051 if (
1052 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
1053 and module.params["context"]
1054 ):
1055 if new_fsys["destroyed"] != fsys.destroyed:
1056 delres = blade.patch_file_systems(
1057 names=[fs_name],
1058 context_names=[module.params["context"]],
1059 file_system=FileSystemPatch(destroyed=new_fsys["destroyed"]),
1060 )
1061 if delres.status_code != 200:
1062 module.fail_json(
1063 msg="Failed to update filesystem {0} deleted status. Error {1}".format(
1064 fs_name, get_error_message(res)
1065 )
1066 )
1067 res = blade.patch_file_systems(
1068 names=[fs_name],
1069 context_names=[module.params["context"]],
1070 file_system=FileSystemPatch(
1071 default_group_quota=new_fsys["default_group_quota"],
1072 default_user_quota=new_fsys["default_user_quota"],
1073 fast_remove_directory_enabled=new_fsys["fastremove"],
1074 hard_limit_enabled=new_fsys["hardlimit"],
1075 snapshot_directory_enabled=new_fsys["snapshot"],
1076 http=Http(enabled=new_fsys["http"]),
1077 multi_protocol=MultiProtocol(
1078 access_control_style=new_fsys["acs"],
1079 safeguard_acls=new_fsys["safeguard_acls"],
1080 ),
1081 nfs=NfsPatch(
1082 v3_enabled=new_fsys["nfsv3"],
1083 v4_1_enabled=new_fsys["nfsv4"],
1084 ),
1085 provisioned=new_fsys["provisioned"],
1086 requested_promotion_state=new_fsys["requested_promotion_state"],
1087 smb=Smb(enabled=new_fsys["smb"]),
1088 writable=new_fsys["writable"],
1089 ),
1090 discard_non_snapshotted_data=module.params["discard_snaps"],
1091 ignore_usage=module.params["ignore_usage"],
1092 )
1093 else:
1094 if new_fsys["destroyed"] != fsys.destroyed:
1095 delres = blade.patch_file_systems(
1096 names=[fs_name],
1097 file_system=FileSystemPatch(destroyed=new_fsys["destroyed"]),
1098 )
1099 if delres.status_code != 200:
1100 module.fail_json(
1101 msg="Failed to update filesystem {0} deleted status. Error {1}".format(
1102 fs_name, get_error_message(res)
1103 )
1104 )
1105 res = blade.patch_file_systems(
1106 names=[fs_name],
1107 file_system=FileSystemPatch(
1108 default_group_quota=new_fsys["default_group_quota"],
1109 default_user_quota=new_fsys["default_user_quota"],
1110 fast_remove_directory_enabled=new_fsys["fastremove"],
1111 hard_limit_enabled=new_fsys["hardlimit"],
1112 snapshot_directory_enabled=new_fsys["snapshot"],
1113 http=Http(enabled=new_fsys["http"]),
1114 multi_protocol=MultiProtocol(
1115 access_control_style=new_fsys["acs"],
1116 safeguard_acls=new_fsys["safeguard_acls"],
1117 ),
1118 nfs=NfsPatch(
1119 v3_enabled=new_fsys["nfsv3"],
1120 v4_1_enabled=new_fsys["nfsv4"],
1121 ),
1122 provisioned=new_fsys["provisioned"],
1123 requested_promotion_state=new_fsys["requested_promotion_state"],
1124 smb=Smb(enabled=new_fsys["smb"]),
1125 writable=new_fsys["writable"],
1126 ),
1127 discard_non_snapshotted_data=module.params["discard_snaps"],
1128 ignore_usage=module.params["ignore_usage"],
1129 )
1130 if res.status_code != 200:
1131 module.fail_json(
1132 msg="Failed to update filesystem {0}. Error {1}".format(
1133 fs_name, get_error_message(res)
1134 )
1135 )
1136 if (
1137 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
1138 and module.params["context"]
1139 ):
1140 current_fs = list(
1141 blade.get_file_systems(
1142 context_names=[module.params["context"]],
1143 filter="name='" + fs_name + "'",
1144 ).items
1145 )[0]
1146 else:
1147 current_fs = list(
1148 blade.get_file_systems(filter="name='" + fs_name + "'").items
1149 )[0]
1150 if (
1151 LooseVersion(EXPORT_POLICY_API_VERSION) <= LooseVersion(api_version)
1152 and module.params["export_policy"]
1153 and (current_fs.nfs.v3_enabled or current_fs.nfs.v4_1_enabled)
1154 ):
1155 change_export = False
1156 if (
1157 current_fs.nfs.export_policy.name
1158 and current_fs.nfs.export_policy.name != module.params["export_policy"]
1159 ):
1160 change_export = True
1161 if not current_fs.nfs.export_policy.name and module.params["export_policy"]:
1162 change_export = True
1163 if change_export and not module.check_mode:
1164 export_attr = FileSystemPatch(
1165 nfs=NfsPatch(
1166 export_policy=Reference(name=module.params["export_policy"])
1167 )
1168 )
1169 if (
1170 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
1171 and module.params["context"]
1172 ):
1173 res = blade.patch_file_systems(
1174 names=[fs_name],
1175 file_system=export_attr,
1176 context_names=[module.params["context"]],
1177 )
1178 else:
1179 res = blade.patch_file_systems(names=[fs_name], file_system=export_attr)
1180 if res.status_code != 200:
1181 module.fail_json(
1182 msg="Failed to modify export policy {1} for "
1183 "filesystem {0}. Error: {2}".format(
1184 fs_name,
1185 module.params["export_policy"],
1186 get_error_message(res),
1187 )
1188 )
1189 if module.params["export_policy"] is not None:
1190 module.deprecate(
1191 "export_policy is deprecated. Use the purefb_export "
1192 "module's export_policy option to attach NFS export "
1193 "policies via the dedicated File System Exports "
1194 "endpoints.",
1195 version="2.0.0",
1196 collection_name="everpure.flashblade",
1197 )
1198 if module.params["share_policy"] is not None:
1199 module.deprecate(
1200 "share_policy is deprecated. Use the purefb_export "
1201 "module's share_policy option to attach SMB share "
1202 "policies via the dedicated File System Exports "
1203 "endpoints.",
1204 version="2.0.0",
1205 collection_name="everpure.flashblade",
1206 )
1207 if module.params["client_policy"] is not None:
1208 module.deprecate(
1209 "client_policy is deprecated. Use the purefb_export "
1210 "module's client_policy option to attach SMB client "
1211 "policies via the dedicated File System Exports "
1212 "endpoints.",
1213 version="2.0.0",
1214 collection_name="everpure.flashblade",
1215 )
1216 if module.params["nfs_rules"] is not None:
1217 module.deprecate(
1218 "nfs_rules is deprecated. Use the purefb_export module to attach "
1219 "NFS export policies via the File System Exports endpoints.",
1220 version="2.0.0",
1221 collection_name="everpure.flashblade",
1222 )
1223 if realm_name:
1224 module.warn(
1225 "nfs_rules is not supported for realm filesystems and "
1226 "will be ignored."
1227 )
1228 elif getattr(current_fs.nfs, "rules", None) != module.params["nfs_rules"]:
1229 change_rules = True
1230 if not module.check_mode:
1231 rules_attr = FileSystemPatch(
1232 nfs=NfsPatch(rules=module.params["nfs_rules"])
1233 )
1234 if (
1235 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
1236 and module.params["context"]
1237 ):
1238 res = blade.patch_file_systems(
1239 names=[fs_name],
1240 file_system=rules_attr,
1241 context_names=[module.params["context"]],
1242 )
1243 else:
1244 res = blade.patch_file_systems(
1245 names=[fs_name], file_system=rules_attr
1246 )
1247 if res.status_code != 200:
1248 module.fail_json(
1249 msg="Failed to modify nfs_rules for "
1250 "filesystem {0}. Error: {1}".format(
1251 fs_name,
1252 get_error_message(res),
1253 )
1254 )
1255 if (
1256 LooseVersion(SMB_POLICY_API_VERSION) <= LooseVersion(api_version)
1257 and module.params["client_policy"]
1258 and current_fs.smb.enabled
1259 ):
1260 if (
1261 current_fs.smb.client_policy.name
1262 and current_fs.smb.client_policy.name != module.params["client_policy"]
1263 ):
1264 change_client = True
1265 if not current_fs.smb.client_policy.name and module.params["client_policy"]:
1266 change_client = True
1267 if change_client and not module.check_mode:
1268 client_attr = FileSystemPatch(
1269 smb=Smb(client_policy=Reference(name=module.params["client_policy"]))
1270 )
1271 if (
1272 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
1273 and module.params["context"]
1274 ):
1275 res = blade.patch_file_systems(
1276 names=[fs_name],
1277 file_system=client_attr,
1278 context_names=[module.params["context"]],
1279 )
1280 else:
1281 res = blade.patch_file_systems(names=[fs_name], file_system=client_attr)
1282 if res.status_code != 200:
1283 module.fail_json(
1284 msg="Failed to modify client policy {1} for "
1285 "filesystem {0}. Error: {2}".format(
1286 fs_name,
1287 module.params["client_policy"],
1288 get_error_message(res),
1289 )
1290 )
1291 if (
1292 LooseVersion(SMB_POLICY_API_VERSION) <= LooseVersion(api_version)
1293 and module.params["share_policy"]
1294 and current_fs.smb.enabled
1295 ):
1296 if (
1297 current_fs.smb.share_policy.name
1298 and current_fs.smb.share_policy.name != module.params["share_policy"]
1299 ):
1300 change_share = True
1301 if not current_fs.smb.share_policy.name and module.params["share_policy"]:
1302 change_share = True
1303 if change_share and not module.check_mode:
1304 share_attr = FileSystemPatch(
1305 smb=Smb(share_policy=Reference(name=module.params["share_policy"]))
1306 )
1307 if (
1308 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
1309 and module.params["context"]
1310 ):
1311 res = blade.patch_file_systems(
1312 names=[fs_name],
1313 file_system=share_attr,
1314 context_names=[module.params["context"]],
1315 )
1316 else:
1317 res = blade.patch_file_systems(names=[fs_name], file_system=share_attr)
1318 if res.status_code != 200:
1319 module.fail_json(
1320 msg="Failed to modify share policy {1} for "
1321 "filesystem {0}. Error: {2}".format(
1322 fs_name,
1323 module.params["share_policy"],
1324 get_error_message(res),
1325 )
1326 )
1327 if (
1328 LooseVersion(CA_API_VERSION) <= LooseVersion(api_version)
1329 and current_fs.smb.enabled
1330 ):
1331 if (
1332 module.params["continuous_availability"]
1333 != current_fs.smb.continuous_availability_enabled
1334 ):
1335 change_ca = True
1336 if not module.check_mode and change_ca:
1337 ca_attr = FileSystemPatch(
1338 smb=Smb(
1339 continuous_availability_enabled=module.params[
1340 "continuous_availability"
1341 ]
1342 )
1343 )
1344 if (
1345 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
1346 and module.params["context"]
1347 ):
1348 res = blade.patch_file_systems(
1349 names=[fs_name],
1350 file_system=ca_attr,
1351 context_names=[module.params["context"]],
1352 )
1353 else:
1354 res = blade.patch_file_systems(names=[fs_name], file_system=ca_attr)
1355 if res.status_code != 200:
1356 module.fail_json(
1357 msg="Failed to modify continuous availability for "
1358 "filesystem {0}. Error: {1}".format(
1359 fs_name,
1360 get_error_message(res),
1361 )
1362 )
1363 if LooseVersion(GOWNER_API_VERSION) <= LooseVersion(api_version):
1364 if module.params["group_ownership"] != current_fs.group_ownership:
1365 change_go = True
1366 if not module.check_mode and change_go:
1367 go_attr = FileSystemPatch(group_ownership=module.params["group_ownership"])
1368 if (
1369 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
1370 and module.params["context"]
1371 ):
1372 res = blade.patch_file_systems(
1373 names=[fs_name],
1374 file_system=go_attr,
1375 context_names=[module.params["context"]],
1376 )
1377 else:
1378 res = blade.patch_file_systems(names=[fs_name], file_system=go_attr)
1379 if res.status_code != 200:
1380 module.fail_json(
1381 msg="Failed to modify group ownership for "
1382 "filesystem {0}. Error: {1}".format(
1383 fs_name,
1384 get_error_message(res),
1385 )
1386 )
1387 if (
1388 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
1389 and module.params["storage_class"]
1390 ):
1391 if module.params["storage_class"] != current_fs.storage_class:
1392 change_sc = True
1393 sc_patch = {
1394 "names": [fs_name],
1395 "file_system": FileSystemPatch(
1396 storage_class=StorageClassInfo(name=module.params["storage_class"])
1397 ),
1398 "cancel_in_progress_storage_class_transition": module.params[
1399 "cancel_in_progress"
1400 ],
1401 }
1402 if module.params["context"]:
1403 sc_patch["context_names"] = [module.params["context"]]
1404 res = blade.patch_file_systems(**sc_patch)
1406 module.exit_json(
1407 changed=(
1408 changed
1409 or change_export
1410 or change_share
1411 or change_ca
1412 or change_go
1413 or change_sc
1414 or change_client
1415 or change_rules
1416 )
1417 )
1420def _delete_fs(module, blade):
1421 """In module Delete Filesystem"""
1422 # Determine if this is a realm filesystem
1423 realm_name = None
1424 if module.params.get("realm"):
1425 realm_name = module.params["realm"]
1426 elif "::" in module.params["name"]:
1427 realm_name = module.params["name"].split("::")[0]
1428 # Construct filesystem name - if realm provided, prepend realm::
1429 fs_name = module.params["name"]
1430 if realm_name and "::" not in fs_name:
1431 fs_name = "{0}::{1}".format(realm_name, fs_name)
1432 res = blade.patch_file_systems(
1433 names=[fs_name],
1434 file_system=FileSystemPatch(
1435 nfs=NfsPatch(v3_enabled=False, v4_1_enabled=False),
1436 smb=Smb(enabled=False),
1437 http=Http(enabled=False),
1438 multi_protocol=MultiProtocol(access_control_style="shared"),
1439 destroyed=True,
1440 ),
1441 )
1442 if res.status_code != 200:
1443 module.fail_json(
1444 msg="Failed to delete filesystem {0}. Error: {1}".format(
1445 fs_name, get_error_message(res)
1446 )
1447 )
1449 res = blade.delete_file_systems(names=[fs_name])
1450 if res.status_code != 200:
1451 module.fail_json(
1452 msg="Failed to eradicate deleted filesystem {0}. Error: {1}".format(
1453 fs_name, get_error_message(res)
1454 )
1455 )
1458def delete_fs(module, blade):
1459 """Delete Filesystem"""
1460 # Determine if this is a realm filesystem
1461 realm_name = None
1462 if module.params.get("realm"):
1463 realm_name = module.params["realm"]
1464 elif "::" in module.params["name"]:
1465 realm_name = module.params["name"].split("::")[0]
1466 # Construct filesystem name - if realm provided, prepend realm::
1467 fs_name = module.params["name"]
1468 if realm_name and "::" not in fs_name:
1469 fs_name = "{0}::{1}".format(realm_name, fs_name)
1470 changed = True
1471 if not module.check_mode:
1472 res = blade.patch_file_systems(
1473 names=[fs_name],
1474 file_system=FileSystemPatch(
1475 nfs=NfsPatch(v3_enabled=False, v4_1_enabled=False),
1476 smb=Smb(enabled=False),
1477 http=Http(enabled=False),
1478 destroyed=True,
1479 ),
1480 delete_link_on_eradication=module.params["delete_link"],
1481 )
1482 if res.status_code != 200:
1483 module.fail_json(
1484 msg="Failed to delete filesystem {0}. Error: {1}".format(
1485 fs_name, get_error_message(res)
1486 )
1487 )
1488 if module.params["eradicate"]:
1489 res = blade.delete_file_systems(names=[fs_name])
1490 if res.status_code != 200:
1491 module.fail_json(
1492 msg="Failed to eradicate filesystem {0}. Error: {1}".format(
1493 fs_name, get_error_message(res)
1494 )
1495 )
1496 module.exit_json(changed=changed)
1499def eradicate_fs(module, blade):
1500 """Eradicate Filesystem"""
1501 # Determine if this is a realm filesystem
1502 realm_name = None
1503 if module.params.get("realm"):
1504 realm_name = module.params["realm"]
1505 elif "::" in module.params["name"]:
1506 realm_name = module.params["name"].split("::")[0]
1507 # Construct filesystem name - if realm provided, prepend realm::
1508 fs_name = module.params["name"]
1509 if realm_name and "::" not in fs_name:
1510 fs_name = "{0}::{1}".format(realm_name, fs_name)
1511 changed = True
1512 if not module.check_mode:
1513 res = blade.delete_file_systems(names=[fs_name])
1514 if res.status_code != 200:
1515 module.fail_json(
1516 msg="Failed to eradicate filesystem {0}. Error: {1}".format(
1517 fs_name, get_error_message(res)
1518 )
1519 )
1520 module.exit_json(changed=changed)
1523def main():
1524 argument_spec = purefb_argument_spec()
1525 argument_spec.update(
1526 dict(
1527 name=dict(type="str", required=True),
1528 eradicate=dict(default="false", type="bool"),
1529 nfsv3=dict(default="true", type="bool"),
1530 nfsv4=dict(default="true", type="bool"),
1531 nfs_rules=dict(type="str"),
1532 smb=dict(type="bool"),
1533 http=dict(type="bool"),
1534 snapshot=dict(type="bool"),
1535 writable=dict(type="bool"),
1536 promote=dict(type="bool"),
1537 fastremove=dict(type="bool"),
1538 hard_limit=dict(type="bool"),
1539 user_quota=dict(type="str"),
1540 policy=dict(type="str"),
1541 group_quota=dict(type="str"),
1542 smb_aclmode=dict(
1543 type="str", default="shared", choices=["shared", "native"]
1544 ),
1545 group_ownership=dict(
1546 choices=["creator", "parent-directory"], default="creator"
1547 ),
1548 policy_state=dict(default="present", choices=["present", "absent"]),
1549 state=dict(default="present", choices=["present", "absent"]),
1550 delete_link=dict(default=False, type="bool"),
1551 discard_snaps=dict(default=False, type="bool"),
1552 safeguard_acls=dict(type="bool"),
1553 access_control=dict(
1554 type="str",
1555 default="shared",
1556 choices=["nfs", "smb", "shared", "independent", "mode-bits"],
1557 ),
1558 size=dict(type="str"),
1559 export_policy=dict(type="str"),
1560 share_policy=dict(type="str"),
1561 client_policy=dict(type="str"),
1562 continuous_availability=dict(type="bool", default="true"),
1563 ignore_usage=dict(type="bool", default=False),
1564 cancel_in_progress=dict(type="bool", default=False),
1565 context=dict(type="str", default=""),
1566 storage_class=dict(type="str"),
1567 realm=dict(type="str"),
1568 )
1569 )
1571 module = AnsibleModule(argument_spec, supports_check_mode=True)
1573 state = module.params["state"]
1574 blade = get_system(module)
1575 api_version = get_rest_api_version(blade)
1576 if (
1577 LooseVersion(CONTEXT_API_VERSION) <= LooseVersion(api_version)
1578 and not module.params["context"]
1579 ):
1580 # Only default the context to the local array name when this array is a
1581 # member of a fleet. A standalone array is "not in a fleet" and rejects
1582 # fleet context, so leave context unset - no context_names is then sent.
1583 fleet_res = blade.get_fleets()
1584 if fleet_res.status_code == 200 and list(fleet_res.items):
1585 module.params["context"] = list(blade.get_arrays().items)[0].name
1587 # Check if filesystem exists
1588 # If realm is provided and filesystem name doesn't include realm prefix,
1589 # also check for realm::filesystem format
1590 fsys = get_filesystem(module, blade)
1591 if not fsys and module.params.get("realm") and "::" not in module.params["name"]:
1592 # Try looking for realm::filesystem format
1593 original_name = module.params["name"]
1594 qualified_name = "{0}::{1}".format(module.params["realm"], original_name)
1595 module.params["name"] = qualified_name
1596 fsys = get_filesystem(module, blade)
1597 # If not found with qualified name, restore original name for creation
1598 if not fsys:
1599 module.params["name"] = original_name
1601 if module.params["eradicate"] and state == "present":
1602 module.warn("Eradicate flag ignored without state=absent")
1604 if module.params["smb_aclmode"] == "native":
1605 module.fail_json(
1606 msg="Native SMB ACL mode is no longer supported. "
1607 "Use the access_control parameter."
1608 )
1609 if state == "present" and not fsys:
1610 create_fs(module, blade)
1611 elif state == "present" and fsys:
1612 modify_fs(module, blade)
1613 elif state == "absent" and fsys and not fsys.destroyed:
1614 delete_fs(module, blade)
1615 elif state == "absent" and fsys and fsys.destroyed and module.params["eradicate"]:
1616 eradicate_fs(module, blade)
1617 elif state == "absent" and not fsys:
1618 module.exit_json(changed=False)
1619 module.exit_json(changed=False)
1622if __name__ == "__main__":
1623 main()