Skip to content

Commit d9846a7

Browse files
cephadm: move infer_local_ceph_image out of cephadm.py
Move infer_local_ceph_image out of cephadm.py into cephadmlib.container_lookup continuing the overall effort to shrink cephadm.py. Signed-off-by: John Mulligan <[email protected]>
1 parent c405e70 commit d9846a7

File tree

2 files changed

+86
-82
lines changed

2 files changed

+86
-82
lines changed

src/cephadm/cephadm.py

Lines changed: 1 addition & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,10 @@
8585
concurrent_tasks,
8686
)
8787
from cephadmlib.container_engines import (
88-
ImageInfo,
8988
Podman,
9089
check_container_engine,
9190
find_container_engine,
9291
normalize_container_id,
93-
parsed_container_image_list,
9492
parsed_container_mem_usage,
9593
pull_command,
9694
registry_login,
@@ -203,6 +201,7 @@
203201
MemUsageStatusUpdater,
204202
VersionStatusUpdater,
205203
)
204+
from cephadmlib.container_lookup import infer_local_ceph_image
206205

207206

208207
FuncT = TypeVar('FuncT', bound=Callable)
@@ -466,84 +465,6 @@ def update_default_image(ctx: CephadmContext) -> None:
466465
ctx.image = _get_default_image(ctx)
467466

468467

469-
def infer_local_ceph_image(
470-
ctx: CephadmContext, container_path: str = ''
471-
) -> Optional[str]:
472-
"""Infer the best ceph image to use based on the following criteria:
473-
Out of all images labeled as ceph that are non-dangling, prefer
474-
1. the same image as the daemon container specified by -name arg (if provided).
475-
2. the image used by any ceph container running on the host
476-
3. the most ceph recent image on the host
477-
478-
:return: An image name or none
479-
"""
480-
from operator import itemgetter
481-
482-
# enumerate ceph images on the system
483-
images = parsed_container_image_list(
484-
ctx,
485-
filters=['dangling=false', 'label=ceph=True'],
486-
container_path=container_path,
487-
)
488-
if not images:
489-
logger.warning('No non-dangling ceph images found')
490-
return None # no images at all cached on host
491-
492-
# find running ceph daemons
493-
_daemons = ceph_daemons()
494-
daemon_name = getattr(ctx, 'name', '')
495-
_cinfo_key = '_container_info'
496-
_updater = CoreStatusUpdater(keep_container_info=_cinfo_key)
497-
matching_daemons = [
498-
itemgetter(_cinfo_key, 'name')(_updater.expand(ctx, entry))
499-
for entry in daemons_matching(
500-
ctx, fsid=ctx.fsid, daemon_type_predicate=lambda t: t in _daemons
501-
)
502-
]
503-
# collect the running ceph daemon image ids
504-
images_in_use_by_daemon = set(
505-
d.image_id for d, n in matching_daemons if n == daemon_name
506-
)
507-
images_in_use = set(d.image_id for d, _ in matching_daemons)
508-
509-
# prioritize images
510-
def _keyfunc(image: ImageInfo) -> Tuple[bool, bool, str]:
511-
return (
512-
bool(
513-
image.digest
514-
and any(
515-
v.startswith(image.image_id)
516-
for v in images_in_use_by_daemon
517-
)
518-
),
519-
bool(
520-
image.digest
521-
and any(v.startswith(image.image_id) for v in images_in_use)
522-
),
523-
image.created,
524-
)
525-
526-
images.sort(key=_keyfunc, reverse=True)
527-
best_image = images[0]
528-
name_match, ceph_match, _ = _keyfunc(best_image)
529-
reason = 'not in the list of non-dangling images with ceph=True label'
530-
if images_in_use_by_daemon and not name_match:
531-
expected = list(images_in_use_by_daemon)[0]
532-
logger.warning(
533-
'Not using image %r of named daemon: %s',
534-
expected,
535-
reason,
536-
)
537-
if images_in_use and not ceph_match:
538-
expected = list(images_in_use)[0]
539-
logger.warning(
540-
'Not using image %r of ceph daemon: %s',
541-
expected,
542-
reason,
543-
)
544-
return best_image.name
545-
546-
547468
def get_log_dir(fsid, log_dir):
548469
# type: (str, str) -> str
549470
return os.path.join(log_dir, fsid)

src/cephadm/cephadmlib/container_lookup.py

Lines changed: 85 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
11
# container_lookup.py - high-level functions for getting container info
22

3-
from typing import Optional
3+
from operator import itemgetter
4+
from typing import Optional, Tuple
45

56
import logging
67

7-
from .container_engines import ContainerInfo, parsed_container_image_stats
8+
from .container_engines import (
9+
ContainerInfo,
10+
ImageInfo,
11+
parsed_container_image_list,
12+
parsed_container_image_stats,
13+
)
814
from .container_types import get_container_stats
915
from .context import CephadmContext
1016
from .daemon_identity import DaemonIdentity
17+
from .daemons.ceph import ceph_daemons
1118
from .listing import daemons_matching
1219
from .listing_updaters import CoreStatusUpdater
1320

@@ -89,3 +96,79 @@ def get_container_info(
8996
'bad daemon state: no image, not running: %r', matched_deamon
9097
)
9198
return None
99+
100+
101+
def infer_local_ceph_image(
102+
ctx: CephadmContext, container_path: str = ''
103+
) -> Optional[str]:
104+
"""Infer the best ceph image to use based on the following criteria:
105+
Out of all images labeled as ceph that are non-dangling, prefer
106+
1. the same image as the daemon container specified by -name arg (if provided).
107+
2. the image used by any ceph container running on the host
108+
3. the most ceph recent image on the host
109+
110+
:return: An image name or none
111+
"""
112+
# enumerate ceph images on the system
113+
images = parsed_container_image_list(
114+
ctx,
115+
filters=['dangling=false', 'label=ceph=True'],
116+
container_path=container_path,
117+
)
118+
if not images:
119+
logger.warning('No non-dangling ceph images found')
120+
return None # no images at all cached on host
121+
122+
# find running ceph daemons
123+
_daemons = ceph_daemons()
124+
daemon_name = getattr(ctx, 'name', '')
125+
_cinfo_key = '_container_info'
126+
_updater = CoreStatusUpdater(keep_container_info=_cinfo_key)
127+
matching_daemons = [
128+
itemgetter(_cinfo_key, 'name')(_updater.expand(ctx, entry))
129+
for entry in daemons_matching(
130+
ctx, fsid=ctx.fsid, daemon_type_predicate=lambda t: t in _daemons
131+
)
132+
]
133+
# collect the running ceph daemon image ids
134+
images_in_use_by_daemon = set(
135+
d.image_id for d, n in matching_daemons if n == daemon_name
136+
)
137+
images_in_use = set(d.image_id for d, _ in matching_daemons)
138+
139+
# prioritize images
140+
def _keyfunc(image: ImageInfo) -> Tuple[bool, bool, str]:
141+
return (
142+
bool(
143+
image.digest
144+
and any(
145+
v.startswith(image.image_id)
146+
for v in images_in_use_by_daemon
147+
)
148+
),
149+
bool(
150+
image.digest
151+
and any(v.startswith(image.image_id) for v in images_in_use)
152+
),
153+
image.created,
154+
)
155+
156+
images.sort(key=_keyfunc, reverse=True)
157+
best_image = images[0]
158+
name_match, ceph_match, _ = _keyfunc(best_image)
159+
reason = 'not in the list of non-dangling images with ceph=True label'
160+
if images_in_use_by_daemon and not name_match:
161+
expected = list(images_in_use_by_daemon)[0]
162+
logger.warning(
163+
'Not using image %r of named daemon: %s',
164+
expected,
165+
reason,
166+
)
167+
if images_in_use and not ceph_match:
168+
expected = list(images_in_use)[0]
169+
logger.warning(
170+
'Not using image %r of ceph daemon: %s',
171+
expected,
172+
reason,
173+
)
174+
return best_image.name

0 commit comments

Comments
 (0)