]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
pybind/mgr/dashboard: initial block integration 15521/head
authorJason Dillaman <dillaman@redhat.com>
Tue, 6 Jun 2017 19:03:58 +0000 (15:03 -0400)
committerJason Dillaman <dillaman@redhat.com>
Fri, 23 Jun 2017 13:00:39 +0000 (09:00 -0400)
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/pybind/mgr/dashboard/base.html
src/pybind/mgr/dashboard/module.py
src/pybind/mgr/dashboard/rbd.html
src/pybind/mgr/dashboard/rbd_ls.py

index 41d059347697ae6b2b8015c310179984ff18eff3..e7256d1ba0aeb6d2d2a35ca74b5536fe6babe56a 100644 (file)
                 }
             }
 
-            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">
index 362faddad11df865fbc1660373f1b90bbb3ccd29..02c824bd56fdfc94b94a12ac324fe6fb9cda9f02 100644 (file)
@@ -32,7 +32,7 @@ from types import OsdMap, NotFound, Config, FsMap, MonMap, \
     PgSummary, Health, MonStatus
 
 import rados
-from rbd_ls import RbdLs
+from rbd_ls import RbdLs, RbdPoolLs
 from cephfs_clients import CephFSClients
 
 
@@ -79,6 +79,10 @@ class Module(MgrModule):
         # 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 = {}
@@ -412,6 +416,19 @@ class Module(MgrModule):
                 """
                 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 = [
                     {
@@ -424,6 +441,7 @@ class Module(MgrModule):
 
                 return {
                     'health': global_instance().get_sync_object(Health).data,
+                    'rbd_pools': rbd_pools,
                     'filesystems': filesystems
                 }
 
index 3e0e69945858075a8fe197282429b12cde595584..ed4b9633d67fa2baefb2507ff5e1d334e3fbcc41 100644 (file)
@@ -47,9 +47,9 @@
                 <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>
@@ -61,4 +61,4 @@
 </section>
 <!-- /.content -->
 
-{% endblock %}
\ No newline at end of file
+{% endblock %}
index 510a7777820368a9628b47588ab532219c340ec6..e03d78ed1ade8f0f23831779ee61e041e979057a 100644 (file)
@@ -1,8 +1,30 @@
 
-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):
@@ -14,16 +36,10 @@ class RbdLs(RemoteViewCache):
         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):
@@ -34,5 +50,14 @@ class RbdLs(RemoteViewCache):
             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