]> git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/dashboard/services/tcmu_service.py
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / pybind / mgr / dashboard / services / tcmu_service.py
1 from mgr_util import get_most_recent_rate
2
3 from dashboard.services.ceph_service import CephService
4
5 from .. import mgr
6
7 try:
8 from typing import Dict
9 except ImportError:
10 pass # Just for type checking
11
12
13 SERVICE_TYPE = 'tcmu-runner'
14
15
16 class TcmuService(object):
17 # pylint: disable=too-many-nested-blocks
18 # pylint: disable=too-many-branches
19 @staticmethod
20 def get_iscsi_info():
21 daemons = {} # type: Dict[str, dict]
22 images = {} # type: Dict[str, dict]
23 daemon = None
24 for service in CephService.get_service_list(SERVICE_TYPE):
25 metadata = service['metadata']
26 if metadata is None:
27 continue
28 status = service['status']
29 hostname = service['hostname']
30
31 daemon = daemons.get(hostname, None)
32 if daemon is None:
33 daemon = {
34 'server_hostname': hostname,
35 'version': metadata['ceph_version'],
36 'optimized_paths': 0,
37 'non_optimized_paths': 0
38 }
39 daemons[hostname] = daemon
40
41 service_id = service['id']
42 device_id = service_id.split(':')[-1]
43 image = images.get(device_id)
44 if image is None:
45 image = {
46 'device_id': device_id,
47 'pool_name': metadata['pool_name'],
48 'name': metadata['image_name'],
49 'id': metadata.get('image_id', None),
50 'optimized_paths': [],
51 'non_optimized_paths': []
52 }
53 images[device_id] = image
54
55 if status.get('lock_owner', 'false') == 'true':
56 daemon['optimized_paths'] += 1
57 image['optimized_paths'].append(hostname)
58
59 perf_key_prefix = "librbd-{id}-{pool}-{name}.".format(
60 id=metadata.get('image_id', ''),
61 pool=metadata['pool_name'],
62 name=metadata['image_name'])
63 perf_key = "{}lock_acquired_time".format(perf_key_prefix)
64 perf_value = mgr.get_counter('tcmu-runner',
65 service_id,
66 perf_key)[perf_key]
67 if perf_value:
68 lock_acquired_time = perf_value[-1][1] / 1000000000
69 else:
70 lock_acquired_time = 0
71 if lock_acquired_time > image.get('optimized_since', 0):
72 image['optimized_daemon'] = hostname
73 image['optimized_since'] = lock_acquired_time
74 image['stats'] = {}
75 image['stats_history'] = {}
76 for s in ['rd', 'wr', 'rd_bytes', 'wr_bytes']:
77 perf_key = "{}{}".format(perf_key_prefix, s)
78 rates = CephService.get_rates('tcmu-runner', service_id, perf_key)
79 image['stats'][s] = get_most_recent_rate(rates)
80 image['stats_history'][s] = rates
81 else:
82 daemon['non_optimized_paths'] += 1
83 image['non_optimized_paths'].append(hostname)
84
85 # clear up races w/ tcmu-runner clients that haven't detected
86 # loss of optimized path
87 TcmuService.remove_undetected_clients(images, daemons, daemon)
88
89 return {
90 'daemons': sorted(daemons.values(),
91 key=lambda d: d['server_hostname']),
92 'images': sorted(images.values(), key=lambda i: ['id']),
93 }
94
95 @staticmethod
96 def get_image_info(pool_name, image_name, get_iscsi_info):
97 for image in get_iscsi_info['images']:
98 if image['pool_name'] == pool_name and image['name'] == image_name:
99 return image
100 return None
101
102 @staticmethod
103 def remove_undetected_clients(images, daemons, daemon):
104 for image in images.values():
105 optimized_daemon = image.get('optimized_daemon', None)
106 if optimized_daemon:
107 for daemon_name in image['optimized_paths']:
108 if daemon_name != optimized_daemon:
109 daemon = daemons[daemon_name]
110 daemon['optimized_paths'] -= 1
111 daemon['non_optimized_paths'] += 1
112 image['non_optimized_paths'].append(daemon_name)
113 image['optimized_paths'] = [optimized_daemon]