You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by ha...@apache.org on 2020/06/19 14:00:52 UTC
[ambari] branch trunk updated: [AMBARI-25208] : Enable/Disable
HBase Cross Cluster Replication (without common-service changes for trunk)
(#3014) (virajjasani via dgrinenko)
This is an automated email from the ASF dual-hosted git repository.
hapylestat pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ambari.git
The following commit(s) were added to refs/heads/trunk by this push:
new a42d52f [AMBARI-25208] : Enable/Disable HBase Cross Cluster Replication (without common-service changes for trunk) (#3014) (virajjasani via dgrinenko)
a42d52f is described below
commit a42d52f7999592c96f67ad114d27f7b8a2a92e66
Author: Viraj Jasani <vi...@gmail.com>
AuthorDate: Fri Jun 19 19:30:42 2020 +0530
[AMBARI-25208] : Enable/Disable HBase Cross Cluster Replication (without common-service changes for trunk) (#3014) (virajjasani via dgrinenko)
---
.../BackgroundCustomCommandExecutionTest.java | 102 ++++++++++++++-
.../stacks/HDP/2.0.5/services/HBASE/metainfo.xml | 16 +++
ambari-web/app/controllers/main/service/item.js | 140 +++++++++++++++++++++
ambari-web/app/messages.js | 15 +++
ambari-web/app/models/host_component.js | 16 +++
ambari-web/app/styles/alerts.less | 20 +++
ambari-web/app/styles/application.less | 3 +
.../modal_popups/update_replication_popup.hbs | 61 +++++++++
ambari-web/app/utils/ajax/ajax.js | 51 ++++++++
ambari-web/app/views/main/service/item.js | 14 ++-
10 files changed, 433 insertions(+), 5 deletions(-)
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/BackgroundCustomCommandExecutionTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/BackgroundCustomCommandExecutionTest.java
index 89d0630..c979984 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/BackgroundCustomCommandExecutionTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/BackgroundCustomCommandExecutionTest.java
@@ -77,6 +77,13 @@ public class BackgroundCustomCommandExecutionTest {
private Clusters clusters;
private static final String REQUEST_CONTEXT_PROPERTY = "context";
+ private static final String UPDATE_REPLICATION_PARAMS = "{\n" +
+ " \"replication_cluster_keys\": c7007.ambari.apache.org,c7008.ambari.apache.org,c7009.ambari.apache.org:2181:/hbase,\n" +
+ " \"replication_peers\": 1\n" +
+ " }";
+ private static final String STOP_REPLICATION_PARAMS = "{\n" +
+ " \"replication_peers\": 1\n" +
+ " }";
@Captor ArgumentCaptor<Request> requestCapture;
@Mock ActionManager am;
@@ -180,15 +187,18 @@ public class BackgroundCustomCommandExecutionTest {
createCluster("c1");
addHost("c6401","c1");
addHost("c6402","c1");
+ addHost("c7007", "c1");
clusters.updateHostMappings(clusters.getHost("c6401"));
clusters.updateHostMappings(clusters.getHost("c6402"));
+ clusters.updateHostMappings(clusters.getHost("c7007"));
clusters.getCluster("c1");
createService("c1", "HDFS", null);
-
- createServiceComponent("c1","HDFS","NAMENODE", State.INIT);
-
- createServiceComponentHost("c1","HDFS","NAMENODE","c6401", null);
+ createService("c1", "HBASE", null);
+ createServiceComponent("c1", "HDFS", "NAMENODE", State.INIT);
+ createServiceComponent("c1", "HBASE", "HBASE_MASTER", State.INIT);
+ createServiceComponentHost("c1", "HDFS", "NAMENODE", "c6401", null);
+ createServiceComponentHost("c1", "HBASE", "HBASE_MASTER", "c7007", null);
}
private void addHost(String hostname, String clusterName) throws AmbariException {
clusters.addHost(hostname);
@@ -206,6 +216,90 @@ public class BackgroundCustomCommandExecutionTest {
host.setHostAttributes(hostAttributes);
}
+
+ @SuppressWarnings("serial")
+ @Test
+ public void testUpdateHBaseReplicationCustomCommand()
+ throws AuthorizationException, AmbariException, IllegalAccessException,
+ NoSuchFieldException {
+ createClusterFixture();
+ Map<String, String> requestProperties = new HashMap<String, String>() {
+ {
+ put(REQUEST_CONTEXT_PROPERTY, "Enable Cross Cluster HBase Replication");
+ put("command", "UPDATE_REPLICATION");
+ put("parameters", UPDATE_REPLICATION_PARAMS);
+ }
+ };
+ ExecuteActionRequest actionRequest = new ExecuteActionRequest("c1",
+ "UPDATE_REPLICATION", new HashMap<>(), false);
+ actionRequest.getResourceFilters().add(new RequestResourceFilter("HBASE", "HBASE_MASTER",
+ Collections.singletonList("c7007")));
+
+ controller.createAction(actionRequest, requestProperties);
+
+ Mockito.verify(am, Mockito.times(1))
+ .sendActions(requestCapture.capture(), any(ExecuteActionRequest.class));
+
+ Request request = requestCapture.getValue();
+ Assert.assertNotNull(request);
+ Assert.assertNotNull(request.getStages());
+ Assert.assertEquals(1, request.getStages().size());
+ Stage stage = request.getStages().iterator().next();
+
+ Assert.assertEquals(1, stage.getHosts().size());
+
+ List<ExecutionCommandWrapper> commands = stage.getExecutionCommands("c7007");
+ Assert.assertEquals(1, commands.size());
+ ExecutionCommand command = commands.get(0).getExecutionCommand();
+ Assert.assertEquals(AgentCommandType.EXECUTION_COMMAND, command.getCommandType());
+ Assert.assertEquals("UPDATE_REPLICATION", command.getCommandParams().get("custom_command"));
+
+ }
+
+
+
+ @SuppressWarnings("serial")
+ @Test
+ public void testStopHBaseReplicationCustomCommand()
+ throws AuthorizationException, AmbariException, IllegalAccessException,
+ NoSuchFieldException {
+ createClusterFixture();
+ Map<String, String> requestProperties = new HashMap<String, String>() {
+ {
+ put(REQUEST_CONTEXT_PROPERTY, "Disable Cross Cluster HBase Replication");
+ put("command", "STOP_REPLICATION");
+ put("parameters", STOP_REPLICATION_PARAMS);
+ }
+ };
+ ExecuteActionRequest actionRequest = new ExecuteActionRequest("c1",
+ "STOP_REPLICATION", new HashMap<>(), false);
+ actionRequest.getResourceFilters().add(new RequestResourceFilter("HBASE", "HBASE_MASTER",
+ Collections.singletonList("c7007")));
+
+ controller.createAction(actionRequest, requestProperties);
+
+ Mockito.verify(am, Mockito.times(1))
+ .sendActions(requestCapture.capture(), any(ExecuteActionRequest.class));
+
+ Request request = requestCapture.getValue();
+ Assert.assertNotNull(request);
+ Assert.assertNotNull(request.getStages());
+ Assert.assertEquals(1, request.getStages().size());
+ Stage stage = request.getStages().iterator().next();
+
+ Assert.assertEquals(1, stage.getHosts().size());
+
+ List<ExecutionCommandWrapper> commands = stage.getExecutionCommands("c7007");
+ Assert.assertEquals(1, commands.size());
+ ExecutionCommand command = commands.get(0).getExecutionCommand();
+ Assert.assertEquals(AgentCommandType.EXECUTION_COMMAND, command.getCommandType());
+ Assert.assertEquals("STOP_REPLICATION", command.getCommandParams().get("custom_command"));
+
+ }
+
+
+
+
private void createCluster(String clusterName) throws AmbariException, AuthorizationException {
ClusterRequest r = new ClusterRequest(null, clusterName, State.INSTALLED.name(),
SecurityType.NONE, STACK_ID.getStackId(), null);
diff --git a/ambari-server/src/test/resources/stacks/HDP/2.0.5/services/HBASE/metainfo.xml b/ambari-server/src/test/resources/stacks/HDP/2.0.5/services/HBASE/metainfo.xml
index 322a190..57e6125 100644
--- a/ambari-server/src/test/resources/stacks/HDP/2.0.5/services/HBASE/metainfo.xml
+++ b/ambari-server/src/test/resources/stacks/HDP/2.0.5/services/HBASE/metainfo.xml
@@ -59,6 +59,22 @@
<timeout>600</timeout>
</commandScript>
</customCommand>
+ <customCommand>
+ <name>UPDATE_REPLICATION</name>
+ <commandScript>
+ <script>scripts/hbase_master.py</script>
+ <scriptType>PYTHON</scriptType>
+ <timeout>600</timeout>
+ </commandScript>
+ </customCommand>
+ <customCommand>
+ <name>STOP_REPLICATION</name>
+ <commandScript>
+ <script>scripts/hbase_master.py</script>
+ <scriptType>PYTHON</scriptType>
+ <timeout>600</timeout>
+ </commandScript>
+ </customCommand>
</customCommands>
</component>
diff --git a/ambari-web/app/controllers/main/service/item.js b/ambari-web/app/controllers/main/service/item.js
index 0a7f1e3..d749c31 100644
--- a/ambari-web/app/controllers/main/service/item.js
+++ b/ambari-web/app/controllers/main/service/item.js
@@ -937,6 +937,146 @@ App.MainServiceItemController = Em.Controller.extend(App.SupportClientConfigsDow
});
},
+ /**
+ * On click handler for Update HBase Replication command from items menu
+ */
+ updateHBaseReplication: function () {
+ const controller = this;
+ App.ModalPopup.show({
+ classNames: ['sixty-percent-width-modal', 'service-params-popup'],
+ header: Em.I18n.t('services.service.actions.run.updateHBaseReplication.context'),
+ primary: Em.I18n.t('common.start'),
+ secondary: Em.I18n.t('common.cancel'),
+ peerId: '',
+ parentzkey: '/hbase',
+ zkport: '2181',
+ zkquorum: '',
+ errorMessage: Em.I18n.t('services.service.actions.run.updateHBaseReplication.promptError'),
+ isInvalid: function () {
+ const zkquorum = this.get('zkquorum');
+ const zkport = this.get('zkport');
+ const parentzkey = this.get('parentzkey');
+ const peerId = this.get('peerId');
+ if (zkquorum && zkport && parentzkey && peerId) {
+ if (isNaN(zkport) || isNaN(peerId)) {
+ return true;
+ }
+ const zkquorumArray = zkquorum.split(',');
+ return zkquorumArray.length < 2;
+ } else {
+ return true;
+ }
+ }.property('zkquorum', 'zkport', 'parentzkey', 'peerId'),
+ disablePrimary: Em.computed.alias('isInvalid'),
+ onPrimary: function () {
+ if (this.get('isInvalid')) {
+ return;
+ }
+ App.ajax.send({
+ name: 'service.item.updateHBaseReplication',
+ sender: controller,
+ data: {
+ hosts: App.Service.find('HBASE').get('hostComponents').findProperty('componentName', 'HBASE_MASTER').get('hostName'),
+ replication_peers: this.get('peerId'),
+ replication_cluster_keys: this.get('zkquorum') + ':' + this.get('zkport') + ":" + this.get('parentzkey')
+ },
+ success: 'updateHBaseReplicationSuccessCallback',
+ error: 'updateHBaseReplicationErrorCallback',
+ showLoadingPopup: true
+ });
+ this.hide();
+ },
+ bodyClass: Ember.View.extend({
+ templateName: require('templates/common/modal_popups/update_replication_popup'),
+ zkquorumText: Em.I18n.t('services.service.actions.run.updateHBaseReplication.zkquorumText.prompt'),
+ zkportText: Em.I18n.t('services.service.actions.run.updateHBaseReplication.zkportText.prompt'),
+ parentzkeyText: Em.I18n.t('services.service.actions.run.updateHBaseReplication.parentzkeyText.prompt'),
+ peerIdText: Em.I18n.t('services.service.actions.run.updateHBaseReplication.peerIdText.prompt')
+ })
+ });
+ },
+
+ updateHBaseReplicationSuccessCallback: function (data) {
+ if (data.Requests.id) {
+ App.router.get('backgroundOperationsController').showPopup();
+ }
+ },
+
+ updateHBaseReplicationErrorCallback: function (data) {
+ var error = Em.I18n.t('services.service.actions.run.updateHBaseReplication.error');
+ if (data && data.responseText) {
+ try {
+ const json = $.parseJSON(data.responseText);
+ error += json.message;
+ } catch (err) {
+ console.log(err);
+ }
+ }
+ App.showAlertPopup(Em.I18n.t('services.service.actions.run.updateHBaseReplication.error'), error);
+ },
+
+
+ /**
+ * On click handler for Stop HBase Replication command from items menu
+ */
+ stopHBaseReplication: function () {
+ const controller = this;
+ App.ModalPopup.show({
+ classNames: ['forty-percent-width-modal'],
+ header: Em.I18n.t('services.service.actions.run.stopHBaseReplication.context'),
+ primary: Em.I18n.t('common.start'),
+ secondary: Em.I18n.t('common.cancel'),
+ inputValue: '',
+ errorMessage: Em.I18n.t('services.service.actions.run.stopHBaseReplication.promptError'),
+ isInvalid: function () {
+ const inputValue = this.get('inputValue');
+ return !inputValue || isNaN(inputValue);
+ }.property('inputValue'),
+ disablePrimary: Em.computed.alias('isInvalid'),
+ onPrimary: function () {
+ if (this.get('isInvalid')) {
+ return;
+ }
+ App.ajax.send({
+ name: 'service.item.stopHBaseReplication',
+ sender: controller,
+ data: {
+ hosts: App.Service.find('HBASE').get('hostComponents').findProperty('componentName', 'HBASE_MASTER').get('hostName'),
+ replication_peers: this.get('inputValue')
+ },
+ success: 'stopHBaseReplicationSuccessCallback',
+ error: 'stopHBaseReplicationErrorCallback',
+ showLoadingPopup: true
+ });
+ this.hide();
+ },
+ bodyClass: Ember.View.extend({
+ templateName: require('templates/common/modal_popups/prompt_popup'),
+ text: Em.I18n.t('services.service.actions.run.stopHBaseReplication.prompt'),
+ })
+ });
+ },
+
+ stopHBaseReplicationSuccessCallback: function (data) {
+ if (data.Requests.id) {
+ App.router.get('backgroundOperationsController').showPopup();
+ }
+ },
+
+ stopHBaseReplicationErrorCallback: function (data) {
+ var error = Em.I18n.t('services.service.actions.run.stopHBaseReplication.error');
+ if (data && data.responseText) {
+ try {
+ const json = $.parseJSON(data.responseText);
+ error += json.message;
+ } catch (err) {
+ console.log(err);
+ }
+ }
+ App.showAlertPopup(Em.I18n.t('services.service.actions.run.stopHBaseReplication.error'), error);
+ },
+
+
restartAllHostComponents: function (serviceName) {
const serviceDisplayName = this.get('content.displayName'),
bodyMessage = Em.Object.create({
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index cc8e159..89a8f15 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -2111,6 +2111,21 @@ Em.I18n.translations = {
'services.service.actions.run.stopLdapKnox.title':'Stop Demo LDAP Knox Gateway',
'services.service.actions.run.stopLdapKnox.context':'Stop Demo LDAP',
'services.service.actions.run.startStopLdapKnox.error': 'Error during remote command: ',
+ 'services.service.actions.run.updateHBaseReplication.label': 'Start/Update HBase Replication',
+ 'services.service.actions.run.updateHBaseReplication.context': 'Enable Cross Cluster HBase Replication',
+ 'services.service.actions.run.updateHBaseReplication.title': 'HBase Replication: Start/Update',
+ 'services.service.actions.run.updateHBaseReplication.promptError': 'ZKQuorum should be comma(,) separated ZK nodes. Port and Peer ID should be number',
+ 'services.service.actions.run.updateHBaseReplication.zkquorumText.prompt': 'Peer Cluster ZK Quorum: ',
+ 'services.service.actions.run.updateHBaseReplication.zkportText.prompt': 'Peer Cluster ZK Port: ',
+ 'services.service.actions.run.updateHBaseReplication.parentzkeyText.prompt': 'Parent ZKey for HBase: ',
+ 'services.service.actions.run.updateHBaseReplication.peerIdText.prompt': 'Peer Cluster ID: ',
+ 'services.service.actions.run.updateHBaseReplication.error':'Error while setting up HBase Cross Cluster Replication ',
+ 'services.service.actions.run.stopHBaseReplication.label': 'Stop HBase Replication',
+ 'services.service.actions.run.stopHBaseReplication.context': 'Disable Cross Cluster HBase Replication',
+ 'services.service.actions.run.stopHBaseReplication.title': 'HBase Replication: Stop',
+ 'services.service.actions.run.stopHBaseReplication.promptError': 'Peer ID should be number',
+ 'services.service.actions.run.stopHBaseReplication.error': 'Error while disabling HBase Cross Cluster Replication ',
+ 'services.service.actions.run.stopHBaseReplication.prompt': 'Peer Cluster ID to remove from Replication Peer list: ',
// Hive Server Interactive custom command to restart LLAP
'services.service.actions.run.restartLLAP':'Restart LLAP',
diff --git a/ambari-web/app/models/host_component.js b/ambari-web/app/models/host_component.js
index 92014ba..87a6439 100644
--- a/ambari-web/app/models/host_component.js
+++ b/ambari-web/app/models/host_component.js
@@ -574,6 +574,22 @@ App.HostComponentActionMap = {
label: Em.I18n.t('admin.nameNodeFederation.button.enable'),
cssClass: 'icon icon-sitemap',
disabled: !App.get('isHaEnabled')
+ },
+ UPDATE_REPLICATION: {
+ action: 'updateHBaseReplication',
+ customCommand: 'UPDATE_REPLICATION',
+ context: Em.I18n.t('services.service.actions.run.updateHBaseReplication.context'),
+ label: Em.I18n.t('services.service.actions.run.updateHBaseReplication.label'),
+ cssClass: 'glyphicon glyphicon-refresh',
+ disabled: false
+ },
+ STOP_REPLICATION: {
+ action: 'stopHBaseReplication',
+ customCommand: 'STOP_REPLICATION',
+ context: Em.I18n.t('services.service.actions.run.stopHBaseReplication.context'),
+ label: Em.I18n.t('services.service.actions.run.stopHBaseReplication.label'),
+ cssClass: 'glyphicon glyphicon-refresh',
+ disabled: false
}
};
},
diff --git a/ambari-web/app/styles/alerts.less b/ambari-web/app/styles/alerts.less
index 0bac6a4..2bdf6e0 100644
--- a/ambari-web/app/styles/alerts.less
+++ b/ambari-web/app/styles/alerts.less
@@ -496,6 +496,26 @@
width: 95%;
}
+.service-params-popup {
+ .modal {
+ .modal-dialog {
+ width: 55%;
+ .modal-content {
+ height: 60%;
+ .modal-body {
+ padding-left: 0;
+ padding-right: 0;
+ height: 75%;
+ font-size: 14px;
+ .definition-latest-text, .timeago {
+ font-size: 12px;
+ }
+ }
+ }
+ }
+ }
+}
+
.alerts-popup-wrap {
#alert-info {
overflow: auto;
diff --git a/ambari-web/app/styles/application.less b/ambari-web/app/styles/application.less
index b3171fe..5bf9f4f 100644
--- a/ambari-web/app/styles/application.less
+++ b/ambari-web/app/styles/application.less
@@ -2082,6 +2082,9 @@ input[type="radio"].align-checkbox, input[type="checkbox"].align-checkbox {
.prompt-input {
width: 80px;
}
+ .large-prompt-input {
+ width: 70%;
+ }
}
#views {
diff --git a/ambari-web/app/templates/common/modal_popups/update_replication_popup.hbs b/ambari-web/app/templates/common/modal_popups/update_replication_popup.hbs
new file mode 100644
index 0000000..ff1b19d
--- /dev/null
+++ b/ambari-web/app/templates/common/modal_popups/update_replication_popup.hbs
@@ -0,0 +1,61 @@
+{{!
+* 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="prompt-popup">
+ <form>
+ <div {{bindAttr class=":form-group view.parentView.isInvalid:has-error"}}>
+ <h4>{{view.title}}</h4>
+ <p>{{view.description}}</p>
+ <br/>
+ <label class="control-label">{{view.zkquorumText}}</label>
+ <div>
+
+ {{view Em.TextField class="large-prompt-input form-control" valueBinding="view.parentView.zkquorum"}}
+ </div>
+ <br/>
+ <label class="control-label">{{view.zkportText}}</label>
+ <div>
+
+ {{view Em.TextField class="prompt-input form-control" valueBinding="view.parentView.zkport"}}
+ </div>
+ <br/>
+ <label class="control-label">{{view.parentzkeyText}}</label>
+ <div>
+
+ {{view Em.TextField class="prompt-input form-control" valueBinding="view.parentView.parentzkey"}}
+ </div>
+ <br/>
+ <label class="control-label">{{view.peerIdText}}</label>
+ <div>
+
+ {{view Em.TextField class="prompt-input form-control" valueBinding="view.parentView.peerId"}}
+ </div>
+ <div>
+ {{#if view.parentView.isChanged}}
+ <a href="#" data-toggle="tooltip" class="btn-sm"
+ {{action "doRestoreDefaultValue" this target="view.parentView"}}
+ {{translateAttr data-original-title="common.reset.default"}}>
+ <i class="icon-undo"></i>
+ </a>
+ {{/if}}
+ </div>
+ {{#if view.parentView.isInvalid}}
+ <span class="help-block validation-block">{{view.parentView.errorMessage}}</span>
+ {{/if}}
+ </div>
+ </form>
+</div>
diff --git a/ambari-web/app/utils/ajax/ajax.js b/ambari-web/app/utils/ajax/ajax.js
index 4b2cf98..dd34184 100644
--- a/ambari-web/app/utils/ajax/ajax.js
+++ b/ambari-web/app/utils/ajax/ajax.js
@@ -696,6 +696,57 @@ var urls = {
}
},
+ 'service.item.updateHBaseReplication': {
+ 'real': '/clusters/{clusterName}/requests',
+ 'mock': '',
+ 'format': function (data) {
+ return {
+ type: 'POST',
+ data: JSON.stringify({
+ RequestInfo: {
+ 'context': Em.I18n.t('services.service.actions.run.updateHBaseReplication.context'),
+ 'command': 'UPDATE_REPLICATION',
+ "parameters": {
+ "replication_cluster_keys": data.replication_cluster_keys,
+ "replication_peers": data.replication_peers
+ }
+ },
+ "Requests/resource_filters": [{
+ 'service_name': 'HBASE',
+ 'component_name': 'HBASE_MASTER',
+ 'hosts': data.hosts
+ }]
+ })
+ }
+ }
+ },
+
+ 'service.item.stopHBaseReplication': {
+ 'real': '/clusters/{clusterName}/requests',
+ 'mock': '',
+ 'format': function (data) {
+ return {
+ type: 'POST',
+ data: JSON.stringify({
+ RequestInfo: {
+ 'context': Em.I18n.t('services.service.actions.run.stopHBaseReplication.context'),
+ 'command': 'STOP_REPLICATION',
+ "parameters": {
+ "replication_peers": data.replication_peers
+ }
+ },
+ "Requests/resource_filters": [{
+ 'service_name': 'HBASE',
+ 'component_name': 'HBASE_MASTER',
+ 'hosts': data.hosts
+ }]
+ })
+ }
+ }
+ },
+
+
+
'service.item.executeCustomCommand': {
'real': '/clusters/{clusterName}/requests',
'mock': '',
diff --git a/ambari-web/app/views/main/service/item.js b/ambari-web/app/views/main/service/item.js
index e256743..bb61663 100644
--- a/ambari-web/app/views/main/service/item.js
+++ b/ambari-web/app/views/main/service/item.js
@@ -35,7 +35,7 @@ App.MainServiceItemView = Em.View.extend(App.HiveInteractiveCheck, {
mastersExcludedCommands: {
'NAMENODE': ['DECOMMISSION', 'REBALANCEHDFS'],
'RESOURCEMANAGER': ['DECOMMISSION', 'REFRESHQUEUES'],
- 'HBASE_MASTER': ['DECOMMISSION'],
+ 'HBASE_MASTER': ['DECOMMISSION', 'UPDATE_REPLICATION', 'STOP_REPLICATION'],
'KNOX_GATEWAY': ['STARTDEMOLDAP','STOPDEMOLDAP'],
'HAWQMASTER': ['IMMEDIATE_STOP_HAWQ_SERVICE', 'RUN_HAWQ_CHECK', 'HAWQ_CLEAR_CACHE', 'REMOVE_HAWQ_STANDBY', 'RESYNC_HAWQ_STANDBY'],
'HAWQSEGMENT': ['IMMEDIATE_STOP_HAWQ_SEGMENT'],
@@ -276,6 +276,18 @@ App.MainServiceItemView = Em.View.extend(App.HiveInteractiveCheck, {
}
}
+ const hMasterComponent = App.StackServiceComponent.find().findProperty('componentName', 'HBASE_MASTER');
+ if (serviceName === 'HBASE' && hMasterComponent) {
+ const hMasterCustomCommands = hMasterComponent.get('customCommands');
+ if (hMasterCustomCommands && hMasterCustomCommands.contains('UPDATE_REPLICATION')) {
+ options.push(actionMap.UPDATE_REPLICATION);
+ }
+ if (hMasterCustomCommands && hMasterCustomCommands.contains('STOP_REPLICATION')) {
+ options.push(actionMap.STOP_REPLICATION);
+ }
+ }
+
+
/**
* Display all custom commands of Master and StandBy on Service page.
**/