Skip to content

Commit 5ed3a98

Browse files
authored
Merge pull request ceph#65069 from phlogistonjohn/jjm-fix-ports-remotectl
smb: fix custom ports feature with remote-control sidecar Reviewed-by: Adam King <[email protected]> Reviewed-by: Anoop C S <[email protected]> Reviewed-by: Avan Thakkar <[email protected]>
2 parents 37bd93e + 98d4853 commit 5ed3a98

File tree

6 files changed

+107
-26
lines changed

6 files changed

+107
-26
lines changed

src/cephadm/cephadmlib/daemons/smb.py

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
Tuple,
1818
)
1919

20+
import ceph.smb.constants
21+
2022
from .. import context_getters
2123
from .. import daemon_form
2224
from .. import data_utils
@@ -104,20 +106,35 @@ def conf_interface(self) -> str:
104106

105107

106108
class Ports(enum.Enum):
107-
SMB = 445
108-
SMBMETRICS = 9922
109-
CTDB = 4379
110-
REMOTE_CONTROL = 54445
109+
SMB = ceph.smb.constants.SMB_PORT
110+
SMBMETRICS = ceph.smb.constants.SMBMETRICS_PORT
111+
CTDB = ceph.smb.constants.CTDB_PORT
112+
REMOTE_CONTROL = ceph.smb.constants.REMOTE_CONTROL_PORT
111113

112114
def customized(self, service_ports: Dict[str, int]) -> int:
113115
"""Return a custom port value if it is present in service_ports or the
114116
default port value if it is not present.
115117
"""
116-
port = service_ports.get(self.name.lower())
118+
port = service_ports.get(str(self))
117119
if port:
118120
return int(port)
119121
return int(self.value)
120122

123+
def __str__(self) -> str:
124+
# NOTE: mypy is getting the key type below wrong. using reveal_type:
125+
# >>> reveal_type(self.SMB)
126+
# > note: Revealed type is "builtins.int"
127+
# >>> reveal_type(self)
128+
# > note: Revealed type is "cephadmlib.daemons.smb.Ports"
129+
# maybe newer versions would not hit this issue?
130+
names: Dict[Any, str] = {
131+
self.SMB: ceph.smb.constants.SMB,
132+
self.SMBMETRICS: ceph.smb.constants.SMBMETRICS,
133+
self.CTDB: ceph.smb.constants.CTDB,
134+
self.REMOTE_CONTROL: ceph.smb.constants.REMOTE_CONTROL,
135+
}
136+
return names[self]
137+
121138

122139
@dataclasses.dataclass(frozen=True)
123140
class TLSFiles:

src/pybind/mgr/smb/tests/test_validation.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,17 @@ def test_check_access_name(value, ok, err_match):
144144
({'smb': 4455, 'sbmetrics': 9009}, 'invalid service names'),
145145
(
146146
{'smb': 4455, 'smbmetrics': 9999, 'ctdb': 9999},
147-
'must not be repeated',
147+
'must be unique',
148148
),
149+
# can't use 445 it's the default smb port!
150+
(
151+
{'smbmetrics': 445},
152+
'must be unique',
153+
),
154+
# its valid to swap stuff around (don't do this please)
155+
({'smbmetrics': 4379, 'ctdb': 9922}, None),
156+
# remote-control is a valid service name to modify
157+
({'remote-control': 65432}, None),
149158
],
150159
)
151160
def test_check_custom_ports(value, err_match):

src/pybind/mgr/smb/validation.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import posixpath
44
import re
55

6+
import ceph.smb.constants
7+
68
# Initially, this regex is pretty restrictive. But I (JJM) find that
79
# starting out more restricitive is better than not because it's generally
810
# easier to relax strict rules then discover someone relies on lax rules
@@ -114,14 +116,14 @@ def check_access_name(name: str) -> None:
114116
raise ValueError('login name may not exceed 128 characters')
115117

116118

117-
PORT_SERVICES = {"smb", "ctdb", "smbmetrics"}
118119
_MAX_PORT = (1 << 16) - 1
119120

120121

121122
def check_custom_ports(ports: Optional[Dict[str, int]]) -> None:
122123
if ports is None:
123124
return
124-
other = set(ports) - PORT_SERVICES
125+
_defaults = ceph.smb.constants.DEFAULT_PORTS
126+
other = set(ports) - set(_defaults)
125127
if other:
126128
raise ValueError(
127129
"invalid service names for custom ports:"
@@ -132,5 +134,12 @@ def check_custom_ports(ports: Optional[Dict[str, int]]) -> None:
132134
raise ValueError(
133135
f'invalid port number(s): {", ".join(sorted(invalid))}'
134136
)
135-
if len(ports) != len(set(ports.values())):
136-
raise ValueError('port numbers must not be repeated')
137+
# make sure ports are unique per service
138+
all_ports = _defaults | ports
139+
for port in all_ports.values():
140+
using_port = {s for s, p in all_ports.items() if p == port}
141+
if len(using_port) > 1:
142+
raise ValueError(
143+
'port numbers must be unique:'
144+
f' {port} used for {", ".join(sorted(using_port))}'
145+
)

src/python-common/ceph/deployment/service_spec.py

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
from ceph.deployment.utils import verify_positive_int, verify_non_negative_number
3636
from ceph.deployment.utils import verify_boolean, verify_enum
3737
from ceph.utils import is_hex
38+
from ceph.smb import constants as smbconst
3839

3940
ServiceSpecT = TypeVar('ServiceSpecT', bound='ServiceSpec')
4041
FuncT = TypeVar('FuncT', bound=Callable)
@@ -3315,8 +3316,8 @@ def convert_list(
33153316

33163317
class SMBSpec(ServiceSpec):
33173318
service_type = 'smb'
3318-
_valid_features = {'domain', 'clustered', 'cephfs-proxy', 'remote-control'}
3319-
_valid_service_names = {'smb', 'smbmetrics', 'ctdb', 'remote-control'}
3319+
_valid_features = smbconst.FEATURES
3320+
_valid_service_names = smbconst.SERVICES
33203321
_default_cluster_meta_obj = 'cluster.meta.json'
33213322
_default_cluster_lock_obj = 'cluster.meta.lock'
33223323

@@ -3430,23 +3431,24 @@ def validate(self) -> None:
34303431
raise ValueError(
34313432
f'invalid feature flags: {", ".join(invalid)}'
34323433
)
3433-
if 'clustered' in self.features and not self.cluster_meta_uri:
3434+
_clustered = smbconst.CLUSTERED
3435+
if _clustered in self.features and not self.cluster_meta_uri:
34343436
# derive a cluster meta uri from config uri by default (if possible)
34353437
self.cluster_meta_uri = self._derive_cluster_uri(
34363438
self.config_uri,
34373439
self._default_cluster_meta_obj,
34383440
)
3439-
if 'clustered' not in self.features and self.cluster_meta_uri:
3441+
if _clustered not in self.features and self.cluster_meta_uri:
34403442
raise ValueError(
34413443
'cluster meta uri unsupported when "clustered" feature not set'
34423444
)
3443-
if 'clustered' in self.features and not self.cluster_lock_uri:
3445+
if _clustered in self.features and not self.cluster_lock_uri:
34443446
# derive a cluster meta uri from config uri by default (if possible)
34453447
self.cluster_lock_uri = self._derive_cluster_uri(
34463448
self.config_uri,
34473449
self._default_cluster_lock_obj,
34483450
)
3449-
if 'clustered' not in self.features and self.cluster_lock_uri:
3451+
if _clustered not in self.features and self.cluster_lock_uri:
34503452
raise ValueError(
34513453
'cluster lock uri unsupported when "clustered" feature not set'
34523454
)
@@ -3465,12 +3467,7 @@ def _derive_cluster_uri(self, uri: str, objname: str) -> str:
34653467
return uri
34663468

34673469
def _default_ports(self) -> Dict[str, int]:
3468-
return {
3469-
'smb': 445,
3470-
'smbmetrics': 9922,
3471-
'ctdb': 4379,
3472-
'remote-control': 54445,
3473-
}
3470+
return dict(smbconst.DEFAULT_PORTS)
34743471

34753472
def service_ports(self) -> Dict[str, int]:
34763473
ports = self._default_ports()
@@ -3479,13 +3476,13 @@ def service_ports(self) -> Dict[str, int]:
34793476
return ports
34803477

34813478
def metrics_exporter_port(self) -> int:
3482-
return self.service_ports()['smbmetrics']
3479+
return self.service_ports()[smbconst.SMBMETRICS]
34833480

34843481
def get_port_start(self) -> List[int]:
34853482
_ports = self.service_ports()
3486-
ports = [_ports['smb'], _ports['smbmetrics']]
3487-
if 'clustered' in self.features:
3488-
ports.append(_ports['ctdb'])
3483+
ports = [_ports[smbconst.SMB], _ports[smbconst.SMBMETRICS]]
3484+
if smbconst.CLUSTERED in self.features:
3485+
ports.append(_ports[smbconst.CTDB])
34893486
return ports
34903487

34913488
def strict_cluster_ip_specs(self) -> List[Dict[str, Any]]:

src/python-common/ceph/smb/__init__.py

Whitespace-only changes.
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Shared constant values that apply across all ceph components that manage
2+
# smb services (mgr module, cephadm mgr module, cephadm binary, etc)
3+
4+
5+
# Generic/common names
6+
SMB = 'smb'
7+
CTDB = 'ctdb'
8+
9+
10+
# Feature names
11+
CEPHFS_PROXY = 'cephfs-proxy'
12+
CLUSTERED = 'clustered'
13+
DOMAIN = 'domain'
14+
REMOTE_CONTROL = 'remote-control'
15+
SMBMETRICS = 'smbmetrics'
16+
17+
18+
# Features are optional components that can be deployed in a suite of smb
19+
# related containers. It may run as a separate sidecar or side-effect the
20+
# configuration of another component.
21+
FEATURES = {
22+
CEPHFS_PROXY,
23+
CLUSTERED,
24+
DOMAIN,
25+
REMOTE_CONTROL,
26+
}
27+
28+
# Services are components that listen on a "public" network port, to expose
29+
# network services to remote clients.
30+
SERVICES = {
31+
CTDB,
32+
REMOTE_CONTROL,
33+
SMB,
34+
SMBMETRICS,
35+
}
36+
37+
38+
# Default port values
39+
SMB_PORT = 445
40+
SMBMETRICS_PORT = 9922
41+
CTDB_PORT = 4379
42+
REMOTE_CONTROL_PORT = 54445
43+
44+
DEFAULT_PORTS = {
45+
SMB: SMB_PORT,
46+
SMBMETRICS: SMBMETRICS_PORT,
47+
CTDB: CTDB_PORT,
48+
REMOTE_CONTROL: REMOTE_CONTROL_PORT,
49+
}

0 commit comments

Comments
 (0)