|
29 | 29 | JoinSourceType, |
30 | 30 | LoginAccess, |
31 | 31 | LoginCategory, |
| 32 | + SMBClustering, |
32 | 33 | State, |
33 | 34 | UserGroupSourceType, |
34 | 35 | ) |
@@ -788,24 +789,33 @@ def _keyfunc(r: SMBResource) -> int: |
788 | 789 |
|
789 | 790 | def _check_cluster(cluster: ClusterRef, staging: _Staging) -> None: |
790 | 791 | """Check that the cluster resource can be updated.""" |
791 | | - if cluster.intent == Intent.REMOVED: |
792 | | - share_ids = ShareEntry.ids(staging) |
793 | | - clusters_used = {cid for cid, _ in share_ids} |
794 | | - if cluster.cluster_id in clusters_used: |
795 | | - raise ErrorResult( |
796 | | - cluster, |
797 | | - msg="cluster in use by shares", |
798 | | - status={ |
799 | | - 'shares': [ |
800 | | - shid |
801 | | - for cid, shid in share_ids |
802 | | - if cid == cluster.cluster_id |
803 | | - ] |
804 | | - }, |
805 | | - ) |
806 | | - return |
| 792 | + if cluster.intent == Intent.PRESENT: |
| 793 | + return _check_cluster_present(cluster, staging) |
| 794 | + return _check_cluster_removed(cluster, staging) |
| 795 | + |
| 796 | + |
| 797 | +def _check_cluster_removed(cluster: ClusterRef, staging: _Staging) -> None: |
| 798 | + share_ids = ShareEntry.ids(staging) |
| 799 | + clusters_used = {cid for cid, _ in share_ids} |
| 800 | + if cluster.cluster_id in clusters_used: |
| 801 | + raise ErrorResult( |
| 802 | + cluster, |
| 803 | + msg="cluster in use by shares", |
| 804 | + status={ |
| 805 | + 'shares': [ |
| 806 | + shid |
| 807 | + for cid, shid in share_ids |
| 808 | + if cid == cluster.cluster_id |
| 809 | + ] |
| 810 | + }, |
| 811 | + ) |
| 812 | + |
| 813 | + |
| 814 | +def _check_cluster_present(cluster: ClusterRef, staging: _Staging) -> None: |
807 | 815 | assert isinstance(cluster, resources.Cluster) |
808 | 816 | cluster.validate() |
| 817 | + if not staging.is_new(cluster): |
| 818 | + _check_cluster_modifications(cluster, staging) |
809 | 819 | for auth_ref in _auth_refs(cluster): |
810 | 820 | auth = staging.get_join_auth(auth_ref) |
811 | 821 | if ( |
@@ -834,6 +844,53 @@ def _check_cluster(cluster: ClusterRef, staging: _Staging) -> None: |
834 | 844 | ) |
835 | 845 |
|
836 | 846 |
|
| 847 | +def _check_cluster_modifications( |
| 848 | + cluster: resources.Cluster, staging: _Staging |
| 849 | +) -> None: |
| 850 | + """cluster has some fields we do not permit changing after the cluster has |
| 851 | + been created. |
| 852 | + """ |
| 853 | + prev = ClusterEntry.from_store( |
| 854 | + staging.destination_store, cluster.cluster_id |
| 855 | + ).get_cluster() |
| 856 | + if cluster.auth_mode != prev.auth_mode: |
| 857 | + raise ErrorResult( |
| 858 | + cluster, |
| 859 | + 'auth_mode value may not be changed', |
| 860 | + status={'existing_auth_mode': prev.auth_mode}, |
| 861 | + ) |
| 862 | + if cluster.auth_mode == AuthMode.ACTIVE_DIRECTORY: |
| 863 | + assert prev.domain_settings |
| 864 | + if not cluster.domain_settings: |
| 865 | + # should not occur |
| 866 | + raise ErrorResult(cluster, "domain settings missing from cluster") |
| 867 | + if cluster.domain_settings.realm != prev.domain_settings.realm: |
| 868 | + raise ErrorResult( |
| 869 | + cluster, |
| 870 | + 'domain/realm value may not be changed', |
| 871 | + status={'existing_domain_realm': prev.domain_settings.realm}, |
| 872 | + ) |
| 873 | + if cluster.is_clustered() != prev.is_clustered(): |
| 874 | + prev_clustering = prev.is_clustered() |
| 875 | + cterms = {True: 'enabled', False: 'disabled'} |
| 876 | + msg = ( |
| 877 | + f'a cluster resource with clustering {cterms[prev_clustering]}' |
| 878 | + f' may not be changed to clustering {cterms[not prev_clustering]}' |
| 879 | + ) |
| 880 | + opt_terms = { |
| 881 | + True: SMBClustering.ALWAYS.value, |
| 882 | + False: SMBClustering.NEVER.value, |
| 883 | + } |
| 884 | + hint = { |
| 885 | + 'note': ( |
| 886 | + 'Set "clustering" to an explicit value that matches the' |
| 887 | + ' current clustering behavior' |
| 888 | + ), |
| 889 | + 'value': opt_terms[prev_clustering], |
| 890 | + } |
| 891 | + raise ErrorResult(cluster, msg, status={'hint': hint}) |
| 892 | + |
| 893 | + |
837 | 894 | def _parse_earmark(earmark: str) -> dict: |
838 | 895 | parts = earmark.split('.') |
839 | 896 |
|
|
0 commit comments