cfg-checker ceph bench module alpha version

 - Ceph benchmark report (beta)
 - Updated result time choosing. Now results reported based on start time
 - New methods for listing
 - Cleanup-only mode
 - Unified results processing
 - Additional ceph info gather
 - Experimental barchart graph example

Fixes:
 - Kube API client recreated each time for stability (HTTP/WebSocket specifics)
 - args naming fixes
 -

Change-Id: Id541f789a00ab4ee827603c5b6f7f07899aaa7c5
diff --git a/templates/bar_chart.j2 b/templates/bar_chart.j2
new file mode 100644
index 0000000..52a042e
--- /dev/null
+++ b/templates/bar_chart.j2
@@ -0,0 +1,76 @@
+<style>
+    .bc-wrap {
+        display: table;
+        position: relative;
+        margin: 7px 0;
+        height: 60px;
+      }
+      .bc-container {
+        display: table-cell;
+        width: 100%;
+        height: 100%;
+        padding-left: 15px;
+      }
+      .bc {
+       display: table;
+       height: 100%;
+       width: 100%;
+       border-bottom: 2px solid black;
+      }
+      .bccol {
+        position: relative;
+        vertical-align: bottom;
+        display: table-cell;
+        height: 100%;
+      }
+      .bcbar {
+        position: relative;
+        height: 0;
+        transition: height 0.5s 2s;
+        width: 25px;
+        margin: auto;
+        background-color: #358;
+      }
+      .bcfooter {
+        position: absolute;
+        text-align: center;
+        width: 100%;
+        top: 53px;
+        font-size: 10px;
+      }
+      .bctimecol {
+        position: absolute;
+        top: 0;
+        height: 100%;
+        width: 100%;
+      }
+      .bctime {
+        height: 15px;
+        vertical-align: middle;
+        position: relative;
+      }
+      .bctime:after {
+        border-bottom: 1px dotted black;
+        content: "";
+        position: absolute;
+        width: 100%;
+        left: 0;
+        top: 0em;
+      }
+      .bctimetext {
+        position: absolute;
+        top: -8px;
+        z-index: 1;
+        background: white;
+        padding-right: 5px;
+        color: #4d4d4d;
+        font-size: 8px;
+        font-family: 'Avenir Medium';
+      }
+      .red-bar {
+        background-color: darkred;
+      }
+      .green-bar {
+        background-color: green;
+      }
+</style>
diff --git a/templates/ceph_bench_html.j2 b/templates/ceph_bench_html.j2
new file mode 100644
index 0000000..e847cb4
--- /dev/null
+++ b/templates/ceph_bench_html.j2
@@ -0,0 +1,679 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Ceph cluster info</title>
+    {% include 'common_styles.j2' %}
+    {% include 'common_scripts.j2' %}
+    {% include 'bar_chart.j2' %}
+    <style>
+        table.cluster_nodes {
+            width: 100%;
+            margin-left: 1%;
+            margin-right: 1%;
+        }
+        .barcontent {
+            margin: auto;
+            width: 1350px;
+            padding: 10px;
+        }
+        .bar-centered {
+            float: none;
+            transform: translate(25%);
+        }
+    
+        /* Node rows*/
+		.node {
+			font-family: "LaoSangamMN", Monaco, monospace;
+			font-size: 0.8em;
+			display: flex;
+			background-color: white;
+            align-items: center;
+		}
+		.collapsable {
+			font-family: "LaoSangamMN", Monaco, monospace;
+			font-size: 0.8em;
+			display: none;
+            background-color: white;
+            visibility: hidden;
+        }
+        .collapsable.in {
+            visibility: visible;
+            display: inline-block;
+        }
+
+        .row_button {
+            background-color: #468;
+            color: #fff;
+            cursor: pointer;
+            padding: 5px;
+            width: 100%;
+            border: none;
+            text-align: left;
+            outline: none;
+            font-size: 13px;
+        }
+        .row_button:after {
+            content: '\02795'; /* Unicode character for "plus" sign (+) */
+            font-size: 13px;
+            color: white;
+            float: left;
+            margin-left: 5px;
+        }
+          
+        .row_active:after {
+            content: "\2796"; /* Unicode character for "minus" sign (-) */
+            color: white
+        }        
+
+        .row_active, .row_button:hover {
+            background-color: #68a;
+            color: white
+        }
+
+        .cell_button {
+            color: darkgreen;
+            cursor: pointer;
+            padding: 5px;
+            width: 100%;
+            border: none;
+            text-align: center;
+            outline: none;
+        }
+        .cell_button:hover {
+            background-color: gray;
+        }
+        
+        .row_content {
+            padding: 0 18px;
+            background-color: white;
+            max-height: 0;
+            overflow: hidden;
+            transition: max-height 0.2s ease-out;
+            border-width: 1px;
+            border-color: #68a;
+            border-style: solid;
+        }
+
+        div.services > .collapsable.in {
+            display: table-row;
+        }
+        tr:nth-child(even) {
+            background-color: #eee;
+        }
+        tr:nth-child(odd) {
+            background-color: #fff;
+        }
+	
+        tr.node > td, tr.collapsable > td {
+            display: block;
+            float: left;
+            padding: 1px;
+            margin: 2px;
+        }
+        td > .osd_group {
+            display: grid;
+            grid-template-columns: 40px 25px 25px 70px;
+            padding-left: 0px;
+            padding-right: 0px;
+            margin: 1px;
+        }
+        td > .props_group {
+            display: grid;
+            grid-template-columns: 60px 60px 80px 35px 45px 95px 50px 60px 45px;
+            padding-left: 0px;
+            padding-right: 0px;
+            margin: 1px;
+        }
+        td > .pg_group {
+            display: grid;
+            grid-template-columns: 50px 40px 60px 65px 60px 65px 65px;;
+            padding-left: 0px;
+            padding-right: 0px;
+            margin: 1px;
+        }
+        td > .bench_run_group {
+            display: grid;
+            grid-template-columns: 80px 80px 80px 80px 75px 75px;
+            padding-left: 0px;
+            padding-right: 0px;
+            margin: 1px;
+        }
+        td > .bench_group {
+            display: grid;
+            grid-template-columns: 80px 80px 75px 75px;
+            padding-left: 0px;
+            padding-right: 0px;
+            margin: 1px;
+        }
+        td > .meta_group {
+            display: inline-block;
+            grid-template-columns: repeat(4, auto);
+            padding-left: 0px;
+            padding-right: 0px;
+            margin: 1px;
+        }
+        .item {
+        	display: inline-grid;
+  			border-width: 1px;
+			border-style: solid;
+			margin: 1px 1px 1px 1px;
+            padding: 0px 1px 0px 1px;
+        }
+
+	    .spacer { border-radius: 2px; width: 20px;}
+        .status { border-radius: 10px; width: 120px; text-align: center;}
+	    .health_ok { background-color: #393; color: white;}
+        .health_error { background-color: #933; color: white;}
+        .health_warn { background-color: #eb3; color: #333;}
+        .checks_code { border-radius: 2px; width: 20%; background-color: transparent; color: darkred;}
+
+        .head { height: 18px; background-color: transparent; border-color: transparent; border: 0px;}
+        .centered { text-align: center;}
+        .right { text-align: right;}
+	    .col_shortmessage {	min-width: 300px; }
+        .col_longmessage {	width: auto; }
+        .col_properties { width: auto;}
+
+        .srv_name { width: 300px }
+        .srv_path { width: 250px }
+        .srv_timestamp { width: 250px }
+        .srv_addr { width: 450px }
+
+        .id { width: 30px }
+        .bucket_name { width: 365px }
+        .bucket_type { width: 50px }
+        .bucket_params { width: 200px }
+        .bucket_items { width: 630px }
+
+        .df_name { width: 300px }
+        .df_total { width: 150px }
+        .df_avail { width: 150px }
+        .df_used { width: 150px }
+        .df_used_raw { width: 150px }
+        .df_used_raw_rate { width: 150px }
+
+        .rdf_name { width: 200px; }
+        .rdf_obj { width: 75px; }
+        .rdf_total { width: 100px; }
+        .rdf_used { width: 100px; }
+        .rdf_bench { width: 100px; }
+
+        .dev_name { width: 300px; }
+        .dev_param { width: 100px; }
+
+        .mon_name { width: 100px }
+        .mon_url { width: 500px }
+
+        .meters {
+            display: inline-block;
+            margin: 1px;
+        }
+        .meters > .meter {
+            display: block;
+            float: left;
+  			border-width: 1px;
+			border-style: solid;
+			margin: 0px 1px 0px 1px;
+            padding: 0px 1px 0px 1px;
+            
+        }
+        .meters > .warn {
+			border-color: #d3a200;
+			background-color: rgb(255, 216, 133);
+        }
+        .meters > .fail {
+			border-color: #bb0000;
+			background-color: rgb(250, 135, 135);
+        }
+        .osd { border-color: #a0c0a0; background-color: rgb(252, 248, 248); text-align: center;}
+        .prop { border-color: #74c28b; background-color: rgb(252, 248, 248); text-align: center;}
+        .pg { border-color: #c0c0a0; background-color: rgb(255, 255, 251); text-align: right; }
+        .bench { border-color: #a0c0c0; background-color: rgb(255, 250, 250); text-align: right; }
+        .lat_commit { border-color: #a0c0c0; background-color: rgb(255, 250, 250); text-align: right; width: 45px}
+        .lat_apply { border-color: #a0c0c0; background-color: rgb(255, 250, 250); text-align: left;  width: 35px}
+        .meta_name { border-color: #c4b890; background-color: #e7dbb6; text-align: left; width: 150px;}
+        .meta_value { border-color: #c6c3ba;background-color: #d4d4d4; text-align: left; width: 480px;}
+
+        .map_grid {
+            display: grid;
+            grid-template-columns: auto auto auto auto auto auto auto auto auto auto;
+            grid-column-gap: 20px;
+            padding-left: 0px;
+            padding-right: 0px;
+            margin: 1px;
+            margin-left: 20px;
+
+        }
+        .map_item {
+        	display: inline-grid;
+            border-width: 0px;
+			border-style: solid;
+			margin: 1px 1px 1px 1px;
+            padding: 0px 1px 0px 1px;
+        }
+
+        .map_grid > .ok {
+            color: #80a080;
+        }
+        .map_grid > .warn {
+            color: #d3a200;
+        }
+        .map_grid > .fail {
+            color: #bb0000;
+        }
+
+        .modules {
+			font-family: "LaoSangamMN", Monaco, monospace;
+			font-size: 0.8em;
+			background-color: white;
+        }
+        .module_node {
+            margin-bottom: 2px;
+            display: flex;
+        }
+        .module_name, .node_name {
+            text-align: center;
+            border-width: 0px;
+			border-style: solid;
+			margin: 1px 1px 1px 1px;
+            padding: 0px 1px 0px 1px;
+            min-width: 250px;
+            border-radius: 10px;
+        }
+        .node_name {
+            background-color: #ddd;
+        }
+        .module_grid {
+            display: grid;
+            grid-template-columns: repeat(8, 100px);
+            grid-template-rows: repeat(6, auto);
+            grid-auto-flow: column;
+            grid-column-gap: 10px;
+            padding-left: 0px;
+            padding-right: 0px;
+            margin: 1px;
+            margin-left: 20px;
+          }
+        .module {
+            display: inline-grid;
+            text-align: center;
+            border-width: 0px;
+			border-style: solid;
+			margin: 1px 1px 1px 1px;
+            padding: 0px 1px 0px 1px;
+            min-width: 100px;
+            border-radius: 10px;
+        }
+
+        .module_grid > .on, .service_node > .ok {
+            background-color: #8c8;
+        }
+        .module_grid > .off, .service_node > .off{
+            background-color: #9aa;
+        }
+        .module_grid > .fail, .service_node > .fail {
+            background-color: #a33;
+        }
+        .module_grid > .always, .service_node > .fail {
+            background-color: #282;
+        }
+
+        .tooltiptext {
+            transform: translate(100px);
+        }
+
+        .console {
+            background-color: black;
+            font-family: "Lucida Console", Monaco, monospace;
+            font-size: 0.5em;
+            width: auto;
+            color: #fff;
+            border-radius: 6px;
+            padding: 5px 5px;
+        }
+    
+    </style>
+</head>
+<body onload="init()">
+
+<div class="header">
+    <div class="label">Ceph version:</div>
+    <div class="text">{{ ceph_version }}</div>
+    <div class="label">Image:</div>
+    <div class="text">{{ cluster.image }}</div>
+    <div class="label date">generated on: {{ gen_date }}</div>
+</div>
+
+<div class="bar">
+    <div class="bar-centered">
+        <button class="bar-item" onclick="openBar(event, 'bench')">Benchmark Results</button>
+        <button class="bar-item" onclick="openBar(event, 'status')">Status</button>
+        <!-- <button class="bar-item" onclick="openBar(event, 'latency')">Latency</button> -->
+    </div>
+</div>
+
+<!-- Benchmarks -->
+{% macro bench_page(results, id_label) %}
+<div id="{{ id_label }}" class="barcontent">
+    <h5>{{ caller() }}</h5>
+    <hr>
+    <table class="ceph_status">
+        <tr class="node">
+            <td class="status">Time started</td>
+            <td class="status">Data point</td>
+            <td class="col_properties">
+                <div class="props_group">
+                    <div class="item prop">Warmup</div>
+                    <div class="item prop">Run Time</div>
+                    <div class="item prop">Storage class</div>
+                    <div class="item pg">PGs</div>
+                    <div class="item prop">Engine</div>
+                    <div class="item prop">Mode</div>
+                    <div class="item prop">BS</div>
+                    <div class="item prop">IOdepth</div>
+                    <div class="item prop">Size</div>
+                </div>
+            </td>
+            <td class="col_bench">
+                <div class="bench_run_group">
+                    <div class="item bench">Read, MB/s</div>
+                    <div class="item bench">Avg lat, usec</div>
+                    <div class="item bench">Read, op/s</div>
+                    <div class="item bench">Write, MB/s</div>
+                    <div class="item bench">Avg lat, usec</div>
+                    <div class="item bench">Write, op/s</div>
+                </div>
+            </td>
+        </tr>
+        {% for time,dt in results.items() %}
+        {% set t = dt["totals"] %}
+        {% set o = dt["input_options"] %}
+        {% set tstripped = time | tstrip %}
+        <tr class="node" onclick="toggleClassByID('timing_{{ tstripped }}_data')" id="timing_{{ tstripped }}_button">
+            <td class="status">{{ time }}</td>
+            <td class="status">All agents</td>
+            <td class="col_properties">
+                <div class="props_group">
+                    <div class="item prop">{{ o["ramp_time"] }}</div>
+                    <div class="item prop">{{ o["runtime"] }}</div>
+                    <div class="item prop">{{ t["storage_class"] }}</div>
+                    <div class="item pg">{{ t["storage_class_stats"]["num_pg"] }}</div>
+                    <div class="item prop">{{ o["ioengine"] }}</div>
+                    <div class="item prop">{{ o["readwrite"] }} ({{ o["rwmixread"] }}/{{ 100-o["rwmixread"] }})</div>
+                    <div class="item prop">{{ o["bs"] }}</div>
+                    <div class="item prop">{{ o["iodepth"] }}</div>
+                    <div class="item prop">{{ o["size"] }}</div>
+                </div>
+            </td>
+            <td class="col_bench">
+                <div class="bench_run_group">
+                    <div class="item bench">{{ t["read_bw_bytes"] | to_mb }}</div>
+                    <div class="item bench">{{ "%0.2f" | format(t["read_avg_lat_us"]|float) }}</div>
+                    <div class="item bench">{{ "%0.2f" | format(t["read_iops"]|float) }}</div>
+                    <div class="item bench">{{ t["write_bw_bytes"] | to_mb }}</div>
+                    <div class="item bench">{{ "%0.2f" | format(t["write_avg_lat_us"]|float) }}</div>
+                    <div class="item bench">{{ "%0.2f" | format(t["write_iops"]|float) }}</div>
+                </div>
+            </td>
+        </tr>
+        <tr class="collapsable" id="timing_{{ tstripped }}_data"><td colspan=3>
+            <div class="bc-wrap">
+                <div class="bctimecol">
+                 <div class="bctime"><span class="bctimetext">110</span></div>
+                 <div class="bctime"><span class="bctimetext">75</span></div>
+                 <div class="bctime"><span class="bctimetext">50</span></div>
+                 <div class="bctime"><span class="bctimetext">15</span></div>
+                </div>
+                   
+                <div class="bc-container">
+                 <div class="bc">
+                  <div class="bccol"><div class="bcbar" style="height: 75%;"></div><div class="bcfooter">2s</div></div>
+                  <div class="bccol"><div class="bcbar" style="height: 25%;"></div><div class="bcfooter">4s</div></div>
+                  <div class="bccol"><div class="bcbar" style="height: 55%;"></div><div class="bcfooter">6s</div></div>
+                  <div class="bccol"><div class="bcbar" style="height: 65%;"></div><div class="bcfooter">8s</div></div>
+                  <div class="bccol"><div class="bcbar" style="height: 15%;"></div><div class="bcfooter">10s</div></div>
+                  <div class="bccol"><div class="bcbar" style="height: 16%;"></div><div class="bcfooter">12s</div></div>
+                  <div class="bccol"><div class="bcbar" style="height: 17%;"></div><div class="bcfooter">14s</div></div>
+                  <div class="bccol"><div class="bcbar" style="height: 18%;"></div><div class="bcfooter">16s</div></div>
+                  <div class="bccol"><div class="bcbar" style="height: 19%;"></div><div class="bcfooter">18s</div></div>
+                  <div class="bccol"><div class="bcbar" style="height: 20%;"></div><div class="bcfooter">20s</div></div>
+                  <div class="bccol"><div class="bcbar" style="height: 21%;"></div><div class="bcfooter">22s</div></div>
+                 </div>
+                </div>
+            </div>
+            <table style="table-layout: auto;"><tbody>
+                {% for agent,ag_result in dt["agents"].items() %}
+                {% set j = ag_result[time]["jobs"][0] %}
+                <tr>
+                    <td class="status">{{ time }}</td>
+                    <td class="status">{{ agent }}</td>
+                    <td class="col_properties">
+                        <div class="props_group">
+                            <div class="item prop">{{ j["job options"]["ramp_time"] }}</div>
+                            <div class="item prop">{{ j["job options"]["runtime"] }}</div>
+                            <div class="item prop">{{ t["storage_class"] }}</div>
+                            <div class="item pg">{{ t["storage_class_stats"]["num_pg"] }}</div>
+                            <div class="item prop">{{ o["ioengine"] }}</div>
+                            <div class="item prop">{{ o["readwrite"] }} ({{ o["rwmixread"] }}/{{ 100-o["rwmixread"] }})</div>
+                            <div class="item prop">{{ j["job options"]["bs"] }}</div>
+                            <div class="item prop">{{ o["iodepth"] }}</div>
+                            <div class="item prop">{{ j["job options"]["size"] }}</div>
+                        </div>
+                    </td>
+                    <td class="col_bench">
+                        <div class="bench_run_group">
+                            <div class="item bench">{{ j["read"]["bw_bytes"] | to_mb }}</div>
+                            <div class="item bench">{{ "%0.2f" | format(j["read"]["lat_ns"]["mean"]|float / 1000) }}</div>
+                            <div class="item bench">{{ "%0.2f" | format(j["read"]["iops"]|float) }}</div>
+                            <div class="item bench">{{ j["write"]["bw_bytes"] | to_mb }}</div>
+                            <div class="item bench">{{ "%0.2f" | format(j["write"]["lat_ns"]["mean"]|float / 1000) }}</div>
+                            <div class="item bench">{{ "%0.2f" | format(j["write"]["iops"]|float) }}</div>
+                        </div>
+                    </td>
+                </tr>
+                        </tr>
+                {% endfor %}
+            </tbody></table>
+        </td></tr>
+        {% endfor %}
+    </table>
+</div>
+{% endmacro %}
+
+<!-- Status page -->
+{% macro status_page(info, id_label) %}
+<div id="{{ id_label }}" class="barcontent">
+    <h5>{{ caller() }}</h5>
+    <hr>
+    <table class="ceph_status">
+        <tr class="node">
+            <td class="status">Cluster status</td>
+            <td class="col_shortmessage">Status summary</td>
+            <td class="col_osd">
+                <div class="osd_group">
+                    <div class="item osd">OSDs</div>
+                    <div class="item osd">Up</div>
+                    <div class="item osd">In</div>
+                    <div class="item osd">Remap PGs</div>
+                </div>
+            </td>
+            <td class="col_pgs">
+                <div class="pg_group">
+                    <div class="item pg">PGs</div>
+                    <div class="item pg">Pools</div>
+                    <div class="item pg">Objects</div>
+                    <div class="item pg">Data, GB</div>
+                    <div class="item pg">Used, GB</div>
+                    <div class="item pg">Avail, GB</div>
+                    <div class="item pg">Total, GB</div>
+                </div>
+            </td>
+            <td class="col_bench">
+                <div class="bench_group">
+                    <div class="item bench">Read, MB/sec</div>
+                    <div class="item bench">Write, MB/sec</div>
+                    <div class="item bench">Read, op/sec</div>
+                    <div class="item bench">Write, op/sec</div>
+                </div>
+            </td>
+        </tr>
+        {% set cs = idle_status %}
+        {% set osdmap = cs | get_osdmap %}
+        <tr class="node" onclick="toggleClassByID('health_data')" id="health_data_button">
+            <td class="status {{ health_detail["status"] | lower }}">{{ health_detail["status"] }}</td>
+            <td class="col_shortmessage">
+                {% for code,dt in health_detail["checks"].items() %}
+                {{ dt["summary"]["message"] }}<br>
+                {% endfor %}
+            </td>
+            <!-- background: linear-gradient(to right, gray 0% 20%, transparent 20% 100%); -->
+            <td class="col_osd">
+                <div class="osd_group">
+                    <div class="item osd">{{ osdmap["num_osds"] }}</div>
+                    <div class="item osd">{{ osdmap["num_up_osds"] }}</div>
+                    <div class="item osd">{{ osdmap["num_in_osds"] }}</div>
+                    <div class="item osd">{{ osdmap["num_remapped_pgs"] }}</div>
+                </div>
+            </td>
+            {% set pgmap = cs["pgmap"] %}
+            <td class="col_pgs">
+                <div class="pg_group">
+                    <div class="item pg">{{ pgmap["num_pgs"] }}</div>
+                    <div class="item pg">{{ pgmap["num_pools"] }}</div>
+                    <div class="item pg">{{ pgmap["num_objects"] }}</div>
+                    <div class="item pg">{{ pgmap["data_bytes"] | to_gb }}</div>
+                    <div class="item pg">{{ pgmap["bytes_used"] | to_gb }}</div>
+                    <div class="item pg">{{ pgmap["bytes_avail"] | to_gb }}</div>
+                    <div class="item pg">{{ pgmap["bytes_total"] | to_gb }}</div>
+                </div>
+            </td>
+            <td class="col_bench">
+                <div class="bench_group">
+                    {% if "read_bytes_sec" in pgmap %}
+                    <div class="item bench">{{ pgmap["read_bytes_sec"] | to_mb }}</div>
+                    {% else %}
+                    <div class="item bench">0</div>
+                    {% endif %}
+                    {% if "write_bytes_sec" in pgmap %}
+                    <div class="item bench">{{ pgmap["write_bytes_sec"] | to_mb }}</div>
+                    {% else %}
+                    <div class="item bench">0</div>
+                    {% endif %}
+                    {% if "read_op_per_sec" in pgmap %}
+                    <div class="item bench">{{ pgmap["read_op_per_sec"] }}</div>
+                    {% else %}
+                    <div class="item bench">0</div>
+                    {% endif %}
+                    {% if "write_op_per_sec" in pgmap %}
+                    <div class="item bench">{{ pgmap["write_op_per_sec"] }}</div>
+                    {% else %}
+                    <div class="item bench">0</div>
+                    {% endif %}
+                </div>
+            </td>
+        </tr>
+        <tr class="collapsable in" id="health_data"><td colspan=3>
+            <table><tbody>
+                {% for code,dt in health_detail["checks"].items() %}
+                <tr>
+                    <td class="spacer"></td>
+                    <td class="status {{ dt["severity"] | lower }}">{{ dt["severity"] }}</td>
+                    <td class="checks_code">{{ code }}</td>
+                    <td class="col_longmessage">
+                        <table><tbody>
+                            {% for detail in dt["detail"] %}
+                            <tr><td>{{ detail["message"] }}</td></tr>
+                            {% endfor %}
+                        </tbody></table>
+                    </td>
+                </tr>
+                {% endfor %}
+            </tbody></table>
+        </td></tr>
+    </table>
+    <hr>
+    <!-- Services -->
+    {% set sm = idle_status["servicemap"] %}
+    <h5>Services: {{ sm["services"] | count }} running. Last modification: {{ sm["modified"] }}</h5>
+    <table class="ceph_status">
+        <tr class="node">
+            <td class="srv_name">Name</td>
+            <td class="srv_path">Subpath</td>
+            <td class="srv_timestamp">Start time</td>
+            <td class="srv_addr">Address</td>
+        </tr>
+        {% for name, d1 in sm["services"].items() %}
+        {% if "daemons" in d1 %}
+            {% set d2 = d1["daemons"] %}
+            {% for key, d3 in d2.items() %}
+                {% if key.startswith("rgw.store") %}
+        <tr class="node" onclick="toggleClassByID('{{ name }}_service_data')" id="{{ name }}_service_data_button">
+            <td class="srv_name">{{ name }} ({{ d3["gid"] }})</td>
+            <td class="srv_path">daemons:{{ key }}</td>
+            <td class="srv_timestamp">{{ d3["start_stamp"] }}</td>
+            <td class="srv_addr">{{ d3["addr"] }}</td>
+        </tr>
+        <tr class="collapsable in" id="{{ name}}_service_data"><td colspan=4>
+            <table><tbody>
+                <tr><td class="metadata">
+                {% for mname, mvalue in d3["metadata"].items() %}
+                    <div class="meta_group">
+                        <div class="item meta_name">{{ mname }}</div>
+                        <div class="item meta_value">{{ mvalue }}</div>
+                    </div>
+                {% endfor %}
+                </td></tr>
+            </tbody></table>
+        </td></tr>
+                {% endif %}
+            {% endfor %}
+        {% endif %}
+        {% endfor %}
+    </table>
+    <hr>
+    <!-- Modules -->
+    {% set mgrmap = idle_status["mgrmap"] %}
+    {% set mods = mgrmap["modules"] %}
+    {% set avail = mgrmap["available_modules"] %}
+    {% if "always_on_modules" in mgrmap %}
+    {% set always_on = mgrmap["always_on_modules"].values() | list %}
+    {% set always_on = always_on[0] %}
+    {% else %}
+    {% set always_on = [] %}
+    {% endif %}
+    <h5>Modules: {{ mods | count}} active. {{ always_on | count }} always on. {{ avail | count }} available.</h5>
+    <div class="modules">
+        <div class="module_grid">
+            {% for mod in avail %}
+                {% if mod["name"] in always_on %}
+                <div class="module always">{{ mod["name"] }}</div>
+                {% elif mod["name"] in mods %}
+                <div class="module on">{{ mod["name"] }}</div>
+                {% elif not mod["can_run"] %}
+                <div class="module fail tooltip">
+                    <div class="module fail">{{ mod["name"] }}</div>
+                    <pre class="tooltiptext">{{ mod["error_string"] | linebreaks }}</pre>
+                </div>
+                {% else %}
+                <div class="module">{{ mod["name"] }}</div>
+                {% endif %}
+            {% endfor %}
+        </div>
+    </div>
+    <hr>
+</div>
+{% endmacro %}
+
+<!-- ================================= -->
+<!-- Cluster nodes page -->
+{% call bench_page(results, "bench") %}
+    Benchmark results
+{% endcall %}
+
+{% call status_page(info, "status") %}
+    Cluster status
+{% endcall %}
+
+</body>
+</html>
\ No newline at end of file
diff --git a/templates/cfgagent-template.yaml b/templates/cfgagent-template.yaml
index 3152c5f..86c58e6 100644
--- a/templates/cfgagent-template.yaml
+++ b/templates/cfgagent-template.yaml
@@ -5,13 +5,14 @@
   namespace: qa-space
   labels:
     name: cfgagent-xx
+    app: cfgagent
 spec:
   containers:
   - command:
     - checker-agent
     imagePullPolicy: IfNotPresent
     name: cfgagent-pod
-    image: savex13/cfg-checker-agent:0.64
+    image: savex13/cfg-checker-agent:0.65
     volumeMounts:
     - mountPath: /cephvol
       name: cfgagent-pv-placeholder