Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -250,56 +250,39 @@

<script type="text/x-dust-template" id="tmpl-snapshot">
<div class="page-header"><h1>Snapshot Summary</h1></div>
<div class="page-header"><h1><small>Snapshottable directories: {@size key=SnapshottableDirectories}{/size}</small></div>
<div class="snapshot-stats"><h2><small>Snapshottable Directories: {@size key=SnapshottableDirectories}{/size}</small></div>
<div class="snapshot-stats"><h2><small>Total Snapshots: {@size key=Snapshots}{/size}</small></div>
<small>
<table class="table">
<table class="table" id="table-snapshots">
<thead>
<tr>
<th></th>
<th>Path</th>
<th>Snapshot Number</th>
<th>Snapshots Count</th>
<th>Snapshot Quota</th>
<th>Modification Time</th>
<th>Permission</th>
<th>Owner</th>
<th>Group</th>
</tr>
</thead>
{#SnapshottableDirectories}
<tr>
<td>{path}</td>
<td>{snapshotNumber}</td>
<td>{snapshotQuota}</td>
<td>{modificationTime|date_tostring}</td>
<td>{permission|helper_to_permission}</td>
<td>{owner}</td>
<td>{group}</td>
</tr>
{/SnapshottableDirectories}
</table>
</small>

<div class="page-header"><h1><small>Snapshots: {@size key=Snapshots}{/size}</small></div>

<small>
<table class="table">
<thead>
<tbody>
{#SnapshottableDirectories}
<tr>
<th>Snapshot ID</th>
<th>Snapshot Directory</th>
<th>Modification Time</th>
<th>Status</th>
<td class="details-control"></td>
<td ng-value="{path}">{path}</td>
<td ng-value="{snapshotNumber}">{snapshotNumber}</td>
<td ng-value="{snapshotQuota}">{snapshotQuota}</td>
<td ng-value="{modificationTime}">{modificationTime|date_tostring}</td>
<td>{permission|helper_to_permission}</td>
<td ng-value="{owner}">{owner}</td>
<td ng-value="{group}">{group}</td>
</tr>
</thead>
{#Snapshots}
<tr>
<td>{snapshotID}</td>
<td>{snapshotDirectory}</td>
<td>{modificationTime|date_tostring}</td>
<td>{status}</td>
</tr>
{/Snapshots}
{/SnapshottableDirectories}
</tbody>
</table>
</small>

</script>

<script type="text/x-dust-template" id="tmpl-datanode">
Expand Down
117 changes: 117 additions & 0 deletions hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/hdfs/dfshealth.js
Original file line number Diff line number Diff line change
Expand Up @@ -429,10 +429,127 @@
dust.render('snapshot-info', resp.beans[0], function(err, out) {
$('#tab-snapshot').html(out);
$('#ui-tabs a[href="#tab-snapshot"]').tab('show');

// Build a map to store snapshottable directory -> snapshots
var snapshots = 'Snapshots' in resp.beans[0] ? resp.beans[0].Snapshots : [];
var snapshotsMap = snapshots.reduce(function(result, snapshot) {
var rootPath = snapshot.snapshotDirectory.substr(0, snapshot.snapshotDirectory.indexOf(".snapshot") -1 );
if (rootPath in result) {
var arr = result[rootPath];
arr.push(snapshot);
result[rootPath] = arr;
} else {
result[rootPath] = [snapshot];
}
return result;
}, {});

var table = $('#table-snapshots').DataTable( {
'lengthMenu': [ [25, 50, 100, -1], [25, 50, 100, "All"] ],
'columns': [
{ 'orderable': false, 'searchable': false, 'data': null, 'defaultContent': "" },
{ 'data': 'path', 'orderDataType': 'ng-value', 'searchable': true , 'type': 'string', 'defaultContent': "" },
{ 'data': 'snapshotNumber', 'orderDataType': 'ng-value', 'searchable': false , 'type': 'num', 'defaultContent': 0 },
{ 'data': 'snapshotQuota', 'orderDataType': 'ng-value', 'searchable': false , 'type': 'num', 'defaultContent': 0 },
{ 'data': 'modificationTime', 'orderDataType': 'ng-value', 'searchable': false , 'type': 'string', 'defaultContent': "" },
{ 'data': 'permission', 'orderable': false, 'searchable': false , 'type': 'string', 'defaultContent': "" },
{ 'data': 'owner', 'orderDataType': 'ng-value', 'searchable': true , 'type': 'string', 'defaultContent': "" },
{ 'data': 'group', 'orderDataType': 'ng-value', 'searchable': true , 'type': 'string', 'defaultContent': "" }
],
'order': [[ 1, 'asc' ]]
});
// Add event listener for opening and closing details
$('#table-snapshots tbody').on('click', 'td.details-control', function () {
var tr = $(this).closest('tr');
var row = table.row( tr );

if ( row.child.isShown() ) {
// This row is already open - close it
row.child.hide();
tr.removeClass('shown');
}
else {
// Open this row
row.child( formatExpandedRow(row.data(), snapshotsMap) ).show();
var tableId = getSubTableId(row.data());
if (!$.fn.dataTable.isDataTable('#'+tableId)) {
$('#' + tableId).DataTable({
'lengthMenu': [[25, 50, 100, -1], [25, 50, 100, "All"]],
'columns': [
{
'orderDataType': 'ng-value',
'searchable': true,
'type': 'num',
'defaultContent': 0
},
{
'orderDataType': 'ng-value',
'searchable': true,
'type': 'string',
'defaultContent': ""
},
{
'orderDataType': 'ng-value',
'searchable': true,
'type': 'string',
'defaultContent': ""
},
{
'orderDataType': 'ng-value',
'searchable': true,
'type': 'string',
'defaultContent': ""
}
],
'order': [[0, 'asc']]
});
}
tr.addClass('shown');
}
});
});
})).fail(ajax_error_handler);
}

function getSubTableId(row) {
var path = row.path;
// replace all "/" with "-"
path = path.replace(/\//g, '-');
return "table-snapshots"+path;
}

function formatExpandedRow (row, snapshotsMap) {
// `row` is the original data object for the row
var tableId = getSubTableId(row);
var path = row.path;
var snapshots = snapshotsMap[path];
if (!snapshots || snapshots.length === 0) {
return 'No snapshots found for this path';
}
var tbody = snapshots.reduce(function(result, snapshot) {
var html = '<tr>'+
'<td ng-value="'+snapshot.snapshotID+'">'+ snapshot.snapshotID +'</td>'+
'<td ng-value="'+snapshot.snapshotDirectory+'">'+ snapshot.snapshotDirectory +'</td>'+
'<td ng-value="'+snapshot.modificationTime+'">'+ moment(Number(snapshot.modificationTime)).format('ddd MMM DD HH:mm:ss ZZ YYYY') +'</td>'+
'<td ng-value="'+snapshot.status+'">'+ snapshot.status +'</td>'+
'</tr>';
return result + html;
}, "");
return '<table class="table sub-table" id='+ tableId +'>'+
'<thead>'+
'<tr>'+
'<th>Snapshot ID</th>'+
'<th>Snapshot Directory</th>'+
'<th>Modification Time</th>' +
'<th>Status</th>' +
'</tr>'+
'</thead>'+
'<tbody>'+
tbody +
'</tbody>'+
'</table>';
}

function load_page() {
var hash = window.location.hash;
switch(hash) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -369,4 +369,35 @@ header.bs-docs-nav, header.bs-docs-nav .navbar-brand {
.bar text {
fill: #fff;
font: 10px sans-serif;
}
}

td.details-control:before {
color: #5fa341;
content: "\2b";
cursor: pointer;
font-size: 1.5em;
line-height: 1em;
}

tr.shown td.details-control:before {
color: #c7254e;
content: "\2212";
cursor: pointer;
font-size: 1.5em;
line-height: 1em;
}

#table-snapshots_wrapper {
margin-top: 20px;
}

table#table-snapshots>tbody>tr>td>.dataTables_wrapper {
padding-left: 50px;
padding-right: 10px;
padding-top: 10px;
background-color: #ddd;
}

.snapshot-stats>h2 {
margin: 0;
}