http://git-wip-us.apache.org/repos/asf/eagle/blob/c32b7152/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/ctrls/overview.js
----------------------------------------------------------------------
diff --git 
a/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/ctrls/overview.js 
b/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/ctrls/overview.js
new file mode 100644
index 0000000..6e7df0b
--- /dev/null
+++ 
b/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/ctrls/overview.js
@@ -0,0 +1,298 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function () {
+       /**
+        * `register` without params will load the module which using require
+        */
+       register(function (hadoopMetricApp) {
+               hadoopMetricApp.controller("overviewCtrl", function ($q, 
$wrapState, $scope, PageConfig, METRIC, Time) {
+                       var cache = {};
+                       $scope.site = $wrapState.param.siteId;
+                       var activeMasterInfo = METRIC.hbaseMaster($scope.site, 
"active", 1);
+
+                       PageConfig.title = 'HBase';
+                       var storageOption = {
+                               animation: false,
+                               tooltip: {
+                                       formatter: function (points) {
+                                               return points[0].name + "<br/>" 
+
+                                                       $.map(points, function 
(point) {
+                                                               return '<span 
style="display:inline-block;margin-right:5px;border-radius:10px;width:9px;height:9px;background-color:'
 + point.color + '"></span> ' +
+                                                                       
point.seriesName + ": " +
+                                                                       
common.number.abbr(point.value, true, 0);
+                                                       
}).reverse().join("<br/>");
+                                       }
+                               },
+                               yAxis: [{
+                                       axisLabel: {
+                                               formatter: function (value) {
+                                                       return 
common.number.abbr(value, true);
+                                               }
+                                       }
+                               }]
+                       };
+
+
+                       function generateHbaseMetric(name, flag) {
+                               var startTime = Time.startTime();
+                               var endTime = Time.endTime();
+                               var interval = Time.diffInterval(startTime, 
endTime);
+                               var intervalMin = interval / 1000 / 60;
+                               var trendStartTime = Time.align(startTime, 
interval);
+                               var trendEndTime = Time.align(endTime, 
interval);
+
+                               $scope.site = $wrapState.param.siteId;
+                               var result = cache[name] || 
activeMasterInfo._promise.then(function (res) {
+                                               var hostname = cache[hostname] 
= cache[hostname] || res[0].tags.hostname;
+                                               $scope.defaultHostname = 
$wrapState.param.hostname || hostname;
+
+                                               var jobCond = {
+                                                       site: $scope.site,
+                                                       component: 
"hbasemaster",
+                                                       host: 
$scope.defaultHostname
+                                               };
+                                               return 
METRIC.aggMetricsToEntities(METRIC.hbaseMetricsAggregation(jobCond, name, 
["site"], "avg(value)", intervalMin, trendStartTime, trendEndTime), flag)
+                                                       ._promise.then(function 
(list) {
+                                                               var metricFlag 
= $.map(list, function (metrics) {
+                                                                       return 
metrics[0].flag;
+                                                               });
+                                                               return 
[metricFlag, list];
+                                                       });
+                                       });
+                               return result;
+                       }
+
+                       function mergeMetricToOneSeries(metricTitle, metrics, 
legendName, dataOption, option) {
+                               var series = [];
+
+                               $.each(metrics, function (i, metricMap) {
+                                       if (typeof metricMap !== 'undefined') {
+                                               
series.push(METRIC.metricsToSeries(legendName[i], metricMap[0], option));
+                                       }
+                               });
+                               return {
+                                       title: metricTitle,
+                                       series: series,
+                                       option: dataOption || {},
+                                       loading: false
+                               };
+                       }
+
+                       function countHBaseRole(site, status, role, groups, 
filed, limit) {
+                               var jobCond = {
+                                       site: site,
+                                       status: status,
+                                       role: role
+                               };
+                               return METRIC.aggHBaseInstance(jobCond, groups, 
filed, limit);
+                       }
+
+                       function sumAllRegions(site, role, groups, filed, 
limit) {
+                               var jobCond = {
+                                       site: site,
+                                       role: role
+                               };
+                               return METRIC.aggHBaseInstance(jobCond, groups, 
filed, limit);
+                       }
+
+                       // TODO: Optimize the chart count
+                       // TODO: ECharts dynamic refresh series bug: 
https://github.com/ecomfe/echarts/issues/4033
+                       $scope.chartList = [
+                               {
+                                       name: "MemoryUsage",
+                                       metrics: ["nonheap", "heap"],
+                                       linename: ["nonheap", "heap"],
+                                       option: storageOption
+                               },
+                               {
+                                       name: "Master Averageload",
+                                       metrics: ["averageload"],
+                                       linename: ["averageload"],
+                                       option: {}
+                               },
+                               {
+                                       name: "Ritcount",
+                                       metrics: ["ritcount", 
"ritcountoverthreshold"],
+                                       linename: ["ritcount", 
"ritcountoverthreshold"],
+                                       option: {}
+                               },
+                               {
+                                       name: "AssignOpsNum",
+                                       metrics: ["AssignNumOps"],
+                                       linename: ["numOps"],
+                                       option: {}
+                               },
+                               {
+                                       name: "Assign",
+                                       metrics: ["AssignMin", "AssignMax", 
"AssignPercentile75th", "AssignPercentile95th", "AssignPercentile99th"],
+                                       linename: ["min", "max", "75th", 
"95th", "99th"],
+                                       option: {}
+                               },
+                               {
+                                       name: "BulkAssignOpsNum",
+                                       metrics: ["BulkAssignNum_ops"],
+                                       linename: ["num_ops"],
+                                       option: {}
+                               },
+                               {
+                                       name: "BulkAssign",
+                                       metrics: ["BulkAssignMin", 
"BulkAssignMax", "BulkAssignPercentile75th", "BulkAssignPercentile95th", 
"BulkAssignPercentile99th"],
+                                       linename: ["min", "max", "75th", 
"95th", "99th"],
+                                       option: {}
+                               },
+                               {
+                                       name: "BalancerClusterOpsNum",
+                                       metrics: ["BalancerClusterNum_ops"],
+                                       linename: ["num_ops"],
+                                       option: {}
+                               },
+                               {
+                                       name: "BalancerCluster",
+                                       metrics: ["BalancerClusterMin", 
"BalancerClusterMax", "BalancerClusterPercentile75th", 
"BalancerClusterPercentile95th", "BalancerClusterPercentile99th"],
+                                       linename: ["min", "max", "75th", 
"95th", "99th"],
+                                       option: {}
+                               },
+                               {
+                                       name: "HlogSplitTime",
+                                       metrics: ["HlogSplitTimeMin", 
"HlogSplitTimeMax"],
+                                       linename: ["HlogSplitTime_min", 
"HlogSplitTime_max"],
+                                       option: {}
+                               },
+                               {
+                                       name: "HlogSplitTime Percentile",
+                                       metrics: 
["HlogSplitTimePercentile75th", "HlogSplitTimePercentile95th", 
"HlogSplitTimePercentile99th"],
+                                       linename: ["75th", "95th", "99th"],
+                                       option: {}
+                               },
+                               {
+                                       name: "HlogSplitSize",
+                                       metrics: 
["HlogSplitSizeMin","HlogSplitSizeMax"],
+                                       linename: ["Min", "Max"],
+                                       option: {}
+                               },
+                               {
+                                       name: "MetaHlogSplitTime",
+                                       metrics: ["MetaHlogSplitTimeMin", 
"MetaHlogSplitTimeMax"],
+                                       linename: ["Min", "Max"],
+                                       option: {}
+                               },
+                               {
+                                       name: "MetaHlogSplitTime Percentile",
+                                       metrics: 
["MetaHlogSplitTimePercentile75th", "MetaHlogSplitTimePercentile95th", 
"MetaHlogSplitTimePercentile99th"],
+                                       linename: ["75th", "95th", "99th"],
+                                       option: {}
+                               },
+                               {
+                                       name: "MetaHlogSplitSize",
+                                       metrics: ["MetaHlogSplitSizeMin", 
"MetaHlogSplitSizeMax"],
+                                       linename: ["Min", "Max"],
+                                       option: {}
+                               }
+                       ];
+                       $scope.metricList = [];
+                       $.each($scope.chartList, function (i) {
+                               var chart = $scope.chartList[i];
+                               var chartname = chart.name;
+                               $scope.metricList[chartname] = {
+                                       title: chartname,
+                                       series: {},
+                                       option: {},
+                                       loading: true,
+                                       promises: []
+                               };
+                       });
+                       $scope.refresh = function () {
+
+                               METRIC.getMetricObj().then(function (res) {
+                                       var masterMetricList = res.master;
+                                       $.each($scope.chartList, function (i) {
+                                               var chart = $scope.chartList[i];
+                                               var metricList = chart.metrics;
+                                               $.each(metricList, function (j) 
{
+                                                       var metricKey = 
metricList[j];
+                                                       var metricspromies = 
generateHbaseMetric(masterMetricList[metricKey], metricKey);
+                                                       var chartname = 
chart.name;
+                                                       
$scope.metricList[chartname].promises.push(metricspromies);
+                                               });
+                                       });
+
+                                       $.each($scope.chartList, function (k) {
+                                               var chart = $scope.chartList[k];
+                                               var chartname = chart.name;
+                                               
$q.all($scope.metricList[chartname].promises).then(function (resp) {
+                                                       var series = [];
+                                                       for (var r = 0; r < 
resp.length; r += 1) {
+                                                               var rs = 
resp[r][1];
+                                                               if (rs.length > 
0) {
+                                                                       
series.push(rs);
+                                                               }
+                                                       }
+                                                       
$scope.metricList[chartname] = mergeMetricToOneSeries(chartname, series, 
chart.linename, chart.option);
+                                               });
+                                       });
+                               });
+
+                               countHBaseRole($scope.site, "active", 
"hmaster", ["site"], "count")._promise.then(function (res) {
+                                       $.map(res, function (data) {
+                                               $scope.hmasteractivenum = 
data.value[0];
+                                       });
+                               });
+                               countHBaseRole($scope.site, "standby", 
"hmaster", ["site"], "count")._promise.then(function (res) {
+                                       $.map(res, function (data) {
+                                               $scope.hmasterstandbynum = 
data.value[0];
+                                       });
+                               });
+
+                               countHBaseRole($scope.site, "live", 
"regionserver", ["site"], "count")._promise.then(function (res) {
+                                       $.map(res, function (data) {
+                                               $scope.regionserverhealtynum = 
data.value[0];
+                                       });
+                               });
+                               countHBaseRole($scope.site, "dead", 
"regionserver", ["site"], "count")._promise.then(function (res) {
+                                       $.map(res, function (data) {
+                                               $scope.regionserverunhealtynum 
= data.value[0];
+                                       });
+                               });
+                               sumAllRegions($scope.site, "regionserver", 
["site"], "sum(numRegions)")._promise.then(function (res) {
+                                       $.map(res, function (data) {
+                                               $scope.regionsnum = 
data.value[0];
+                                       });
+                               });
+
+                               activeMasterInfo._promise.then(function (res) {
+                                       var hostname = cache[hostname] = 
cache[hostname] || res[0].tags.hostname;
+                                       $scope.defaultHostname = 
$wrapState.param.hostname || hostname;
+                                       var jobCond = {
+                                               site: $scope.site,
+                                               component: "hbasemaster",
+                                               host: $scope.defaultHostname
+                                       };
+                                       METRIC.hbaseMomentMetric(jobCond, 
"hadoop.hbase.master.server.averageload", 1).then(function (res) {
+                                               $scope.hmasteraverageload = 
(typeof res.data.obj[0] !== 'undefined') ? res.data.obj[0].value[0] : "-1";
+                                       });
+                               });
+                       };
+                       Time.onReload(function () {
+                               cache = {};
+                               $scope.refresh();
+                       }, $scope);
+                       $scope.refresh();
+               });
+       });
+})();

http://git-wip-us.apache.org/repos/asf/eagle/blob/c32b7152/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/ctrls/regionDetailCtrl.js
----------------------------------------------------------------------
diff --git 
a/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/ctrls/regionDetailCtrl.js
 
b/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/ctrls/regionDetailCtrl.js
new file mode 100644
index 0000000..838b3a2
--- /dev/null
+++ 
b/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/ctrls/regionDetailCtrl.js
@@ -0,0 +1,306 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function () {
+       /**
+        * `register` without params will load the module which using require
+        */
+       register(function (hadoopMetricApp) {
+               hadoopMetricApp.controller("regionDetailCtrl", function ($q, 
$wrapState, $scope, PageConfig, Time, METRIC) {
+                       var cache = {};
+                       $scope.site = $wrapState.param.siteId;
+                       $scope.hostname = $wrapState.param.hostname;
+                       PageConfig.title = 'RegionServer ' + "(" + 
$scope.hostname + ")";
+                       Time.autoRefresh = false;
+
+                       var sizeoption = {
+                               animation: false,
+                               tooltip: {
+                                       formatter: function (points) {
+                                               return points[0].name + "<br/>" 
+
+                                                       $.map(points, function 
(point) {
+                                                               return '<span 
style="display:inline-block;margin-right:5px;border-radius:10px;width:9px;height:9px;background-color:'
 + point.color + '"></span> ' +
+                                                                       
point.seriesName + ": " +
+                                                                       
common.number.abbr(point.value, true);
+                                                       
}).reverse().join("<br/>");
+                                       }
+                               },
+                               legend: {
+                                       x: 'center', y: 'bottom'
+                               },
+                               areaStyle: {normal: {}},
+                               yAxis: [{
+                                       axisLabel: {
+                                               formatter: function (value) {
+                                                       return 
common.number.abbr(value, true);
+                                               }
+                                       }
+                               }]
+                       };
+                       var digitalOption = {
+                               animation: false,
+                               tooltip: {
+                                       formatter: function (points) {
+                                               return points[0].name + "<br/>" 
+
+                                                       $.map(points, function 
(point) {
+                                                               return '<span 
style="display:inline-block;margin-right:5px;border-radius:10px;width:9px;height:9px;background-color:'
 + point.color + '"></span> ' +
+                                                                       
point.seriesName + ": " +
+                                                                       
common.number.abbr(point.value, false, 0);
+                                                       
}).reverse().join("<br/>");
+                                       }
+                               },
+                               yAxis: [{
+                                       axisLabel: {
+                                               formatter: function (value) {
+                                                       return 
common.number.abbr(value, false);
+                                               }
+                                       }
+                               }]
+                       };
+
+                       var gctimeoption = {
+                               legend: {
+                                       x: 'center', y: 'bottom'
+                               },
+                               yAxis: [{
+                                       axisLabel: {
+                                               formatter: function (value) {
+                                                       return value / 1000 + ' 
S';
+                                               }
+                                       }
+                               }]
+                       };
+                       $scope.chartList = [
+                               {
+                                       name: "Memory Usage",
+                                       metrics: ["nonheap", "heap"],
+                                       option: sizeoption
+                               },
+                               {
+                                       name: "Direct Memory Usage",
+                                       metrics: ["directmemory"],
+                                       option: sizeoption
+                               },
+                               {
+                                       name: "GC count",
+                                       metrics: ["GCCount"],
+                                       option: {}
+                               },
+                               {
+                                       name: "GC TimeMillis",
+                                       metrics: ["GCTimeMillis"],
+                                       option: gctimeoption
+                               },
+                               {
+                                       name: "QueueSize",
+                                       metrics: ["QueueSize"],
+                                       option: {}
+                               },
+                               {
+                                       name: "NumCallsInGeneralQueue",
+                                       metrics: ["NumCallsInGeneralQueue"],
+                                       option: {}
+                               },
+                               {
+                                       name: "NumActiveHandler",
+                                       metrics: ["NumActiveHandler"],
+                                       option: {}
+                               },
+                               {
+                                       name: "IPC Queue Time (99th)",
+                                       metrics: ["IPCQueueTime99th"],
+                                       option: {}
+                               },
+                               {
+                                       name: "IPC Process Time (99th)",
+                                       metrics: ["IPCProcessTime99th"],
+                                       option: {}
+                               },
+                               {
+                                       name: "QueueCallTime_num_ops",
+                                       metrics: ["QueueCallTime_num_ops"],
+                                       option: digitalOption
+                               },
+                               {
+                                       name: "ProcessCallTime_num_ops",
+                                       metrics: ["ProcessCallTime_num_ops"],
+                                       option: digitalOption
+                               },
+                               {
+                                       name: "RegionCount",
+                                       metrics: ["RegionCount"],
+                                       option: {}
+                               },
+                               {
+                                       name: "StoreCount",
+                                       metrics: ["StoreCount"],
+                                       option: {}
+                               },
+                               {
+                                       name: "MemStoreSize",
+                                       metrics: ["MemStoreSize"],
+                                       option: sizeoption
+                               },
+                               {
+                                       name: "StoreFileSize",
+                                       metrics: ["StoreFileSize"],
+                                       option: sizeoption
+                               },
+                               {
+                                       name: "SlitQueueLength",
+                                       metrics: ["SlitQueueLength"],
+                                       option: {}
+                               },
+                               {
+                                       name: "CompactionQueueLength",
+                                       metrics: ["CompactionQueueLength"],
+                                       option: {}
+                               },
+                               {
+                                       name: "FlushQueueLength",
+                                       metrics: ["FlushQueueLength"],
+                                       option: {}
+                               },
+                               {
+                                       name: "BlockCacheSize",
+                                       metrics: ["BlockCacheSize"],
+                                       option: sizeoption
+                               },
+                               {
+                                       name: "BlockCacheHitCount",
+                                       metrics: ["BlockCacheHitCount"],
+                                       option: {}
+                               },
+                               {
+                                       name: "BlockCacheCountHitPercent",
+                                       metrics: ["BlockCacheCountHitPercent"],
+                                       option: digitalOption
+                               },
+                               {
+                                       name: "TotalRequestCount",
+                                       metrics: ["TotalRequestCount"],
+                                       option: digitalOption
+                               },
+                               {
+                                       name: "ReadRequestCount",
+                                       metrics: ["ReadRequestCount"],
+                                       option: digitalOption
+                               },
+                               {
+                                       name: "WriteRequestCount",
+                                       metrics: ["WriteRequestCount"],
+                                       option: digitalOption
+                               }
+                       ];
+
+                       $scope.metricList = [];
+                       $.each($scope.chartList, function (i) {
+                               var chart = $scope.chartList[i];
+                               var chartname = chart.name;
+                               $scope.metricList[chartname] = {
+                                       title: chartname,
+                                       series: {},
+                                       option: {},
+                                       loading: true,
+                                       promises: []
+                               };
+                       });
+                       $scope.refresh = function () {
+                               var startTime = Time.startTime();
+                               var endTime = Time.endTime();
+
+                               METRIC.getMetricObj().then(function (res) {
+                                       var masterMetricList = res.regionserver;
+                                       $.each($scope.chartList, function (i) {
+                                               var chart = $scope.chartList[i];
+                                               var metricList = chart.metrics;
+                                               $.each(metricList, function (j) 
{
+                                                       var metricKey = 
metricList[j];
+                                                       var metricspromies = 
generateHbaseMetric(masterMetricList[metricKey], startTime, endTime, metricKey);
+                                                       var chartname = 
chart.name;
+                                                       
$scope.metricList[chartname].promises.push(metricspromies);
+                                               });
+                                       });
+
+                                       $.each($scope.chartList, function (k) {
+                                               var chart = $scope.chartList[k];
+                                               var chartname = chart.name;
+                                               
$q.all($scope.metricList[chartname].promises).then(function (resp) {
+                                                       var series = [];
+                                                       for (var r = 0; r < 
resp.length; r += 1) {
+                                                               var rs = 
resp[r][1];
+                                                               if (rs.length > 
0) {
+                                                                       
series.push(rs);
+                                                               }
+                                                       }
+                                                       
$scope.metricList[chartname] = mergeSeries(chartname, series, chart.metrics, 
chart.option);
+                                               });
+                                       });
+                               });
+
+                               METRIC.regionserverStatus($scope.hostname, 
$scope.site)._promise.then(function (res) {
+                                       $scope.regionstatus = res;
+                               });
+                       };
+                       Time.onReload(function () {
+                               cache = {};
+                               $scope.refresh();
+                       }, $scope);
+                       $scope.refresh();
+
+
+                       function generateHbaseMetric(name, startTime, endTime, 
flag) {
+                               var interval = Time.diffInterval(startTime, 
endTime);
+                               var intervalMin = interval / 1000 / 60;
+                               var trendStartTime = Time.align(startTime, 
interval);
+                               var trendEndTime = Time.align(endTime, 
interval);
+
+                               var condition = {
+                                       site: $scope.site,
+                                       component: "regionserver",
+                                       host: $scope.hostname
+                               };
+                               return 
METRIC.aggMetricsToEntities(METRIC.hbaseMetricsAggregation(condition, name, 
["site"], "avg(value)", intervalMin, trendStartTime, trendEndTime), flag)
+                                       ._promise.then(function (list) {
+                                               var metricFlag = $.map(list, 
function (metrics) {
+                                                       return metrics[0].flag;
+                                               });
+                                               return [metricFlag, list];
+                                       });
+                       }
+
+                       function mergeSeries(title, metrics, linename, option) {
+                               var series = [];
+                               $.each(metrics, function (i, metricMap) {
+                                       $.map(metricMap, function (metric) {
+                                               if (typeof metric !== 
'undefined') {
+                                                       
series.push(METRIC.metricsToSeries(linename[i], metric, option));
+                                               }
+                                       });
+                               });
+                               return {
+                                       title: title,
+                                       series: series,
+                                       option: option || {},
+                                       loading: false
+                               };
+                       }
+               });
+       });
+})
+();

http://git-wip-us.apache.org/repos/asf/eagle/blob/c32b7152/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/ctrls/regionListCtrl.js
----------------------------------------------------------------------
diff --git 
a/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/ctrls/regionListCtrl.js
 
b/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/ctrls/regionListCtrl.js
new file mode 100644
index 0000000..1477e32
--- /dev/null
+++ 
b/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/ctrls/regionListCtrl.js
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function () {
+       /**
+        * `register` without params will load the module which using require
+        */
+       register(function (hadoopMetricApp) {
+
+               hadoopMetricApp.controller("regionListCtrl", function 
($wrapState, $scope, PageConfig, METRIC) {
+
+                       // Initialization
+                       PageConfig.title = "HBASE RegionServers";
+                       $scope.tableScope = {};
+                       $scope.live = METRIC.STATUS_LIVE;
+                       $scope.dead = METRIC.STATUS_DEAD;
+                       $scope.site = $wrapState.param.siteId;
+                       $scope.searchPathList = [["tags", "hostname"], ["tags", 
"rack"], ["tags", "site"], ["status"]];
+                       $scope.regionserverList = 
METRIC.regionserverList($scope.site);
+
+               });
+       });
+})();

http://git-wip-us.apache.org/repos/asf/eagle/blob/c32b7152/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/index.html
----------------------------------------------------------------------
diff --git 
a/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/index.html 
b/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/index.html
new file mode 100644
index 0000000..454e3c6
--- /dev/null
+++ b/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/index.html
@@ -0,0 +1,6 @@
+<htm>
+    <body>
+    <h1>HBase Metric Monitor Application!</h1>
+    <i><b>url</b>: /apps/hbase</i>
+    </body>
+</htm>

http://git-wip-us.apache.org/repos/asf/eagle/blob/c32b7152/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/index.js
----------------------------------------------------------------------
diff --git 
a/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/index.js 
b/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/index.js
new file mode 100644
index 0000000..c6b5135
--- /dev/null
+++ b/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/index.js
@@ -0,0 +1,329 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function () {
+       /**
+        * `register` is global function that for application to set up 
'controller', 'service', 'directive', 'route' in Eagle
+        */
+       var hadoopMetricApp = register(['ngRoute', 'ngAnimate', 'ui.router', 
'eagle.service']);
+
+       hadoopMetricApp.route("HBaseMetric", {
+               url: "/hadoopService/HBase/overview?startTime&endTime",
+               site: true,
+               templateUrl: "partials/overview.html",
+               controller: "overviewCtrl",
+               resolve: {time: true}
+       }).route("regionDetail", {
+               url: "/hadoopService/HBase/regionDetail/:hostname",
+               site: true,
+               templateUrl: "partials/region/regionDetail.html",
+               controller: "regionDetailCtrl",
+               resolve: {time: true}
+       }).route("regionList", {
+               url: "/hadoopService/HBase/regionList",
+               site: true,
+               templateUrl: "partials/region/regionList.html",
+               controller: "regionListCtrl"
+       }).route("backupMasterList", {
+               url: "/hadoopService/HBase/backupMasterList",
+               site: true,
+               templateUrl: "partials/backupMasterList.html",
+               controller: "backupMasterListCtrl"
+       }).route("masterDetail", {
+               url: "/hadoopService/HBase/:hostname?startTime&endTime",
+               site: true,
+               reloadOnSearch: false,
+               templateUrl: "partials/overview.html",
+               controller: "overviewCtrl",
+               resolve: {time: true}
+       });
+
+       hadoopMetricApp.portal({
+               name: "Services", icon: "heartbeat", list: [
+                       {name: "HBase", path: "hadoopService/HBase/overview"}
+               ]
+       }, true);
+
+       hadoopMetricApp.service("METRIC", function ($q, $http, Time, Site, 
Application) {
+               var METRIC = window._METRIC = {};
+               METRIC.STATUS_LIVE = "live";
+               METRIC.STATUS_DEAD = "dead";
+               METRIC.QUERY_HBASE_METRICS = 
'${baseURL}/rest/entities?query=GenericMetricService[${condition}]{*}&metricName=${metric}&pageSize=${limit}';
+               METRIC.QUERY_HBASE_METRICS_WITHTIME = 
'${baseURL}/rest/entities?query=GenericMetricService[${condition}]{*}&metricName=${metric}&pageSize=${limit}&startTime=${startTime}&endTime=${endTime}';
+               METRIC.QUERY_HBASE_INSTANCE = 
'${baseURL}/rest/entities?query=HbaseServiceInstance[${condition}]{*}&pageSize=${limit}';
+               METRIC.QUERY_HBASE_INSTANCE_AGG = 
"${baseURL}/rest/entities?query=HbaseServiceInstance[${condition}]<${groups}>{${field}}&pageSize=${limit}";
+               METRIC.QUERY_HBASE_METRICS_INTERVAL = 
'${baseURL}/rest/entities?query=GenericMetricService[${condition}]<${groups}>{${field}}${order}${top}&metricName=${metric}&pageSize=${limit}&startTime=${startTime}&endTime=${endTime}&intervalmin=${intervalMin}&timeSeries=true';
+               /**
+                * Fetch query content with current site application 
configuration
+                * @param {string} queryName
+                */
+               var getQuery = METRIC.getQuery = function (queryName, siteId) {
+                       var baseURL;
+                       siteId = siteId || Site.current().siteId;
+                       var app = Application.find("HBASE_METRIC_WEB_APP", 
siteId)[0];
+                       var host = app.configuration["service.host"];
+                       var port = app.configuration["service.port"];
+
+                       if (!host && !port) {
+                               baseURL = "";
+                       } else {
+                               if (host === "localhost" || !host) {
+                                       host = location.hostname;
+                               }
+                               if (!port) {
+                                       port = location.port;
+                               }
+                               baseURL = "http://"; + host + ":" + port;
+                       }
+
+                       return common.template(METRIC["QUERY_" + queryName], 
{baseURL: baseURL});
+               };
+
+               function wrapList(promise) {
+                       var _list = [];
+                       _list._done = false;
+
+                       _list._promise = promise.then(
+                               /**
+                                * @param {{}} res
+                                * @param {{}} res.data
+                                * @param {{}} res.data.obj
+                                */
+                               function (res) {
+                                       _list.splice(0);
+                                       Array.prototype.push.apply(_list, 
res.data.obj);
+                                       _list._done = true;
+                                       return _list;
+                               });
+                       return _list;
+               }
+
+               function toFields(fields) {
+                       return (fields || []).length > 0 ? $.map(fields, 
function (field) {
+                               return "@" + field;
+                       }).join(",") : "*";
+               }
+
+               METRIC.metricsToSeries = function (name, metrics, option, 
rawData) {
+                       if (arguments.length === 4 && typeof rawData === 
"object") {
+                               option = rawData;
+                               rawData = false;
+                       }
+
+                       var data = $.map(metrics, function (metric) {
+                               return rawData ? metric.value[0] : {
+                                       x: metric.timestamp,
+                                       y: metric.value[0]
+                               };
+                       });
+                       return $.extend({
+                               name: name,
+                               showSymbol: false,
+                               type: "line",
+                               data: data
+                       }, option || {});
+               };
+
+               METRIC.get = function (url, params) {
+                       return $http({
+                               url: url,
+                               method: "GET",
+                               params: params
+                       });
+               };
+
+               METRIC.condition = function (condition) {
+                       return $.map(condition, function (value, key) {
+                               return "@" + key + '="' + value + '"';
+                       }).join(" AND ");
+               };
+
+
+               METRIC.hbaseMetrics = function (condition, metric, startTime, 
endTime, limit) {
+                       var config = {
+                               condition: METRIC.condition(condition),
+                               startTime: Time.format(startTime),
+                               endTime: Time.format(endTime),
+                               metric: metric,
+                               limit: limit || 10000
+                       };
+
+                       var metrics_url = 
common.template(getQuery("HBASE_METRICS_WITHTIME"), config);
+                       return wrapList(METRIC.get(metrics_url));
+               };
+
+               METRIC.hbaseMomentMetric = function (condition, metric, limit) {
+                       var config = {
+                               condition: METRIC.condition(condition),
+                               metric: metric,
+                               limit: limit || 10000
+                       };
+
+                       var metrics_url = 
common.template(getQuery("HBASE_METRICS"), config);
+                       return METRIC.get(metrics_url);
+               };
+
+               METRIC.aggHBaseInstance = function (condition, groups, field, 
limit) {
+                       var fields = field.split(/\s*,\s*/);
+                       var fieldStr = $.map(fields, function (field, index) {
+                               var matches = field.match(/^([^\s]*)(\s+.*)?$/);
+                               if (matches[2]) {
+                                       orderId = index;
+                               }
+                               return matches[1];
+                       }).join(", ");
+                       var config = {
+                               condition: METRIC.condition(condition),
+                               groups: toFields(groups),
+                               field: fieldStr,
+                               limit: limit || 10000
+                       };
+                       var metrics_url = 
common.template(getQuery("HBASE_INSTANCE_AGG"), config);
+                       return wrapList(METRIC.get(metrics_url));
+               };
+
+               METRIC.hbaseMetricsAggregation = function (condition, metric, 
groups, field, intervalMin, startTime, endTime, top, limit) {
+                       var fields = field.split(/\s*,\s*/);
+                       var orderId = -1;
+                       var fieldStr = $.map(fields, function (field, index) {
+                               var matches = field.match(/^([^\s]*)(\s+.*)?$/);
+                               if (matches[2]) {
+                                       orderId = index;
+                               }
+                               return matches[1];
+                       }).join(", ");
+
+
+                       var config = {
+                               condition: METRIC.condition(condition),
+                               startTime: Time.format(startTime),
+                               endTime: Time.format(endTime),
+                               metric: metric,
+                               groups: toFields(groups),
+                               field: fieldStr,
+                               order: orderId === -1 ? "" : ".{" + 
fields[orderId] + "}",
+                               top: top ? "&top=" + top : "",
+                               intervalMin: intervalMin,
+                               limit: limit || 10000
+                       };
+
+                       var metrics_url = 
common.template(getQuery("HBASE_METRICS_INTERVAL"), config);
+                       var _list = wrapList(METRIC.get(metrics_url));
+                       _list._aggInfo = {
+                               groups: groups,
+                               startTime: Time(startTime).valueOf(),
+                               interval: intervalMin * 60 * 1000
+                       };
+                       _list._promise.then(function () {
+                               _list.reverse();
+                       });
+                       return _list;
+               };
+
+               METRIC.aggMetricsToEntities = function (list, param, flatten) {
+                       var _list = [];
+                       _list.done = false;
+                       _list._promise = list._promise.then(function () {
+                               var _startTime = list._aggInfo.startTime;
+                               var _interval = list._aggInfo.interval;
+
+                               $.each(list, function (i, obj) {
+                                       var tags = {};
+                                       $.each(list._aggInfo.groups, function 
(j, group) {
+                                               tags[group] = obj.key[j];
+                                       });
+
+                                       var _subList = $.map(obj.value[0], 
function (value, index) {
+                                               return {
+                                                       timestamp: _startTime + 
index * _interval,
+                                                       value: [value],
+                                                       tags: tags,
+                                                       flag: param
+                                               };
+                                       });
+
+                                       if (flatten) {
+                                               _list.push.apply(_list, 
_subList);
+                                       } else {
+                                               _list.push(_subList);
+                                       }
+                               });
+                               _list.done = true;
+                               return _list;
+                       });
+                       return _list;
+               };
+
+
+               METRIC.hbasehostStatus = function (condition, limit) {
+                       var config = {
+                               condition: METRIC.condition(condition),
+                               limit: limit || 10000
+                       };
+
+                       var metrics_url = 
common.template(getQuery("HBASE_INSTANCE"), config);
+                       return wrapList(METRIC.get(metrics_url));
+               };
+
+               METRIC.hbaseMaster = function (siteId, status, limit) {
+                       var condition = {
+                               site: siteId,
+                               role: "hmaster",
+                               status: status
+                       };
+                       return METRIC.hbasehostStatus(condition, limit);
+               };
+
+               METRIC.regionserverStatus = function (hostname, siteid) {
+                       var hoststateinfo;
+                       var condition = {
+                               site: siteid,
+                               role: "regionserver",
+                               hostname: hostname
+                       };
+                       hoststateinfo = METRIC.hbasehostStatus(condition, 1);
+                       return hoststateinfo;
+               };
+
+               METRIC.regionserverList = function (siteid) {
+                       var hoststateinfos;
+                       var condition = {
+                               site: siteid,
+                               role: "regionserver"
+                       };
+                       hoststateinfos = METRIC.hbasehostStatus(condition);
+                       return hoststateinfos;
+               };
+
+               METRIC.getMetricObj = function () {
+                       var deferred = $q.defer();
+                       $http.get("apps/hbase/config.json").success(function 
(resp) {
+                               deferred.resolve(resp);
+                       });
+                       return deferred.promise;
+               };
+               return METRIC;
+       });
+
+       hadoopMetricApp.requireCSS("style/index.css");
+       hadoopMetricApp.require("widgets/availabilityChart.js");
+       hadoopMetricApp.require("ctrls/overview.js");
+       hadoopMetricApp.require("ctrls/regionDetailCtrl.js");
+       hadoopMetricApp.require("ctrls/regionListCtrl.js");
+       hadoopMetricApp.require("ctrls/backupMasterListCtrl.js");
+})();

http://git-wip-us.apache.org/repos/asf/eagle/blob/c32b7152/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/partials/backupMasterList.html
----------------------------------------------------------------------
diff --git 
a/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/partials/backupMasterList.html
 
b/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/partials/backupMasterList.html
new file mode 100644
index 0000000..13e20c9
--- /dev/null
+++ 
b/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/partials/backupMasterList.html
@@ -0,0 +1,52 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+<div class="box box-primary">
+       <div class="box-header with-border">
+               <h3 class="box-title">
+                       <span ng-show="!backupMasterList._done || isSorting" 
class="fa fa-refresh fa-spin no-animate"></span>
+               </h3>
+       </div>
+       <div class="box-body">
+               <div id="backupMasterList" sort-table="backupMasterList" 
is-sorting="isSorting"
+                        search-path-list="searchPathList"
+                        scope="tableScope">
+                       <table class="table table-bordered">
+                               <thead>
+                               <tr>
+                                       <th sortpath="tags.hostname">Master</th>
+                                       <th sortpath="tags.rack">Rack</th>
+                                       <th sortpath="tags.site">SiteId</th>
+                                       <th sortpath="status">Status</th>
+                               </tr>
+                               </thead>
+                               <tbody>
+                               <tr ng-repeat="item in backupMasterList">
+                                       <td>
+                                               <a 
ui-sref="masterDetail({siteId: site, hostname: 
item.tags.hostname})">{{item.tags.hostname}}</a>
+                                       </td>
+                                       <td>{{item.tags.rack}}</td>
+                                       <td>{{item.tags.site}}</td>
+                                       <td>
+                                               <span>{{item.status}}</span>
+                                       </td>
+                               </tr>
+                               </tbody>
+                       </table>
+               </div>
+       </div>
+</div>

http://git-wip-us.apache.org/repos/asf/eagle/blob/c32b7152/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/partials/overview.html
----------------------------------------------------------------------
diff --git 
a/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/partials/overview.html
 
b/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/partials/overview.html
new file mode 100644
index 0000000..0e194ef
--- /dev/null
+++ 
b/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/partials/overview.html
@@ -0,0 +1,111 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<div class="box box-primary">
+       <div class="box-header with-border">
+               <span class="fa fa-television"></span>
+               <h3 class="box-title">
+                       HBase Service Summary Information
+               </h3>
+       </div>
+       <div class="box-body">
+               <table class="table table-striped hadoopMetric-table">
+                       <tr>
+                               <td width="5%">
+                                       <span 
ng-show="hmasteractivenum">{{hmasteractivenum}}</span>
+                                       <span 
ng-show="!hmasteractivenum">N/A</span>
+                               </td>
+                               <th width="45%">Active HBase Master</th>
+                               <td width="5%">
+                                       <span 
ng-show="regionsnum">{{regionsnum}}</span>
+                                       <span ng-show="!regionsnum">N/A</span>
+                               </td>
+                               <th width="45%">Regions
+                               </th>
+                       </tr>
+                       <tr>
+                               <td>
+                                       <a ui-sref="backupMasterList({siteId: 
site})">
+                                               <span 
ng-show="hmasterstandbynum">{{hmasterstandbynum}}</span></a>
+                                       <span 
ng-show="!hmasterstandbynum">0</span>
+                               </td>
+                               <th>Backup HBase Master</th>
+                               <td>
+                                       <span ng-show="hmasteraverageload !== 
'-1'">{{common.number.format(hmasteraverageload, 0)}}</span>
+                                       <span ng-show="hmasteraverageload === 
'-1'">N/A</span>
+                               </td>
+                               <th>Average Load</th>
+                       </tr>
+                       <tr>
+                               <td>
+                                       <a ui-sref="regionList({siteId: site})">
+                                               <span 
ng-show="regionserverhealtynum || 
regionserverunhealtynum">{{regionserverhealtynum+regionserverunhealtynum}}</span></a>
+                                       <span ng-show="!regionserverhealtynum 
&& !regionserverunhealtynum">N/A</span>
+                               </td>
+                               <th>RegionServers:
+                                       <a ui-sref="regionList({siteId: site})">
+                                               <span 
ng-show="regionserverhealtynum">{{regionserverhealtynum}}</span></a>
+                                       <span 
ng-show="!regionserverhealtynum">0</span>
+                                       <span
+                                       class="label label-success">Good 
Health</span> /
+                                       <a ui-sref="regionList({siteId: site})">
+                                               <span 
ng-show="regionserverunhealtynum">{{regionserverunhealtynum}}</span></a>
+                                           <span 
ng-show="!regionserverunhealtynum">0</span>
+                                       <span class="label label-danger">Bad 
Health</span>
+                               </th>
+                               <td></td>
+                               <th></th>
+                       </tr>
+               </table>
+       </div>
+</div>
+
+<div class="box box-primary">
+       <div class="box-header with-border">
+               <span class="fa fa-line-chart"></span>
+               <h3 class="box-title">
+                       Metrics
+                       <span>({{defaultHostname}})</span>
+               </h3>
+       </div>
+       <div class="box-body no-padding">
+               <div class="row border-split">
+                       <div class="col-sm-6 col-md-4 col-lg-6" 
ng-repeat="chart in chartList track by $index">
+                               <div class="hadoopMetric-chart">
+                                       
<h3>{{metricList[chart.name].title}}</h3>
+                                       <div 
ng-show="metricList[chart.name].loading" chart 
class="hadoopMetric-chart-container"></div>
+                                       <div 
ng-show="metricList[chart.name].loading" class="overlay-wrapper">
+                                               <div class="overlay">
+                                                       <i class="fa fa-refresh 
fa-spin"></i>
+                                               </div>
+                                       </div>
+                                       <div 
ng-show="metricList[chart.name].series.length" chart 
class="hadoopMetric-chart-container"
+                                                
series="metricList[chart.name].series"
+                                                
option="metricList[chart.name].option"></div>
+                                       <div 
ng-show="!metricList[chart.name].series.length && 
!metricList[chart.name].loading" class="hadoopMetric-chart-container">
+                                               <div 
class="hadoopMetric-chart-container-withborder">
+                                                       <div 
class="hadoopMetric-no-chart-data">
+                                                               <span class="fa 
fa-question-circle"></span><span> NO DATA</span>
+                                                       </div>
+                                               </div>
+                                       </div>
+                               </div>
+                       </div>
+               </div>
+       </div>
+</div>

http://git-wip-us.apache.org/repos/asf/eagle/blob/c32b7152/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/partials/region/regionDetail.html
----------------------------------------------------------------------
diff --git 
a/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/partials/region/regionDetail.html
 
b/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/partials/region/regionDetail.html
new file mode 100644
index 0000000..63a895f
--- /dev/null
+++ 
b/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/partials/region/regionDetail.html
@@ -0,0 +1,117 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<div class="box box-primary">
+       <div class="box-header with-border">
+               <span class="fa fa-television"></span>
+               <h3 class="box-title">
+                       Summary
+               </h3>
+       </div>
+       <div class="box-body">
+               <table class="table table-striped">
+                       <tbody ng-if="(regionstatus || []).length !== 0">
+                       <tr>
+                               <th>Status</th>
+                               <td class="text-break">
+                                       <span 
ng-if="regionstatus[0].status==='live'" class="label 
label-success">Healthy</span>
+                                       <span 
ng-if="regionstatus[0].status!=='live'" class="label 
label-danger">UnHealthy</span>
+                               </td>
+                       </tr>
+                       <tr>
+                               <th>Rack</th>
+                               <td 
class="text-break">{{regionstatus[0].tags.rack}}</td>
+                       </tr>
+                       <tr>
+                               <th>MaxHeap</th>
+                               <td 
class="text-break">{{regionstatus[0].maxHeapMB}} MB</td>
+                       </tr>
+                       <tr>
+                               <th>UsedHeap</th>
+                               <td 
class="text-break">{{regionstatus[0].usedHeapMB}} MB</td>
+                       </tr>
+                       <tr>
+                               <th>NumRegions</th>
+                               <td 
class="text-break">{{regionstatus[0].numRegions}}</td>
+                       </tr>
+                       <tr>
+                               <th>NumRequests</th>
+                               <td 
class="text-break">{{regionstatus[0].numRequests}}</td>
+                       </tr>
+                       </tbody>
+                       <tbody ng-if="regionstatus.length === 0">
+                       <tr>
+                               <th>Status</th>
+                               <td class="text-break"><span class="label 
label-danger">Unknow</span></td>
+                       </tr>
+                       <tr>
+                               <th>Rack</th>
+                               <td class="text-break"><span class="label 
label-danger">Unknow</span></td>
+                       </tr>
+                       <tr>
+                               <th>MaxHeap</th>
+                               <td class="text-break"><span class="label 
label-danger">Unknow</span></td>
+                       </tr>
+                       <tr>
+                               <th>UsedHeap</th>
+                               <td class="text-break"><span class="label 
label-danger">Unknow</span></td>
+                       </tr>
+                       <tr>
+                               <th>NumRegions</th>
+                               <td class="text-break"><span class="label 
label-danger">Unknow</span></td>
+                       </tr>
+                       <tr>
+                               <th>NumRequests</th>
+                               <td class="text-break"><span class="label 
label-danger">Unknow</span></td>
+                       </tr>
+                       </tbody>
+               </table>
+       </div>
+</div>
+
+<div class="box box-primary">
+       <div class="box-header with-border">
+               <span class="fa fa-line-chart"></span>
+               <h3 class="box-title">
+                       Metrics
+               </h3>
+       </div>
+       <div class="box-body no-padding">
+               <div class="row border-split">
+                       <div class="col-sm-6 hadoopMetric-col-md-6 col-lg-6" 
ng-repeat="chart in chartList track by $index">
+                               <div class="hadoopMetric-chart">
+                                       
<h3>{{metricList[chart.name].title}}</h3>
+                                       <div 
ng-show="metricList[chart.name].loading" 
class="hadoopMetric-chart-container"></div>
+                                       <div 
ng-show="metricList[chart.name].loading" class="overlay-wrapper">
+                                               <div class="overlay">
+                                                       <i class="fa fa-refresh 
fa-spin"></i>
+                                               </div>
+                                       </div>
+                                       <div 
ng-show="metricList[chart.name].series.length" chart 
class="hadoopMetric-chart-container"
+                                                
series="metricList[chart.name].series"
+                                                
option="metricList[chart.name].option"></div>
+                                       <div 
ng-show="!metricList[chart.name].series.length && 
!metricList[chart.name].loading" class="hadoopMetric-chart-container">
+                                               <div 
class="hadoopMetric-no-chart-data">
+                                                       <span class="fa 
fa-question-circle"></span><span> NO DATA</span>
+                                               </div>
+                                       </div>
+                               </div>
+                       </div>
+               </div>
+       </div>
+</div>

http://git-wip-us.apache.org/repos/asf/eagle/blob/c32b7152/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/partials/region/regionList.html
----------------------------------------------------------------------
diff --git 
a/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/partials/region/regionList.html
 
b/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/partials/region/regionList.html
new file mode 100644
index 0000000..d1a7440
--- /dev/null
+++ 
b/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/partials/region/regionList.html
@@ -0,0 +1,53 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+<div class="box box-primary">
+       <div class="box-header with-border">
+               <h3 class="box-title">
+                       <span ng-show="!regionserverList._done || isSorting" 
class="fa fa-refresh fa-spin no-animate"></span>
+               </h3>
+       </div>
+       <div class="box-body">
+               <div id="regionserverList" sort-table="regionserverList" 
is-sorting="isSorting"
+                        search-path-list="searchPathList"
+                        scope="tableScope">
+                       <table class="table table-bordered">
+                               <thead>
+                               <tr>
+                                       <th 
sortpath="tags.hostname">RegionServer</th>
+                                       <th sortpath="tags.rack">Rack</th>
+                                       <th sortpath="tags.site">SiteId</th>
+                                       <th sortpath="status">Status</th>
+                               </tr>
+                               </thead>
+                               <tbody>
+                               <tr ng-repeat="item in regionserverList">
+                                       <td>
+                                               <a 
ui-sref="regionDetail({siteId: site, hostname: 
item.tags.hostname})">{{item.tags.hostname}}</a>
+                                       </td>
+                                       <td>{{item.tags.rack}}</td>
+                                       <td>{{item.tags.site}}</td>
+                                       <td>
+                                               <span 
ng-if="item.status===live" class="label label-success">Healthy</span>
+                                               <span 
ng-if="item.status===dead" class="label label-danger">UnHealthy</span>
+                                       </td>
+                               </tr>
+                               </tbody>
+                       </table>
+               </div>
+       </div>
+</div>

http://git-wip-us.apache.org/repos/asf/eagle/blob/c32b7152/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/style/index.css
----------------------------------------------------------------------
diff --git 
a/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/style/index.css 
b/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/style/index.css
new file mode 100644
index 0000000..aa215ab
--- /dev/null
+++ 
b/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/style/index.css
@@ -0,0 +1,88 @@
+@CHARSET "UTF-8";
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+.hadoopMetric-chart {
+       position: relative;
+       margin-bottom: 15px;
+}
+
+.hadoopMetric-chart h3 {
+       font-size: 20px;
+       margin: 10px 0 0 0;
+}
+
+.hadoopMetric-chart .hadoopMetric-chart-container {
+       height: 300px;
+       position: relative;
+}
+
+.hadoopMetric-chart .hadoopMetric-no-chart-data {
+       position:absolute;
+       left: 38%;
+       top: 40%;
+       font-size: 20px;
+       color: #999;
+}
+
+.with-border .hadoopMetric-chart {
+       padding-bottom: 15px;
+       margin-bottom: 15px;
+       border-bottom: 1px solid #f4f4f4;
+}
+
+.with-border .hadoopMetric-chart:last-child {
+       padding-bottom: 0;
+       margin-bottom: 0;
+       border-bottom: 0;
+}
+
+.hadoopMetric-widget {
+       width: 100%;
+       box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
+       border-radius: 2px;
+       padding: 10px;
+}
+
+.hadoopMetric-widget h3 {
+       margin: 0;
+       padding: 0;
+}
+
+.hadoopMetric-widget .hadoopMetric-chart-container {
+       height: 100px;
+}
+
+.hadoopMetric-summary-a {
+       color: #fff;
+}
+
+.small-box.hadoopMetric-widget {
+       margin: 0;
+       height: 100%;
+       min-height: 110px;
+}
+
+.hadoopMetric-widget-detail {
+       margin-left: 12px;
+       margin-top: 10px;
+}
+
+.hadoopMetric-table {
+       text-align: right;
+}

http://git-wip-us.apache.org/repos/asf/eagle/blob/c32b7152/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/widgets/availabilityChart.js
----------------------------------------------------------------------
diff --git 
a/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/widgets/availabilityChart.js
 
b/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/widgets/availabilityChart.js
new file mode 100644
index 0000000..bd0a278
--- /dev/null
+++ 
b/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/widgets/availabilityChart.js
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function () {
+       /**
+        * `register` without params will load the module which using require
+        */
+       register(function (hadoopMetricApp) {
+               var COLOR_MAPPING = {
+                       HDFS: 'orange',
+                       HBase: 'yellow',
+                       Yarn: 'green'
+               };
+
+               hadoopMetricApp.directive("hadoopMetricWidget", function () {
+                       return {
+                               restrict: 'AE',
+                               controller: function ($scope, $attrs, METRIC, 
Application, $interval, Site, $wrapState) {
+                                       // Get site
+                                       var site = $scope.site;
+                                       var refreshInterval;
+
+                                       if(!site) {
+                                               $scope.list = 
$.map(Application.find("HADOOP_METRIC_MONITOR"), function (app) {
+                                                       return {
+                                                               siteId: 
app.site.siteId,
+                                                               siteName: 
app.site.siteName || app.site.siteId
+                                                       };
+                                               });
+                                       } else {
+                                               $scope.list = [{
+                                                       siteId: site.siteId,
+                                                       siteName: site.siteName 
|| site.siteId
+                                               }];
+                                       }
+                                       // Get type
+                                       $scope.type = $attrs.type;
+
+                                       // Customize chart color
+                                       $scope.bgColor = 
COLOR_MAPPING[$scope.type];
+
+                                       function countHBaseRole(site, status, 
role, groups, filed, limit) {
+                                               var jobCond = {
+                                                       site: site,
+                                                       status: status,
+                                                       role: role
+                                               };
+                                               return 
METRIC.aggHBaseInstance(jobCond, groups, filed, limit);
+                                       }
+
+                                       // Ref: jpm widget if need keep refresh 
the widget
+
+                                       function refresh() {
+                                               $.each($scope.list, function 
(i, site) {
+
+                                                       
countHBaseRole(site.siteId, "active", "hmaster", ["site"], 
"count")._promise.then(function (res) {
+                                                               $.map(res, 
function (data) {
+                                                                       
$scope.hmasteractivenum = data.value[0];
+                                                               });
+                                                       });
+                                                       
countHBaseRole(site.siteId, "standby", "hmaster", ["site"], 
"count")._promise.then(function (res) {
+                                                               $.map(res, 
function (data) {
+                                                                       
$scope.hmasterstandbynum = data.value[0];
+                                                               });
+                                                       });
+                                                       
countHBaseRole(site.siteId, "live", "regionserver", ["site"], 
"count")._promise.then(function (res) {
+                                                               $.map(res, 
function (data) {
+                                                                       
$scope.regionserverhealtynum = data.value[0];
+                                                               });
+                                                       });
+                                                       
countHBaseRole(site.siteId, "dead", "regionserver", ["site"], 
"count")._promise.then(function (res) {
+                                                               $.map(res, 
function (data) {
+                                                                       
$scope.regionserverunhealtynum = data.value[0];
+                                                               });
+                                                       });
+                                               });
+                                       }
+
+                                       refresh();
+                                       refreshInterval = $interval(refresh, 30 
* 1000);
+
+                                       $scope.$on('$destroy', function () {
+                                               
$interval.cancel(refreshInterval);
+                                       });
+                               },
+                               template:
+                               '<div class="small-box hadoopMetric-widget 
bg-{{bgColor}}">' +
+                                   '<div class="inner">' +
+                                       '<h3>{{type}}</h3>' +
+                                       '<div ng-show="hmasteractivenum" 
class="hadoopMetric-widget-detail">' +
+                                               '<a 
ui-sref="HBaseMetric({siteId: site.siteId})">' +
+                                           
'<span>{{hmasteractivenum+hmasterstandbynum}}</span> Masters (' +
+                                           '<span 
ng-show="hmasteractivenum">{{hmasteractivenum}}</span><span 
ng-show="!hmasteractivenum">0</span> Active / ' +
+                                           '<span 
ng-show="hmasterstandbynum">{{hmasterstandbynum}}</span><span 
ng-show="!hmasterstandbynum">0</span> Standby)' +
+                                               '</a>' +
+                                       '</div>' +
+                                       '<div ng-show="!hmasteractivenum" 
class="hadoopMetric-widget-detail">' +
+                                          '<span class="fa 
fa-question-circle"></span><span> NO DATA</span>' +
+                                       '</div>' +
+                                       '<div ng-show="hmasteractivenum" 
class="hadoopMetric-widget-detail">' +
+                                           '<a ui-sref="regionList({siteId: 
site.siteId})">' +
+                                           
'<span>{{regionserverhealtynum+regionserverunhealtynum}}</span> RegionServers 
(' +
+                                           '<span 
ng-show="regionserverhealtynum">{{regionserverhealtynum}}</span><span 
ng-show="!regionserverhealtynum">0</span> Healthy / ' +
+                                           '<span 
ng-show="regionserverunhealtynum">{{regionserverunhealtynum}}</span><span 
ng-show="!regionserverunhealtynum">0</span> Unhealthy)' +
+                                           '</a>' +
+                                       '</div>' +
+                                   '</div>' +
+                                   '<div class="icon">' +
+                                       '<i class="fa fa-taxi"></i>' +
+                                   '</div>' +
+                               '</div>',
+                               replace: true
+                       };
+               });
+
+               function withType(serviceType) {
+                       /**
+                        * Customize the widget content. Return false will 
prevent auto compile.
+                        * @param {{}} $element
+                        * @param {function} $element.append
+                        */
+                       return function registerWidget($element) {
+                               $element.append(
+                                       $("<div hadoop-metric-widget 
data-type='" + serviceType + "'>")
+                               );
+                       };
+               }
+               hadoopMetricApp.widget("availabilityHBaseChart", 
withType('HBase'), true);
+       });
+})();

http://git-wip-us.apache.org/repos/asf/eagle/blob/c32b7152/eagle-metric/eagle-hbase-web/src/main/webapp/package.json
----------------------------------------------------------------------
diff --git a/eagle-metric/eagle-hbase-web/src/main/webapp/package.json 
b/eagle-metric/eagle-hbase-web/src/main/webapp/package.json
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/eagle/blob/c32b7152/eagle-metric/eagle-hbase-web/src/test/org/apache/eagle/metric/HBaseMetricWebApplicationProviderTest.java
----------------------------------------------------------------------
diff --git 
a/eagle-metric/eagle-hbase-web/src/test/org/apache/eagle/metric/HBaseMetricWebApplicationProviderTest.java
 
b/eagle-metric/eagle-hbase-web/src/test/org/apache/eagle/metric/HBaseMetricWebApplicationProviderTest.java
new file mode 100644
index 0000000..eae05e5
--- /dev/null
+++ 
b/eagle-metric/eagle-hbase-web/src/test/org/apache/eagle/metric/HBaseMetricWebApplicationProviderTest.java
@@ -0,0 +1,100 @@
+package org.apache.eagle.metric;/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import com.google.inject.Inject;
+import org.apache.eagle.app.resource.ApplicationResource;
+import org.apache.eagle.app.service.ApplicationOperations;
+import org.apache.eagle.app.test.ApplicationTestBase;
+import org.apache.eagle.metadata.model.ApplicationEntity;
+import org.apache.eagle.metadata.model.SiteEntity;
+import org.apache.eagle.metadata.resource.SiteResource;
+import org.apache.eagle.metadata.service.ApplicationStatusUpdateService;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @Since 2/20/17.
+ */
+public class HBaseMetricWebApplicationProviderTest extends ApplicationTestBase 
{
+    @Inject
+    private SiteResource siteResource;
+
+    @Inject
+    private ApplicationResource applicationResource;
+
+    @Inject
+    private ApplicationStatusUpdateService statusUpdateService;
+
+    private void installDependencies(){
+        ApplicationOperations.InstallOperation installDependency1 = new 
ApplicationOperations.InstallOperation("test_site", 
"TOPOLOGY_HEALTH_CHECK_APP", ApplicationEntity.Mode.LOCAL);
+        applicationResource.installApplication(installDependency1);
+
+        ApplicationOperations.InstallOperation installDependency2 = new 
ApplicationOperations.InstallOperation("test_site", "HADOOP_METRIC_MONITOR", 
ApplicationEntity.Mode.LOCAL);
+        applicationResource.installApplication(installDependency2);
+    }
+
+    /**
+     * register site
+     * install app
+     * start app
+     * stop app
+     * uninstall app
+     *
+     * @throws InterruptedException
+     */
+    @Test
+    public void testApplicationLifecycle() throws InterruptedException {
+        // Create local site
+        SiteEntity siteEntity = new SiteEntity();
+        siteEntity.setSiteId("test_site");
+        siteEntity.setSiteName("Test Site");
+        siteEntity.setDescription("Test Site for HBASE_METRIC_WEB_APP");
+        siteResource.createSite(siteEntity);
+        Assert.assertNotNull(siteEntity.getUuid());
+
+
+
+        ApplicationOperations.InstallOperation installOperation = new 
ApplicationOperations.InstallOperation("test_site", "HBASE_METRIC_WEB_APP", 
ApplicationEntity.Mode.LOCAL);
+        installOperation.setConfiguration(getConf());
+        installDependencies();
+        // Install application
+        ApplicationEntity applicationEntity = 
applicationResource.installApplication(installOperation).getData();
+        //Todo: comment these for now, because they haven't been implemented
+        // Start application
+//        applicationResource.startApplication(new 
ApplicationOperations.StartOperation(applicationEntity.getUuid()));
+//        // Stop application
+//        applicationResource.stopApplication(new 
ApplicationOperations.StopOperation(applicationEntity.getUuid()));
+        //Uninstall application
+        awaitApplicationStop(applicationEntity);
+        applicationResource.uninstallApplication(new 
ApplicationOperations.UninstallOperation(applicationEntity.getUuid()));
+        try {
+            
applicationResource.getApplicationEntityByUUID(applicationEntity.getUuid());
+            Assert.fail("Application instance (UUID: " + 
applicationEntity.getUuid() + ") should have been uninstalled");
+        } catch (Exception ex) {
+            // Expected exception
+        }
+    }
+
+    private Map<String, Object> getConf() {
+        Map<String, Object> conf = new HashMap<>();
+        conf.put("service.host", "localhost");
+        conf.put("service.port", "9090");
+        return conf;
+    }
+}

http://git-wip-us.apache.org/repos/asf/eagle/blob/c32b7152/eagle-metric/eagle-hdfs-web/pom.xml
----------------------------------------------------------------------
diff --git a/eagle-metric/eagle-hdfs-web/pom.xml 
b/eagle-metric/eagle-hdfs-web/pom.xml
new file mode 100644
index 0000000..dd38416
--- /dev/null
+++ b/eagle-metric/eagle-hdfs-web/pom.xml
@@ -0,0 +1,57 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+    <parent>
+        <artifactId>eagle-metric-parent</artifactId>
+        <groupId>org.apache.eagle</groupId>
+        <version>0.5.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>eagle-hdfs-web</artifactId>
+    <name>Eagle::App::HadoopMetric::Hdfs::WebUI</name>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.eagle</groupId>
+            <artifactId>eagle-app-base</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.eagle</groupId>
+            <artifactId>eagle-hadoop-metric</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.eagle</groupId>
+            <artifactId>eagle-topology-app</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+    <build>
+        <resources>
+            <resource>
+                <directory>src/main/webapp/app</directory>
+                <targetPath>assets/</targetPath>
+            </resource>
+            <resource>
+                <directory>src/main/resources</directory>
+            </resource>
+        </resources>
+    </build>
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/eagle/blob/c32b7152/eagle-metric/eagle-hdfs-web/src/main/java/org/apache/eagle/metric/HdfsMetricWebApplicationProvider.java
----------------------------------------------------------------------
diff --git 
a/eagle-metric/eagle-hdfs-web/src/main/java/org/apache/eagle/metric/HdfsMetricWebApplicationProvider.java
 
b/eagle-metric/eagle-hdfs-web/src/main/java/org/apache/eagle/metric/HdfsMetricWebApplicationProvider.java
new file mode 100644
index 0000000..434e1f4
--- /dev/null
+++ 
b/eagle-metric/eagle-hdfs-web/src/main/java/org/apache/eagle/metric/HdfsMetricWebApplicationProvider.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.eagle.metric;
+
+import org.apache.eagle.app.StaticApplicationProvider;
+
+public class HdfsMetricWebApplicationProvider extends 
StaticApplicationProvider {
+    // HdfsWebApplicationProvider SPI Interface
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/eagle/blob/c32b7152/eagle-metric/eagle-hdfs-web/src/main/resources/META-INF/providers/org.apache.eagle.metric.HdfsMetricWebApplicationProvider.xml
----------------------------------------------------------------------
diff --git 
a/eagle-metric/eagle-hdfs-web/src/main/resources/META-INF/providers/org.apache.eagle.metric.HdfsMetricWebApplicationProvider.xml
 
b/eagle-metric/eagle-hdfs-web/src/main/resources/META-INF/providers/org.apache.eagle.metric.HdfsMetricWebApplicationProvider.xml
new file mode 100644
index 0000000..b6f70d1
--- /dev/null
+++ 
b/eagle-metric/eagle-hdfs-web/src/main/resources/META-INF/providers/org.apache.eagle.metric.HdfsMetricWebApplicationProvider.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<application>
+    <type>HDFS_METRIC_WEB_APP</type>
+    <name>Hdfs Metric Monitoring Web </name>
+    <viewPath>/apps/hdfs</viewPath>
+    <description>Hdfs Metric Monitoring Web</description>
+    <dependencies>
+        <dependency>
+            <type>HADOOP_METRIC_MONITOR</type>
+            <required>true</required>
+        </dependency>
+        <dependency>
+            <type>TOPOLOGY_HEALTH_CHECK_APP</type>
+            <required>true</required>
+        </dependency>
+    </dependencies>
+    <configuration>
+        <property>
+            <name>service.host</name>
+            <displayName>Eagle Service Host</displayName>
+            <description>Set additional eagle service host, default: using 
current host</description>
+        </property>
+        <property>
+            <name>service.port</name>
+            <displayName>Eagle Service Port</displayName>
+            <description>Set additional eagle service port, default: using 
current port</description>
+        </property>
+    </configuration>
+</application>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/eagle/blob/c32b7152/eagle-metric/eagle-hdfs-web/src/main/resources/META-INF/services/org.apache.eagle.app.spi.ApplicationProvider
----------------------------------------------------------------------
diff --git 
a/eagle-metric/eagle-hdfs-web/src/main/resources/META-INF/services/org.apache.eagle.app.spi.ApplicationProvider
 
b/eagle-metric/eagle-hdfs-web/src/main/resources/META-INF/services/org.apache.eagle.app.spi.ApplicationProvider
new file mode 100644
index 0000000..3dec9d0
--- /dev/null
+++ 
b/eagle-metric/eagle-hdfs-web/src/main/resources/META-INF/services/org.apache.eagle.app.spi.ApplicationProvider
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+org.apache.eagle.metric.HdfsMetricWebApplicationProvider
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/eagle/blob/c32b7152/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/ctrl/overview.js
----------------------------------------------------------------------
diff --git 
a/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/ctrl/overview.js 
b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/ctrl/overview.js
new file mode 100644
index 0000000..b8d57a7
--- /dev/null
+++ b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/ctrl/overview.js
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function () {
+       /**
+        * `register` without params will load the module which using require
+        */
+       register(function (hdfsMetricApp) {
+               hdfsMetricApp.controller("overviewCtrl", function (PageConfig) {
+                       PageConfig.title = 'Hdfs';
+
+               });
+       });
+})();

http://git-wip-us.apache.org/repos/asf/eagle/blob/c32b7152/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/index.html
----------------------------------------------------------------------
diff --git 
a/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/index.html 
b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/index.html
new file mode 100644
index 0000000..799ad15
--- /dev/null
+++ b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/index.html
@@ -0,0 +1,6 @@
+<htm>
+    <body>
+    <h1>HDFS Metric Monitor Application!</h1>
+    <i><b>url</b>: /apps/hdfs</i>
+    </body>
+</htm>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/eagle/blob/c32b7152/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/index.js
----------------------------------------------------------------------
diff --git a/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/index.js 
b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/index.js
new file mode 100644
index 0000000..48b3feb
--- /dev/null
+++ b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/index.js
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function () {
+       /**
+        * `register` is global function that for application to set up 
'controller', 'service', 'directive', 'route' in Eagle
+        */
+       var hdfsMetricApp = register(['ngRoute', 'ngAnimate', 'ui.router', 
'eagle.service']);
+
+       hdfsMetricApp.route("HdfsMetric", {
+               url: "/hadoopService/hdfs",
+               site: true,
+               templateUrl: "partials/overview.html",
+               controller: "overviewCtrl",
+               resolve: {time: true}
+       });
+
+       hdfsMetricApp.portal({
+               name: "Services", icon: "heartbeat", list: [
+                       {name: "HDFS", path: "hadoopService/hdfs"}
+               ]
+       }, true);
+
+    hdfsMetricApp.requireCSS("style/index.css");
+    hdfsMetricApp.require("widget/availabilityChart.js");
+       hdfsMetricApp.require("ctrl/overview.js");
+})();

http://git-wip-us.apache.org/repos/asf/eagle/blob/c32b7152/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/partials/overview.html
----------------------------------------------------------------------
diff --git 
a/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/partials/overview.html
 
b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/partials/overview.html
new file mode 100644
index 0000000..678b221
--- /dev/null
+++ 
b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/partials/overview.html
@@ -0,0 +1,17 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+HDFS Page

http://git-wip-us.apache.org/repos/asf/eagle/blob/c32b7152/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/style/index.css
----------------------------------------------------------------------
diff --git 
a/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/style/index.css 
b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/style/index.css
new file mode 100644
index 0000000..aa215ab
--- /dev/null
+++ b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/style/index.css
@@ -0,0 +1,88 @@
+@CHARSET "UTF-8";
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+.hadoopMetric-chart {
+       position: relative;
+       margin-bottom: 15px;
+}
+
+.hadoopMetric-chart h3 {
+       font-size: 20px;
+       margin: 10px 0 0 0;
+}
+
+.hadoopMetric-chart .hadoopMetric-chart-container {
+       height: 300px;
+       position: relative;
+}
+
+.hadoopMetric-chart .hadoopMetric-no-chart-data {
+       position:absolute;
+       left: 38%;
+       top: 40%;
+       font-size: 20px;
+       color: #999;
+}
+
+.with-border .hadoopMetric-chart {
+       padding-bottom: 15px;
+       margin-bottom: 15px;
+       border-bottom: 1px solid #f4f4f4;
+}
+
+.with-border .hadoopMetric-chart:last-child {
+       padding-bottom: 0;
+       margin-bottom: 0;
+       border-bottom: 0;
+}
+
+.hadoopMetric-widget {
+       width: 100%;
+       box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
+       border-radius: 2px;
+       padding: 10px;
+}
+
+.hadoopMetric-widget h3 {
+       margin: 0;
+       padding: 0;
+}
+
+.hadoopMetric-widget .hadoopMetric-chart-container {
+       height: 100px;
+}
+
+.hadoopMetric-summary-a {
+       color: #fff;
+}
+
+.small-box.hadoopMetric-widget {
+       margin: 0;
+       height: 100%;
+       min-height: 110px;
+}
+
+.hadoopMetric-widget-detail {
+       margin-left: 12px;
+       margin-top: 10px;
+}
+
+.hadoopMetric-table {
+       text-align: right;
+}

http://git-wip-us.apache.org/repos/asf/eagle/blob/c32b7152/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/widget/availabilityChart.js
----------------------------------------------------------------------
diff --git 
a/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/widget/availabilityChart.js
 
b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/widget/availabilityChart.js
new file mode 100644
index 0000000..fbfc73d
--- /dev/null
+++ 
b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/widget/availabilityChart.js
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function () {
+       /**
+        * `register` without params will load the module which using require
+        */
+       register(function (hdfsMetricApp) {
+               var COLOR_MAPPING = {
+                       HDFS: 'orange',
+                       HBase: 'yellow',
+                       Yarn: 'green',
+               };
+
+               var widgetChartOption = {
+                       color: ['#FFFFFF'],
+                       grid: {
+                               top: 0,
+                               right: 0,
+                               bottom: 0,
+                               left: 0,
+                               containLabel: false,
+                       },
+                       xAxis: {
+                               axisLine: {show: false},
+                               axisLabel: {show: false},
+                       },
+                       yAxis: [{
+                               axisLine: {show: false},
+                               axisLabel: {show: false},
+                               axisTick: {show: false},
+                               splitLine: {show: false},
+                       }],
+               };
+
+               hdfsMetricApp.directive("hdfsMetricWidget", function () {
+                       return {
+                               restrict: 'AE',
+                               controller: function($scope, $attrs) {
+                                       // Get site
+                                       var site = $scope.site;
+
+                                       // Get type
+                                       $scope.type = $attrs.type;
+
+                                       // Customize chart color
+                                       $scope.bgColor = 
COLOR_MAPPING[$scope.type];
+
+                                       $scope.chartOption = widgetChartOption;
+
+                                       // Mock fetch data
+                                       var now = +new Date();
+                                       var data = [];
+                                       for(var j = 0 ; j < 30 ; j += 1) {
+                                               data.push({x: now + j * 1000 * 
60, y: Math.random() * 100});
+                                       }
+                                       $scope.series = [{
+                                               name: '',
+                                               type: 'line',
+                                               data: data,
+                                               showSymbol: false,
+                                       }];
+
+                                       // Ref: jpm widget if need keep refresh 
the widget
+                               },
+                               template:
+                               '<div class="hadoopMetric-widget 
bg-{{bgColor}}">' +
+                                       '<h3>{{type}}</h3>' +
+                                       '<div chart 
class="hadoopMetric-chart-container" series="series" 
option="chartOption"></div>' +
+                               '</div>',
+                               replace: true
+                       };
+               });
+
+               function withType(serviceType) {
+                       /**
+                        * Customize the widget content. Return false will 
prevent auto compile.
+                        * @param {{}} $element
+                        * @param {function} $element.append
+                        */
+                       return function registerWidget($element) {
+                               $element.append(
+                                       $("<div hdfs-metric-widget data-type='" 
+ serviceType + "'>")
+                               );
+                       }
+               }
+
+               hdfsMetricApp.widget("availabilityHdfsChart", withType('HDFS'), 
true);
+       });
+})();

http://git-wip-us.apache.org/repos/asf/eagle/blob/c32b7152/eagle-metric/eagle-hdfs-web/src/main/webapp/package.json
----------------------------------------------------------------------
diff --git a/eagle-metric/eagle-hdfs-web/src/main/webapp/package.json 
b/eagle-metric/eagle-hdfs-web/src/main/webapp/package.json
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/eagle/blob/c32b7152/eagle-metric/eagle-hdfs-web/src/test/org/apache/eagle/metric/HdfsMetricWebApplicationProviderTest.java
----------------------------------------------------------------------
diff --git 
a/eagle-metric/eagle-hdfs-web/src/test/org/apache/eagle/metric/HdfsMetricWebApplicationProviderTest.java
 
b/eagle-metric/eagle-hdfs-web/src/test/org/apache/eagle/metric/HdfsMetricWebApplicationProviderTest.java
new file mode 100644
index 0000000..8e61af4
--- /dev/null
+++ 
b/eagle-metric/eagle-hdfs-web/src/test/org/apache/eagle/metric/HdfsMetricWebApplicationProviderTest.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.eagle.metric;
+import com.google.inject.Inject;
+import org.apache.eagle.app.resource.ApplicationResource;
+import org.apache.eagle.app.service.ApplicationOperations;
+import org.apache.eagle.app.test.ApplicationTestBase;
+import org.apache.eagle.metadata.model.ApplicationEntity;
+import org.apache.eagle.metadata.model.SiteEntity;
+import org.apache.eagle.metadata.resource.SiteResource;
+import org.apache.eagle.metadata.service.ApplicationStatusUpdateService;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @Since 2/20/17.
+ */
+public class HdfsMetricWebApplicationProviderTest extends ApplicationTestBase {
+    @Inject
+    private SiteResource siteResource;
+
+    @Inject
+    private ApplicationResource applicationResource;
+
+    @Inject
+    private ApplicationStatusUpdateService statusUpdateService;
+
+    private void installDependencies(){
+        ApplicationOperations.InstallOperation installDependency1 = new 
ApplicationOperations.InstallOperation("test_site", 
"TOPOLOGY_HEALTH_CHECK_APP", ApplicationEntity.Mode.LOCAL);
+        applicationResource.installApplication(installDependency1);
+
+        ApplicationOperations.InstallOperation installDependency2 = new 
ApplicationOperations.InstallOperation("test_site", "HADOOP_METRIC_MONITOR", 
ApplicationEntity.Mode.LOCAL);
+        applicationResource.installApplication(installDependency2);
+    }
+
+    /**
+     * register site
+     * install app
+     * start app
+     * stop app
+     * uninstall app
+     *
+     * @throws InterruptedException
+     */
+    @Test
+    public void testApplicationLifecycle() throws InterruptedException {
+        // Create local site
+        SiteEntity siteEntity = new SiteEntity();
+        siteEntity.setSiteId("test_site");
+        siteEntity.setSiteName("Test Site");
+        siteEntity.setDescription("Test Site for HDFS_METRIC_WEB_APP");
+        siteResource.createSite(siteEntity);
+        Assert.assertNotNull(siteEntity.getUuid());
+
+
+
+        ApplicationOperations.InstallOperation installOperation = new 
ApplicationOperations.InstallOperation("test_site", "HDFS_METRIC_WEB_APP", 
ApplicationEntity.Mode.LOCAL);
+        installOperation.setConfiguration(getConf());
+        installDependencies();
+        // Install application
+        ApplicationEntity applicationEntity = 
applicationResource.installApplication(installOperation).getData();
+        //Todo: comment these for now, because they haven't been implemented
+        // Start application
+//        applicationResource.startApplication(new 
ApplicationOperations.StartOperation(applicationEntity.getUuid()));
+//        // Stop application
+//        applicationResource.stopApplication(new 
ApplicationOperations.StopOperation(applicationEntity.getUuid()));
+        //Uninstall application
+        awaitApplicationStop(applicationEntity);
+        applicationResource.uninstallApplication(new 
ApplicationOperations.UninstallOperation(applicationEntity.getUuid()));
+        try {
+            
applicationResource.getApplicationEntityByUUID(applicationEntity.getUuid());
+            Assert.fail("Application instance (UUID: " + 
applicationEntity.getUuid() + ") should have been uninstalled");
+        } catch (Exception ex) {
+            // Expected exception
+        }
+    }
+
+    private Map<String, Object> getConf() {
+        Map<String, Object> conf = new HashMap<>();
+        conf.put("service.host", "localhost");
+        conf.put("service.port", "9090");
+        return conf;
+    }
+}

Reply via email to