You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by yu...@apache.org on 2014/01/25 04:37:08 UTC
git commit: AMBARI-4364. Add ability to decom/recom NodeManager from
Host Details page. (xiwang via yusaku) AMBARI-4379. Add ability to
decom/recom TaskTracker from Host Details page. (xiwang via yusaku)
Updated Branches:
refs/heads/trunk f14dae7ef -> 930c8d909
AMBARI-4364. Add ability to decom/recom NodeManager from Host Details page. (xiwang via yusaku)
AMBARI-4379. Add ability to decom/recom TaskTracker from Host Details page. (xiwang via yusaku)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/930c8d90
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/930c8d90
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/930c8d90
Branch: refs/heads/trunk
Commit: 930c8d909cde3c3ec87f09d75d7cc9d31ec9c51b
Parents: f14dae7
Author: Yusaku Sako <yu...@hortonworks.com>
Authored: Fri Jan 24 19:35:59 2014 -0800
Committer: Yusaku Sako <yu...@hortonworks.com>
Committed: Fri Jan 24 19:35:59 2014 -0800
----------------------------------------------------------------------
ambari-web/app/controllers/main/host/details.js | 344 +++++++++-----
ambari-web/app/messages.js | 11 +
ambari-web/app/templates/main/host/summary.hbs | 32 ++
ambari-web/app/utils/ajax.js | 99 ++++
ambari-web/app/views/main/host/summary.js | 449 +++++++++++++++----
5 files changed, 736 insertions(+), 199 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/930c8d90/ambari-web/app/controllers/main/host/details.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/host/details.js b/ambari-web/app/controllers/main/host/details.js
index 76d6d8e..f81a794 100644
--- a/ambari-web/app/controllers/main/host/details.js
+++ b/ambari-web/app/controllers/main/host/details.js
@@ -649,28 +649,34 @@ App.MainHostDetailsController = Em.Controller.extend({
}
});
},
+
/**
- * send command to server to run decommission on DATANODE
+ * send command to server to run decommission on DATANODE, TASKTRACKER, NODEMANAGER, REGIONSERVER
* @param event
*/
decommission: function(event){
var self = this;
- var decommissionHostNames = this.get('view.decommissionDataNodeHostNames');
- if (decommissionHostNames == null) {
- decommissionHostNames = [];
- }
App.showConfirmationPopup(function(){
var component = event.context;
- // Only HDFS service as of now
var svcName = component.get('service.serviceName');
+ var hostName = self.get('content.hostName');
+ // HDFS service, decommission DataNode
if (svcName === "HDFS") {
- var hostName = self.get('content.hostName');
- var index = decommissionHostNames.indexOf(hostName);
- if (index < 0) {
- decommissionHostNames.push(hostName);
- }
- self.doDatanodeDecommission(decommissionHostNames, true);
+ self.doDecommission(hostName, svcName, "NAMENODE", "DATANODE");
+ }
+ // YARN service, decommission NodeManager
+ if (svcName === "YARN") {
+ self.doDecommission(hostName, svcName, "RESOURCEMANAGER", "NODEMANAGER");
+ }
+ // MAPREDUCE service, decommission TaskTracker
+ if (svcName === "MAPREDUCE") {
+ self.doDecommission(hostName, svcName, "JOBTRACKER", "TASKTRACKER");
+ }
+ // HBASE service, decommission RegionServer
+ if (svcName === "HBASE") {
+ self.doDecommissionRegionServer(hostName, svcName, "HBASE_MASTER", "HBASE_REGIONSERVER");
}
+
// load data (if we need to show this background operations popup) from persist
App.router.get('applicationController').dataLoading().done(function (initValue) {
if (initValue) {
@@ -679,107 +685,35 @@ App.MainHostDetailsController = Em.Controller.extend({
});
});
},
-
- /**
- * Performs either Decommission or Recommission by updating the hosts list on
- * server.
- * @param {Array} decommissionHostNames
- * @param {Boolean} decommission defines context for request (true for decommission and false for recommission)
- */
- doDatanodeDecommission: function(decommissionHostNames, decommission){
- var self = this;
- if (decommissionHostNames == null) {
- decommissionHostNames = [];
- }
- var invocationTag = String(new Date().getTime());
- var context = decommission ? Em.I18n.t('hosts.host.datanode.decommission') : Em.I18n.t('hosts.host.datanode.recommission');
- var clusterName = App.router.get('clusterController.clusterName');
- var clusterUrl = App.apiPrefix + '/clusters/' + clusterName;
- var configsUrl = clusterUrl + '/configurations';
- var configsData = {
- type: "hdfs-exclude-file",
- tag: invocationTag,
- properties: {
- datanodes: decommissionHostNames.join(',')
- }
- };
- var configsAjax = {
- type: 'POST',
- url: configsUrl,
- dataType: 'json',
- data: JSON.stringify(configsData),
- timeout: App.timeout,
- success: function(){
- var actionsUrl = clusterUrl + '/requests';
- var actionsData = {
- RequestInfo: {
- context: context,
- command: 'DECOMMISSION_DATANODE',
- service_name: 'HDFS',
- parameters: {
- excludeFileTag: invocationTag
- }
- }
- };
- var actionsAjax = {
- type: 'POST',
- url: actionsUrl,
- dataType: 'json',
- data: JSON.stringify(actionsData),
- timeout: App.timeout,
- success: function(){
- var persistUrl = App.apiPrefix + '/persist';
- var persistData = {
- "decommissionDataNodesTag": invocationTag
- };
- var persistPutAjax = {
- type: 'POST',
- url: persistUrl,
- dataType: 'json',
- data: JSON.stringify(persistData),
- timeout: App.timeout,
- success: function(){
- var view = self.get('view');
- view.loadDecommissionNodesList();
- }
- };
- jQuery.ajax(persistPutAjax);
- },
- error: function(xhr, textStatus, errorThrown){
- console.log(textStatus);
- console.log(errorThrown);
- }
- };
- jQuery.ajax(actionsAjax);
- },
- error: function(xhr, textStatus, errorThrown){
- console.log(textStatus);
- console.log(errorThrown);
- }
- };
- jQuery.ajax(configsAjax);
- },
-
+
/**
- * send command to server to run recommission on DATANODE
+ * send command to server to run recommission on DATANODE, TASKTRACKER, NODEMANAGER
* @param event
*/
recommission: function(event){
var self = this;
- var decommissionHostNames = this.get('view.decommissionDataNodeHostNames');
- if (decommissionHostNames == null) {
- decommissionHostNames = [];
- }
App.showConfirmationPopup(function(){
var component = event.context;
- // Only HDFS service as of now
var svcName = component.get('service.serviceName');
+ var hostName = self.get('content.hostName');
+ var start_context = Em.I18n.t('requestInfo.startHostComponent') + " " + component.get('displayName');
+ // HDFS service, Recommission datanode
if (svcName === "HDFS") {
- var hostName = self.get('content.hostName');
- var index = decommissionHostNames.indexOf(hostName);
- decommissionHostNames.splice(index, 1);
- self.doDatanodeDecommission(decommissionHostNames, false);
+ self.doRecommissionAndStart(hostName, svcName, "NAMENODE", "DATANODE", start_context);
}
+ // YARN service, Recommission nodeManager
+ if (svcName === "YARN") {
+ self.doRecommissionAndStart(hostName, svcName, "RESOURCEMANAGER", "NODEMANAGER", start_context);
+ }
+ // MAPREDUCE service, Recommission taskTracker
+ if (svcName === "MAPREDUCE") {
+ self.doRecommissionAndRestart(hostName, svcName, "JOBTRACKER", "TASKTRACKER");
+ }
+ // HBASE service, Recommission RegionServer
+ if (svcName === "HBASE") {
+ self.doRecommissionAndStart(hostName, svcName, "HBASE_MASTER", "HBASE_REGIONSERVER", start_context);
+ }
+
// load data (if we need to show this background operations popup) from persist
App.router.get('applicationController').dataLoading().done(function (initValue) {
if (initValue) {
@@ -788,7 +722,209 @@ App.MainHostDetailsController = Em.Controller.extend({
});
});
},
-
+
+ /**
+ * Performs Decommission (for DN, TT and NM)
+ */
+ doDecommission: function(hostName, serviceName, componentName, slaveType){
+ var contextNameString = 'hosts.host.' + slaveType.toLowerCase() + '.decommission';
+ var context = Em.I18n.t(contextNameString);
+ App.ajax.send({
+ name: 'host.host_component.decommission_slave',
+ sender: this,
+ data: {
+ context: context,
+ command: 'DECOMMISSION',
+ hostName: hostName,
+ serviceName: serviceName ,
+ componentName: componentName,
+ slaveType: slaveType
+ },
+ success: 'decommissionSuccessCallback',
+ error: 'decommissionErrorCallback'
+ });
+ },
+
+ /**
+ * Performs Decommission (for RegionServer)
+ */
+ doDecommissionRegionServer: function(hostName, serviceName, componentName, slaveType){
+
+ App.ajax.send({
+ name: 'host.host_component.recommission_and_restart',
+ sender: this,
+ data: {
+ intervalTimeSeconds: 1,
+ toleratePercentage : 50,
+ batches:[
+ {
+ "order_id" : 1,
+ "type" : "POST",
+ "uri" : App.apiPrefix + "/clusters/" + App.get('clusterName') + "/requests",
+ "RequestBodyInfo" : {
+ "RequestInfo" : {
+ "context" : Em.I18n.t('hosts.host.regionserver.decommission.batch1'),
+ "command" : "DECOMMISSION",
+ "service_name" : serviceName,
+ "component_name" : componentName,
+ "parameters" : {
+ "slave_type": slaveType,
+ "excluded_hosts": hostName
+ }
+ }
+ }
+ },
+ {
+ "order_id" : 2,
+ "type" : "PUT",
+ "uri" : App.apiPrefix + "/clusters/" + App.get('clusterName') + "/hosts/" + hostName + "/host_components/" + slaveType.toUpperCase(),
+ "RequestBodyInfo" : {
+ "RequestInfo" : {
+ "context" : Em.I18n.t('hosts.host.regionserver.decommission.batch2')
+ },
+ "Body": {
+ "HostRoles": {
+ "state": 'INSTALLED'
+ }
+ }
+ }
+ },
+ {
+ "order_id" : 3,
+ "type" : "POST",
+ "uri" : App.apiPrefix + "/clusters/" + App.get('clusterName') + "/requests",
+ "RequestBodyInfo" : {
+ "RequestInfo" : {
+ "context" : Em.I18n.t('hosts.host.regionserver.decommission.batch3'),
+ "command" : "DECOMMISSION",
+ "service_name" : serviceName,
+ "component_name" : componentName,
+ "parameters" : {
+ "slave_type": slaveType,
+ "excluded_hosts": hostName,
+ "mark_draining_only": "true"
+ }
+ }
+ }
+ }
+ ]
+ },
+ success: 'decommissionSuccessCallback',
+ error: 'decommissionErrorCallback'
+ });
+ },
+
+ decommissionAndStartSuccessCallback: function (response, request, data) {
+ console.log('Success in decommission callback:' + response);
+ if (!App.testMode) {
+ App.router.get('clusterController').loadUpdatedStatusDelayed(500);
+ }
+ },
+ decommissionSuccessCallback: function (response, request, data) {
+ console.log('Success in decommission callback:' + response);
+ },
+ decommissionErrorCallback: function (request, ajaxOptions, error) {
+ console.log('ERROR: '+ error);
+ },
+
+ doRecommissionAndStart: function(hostName, serviceName, componentName, slaveType, startContext){
+ var contextNameString_1 = 'hosts.host.' + slaveType.toLowerCase() + '.recommission';
+ var context_1 = Em.I18n.t(contextNameString_1);
+ App.ajax.send({
+ name: 'host.host_component.recommission_and_restart',
+ sender: this,
+ data: {
+ intervalTimeSeconds: 1,
+ toleratePercentage : 50,
+ batches:[
+ {
+ "order_id" : 1,
+ "type" : "POST",
+ "uri" : App.apiPrefix + "/clusters/" + App.get('clusterName') + "/requests",
+ "RequestBodyInfo" : {
+ "RequestInfo" : {
+ "context" : context_1,
+ "command" : "DECOMMISSION",
+ "service_name" : serviceName,
+ "component_name" : componentName,
+ "parameters" : {
+ "slave_type": slaveType,
+ "included_hosts": hostName
+ }
+ }
+ }
+ },
+ {
+ "order_id" : 2,
+ "type" : "PUT",
+ "uri" : App.apiPrefix + "/clusters/" + App.get('clusterName') + "/hosts/" + hostName + "/host_components/" + slaveType.toUpperCase(),
+ "RequestBodyInfo" : {
+ "RequestInfo" : {
+ "context" : startContext
+ },
+ "Body": {
+ "HostRoles": {
+ "state": 'STARTED'
+ }
+ }
+ }
+ }
+ ]
+ },
+ success: 'decommissionAndStartSuccessCallback',
+ error: 'decommissionErrorCallback'
+ });
+ },
+ doRecommissionAndRestart: function(hostName, serviceName, componentName, slaveType){
+ var contextNameString_1 = 'hosts.host.' + slaveType.toLowerCase() + '.recommission';
+ var context_1 = Em.I18n.t(contextNameString_1);
+ var contextNameString_2 = 'hosts.host.' + slaveType.toLowerCase() + '.restart';
+ var context_2 = Em.I18n.t(contextNameString_2);
+ App.ajax.send({
+ name: 'host.host_component.recommission_and_restart',
+ sender: this,
+ data: {
+ intervalTimeSeconds: 1,
+ toleratePercentage : 50,
+ batches:[
+ {
+ "order_id" : 1,
+ "type" : "POST",
+ "uri" : App.apiPrefix + "/clusters/" + App.get('clusterName') + "/requests",
+ "RequestBodyInfo" : {
+ "RequestInfo" : {
+ "context" : context_1,
+ "command" : "DECOMMISSION",
+ "service_name" : serviceName,
+ "component_name" : componentName,
+ "parameters" : {
+ "slave_type": slaveType,
+ "included_hosts": hostName
+ }
+ }
+ }
+ },
+ {
+ "order_id" : 2,
+ "type" : "POST",
+ "uri" : App.apiPrefix + "/clusters/" + App.get('clusterName') + "/requests",
+ "RequestBodyInfo" : {
+ "RequestInfo" : {
+ "context" : context_2,
+ "command" : "RESTART",
+ "service_name" : serviceName,
+ "component_name" : slaveType,
+ "hosts" : hostName
+ }
+ }
+ }
+ ]
+ },
+ success: 'decommissionSuccessCallback',
+ error: 'decommissionErrorCallback'
+ });
+ },
+
doAction: function(option) {
switch (option.context.action) {
case "deleteHost":
http://git-wip-us.apache.org/repos/asf/ambari/blob/930c8d90/ambari-web/app/messages.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index 1bf7a52..5e9a68f 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -1401,6 +1401,17 @@ Em.I18n.translations = {
'hosts.host.addComponent.securityNote':'You are running your cluster in secure mode. You must set up the keytab for {0} on {1} before you proceed. Otherwise, the component will not be able to start properly.',
'hosts.host.datanode.decommission':'Decommission DataNode',
'hosts.host.datanode.recommission':'Recommission DataNode',
+ 'hosts.host.nodemanager.decommission':'Decommission NodeManager',
+ 'hosts.host.nodemanager.recommission':'Recommission NodeManager',
+ 'hosts.host.tasktracker.decommission':'Decommission TaskTracker',
+ 'hosts.host.tasktracker.recommission':'Recommission TaskTracker',
+ 'hosts.host.tasktracker.restart':'Restart TaskTracker',
+ 'hosts.host.regionserver.decommission.batch1':'Decommission RegionServer - Turn drain mode on',
+ 'hosts.host.regionserver.decommission.batch2':'Decommission RegionServer - Stop RegionServer',
+ 'hosts.host.regionserver.decommission.batch3':'Decommission RegionServer - Turn drain mode off',
+ 'hosts.host.regionserver.recommission':'Recommission HBase RegionServer',
+ 'hosts.host.decommissioned':'Decommissioned',
+ 'hosts.host.decommissioning':'Decommissioning...',
'hosts.host.alert.noAlerts':'No alerts',
http://git-wip-us.apache.org/repos/asf/ambari/blob/930c8d90/ambari-web/app/templates/main/host/summary.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/host/summary.hbs b/ambari-web/app/templates/main/host/summary.hbs
index ecda7f8..072676c 100644
--- a/ambari-web/app/templates/main/host/summary.hbs
+++ b/ambari-web/app/templates/main/host/summary.hbs
@@ -90,6 +90,38 @@
</li>
{{/if}}
{{/if}}
+ {{#if view.isNodeManager}}
+ {{#if view.isNodeManagerDecommissionAvailable}}
+ <li {{bindAttr class="view.noActionAvailable"}}>
+ <a href="javascript:void(null)" data-toggle="modal" {{action "decommission" view.content target="controller"}}>
+ {{t common.decommission}}
+ </a>
+ </li>
+ {{/if}}
+ {{#if view.isNodeManagerRecommissionAvailable}}
+ <li {{bindAttr class="view.noActionAvailable"}}>
+ <a href="javascript:void(null)" data-toggle="modal" {{action "recommission" view.content target="controller"}}>
+ {{t common.recommission}}
+ </a>
+ </li>
+ {{/if}}
+ {{/if}}
+ {{#if view.isTaskTracker}}
+ {{#if view.isTaskTrackerDecommissionAvailable}}
+ <li {{bindAttr class="view.noActionAvailable"}}>
+ <a href="javascript:void(null)" data-toggle="modal" {{action "decommission" view.content target="controller"}}>
+ {{t common.decommission}}
+ </a>
+ </li>
+ {{/if}}
+ {{#if view.isTaskTrackerRecommissionAvailable}}
+ <li {{bindAttr class="view.noActionAvailable"}}>
+ <a href="javascript:void(null)" data-toggle="modal" {{action "recommission" view.content target="controller"}}>
+ {{t common.recommission}}
+ </a>
+ </li>
+ {{/if}}
+ {{/if}}
{{#if view.isDeletableComponent}}
<li {{bindAttr class="view.isDeleteComponentDisabled:disabled"}}>
<a href="javascript:void(null)" data-toggle="modal" {{action "deleteComponent" view.content target="controller"}}>
http://git-wip-us.apache.org/repos/asf/ambari/blob/930c8d90/ambari-web/app/utils/ajax.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/ajax.js b/ambari-web/app/utils/ajax.js
index c7d73a1..49ce65b 100644
--- a/ambari-web/app/utils/ajax.js
+++ b/ambari-web/app/utils/ajax.js
@@ -327,6 +327,105 @@ var urls = {
}
}
},
+ 'host.host_component.slave_desired_admin_state': {
+ 'real': '/clusters/{clusterName}/hosts/{hostName}/host_components/{componentName}/?fields=HostRoles/desired_admin_state',
+ 'mock': '',
+ 'type': 'GET',
+ 'format': function (data, opt) {
+ return {
+ };
+ }
+ },
+ 'host.host_component.datanodes_decommission_status': {
+ 'real': '/clusters/{clusterName}/services/HDFS/components/NAMENODE/?fields=ServiceComponentInfo',
+ 'mock': '',
+ 'type': 'GET',
+ 'format': function (data, opt) {
+ return {
+ };
+ }
+ },
+ 'host.host_component.nodemanager_decommission_status': {
+ 'real': '/clusters/{clusterName}/services/YARN/components/RESOURCEMANAGER/?fields=ServiceComponentInfo',
+ 'mock': '',
+ 'type': 'GET',
+ 'format': function (data, opt) {
+ return {
+ };
+ }
+ },
+ 'host.host_component.tasktracker_decommission_status': {
+ 'real': '/clusters/{clusterName}/services/MAPREDUCE/components/JOBTRACKER/?fields=ServiceComponentInfo',
+ 'mock': '',
+ 'type': 'GET',
+ 'format': function (data, opt) {
+ return {
+ };
+ }
+ },
+ 'host.host_component.decommission_slave': {
+ 'real' : '/clusters/{clusterName}/requests',
+ 'mock' : '',
+ 'format' : function(data) {
+ return {
+ type : 'POST',
+ data : JSON.stringify({
+ RequestInfo: {
+ 'context': data.context,
+ 'command': data.command,
+ 'service_name': data.serviceName,
+ 'component_name': data.componentName,
+ 'parameters': {
+ 'slave_type': data.slaveType,
+ 'excluded_hosts': data.hostName
+ }
+ }
+ })
+ }
+ }
+ },
+ 'host.host_component.recommission_and_restart': {
+ 'real': '/clusters/{clusterName}/request_schedules',
+ 'mock': '',
+ 'format' : function(data) {
+ return {
+ type : 'POST',
+ data : JSON.stringify([ {
+ "RequestSchedule" : {
+ "batch" : [ {
+ "requests" : data.batches
+ }, {
+ "batch_settings" : {
+ "batch_separation_in_seconds" : data.intervalTimeSeconds,
+ "task_failure_tolerance" : data.toleratePercentage
+ }
+ } ]
+ }
+ } ])
+ }
+ }
+ },
+ 'host.host_component.recommission_slave' : {
+ 'real' : '/clusters/{clusterName}/requests',
+ 'mock' : '',
+ 'format' : function(data) {
+ return {
+ type : 'POST',
+ data : JSON.stringify({
+ RequestInfo: {
+ context: data.context,
+ command: data.command,
+ service_name: data.serviceName,
+ component_name: data.componentName,
+ parameters: {
+ slave_type: data.slaveType,
+ included_hosts: data.hostName
+ }
+ }
+ })
+ }
+ }
+ },
'host.stale_host_components.start_stop': {
'real': '/clusters/{clusterName}/hosts/{hostName}/host_components?HostRoles/stale_configs=true&' +
'HostRoles/component_name.in({componentNames})',
http://git-wip-us.apache.org/repos/asf/ambari/blob/930c8d90/ambari-web/app/views/main/host/summary.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/host/summary.js b/ambari-web/app/views/main/host/summary.js
index dc3f2a6..18875c3 100644
--- a/ambari-web/app/views/main/host/summary.js
+++ b/ambari-web/app/views/main/host/summary.js
@@ -45,70 +45,10 @@ App.MainHostSummaryView = Em.View.extend({
return Em.I18n.t('hosts.host.details.needToRestart').format(this.get('content.componentsWithStaleConfigsCount'), word);
}.property('content.componentsWithStaleConfigsCount'),
- /**
- * @type: [{String}]
- */
- decommissionDataNodeHostNames: null,
-
- loadDecommissionNodesList: function () {
- var self = this;
- var clusterName = App.router.get('clusterController.clusterName');
- var persistUrl = App.apiPrefix + '/persist/decommissionDataNodesTag';
- var clusterUrl = App.apiPrefix + '/clusters/' + clusterName;
- var getConfigAjax = {
- type: 'GET',
- url: persistUrl,
- dataType: 'json',
- timeout: App.timeout,
- success: function (decommissionDataNodesTag) {
- if (decommissionDataNodesTag) {
- // We know the tag which contains the decommisioned nodes.
- var configsUrl = clusterUrl + '/configurations?type=hdfs-exclude-file&tag=' + decommissionDataNodesTag;
- var decomNodesAjax = {
- type: 'GET',
- url: configsUrl,
- dataType: 'json',
- timeout: App.timeout,
- success: function (data) {
- if (data && data.items) {
- var csv = data.items[0].properties.datanodes;
- if (csv!==null && csv.length>0) {
- self.set('decommissionDataNodeHostNames', csv.split(','));
- } else {
- self.set('decommissionDataNodeHostNames', null);
- }
- }
- },
- error: function (xhr, textStatus, errorThrown) {
- console.log(textStatus);
- console.log(errorThrown);
- }
- };
- jQuery.ajax(decomNodesAjax);
- }
- },
- error: function (xhr, textStatus, errorThrown) {
- // No tag pointer in persist. Rely on service's decomNodes.
- var hdfsSvcs = App.HDFSService.find();
- if (hdfsSvcs && hdfsSvcs.get('length') > 0) {
- var hdfsSvc = hdfsSvcs.objectAt(0);
- if (hdfsSvc) {
- var hostNames = [];
- var decomNodes = hdfsSvc.get('decommissionDataNodes');
- decomNodes.forEach(function (decomNode) {
- hostNames.push(decomNode.get('hostName'));
- });
- self.set('decommissionDataNodeHostNames', hostNames);
- }
- }
- }
- };
- jQuery.ajax(getConfigAjax);
- },
didInsertElement: function () {
- if (this.get('content.hostComponents').someProperty('componentName', 'DATANODE')) {
- this.loadDecommissionNodesList();
- }
+ //if (this.get('content.hostComponents').someProperty('componentName', 'DATANODE')) {
+ //this.loadDecommissionNodesList();
+ //}
this.addToolTip();
},
addToolTip: function() {
@@ -287,6 +227,15 @@ App.MainHostSummaryView = Em.View.extend({
if (this.get('isInProgress')) {
this.doBlinking();
}
+ if (this.get('isDataNode')){
+ this.loadDataNodeDecommissionStatus();
+ }
+ if (this.get('isNodeManager')){
+ this.loadNodeManagerDecommissionStatus();
+ }
+ if (this.get('isTaskTracker')){
+ this.loadTaskTrackerDecommissionStatus();
+ }
},
hostComponent: function () {
var hostComponent = null;
@@ -315,17 +264,22 @@ App.MainHostSummaryView = Em.View.extend({
var hostComponent = this.get('hostComponent');
if (hostComponent) {
componentTextStatus = hostComponent.get('componentTextStatus');
- if(this.get("isDataNode"))
- if(this.get('isDataNodeRecommissionAvailable')){
- if(hostComponent.get('isDecommissioning')){
- componentTextStatus = "Decommissioning...";
- } else {
- componentTextStatus = "Decommissioned";
- }
+ if(this.get("isDataNode") && this.get('isDataNodeRecommissionAvailable')){
+ if(this.get('isDataNodeDecommissioning')){
+ componentTextStatus = Em.I18n.t('hosts.host.decommissioning');
+ } else {
+ componentTextStatus = Em.I18n.t('hosts.host.decommissioned');
}
+ }
+ if(this.get("isNodeManager") && this.get('isNodeManagerRecommissionAvailable')){
+ componentTextStatus = Em.I18n.t('hosts.host.decommissioned');
+ }
+ if(this.get("isTaskTracker") && this.get('isTaskTrackerRecommissionAvailable')){
+ componentTextStatus = Em.I18n.t('hosts.host.decommissioned');
+ }
}
return componentTextStatus;
- }.property('workStatus','isDataNodeRecommissionAvailable'),
+ }.property('workStatus','isDataNodeRecommissionAvailable', 'isDataNodeDecommissioning', 'isNodeManagerRecommissionAvailable','isTaskTrackerRecommissionAvailable'),
statusClass: function () {
//If the component is DataNode
@@ -335,6 +289,20 @@ App.MainHostSummaryView = Em.View.extend({
}
}
+ //If the component is NodeManager
+ if (this.get('isNodeManager')) {
+ if (this.get('isNodeManagerRecommissionAvailable') && (this.get('isStart') || this.get('workStatus') == 'INSTALLED')) {
+ return 'health-status-DEAD-ORANGE';
+ }
+ }
+
+ //If the component is TaskTracker
+ if (this.get('isTaskTracker')) {
+ if (this.get('isTaskTrackerRecommissionAvailable') && (this.get('isStart') || this.get('workStatus') == 'INSTALLED')) {
+ return 'health-status-DEAD-ORANGE';
+ }
+ }
+
//Class when install failed
if (this.get('workStatus') === App.HostComponentStatus.install_failed) {
return 'health-status-color-red icon-cog';
@@ -352,7 +320,7 @@ App.MainHostSummaryView = Em.View.extend({
//For all other cases
return 'health-status-' + App.HostComponentStatus.getKeyName(this.get('workStatus'));
- }.property('workStatus', 'isDataNodeRecommissionAvailable', 'this.content.isDecommissioning'),
+ }.property('workStatus', 'isDataNodeRecommissionAvailable', 'isNodeManagerRecommissionAvailable', 'isTaskTrackerRecommissionAvailable'),
disabled: function () {
return (this.get('parentView.content.healthClass') === "health-status-DEAD-YELLOW") ? 'disabled' : '';
@@ -391,13 +359,13 @@ App.MainHostSummaryView = Em.View.extend({
}
},
/**
- * Start blinking when host component is starting/stopping
+ * Start blinking when host component is starting/stopping/decommissioning
*/
startBlinking: function () {
this.$('.components-health').stop(true, true);
this.$('.components-health').css({opacity: 1.0});
this.doBlinking();
- }.observes('workStatus','isDataNodeRecommissionAvailable'),
+ }.observes('workStatus','isDataNodeRecommissionAvailable', 'isDecommissioning'),
isStart: function () {
return (this.get('workStatus') == App.HostComponentStatus.started || this.get('workStatus') == App.HostComponentStatus.starting);
@@ -426,43 +394,334 @@ App.MainHostSummaryView = Em.View.extend({
return (this.get('workStatus') === App.HostComponentStatus.stopping ||
this.get('workStatus') === App.HostComponentStatus.starting) ||
this.get('isDecommissioning');
- }.property('workStatus', 'isDataNodeRecommissionAvailable'),
- /**
- * Shows whether we need to show Decommision/Recomission buttons
- */
+ }.property('workStatus', 'isDecommissioning'),
+
isDataNode: function () {
return this.get('content.componentName') === 'DATANODE';
}.property('content'),
-
- isDecommissioning: function () {
- var hostComponentDecommissioning = this.get('hostComponent.isDecommissioning');
- return this.get('isDataNode') && this.get("isDataNodeRecommissionAvailable") && hostComponentDecommissioning;
- }.property("workStatus", "isDataNodeRecommissionAvailable", "hostComponent.isDecommissioning"),
+ isNodeManager: function () {
+ return this.get('content.componentName') === 'NODEMANAGER';
+ }.property('content'),
+ isTaskTracker: function () {
+ return this.get('content.componentName') === 'TASKTRACKER';
+ }.property('content'),
+ isRegionServer: function () {
+ return this.get('content.componentName') === 'HBASE_REGIONSERVER';
+ }.property('content'),
isInMaintenance: function () {
return (this.get('workStatus') == App.HostComponentStatus.maintenance);
}.property("workStatus"),
+
+ isDecommissioning: function () {
+ //the slaves is decommissioning.
+ return this.get('isDataNode') && this.get("isDataNodeDecommissioning");
+ }.property("workStatus", "isDataNodeDecommissioning"),
+
+ isDataNodeDecommissioning: null,
+ isDataNodeDecommissionAvailable: null,
+ isDataNodeRecommissionAvailable: null,
+
+ /**
+ * load Recommission/Decommission status from adminState of each live node
+ */
+ loadDataNodeDecommissionStatus: function () {
+ var clusterName = App.router.get('clusterController.clusterName');
+ var hostName = App.router.get('mainHostDetailsController.content.hostName');
+ var componentName = 'NAMENODE';
+ var slaveType = 'DATANODE';
+ var version = App.get('currentStackVersionNumber');
+ var dfd = $.Deferred();
+ var self = this;
+ this.getDNDecommissionStatus(clusterName, hostName, componentName).done(function () {
+ var curObj = self.get('decommissionedStatusObject');
+ self.set('decommissionedStatusObject', null);
+ // HDP-2 stack
+ if (version.charAt(0) == 2) {
+ if (curObj) {
+ var liveNodesJson = App.parseJSON(curObj.LiveNodes);
+ if (liveNodesJson && liveNodesJson[hostName] ) {
+ switch(liveNodesJson[hostName].adminState) {
+ case "In Service":
+ self.set('isDataNodeRecommissionAvailable', false);
+ self.set('isDataNodeDecommissioning', false);
+ self.set('isDataNodeDecommissionAvailable', self.get('isStart'));
+ break;
+ case "Decommission In Progress":
+ self.set('isDataNodeRecommissionAvailable', true);
+ self.set('isDataNodeDecommissioning', true);
+ self.set('isDataNodeDecommissionAvailable', false);
+ break;
+ case "Decommissioned":
+ self.set('isDataNodeRecommissionAvailable', true);
+ self.set('isDataNodeDecommissioning', false);
+ self.set('isDataNodeDecommissionAvailable', false);
+ break;
+ }
+ } else {
+ // if namenode is down, get desired_admin_state to decide if the used had issued a decommission
+ var deferred = $.Deferred();
+ self.getDesiredAdminState(clusterName, hostName, slaveType).done( function () {
+ var desired_admin_state = self.get('desiredAdminState');
+ self.set('desiredAdminState', null);
+ switch(desired_admin_state) {
+ case "INSERVICE":
+ self.set('isDataNodeRecommissionAvailable', false);
+ self.set('isDataNodeDecommissioning', false);
+ self.set('isDataNodeDecommissionAvailable', self.get('isStart'));
+ break;
+ case "DECOMMISSIONED":
+ self.set('isDataNodeRecommissionAvailable', true);
+ self.set('isDataNodeDecommissioning', false);
+ self.set('isDataNodeDecommissionAvailable', false);
+ break;
+ }
+ deferred.resolve(desired_admin_state);
+ });
+ }
+ }
+ }
+ // HDP-1 stack
+ if (version.charAt(0) == 1) {
+ if (curObj) {
+ var liveNodesJson = App.parseJSON(curObj.LiveNodes);
+ var decomNodesJson = App.parseJSON(curObj.DecomNodes);
+ var deadNodesJson = App.parseJSON(curObj.DeadNodes);
+ if (decomNodesJson && decomNodesJson[hostName] ) {
+ self.set('isDataNodeRecommissionAvailable', true);
+ self.set('isDataNodeDecommissioning', true);
+ self.set('isDataNodeDecommissionAvailable', false);
+ } else if (deadNodesJson && deadNodesJson[hostName] ) {
+ self.set('isDataNodeRecommissionAvailable', true);
+ self.set('isDataNodeDecommissioning', false);
+ self.set('isDataNodeDecommissionAvailable', false);
+ } else if (liveNodesJson && liveNodesJson[hostName] ) {
+ self.set('isDataNodeRecommissionAvailable', false);
+ self.set('isDataNodeDecommissioning', false);
+ self.set('isDataNodeDecommissionAvailable', self.get('isStart'));
+ } else {
+ // if namenode is down, get desired_admin_state to decide if the used had issued a decommission
+ var deferred = $.Deferred();
+ self.getDesiredAdminState(clusterName, hostName, slaveType).done( function () {
+ var desired_admin_state = self.get('desiredAdminState');
+ self.set('desiredAdminState', null);
+ switch(desired_admin_state) {
+ case "INSERVICE":
+ self.set('isDataNodeRecommissionAvailable', false);
+ self.set('isDataNodeDecommissioning', false);
+ self.set('isDataNodeDecommissionAvailable', self.get('isStart'));
+ break;
+ case "DECOMMISSIONED":
+ self.set('isDataNodeRecommissionAvailable', true);
+ self.set('isDataNodeDecommissioning', false);
+ self.set('isDataNodeDecommissionAvailable', false);
+ break;
+ }
+ deferred.resolve(desired_admin_state);
+ });
+ }
+ }
+ }
+ dfd.resolve(curObj);
+ });
+ return dfd.promise();
+ }.observes('App.router.mainHostDetailsController.content'),
+
+ /**
+ * get datanodes decommission status: from NAMENODE component, liveNodes property
+ */
+ getDNDecommissionStatus: function(clusterName, hostName, componentName){
+ return App.ajax.send({
+ name: 'host.host_component.datanodes_decommission_status',
+ sender: this,
+ data: {
+ clusterName: clusterName,
+ hostName: hostName,
+ componentName: componentName
+ },
+ success: 'getDNDecommissionStatusSuccessCallback',
+ error: 'getDNDecommissionStatusErrorCallback'
+ });
+ },
+ decommissionedStatusObject: null,
+ getDNDecommissionStatusSuccessCallback: function (response, request, data) {
+ var statusObject = response.ServiceComponentInfo;
+ if ( statusObject != null) {
+ this.set('decommissionedStatusObject', statusObject);
+ return statusObject;
+ }
+ },
+ getDNDecommissionStatusErrorCallback: function (request, ajaxOptions, error) {
+ console.log('ERROR: '+ error);
+ this.set('decommissionedStatusObject', null);
+ return null;
+ },
+
+ /**
+ * get desired_admin_state status of DataNode, TaskTracker, NodeManager and RegionServer
+ */
+ getDesiredAdminState: function(clusterName, hostName, componentName){
+ return App.ajax.send({
+ name: 'host.host_component.slave_desired_admin_state',
+ sender: this,
+ data: {
+ clusterName: clusterName,
+ hostName: hostName,
+ componentName: componentName
+ },
+ success: 'getDesiredAdminStateSuccessCallback',
+ error: 'getDesiredAdminStateErrorCallback'
+ });
+ },
+ desiredAdminState: null,
+ getDesiredAdminStateSuccessCallback: function (response, request, data) {
+ var status = response.HostRoles.desired_admin_state;
+ if ( status != null) {
+ this.set('desiredAdminState', status);
+ return status;
+ }
+ },
+ getDesiredAdminStateErrorCallback: function (request, ajaxOptions, error) {
+ console.log('ERROR: '+ error);
+ this.set('desiredAdminState', null);
+ return null;
+ },
+
+ isNodeManagerDecommissionAvailable: null,
+ isNodeManagerRecommissionAvailable: null,
+
/**
- * Set in template via binding from parent view
+ * load Recommission/Decommission status for nodeManager from nodeManagers list
*/
- decommissionDataNodeHostNames: null,
+ loadNodeManagerDecommissionStatus: function () {
+ var clusterName = App.router.get('clusterController.clusterName');
+ var hostName = App.router.get('mainHostDetailsController.content.hostName');
+ var componentName = 'RESOURCEMANAGER';
+ var slaveType = 'NODEMANAGER';
+ var dfd = $.Deferred();
+ var self = this;
+ this.getNMDecommissionStatus(clusterName, hostName, componentName).done(function () {
+ var curObj = self.get('decommissionedStatusObject');
+ self.set('decommissionedStatusObject', null);
+ if (curObj && curObj.rm_metrics) {
+ var nodeManagersArray = App.parseJSON(curObj.rm_metrics.cluster.nodeManagers);
+ if (nodeManagersArray.findProperty('HostName', hostName)){
+ self.set('isNodeManagerRecommissionAvailable', false);
+ self.set('isNodeManagerDecommissionAvailable', self.get('isStart'));
+ } else {
+ self.set('isNodeManagerRecommissionAvailable', true);
+ self.set('isNodeManagerDecommissionAvailable', false);
+ }
+ } else if (!curObj.rm_metrics) {
+ // if ResourceManager is down, get desired_admin_state of NM to decide if the used had issued a decommission
+ var deferred = $.Deferred();
+ self.getDesiredAdminState(clusterName, hostName, slaveType).done( function () {
+ var desired_admin_state = self.get('desiredAdminState');
+ self.set('desiredAdminState', null);
+ switch(desired_admin_state) {
+ case "INSERVICE":
+ self.set('isNodeManagerRecommissionAvailable', false);
+ self.set('isNodeManagerDecommissionAvailable', self.get('isStart'));
+ break;
+ case "DECOMMISSIONED":
+ self.set('isNodeManagerRecommissionAvailable', true);
+ self.set('isNodeManagerDecommissionAvailable', false);
+ break;
+ }
+ deferred.resolve(desired_admin_state);
+ });
+ }
+ dfd.resolve(curObj);
+ });
+ return dfd.promise();
+ }.observes('App.router.mainHostDetailsController.content'),
+
/**
- * Decommission is available whenever the service is started.
+ * get NodeManager decommission status: from RESOURCEMANAGER component, rm_metrics/nodeManagers property
*/
- isDataNodeDecommissionAvailable: function () {
- return this.get('isStart') && !this.get('isDataNodeRecommissionAvailable');
- }.property('isStart', 'isDataNodeRecommissionAvailable'),
+ getNMDecommissionStatus: function(clusterName, hostName, componentName){
+ return App.ajax.send({
+ name: 'host.host_component.nodemanager_decommission_status',
+ sender: this,
+ data: {
+ clusterName: clusterName,
+ hostName: hostName,
+ componentName: componentName
+ },
+ success: 'getDNDecommissionStatusSuccessCallback',
+ error: 'getDNDecommissionStatusErrorCallback'
+ });
+ },
+
+ isTaskTrackerDecommissionAvailable: null,
+ isTaskTrackerRecommissionAvailable: null,
/**
- * Recommission is available only when this hostname shows up in the
- * 'decommissionDataNodeHostNames'
+ * load Recommission/Decommission status for TaskTracker from JobTracker/AliveNodes list
*/
- isDataNodeRecommissionAvailable: function () {
- var decommissionHostNames = this.get('decommissionDataNodeHostNames');
+ loadTaskTrackerDecommissionStatus: function () {
+ var clusterName = App.router.get('clusterController.clusterName');
var hostName = App.router.get('mainHostDetailsController.content.hostName');
- return decommissionHostNames != null && decommissionHostNames.contains(hostName);
- }.property('App.router.mainHostDetailsController.content', 'decommissionDataNodeHostNames'),
+ var componentName = 'JOBTRACKER';
+ var slaveType = 'TASKTRACKER';
+ var dfd = $.Deferred();
+ var self = this;
+ this.getTTDecommissionStatus(clusterName, hostName, componentName).done(function () {
+ var curObj = self.get('decommissionedStatusObject');
+ self.set('decommissionedStatusObject', null);
+ if (curObj) {
+ var aliveNodesArray = App.parseJSON(curObj.AliveNodes);
+ if (aliveNodesArray != null) {
+ if (aliveNodesArray.findProperty('hostname', hostName)){
+ self.set('isTaskTrackerRecommissionAvailable', false);
+ self.set('isTaskTrackerDecommissionAvailable', self.get('isStart'));
+ } else {
+ self.set('isTaskTrackerRecommissionAvailable', true);
+ self.set('isTaskTrackerDecommissionAvailable', false);
+ }
+ }
+ } else {
+ // if JobTracker is down, get desired_admin_state of TT to decide if the used had issued a decommission
+ var deferred = $.Deferred();
+ self.getDesiredAdminState(clusterName, hostName, slaveType).done( function () {
+ var desired_admin_state = self.get('desiredAdminState');
+ self.set('desiredAdminState', null);
+ switch(desired_admin_state) {
+ case "INSERVICE":
+ self.set('isTaskTrackerRecommissionAvailable', false);
+ self.set('isTaskTrackerDecommissionAvailable', self.get('isStart'));
+ break;
+ case "DECOMMISSIONED":
+ self.set('isTaskTrackerRecommissionAvailable', true);
+ self.set('isTaskTrackerDecommissionAvailable', false);
+ break;
+ }
+ deferred.resolve(desired_admin_state);
+ });
+ }
+ dfd.resolve(curObj);
+ });
+ return dfd.promise();
+ }.observes('App.router.mainHostDetailsController.content'),
+
+ /**
+ * get TaskTracker decommission status: from JobTracker component, AliveNodes property
+ */
+ getTTDecommissionStatus: function(clusterName, hostName, componentName){
+ return App.ajax.send({
+ name: 'host.host_component.tasktracker_decommission_status',
+ sender: this,
+ data: {
+ clusterName: clusterName,
+ hostName: hostName,
+ componentName: componentName
+ },
+ success: 'getDNDecommissionStatusSuccessCallback',
+ error: 'getDNDecommissionStatusErrorCallback'
+ });
+ },
+
/**
* Shows whether we need to show Delete button