]>
Commit | Line | Data |
---|---|---|
2a845540 TL |
1 | import logging |
2 | from typing import Dict, List, TYPE_CHECKING | |
3 | from ceph.utils import datetime_now | |
4 | from .schedule import HostAssignment | |
5 | from ceph.deployment.service_spec import ServiceSpec, TunedProfileSpec | |
6 | ||
7 | if TYPE_CHECKING: | |
8 | from cephadm.module import CephadmOrchestrator | |
9 | ||
10 | logger = logging.getLogger(__name__) | |
11 | ||
12 | SYSCTL_DIR = '/etc/sysctl.d' | |
13 | ||
14 | ||
15 | class TunedProfileUtils(): | |
16 | def __init__(self, mgr: "CephadmOrchestrator") -> None: | |
17 | self.mgr = mgr | |
18 | ||
19 | def _profile_to_str(self, p: TunedProfileSpec) -> str: | |
20 | p_str = f'# created by cephadm\n# tuned profile "{p.profile_name}"\n\n' | |
21 | for k, v in p.settings.items(): | |
22 | p_str += f'{k} = {v}\n' | |
23 | return p_str | |
24 | ||
25 | def _write_all_tuned_profiles(self) -> None: | |
26 | host_profile_mapping: Dict[str, List[Dict[str, str]]] = {} | |
27 | for host in self.mgr.cache.get_hosts(): | |
28 | host_profile_mapping[host] = [] | |
29 | ||
30 | for profile in self.mgr.tuned_profiles.list_profiles(): | |
31 | p_str = self._profile_to_str(profile) | |
32 | ha = HostAssignment( | |
33 | spec=ServiceSpec( | |
34 | 'crash', placement=profile.placement), | |
35 | hosts=self.mgr.cache.get_schedulable_hosts(), | |
36 | unreachable_hosts=self.mgr.cache.get_unreachable_hosts(), | |
37 | draining_hosts=self.mgr.cache.get_draining_hosts(), | |
38 | daemons=[], | |
39 | networks=self.mgr.cache.networks, | |
40 | ) | |
41 | all_slots, _, _ = ha.place() | |
42 | for host in {s.hostname for s in all_slots}: | |
43 | host_profile_mapping[host].append({profile.profile_name: p_str}) | |
44 | ||
45 | for host, profiles in host_profile_mapping.items(): | |
46 | self._remove_stray_tuned_profiles(host, profiles) | |
47 | self._write_tuned_profiles(host, profiles) | |
48 | ||
49 | def _remove_stray_tuned_profiles(self, host: str, profiles: List[Dict[str, str]]) -> None: | |
39ae355f TL |
50 | """ |
51 | this function looks at the contents of /etc/sysctl.d/ for profiles we have written | |
52 | that should now be removed. It assumes any file with "-cephadm-tuned-profile.conf" in | |
53 | it is written by us any without that are not. Only files written by us are considered | |
54 | candidates for removal. The "profiles" parameter is a list of dictionaries that map | |
55 | profile names to the file contents to actually be written to the | |
56 | /etc/sysctl.d/<profile-name>-cephadm-tuned-profile.conf. For example | |
57 | [ | |
58 | { | |
59 | 'profile1': 'setting1: value1\nsetting2: value2' | |
60 | }, | |
61 | { | |
62 | 'profile2': 'setting3: value3' | |
63 | } | |
64 | ] | |
65 | what we want to end up doing is going through the keys of the dicts and appending | |
66 | -cephadm-tuned-profile.conf to the profile names to build our list of profile files that | |
67 | SHOULD be on the host. Then if we see any file names that don't match this, but | |
68 | DO include "-cephadm-tuned-profile.conf" (implying they're from us), remove them. | |
69 | """ | |
aee94f69 | 70 | if self.mgr.cache.is_host_unreachable(host): |
2a845540 TL |
71 | return |
72 | cmd = ['ls', SYSCTL_DIR] | |
39ae355f | 73 | found_files = self.mgr.ssh.check_execute_command(host, cmd, log_command=self.mgr.log_refresh_metadata).split('\n') |
2a845540 | 74 | found_files = [s.strip() for s in found_files] |
39ae355f TL |
75 | profile_names: List[str] = sum([[*p] for p in profiles], []) # extract all profiles names |
76 | profile_names = list(set(profile_names)) # remove duplicates | |
77 | expected_files = [p + '-cephadm-tuned-profile.conf' for p in profile_names] | |
2a845540 TL |
78 | updated = False |
79 | for file in found_files: | |
80 | if '-cephadm-tuned-profile.conf' not in file: | |
81 | continue | |
39ae355f | 82 | if file not in expected_files: |
2a845540 TL |
83 | logger.info(f'Removing stray tuned profile file {file}') |
84 | cmd = ['rm', '-f', f'{SYSCTL_DIR}/{file}'] | |
85 | self.mgr.ssh.check_execute_command(host, cmd) | |
86 | updated = True | |
87 | if updated: | |
88 | self.mgr.ssh.check_execute_command(host, ['sysctl', '--system']) | |
89 | ||
90 | def _write_tuned_profiles(self, host: str, profiles: List[Dict[str, str]]) -> None: | |
aee94f69 | 91 | if self.mgr.cache.is_host_unreachable(host): |
2a845540 TL |
92 | return |
93 | updated = False | |
94 | for p in profiles: | |
95 | for profile_name, content in p.items(): | |
96 | if self.mgr.cache.host_needs_tuned_profile_update(host, profile_name): | |
97 | logger.info(f'Writing tuned profile {profile_name} to host {host}') | |
98 | profile_filename: str = f'{SYSCTL_DIR}/{profile_name}-cephadm-tuned-profile.conf' | |
99 | self.mgr.ssh.write_remote_file(host, profile_filename, content.encode('utf-8')) | |
100 | updated = True | |
101 | if updated: | |
102 | self.mgr.ssh.check_execute_command(host, ['sysctl', '--system']) | |
103 | self.mgr.cache.last_tuned_profile_update[host] = datetime_now() |