Skip to content

Commit 2c2af3b

Browse files
authored
Merge pull request ceph#61579 from phlogistonjohn/jjm-cephadm-small-moves
cephadm: move three functions out of cephadm.py Reviewed-by: Adam King <[email protected]>
2 parents 09f5779 + 9bb0de4 commit 2c2af3b

File tree

6 files changed

+226
-118
lines changed

6 files changed

+226
-118
lines changed

src/cephadm/cephadm.py

Lines changed: 6 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -88,17 +88,18 @@
8888
Podman,
8989
check_container_engine,
9090
find_container_engine,
91+
parsed_container_mem_usage,
92+
parsed_container_cpu_perc,
9193
pull_command,
9294
registry_login,
9395
)
9496
from cephadmlib.data_utils import (
9597
dict_get_join,
96-
get_legacy_config_fsid,
98+
get_legacy_daemon_fsid,
9799
is_fsid,
98100
normalize_image_digest,
99101
try_convert_datetime,
100102
read_config,
101-
with_units_to_int,
102103
_extract_host_info_from_applied_spec,
103104
)
104105
from cephadmlib.file_utils import (
@@ -738,27 +739,6 @@ def lookup_unit_name_by_daemon_name(ctx: CephadmContext, fsid: str, name: str) -
738739
raise Error('Failed to get unit name for {}'.format(daemon))
739740

740741

741-
def get_legacy_daemon_fsid(ctx, cluster,
742-
daemon_type, daemon_id, legacy_dir=None):
743-
# type: (CephadmContext, str, str, Union[int, str], Optional[str]) -> Optional[str]
744-
fsid = None
745-
if daemon_type == 'osd':
746-
try:
747-
fsid_file = os.path.join(ctx.data_dir,
748-
daemon_type,
749-
'ceph-%s' % daemon_id,
750-
'ceph_fsid')
751-
if legacy_dir is not None:
752-
fsid_file = os.path.abspath(legacy_dir + fsid_file)
753-
with open(fsid_file, 'r') as f:
754-
fsid = f.read().strip()
755-
except IOError:
756-
pass
757-
if not fsid:
758-
fsid = get_legacy_config_fsid(cluster, legacy_dir=legacy_dir)
759-
return fsid
760-
761-
762742
def create_daemon_dirs(
763743
ctx: CephadmContext,
764744
ident: 'DaemonIdentity',
@@ -1653,13 +1633,7 @@ def _daemon_ls_subset(self) -> Dict[str, Dict[str, Any]]:
16531633
# not changed for any daemon, we assume our cached info is good.
16541634
daemons: Dict[str, Dict[str, Any]] = {}
16551635
data_dir = self.ctx.data_dir
1656-
seen_memusage = {} # type: Dict[str, int]
1657-
out, err, code = call(
1658-
self.ctx,
1659-
[self.ctx.container_engine.path, 'stats', '--format', '{{.ID}},{{.MemUsage}}', '--no-stream'],
1660-
verbosity=CallVerbosity.DEBUG
1661-
)
1662-
seen_memusage_cid_len, seen_memusage = _parse_mem_usage(code, out)
1636+
seen_memusage_cid_len, seen_memusage = parsed_container_mem_usage(self.ctx)
16631637
# we need a mapping from container names to ids. Later we will convert daemon
16641638
# names to container names to get daemons container id to see if it has changed
16651639
out, err, code = call(
@@ -3471,21 +3445,8 @@ def list_daemons(
34713445
seen_digests = {} # type: Dict[str, List[str]]
34723446

34733447
# keep track of memory and cpu usage we've seen
3474-
seen_memusage = {} # type: Dict[str, int]
3475-
seen_cpuperc = {} # type: Dict[str, str]
3476-
out, err, code = call(
3477-
ctx,
3478-
[container_path, 'stats', '--format', '{{.ID}},{{.MemUsage}}', '--no-stream'],
3479-
verbosity=CallVerbosity.QUIET
3480-
)
3481-
seen_memusage_cid_len, seen_memusage = _parse_mem_usage(code, out)
3482-
3483-
out, err, code = call(
3484-
ctx,
3485-
[container_path, 'stats', '--format', '{{.ID}},{{.CPUPerc}}', '--no-stream'],
3486-
verbosity=CallVerbosity.QUIET
3487-
)
3488-
seen_cpuperc_cid_len, seen_cpuperc = _parse_cpu_perc(code, out)
3448+
seen_memusage_cid_len, seen_memusage = parsed_container_mem_usage(ctx)
3449+
seen_cpuperc_cid_len, seen_cpuperc = parsed_container_cpu_perc(ctx)
34893450

34903451
# /var/lib/ceph
34913452
if os.path.exists(data_dir):
@@ -3688,40 +3649,6 @@ def list_daemons(
36883649
return ls
36893650

36903651

3691-
def _parse_mem_usage(code: int, out: str) -> Tuple[int, Dict[str, int]]:
3692-
# keep track of memory usage we've seen
3693-
seen_memusage = {} # type: Dict[str, int]
3694-
seen_memusage_cid_len = 0
3695-
if not code:
3696-
for line in out.splitlines():
3697-
(cid, usage) = line.split(',')
3698-
(used, limit) = usage.split(' / ')
3699-
try:
3700-
seen_memusage[cid] = with_units_to_int(used)
3701-
if not seen_memusage_cid_len:
3702-
seen_memusage_cid_len = len(cid)
3703-
except ValueError:
3704-
logger.info('unable to parse memory usage line\n>{}'.format(line))
3705-
pass
3706-
return seen_memusage_cid_len, seen_memusage
3707-
3708-
3709-
def _parse_cpu_perc(code: int, out: str) -> Tuple[int, Dict[str, str]]:
3710-
seen_cpuperc = {}
3711-
seen_cpuperc_cid_len = 0
3712-
if not code:
3713-
for line in out.splitlines():
3714-
(cid, cpuperc) = line.split(',')
3715-
try:
3716-
seen_cpuperc[cid] = cpuperc
3717-
if not seen_cpuperc_cid_len:
3718-
seen_cpuperc_cid_len = len(cid)
3719-
except ValueError:
3720-
logger.info('unable to parse cpu percentage line\n>{}'.format(line))
3721-
pass
3722-
return seen_cpuperc_cid_len, seen_cpuperc
3723-
3724-
37253652
def get_daemon_description(ctx, fsid, name, detail=False, legacy_dir=None):
37263653
# type: (CephadmContext, str, str, bool, Optional[str]) -> Dict[str, str]
37273654

src/cephadm/cephadmlib/container_engines.py

Lines changed: 114 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
# container_engines.py - container engine types and selection funcs
22

33
import os
4+
import logging
45

56
from typing import Tuple, List, Optional, Dict
67

7-
from .call_wrappers import call_throws, CallVerbosity
8+
from .call_wrappers import call_throws, call, CallVerbosity
89
from .context import CephadmContext
910
from .container_engine_base import ContainerEngine
1011
from .constants import (
@@ -13,9 +14,13 @@
1314
MIN_PODMAN_VERSION,
1415
PIDS_LIMIT_UNLIMITED_PODMAN_VERSION,
1516
)
17+
from .data_utils import with_units_to_int
1618
from .exceptions import Error
1719

1820

21+
logger = logging.getLogger()
22+
23+
1924
class Podman(ContainerEngine):
2025
EXE = 'podman'
2126

@@ -189,3 +194,111 @@ def pull_command(
189194
if os.path.exists('/etc/ceph/podman-auth.json'):
190195
cmd.append('--authfile=/etc/ceph/podman-auth.json')
191196
return cmd
197+
198+
199+
def _container_mem_usage(
200+
ctx: CephadmContext,
201+
*,
202+
container_path: str = '',
203+
verbosity: CallVerbosity = CallVerbosity.QUIET,
204+
) -> Tuple[str, str, int]:
205+
container_path = container_path or ctx.container_engine.path
206+
out, err, code = call(
207+
ctx,
208+
[
209+
container_path,
210+
'stats',
211+
'--format',
212+
'{{.ID}},{{.MemUsage}}',
213+
'--no-stream',
214+
],
215+
verbosity=verbosity,
216+
)
217+
return out, err, code
218+
219+
220+
def _parse_mem_usage(code: int, out: str) -> Tuple[int, Dict[str, int]]:
221+
# keep track of memory usage we've seen
222+
seen_memusage = {} # type: Dict[str, int]
223+
seen_memusage_cid_len = 0
224+
if not code:
225+
for line in out.splitlines():
226+
(cid, usage) = line.split(',')
227+
(used, limit) = usage.split(' / ')
228+
try:
229+
seen_memusage[cid] = with_units_to_int(used)
230+
if not seen_memusage_cid_len:
231+
seen_memusage_cid_len = len(cid)
232+
except ValueError:
233+
logger.info(
234+
'unable to parse memory usage line\n>{}'.format(line)
235+
)
236+
pass
237+
return seen_memusage_cid_len, seen_memusage
238+
239+
240+
def parsed_container_mem_usage(
241+
ctx: CephadmContext,
242+
*,
243+
container_path: str = '',
244+
verbosity: CallVerbosity = CallVerbosity.QUIET,
245+
) -> Tuple[int, Dict[str, int]]:
246+
"""Return memory useage values parsed from the container engine's container status."""
247+
out, _, code = _container_mem_usage(
248+
ctx, container_path=container_path, verbosity=verbosity
249+
)
250+
return _parse_mem_usage(code, out)
251+
252+
253+
def _container_cpu_perc(
254+
ctx: CephadmContext,
255+
*,
256+
container_path: str = '',
257+
verbosity: CallVerbosity = CallVerbosity.QUIET,
258+
) -> Tuple[str, str, int]:
259+
container_path = container_path or ctx.container_engine.path
260+
out, err, code = call(
261+
ctx,
262+
[
263+
container_path,
264+
'stats',
265+
'--format',
266+
'{{.ID}},{{.CPUPerc}}',
267+
'--no-stream',
268+
],
269+
verbosity=CallVerbosity.QUIET,
270+
)
271+
return out, err, code
272+
273+
274+
def _parse_cpu_perc(code: int, out: str) -> Tuple[int, Dict[str, str]]:
275+
seen_cpuperc = {}
276+
seen_cpuperc_cid_len = 0
277+
if not code:
278+
for line in out.splitlines():
279+
(cid, cpuperc) = line.split(',')
280+
try:
281+
seen_cpuperc[cid] = cpuperc
282+
if not seen_cpuperc_cid_len:
283+
seen_cpuperc_cid_len = len(cid)
284+
except ValueError:
285+
logger.info(
286+
'unable to parse cpu percentage line\n>{}'.format(line)
287+
)
288+
pass
289+
return seen_cpuperc_cid_len, seen_cpuperc
290+
291+
292+
def parsed_container_cpu_perc(
293+
ctx: CephadmContext,
294+
*,
295+
container_path: str = '',
296+
verbosity: CallVerbosity = CallVerbosity.QUIET,
297+
) -> Tuple[int, Dict[str, str]]:
298+
"""Return cpu percentage used values parsed from the container engine's
299+
container status.
300+
"""
301+
out, _, code = _container_cpu_perc(
302+
ctx, container_path=container_path, verbosity=verbosity
303+
)
304+
return _parse_cpu_perc(code, out)

src/cephadm/cephadmlib/data_utils.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@
99

1010
from configparser import ConfigParser
1111

12-
from typing import Dict, Any, Optional, Iterable, List
12+
from typing import Dict, Any, Optional, Iterable, List, Union
1313

1414
from .constants import DATEFMT, DEFAULT_REGISTRY
15+
from .context import CephadmContext
1516
from .exceptions import Error
1617

1718

@@ -205,6 +206,30 @@ def get_legacy_config_fsid(
205206
return None
206207

207208

209+
def get_legacy_daemon_fsid(
210+
ctx: CephadmContext,
211+
cluster: str,
212+
daemon_type: str,
213+
daemon_id: Union[int, str],
214+
legacy_dir: Optional[str] = None,
215+
) -> Optional[str]:
216+
fsid = None
217+
if daemon_type == 'osd':
218+
try:
219+
fsid_file = os.path.join(
220+
ctx.data_dir, daemon_type, 'ceph-%s' % daemon_id, 'ceph_fsid'
221+
)
222+
if legacy_dir is not None:
223+
fsid_file = os.path.abspath(legacy_dir + fsid_file)
224+
with open(fsid_file, 'r') as f:
225+
fsid = f.read().strip()
226+
except IOError:
227+
pass
228+
if not fsid:
229+
fsid = get_legacy_config_fsid(cluster, legacy_dir=legacy_dir)
230+
return fsid
231+
232+
208233
def _extract_host_info_from_applied_spec(
209234
f: Iterable[str],
210235
) -> List[Dict[str, str]]:

src/cephadm/tests/fixtures.py

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import contextlib
12
import mock
23
import os
34
import pytest
@@ -153,6 +154,8 @@ def with_cephadm_ctx(
153154
cmd: List[str],
154155
list_networks: Optional[Dict[str, Dict[str, List[str]]]] = None,
155156
hostname: Optional[str] = None,
157+
*,
158+
mock_cephadm_call_fn: bool = True,
156159
):
157160
"""
158161
:param cmd: cephadm command argv
@@ -163,25 +166,25 @@ def with_cephadm_ctx(
163166
hostname = 'host1'
164167

165168
_cephadm = import_cephadm()
166-
with mock.patch('cephadmlib.net_utils.attempt_bind'), \
167-
mock.patch('cephadmlib.call_wrappers.call', return_value=('', '', 0)), \
168-
mock.patch('cephadmlib.call_wrappers.call_timeout', return_value=0), \
169-
mock.patch('cephadm.call', return_value=('', '', 0)), \
170-
mock.patch('cephadm.call_timeout', return_value=0), \
171-
mock.patch('cephadmlib.exe_utils.find_executable', return_value='foo'), \
172-
mock.patch('cephadm.get_container_info', return_value=None), \
173-
mock.patch('cephadm.is_available', return_value=True), \
174-
mock.patch('cephadm.json_loads_retry', return_value={'epoch' : 1}), \
175-
mock.patch('cephadm.logger'), \
176-
mock.patch('cephadm.FileLock'), \
177-
mock.patch('socket.gethostname', return_value=hostname):
169+
with contextlib.ExitStack() as stack:
170+
stack.enter_context(mock.patch('cephadmlib.net_utils.attempt_bind'))
171+
stack.enter_context(mock.patch('cephadmlib.exe_utils.find_executable', return_value='foo'))
172+
stack.enter_context(mock.patch('cephadm.get_container_info', return_value=None))
173+
stack.enter_context(mock.patch('cephadm.is_available', return_value=True))
174+
stack.enter_context(mock.patch('cephadm.json_loads_retry', return_value={'epoch' : 1}))
175+
stack.enter_context(mock.patch('cephadm.logger'))
176+
stack.enter_context(mock.patch('cephadm.FileLock'))
177+
stack.enter_context(mock.patch('socket.gethostname', return_value=hostname))
178+
if mock_cephadm_call_fn:
179+
stack.enter_context(mock.patch('cephadmlib.call_wrappers.call', return_value=('', '', 0)))
180+
stack.enter_context(mock.patch('cephadmlib.call_wrappers.call_timeout', return_value=0))
181+
stack.enter_context(mock.patch('cephadm.call', return_value=('', '', 0)))
182+
stack.enter_context(mock.patch('cephadm.call_timeout', return_value=0))
183+
if list_networks is not None:
184+
stack.enter_context(mock.patch('cephadm.list_networks', return_value=list_networks))
178185
ctx: _cephadm.CephadmContext = _cephadm.cephadm_init_ctx(cmd)
179186
ctx.container_engine = mock_podman()
180-
if list_networks is not None:
181-
with mock.patch('cephadm.list_networks', return_value=list_networks):
182-
yield ctx
183-
else:
184-
yield ctx
187+
yield ctx
185188

186189

187190
@pytest.fixture()

0 commit comments

Comments
 (0)