]> git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/dashboard/controllers/health.py
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / pybind / mgr / dashboard / controllers / health.py
1 # -*- coding: utf-8 -*-
2 from __future__ import absolute_import
3
4 import json
5
6 from . import ApiController, Endpoint, BaseController
7
8 from .. import mgr
9 from ..security import Permission, Scope
10 from ..services.ceph_service import CephService
11 from ..services.iscsi_cli import IscsiGatewaysConfig
12
13
14 class HealthData(object):
15 """
16 A class to be used in combination with BaseController to allow either
17 "full" or "minimal" sets of health data to be collected.
18
19 To function properly, it needs BaseCollector._has_permissions to be passed
20 in as ``auth_callback``.
21 """
22
23 def __init__(self, auth_callback, minimal=True):
24 self._has_permissions = auth_callback
25 self._minimal = minimal
26
27 @staticmethod
28 def _partial_dict(orig, keys):
29 return {k: orig[k] for k in keys}
30
31 def all_health(self):
32 result = {
33 "health": self.basic_health(),
34 }
35
36 if self._has_permissions(Permission.READ, Scope.MONITOR):
37 result['mon_status'] = self.mon_status()
38
39 if self._has_permissions(Permission.READ, Scope.CEPHFS):
40 result['fs_map'] = self.fs_map()
41
42 if self._has_permissions(Permission.READ, Scope.OSD):
43 result['osd_map'] = self.osd_map()
44 result['scrub_status'] = self.scrub_status()
45 result['pg_info'] = self.pg_info()
46
47 if self._has_permissions(Permission.READ, Scope.MANAGER):
48 result['mgr_map'] = self.mgr_map()
49
50 if self._has_permissions(Permission.READ, Scope.POOL):
51 result['pools'] = self.pools()
52 result['df'] = self.df()
53 result['client_perf'] = self.client_perf()
54
55 if self._has_permissions(Permission.READ, Scope.HOSTS):
56 result['hosts'] = self.host_count()
57
58 if self._has_permissions(Permission.READ, Scope.RGW):
59 result['rgw'] = self.rgw_count()
60
61 if self._has_permissions(Permission.READ, Scope.ISCSI):
62 result['iscsi_daemons'] = self.iscsi_daemons()
63
64 return result
65
66 def basic_health(self):
67 health_data = mgr.get("health")
68 health = json.loads(health_data['json'])
69
70 # Transform the `checks` dict into a list for the convenience
71 # of rendering from javascript.
72 checks = []
73 for k, v in health['checks'].items():
74 v['type'] = k
75 checks.append(v)
76
77 checks = sorted(checks, key=lambda c: c['severity'])
78 health['checks'] = checks
79 return health
80
81 def client_perf(self):
82 result = CephService.get_client_perf()
83 if self._minimal:
84 result = self._partial_dict(
85 result,
86 ['read_bytes_sec', 'read_op_per_sec',
87 'recovering_bytes_per_sec', 'write_bytes_sec',
88 'write_op_per_sec']
89 )
90 return result
91
92 def df(self):
93 df = mgr.get('df')
94
95 del df['stats_by_class']
96
97 df['stats']['total_objects'] = sum(
98 [p['stats']['objects'] for p in df['pools']])
99 if self._minimal:
100 df = dict(stats=self._partial_dict(
101 df['stats'],
102 ['total_avail_bytes', 'total_bytes', 'total_objects',
103 'total_used_raw_bytes']
104 ))
105 return df
106
107 def fs_map(self):
108 fs_map = mgr.get('fs_map')
109 if self._minimal:
110 fs_map = self._partial_dict(fs_map, ['filesystems', 'standbys'])
111 fs_map['standbys'] = [{}] * len(fs_map['standbys'])
112 fs_map['filesystems'] = [self._partial_dict(item, ['mdsmap']) for
113 item in fs_map['filesystems']]
114 for fs in fs_map['filesystems']:
115 mdsmap_info = fs['mdsmap']['info']
116 min_mdsmap_info = dict()
117 for k, v in mdsmap_info.items():
118 min_mdsmap_info[k] = self._partial_dict(v, ['state'])
119 fs['mdsmap'] = dict(info=min_mdsmap_info)
120 return fs_map
121
122 def host_count(self):
123 return len(mgr.list_servers())
124
125 def iscsi_daemons(self):
126 gateways = IscsiGatewaysConfig.get_gateways_config()['gateways']
127 return len(gateways) if gateways else 0
128
129 def mgr_map(self):
130 mgr_map = mgr.get('mgr_map')
131 if self._minimal:
132 mgr_map = self._partial_dict(mgr_map, ['active_name', 'standbys'])
133 mgr_map['standbys'] = [{}] * len(mgr_map['standbys'])
134 return mgr_map
135
136 def mon_status(self):
137 mon_status = json.loads(mgr.get('mon_status')['json'])
138 if self._minimal:
139 mon_status = self._partial_dict(mon_status, ['monmap', 'quorum'])
140 mon_status['monmap'] = self._partial_dict(
141 mon_status['monmap'], ['mons']
142 )
143 mon_status['monmap']['mons'] = [{}] * \
144 len(mon_status['monmap']['mons'])
145 return mon_status
146
147 def osd_map(self):
148 osd_map = mgr.get('osd_map')
149 assert osd_map is not None
150 # Not needed, skip the effort of transmitting this to UI
151 del osd_map['pg_temp']
152 if self._minimal:
153 osd_map = self._partial_dict(osd_map, ['osds'])
154 osd_map['osds'] = [
155 self._partial_dict(item, ['in', 'up'])
156 for item in osd_map['osds']
157 ]
158 else:
159 osd_map['tree'] = mgr.get('osd_map_tree')
160 osd_map['crush'] = mgr.get('osd_map_crush')
161 osd_map['crush_map_text'] = mgr.get('osd_map_crush_map_text')
162 osd_map['osd_metadata'] = mgr.get('osd_metadata')
163 return osd_map
164
165 def pg_info(self):
166 pg_info = CephService.get_pg_info()
167 if self._minimal:
168 pg_info = self._partial_dict(pg_info, ['pgs_per_osd', 'statuses'])
169 return pg_info
170
171 def pools(self):
172 pools = CephService.get_pool_list_with_stats()
173 if self._minimal:
174 pools = [{}] * len(pools)
175 return pools
176
177 def rgw_count(self):
178 return len(CephService.get_service_list('rgw'))
179
180 def scrub_status(self):
181 return CephService.get_scrub_status()
182
183
184 @ApiController('/health')
185 class Health(BaseController):
186 def __init__(self):
187 super(Health, self).__init__()
188 self.health_full = HealthData(self._has_permissions, minimal=False)
189 self.health_minimal = HealthData(self._has_permissions, minimal=True)
190
191 @Endpoint()
192 def full(self):
193 return self.health_full.all_health()
194
195 @Endpoint()
196 def minimal(self):
197 return self.health_minimal.all_health()