]>
Commit | Line | Data |
---|---|---|
f6b5b4d7 | 1 | import logging |
801d1391 | 2 | import re |
f6b5b4d7 | 3 | import json |
f91f0fd5 | 4 | import datetime |
f6b5b4d7 TL |
5 | from enum import Enum |
6 | from functools import wraps | |
7 | from typing import Optional, Callable, TypeVar, List, NewType, TYPE_CHECKING | |
801d1391 TL |
8 | from orchestrator import OrchestratorError |
9 | ||
f6b5b4d7 TL |
10 | if TYPE_CHECKING: |
11 | from cephadm import CephadmOrchestrator | |
12 | ||
13 | T = TypeVar('T') | |
14 | logger = logging.getLogger(__name__) | |
15 | ||
16 | ConfEntity = NewType('ConfEntity', str) | |
f91f0fd5 TL |
17 | |
18 | DATEFMT = '%Y-%m-%dT%H:%M:%S.%f' | |
f6b5b4d7 TL |
19 | |
20 | ||
21 | class CephadmNoImage(Enum): | |
22 | token = 1 | |
23 | ||
24 | ||
25 | # Used for _run_cephadm used for check-host etc that don't require an --image parameter | |
26 | cephadmNoImage = CephadmNoImage.token | |
27 | ||
28 | ||
29 | def name_to_config_section(name: str) -> ConfEntity: | |
801d1391 TL |
30 | """ |
31 | Map from daemon names to ceph entity names (as seen in config) | |
32 | """ | |
33 | daemon_type = name.split('.', 1)[0] | |
1911f103 | 34 | if daemon_type in ['rgw', 'rbd-mirror', 'nfs', 'crash', 'iscsi']: |
f6b5b4d7 | 35 | return ConfEntity('client.' + name) |
801d1391 | 36 | elif daemon_type in ['mon', 'osd', 'mds', 'mgr', 'client']: |
f6b5b4d7 | 37 | return ConfEntity(name) |
801d1391 | 38 | else: |
f6b5b4d7 | 39 | return ConfEntity('mon') |
e306af50 TL |
40 | |
41 | ||
f6b5b4d7 TL |
42 | def forall_hosts(f: Callable[..., T]) -> Callable[..., List[T]]: |
43 | @wraps(f) | |
44 | def forall_hosts_wrapper(*args) -> List[T]: | |
45 | from cephadm.module import CephadmOrchestrator | |
46 | ||
47 | # Some weired logic to make calling functions with multiple arguments work. | |
48 | if len(args) == 1: | |
49 | vals = args[0] | |
50 | self = None | |
51 | elif len(args) == 2: | |
52 | self, vals = args | |
53 | else: | |
54 | assert 'either f([...]) or self.f([...])' | |
55 | ||
56 | def do_work(arg): | |
57 | if not isinstance(arg, tuple): | |
58 | arg = (arg, ) | |
59 | try: | |
60 | if self: | |
61 | return f(self, *arg) | |
62 | return f(*arg) | |
63 | except Exception as e: | |
64 | logger.exception(f'executing {f.__name__}({args}) failed.') | |
65 | raise | |
66 | ||
67 | assert CephadmOrchestrator.instance is not None | |
68 | return CephadmOrchestrator.instance._worker_pool.map(do_work, vals) | |
69 | ||
70 | return forall_hosts_wrapper | |
71 | ||
72 | ||
73 | def get_cluster_health(mgr: 'CephadmOrchestrator') -> str: | |
74 | # check cluster health | |
75 | ret, out, err = mgr.check_mon_command({ | |
76 | 'prefix': 'health', | |
77 | 'format': 'json', | |
78 | }) | |
79 | try: | |
80 | j = json.loads(out) | |
81 | except Exception as e: | |
82 | raise OrchestratorError('failed to parse health status') | |
83 | ||
84 | return j['status'] | |
f91f0fd5 TL |
85 | |
86 | ||
87 | def is_repo_digest(image_name: str) -> bool: | |
88 | """ | |
89 | repo digest are something like "ceph/ceph@sha256:blablabla" | |
90 | """ | |
91 | return '@' in image_name | |
92 | ||
93 | ||
94 | def str_to_datetime(input: str) -> datetime.datetime: | |
95 | return datetime.datetime.strptime(input, DATEFMT) | |
96 | ||
97 | ||
98 | def datetime_to_str(dt: datetime.datetime) -> str: | |
99 | return dt.strftime(DATEFMT) |