AMBARI-3775. Adding or Deleting zookeeper servers should reconfigure ha.zookeeper.quorum, hbase.zookeeper.quorum, and templeton.zookeeper.hosts properties. (onechiporenko)
diff --git a/ambari-web/app/controllers/main/host/details.js b/ambari-web/app/controllers/main/host/details.js
index 916c971..9f1a976 100644
--- a/ambari-web/app/controllers/main/host/details.js
+++ b/ambari-web/app/controllers/main/host/details.js
@@ -366,48 +366,55 @@
var securityEnabled = App.router.get('mainAdminSecurityController').getUpdatedSecurityStatus();
- if (securityEnabled) {
+ if (componentName === 'ZOOKEEPER_SERVER') {
App.showConfirmationPopup(function() {
self.primary(component);
- }, Em.I18n.t('hosts.host.addComponent.securityNote').format(componentName,self.get('content.hostName')));
+ }, Em.I18n.t('hosts.host.addComponent.addZooKeeper'));
}
else {
- var dn = displayName;
- if (subComponentNames !== null && subComponentNames.length > 0) {
- var dns = [];
- subComponentNames.forEach(function(scn){
- dns.push(App.format.role(scn));
- });
- dn += " ("+dns.join(", ")+")";
+ if (securityEnabled) {
+ App.showConfirmationPopup(function() {
+ self.primary(component);
+ }, Em.I18n.t('hosts.host.addComponent.securityNote').format(componentName,self.get('content.hostName')));
}
- App.ModalPopup.show({
- primary: Em.I18n.t('yes'),
- secondary: Em.I18n.t('no'),
- header: Em.I18n.t('popup.confirmation.commonHeader'),
- addComponentMsg: function() {
- return Em.I18n.t('hosts.host.addComponent.msg').format(dn);
- }.property(),
- bodyClass: Ember.View.extend({
- templateName: require('templates/main/host/details/addComponentPopup')
- }),
- onPrimary: function () {
- this.hide();
- if (component.get('componentName') === 'CLIENTS') {
- // Clients component has many sub-components which
- // need to be installed.
- var scs = component.get('subComponentNames');
- scs.forEach(function (sc, index) {
- var c = Em.Object.create({
- displayName: App.format.role(sc),
- componentName: sc
- });
- self.primary(c, scs.length - index === 1);
- });
- } else {
- self.primary(component, true);
- }
+ else {
+ var dn = displayName;
+ if (subComponentNames !== null && subComponentNames.length > 0) {
+ var dns = [];
+ subComponentNames.forEach(function(scn){
+ dns.push(App.format.role(scn));
+ });
+ dn += " ("+dns.join(", ")+")";
}
- });
+ App.ModalPopup.show({
+ primary: Em.I18n.t('yes'),
+ secondary: Em.I18n.t('no'),
+ header: Em.I18n.t('popup.confirmation.commonHeader'),
+ addComponentMsg: function() {
+ return Em.I18n.t('hosts.host.addComponent.msg').format(dn);
+ }.property(),
+ bodyClass: Ember.View.extend({
+ templateName: require('templates/main/host/details/addComponentPopup')
+ }),
+ onPrimary: function () {
+ this.hide();
+ if (component.get('componentName') === 'CLIENTS') {
+ // Clients component has many sub-components which
+ // need to be installed.
+ var scs = component.get('subComponentNames');
+ scs.forEach(function (sc, index) {
+ var c = Em.Object.create({
+ displayName: App.format.role(sc),
+ componentName: sc
+ });
+ self.primary(c, scs.length - index === 1);
+ });
+ } else {
+ self.primary(component, true);
+ }
+ }
+ });
+ }
}
},
@@ -465,10 +472,85 @@
if (App.router.get('applicationController').loadShowBgChecked() && showPopup) {
App.router.get('backgroundOperationsController').showPopup();
}
+ if (componentName === 'ZOOKEEPER_SERVER') {
+ self.checkZkConfigs();
+ }
});
});
},
/**
+ * Load tags
+ */
+ checkZkConfigs: function() {
+ App.ajax.send({
+ name: 'config.tags',
+ sender: this,
+ success: 'checkZkConfigsSuccessCallback'
+ });
+ },
+ /**
+ * Load needed configs
+ * @param data
+ */
+ checkZkConfigsSuccessCallback: function(data) {
+ var urlParams = [];
+ urlParams.push('(type=core-site&tag=' + data.Clusters.desired_configs['core-site'].tag + ')');
+ if (App.Service.find().someProperty('serviceName', 'HBASE')) {
+ urlParams.push('(type=hbase-site&tag=' + data.Clusters.desired_configs['hbase-site'].tag + ')');
+ }
+ if (App.Service.find().someProperty('serviceName', 'HIVE')) {
+ urlParams.push('(type=webhcat-site&tag=' + data.Clusters.desired_configs['webhcat-site'].tag + ')');
+ }
+ App.ajax.send({
+ name: 'reassign.load_configs',
+ sender: this,
+ data: {
+ urlParams: urlParams.join('|')
+ },
+ success: 'setNewZkConfigs'
+ });
+ },
+ /**
+ * Set new values for some configs
+ * @param data
+ */
+ setNewZkConfigs: function(data) {
+ var configs = [];
+ data.items.forEach(function (item) {
+ configs[item.type] = item.properties;
+ }, this);
+ if (App.isHadoop2Stack) {
+ if (!App.HostComponent.find().someProperty('componentName', 'SECONDARY_NAMENODE')) {
+ var zks = App.HostComponent.find().filterProperty('componentName', 'ZOOKEEPER_SERVER').mapProperty('host.hostName');
+ var value = '';
+ zks.forEach(function(zk) {
+ value += zk + ':2181,';
+ });
+ value.slice(0,-1);
+ configs['core-site']['ha.zookeeper.quorum'] = value;
+ }
+ }
+ var oneZk = App.HostComponent.find().findProperty('componentName', 'ZOOKEEPER_SERVER').get('host.hostName');
+ if (configs['hbase-site']) {
+ configs['hbase-site']['hbase.zookeeper.quorum'] = oneZk;
+ }
+ if (configs['webhcat-site']) {
+ configs['webhcat-site']['templeton.zookeeper.hosts'] = oneZk;
+ }
+ for (var site in configs) {
+ if (!configs.hasOwnProperty(site)) continue;
+ App.ajax.send({
+ name: 'reassign.save_configs',
+ sender: this,
+ data: {
+ siteName: site,
+ properties: configs[site]
+ }
+ });
+ }
+ },
+
+ /**
* send command to server to install selected host component
* @param event
* @param context
@@ -717,8 +799,12 @@
var lastComponents = [];
var componentsOnHost = this.get('content.hostComponents');
var allComponents = App.HostComponent.find();
+ var zkServerInstalled = false;
if (componentsOnHost && componentsOnHost.get('length') > 0) {
componentsOnHost.forEach(function (cInstance) {
+ if (cInstance.get('componentName') === 'ZOOKEEPER_SERVER') {
+ zkServerInstalled = true;
+ }
if (allComponents.filterProperty('componentName', cInstance.get('componentName')).get('length') === 1) {
lastComponents.push(cInstance.get('displayName'));
}
@@ -747,7 +833,15 @@
this.raiseDeleteComponentsError(runningComponents, 'runningList');
return;
}
- this._doDeleteHost(unknownComponents, lastComponents);
+ if (zkServerInstalled) {
+ var self = this;
+ App.showConfirmationPopup(function() {
+ self._doDeleteHost(unknownComponents, lastComponents);
+ }, Em.I18n.t('hosts.host.addComponent.deleteHostWithZooKeeper'));
+ }
+ else {
+ this._doDeleteHost(unknownComponents, lastComponents);
+ }
},
raiseDeleteComponentsError: function (components, type) {
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index 34d5cf6..dcb18b1 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -906,6 +906,7 @@
'services.service.start':'Start',
'services.service.stop':'Stop',
+ 'services.nothingToAdd':'Nothing to add',
'services.service.summary.version':'Version',
'services.service.summary.viewHost':'View Host',
'services.service.summary.viewHosts':'View Hosts',
@@ -1329,6 +1330,8 @@
'hosts.host.deleteComponent.popup.warning':'<b>WARNING!</b> Delete the last <i>{0}</i> component in the cluster?</br>Deleting the last component in the cluster could result in permanent loss of service data.',
'hosts.host.installComponent.msg':'Are you sure you want to install {0}?',
'hosts.host.addComponent.msg':'Are you sure you want to add {0}?',
+ 'hosts.host.addComponent.addZooKeeper':'Adding ZooKeeper Server may reconfigure such properties:<ul><li>ha.zookeeper.quorum</li><li>hbase.zookeeper.quorum</li><li>templeton.zookeeper.hosts</li></ul>',
+ 'hosts.host.addComponent.deleteHostWithZooKeeper':'Deleting host with ZooKeeper Server may reconfigure such properties:<ul><li>ha.zookeeper.quorum</li><li>hbase.zookeeper.quorum</li><li>templeton.zookeeper.hosts</li></ul>',
'hosts.host.addComponent.note':'Note: After this component is installed, go to Services -> Nagios to restart the Nagios service. This is required for the alerts and notifications to work properly.',
'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',
diff --git a/ambari-web/app/views/common/modal_popup.js b/ambari-web/app/views/common/modal_popup.js
index f20d01b..72db6f3 100644
--- a/ambari-web/app/views/common/modal_popup.js
+++ b/ambari-web/app/views/common/modal_popup.js
@@ -95,7 +95,7 @@
return popup;
}
-})
+});
App.showReloadPopup = function () {
return App.ModalPopup.show({
@@ -106,7 +106,7 @@
body: "<div class='alert alert-info'><div class='spinner'><span>" + this.t('app.reloadPopup.text') + "</span></div></div><div><a href='#' onclick='location.reload();'>" + this.t('app.reloadPopup.link') + "</a></div>",
encodeBody: false
});
-}
+};
/**
* Show confirmation popup
@@ -121,6 +121,7 @@
}
return App.ModalPopup.show({
primary: Em.I18n.t('ok'),
+ encodeBody: false,
secondary: Em.I18n.t('common.cancel'),
header: Em.I18n.t('popup.confirmation.commonHeader'),
body: body || Em.I18n.t('question.sure'),
@@ -158,4 +159,4 @@
}
}
});
-}
\ No newline at end of file
+};
\ No newline at end of file