]>
git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/dashboard/controllers/cephfs.py
1 # -*- coding: utf-8 -*-
2 from __future__
import absolute_import
4 from collections
import defaultdict
8 from . import ApiController
, RESTController
10 from ..exceptions
import DashboardException
11 from ..security
import Scope
12 from ..services
.ceph_service
import CephService
13 from ..tools
import ViewCache
16 @ApiController('/cephfs', Scope
.CEPHFS
)
17 class CephFS(RESTController
):
19 super(CephFS
, self
).__init
__()
21 # Stateful instances of CephFSClients, hold cached results. Key to
23 self
.cephfs_clients
= {}
26 fsmap
= mgr
.get("fs_map")
27 return fsmap
['filesystems']
30 fs_id
= self
.fs_id_to_int(fs_id
)
32 return self
.fs_status(fs_id
)
34 @RESTController.Resource('GET')
35 def clients(self
, fs_id
):
36 fs_id
= self
.fs_id_to_int(fs_id
)
38 return self
._clients
(fs_id
)
40 @RESTController.Resource('GET')
41 def mds_counters(self
, fs_id
):
43 Result format: map of daemon name to map of counter to list of datapoints
44 rtype: dict[str, dict[str, list]]
47 # Opinionated list of interesting performance counters for the GUI --
48 # if you need something else just add it. See how simple life is
49 # when you don't have to write general purpose APIs?
51 "mds_server.handle_client_request",
53 "mds_cache.num_strays",
55 "mds.exported_inodes",
57 "mds.imported_inodes",
64 fs_id
= self
.fs_id_to_int(fs_id
)
67 mds_names
= self
._get
_mds
_names
(fs_id
)
69 for mds_name
in mds_names
:
71 for counter
in counters
:
72 data
= mgr
.get_counter("mds", mds_name
, counter
)
74 result
[mds_name
][counter
] = data
[counter
]
76 result
[mds_name
][counter
] = []
81 def fs_id_to_int(fs_id
):
85 raise DashboardException(code
='invalid_cephfs_id',
86 msg
="Invalid cephfs ID {}".format(fs_id
),
89 def _get_mds_names(self
, filesystem_id
=None):
92 fsmap
= mgr
.get("fs_map")
93 for fs
in fsmap
['filesystems']:
94 if filesystem_id
is not None and fs
['id'] != filesystem_id
:
96 names
.extend([info
['name']
97 for _
, info
in fs
['mdsmap']['info'].items()])
99 if filesystem_id
is None:
100 names
.extend(info
['name'] for info
in fsmap
['standbys'])
104 def _append_mds_metadata(self
, mds_versions
, metadata_key
):
105 metadata
= mgr
.get_metadata('mds', metadata_key
)
108 mds_versions
[metadata
.get('ceph_version', 'unknown')].append(metadata_key
)
110 # pylint: disable=too-many-statements,too-many-branches
111 def fs_status(self
, fs_id
):
112 mds_versions
= defaultdict(list)
114 fsmap
= mgr
.get("fs_map")
116 for fs
in fsmap
['filesystems']:
117 if fs
['id'] == fs_id
:
121 if filesystem
is None:
122 raise cherrypy
.HTTPError(404,
123 "CephFS id {0} not found".format(fs_id
))
127 mdsmap
= filesystem
['mdsmap']
131 for rank
in mdsmap
["in"]:
132 up
= "mds_{0}".format(rank
) in mdsmap
["up"]
134 gid
= mdsmap
['up']["mds_{0}".format(rank
)]
135 info
= mdsmap
['info']['gid_{0}'.format(gid
)]
136 dns
= mgr
.get_latest("mds", info
['name'], "mds_mem.dn")
137 inos
= mgr
.get_latest("mds", info
['name'], "mds_mem.ino")
140 client_count
= mgr
.get_latest("mds", info
['name'],
141 "mds_sessions.session_count")
142 elif client_count
== 0:
143 # In case rank 0 was down, look at another rank's
144 # sessionmap to get an indication of clients.
145 client_count
= mgr
.get_latest("mds", info
['name'],
146 "mds_sessions.session_count")
148 laggy
= "laggy_since" in info
150 state
= info
['state'].split(":")[1]
154 # Populate based on context of state, e.g. client
155 # ops for an active daemon, replay progress, reconnect
157 if state
== "active":
158 activity
= CephService
.get_rate("mds",
160 "mds_server.handle_client_request")
164 self
._append
_mds
_metadata
(mds_versions
, info
['name'])
170 "activity": activity
,
188 # Find the standby replays
189 # pylint: disable=unused-variable
190 for gid_str
, daemon_info
in mdsmap
['info'].items():
191 if daemon_info
['state'] != "up:standby-replay":
194 inos
= mgr
.get_latest("mds", daemon_info
['name'], "mds_mem.ino")
195 dns
= mgr
.get_latest("mds", daemon_info
['name'], "mds_mem.dn")
197 activity
= CephService
.get_rate(
198 "mds", daemon_info
['name'], "mds_log.replay")
202 "rank": "{0}-s".format(daemon_info
['rank']),
203 "state": "standby-replay",
204 "mds": daemon_info
['name'],
205 "activity": activity
,
212 pool_stats
= {p
['id']: p
['stats'] for p
in df
['pools']}
213 osdmap
= mgr
.get("osd_map")
214 pools
= {p
['pool']: p
for p
in osdmap
['pools']}
215 metadata_pool_id
= mdsmap
['metadata_pool']
216 data_pool_ids
= mdsmap
['data_pools']
219 for pool_id
in [metadata_pool_id
] + data_pool_ids
:
220 pool_type
= "metadata" if pool_id
== metadata_pool_id
else "data"
221 stats
= pool_stats
[pool_id
]
223 "pool": pools
[pool_id
]['pool_name'],
225 "used": stats
['bytes_used'],
226 "avail": stats
['max_avail']
230 for standby
in fsmap
['standbys']:
231 self
._append
_mds
_metadata
(mds_versions
, standby
['name'])
232 standby_table
.append({
233 'name': standby
['name']
239 "name": mdsmap
['fs_name'],
240 "client_count": client_count
,
244 "standbys": standby_table
,
245 "versions": mds_versions
248 def _clients(self
, fs_id
):
249 cephfs_clients
= self
.cephfs_clients
.get(fs_id
, None)
250 if cephfs_clients
is None:
251 cephfs_clients
= CephFSClients(mgr
, fs_id
)
252 self
.cephfs_clients
[fs_id
] = cephfs_clients
255 status
, clients
= cephfs_clients
.get()
256 except AttributeError:
257 raise cherrypy
.HTTPError(404,
258 "No cephfs with id {0}".format(fs_id
))
261 raise cherrypy
.HTTPError(404,
262 "No cephfs with id {0}".format(fs_id
))
264 # Decorate the metadata with some fields that will be
265 # indepdendent of whether it's a kernel or userspace
266 # client, so that the javascript doesn't have to grok that.
267 for client
in clients
:
268 if "ceph_version" in client
['client_metadata']:
269 client
['type'] = "userspace"
270 client
['version'] = client
['client_metadata']['ceph_version']
271 client
['hostname'] = client
['client_metadata']['hostname']
272 elif "kernel_version" in client
['client_metadata']:
273 client
['type'] = "kernel"
274 client
['version'] = client
['client_metadata']['kernel_version']
275 client
['hostname'] = client
['client_metadata']['hostname']
277 client
['type'] = "unknown"
278 client
['version'] = ""
279 client
['hostname'] = ""
287 class CephFSClients(object):
288 def __init__(self
, module_inst
, fscid
):
289 self
._module
= module_inst
294 return CephService
.send_command('mds', 'session ls', srv_spec
='{0}:0'.format(self
.fscid
))