You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by rz...@apache.org on 2016/10/24 20:55:43 UTC

ambari git commit: AMBARI-18669 - Manage Journal Node Wizard Initial UI (rzang)

Repository: ambari
Updated Branches:
  refs/heads/branch-2.5 11cd92373 -> 9bb588037


AMBARI-18669 - Manage Journal Node Wizard Initial UI (rzang)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/9bb58803
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/9bb58803
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/9bb58803

Branch: refs/heads/branch-2.5
Commit: 9bb588037af3aae0eefb14ed2488ca57e7517754
Parents: 11cd923
Author: Richard Zang <rz...@apache.org>
Authored: Mon Oct 24 13:53:00 2016 -0700
Committer: Richard Zang <rz...@apache.org>
Committed: Mon Oct 24 13:53:48 2016 -0700

----------------------------------------------------------------------
 ambari-web/app/config.js                        |   3 +-
 ambari-web/app/controllers.js                   |   8 +
 .../journalNode/progress_controller.js          |  50 +++++
 .../journalNode/step1_controller.js             |  94 +++++++++
 .../journalNode/step2_controller.js             | 181 ++++++++++++++++
 .../journalNode/step3_controller.js             |  23 ++
 .../journalNode/step4_controller.js             |  81 +++++++
 .../journalNode/step5_controller.js             |  23 ++
 .../journalNode/step6_controller.js             |   9 +
 .../journalNode/wizard_controller.js            | 194 +++++++++++++++++
 .../nameNode/wizard_controller.js               |   4 -
 .../main/admin/highAvailability_controller.js   |   5 +
 ambari-web/app/controllers/main/service/item.js |   5 +
 ambari-web/app/controllers/wizard.js            |   4 +
 .../data/HDP2/move_journal_node_properties.js   |  42 ++++
 ambari-web/app/messages.js                      |  47 +++++
 ambari-web/app/models/host_component.js         |   7 +
 ambari-web/app/routes/main.js                   |   2 +
 .../app/routes/manage_journalnode_routes.js     | 209 +++++++++++++++++++
 ambari-web/app/styles/application.less          |   2 +-
 .../highAvailability/journalNode/step1.hbs      |   4 +
 .../highAvailability/journalNode/step2.hbs      |  63 ++++++
 .../highAvailability/journalNode/step3.hbs      |  32 +++
 .../highAvailability/journalNode/step4.hbs      |  18 ++
 .../highAvailability/journalNode/step5.hbs      |  27 +++
 .../highAvailability/journalNode/step6.hbs      |  18 ++
 .../highAvailability/journalNode/wizard.hbs     |  43 ++++
 ambari-web/app/utils/db.js                      |   8 +
 ambari-web/app/views.js                         |   8 +
 .../journalNode/progress_view.js                |  39 ++++
 .../highAvailability/journalNode/step1_view.js  |  30 +++
 .../highAvailability/journalNode/step2_view.js  |  33 +++
 .../highAvailability/journalNode/step3_view.js  |  29 +++
 .../highAvailability/journalNode/step4_view.js  |  24 +++
 .../highAvailability/journalNode/step5_view.js  |  48 +++++
 .../highAvailability/journalNode/step6_view.js  |  24 +++
 .../highAvailability/journalNode/wizard_view.js |  46 ++++
 ambari-web/app/views/main/service/item.js       |   6 +
 38 files changed, 1487 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/config.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/config.js b/ambari-web/app/config.js
index 4550eb8..3680b37 100644
--- a/ambari-web/app/config.js
+++ b/ambari-web/app/config.js
@@ -87,7 +87,8 @@ App.supports = {
   enableIpa: false,
   addingNewRepository: false,
   kerberosStackAdvisor: true,
-  logCountVizualization: false
+  logCountVizualization: false,
+  manageJournalNode: false
 };
 
 if (App.enableExperimental) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/controllers.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers.js b/ambari-web/app/controllers.js
index 2537f62..a911405 100644
--- a/ambari-web/app/controllers.js
+++ b/ambari-web/app/controllers.js
@@ -74,6 +74,14 @@ require('controllers/main/admin/highAvailability/rangerAdmin/step1_controller');
 require('controllers/main/admin/highAvailability/rangerAdmin/step2_controller');
 require('controllers/main/admin/highAvailability/rangerAdmin/step3_controller');
 require('controllers/main/admin/highAvailability/rangerAdmin/step4_controller');
+require('controllers/main/admin/highAvailability/journalNode/wizard_controller');
+require('controllers/main/admin/highAvailability/journalNode/progress_controller');
+require('controllers/main/admin/highAvailability/journalNode/step1_controller');
+require('controllers/main/admin/highAvailability/journalNode/step2_controller');
+require('controllers/main/admin/highAvailability/journalNode/step3_controller');
+require('controllers/main/admin/highAvailability/journalNode/step4_controller');
+require('controllers/main/admin/highAvailability/journalNode/step5_controller');
+require('controllers/main/admin/highAvailability/journalNode/step6_controller');
 require('controllers/main/admin/stack_and_upgrade_controller');
 require('controllers/main/admin/serviceAccounts_controller');
 require('utils/polling');

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/controllers/main/admin/highAvailability/journalNode/progress_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/admin/highAvailability/journalNode/progress_controller.js b/ambari-web/app/controllers/main/admin/highAvailability/journalNode/progress_controller.js
new file mode 100644
index 0000000..436a8bd
--- /dev/null
+++ b/ambari-web/app/controllers/main/admin/highAvailability/journalNode/progress_controller.js
@@ -0,0 +1,50 @@
+/**
+ * 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.
+ */
+
+var App = require('app');
+
+App.ManageJournalNodeProgressPageController = App.ManageJournalNodeWizardController.extend(App.wizardProgressPageControllerMixin, {
+  name: 'manageJournalNodeProgressPageController',
+  clusterDeployState: 'JOURNALNODE_MANAGEMENT',
+  tasksMessagesPrefix: 'admin.manageJournalNode.wizard.step',
+  isRollback: false,
+  
+  /**
+   * Prepare object to send to the server to save configs
+   * Split all configs by site names and tag and note
+   * @param siteNames Array
+   * @param data Object
+   * @param note String
+   */
+  reconfigureSites: function(siteNames, data, note) {
+    var tagName = App.get('testMode') ? 'version1' : 'version' + (new Date).getTime();
+    return siteNames.map(function(_siteName) {
+      var config = data.items.findProperty('type', _siteName);
+      var configToSave = {
+        type: _siteName,
+        tag: tagName,
+        properties: config && config.properties,
+        service_config_version_note: note || ''
+      };
+      if (config && config.properties_attributes) {
+        configToSave.properties_attributes = config.properties_attributes;
+      }
+      return configToSave;
+    });
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/controllers/main/admin/highAvailability/journalNode/step1_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/admin/highAvailability/journalNode/step1_controller.js b/ambari-web/app/controllers/main/admin/highAvailability/journalNode/step1_controller.js
new file mode 100644
index 0000000..0da5264
--- /dev/null
+++ b/ambari-web/app/controllers/main/admin/highAvailability/journalNode/step1_controller.js
@@ -0,0 +1,94 @@
+/**
+ * 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.
+ */
+
+var App = require('app');
+
+require('controllers/wizard/step5_controller');
+
+App.ManageJournalNodeWizardStep1Controller = Em.Controller.extend(App.BlueprintMixin, App.AssignMasterComponents, {
+
+  name:"manageJournalNodeWizardStep1Controller",
+
+  useServerValidation: false,
+
+  mastersToShow: ['JOURNALNODE'],
+
+  mastersToAdd: [],
+
+  showInstalledMastersFirst: true,
+
+  JOURNALNODES_COUNT_MINIMUM: 3, // TODO get this from stack
+
+  renderComponents: function(masterComponents) {
+    var jns = App.HostComponent.find().filterProperty('componentName', 'JOURNALNODE');
+    var count = jns.get('length');
+    for (var i = 0; i < count; i++) {
+      this.get('mastersToAdd').push('JOURNALNODE');
+    }
+    this._super(masterComponents);
+    this.updateJournalNodeInfo();
+    this.showHideJournalNodesAddRemoveControl();
+  },
+
+  addComponent: function(componentName) {
+    this._super(componentName);
+    this.showHideJournalNodesAddRemoveControl();
+  },
+
+  removeComponent: function(componentName, serviceComponentId) {
+    this._super(componentName, serviceComponentId);
+    this.showHideJournalNodesAddRemoveControl()
+  },
+
+  showHideJournalNodesAddRemoveControl: function() {
+    var masterComponents = this.get('selectedServicesMasters');
+    var jns = masterComponents.filterProperty('component_name', 'JOURNALNODE');
+    var maxNumMasters = this.getMaxNumberOfMasters('JOURNALNODE')
+    var showRemoveControl = jns.get('length') > this.get('JOURNALNODES_COUNT_MINIMUM');
+    var showAddControl = jns.get('length') < maxNumMasters;
+    jns.forEach(function(item) {
+      item.set('showAddControl', false);
+      item.set('showRemoveControl', showRemoveControl);
+    });
+    jns.set('lastObject.showAddControl', showAddControl);
+  },
+
+  updateJournalNodeInfo: function() {
+    var jns = this.get('selectedServicesMasters').filterProperty('component_name', 'JOURNALNODE');
+    var hosts = App.HostComponent.find().filterProperty('componentName', 'JOURNALNODE').mapProperty('hostName');
+    jns.forEach(function(item) {
+      item.set('selectedHost', hosts.pop());
+      item.set('isInstalled', true);
+    });
+  },
+
+  /**
+   * Callback after load controller data (hosts, host components etc)
+   * @method loadStepCallback
+   */
+  loadStepCallback: function(components, self) {
+    self.renderComponents(components);
+
+    self.get('addableComponents').forEach(function (componentName) {
+      self.updateComponent(componentName);
+    }, self);
+    self.set('isLoaded', true);
+  }
+
+});
+

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/controllers/main/admin/highAvailability/journalNode/step2_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/admin/highAvailability/journalNode/step2_controller.js b/ambari-web/app/controllers/main/admin/highAvailability/journalNode/step2_controller.js
new file mode 100644
index 0000000..920bbd1e
--- /dev/null
+++ b/ambari-web/app/controllers/main/admin/highAvailability/journalNode/step2_controller.js
@@ -0,0 +1,181 @@
+/**
+ * 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.
+ */
+
+/**
+ * @typedef {object} nnHaConfigDependencies
+ * @property {string} namespaceId
+ * @property {object} serverConfigs
+ * @property {string|number} nnHttpPort
+ * @property {string|number} nnHttpsPort
+ * @property {string|number} nnRpcPort
+ * @property {string|number} zkClientPort
+ */
+
+var App = require('app');
+
+require('utils/configs/nn_ha_config_initializer');
+
+App.ManageJournalNodeWizardStep2Controller = Em.Controller.extend({
+  name: "manageJournalNodeWizardStep2Controller",
+  selectedService: null,
+  stepConfigs: [],
+  serverConfigData: {},
+  moveJNConfig: $.extend(true, {}, require('data/HDP2/move_journal_node_properties').moveJNConfig),
+  once: false,
+  isLoaded: false,
+  versionLoaded: true,
+  hideDependenciesInfoBar: true,
+
+  clearStep: function () {
+    this.get('stepConfigs').clear();
+    this.set('serverConfigData', {});
+  },
+
+  loadStep: function () {
+    this.clearStep();
+    this.loadConfigsTags();
+  },
+
+  loadConfigsTags: function () {
+    App.ajax.send({
+      name: 'config.tags',
+      sender: this,
+      success: 'onLoadConfigsTags',
+      error: 'onTaskError'
+    });
+  },
+
+
+  onLoadConfigsTags: function (data) {
+    var urlParams = [];
+    var hdfsSiteTag = data.Clusters.desired_configs['hdfs-site'].tag;
+    urlParams.push('(type=hdfs-site&tag=' + hdfsSiteTag + ')');
+    this.set("hdfsSiteTag", {name : "hdfsSiteTag", value : hdfsSiteTag});
+
+    App.ajax.send({
+      name: 'admin.get.all_configurations',
+      sender: this,
+      data: {
+        urlParams: urlParams.join('|')
+      },
+      success: 'onLoadConfigs',
+      error: 'onTaskError'
+    });
+  },
+
+  onLoadConfigs: function (data) {
+    this.set('serverConfigData',data);
+    this.tweakServiceConfigs(this.get('moveJNConfig.configs'));
+    this.renderServiceConfigs(this.get('moveJNConfig'));
+    this.set('isLoaded', true);
+  },
+
+  /**
+   * Generate set of data used to correctly initialize config values and names
+   */
+  _prepareDependencies: function () {
+    var ret = {};
+    var configsFromServer = this.get('serverConfigData.items');
+    ret.namespaceId = this.get('content.nameServiceId');
+    ret.serverConfigs = configsFromServer;
+    return ret;
+  },
+
+  /**
+   * Generate set of data with information about cluster topology
+   * Used in the configs' initialization process
+   *
+   * @returns {extendedTopologyLocalDB}
+   * @private
+   * @method _prepareLocalDB
+   */
+  _prepareLocalDB: function () {
+    var localDB = this.get('content').getProperties(['masterComponentHosts', 'slaveComponentHosts', 'hosts']);
+    localDB.installedServices = App.Service.find().mapProperty('serviceName');
+    return localDB;
+  },
+
+  tweakServiceConfigs: function(configs) {
+    var localDB = this._prepareLocalDB();
+    var dependencies = this._prepareDependencies();
+
+    configs.forEach(function (config) {
+      App.NnHaConfigInitializer.initialValue(config, localDB, dependencies);
+      config.isOverridable = false;
+    });
+
+    return configs;
+  },
+
+  /**
+   * Find and remove config properties in <code>serverConfigData</code>
+   * @param configsToRemove - map of config sites and properties to remove
+   * @param configs - configuration object
+   * @returns {Object}
+   */
+  removeConfigs:function (configsToRemove, configs) {
+    Em.keys(configsToRemove).forEach(function(site){
+      var siteConfigs = configs.items.findProperty('type', site);
+      if (siteConfigs) {
+        configsToRemove[site].forEach(function (property) {
+          delete siteConfigs.properties[property];
+        });
+      }
+    });
+    return configs;
+  },
+
+  renderServiceConfigs: function (_serviceConfig) {
+    var serviceConfig = App.ServiceConfig.create({
+      serviceName: _serviceConfig.serviceName,
+      displayName: _serviceConfig.displayName,
+      configCategories: [],
+      showConfig: true,
+      configs: []
+    });
+
+    _serviceConfig.configCategories.forEach(function (_configCategory) {
+      if (App.Service.find().someProperty('serviceName', _configCategory.name)) {
+        serviceConfig.configCategories.pushObject(_configCategory);
+      }
+    }, this);
+
+    this.loadComponentConfigs(_serviceConfig, serviceConfig);
+
+    this.get('stepConfigs').pushObject(serviceConfig);
+    this.set('selectedService', this.get('stepConfigs').objectAt(0));
+    this.once = true;
+  },
+
+  /**
+   * Load child components to service config object
+   * @param _componentConfig
+   * @param componentConfig
+   */
+  loadComponentConfigs: function (_componentConfig, componentConfig) {
+    _componentConfig.configs.forEach(function (_serviceConfigProperty) {
+      var serviceConfigProperty = App.ServiceConfigProperty.create(_serviceConfigProperty);
+      componentConfig.configs.pushObject(serviceConfigProperty);
+      serviceConfigProperty.set('isEditable', serviceConfigProperty.get('isReconfigurable'));
+    }, this);
+  },
+
+  isNextDisabled: Em.computed.not('isLoaded')
+
+});
+

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/controllers/main/admin/highAvailability/journalNode/step3_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/admin/highAvailability/journalNode/step3_controller.js b/ambari-web/app/controllers/main/admin/highAvailability/journalNode/step3_controller.js
new file mode 100644
index 0000000..6e73fc0
--- /dev/null
+++ b/ambari-web/app/controllers/main/admin/highAvailability/journalNode/step3_controller.js
@@ -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
+ *
+ *     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.
+ */
+
+var App = require('app');
+
+App.ManageJournalNodeWizardStep3Controller = App.HighAvailabilityWizardStep4Controller.extend({
+  name: 'manageJournalNodeWizardStep3Controller'
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/controllers/main/admin/highAvailability/journalNode/step4_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/admin/highAvailability/journalNode/step4_controller.js b/ambari-web/app/controllers/main/admin/highAvailability/journalNode/step4_controller.js
new file mode 100644
index 0000000..39a074e
--- /dev/null
+++ b/ambari-web/app/controllers/main/admin/highAvailability/journalNode/step4_controller.js
@@ -0,0 +1,81 @@
+/**
+ * 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.
+ */
+
+var App = require('app');
+
+App.ManageJournalNodeWizardStep4Controller = App.ManageJournalNodeProgressPageController.extend({
+  name: 'manageJournalNodeWizardStep4Controller',
+  clusterDeployState: 'JOURNALNODE_MANAGEMENT',
+  tasksMessagesPrefix: 'admin.manageJournalNode.wizard.step',
+
+  commands: ['stopServices', 'installJournalNodes', 'startJournalNodes', 'reconfigureHDFS'],
+
+  hdfsSiteTag : "",
+
+  installJournalNodes: function () {
+    var hostNames = this.get('content.masterComponentHosts').filterProperty('component', 'JOURNALNODE')
+      .filterProperty('isInstalled', false).mapProperty('hostName');
+    this.createInstallComponentTask('JOURNALNODE', hostNames, "HDFS");
+  },
+
+  startJournalNodes: function () {
+    var hostNames = this.get('content.masterComponentHosts').filterProperty('component', 'JOURNALNODE').mapProperty('hostName');
+    this.updateComponent('JOURNALNODE', hostNames, "HDFS", "Start");
+  },
+
+  reconfigureHDFS: function () {
+    var data = this.get('content.serviceConfigProperties');
+    if (App.get('isKerberosEnabled')) {
+      // TODO this.reconfigureSecureHDFS();
+    } else {
+      this.updateConfigProperties(data);
+    }
+  },
+
+  /**
+   * Update service configurations
+   * @param {Object} data - config object to update
+   */
+  updateConfigProperties: function(data) {
+    var siteNames = ['hdfs-site'];
+    var configData = this.reconfigureSites(siteNames, data, Em.I18n.t('admin.manageJournalNode.step4.save.configuration.note').format(App.format.role('NAMENODE', false)));
+    App.ajax.send({
+      name: 'common.service.configurations',
+      sender: this,
+      data: {
+        desired_config: configData
+      },
+      success: 'installHDFSClients',
+      error: 'onTaskError',
+    });
+  },
+
+  installHDFSClients: function () {
+    var nnHostNames = this.get('content.masterComponentHosts').filterProperty('component', 'NAMENODE').mapProperty('hostName');
+    var jnHostNames = this.get('content.masterComponentHosts').filterProperty('component', 'JOURNALNODE').mapProperty('hostName');
+    var hostNames = nnHostNames.concat(jnHostNames).uniq();
+    this.createInstallComponentTask('HDFS_CLIENT', hostNames, 'HDFS');
+    App.clusterStatus.setClusterStatus({
+      clusterName: this.get('content.cluster.name'),
+      clusterState: 'JOURNALNODE_MANAGEMENT',
+      wizardControllerName: this.get('content.controllerName'),
+      localdb: App.db.data
+    });
+  }
+
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/controllers/main/admin/highAvailability/journalNode/step5_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/admin/highAvailability/journalNode/step5_controller.js b/ambari-web/app/controllers/main/admin/highAvailability/journalNode/step5_controller.js
new file mode 100644
index 0000000..2329dee
--- /dev/null
+++ b/ambari-web/app/controllers/main/admin/highAvailability/journalNode/step5_controller.js
@@ -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
+ *
+ *     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.
+ */
+
+var App = require('app');
+
+App.ManageJournalNodeWizardStep5Controller = App.HighAvailabilityWizardStep6Controller.extend({
+  name : 'manageJournalNodeWizardStep5Controller'
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/controllers/main/admin/highAvailability/journalNode/step6_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/admin/highAvailability/journalNode/step6_controller.js b/ambari-web/app/controllers/main/admin/highAvailability/journalNode/step6_controller.js
new file mode 100644
index 0000000..ededc1c
--- /dev/null
+++ b/ambari-web/app/controllers/main/admin/highAvailability/journalNode/step6_controller.js
@@ -0,0 +1,9 @@
+var App = require('app');
+
+App.ManageJournalNodeWizardStep6Controller = App.ManageJournalNodeProgressPageController.extend({
+  name: 'manageJournalNodeWizardStep6Controller',
+  clusterDeployState: 'JOURNALNODE_MANAGEMENT',
+  tasksMessagesPrefix: 'admin.manageJournalNode.wizard.step',
+
+  commands: ['startServices']
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/controllers/main/admin/highAvailability/journalNode/wizard_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/admin/highAvailability/journalNode/wizard_controller.js b/ambari-web/app/controllers/main/admin/highAvailability/journalNode/wizard_controller.js
new file mode 100644
index 0000000..56b6ff5
--- /dev/null
+++ b/ambari-web/app/controllers/main/admin/highAvailability/journalNode/wizard_controller.js
@@ -0,0 +1,194 @@
+/**
+ * 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.
+ */
+
+
+var App = require('app');
+
+App.ManageJournalNodeWizardController = App.WizardController.extend({
+
+  name: 'manageJournalNodeWizardController',
+
+  totalSteps: 5,
+
+  /**
+   * Used for hiding back button in wizard
+   */
+  hideBackButton: true,
+
+  content: Em.Object.create({
+    controllerName: 'manageJournalNodeWizardController',
+    cluster: null,
+    hosts: null,
+    services: null,
+    slaveComponentHosts: null,
+    masterComponentHosts: null,
+    serviceConfigProperties: [],
+    serviceName: 'MISC',
+    hdfsUser:"hdfs",
+    nameServiceId: '',
+    failedTask : null,
+    requestIds: null
+  }),
+
+  setCurrentStep: function (currentStep, completed) {
+    this._super(currentStep, completed);
+    App.clusterStatus.setClusterStatus({
+      clusterName: this.get('content.cluster.name'),
+      clusterState: 'JOURNALNODE_MANAGEMENT',
+      wizardControllerName: 'manageJournalNodeWizardController',
+      localdb: App.db.data
+    });
+  },
+
+  /**
+   * return new object extended from clusterStatusTemplate
+   * @return Object
+   */
+  getCluster: function(){
+    return jQuery.extend({}, this.get('clusterStatusTemplate'), {name: App.router.getClusterName()});
+  },
+
+  loadMap: {
+    '1': [
+      {
+        type: 'async',
+        callback: function () {
+          var dfd = $.Deferred(),
+            self = this,
+            usersLoadingCallback = function () {
+              self.save('hdfsUser');
+              self.load('cluster');
+              self.loadHosts().done(function () {
+                self.loadServicesFromServer();
+                self.loadMasterComponentHosts().done(function () {
+                  self.load('hdfsUser');
+                  dfd.resolve();
+                });
+              });
+            };
+          if (self.getDBProperty('hdfsUser')) {
+            usersLoadingCallback();
+          } else {
+            this.loadHdfsUserFromServer().done(function (data) {
+              self.set('content.hdfsUser', Em.get(data, '0.properties.hdfs_user'));
+              usersLoadingCallback();
+            });
+          }
+          return dfd.promise();
+        }
+      }
+    ],
+    2 : [
+      {
+        type: 'sync',
+        callback: function () {
+          // TODO load nameservice id
+          this.set('content.nameServiceId', 'ns1');
+          this.setDBProperty('nameServiceId', 'ns1');
+          this.loadServiceConfigProperties();
+        }
+      }
+    ],
+    '4': [
+      {
+        type: 'sync',
+        callback: function () {
+          this.loadTasksStatuses();
+          this.loadTasksRequestIds();
+          this.loadRequestIds();
+        }
+      }
+    ],
+    '6': [
+      {
+        type: 'sync',
+        callback: function () {
+          this.loadTasksStatuses();
+          this.loadTasksRequestIds();
+          this.loadRequestIds();
+        }
+      }
+    ]
+
+  },
+
+
+  /**
+   * Save config properties
+   * @param stepController ManageJournalNodeWizardStep3Controller
+   */
+  saveServiceConfigProperties: function(stepController) {
+    var serviceConfigProperties = [];
+    var data = stepController.get('serverConfigData');
+
+    var _content = stepController.get('stepConfigs')[0];
+    _content.get('configs').forEach(function (_configProperties) {
+      var siteObj = data.items.findProperty('type', _configProperties.get('filename'));
+      if (siteObj) {
+        siteObj.properties[_configProperties.get('name')] = _configProperties.get('value');
+      }
+    }, this);
+    this.setDBProperty('serviceConfigProperties', data);
+    this.set('content.serviceConfigProperties', data);
+  },
+
+  /**
+   * Load serviceConfigProperties to model
+   */
+  loadServiceConfigProperties: function () {
+    var serviceConfigProperties = this.getDBProperty('serviceConfigProperties');
+    this.set('content.serviceConfigProperties', serviceConfigProperties);
+  },
+
+
+  saveConfigTag: function(tag){
+    App.db.setManageJournalNodeWizardConfigTag(tag);
+    this.set('content.'+[tag.name], tag.value);
+  },
+  
+  
+  loadConfigTag: function(tag){
+    var tagVal = App.db.getManageJournalNodeWizardConfigTag(tag);
+    this.set('content.'+tag, tagVal);
+  },
+
+  /**
+   * Remove all loaded data.
+   * Created as copy for App.router.clearAllSteps
+   */
+  clearAllSteps: function () {
+    this.clearInstallOptions();
+    // clear temporary information stored during the install
+    this.set('content.cluster', this.getCluster());
+  },
+
+  clearTasksData: function () {
+    this.saveTasksStatuses(undefined);
+    this.saveRequestIds(undefined);
+    this.saveTasksRequestIds(undefined);
+  },
+
+  /**
+   * Clear all temporary data
+   */
+  finish: function () {
+    App.db.data.Installer = {};
+    this.resetDbNamespace();
+    App.router.get('updateController').updateAll();
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/controllers/main/admin/highAvailability/nameNode/wizard_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/admin/highAvailability/nameNode/wizard_controller.js b/ambari-web/app/controllers/main/admin/highAvailability/nameNode/wizard_controller.js
index 72f9ec2..1e2f484 100644
--- a/ambari-web/app/controllers/main/admin/highAvailability/nameNode/wizard_controller.js
+++ b/ambari-web/app/controllers/main/admin/highAvailability/nameNode/wizard_controller.js
@@ -186,10 +186,6 @@ App.HighAvailabilityWizardController = App.WizardController.extend({
     this.set('content.tasksRequestIds', requestIds);
   },
 
-  loadHdfsUserFromServer: function () {
-    return App.get('router.configurationController').loadFromServer([{'siteName': 'hadoop-env'}]);
-  },
-
   loadMap: {
     '1': [
       {

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/controllers/main/admin/highAvailability_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/admin/highAvailability_controller.js b/ambari-web/app/controllers/main/admin/highAvailability_controller.js
index 4cd50a6..71c11db 100644
--- a/ambari-web/app/controllers/main/admin/highAvailability_controller.js
+++ b/ambari-web/app/controllers/main/admin/highAvailability_controller.js
@@ -115,6 +115,11 @@ App.MainAdminHighAvailabilityController = App.WizardController.extend({
     App.router.transitionTo('main.services.enableRAHighAvailability');
     return true;
   },
+  
+  manageJournalNode: function() {
+    App.router.transitionTo('main.services.manageJournalNode');
+    return true;
+  },
 
   /**
    * join or wrap message depending on whether it is array or string

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/controllers/main/service/item.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/service/item.js b/ambari-web/app/controllers/main/service/item.js
index 6ce811d..18a121f 100644
--- a/ambari-web/app/controllers/main/service/item.js
+++ b/ambari-web/app/controllers/main/service/item.js
@@ -1051,6 +1051,11 @@ App.MainServiceItemController = Em.Controller.extend(App.SupportClientConfigsDow
     highAvailabilityController.enableHighAvailability();
   },
 
+  manageJournalNode: function() {
+    var highAvailabilityController = App.router.get('mainAdminHighAvailabilityController');
+    highAvailabilityController.manageJournalNode();
+  },
+
   disableHighAvailability: function() {
     var highAvailabilityController = App.router.get('mainAdminHighAvailabilityController');
     highAvailabilityController.disableHighAvailability();

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/controllers/wizard.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/wizard.js b/ambari-web/app/controllers/wizard.js
index 0eb3d50..f195238 100644
--- a/ambari-web/app/controllers/wizard.js
+++ b/ambari-web/app/controllers/wizard.js
@@ -1430,6 +1430,10 @@ App.WizardController = Em.Controller.extend(App.LocalStorage, App.ThemesMappingM
     this.set("content.recommendations", this.getDBProperty('recommendations'));
   },
 
+  loadHdfsUserFromServer: function () {
+    return App.get('router.configurationController').loadFromServer([{'siteName': 'hadoop-env'}]);
+  },
+
   /**
    * reset stored wizard data and reload App
    * @param {App.WizardController} controller - wizard controller

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/data/HDP2/move_journal_node_properties.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/data/HDP2/move_journal_node_properties.js b/ambari-web/app/data/HDP2/move_journal_node_properties.js
new file mode 100644
index 0000000..87a6cfd
--- /dev/null
+++ b/ambari-web/app/data/HDP2/move_journal_node_properties.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.
+ */
+
+module.exports =
+{
+  "moveJNConfig": {
+    serviceName: 'MISC',
+    displayName: 'MISC',
+    configCategories: [
+      App.ServiceConfigCategory.create({ name: 'HDFS', displayName: 'HDFS'})
+    ],
+    sites: ['hdfs-site'],
+    configs: [
+      {
+        "name": "dfs.namenode.shared.edits.dir",
+        "displayName": "dfs.namenode.shared.edits.dir",
+        "description": " The URI which identifies the group of JNs where the NameNodes will write/read edits.",
+        "isReconfigurable": false,
+        "recommendedValue": "qjournal://node1.example.com:8485;node2.example.com:8485;node3.example.com:8485/mycluster",
+        "value": "qjournal://node1.example.com:8485;node2.example.com:8485;node3.example.com:8485/mycluster",
+        "category": "HDFS",
+        "filename": "hdfs-site",
+        "serviceName": 'MISC'
+      }
+    ]
+  }
+};

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/messages.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index b0f643c..8f49cce 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -1252,6 +1252,53 @@ Em.I18n.translations = {
   'admin.kerberos.disable.notice.completed': 'Services have been successfully tested without kerberos environment.',
   'admin.kerberos.wizard.step1.notice.inProgress': 'Please wait while cluster is being unkerberized',
 
+  'admin.manageJournalNode.label': 'Manage JournalNode',
+  'admin.manageJournalNode.wizard.header': 'Manage JournalNode Wizard',
+  'admin.manageJournalNode.wizard.step1.header': 'Assign JournalNodes',
+  'admin.manageJournalNode.wizard.step2.header': 'Review',
+  'admin.manageJournalNode.wizard.step3.header': 'Save Namespace',
+  'admin.manageJournalNode.wizard.step4.header': 'Add/Remove JournalNodes',
+  'admin.manageJournalNode.wizard.step5.header': 'Format JournalNodes',
+  'admin.manageJournalNode.wizard.step6.header': 'Start Services',
+
+  'admin.manageJournalNode.wizard.step1.body': 'Assign hosts to JournalNodes',
+  'admin.manageJournalNode.wizard.step3.confirm.config.body':'<div class="alert alert-info">' +
+  '<b>Review Configuration Changes.</b></br>' +
+  'The following lists the configuration changes that will be made by the Wizard to manage JournalNode. This information is for <b> review only </b>.' +
+  '</div>',
+
+  'admin.manageJournalNode.wizard.step4.task0.title': 'Stop Services',
+  'admin.manageJournalNode.wizard.step4.task1.title': 'Add JournalNodes',
+  'admin.manageJournalNode.wizard.step4.task2.title': 'Start JournalNodes',
+  'admin.manageJournalNode.wizard.step4.task3.title': 'Reconfigure HDFS',
+  'admin.manageJournalNode.wizard.step6.task0.title': 'Start All Services',
+
+  'admin.manageJournalNode.wizard.step5.bodyHeader': 'Manual Steps Required: Format JournalNodes',
+
+  'admin.manageJournalNode.step4.save.configuration.note' : 'This configuration is created by Manage JournalNode Wizard',
+
+  'admin.manageJournalNode.wizard.progressPage.notice.inProgress': 'Please wait JournalNodes being deployed',
+  'admin.manageJournalNode.wizard.step6.notice.inProgress': 'Please wait for all serviced to be started',
+
+  'admin.manageJournalNode.wizard.step4.notice.inProgress': 'Please wait JournalNodes being deployed',
+  'admin.manageJournalNode.wizard.step3.body':
+  '<ol>' +
+  '<li>Login to the NameNode host <b>{1}</b>.</li>' +
+  '<li>Put the NameNode in Safe Mode (read-only mode):' +
+  '<div class="code-snippet">sudo su {0} -l -c \'hdfs dfsadmin -safemode enter\'</div></li>' +
+  '<li>Once in Safe Mode, create a Checkpoint:' +
+  '<div class="code-snippet">sudo su {0} -l -c \'hdfs dfsadmin -saveNamespace\'</div></li>' +
+  '<li>You will be able to proceed once Ambari detects that the NameNode is in Safe Mode and the Checkpoint has been created successfully.</li>'+
+  '<div class="alert alert-warn">If the <b>Next</b> button is enabled before you run the <b>"Step 3: Save Namespace"</b> command, it means there is a recent Checkpoint already and you may proceed without running the <b>"Step 3: Save Namespace"</b> command.</div>' +
+  '</ol>',
+  'admin.manageJournalNode.wizard.step5.body':
+  '<ol>' +
+  '<li>Login to the NameNode host <b>{1}</b>.</li>' +
+  '<li>Initialize the JournalNodes by running:' +
+  '<div class="code-snippet">sudo su {0} -l -c \'hdfs namenode -initializeSharedEdits\'</div></li>' +
+  '<li>You will be able to proceed once Ambari detects that the JournalNodes have been initialized successfully.</li>' +
+  '</ol>',
+
   'admin.highAvailability':' High Availability',
   'admin.highAvailability.button.enable':'Enable NameNode HA',
   'admin.highAvailability.button.disable':'Disable NameNode HA',

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/models/host_component.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/host_component.js b/ambari-web/app/models/host_component.js
index c6b8264..f31e926 100644
--- a/ambari-web/app/models/host_component.js
+++ b/ambari-web/app/models/host_component.js
@@ -322,6 +322,13 @@ App.HostComponentActionMap = {
         cssClass: 'icon-medkit',
         disabled: false
       },
+      MANAGE_JN: {
+        action: 'manageJournalNode',
+        label: Em.I18n.t('admin.manageJournalNode.label'),
+        cssClass: 'icon-cog',
+        isHidden: !App.get('supports.manageJournalNode') || !App.get('isHaEnabled')
+        || (App.router.get('mainHostController.totalCount') == 3 && App.HostComponent.find().filterProperty('componentName', 'JOURNALNODE').get('length') == 3)
+      },
       TOGGLE_NN_HA: {
         action: App.get('isHaEnabled') ? 'disableHighAvailability' : 'enableHighAvailability',
         label: App.get('isHaEnabled') ? Em.I18n.t('admin.highAvailability.button.disable') : Em.I18n.t('admin.highAvailability.button.enable'),

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/routes/main.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/routes/main.js b/ambari-web/app/routes/main.js
index 45c1cd3..f0fe5d7 100644
--- a/ambari-web/app/routes/main.js
+++ b/ambari-web/app/routes/main.js
@@ -756,6 +756,8 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
 
     enableHighAvailability: require('routes/high_availability_routes'),
 
+    manageJournalNode: require('routes/manage_journalnode_routes'),
+
     enableRMHighAvailability: require('routes/rm_high_availability_routes'),
 
     enableRAHighAvailability: require('routes/ra_high_availability_routes'),

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/routes/manage_journalnode_routes.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/routes/manage_journalnode_routes.js b/ambari-web/app/routes/manage_journalnode_routes.js
new file mode 100644
index 0000000..b108f74
--- /dev/null
+++ b/ambari-web/app/routes/manage_journalnode_routes.js
@@ -0,0 +1,209 @@
+/**
+ * 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.
+ */
+
+var App = require('app');
+
+module.exports = App.WizardRoute.extend({
+  route: '/highAvailability/JournalNode/manage',
+
+  enter: function (router) {
+    var manageJournalNodeWizardController = router.get('manageJournalNodeWizardController');
+    manageJournalNodeWizardController.dataLoading().done(function () {
+      App.router.get('updateController').set('isWorking', false);
+      var popup = App.ModalPopup.show({
+        classNames: ['full-width-modal'],
+        header: Em.I18n.t('admin.manageJournalNode.wizard.header'),
+        bodyClass: App.ManageJournalNodeWizardView.extend({
+          controller: manageJournalNodeWizardController
+        }),
+        primary: Em.I18n.t('form.cancel'),
+        showFooter: false,
+        secondary: null,
+        hideCloseButton: function () {
+          var currStep = App.router.get('manageJournalNodeWizardController.currentStep');
+          switch (currStep) {
+            default :
+              this.set('showCloseButton', true);
+          }
+        }.observes('App.router.manageJournalNodeWizardController.currentStep'),
+
+        onClose: function () {
+          var controller = App.router.get('manageJournalNodeWizardController');
+          controller.clearTasksData();
+          controller.resetOnClose(controller, 'main.services.index');
+        },
+        didInsertElement: function () {
+          this._super();
+          this.fitHeight();
+        }
+      });
+      manageJournalNodeWizardController.set('popup', popup);
+      var currentClusterStatus = App.clusterStatus.get('value');
+      if (currentClusterStatus) {
+        switch (currentClusterStatus.clusterState) {
+          case 'JOURNALNODE_MANAGEMENT' :
+            manageJournalNodeWizardController.setCurrentStep(currentClusterStatus.localdb.ManageJournalNodeWizard.currentStep);
+            break;
+          default:
+            var currStep = App.router.get('manageJournalNodeWizardController.currentStep');
+            manageJournalNodeWizardController.setCurrentStep(currStep);
+            break;
+        }
+      }
+      Em.run.next(function () {
+        App.router.get('wizardWatcherController').setUser(manageJournalNodeWizardController.get('name'));
+        router.transitionTo('step' + manageJournalNodeWizardController.get('currentStep'));
+      });
+    });
+  },
+
+  step1: Em.Route.extend({
+    route: '/step1',
+    connectOutlets: function (router) {
+      var controller = router.get('manageJournalNodeWizardController');
+      controller.dataLoading().done(function () {
+        controller.setCurrentStep('1');
+        controller.loadAllPriorSteps().done(function () {
+          controller.connectOutlet('manageJournalNodeWizardStep1', controller.get('content'));
+        });
+      });
+    },
+    unroutePath: function () {
+      return false;
+    },
+    next: function (router) {
+      var controller = router.get('manageJournalNodeWizardController');
+      var step1Controller = router.get('manageJournalNodeWizardStep1Controller');
+      controller.saveMasterComponentHosts(step1Controller);
+      router.transitionTo('step2');
+    }
+  }),
+
+  step2: Em.Route.extend({
+    route: '/step2',
+    connectOutlets: function (router) {
+      var controller = router.get('manageJournalNodeWizardController');
+      controller.dataLoading().done(function () {
+        controller.setCurrentStep('2');
+        controller.setLowerStepsDisable(2);
+        controller.loadAllPriorSteps().done(function () {
+          controller.connectOutlet('manageJournalNodeWizardStep2', controller.get('content'));
+        });
+      })
+    },
+    unroutePath: function () {
+      return false;
+    },
+    next: function (router) {
+      App.set('router.nextBtnClickInProgress', true);
+      var controller = router.get('manageJournalNodeWizardController');
+      var stepController = router.get('manageJournalNodeWizardStep2Controller');
+      controller.saveServiceConfigProperties(stepController);
+      controller.saveConfigTag(stepController.get("hdfsSiteTag"));
+      App.set('router.nextBtnClickInProgress', false);
+      router.transitionTo('step3');
+    },
+    back: Em.Router.transitionTo('step1')
+  }),
+
+  step3: Em.Route.extend({
+    route: '/step3',
+    connectOutlets: function (router) {
+      var controller = router.get('manageJournalNodeWizardController');
+      controller.dataLoading().done(function () {
+        controller.setCurrentStep('3');
+        controller.setLowerStepsDisable(3);
+        controller.loadAllPriorSteps().done(function () {
+          controller.connectOutlet('manageJournalNodeWizardStep3', controller.get('content'));
+        });
+      })
+    },
+    unroutePath: function () {
+      return false;
+    },
+    next: function (router) {
+      var controller = router.get('manageJournalNodeWizardController');
+      controller.clearTasksData();
+      router.transitionTo('step4');
+    }
+  }),
+
+  step4: Em.Route.extend({
+    route: '/step4',
+    connectOutlets: function (router) {
+      var controller = router.get('manageJournalNodeWizardController');
+      controller.dataLoading().done(function () {
+        controller.setCurrentStep('4');
+        controller.setLowerStepsDisable(4);
+        controller.loadAllPriorSteps().done(function () {
+          controller.connectOutlet('manageJournalNodeWizardStep4', controller.get('content'));
+        });
+      })
+    },
+    unroutePath: function () {
+      return false;
+    },
+    next: function (router) {
+      var controller = router.get('manageJournalNodeWizardController');
+      controller.clearTasksData();
+      router.transitionTo('step5');
+    }
+  }),
+
+  step5: Em.Route.extend({
+    route: '/step5',
+    connectOutlets: function (router) {
+      var controller = router.get('manageJournalNodeWizardController');
+      controller.dataLoading().done(function () {
+        controller.setCurrentStep('5');
+        controller.setLowerStepsDisable(5);
+        controller.loadAllPriorSteps().done(function () {
+          controller.connectOutlet('manageJournalNodeWizardStep5', controller.get('content'));
+        });
+      })
+    },
+    unroutePath: function () {
+      return false;
+    },
+    next: function (router) {
+      router.transitionTo('step6');
+    }
+  }),
+
+  step6: Em.Route.extend({
+    route: '/step5',
+    connectOutlets: function (router) {
+      var controller = router.get('manageJournalNodeWizardController');
+      controller.dataLoading().done(function () {
+        controller.setCurrentStep('6');
+        controller.setLowerStepsDisable(6);
+        controller.loadAllPriorSteps().done(function () {
+          controller.connectOutlet('manageJournalNodeWizardStep6', controller.get('content'));
+        });
+      })
+    },
+    unroutePath: function () {
+      return false;
+    },
+    next: function (router) {
+      var controller = router.get('manageJournalNodeWizardController');
+      controller.clearTasksData();
+      controller.resetOnClose(controller, 'main.services.index');
+    }
+  })
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/styles/application.less
----------------------------------------------------------------------
diff --git a/ambari-web/app/styles/application.less b/ambari-web/app/styles/application.less
index b2b4dd1..8263305 100644
--- a/ambari-web/app/styles/application.less
+++ b/ambari-web/app/styles/application.less
@@ -1084,7 +1084,7 @@ h1 {
     margin-top: 8px;
   }
 
-  #ha-step3-review-table {
+  #ha-step3-review-table, #manage-journal-node-step2-review-table {
     td {
       text-align: left;
       vertical-align: top;

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/templates/main/admin/highAvailability/journalNode/step1.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/admin/highAvailability/journalNode/step1.hbs b/ambari-web/app/templates/main/admin/highAvailability/journalNode/step1.hbs
new file mode 100644
index 0000000..6592d2a
--- /dev/null
+++ b/ambari-web/app/templates/main/admin/highAvailability/journalNode/step1.hbs
@@ -0,0 +1,4 @@
+<h2>{{t admin.manageJournalNode.wizard.step1.header}}</h2>
+<div class="btn-area">
+    <a class="btn btn-success pull-right" {{action next}}>{{t common.next}} &rarr;</a>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/templates/main/admin/highAvailability/journalNode/step2.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/admin/highAvailability/journalNode/step2.hbs b/ambari-web/app/templates/main/admin/highAvailability/journalNode/step2.hbs
new file mode 100644
index 0000000..67a63fd
--- /dev/null
+++ b/ambari-web/app/templates/main/admin/highAvailability/journalNode/step2.hbs
@@ -0,0 +1,63 @@
+{{!
+* 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.
+}}
+
+
+<h2>{{t admin.manageJournalNode.wizard.step3.header}}</h2>
+
+<div id="manage-journal-node-step2-content" class="well pre-scrollable">
+    <div id="step8-info">
+        <table id="manage-journal-node-step2-review-table">
+            <tr>
+                <td>{{t admin.highAvailability.wizard.step3.journalNode}}</td>
+                <td>
+                    <ul>
+                        {{#each item in view.journalNodes}}
+                            <li>{{item.hostName}}</li>
+                        {{/each}}
+                    </ul>
+                </td>
+                <td>
+                    <ul>
+                        {{#each item in view.journalNodes}}
+                            <li><span class="to-be-installed-green"><i
+                                    class="icon-plus"></i>&nbsp;{{t admin.highAvailability.wizard.step3.toBeInstalled}}</span></li>
+                        {{/each}}
+                    </ul>
+                </td>
+            </tr>
+        </table>
+    </div>
+</div>
+
+
+<div id="serviceConfig">
+    {{#if controller.isLoaded}}
+        {{{t admin.manageJournalNode.wizard.step3.confirm.config.body}}}
+        {{view App.ServiceConfigView isNotEditableBinding="controller.isNotEditable"}}
+    {{else}}
+        {{view App.SpinnerView}}
+    {{/if}}
+</div>
+
+<div class="btn-area">
+    <a class="btn" {{action back}}>&larr; {{t common.back}}</a>
+    <a class="btn btn-success pull-right" {{bindAttr disabled="controller.isNextDisabled"}} {{action next}}>{{t common.next}} &rarr;</a>
+    {{#if App.router.nextBtnClickInProgress}}
+        {{view App.SpinnerView tagName="span" classNames="pull-right"}}
+    {{/if}}
+</div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/templates/main/admin/highAvailability/journalNode/step3.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/admin/highAvailability/journalNode/step3.hbs b/ambari-web/app/templates/main/admin/highAvailability/journalNode/step3.hbs
new file mode 100644
index 0000000..b87497f
--- /dev/null
+++ b/ambari-web/app/templates/main/admin/highAvailability/journalNode/step3.hbs
@@ -0,0 +1,32 @@
+{{!
+* 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 id="manage-journal-node-step3">
+    <h2>{{t admin.manageJournalNode.wizard.step3.header}}</h2>
+    {{#unless controller.isNameNodeStarted}}
+        <div class="alert alert-error">
+            {{t admin.highAvailability.wizard.step4.error.nameNode}}
+        </div>
+    {{/unless}}
+    <div class="alert alert-info">
+        {{{view.step3BodyText}}}
+    </div>
+    <div class="btn-area">
+        <a  {{bindAttr class="controller.isNextEnabled::disabled :btn :btn-success :pull-right"}} {{action done target="controller"}}>{{t common.next}} &rarr;</a>
+        <span class="pull-right btn-extra-info">{{view.nnCheckPointText}}</span>
+    </div>
+</div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/templates/main/admin/highAvailability/journalNode/step4.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/admin/highAvailability/journalNode/step4.hbs b/ambari-web/app/templates/main/admin/highAvailability/journalNode/step4.hbs
new file mode 100644
index 0000000..08dc3b9
--- /dev/null
+++ b/ambari-web/app/templates/main/admin/highAvailability/journalNode/step4.hbs
@@ -0,0 +1,18 @@
+{{!
+* 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.
+}}
+{{template "templates/common/progress"}}

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/templates/main/admin/highAvailability/journalNode/step5.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/admin/highAvailability/journalNode/step5.hbs b/ambari-web/app/templates/main/admin/highAvailability/journalNode/step5.hbs
new file mode 100644
index 0000000..53634cd
--- /dev/null
+++ b/ambari-web/app/templates/main/admin/highAvailability/journalNode/step5.hbs
@@ -0,0 +1,27 @@
+{{!
+* 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 id="manage-journal-node-step5">
+    <h2>{{t admin.manageJournalNode.wizard.step5.bodyHeader}}</h2>
+    <div class="alert alert-info">
+        {{{view.step5BodyText}}}
+    </div>
+    <div class="btn-area">
+        <a {{bindAttr class="controller.isNextEnabled::disabled :btn :btn-success :pull-right"}} {{action done target="controller"}}>{{t common.next}} &rarr;</a>
+        <span class="pull-right btn-extra-info">{{view.jnCheckPointText}}</span>
+    </div>
+</div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/templates/main/admin/highAvailability/journalNode/step6.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/admin/highAvailability/journalNode/step6.hbs b/ambari-web/app/templates/main/admin/highAvailability/journalNode/step6.hbs
new file mode 100644
index 0000000..08dc3b9
--- /dev/null
+++ b/ambari-web/app/templates/main/admin/highAvailability/journalNode/step6.hbs
@@ -0,0 +1,18 @@
+{{!
+* 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.
+}}
+{{template "templates/common/progress"}}

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/templates/main/admin/highAvailability/journalNode/wizard.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/admin/highAvailability/journalNode/wizard.hbs b/ambari-web/app/templates/main/admin/highAvailability/journalNode/wizard.hbs
new file mode 100644
index 0000000..a15b8c0
--- /dev/null
+++ b/ambari-web/app/templates/main/admin/highAvailability/journalNode/wizard.hbs
@@ -0,0 +1,43 @@
+{{!
+* 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="wizard">
+    <div class="container">
+        <div class="container-fluid">
+            <div class="row-fluid">
+                <div class="span3">
+                    <!--Sidebar content-->
+                    <div class="well">
+                        <ul class="nav nav-pills nav-stacked">
+                            <li class="nav-header">{{t admin.manageJournalNode.wizard.header}}</li>
+                            <li {{bindAttr class="isStep1:active view.isStep1Disabled:disabled"}}><a href="javascript:void(null);"  {{action gotoStep1 target="controller"}}>{{t admin.manageJournalNode.wizard.step1.header}}</a></li>
+                            <li {{bindAttr class="isStep2:active view.isStep2Disabled:disabled"}}><a href="javascript:void(null);"  {{action gotoStep2 target="controller"}}>{{t admin.manageJournalNode.wizard.step2.header}}</a></li>
+                            <li {{bindAttr class="isStep3:active view.isStep3Disabled:disabled"}}><a href="javascript:void(null);"  {{action gotoStep3 target="controller"}}>{{t admin.manageJournalNode.wizard.step3.header}}</a></li>
+                            <li {{bindAttr class="isStep4:active view.isStep4Disabled:disabled"}}><a href="javascript:void(null);"  {{action gotoStep4 target="controller"}}>{{t admin.manageJournalNode.wizard.step4.header}}</a></li>
+                            <li {{bindAttr class="isStep5:active view.isStep5Disabled:disabled"}}><a href="javascript:void(null);"  {{action gotoStep5 target="controller"}}>{{t admin.manageJournalNode.wizard.step5.header}}</a></li>
+                            <li {{bindAttr class="isStep6:active view.isStep6Disabled:disabled"}}><a href="javascript:void(null);"  {{action gotoStep6 target="controller"}}>{{t admin.manageJournalNode.wizard.step6.header}}</a></li>
+                        </ul>
+                    </div>
+                </div>
+                <div class="wizard-content well span9">
+                    {{outlet}}
+                </div>
+            </div>
+        </div>
+    </div>
+</div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/utils/db.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/db.js b/ambari-web/app/utils/db.js
index a6cdef7..e41b9c0 100644
--- a/ambari-web/app/utils/db.js
+++ b/ambari-web/app/utils/db.js
@@ -361,6 +361,10 @@ App.db.setKerberosWizardConfigTag = function (tag) {
   App.db.set('KerberosWizard', tag.name, tag.value);
 };
 
+App.db.setManageJournalNodeWizardConfigTag = function (tag) {
+  App.db.set('ManageJournalNodeWizard', tag.name, tag.value);
+};
+
 /**
  * Get user model from db
  * @return {*}
@@ -514,6 +518,10 @@ App.db.getReassignMasterWizardComponentDir = function () {
   return App.db.get('ReassignMaster', 'componentDir');
 };
 
+App.db.getManageJournalNodeWizardConfigTag = function (tag) {
+  return App.db.get('ManageJournalNodeWizard', tag);
+};
+
 App.db.getConfigs = function () {
   return App.db.get('app', 'configs');
 };

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/views.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views.js b/ambari-web/app/views.js
index c8a8784..773e8b0 100644
--- a/ambari-web/app/views.js
+++ b/ambari-web/app/views.js
@@ -174,6 +174,14 @@ require('views/main/admin/highAvailability/nameNode/rollbackHA/step1_view');
 require('views/main/admin/highAvailability/nameNode/rollbackHA/step2_view');
 require('views/main/admin/highAvailability/nameNode/rollbackHA/step3_view');
 require('views/main/admin/highAvailability/nameNode/rollbackHA/rollback_wizard_view');
+require('views/main/admin/highAvailability/journalNode/wizard_view');
+require('views/main/admin/highAvailability/journalNode/progress_view');
+require('views/main/admin/highAvailability/journalNode/step1_view');
+require('views/main/admin/highAvailability/journalNode/step2_view');
+require('views/main/admin/highAvailability/journalNode/step3_view');
+require('views/main/admin/highAvailability/journalNode/step4_view');
+require('views/main/admin/highAvailability/journalNode/step5_view');
+require('views/main/admin/highAvailability/journalNode/step6_view');
 require('views/main/admin/highAvailability/resourceManager/wizard_view');
 require('views/main/admin/highAvailability/resourceManager/step1_view');
 require('views/main/admin/highAvailability/resourceManager/step2_view');

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/views/main/admin/highAvailability/journalNode/progress_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/admin/highAvailability/journalNode/progress_view.js b/ambari-web/app/views/main/admin/highAvailability/journalNode/progress_view.js
new file mode 100644
index 0000000..f3e3d13
--- /dev/null
+++ b/ambari-web/app/views/main/admin/highAvailability/journalNode/progress_view.js
@@ -0,0 +1,39 @@
+/**
+ * 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.
+ */
+
+
+var App = require('app');
+
+App.ManageJournalNodeProgressPageView = Em.View.extend(App.wizardProgressPageViewMixin, {
+
+  didInsertElement: function () {
+    this.get('controller').loadStep();
+  },
+
+  headerTitle: function () {
+    var currentStep = App.router.get('manageJournalNodeWizardController.currentStep');
+    return  Em.I18n.t('admin.manageJournalNode.wizard.step' + currentStep + '.header');
+  }.property(),
+
+  noticeInProgress: function () {
+    var currentStep = App.router.get('manageJournalNodeWizardController.currentStep');
+    return  Em.I18n.t('admin.manageJournalNode.wizard.step' + currentStep + '.notice.inProgress');
+  }.property(),
+
+  notice: Em.I18n.t('admin.manageJournalNode.wizard.progressPage.notice.inProgress')
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/views/main/admin/highAvailability/journalNode/step1_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/admin/highAvailability/journalNode/step1_view.js b/ambari-web/app/views/main/admin/highAvailability/journalNode/step1_view.js
new file mode 100644
index 0000000..78e98bd
--- /dev/null
+++ b/ambari-web/app/views/main/admin/highAvailability/journalNode/step1_view.js
@@ -0,0 +1,30 @@
+/**
+ * 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.
+ */
+
+
+var App = require('app');
+require('views/wizard/step5_view');
+
+App.ManageJournalNodeWizardStep1View = App.AssignMasterComponentsView.extend({
+
+  title: Em.I18n.t('admin.manageJournalNode.wizard.step1.header'),
+  
+  alertMessage: Em.I18n.t('admin.manageJournalNode.wizard.step1.body'),
+
+  isBackButtonVisible: false
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/views/main/admin/highAvailability/journalNode/step2_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/admin/highAvailability/journalNode/step2_view.js b/ambari-web/app/views/main/admin/highAvailability/journalNode/step2_view.js
new file mode 100644
index 0000000..c32bd74
--- /dev/null
+++ b/ambari-web/app/views/main/admin/highAvailability/journalNode/step2_view.js
@@ -0,0 +1,33 @@
+/**
+ * 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.
+ */
+
+
+var App = require('app');
+
+App.ManageJournalNodeWizardStep2View = Em.View.extend({
+
+  templateName: require('templates/main/admin/highAvailability/journalNode/step2'),
+  didInsertElement: function () {
+    this.get('controller').loadStep();
+  },
+  journalNodes: function() {
+    return this.get('controller.content.masterComponentHosts').filterProperty('component', 'JOURNALNODE').filterProperty('isInstalled', false);
+  }.property('controller.content.masterComponentHosts@each'),
+
+  isBackButtonVisible: false
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/views/main/admin/highAvailability/journalNode/step3_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/admin/highAvailability/journalNode/step3_view.js b/ambari-web/app/views/main/admin/highAvailability/journalNode/step3_view.js
new file mode 100644
index 0000000..cac4a7e
--- /dev/null
+++ b/ambari-web/app/views/main/admin/highAvailability/journalNode/step3_view.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.
+ */
+
+
+var App = require('app');
+
+App.ManageJournalNodeWizardStep3View = App.HighAvailabilityWizardStep4View.extend({
+  templateName: require('templates/main/admin/highAvailability/journalNode/step3'),
+  step3BodyText: function () {
+    var nN = this.get('controller.content.masterComponentHosts').filterProperty('component', 'NAMENODE').findProperty('isInstalled', true);
+    return Em.I18n.t('admin.manageJournalNode.wizard.step3.body').format(this.get('controller.content.hdfsUser'), nN.hostName);
+  }.property('controller.content.masterComponentHosts'),
+
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/views/main/admin/highAvailability/journalNode/step4_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/admin/highAvailability/journalNode/step4_view.js b/ambari-web/app/views/main/admin/highAvailability/journalNode/step4_view.js
new file mode 100644
index 0000000..ca995b6
--- /dev/null
+++ b/ambari-web/app/views/main/admin/highAvailability/journalNode/step4_view.js
@@ -0,0 +1,24 @@
+/**
+ * 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.
+ */
+
+
+var App = require('app');
+
+App.ManageJournalNodeWizardStep4View = App.ManageJournalNodeProgressPageView.extend({
+  templateName: require('templates/main/admin/highAvailability/journalNode/step4')
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/views/main/admin/highAvailability/journalNode/step5_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/admin/highAvailability/journalNode/step5_view.js b/ambari-web/app/views/main/admin/highAvailability/journalNode/step5_view.js
new file mode 100644
index 0000000..651cabd
--- /dev/null
+++ b/ambari-web/app/views/main/admin/highAvailability/journalNode/step5_view.js
@@ -0,0 +1,48 @@
+/**
+ * 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.
+ */
+
+
+var App = require('app');
+
+App.ManageJournalNodeWizardStep5View = Em.View.extend({
+
+  templateName: require('templates/main/admin/highAvailability/journalNode/step5'),
+
+  didInsertElement: function() {
+    this.get('controller').loadStep();
+  },
+
+  step5BodyText: function () {
+    var nN = this.get('controller.content.masterComponentHosts').filterProperty('component', 'NAMENODE').findProperty('isInstalled', true);
+    var addNN = this.get('controller.content.masterComponentHosts').filterProperty('component', 'NAMENODE').findProperty('isInstalled', false);
+    return Em.I18n.t('admin.manageJournalNode.wizard.step5.body').format(this.get('controller.content.hdfsUser'), nN.hostName, addNN);
+  }.property('controller.content.masterComponentHosts'),
+
+  jnCheckPointText: function () {
+    switch (this.get('controller.status')) {
+      case 'waiting':
+        return Em.I18n.t('admin.highAvailability.wizard.step6.jsNoInit');
+      case 'done':
+        return Em.I18n.t('admin.highAvailability.wizard.step6.jsInit');
+      case 'journalnode_stopped':
+        return Em.I18n.t('admin.highAvailability.wizard.step6.jnStopped');
+      default:
+        return Em.I18n.t('admin.highAvailability.wizard.step6.jsNoInit');
+    }
+  }.property('controller.status')
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/views/main/admin/highAvailability/journalNode/step6_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/admin/highAvailability/journalNode/step6_view.js b/ambari-web/app/views/main/admin/highAvailability/journalNode/step6_view.js
new file mode 100644
index 0000000..b2d87a2
--- /dev/null
+++ b/ambari-web/app/views/main/admin/highAvailability/journalNode/step6_view.js
@@ -0,0 +1,24 @@
+/**
+ * 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.
+ */
+
+
+var App = require('app');
+
+App.ManageJournalNodeWizardStep6View = App.ManageJournalNodeProgressPageView.extend({
+  templateName: require('templates/main/admin/highAvailability/journalNode/step6')
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/views/main/admin/highAvailability/journalNode/wizard_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/admin/highAvailability/journalNode/wizard_view.js b/ambari-web/app/views/main/admin/highAvailability/journalNode/wizard_view.js
new file mode 100644
index 0000000..434971b
--- /dev/null
+++ b/ambari-web/app/views/main/admin/highAvailability/journalNode/wizard_view.js
@@ -0,0 +1,46 @@
+/**
+ * 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.
+ */
+
+
+var App = require('app');
+
+App.ManageJournalNodeWizardView = Em.View.extend({
+
+  templateName: require('templates/main/admin/highAvailability/journalNode/wizard'),
+
+  isStep1Disabled: function () {
+    return this.isStepDisabled(1);
+  }.property('controller.isStepDisabled.@each.value').cacheable(),
+
+  isStep2Disabled: function () {
+    return this.isStepDisabled(2);
+  }.property('controller.isStepDisabled.@each.value').cacheable(),
+
+  isStep3Disabled: function () {
+    return this.isStepDisabled(3);
+  }.property('controller.isStepDisabled.@each.value').cacheable(),
+
+  isStep4Disabled: function () {
+    return this.isStepDisabled(4);
+  }.property('controller.isStepDisabled.@each.value').cacheable(),
+
+  isStepDisabled: function (index) {
+    return this.get('controller.isStepDisabled').findProperty('step', index).get('value');
+  }
+
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bb58803/ambari-web/app/views/main/service/item.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/service/item.js b/ambari-web/app/views/main/service/item.js
index a007e17..b5c665f 100644
--- a/ambari-web/app/views/main/service/item.js
+++ b/ambari-web/app/views/main/service/item.js
@@ -160,6 +160,12 @@ App.MainServiceItemView = Em.View.extend({
           disabled: App.allHostNames.length === App.HostComponent.find().filterProperty('componentName', master).mapProperty('hostName').length
         }));
       });
+      // add "Manage JournalNode" when NNHA is enabled and there is more hosts than JNs
+      var JNCount = App.HostComponent.find().filterProperty('componentName', 'JOURNALNODE').get('length');
+      if (App.get('supports.manageJournalNode') && service.get('serviceName') == 'HDFS' && service.get('serviceTypes').contains('HA_MODE')
+          && (App.router.get('mainHostController.totalCount') > JNCount || JNCount > 3)) {
+        options.push(actionMap.MANAGE_JN);
+      }
       if (service.get('serviceTypes').contains('HA_MODE') && App.isAuthorized('SERVICE.ENABLE_HA')) {
         switch (service.get('serviceName')) {
           case 'HDFS':