}
}
- rivets.formatters.dimless = function(n){
+ var format_number = function(n, divisor, units) {
var width=4;
- var units = [' ', 'k', 'M', 'G', 'T', 'P'];
var unit = 0;
- while (Math.floor(n / (1000**unit)).toString().length > width - 1) {
+ while (Math.floor(n / (divisor**unit)).toString().length > width - 1) {
unit = unit + 1;
}
var truncated_float;
if (unit > 0) {
- truncated_float = truncate((n / Math.pow(1000.0, unit)).toString(), width);
+ truncated_float = truncate((n / Math.pow(divisor, unit)).toString(), width);
} else {
truncated_float = truncate(n, width);
}
return truncated_float + units[unit];
+ }
+
+ rivets.formatters.dimless = function(n){
+ return format_number(n, 1000, [' ', 'k', 'M', 'G', 'T', 'P'])
+ };
+ rivets.formatters.dimless_binary = function(n){
+ return format_number(n, 1024, ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB']);
};
<!--rivet.formatters.mon_summary = function(mon_map) {-->
<li><a href="/servers"><i class="fa fa-server"></i>
<span>Servers</span></a>
</li>
+ <li class="treeview active">
+ <a href="#"><i class="fa fa-hdd-o"></i> <span>Block</span>
+ <span class="pull-right-container">
+ <i class="fa fa-angle-left pull-right"></i>
+ </span>
+ </a>
+ <ul class="treeview-menu menu-open">
+ <li rv-each-pool="rbd_pools">
+ <a rv-href="pool.url">{pool.name}</a>
+ </li>
+ </ul>
+ </li>
<li class="treeview active">
<a href="#"><i class="fa fa-folder"></i> <span>Filesystems</span>
<span class="pull-right-container">
PgSummary, Health, MonStatus
import rados
-from rbd_ls import RbdLs
+from rbd_ls import RbdLs, RbdPoolLs
from cephfs_clients import CephFSClients
# is pool name.
self.rbd_ls = {}
+ # Stateful instance of RbdPoolLs, hold cached list of RBD
+ # pools
+ self.rbd_pool_ls = RbdPoolLs(self)
+
# Stateful instances of CephFSClients, hold cached results. Key to
# dict is FSCID
self.cephfs_clients = {}
"""
Data consumed by the base.html template
"""
+ status, data = global_instance().rbd_pool_ls.get()
+ if data is None:
+ log.warning("Failed to get RBD pool list")
+ data = []
+
+ rbd_pools = sorted([
+ {
+ "name": name,
+ "url": "/rbd/{0}/".format(name)
+ }
+ for name in data
+ ], key=lambda k: k['name'])
+
fsmap = global_instance().get_sync_object(FsMap)
filesystems = [
{
return {
'health': global_instance().get_sync_object(Health).data,
+ 'rbd_pools': rbd_pools,
'filesystems': filesystems
}
<tbody>
<tr rv-each-image="images">
<td>{image.name}</td>
- <td>{image.size | dimless}</td>
+ <td>{image.size | dimless_binary}</td>
<td>{image.num_objs | dimless}</td>
- <td>{image.obj_size | dimless}</td>
+ <td>{image.obj_size | dimless_binary}</td>
<td>{image.parent}</td>
</tr>
</tbody>
</section>
<!-- /.content -->
-{% endblock %}
\ No newline at end of file
+{% endblock %}
-import rados
import rbd
+import rados
+from types import OsdMap
from remote_view_cache import RemoteViewCache
+class RbdPoolLs(RemoteViewCache):
+ def _get(self):
+ from mgr_module import ceph_state
+ ctx_capsule = ceph_state.get_context()
+
+ osd_map = self._module.get_sync_object(OsdMap).data
+ osd_pools = [pool['pool_name'] for pool in osd_map['pools']]
+
+ rbd_pools = []
+ for pool in osd_pools:
+ self.log.debug("Constructing IOCtx " + pool)
+ try:
+ ioctx = self._module.rados.open_ioctx(pool)
+ ioctx.stat("rbd_directory")
+ rbd_pools.append(pool)
+ except (rados.PermissionError, rados.ObjectNotFound):
+ self.log.debug("No RBD directory in " + pool)
+ except:
+ self.log.exception("Failed to open pool " + pool)
+
+ return rbd_pools
class RbdLs(RemoteViewCache):
def __init__(self, module_inst, pool):
self.rbd = None
def _init(self):
- from mgr_module import ceph_state
- ctx_capsule = ceph_state.get_context()
-
- self.log.info("Constructing Rados")
- cluster = rados.Rados(context=ctx_capsule)
- cluster.connect()
- self.log.info("Constructing IOCtx")
- self.ioctx = cluster.open_ioctx("rbd")
+ self.log.debug("Constructing IOCtx")
+ self.ioctx = self._module.rados.open_ioctx(self.pool)
- self.log.info("Constructing RBD")
+ self.log.debug("Constructing RBD")
self.rbd = rbd.RBD()
def _get(self):
i = rbd.Image(self.ioctx, name)
stat = i.stat()
stat['name'] = name
+
+ try:
+ parent_info = i.parent_info()
+ parent = "{}@{}".format(parent_info[0], parent_info[1])
+ if parent_info[0] != self.pool:
+ parent = "{}/{}".format(parent_info[0], parent)
+ stat['parent'] = parent
+ except rbd.ImageNotFound:
+ pass
result.append(stat)
return result