Skip to content

Commit 944d412

Browse files
authored
Merge pull request ceph#60281 from phlogistonjohn/jjm-change-cluster-validate
smb: prevent switching between clustering modes Reviewed-by: Adam King <[email protected]> Reviewed-by: Avan Thakkar <[email protected]>
2 parents 9190d05 + da89acd commit 944d412

File tree

2 files changed

+74
-55
lines changed

2 files changed

+74
-55
lines changed

src/pybind/mgr/smb/handler.py

Lines changed: 73 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
JoinSourceType,
3030
LoginAccess,
3131
LoginCategory,
32+
SMBClustering,
3233
State,
3334
UserGroupSourceType,
3435
)
@@ -788,24 +789,33 @@ def _keyfunc(r: SMBResource) -> int:
788789

789790
def _check_cluster(cluster: ClusterRef, staging: _Staging) -> None:
790791
"""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:
807815
assert isinstance(cluster, resources.Cluster)
808816
cluster.validate()
817+
if not staging.is_new(cluster):
818+
_check_cluster_modifications(cluster, staging)
809819
for auth_ref in _auth_refs(cluster):
810820
auth = staging.get_join_auth(auth_ref)
811821
if (
@@ -834,6 +844,53 @@ def _check_cluster(cluster: ClusterRef, staging: _Staging) -> None:
834844
)
835845

836846

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+
837894
def _parse_earmark(earmark: str) -> dict:
838895
parts = earmark.split('.')
839896

src/pybind/mgr/smb/internal.py

Lines changed: 1 addition & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from typing import Collection, Tuple, Type, TypeVar
55

66
from . import resources
7-
from .enums import AuthMode, ConfigNS, State
7+
from .enums import ConfigNS, State
88
from .proto import (
99
ConfigEntry,
1010
ConfigStore,
@@ -14,7 +14,6 @@
1414
Simplifiable,
1515
)
1616
from .resources import SMBResource
17-
from .results import ErrorResult
1817
from .utils import one
1918

2019
T = TypeVar('T')
@@ -108,43 +107,6 @@ def ids(cls, store: ConfigStoreListing) -> Collection[str]:
108107
def get_cluster(self) -> resources.Cluster:
109108
return self.get_resource_type(resources.Cluster)
110109

111-
def create_or_update(self, resource: Simplifiable) -> State:
112-
assert isinstance(resource, resources.Cluster)
113-
try:
114-
previous = self.config_entry.get()
115-
except KeyError:
116-
previous = None
117-
current = resource.to_simplified()
118-
if current == previous:
119-
return State.PRESENT
120-
elif previous is None:
121-
self.config_entry.set(current)
122-
return State.CREATED
123-
# cluster is special in that is has some fields that we do not
124-
# permit changing.
125-
prev = getattr(
126-
resources.Cluster, '_resource_config'
127-
).object_from_simplified(previous)
128-
if resource.auth_mode != prev.auth_mode:
129-
raise ErrorResult(
130-
resource,
131-
'auth_mode value may not be changed',
132-
status={'existing_auth_mode': prev.auth_mode},
133-
)
134-
if resource.auth_mode == AuthMode.ACTIVE_DIRECTORY:
135-
assert resource.domain_settings
136-
assert prev.domain_settings
137-
if resource.domain_settings.realm != prev.domain_settings.realm:
138-
raise ErrorResult(
139-
resource,
140-
'domain/realm value may not be changed',
141-
status={
142-
'existing_domain_realm': prev.domain_settings.realm
143-
},
144-
)
145-
self.config_entry.set(current)
146-
return State.UPDATED
147-
148110

149111
class ShareEntry(ResourceEntry):
150112
"""Share resource getter/setter for the smb internal data store(s)."""

0 commit comments

Comments
 (0)