You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by jg...@apache.org on 2018/06/22 20:12:06 UTC

[ambari] branch branch-feature-AMBARI-14714 updated: [AMBARI-23643] Mpack Advisor integration in Install Wizard (#1604)

This is an automated email from the ASF dual-hosted git repository.

jgolieb pushed a commit to branch branch-feature-AMBARI-14714
in repository https://gitbox.apache.org/repos/asf/ambari.git


The following commit(s) were added to refs/heads/branch-feature-AMBARI-14714 by this push:
     new a941bd9  [AMBARI-23643] Mpack Advisor integration in Install Wizard (#1604)
a941bd9 is described below

commit a941bd9667866a1cac750cc8e7e443be5627aa92
Author: jayush <ja...@gmail.com>
AuthorDate: Fri Jun 22 13:12:03 2018 -0700

    [AMBARI-23643] Mpack Advisor integration in Install Wizard (#1604)
    
    * AMBARI-14714. Fix some unit tests
    
    * AMBARI-14714. Fix ServiceResourceProviderTest
    
    * Clear clusterData when user is not logged in.
    
    * Remove references to deleted unit test files and fix broken tests.
    
    * AMBARI-23746. Cannot create same named service in different service groups in same request
    
    * AMBARI-23746. Cannot create same named component in different service groups in same request
    
    * [AMBARI-23969] UI should load stack services from multiple mpacks. (#1403)
    
    * [AMBARI-23969] UI should load stack services from multiple mpacks.
    
    * Removed stack version number
    
    * AMBARI-23972. Update code for : (1). 'mpack-recommendations' directory creation and (2). putting 'mpack_advisor_wrapper.py' in '/var/lib/ambari-server/resources/scripts/' folder.
    
    * AMBARI-22875. Service group name mismatch
    
    * AMBARI-23746. Cannot query services with same name
    
    * AMBARI-23746. Use List for componentID duplicate check
    
    * AMBARI-23987. Set 'skip.service.checks' = true during deploy.
    
    * AMBARI-23999 Remove hardcoded logic in UI to create HDPCORE service group and create multiple service groups
    
    * [AMBARI-23993] Mpack Instance Manager should create pid dir and log dir for each instance (#1424)
    
    * AMBARI-23993: Mpack Instance Manager should create pid dir and log dir for each instance
    
    * AMBARI-23993: Mpack Instance Manager should create pid dir and log dir for each instance
    
    * AMBARI-23993-2: Mpack Instance Manager should create pid dir and log dir for each instance: add get_log_dir and get_run_dir to import
    
    * Merge from main feature branch (#1481)
    
    * Remove references to deleted unit test files and fix broken tests.
    
    * [AMBARI-23969] UI should load stack services from multiple mpacks. (#1403)
    
    * [AMBARI-23969] UI should load stack services from multiple mpacks.
    
    * Removed stack version number
    
    * AMBARI-23972. Update code for : (1). 'mpack-recommendations' directory creation and (2). putting 'mpack_advisor_wrapper.py' in '/var/lib/ambari-server/resources/scripts/' folder.
    
    * AMBARI-14714. Fix some unit tests
    
    * AMBARI-14714. Fix ServiceResourceProviderTest
    
    * AMBARI-23746. Cannot create same named service in different service groups in same request
    
    * AMBARI-23746. Cannot create same named component in different service groups in same request
    
    * AMBARI-22875. Service group name mismatch
    
    * AMBARI-23746. Cannot query services with same name
    
    * AMBARI-23746. Use List for componentID duplicate check
    
    * AMBARI-23987. Set 'skip.service.checks' = true during deploy.
    
    * Clear clusterData when user is not logged in.
    
    * [AMBARI-23993] Mpack Instance Manager should create pid dir and log dir for each instance (#1424)
    
    * AMBARI-23993: Mpack Instance Manager should create pid dir and log dir for each instance
    
    * AMBARI-23993: Mpack Instance Manager should create pid dir and log dir for each instance
    
    * AMBARI-23993-2: Mpack Instance Manager should create pid dir and log dir for each instance: add get_log_dir and get_run_dir to import
    
    * AMBARI-23999 Remove hardcoded logic in UI to create HDPCORE service group and create multiple service groups
    
    * AMBARI-24011: Add workaround to hide client modules in the dashboard (jluniya) (#1443)
    
    Change-Id: Ie69b4e0ca654d59952807694cf2f3f24d6b74c0d
    
    * BUG-104321: Python Mpack Advisor should return MpackInstance block during Host Component Layout Recommendation
    
    * AMBARI-24025 Display Mpack Info on Service Summary Page
    
    * AMBARI-24025 Display Mpack Info on Service Summary Page
    
    * AMBARI-23986. Host components API call doesn't return all host components (#1450)
    
    * AMBARI-24030. Fixes the following : 1. Reading the Node Manager Host (nmHost) correctly. 2. Comments the incorrectly implemented fn : isServiceDeployed().
    
    * AMBARI-24025 Display Mpack Info on Service Summary Page
    
    * [AMBARI-24039] Quicklinks for HBASE are not displayed.
    
    * [AMBARI-24033] Use servicegroup api instead of service to show installed services in the UI.
    
    * AMBARI-14714. Fix some unit tests (#1464)
    
    * Merge from main feature branch. (#1485)
    
    * Remove references to deleted unit test files and fix broken tests.
    
    * [AMBARI-23969] UI should load stack services from multiple mpacks. (#1403)
    
    * [AMBARI-23969] UI should load stack services from multiple mpacks.
    
    * Removed stack version number
    
    * AMBARI-23972. Update code for : (1). 'mpack-recommendations' directory creation and (2). putting 'mpack_advisor_wrapper.py' in '/var/lib/ambari-server/resources/scripts/' folder.
    
    * AMBARI-14714. Fix some unit tests
    
    * AMBARI-14714. Fix ServiceResourceProviderTest
    
    * AMBARI-23746. Cannot create same named service in different service groups in same request
    
    * AMBARI-23746. Cannot create same named component in different service groups in same request
    
    * AMBARI-22875. Service group name mismatch
    
    * AMBARI-23746. Cannot query services with same name
    
    * AMBARI-23746. Use List for componentID duplicate check
    
    * AMBARI-23987. Set 'skip.service.checks' = true during deploy.
    
    * Clear clusterData when user is not logged in.
    
    * [AMBARI-23993] Mpack Instance Manager should create pid dir and log dir for each instance (#1424)
    
    * AMBARI-23993: Mpack Instance Manager should create pid dir and log dir for each instance
    
    * AMBARI-23993: Mpack Instance Manager should create pid dir and log dir for each instance
    
    * AMBARI-23993-2: Mpack Instance Manager should create pid dir and log dir for each instance: add get_log_dir and get_run_dir to import
    
    * AMBARI-23999 Remove hardcoded logic in UI to create HDPCORE service group and create multiple service groups
    
    * AMBARI-24011: Add workaround to hide client modules in the dashboard (jluniya) (#1443)
    
    Change-Id: Ie69b4e0ca654d59952807694cf2f3f24d6b74c0d
    
    * BUG-104321: Python Mpack Advisor should return MpackInstance block during Host Component Layout Recommendation
    
    * AMBARI-24025 Display Mpack Info on Service Summary Page
    
    * AMBARI-24025 Display Mpack Info on Service Summary Page
    
    * AMBARI-23986. Host components API call doesn't return all host components (#1450)
    
    * AMBARI-24030. Fixes the following : 1. Reading the Node Manager Host (nmHost) correctly. 2. Comments the incorrectly implemented fn : isServiceDeployed().
    
    * AMBARI-24025 Display Mpack Info on Service Summary Page
    
    * [AMBARI-24039] Quicklinks for HBASE are not displayed.
    
    * [AMBARI-24033] Use servicegroup api instead of service to show installed services in the UI.
    
    * AMBARI-14714. Fix some unit tests (#1464)
    
    * AMBARI-24046. Fix the incorrect string from config_name to config-name in mpack_advisor.py (#1480)
    
    * Revert previous commit (#1486)
    
    * Remove references to deleted unit test files and fix broken tests.
    
    * [AMBARI-23969] UI should load stack services from multiple mpacks. (#1403)
    
    * [AMBARI-23969] UI should load stack services from multiple mpacks.
    
    * Removed stack version number
    
    * AMBARI-23972. Update code for : (1). 'mpack-recommendations' directory creation and (2). putting 'mpack_advisor_wrapper.py' in '/var/lib/ambari-server/resources/scripts/' folder.
    
    * AMBARI-14714. Fix some unit tests
    
    * AMBARI-14714. Fix ServiceResourceProviderTest
    
    * AMBARI-23746. Cannot create same named service in different service groups in same request
    
    * AMBARI-23746. Cannot create same named component in different service groups in same request
    
    * AMBARI-22875. Service group name mismatch
    
    * AMBARI-23746. Cannot query services with same name
    
    * AMBARI-23746. Use List for componentID duplicate check
    
    * AMBARI-23987. Set 'skip.service.checks' = true during deploy.
    
    * Clear clusterData when user is not logged in.
    
    * [AMBARI-23993] Mpack Instance Manager should create pid dir and log dir for each instance (#1424)
    
    * AMBARI-23993: Mpack Instance Manager should create pid dir and log dir for each instance
    
    * AMBARI-23993: Mpack Instance Manager should create pid dir and log dir for each instance
    
    * AMBARI-23993-2: Mpack Instance Manager should create pid dir and log dir for each instance: add get_log_dir and get_run_dir to import
    
    * AMBARI-23999 Remove hardcoded logic in UI to create HDPCORE service group and create multiple service groups
    
    * AMBARI-24011: Add workaround to hide client modules in the dashboard (jluniya) (#1443)
    
    Change-Id: Ie69b4e0ca654d59952807694cf2f3f24d6b74c0d
    
    * BUG-104321: Python Mpack Advisor should return MpackInstance block during Host Component Layout Recommendation
    
    * AMBARI-24025 Display Mpack Info on Service Summary Page
    
    * AMBARI-24025 Display Mpack Info on Service Summary Page
    
    * AMBARI-23986. Host components API call doesn't return all host components (#1450)
    
    * AMBARI-24030. Fixes the following : 1. Reading the Node Manager Host (nmHost) correctly. 2. Comments the incorrectly implemented fn : isServiceDeployed().
    
    * AMBARI-24025 Display Mpack Info on Service Summary Page
    
    * [AMBARI-24039] Quicklinks for HBASE are not displayed.
    
    * [AMBARI-24033] Use servicegroup api instead of service to show installed services in the UI.
    
    * AMBARI-14714. Fix some unit tests (#1464)
    
    * AMBARI-24046. Fix the incorrect string from config_name to config-name in mpack_advisor.py (#1480)
    
    * [AMBARI-23643] Mpack Advisor integration in Install wizard.
    
    * Revert "[AMBARI-23643] Mpack Advisor integration in Install wizard."
    
    This reverts commit 01efc2ce9b3e5d3be67add4c3f262607d3e34390.
    
    * [AMBARI-23643] Mpack Advisor integration in Install Wizard (#1487)
    
    * Remove references to deleted unit test files and fix broken tests.
    
    * [AMBARI-23969] UI should load stack services from multiple mpacks. (#1403)
    
    * [AMBARI-23969] UI should load stack services from multiple mpacks.
    
    * Removed stack version number
    
    * AMBARI-23972. Update code for : (1). 'mpack-recommendations' directory creation and (2). putting 'mpack_advisor_wrapper.py' in '/var/lib/ambari-server/resources/scripts/' folder.
    
    * AMBARI-14714. Fix some unit tests
    
    * AMBARI-14714. Fix ServiceResourceProviderTest
    
    * AMBARI-23746. Cannot create same named service in different service groups in same request
    
    * AMBARI-23746. Cannot create same named component in different service groups in same request
    
    * AMBARI-22875. Service group name mismatch
    
    * AMBARI-23746. Cannot query services with same name
    
    * AMBARI-23746. Use List for componentID duplicate check
    
    * AMBARI-23987. Set 'skip.service.checks' = true during deploy.
    
    * Clear clusterData when user is not logged in.
    
    * [AMBARI-23993] Mpack Instance Manager should create pid dir and log dir for each instance (#1424)
    
    * AMBARI-23993: Mpack Instance Manager should create pid dir and log dir for each instance
    
    * AMBARI-23993: Mpack Instance Manager should create pid dir and log dir for each instance
    
    * AMBARI-23993-2: Mpack Instance Manager should create pid dir and log dir for each instance: add get_log_dir and get_run_dir to import
    
    * AMBARI-23999 Remove hardcoded logic in UI to create HDPCORE service group and create multiple service groups
    
    * AMBARI-24011: Add workaround to hide client modules in the dashboard (jluniya) (#1443)
    
    Change-Id: Ie69b4e0ca654d59952807694cf2f3f24d6b74c0d
    
    * BUG-104321: Python Mpack Advisor should return MpackInstance block during Host Component Layout Recommendation
    
    * AMBARI-24025 Display Mpack Info on Service Summary Page
    
    * AMBARI-24025 Display Mpack Info on Service Summary Page
    
    * AMBARI-23986. Host components API call doesn't return all host components (#1450)
    
    * AMBARI-24030. Fixes the following : 1. Reading the Node Manager Host (nmHost) correctly. 2. Comments the incorrectly implemented fn : isServiceDeployed().
    
    * AMBARI-24025 Display Mpack Info on Service Summary Page
    
    * [AMBARI-24039] Quicklinks for HBASE are not displayed.
    
    * [AMBARI-24033] Use servicegroup api instead of service to show installed services in the UI.
    
    * AMBARI-14714. Fix some unit tests (#1464)
    
    * AMBARI-24046. Fix the incorrect string from config_name to config-name in mpack_advisor.py (#1480)
    
    * [AMBARI-23643] Mpack Advisor integration in Install wizard.
    
    * [AMBARI-24053] Do not move service-specific configs to Misc section
    
    * [AMBARI-24053] Fix bug in previous commit to this issue.
    
    * [AMBARI-24111] Enable configs originating from mpack advisor to be added (#1548)
    
    * [AMBARI-24111] Enable configs originating from mpack advisor to be added.
    
    * Fixed unit test.
    
    * [AMBARI-24083] Enable same service to be installed from multiple mpacks (#1538)
    
    * [AMBARI-24083] Allow clients from multiple mpacks to be installed
    
    * Unit test fixes.
    
    * Unit test added
    
    * [AMBARI-24115] Install all services and start all services with a single request each
    
    * [AMBARI-24137] Fixed mpack display on service summary view.
    
    * [AMBARI-24095] Fixed usages of App.StackService.find(serviceName) since serviceName is no longer used as the value of the StackService model id. (#1581)
    
    * [AMBARI-24095] Fixed usages of App.StackService.find(serviceName) since serviceName is no longer used as the value of the StackService model id.
    
    * Fixed installation issue.
    
    * Fixed a couple instances that were hard-coded.
    
    * Fixed unit test.
---
 ambari-web/app/controllers/installer.js            |   6 +
 ambari-web/app/controllers/main/service.js         |   2 +-
 .../app/controllers/main/service/info/configs.js   |   6 +-
 ambari-web/app/controllers/main/service/item.js    |  12 +-
 .../service/widgets/create/wizard_controller.js    |   2 +-
 ambari-web/app/controllers/wizard.js               | 119 ++++++++++---
 .../app/controllers/wizard/step6_controller.js     |   4 +-
 .../wizard/step7/assign_master_controller.js       |   2 +-
 .../app/controllers/wizard/step7_controller.js     |  10 +-
 .../app/controllers/wizard/step8_controller.js     | 191 +++++++++++----------
 .../app/controllers/wizard/step9_controller.js     |  44 ++---
 .../configs/stack_config_properties_mapper.js      |  27 ++-
 ambari-web/app/mappers/mpack_service_mapper.js     |   6 +-
 ambari-web/app/mappers/service_mapper.js           |  24 ++-
 ambari-web/app/mappers/stack_service_mapper.js     |   5 +-
 ambari-web/app/mixins/common/blueprint.js          |   6 +-
 .../app/mixins/common/configs/configs_saver.js     |   6 +-
 .../app/mixins/common/configs/enhanced_configs.js  |  52 +++---
 .../hosts/host_component_recommendation_mixin.js   |  46 ++---
 .../hosts/host_component_validation_mixin.js       |  46 +++--
 ambari-web/app/mixins/common/serverValidator.js    |  87 ++++------
 .../app/mixins/wizard/assign_master_components.js  |  45 ++---
 ambari-web/app/models/service.js                   |   2 +
 ambari-web/app/styles/bootstrap_overrides.less     |   2 -
 ambari-web/app/utils/ajax/ajax.js                  |  39 +++--
 ambari-web/app/utils/config.js                     |   7 +-
 ambari-web/app/utils/misc.js                       |   7 +-
 .../views/main/dashboard/widgets/hbase_links.js    |   2 +-
 ambari-web/app/views/main/service/item.js          |   2 +-
 .../app/views/main/service/reassign/step5_view.js  |   2 +-
 ambari-web/app/views/main/service/service.js       |   6 +-
 .../main/service/widgets/create/expression_view.js |   2 +-
 ambari-web/test/controllers/installer_test.js      |   9 +-
 .../controllers/main/host/configs_service_test.js  |   8 +
 .../controllers/main/service/info/config_test.js   |   6 +-
 .../test/controllers/main/service/item_test.js     |  22 ++-
 ambari-web/test/controllers/wizard/step5_test.js   |  24 ++-
 .../wizard/step7/assign_master_controller_test.js  |   6 +-
 ambari-web/test/controllers/wizard_test.js         |   3 +-
 .../test/mappers/stack_service_mapper_test.js      |   2 +-
 .../mixins/common/configs/configs_saver_test.js    |  21 ++-
 .../mixins/common/configs/enhanced_configs_test.js | 115 ++++++++-----
 .../host_component_recommendation_mixin_test.js    |  52 +++---
 .../hosts/host_component_validation_mixin_test.js  |  73 ++++----
 .../mixins/common/widgets/widget_section_test.js   |   4 +-
 ambari-web/test/utils/config_test.js               |  11 +-
 46 files changed, 679 insertions(+), 496 deletions(-)

diff --git a/ambari-web/app/controllers/installer.js b/ambari-web/app/controllers/installer.js
index 06c41f0..15c1c43 100644
--- a/ambari-web/app/controllers/installer.js
+++ b/ambari-web/app/controllers/installer.js
@@ -346,6 +346,7 @@ App.InstallerController = App.WizardController.extend(App.Persist, {
         display_name: _component.get('display_name'),
         component: _component.get('component_name'),
         serviceId: _component.get('serviceId'),
+        serviceGroupName: _component.get('mpackInstance'),
         isInstalled: false,
         host_id: hosts[_component.get('selectedHost')].id
       });
@@ -387,6 +388,7 @@ App.InstallerController = App.WizardController.extend(App.Persist, {
   },
 
   loadCurrentHostGroups: function () {
+    this.set("content.recommendations", this.getDBProperty('recommendations'));
     this.set("content.recommendationsHostGroups", this.getDBProperty('recommendationsHostGroups'));
   },
 
@@ -428,6 +430,8 @@ App.InstallerController = App.WizardController.extend(App.Persist, {
       client.forEach(function (clientComponent) {
         clients.pushObject({
           component_name: clientComponent.get('componentName'),
+          service_name: _service.get('serviceName'),
+          serviceGroupName: _service.get('stackName'),
           display_name: clientComponent.get('displayName'),
           isInstalled: false
         });
@@ -1028,6 +1032,8 @@ App.InstallerController = App.WizardController.extend(App.Persist, {
         client.forEach(clientComponent => {
           clients.pushObject({
             component_name: clientComponent.get('componentName'),
+            service_name: service.get('serviceName'),
+            serviceGroupName: service.get('stackName'),
             display_name: clientComponent.get('displayName'),
             isInstalled: false
           });
diff --git a/ambari-web/app/controllers/main/service.js b/ambari-web/app/controllers/main/service.js
index 7455eac..c52471a 100644
--- a/ambari-web/app/controllers/main/service.js
+++ b/ambari-web/app/controllers/main/service.js
@@ -30,7 +30,7 @@ App.MainServiceController = Em.ArrayController.extend(App.SupportClientConfigsDo
     if (!App.router.get('clusterController.isLoaded')) {
       return [];
     }
-    return misc.sortByOrder(App.StackService.find().mapProperty('serviceName'), App.Service.find().toArray());
+    return misc.sortByOrder(App.StackService.find().mapProperty('serviceName'), App.Service.find().toArray(), s => s.get('serviceName'));
   }.property('App.router.clusterController.isLoaded').volatile(),
 
   /**
diff --git a/ambari-web/app/controllers/main/service/info/configs.js b/ambari-web/app/controllers/main/service/info/configs.js
index c0b6b5b..e251f6d 100644
--- a/ambari-web/app/controllers/main/service/info/configs.js
+++ b/ambari-web/app/controllers/main/service/info/configs.js
@@ -324,10 +324,10 @@ App.MainServiceInfoConfigsController = Em.Controller.extend(App.AddSecurityConfi
    * @returns {String[]}
    */
   getServicesDependencies: function(serviceName) {
-    var dependencies = Em.getWithDefault(App.StackService.find(serviceName), 'dependentServiceNames', []);
+    var dependencies = Em.getWithDefault(App.StackService.find().findProperty('serviceName', serviceName), 'dependentServiceNames', []);
     var loop = function(dependentServices, allDependencies) {
       return dependentServices.reduce(function(all, name) {
-        var service = App.StackService.find(name);
+        var service = App.StackService.find().findProperty('serviceName', name);
         if (!service) {
           return all;
         }
@@ -589,7 +589,7 @@ App.MainServiceInfoConfigsController = Em.Controller.extend(App.AddSecurityConfi
   onLoadOverrides: function (allConfigs) {
     this.get('servicesToLoad').forEach(function(serviceName) {
       var configGroups = serviceName === this.get('content.serviceName') ? this.get('configGroups') : this.get('dependentConfigGroups').filterProperty('serviceName', serviceName);
-      var configTypes = App.StackService.find(serviceName).get('configTypeList');
+      var configTypes = App.StackService.find().findProperty('serviceName', serviceName).get('configTypeList');
       var configsByService = this.get('allConfigs').filter(function (c) {
         return configTypes.contains(App.config.getConfigTagFromFileName(c.get('filename')));
       });
diff --git a/ambari-web/app/controllers/main/service/item.js b/ambari-web/app/controllers/main/service/item.js
index 4e67204..3e2ab88 100644
--- a/ambari-web/app/controllers/main/service/item.js
+++ b/ambari-web/app/controllers/main/service/item.js
@@ -127,8 +127,8 @@ App.MainServiceItemController = Em.Controller.extend(App.SupportClientConfigsDow
    */
   interDependentServices: function() {
     var serviceName = this.get('content.serviceName'), interDependentServices = [];
-    App.StackService.find(serviceName).get('requiredServices').forEach(function(requiredService) {
-      if (App.StackService.find(requiredService).get('requiredServices').contains(serviceName)) {
+    App.StackService.find().findProperty('serviceName', serviceName).get('requiredServices').forEach(function(requiredService) {
+      if (App.StackService.find().findProperty('serviceName', requiredService).get('requiredServices').contains(serviceName)) {
         interDependentServices.push(requiredService);
       }
     });
@@ -149,11 +149,11 @@ App.MainServiceItemController = Em.Controller.extend(App.SupportClientConfigsDow
    */
   dependentServiceNames: function() {
     return App.get('router.clusterController.isConfigsPropertiesLoaded') ?
-      App.StackService.find(this.get('content.serviceName')).get('dependentServiceNames') : [];
+      App.StackService.find().findProperty('serviceName', this.get('content.serviceName')).get('dependentServiceNames') : [];
   }.property('content.serviceName', 'App.router.clusterController.isConfigsPropertiesLoaded'),
 
   configDependentServiceNames: function() {
-    return this.get('dependentServiceNames').concat(App.StackService.find(this.get('content.serviceName')).get('requiredServices'))
+    return this.get('dependentServiceNames').concat(App.StackService.find().findProperty('serviceName', this.get('content.serviceName')).get('requiredServices'))
   }.property('dependentServiceNames'),
 
   /**
@@ -244,7 +244,7 @@ App.MainServiceItemController = Em.Controller.extend(App.SupportClientConfigsDow
         });
 
         self.get('configDependentServiceNames').forEach(function(serviceName) {
-          var configTypes = App.StackService.find(serviceName.name).get('configTypeList');
+          var configTypes = App.StackService.find().findProperty('serviceName', serviceName.name).get('configTypeList');
           if (configTypes) {
             var configsByService = allConfigs.filter(function (c) {
               return configTypes.contains(App.config.getConfigTagFromFileName(c.get('filename')));
@@ -1393,7 +1393,7 @@ App.MainServiceItemController = Em.Controller.extend(App.SupportClientConfigsDow
 
     App.Service.find().forEach(function (service) {
       if (!serviceNamesToDelete.contains(service.get('serviceName'))) {
-        var requiredServices = App.StackService.find(service.get('serviceName')).get('requiredServices');
+        var requiredServices = App.StackService.find().findProperty('serviceName', service.get('serviceName')).get('requiredServices');
         serviceNamesToDelete.forEach(function (dependsOnService) {
           if (requiredServices.contains(dependsOnService)) {
             dependentServices.push(service.get('serviceName'));
diff --git a/ambari-web/app/controllers/main/service/widgets/create/wizard_controller.js b/ambari-web/app/controllers/main/service/widgets/create/wizard_controller.js
index a46c5e4..79f6be5 100644
--- a/ambari-web/app/controllers/main/service/widgets/create/wizard_controller.js
+++ b/ambari-web/app/controllers/main/service/widgets/create/wizard_controller.js
@@ -210,7 +210,7 @@ App.WidgetWizardController = App.WizardController.extend({
       data: {
         stackVersionURL: App.get('stackVersionURL'),
         serviceNames: App.Service.find().filter(function (item) {
-          return App.StackService.find(item.get('id')).get('isServiceWithWidgets');
+          return App.StackService.find().findProperty('serviceName', item.get('id')).get('isServiceWithWidgets');
         }).mapProperty('serviceName').join(',')
       },
       callback: callback,
diff --git a/ambari-web/app/controllers/wizard.js b/ambari-web/app/controllers/wizard.js
index feccd7d..ca5891f 100644
--- a/ambari-web/app/controllers/wizard.js
+++ b/ambari-web/app/controllers/wizard.js
@@ -18,7 +18,7 @@
 
 
 var App = require('app');
-
+var blueprintUtils = require('utils/blueprint');
 require('models/host');
 
 App.WizardController = Em.Controller.extend(App.LocalStorage, App.ThemesMappingMixin, {
@@ -553,21 +553,13 @@ App.WizardController = Em.Controller.extend(App.LocalStorage, App.ThemesMappingM
     };
     this.saveClusterStatus(clusterStatus);
 
-    const serviceGroups = this.get('content.serviceGroups');
-    
-    const installPromises = serviceGroups.map(sg => {
-      data.serviceGroupName = sg;
-
-      return App.ajax.send({
-        name: isRetry ? 'common.host_components.update' : 'common.services.update',
-        sender: this,
-        data: data,
-        success: 'installServicesSuccessCallback',
-        error: 'installServicesErrorCallback'
-      })
-    })
-
-    $.when(...installPromises).then(callback, callback);
+    return App.ajax.send({
+      name: isRetry ? 'common.host_components.update' : 'common.services.update.all',
+      sender: this,
+      data: data,
+      success: 'installServicesSuccessCallback',
+      error: 'installServicesErrorCallback'
+    }).then(callback, callback);
   },
 
   installServicesSuccessCallback: function (jsonData) {
@@ -940,20 +932,21 @@ App.WizardController = Em.Controller.extend(App.LocalStorage, App.ThemesMappingM
    * @param stepController
    */
   saveSlaveComponentHosts: function (stepController) {
-    var hosts = stepController.get('hosts'),
-      dbHosts = this.getDBProperty('hosts'),
-      headers = stepController.get('headers');
+    const hosts = stepController.get('hosts');
+    const dbHosts = this.getDBProperty('hosts');
+    const headers = stepController.get('headers');
 
-    var formattedHosts = Ember.Object.create();
+    const formattedHosts = Ember.Object.create();
     headers.forEach(function (header) {
       formattedHosts.set(header.get('name'), []);
     });
 
     hosts.forEach(function (host) {
+      const checkboxes = host.checkboxes;
 
-      var checkboxes = host.checkboxes;
       headers.forEach(function (header) {
-        var cb = checkboxes.findProperty('title', header.get('label'));
+        const cb = checkboxes.findProperty('title', header.get('label'));
+
         if (cb.checked) {
           formattedHosts.get(header.get('name')).push({
             group: 'Default',
@@ -964,13 +957,15 @@ App.WizardController = Em.Controller.extend(App.LocalStorage, App.ThemesMappingM
       });
     });
 
-    var slaveComponentHosts = [];
+    const slaveComponentHosts = [];
 
     headers.forEach(function (header) {
       slaveComponentHosts.push({
         componentName: header.get('name'),
         displayName: header.get('label').replace(/\s/g, ''),
-        hosts: formattedHosts.get(header.get('name'))
+        hosts: formattedHosts.get(header.get('name')),
+        serviceName: header.get('serviceName'),
+        serviceGroupName: header.get('serviceGroupName')
       });
     });
 
@@ -1705,5 +1700,81 @@ App.WizardController = Em.Controller.extend(App.LocalStorage, App.ThemesMappingM
         });
       }
     });
+  },
+
+  /**
+   * Return mpack_instances data needed for mpack advisor recommendations requests.
+   * This is basically service groups formatted as required by the mpack advisor API.
+   */
+  getMpackInstances: function (configs) {
+    const mpackInstances = {};
+    const selectedServices = this.get('content.selectedServices');
+    
+    selectedServices.forEach(service => {
+      //these will be defined by the user in the future
+      const serviceGroupName = service.mpackName;
+      const serviceInstanceName = service.name;
+
+      if (!mpackInstances[serviceGroupName]) {
+        mpackInstances[serviceGroupName] = {
+          name: serviceGroupName,
+          type: service.mpackName,
+          version: service.mpackVersion,
+          service_instances: []
+        };
+      }
+
+      const serviceInstance = {
+        name: serviceInstanceName,
+        type: service.name
+      };
+
+      //configs will be passed if we are building a request for configs recommendations/validations
+      //it will not be passed if we are building a request for host recommendations/validations
+      if (configs) {
+        const configurations = this.getConfigsForServiceInstance(service.name, service.mpackName, service.mpackVersion, configs);
+        if (configurations) {
+          serviceInstance.configurations = configurations;
+        }
+      }  
+
+      mpackInstances[serviceGroupName].service_instances.push(serviceInstance);
+    });
+
+    const mpack_instances = [];
+    for (let prop in mpackInstances) {
+      mpack_instances.push(mpackInstances[prop]);
+    }
+
+    return mpack_instances;
+  },
+
+  /**
+   * Returns configs specific to the given service, stack, and stack version formatted as a blueprint fragment.
+   * This is used to build out the Mpack Advisor config recommendation/validation request.
+   * This is also used to get the "MISC" configs (configs not specific to a service).
+   * 
+   * @param {string} serviceName The name/type of the service to get configs for.
+   * @param {string} stackName The name of the stack/mpack to get configs for.
+   * @param {string} stackVersion The version of the stack/mpack to get configs for.
+   * @param {array} configs List of configs to be filtered. This is typically all configs loaded from the stack information.
+   */
+  getConfigsForServiceInstance: function (serviceName, stackName, stackVersion, configs) {
+    const serviceConfigs = configs.findProperty('serviceName', serviceName);
+    
+    if (serviceConfigs) {
+      let serviceInstanceConfigs;
+      
+      if (stackName && stackVersion) {
+        serviceInstanceConfigs = serviceConfigs.configs.filter(config => (config.stackName === stackName && config.stackVersion === stackVersion) || config.stackName === undefined);
+      } else {
+        serviceInstanceConfigs = serviceConfigs.configs;
+      }  
+
+      serviceConfigs.set('configs', serviceInstanceConfigs);
+      return blueprintUtils.buildConfigsJSON([serviceConfigs]); //buildConfigsJSON() expects an array
+    }
+
+    return null;
   }
 });
diff --git a/ambari-web/app/controllers/wizard/step6_controller.js b/ambari-web/app/controllers/wizard/step6_controller.js
index 3f0b2d7..73e6544 100644
--- a/ambari-web/app/controllers/wizard/step6_controller.js
+++ b/ambari-web/app/controllers/wizard/step6_controller.js
@@ -322,6 +322,8 @@ App.WizardStep6Controller = App.WizardStepController.extend(App.HostComponentVal
         if (serviceComponent.get('isShownOnInstallerSlaveClientPage')) {
           headers.pushObject(Em.Object.create({
             name: serviceComponent.get('componentName'),
+            serviceName: stackService.get('serviceName'),
+            serviceGroupName: stackService.get('stackName'),
             label: App.format.role(serviceComponent.get('componentName'), false),
             allChecked: false,
             isRequired: serviceComponent.get('isRequired'),
@@ -335,7 +337,7 @@ App.WizardStep6Controller = App.WizardStepController.extend(App.HostComponentVal
     }, this);
     if (this.get('content.clients') && !!this.get('content.clients').length) {
       headers.pushObject(Em.Object.create({
-        name: 'CLIENT',
+        name: 'CLIENT',        
         label: App.format.role('CLIENT', false),
         allChecked: false,
         noChecked: true,
diff --git a/ambari-web/app/controllers/wizard/step7/assign_master_controller.js b/ambari-web/app/controllers/wizard/step7/assign_master_controller.js
index ac9c33c..2d18586 100644
--- a/ambari-web/app/controllers/wizard/step7/assign_master_controller.js
+++ b/ambari-web/app/controllers/wizard/step7/assign_master_controller.js
@@ -357,7 +357,7 @@ App.AssignMasterOnStep7Controller = Em.Controller.extend(App.BlueprintMixin, App
     return dependentServices.filter(function (item) {
       return !App.Service.find().findProperty('serviceName', item);
     }).map(function (item) {
-      return App.StackService.find(item).get('displayName');
+      return App.StackService.find().findProperty('serviceName', item).get('displayName');
     });
   },
 
diff --git a/ambari-web/app/controllers/wizard/step7_controller.js b/ambari-web/app/controllers/wizard/step7_controller.js
index e0cd249..860df8a 100644
--- a/ambari-web/app/controllers/wizard/step7_controller.js
+++ b/ambari-web/app/controllers/wizard/step7_controller.js
@@ -617,13 +617,11 @@ App.WizardStep7Controller = App.WizardStepController.extend(App.ServerValidatorM
           self.loadConfigRecommendations(null, self.completeConfigLoading.bind(self));
         });
       }
-
     } else {
       console.timeEnd('applyServicesConfigs execution time: ');
       console.time('loadConfigRecommendations execution time: ');
       self.loadConfigRecommendations(null, self.completeConfigLoading.bind(self));
     }
-
   },
 
   /**
@@ -756,7 +754,13 @@ App.WizardStep7Controller = App.WizardStepController.extend(App.ServerValidatorM
       var serviceName = service.get('serviceName');
       if (['MISC'].concat(this.get('allSelectedServiceNames')).contains(serviceName)) {
         var serviceConfig = App.config.createServiceConfig(serviceName);
-        serviceConfig.set('showConfig', App.StackService.find(serviceName).get('isInstallable'));
+        let stackService;
+        if (serviceName === 'MISC') {
+          stackService = App.StackService.find('MISC');
+        } else {
+          stackService = App.StackService.find().findProperty('serviceName', serviceName);
+        }
+        serviceConfig.set('showConfig', stackService.get('isInstallable'));
         if (this.get('wizardController.name') === 'addServiceController') {
           serviceConfig.set('selected', !this.get('installedServiceNames').concat('MISC').contains(serviceName));
           if (serviceName === 'MISC') {
diff --git a/ambari-web/app/controllers/wizard/step8_controller.js b/ambari-web/app/controllers/wizard/step8_controller.js
index 90c3a3b..4f73fe0 100644
--- a/ambari-web/app/controllers/wizard/step8_controller.js
+++ b/ambari-web/app/controllers/wizard/step8_controller.js
@@ -971,7 +971,7 @@ App.WizardStep8Controller = App.WizardStepController.extend(App.AddSecurityConfi
       const serviceGroups = mpacks.map(mpack => ({
           "ServiceGroupInfo": {
             "service_group_name": mpack.name,
-            "version": mpack.id
+            "version": `${mpack.name}-${mpack.version}`
           }
         })
       );
@@ -1118,37 +1118,52 @@ App.WizardStep8Controller = App.WizardStepController.extend(App.AddSecurityConfi
    * @method createMasterHostComponents
    */
   createMasterHostComponents: function () {
-    var masterOnAllHosts = [];
+    const masterOnAllHosts = [];
 
     this.get('content.services').filterProperty('isSelected').forEach(function (service) {
-      service.get('serviceComponents').filterProperty('isRequiredOnAllHosts').forEach(function (component) {
+      service.get('serviceComponents').filterProperty('isRequiredOnAllHosts').forEach(component => {
         if (component.get('isMaster')) {
           masterOnAllHosts.push(component.get('componentName'));
         }
       }, this);
     }, this);
 
-    // create master components for only selected services.
-    var selectedMasterComponents = this.get('content.masterComponentHosts').filter(function (_component) {
-      return this.get('selectedServices').mapProperty('serviceName').contains(_component.serviceId)
-    }, this);
-    selectedMasterComponents.mapProperty('component').uniq().forEach(function (component) {
-      var hostNames = [];
+    //get unique occurrences per service group, since components in the same SG going onto multiple hosts must only be processed once
+    const uniqueMasterComponents = {};
+    this.get('content.masterComponentHosts').forEach(component => {
+      uniqueMasterComponents[`${component.component}-${component.serviceId}-${component.serviceGroupName}`] = component;
+    });
+    
+    //convert to arry for further filtering
+    const masterComponentsArray = [];
+    for (let prop in uniqueMasterComponents) {
+      masterComponentsArray.push(uniqueMasterComponents[prop]);
+    }
+    
+    //get only selected services.
+    const selectedMasterComponents = masterComponentsArray.filter(component => this.get('selectedServices').mapProperty('serviceName').contains(component.serviceId), this);
+    selectedMasterComponents.forEach(component => {
+      const componentName = component.component;
+      const serviceName = component.serviceId;
+      const serviceGroupName = component.serviceGroupName;
+
       if (masterOnAllHosts.length > 0) {
-        var compOnAllHosts = false;
-        for (var i=0; i < masterOnAllHosts.length; i++) {
-          if (component === masterOnAllHosts[i]) {
+        let compOnAllHosts = false;
+        
+        for (let i = 0; i < masterOnAllHosts.length; i++) {
+          if (componentName === masterOnAllHosts[i]) {
             compOnAllHosts = true;
             break;
           }
         }
+        
         if (!compOnAllHosts) {
-          hostNames = selectedMasterComponents.filterProperty('component', component).filterProperty('isInstalled', false).mapProperty('hostName');
-          this.registerHostsToComponent(hostNames, component);
+          const hostNames = selectedMasterComponents.filterProperty('component', componentName).filterProperty('isInstalled', false).mapProperty('hostName');
+          this.registerHostsToComponent(hostNames, componentName, serviceName, serviceGroupName);
         }
       } else {
-        hostNames = selectedMasterComponents.filterProperty('component', component).filterProperty('isInstalled', false).mapProperty('hostName');
-        this.registerHostsToComponent(hostNames, component);
+        const hostNames = selectedMasterComponents.filterProperty('component', componentName).filterProperty('isInstalled', false).mapProperty('hostName');
+        this.registerHostsToComponent(hostNames, componentName, serviceName, serviceGroupName);
       }
     }, this);
   },
@@ -1222,14 +1237,13 @@ App.WizardStep8Controller = App.WizardStepController.extend(App.AddSecurityConfi
           }
           if (!compOnAllHosts) {
             hostNames = _slave.hosts.filterProperty('isInstalled', false).mapProperty('hostName');
-            this.registerHostsToComponent(hostNames, _slave.componentName);
+            this.registerHostsToComponent(hostNames, _slave.componentName, _slave.serviceName, _slave.serviceGroupName);
           }
         } else {
           hostNames = _slave.hosts.filterProperty('isInstalled', false).mapProperty('hostName');
-          this.registerHostsToComponent(hostNames, _slave.componentName);
+          this.registerHostsToComponent(hostNames, _slave.componentName, _slave.serviceName, _slave.serviceGroupName);
         }
-      }
-      else {
+      } else {
         clients.forEach(function (_client) {
           hostNames = _slave.hosts.mapProperty('hostName');
           // The below logic to install clients to existing/New master hosts should not be applied to Add Host wizard.
@@ -1262,11 +1276,11 @@ App.WizardStep8Controller = App.WizardStepController.extend(App.AddSecurityConfi
             }
             if (!compOnAllHosts) {
               hostNames = hostNames.uniq();
-              this.registerHostsToComponent(hostNames, _client.component_name);
+              this.registerHostsToComponent(hostNames, _client.component_name, _client.service_name, _client.serviceGroupName);
             }
           } else {
             hostNames = hostNames.uniq();
-            this.registerHostsToComponent(hostNames, _client.component_name);
+            this.registerHostsToComponent(hostNames, _client.component_name, _client.service_name, _client.serviceGroupName);
           }
         }, this);
       }
@@ -1286,18 +1300,17 @@ App.WizardStep8Controller = App.WizardStepController.extend(App.AddSecurityConfi
     var clients = this.get('content.clients').filterProperty('isInstalled', false);
     var clientsToMasterMap = this.getClientsMap('isMaster');
     var clientsToClientMap = this.getClientsMap('isClient');
-    var installedClients = [];
+    let installedClients = [];
 
     // Get all the installed Client components
     this.get('content.services').filterProperty('isInstalled').forEach(function (_service) {
-      var serviceClients = App.StackServiceComponent.find().filterProperty('serviceName', _service.get('serviceName')).filterProperty('isClient');
-      serviceClients.forEach(function (client) {
-        installedClients.push(client.get('componentName'));
-      }, this);
+      installedClients = App.StackServiceComponent.find().filterProperty('serviceName', _service.get('serviceName')).filterProperty('isClient');
     }, this);
 
     // Check if there is a dependency for being co-hosted between existing client and selected new master
-    installedClients.forEach(function (_clientName) {
+    installedClients.forEach(function (client) {
+      const _clientName = client.get('componentName');
+
       if (clientsToMasterMap[_clientName] || clientsToClientMap[_clientName]) {
         var hostNames = [];
         if (clientsToMasterMap[_clientName]) {
@@ -1323,8 +1336,8 @@ App.WizardStep8Controller = App.WizardStepController.extend(App.AddSecurityConfi
           // If a dependency for being co-hosted is derived between existing client and selected new master but that
           // dependency is already satisfied in the cluster then disregard the derived dependency
           this.removeClientsFromList(_clientName, hostNames);
-          this.registerHostsToComponent(hostNames, _clientName);
-          if(hostNames.length > 0) {
+          this.registerHostsToComponent(hostNames, _clientName, client.service_name, client.serviceGroupName);
+          if (hostNames.length > 0) {
             this.get('content.additionalClients').pushObject({hostNames: hostNames, componentName: _clientName});
           }
         }
@@ -1372,9 +1385,9 @@ App.WizardStep8Controller = App.WizardStepController.extend(App.AddSecurityConfi
     this.get('content.services').filterProperty('isSelected').forEach(function (service) {
       service.get('serviceComponents').filterProperty('isRequiredOnAllHosts').forEach(function (component) {
         if (service.get('isInstalled') && notInstalledHosts.length) {
-          this.registerHostsToComponent(notInstalledHosts.mapProperty('hostName'), component.get('componentName'));
+          this.registerHostsToComponent(notInstalledHosts.mapProperty('hostName'), component.componentName, component.serviceId, component.serviceGroupName);
         } else if (!service.get('isInstalled') && registeredHosts.length) {
-          this.registerHostsToComponent(registeredHosts.mapProperty('hostName'), component.get('componentName'));
+          this.registerHostsToComponent(registeredHosts.mapProperty('hostName'), component.componentName, component.serviceId, component.serviceGroupName);
         }
       }, this);
     }, this);
@@ -1383,10 +1396,11 @@ App.WizardStep8Controller = App.WizardStepController.extend(App.AddSecurityConfi
     var hiveService = this.get('content.services').filterProperty('isSelected', true).filterProperty('isInstalled', false).findProperty('serviceName', 'HIVE');
     if (hiveService) {
       var hiveDb = this.get('content.serviceConfigProperties').findProperty('name', 'hive_database');
+      const hiveService = masterHosts.filterProperty('component', 'HIVE_SERVER');
       if (hiveDb.value === "New MySQL Database") {
-        this.registerHostsToComponent(masterHosts.filterProperty('component', 'HIVE_SERVER').mapProperty('hostName'), 'MYSQL_SERVER');
+        this.registerHostsToComponent(masterHosts.filterProperty('component', 'HIVE_SERVER').mapProperty('hostName'), 'MYSQL_SERVER', 'HIVE', hiveService.serviceGroupName);
       } else if (hiveDb.value === "New PostgreSQL Database") {
-        this.registerHostsToComponent(masterHosts.filterProperty('component', 'HIVE_SERVER').mapProperty('hostName'), 'POSTGRESQL_SERVER');
+        this.registerHostsToComponent(masterHosts.filterProperty('component', 'HIVE_SERVER').mapProperty('hostName'), 'POSTGRESQL_SERVER', 'HIVE', hiveService.serviceGroupName);
       }
     }
   },
@@ -1398,28 +1412,11 @@ App.WizardStep8Controller = App.WizardStepController.extend(App.AddSecurityConfi
    * @param {String} componentName
    * @method registerHostsToComponent
    */
-  registerHostsToComponent: function (hostNames, componentName) {
+  registerHostsToComponent: function (hostNames, componentName, serviceName, serviceGroupName) {
     if (!hostNames.length) return;
 
-    let serviceName;
-    let serviceGroupName;
-
     const queryStr = `Hosts/host_name.in(${hostNames.join(',')})`;
 
-    let services;
-    if (this.get('isAddHost')) {
-      services = this.get('installedServices');
-    } else {
-      services = this.get('selectedServices');
-    }
-
-    services.forEach( function (service) {
-      if (service.get('serviceComponents').findProperty('componentName', componentName)) {
-        serviceName = service.get('serviceName');
-        serviceGroupName = service.get('stackName');
-      }
-    });
-
     var data = {
       "RequestInfo": {
         "query": queryStr
@@ -1645,53 +1642,59 @@ App.WizardStep8Controller = App.WizardStepController.extend(App.AddSecurityConfi
    * @method createNotification
    */
   createNotification: function () {
-    if (!this.get('isInstaller')) return;
-    var miscConfigs = this.get('configs').filterProperty('serviceName', 'MISC'),
-      createNotification = miscConfigs.findProperty('name', 'create_notification').value;
-    if (createNotification !== 'yes') return;
-      var predefinedNotificationConfigNames = require('data/configs/alert_notification').mapProperty('name'),
-      configsForNotification = this.get('configs').filterProperty('filename', 'alert_notification');
-    var properties = {},
-      names = [
-        'ambari.dispatch.recipients',
-        'mail.smtp.host',
-        'mail.smtp.port',
-        'mail.smtp.from',
-        'mail.smtp.starttls.enable',
-        'mail.smtp.startssl.enable'
-      ];
-    if (miscConfigs.findProperty('name', 'smtp_use_auth').value == 'true') { // yes, it's not converted to boolean
-      names.pushObjects(['ambari.dispatch.credential.username', 'ambari.dispatch.credential.password']);
-    }
+    if (this.get('isInstaller')) {
+      const miscConfigs = this.get('configs').filterProperty('serviceName', 'MISC');
+      if (miscConfigs) {
+        const createNotification = miscConfigs.findProperty('name', 'create_notification');
+        if (createNotification && createNotification.value === 'yes') {
+          const predefinedNotificationConfigNames = require('data/configs/alert_notification').mapProperty('name');
+          const configsForNotification = this.get('configs').filterProperty('filename', 'alert_notification');
+          const properties = {};
+          const names = [
+            'ambari.dispatch.recipients',
+            'mail.smtp.host',
+            'mail.smtp.port',
+            'mail.smtp.from',
+            'mail.smtp.starttls.enable',
+            'mail.smtp.startssl.enable'
+          ];
+
+          if (miscConfigs.findProperty('name', 'smtp_use_auth').value == 'true') { // yes, it's not converted to boolean
+            names.pushObjects(['ambari.dispatch.credential.username', 'ambari.dispatch.credential.password']);
+          }
 
-    names.forEach(function (name) {
-      properties[name] = miscConfigs.findProperty('name', name).value;
-    });
+          names.forEach(function (name) {
+            properties[name] = miscConfigs.findProperty('name', name).value;
+          });
 
-    properties['ambari.dispatch.recipients'] = properties['ambari.dispatch.recipients'].replace(/\s/g, '').split(',');
+          properties['ambari.dispatch.recipients'] = properties['ambari.dispatch.recipients'].replace(/\s/g, '').split(',');
 
-    configsForNotification.forEach(function (config) {
-      if (predefinedNotificationConfigNames.contains(config.name)) return;
-      properties[config.name] = config.value;
-    });
+          configsForNotification.forEach(function (config) {
+            if (predefinedNotificationConfigNames.contains(config.name)) return;
+            properties[config.name] = config.value;
+          });
 
-    var apiObject = {
-      AlertTarget: {
-        name: 'Initial Notification',
-        description: 'Notification created during cluster installing',
-        global: true,
-        notification_type: 'EMAIL',
-        alert_states: ['OK', 'WARNING', 'CRITICAL', 'UNKNOWN'],
-        properties: properties
-      }
-    };
-    this.addRequestToAjaxQueue({
-      name: 'alerts.create_alert_notification',
-      data: {
-        urlParams: 'overwrite_existing=true',
-        data: apiObject
+          var apiObject = {
+            AlertTarget: {
+              name: 'Initial Notification',
+              description: 'Notification created during cluster installing',
+              global: true,
+              notification_type: 'EMAIL',
+              alert_states: ['OK', 'WARNING', 'CRITICAL', 'UNKNOWN'],
+              properties: properties
+            }
+          };
+        
+          this.addRequestToAjaxQueue({
+            name: 'alerts.create_alert_notification',
+            data: {
+              urlParams: 'overwrite_existing=true',
+              data: apiObject
+            }
+          });
+        }
       }
-    });
+    }
   },
 
   /**
diff --git a/ambari-web/app/controllers/wizard/step9_controller.js b/ambari-web/app/controllers/wizard/step9_controller.js
index 6e87ad6..99455e4 100644
--- a/ambari-web/app/controllers/wizard/step9_controller.js
+++ b/ambari-web/app/controllers/wizard/step9_controller.js
@@ -508,7 +508,6 @@ App.WizardStep9Controller = App.WizardStepController.extend(App.ReloadPopupMixin
           success: 'launchStartServicesSuccessCallback',
           error: 'launchStartServicesErrorCallback'
         }).then(callback, callback);
-        break;
       case 'addServiceController':
         var servicesList = this.get('content.services').filterProperty('isSelected').filterProperty('isInstalled', false).mapProperty('serviceName');
         if (servicesList.contains('OOZIE')) {
@@ -520,21 +519,13 @@ App.WizardStep9Controller = App.WizardStepController.extend(App.ReloadPopupMixin
           "urlParams": "ServiceInfo/state=INSTALLED&ServiceInfo/service_name.in(" + servicesList.join(",") + ")&params/run_smoke_test=true&params/reconfigure_client=false"
         };
 
-        serviceGroups = this.get('content.serviceGroups');
-        promises = serviceGroups.map(sg => {
-          data.serviceGroupName = sg;
-
-          return App.ajax.send({
-            name: 'common.services.update', //TODO: This should change to use common.services.update.all when that is implemented on the back end.
-            sender: this,
-            data: data,
-            success: 'launchStartServicesSuccessCallback',
-            error: 'launchStartServicesErrorCallback'
-          })
-        })
-
-        return $.when(...promises).then(callback, callback);
-        break;
+        return App.ajax.send({
+          name: 'common.services.update.all',
+          sender: this,
+          data: data,
+          success: 'launchStartServicesSuccessCallback',
+          error: 'launchStartServicesErrorCallback'
+        }).then(callback, callback);
       default:
         data = {
           "context": Em.I18n.t("requestInfo.startServices"),
@@ -542,20 +533,13 @@ App.WizardStep9Controller = App.WizardStepController.extend(App.ReloadPopupMixin
           "urlParams": "ServiceInfo/state=INSTALLED&params/run_smoke_test=" + !this.get('skipServiceChecks') + "&params/reconfigure_client=false"
         };
 
-        serviceGroups = this.get('content.serviceGroups');
-        promises = serviceGroups.map(sg => {
-          data.serviceGroupName = sg;
-
-          return App.ajax.send({
-            name: 'common.services.update', //TODO: This should change to use common.services.update.all when that is implemented on the back end.
-            sender: this,
-            data: data,
-            success: 'launchStartServicesSuccessCallback',
-            error: 'launchStartServicesErrorCallback'
-          })
-        })
-
-        return $.when(...promises).then(callback, callback);
+        return App.ajax.send({
+          name: 'common.services.update.all',
+          sender: this,
+          data: data,
+          success: 'launchStartServicesSuccessCallback',
+          error: 'launchStartServicesErrorCallback'
+        }).then(callback, callback);
     }
 
     if (App.get('testMode')) {
diff --git a/ambari-web/app/mappers/configs/stack_config_properties_mapper.js b/ambari-web/app/mappers/configs/stack_config_properties_mapper.js
index e9f2a4b..36a93f3 100644
--- a/ambari-web/app/mappers/configs/stack_config_properties_mapper.js
+++ b/ambari-web/app/mappers/configs/stack_config_properties_mapper.js
@@ -127,7 +127,7 @@ App.stackConfigPropertiesMapper = App.QuickDataMapper.create({
                 type : dep.StackConfigurationDependency.dependency_type,
                 name : dep.StackConfigurationDependency.dependency_name
               });
-              var service = App.StackService.find(config.StackConfigurations.service_name);
+              var service = App.StackService.find().findProperty('serviceName', config.StackConfigurations.service_name);
               var dependentService = App.config.get('serviceByConfigTypeMap')[dep.StackConfigurationDependency.dependency_type];
               if (dependentService && service && dependentService.get('serviceName') != service.get('serviceName') && !service.get('dependentServiceNames').contains(dependentService.get('serviceName'))) {
                 service.set('dependentServiceNames', service.get('dependentServiceNames').concat(dependentService.get('serviceName')));
@@ -136,18 +136,14 @@ App.stackConfigPropertiesMapper = App.QuickDataMapper.create({
           }
           if (Em.get(config, 'StackConfigurations.property_depends_on.length') > 0) {
             config.StackConfigurations.property_depends_on.forEach(function(dep) {
-              var service = App.StackService.find(config.StackConfigurations.service_name);
+              var service = App.StackService.find().findProperty('serviceName', config.StackConfigurations.service_name);
               var dependentService = App.config.get('serviceByConfigTypeMap')[dep.type];
               if (dependentService && service && dependentService.get('serviceName') != service.get('serviceName') && !service.get('dependentServiceNames').contains(dependentService.get('serviceName'))) {
                 service.set('dependentServiceNames', service.get('dependentServiceNames').concat(dependentService.get('serviceName')));
               }
             });
           }
-          /**
-           * merging stack info with that is stored on UI
-           * for now is not used; uncomment in will be needed
-           * this.mergeWithUI(config);
-           */
+
           if (this.isMiscService(config.StackConfigurations.property_type)) {
             this.handleSpecialProperties(config);
           } else {
@@ -224,17 +220,18 @@ App.stackConfigPropertiesMapper = App.QuickDataMapper.create({
   },
 
   /**
-   * defines if property should refer to MISC tab
-   * @param type
+   * Returns true if property type should be in the MISC category and appear on the Misc tab in the UI.
+   * 
+   * @param type property type to check
    * @returns {Boolean}
    */
   isMiscService: function(type) {
-    return type.length &&
-      (type.contains('USER')
-      || type.contains('GROUP')
-      || type.contains('ADDITIONAL_USER_PROPERTY')
-      || type.contains('UID')
-      || type.contains('GID'));
+    // return type.length &&
+    //   (type.contains('USER')
+    //   || type.contains('GROUP')
+    //   || type.contains('ADDITIONAL_USER_PROPERTY')
+    //   || type.contains('UID')
+    //   || type.contains('GID'));
   },
 
   /**
diff --git a/ambari-web/app/mappers/mpack_service_mapper.js b/ambari-web/app/mappers/mpack_service_mapper.js
index 72cffa3..3c02e9b 100644
--- a/ambari-web/app/mappers/mpack_service_mapper.js
+++ b/ambari-web/app/mappers/mpack_service_mapper.js
@@ -22,7 +22,7 @@ App.MpackServiceMapper = App.QuickDataMapper.create({
   component_model: App.StackServiceComponent,
 
   config: {
-    id: 'service_name',
+    id: 'id',
     stack_id: 'stack_id',
     service_name: 'service_name',
     service_type: 'service_type',
@@ -79,7 +79,6 @@ App.MpackServiceMapper = App.QuickDataMapper.create({
     var result = [];
     var stackServiceComponents = [];
     var nonInstallableServices = ['KERBEROS'];
-    var displayOrderLength = App.StackService.displayOrder.length;
     var stackService = service.StackServices;
     var serviceComponents = [];
     service.components.forEach(function (serviceComponent) {
@@ -95,7 +94,8 @@ App.MpackServiceMapper = App.QuickDataMapper.create({
       }
       stackServiceComponents.push(parsedResult);
     }, this);
-    stackService.stack_id = stackService.stack_name + '-' + stackService.stack_version;
+    stackService.stack_id = `${stackService.stack_name}-${stackService.stack_version}`;
+    stackService.id = `${stackService.service_name}-${stackService.stack_id}`;
     stackService.service_components = serviceComponents;
     stackService.is_service_with_widgets = service.artifacts.someProperty('Artifacts.artifact_name', 'widgets_descriptor');
     // @todo: replace with server response value after API implementation
diff --git a/ambari-web/app/mappers/service_mapper.js b/ambari-web/app/mappers/service_mapper.js
index 99d8adb..6176505 100644
--- a/ambari-web/app/mappers/service_mapper.js
+++ b/ambari-web/app/mappers/service_mapper.js
@@ -21,10 +21,13 @@ var misc = require('utils/misc');
 App.serviceMapper = App.QuickDataMapper.create({
   model: App.Service,
   config: {
-    id: 'ServiceInfo.service_name',
+    id: 'ServiceInfo.id',
     service_name: 'ServiceInfo.service_name',
     service_group_name: 'ServiceInfo.service_group_name',
-    work_status: 'ServiceInfo.state'
+    work_status: 'ServiceInfo.state',
+    mpack_name: 'ServiceInfo.mpack_name',
+    mpack_version: 'ServiceInfo.mpack_version',
+    tool_tip_content: 'ServiceInfo.tool_tip_content'
   },
   initialAppLoad: false,
   passiveStateMap: {},
@@ -33,8 +36,15 @@ App.serviceMapper = App.QuickDataMapper.create({
     var self = this;
     var passiveStateMap = this.get('passiveStateMap');
     var services = [];
+
     json.items.forEach(function (item) {
-      services = services.concat(item.services);
+      const itemServices = item.services.map(service => {
+        service.ServiceInfo.mpack_name = item.ServiceGroupInfo.mpack_name;
+        service.ServiceInfo.mpack_version = item.ServiceGroupInfo.mpack_version;
+        return service;
+      });
+
+      services = services.concat(itemServices);
     });
 
     services.forEach(function (service) {
@@ -47,9 +57,13 @@ App.serviceMapper = App.QuickDataMapper.create({
         } else {
           var serviceData = {
             ServiceInfo: {
+              id: `${service.ServiceInfo.service_name}-${service.ServiceInfo.service_group_name}`,
               service_name: service.ServiceInfo.service_name,
               service_group_name: service.ServiceInfo.service_group_name,
-              state: service.ServiceInfo.state
+              state: service.ServiceInfo.state,
+              mpack_name: service.ServiceInfo.mpack_name,
+              mpack_version: service.ServiceInfo.mpack_version,
+              tool_tip_content: `${service.ServiceInfo.service_name} (${service.ServiceInfo.service_group_name})`
             },
             host_components: [],
             components: []
@@ -65,7 +79,7 @@ App.serviceMapper = App.QuickDataMapper.create({
         App.serviceMetricsMapper.mapExtendedModel(item);
         return self.parseIt(item, self.get('config'));
       });
-      parsedCacheServices = misc.sortByOrder(App.StackService.find().mapProperty('serviceName'), parsedCacheServices);
+      parsedCacheServices = misc.sortByOrder(App.StackService.find().mapProperty('serviceName'), parsedCacheServices, item => item.service_name);
       App.store.safeLoadMany(this.get('model'), parsedCacheServices);
       this.set('initialAppLoad', true);
     }
diff --git a/ambari-web/app/mappers/stack_service_mapper.js b/ambari-web/app/mappers/stack_service_mapper.js
index a33bf65..7d4c9f7 100644
--- a/ambari-web/app/mappers/stack_service_mapper.js
+++ b/ambari-web/app/mappers/stack_service_mapper.js
@@ -22,7 +22,7 @@ App.stackServiceMapper = App.QuickDataMapper.create({
   component_model: App.StackServiceComponent,
 
   config: {
-    id: 'service_name',
+    id: 'id',
     stack_id: 'stack_id',
     service_name: 'service_name',
     service_type: 'service_type',
@@ -119,7 +119,8 @@ App.stackServiceMapper = App.QuickDataMapper.create({
         }
         stackServiceComponents.push(parsedResult);
       }, this);
-      stackService.stack_id = stackService.stack_name + '-' + stackService.stack_version;
+      stackService.stack_id = `${stackService.stack_name}-${stackService.stack_version}`;
+      stackService.id = `${stackService.service_name}-${stackService.stack_id}`;
       stackService.service_components = serviceComponents;
       stackService.is_service_with_widgets = item.artifacts.someProperty('Artifacts.artifact_name', 'widgets_descriptor');
       // @todo: replace with server response value after API implementation
diff --git a/ambari-web/app/mixins/common/blueprint.js b/ambari-web/app/mixins/common/blueprint.js
index 3df3b1a..cbc633d 100644
--- a/ambari-web/app/mixins/common/blueprint.js
+++ b/ambari-web/app/mixins/common/blueprint.js
@@ -44,7 +44,11 @@ App.BlueprintMixin = Em.Mixin.create({
       res.blueprint.host_groups.push({
         name: group_name,
         components: mappedComponents[host] ? mappedComponents[host].map(function (c) {
-          return { name: Em.get(c, 'componentName') };
+          return {
+            mpack_instance: Em.get(c, 'mpackInstance'),
+            service_instance: Em.get(c, 'serviceInstance'),
+            name: Em.get(c, 'componentName')
+          };
         }) : []
       });
 
diff --git a/ambari-web/app/mixins/common/configs/configs_saver.js b/ambari-web/app/mixins/common/configs/configs_saver.js
index c700c16..0deac16 100644
--- a/ambari-web/app/mixins/common/configs/configs_saver.js
+++ b/ambari-web/app/mixins/common/configs/configs_saver.js
@@ -75,7 +75,7 @@ App.ConfigsSaverMixin = Em.Mixin.create({
    * @type {App.StackService[]}
    */
   currentServices: function() {
-    return [App.StackService.find(this.get('content.serviceName'))];
+    return [App.StackService.find().findProperty('serviceName', this.get('content.serviceName'))];
   }.property('content.serviceName'),
 
   /**
@@ -327,7 +327,7 @@ App.ConfigsSaverMixin = Em.Mixin.create({
 
     //generates list of properties that was changed
     var modifiedConfigs = this.getModifiedConfigs(configs);
-    var serviceFileNames = Object.keys(App.StackService.find(serviceName).get('configTypes')).map(function (type) {
+    var serviceFileNames = Object.keys(App.StackService.find().findProperty('serviceName', serviceName).get('configTypes')).map(function (type) {
       return App.config.getOriginalFileName(type);
     });
 
@@ -439,7 +439,7 @@ App.ConfigsSaverMixin = Em.Mixin.create({
    *
    * @returns {boolean}
    */
-  allowSaveCoreSite: function() {
+  allowSaveCoreSite: function () {
     return this.get('currentServices').some(function(service) {
       return (this.get('coreSiteServiceNames').contains(service.get('serviceName'))
         || this.get('coreSiteServiceType') === service.get('serviceType'));
diff --git a/ambari-web/app/mixins/common/configs/enhanced_configs.js b/ambari-web/app/mixins/common/configs/enhanced_configs.js
index 92d1012..0f22d6c 100644
--- a/ambari-web/app/mixins/common/configs/enhanced_configs.js
+++ b/ambari-web/app/mixins/common/configs/enhanced_configs.js
@@ -219,7 +219,7 @@ App.EnhancedConfigsMixin = Em.Mixin.create(App.ConfigWithOverrideRecommendationP
       if (requiredTags.length) {
         this.loadAdditionalSites(requiredTags, stepConfigs, recommendations, dataToSend, onComplete);
       } else {
-        this.addRecommendationRequestParams(recommendations, dataToSend, stepConfigs);
+        dataToSend.recommendations = this.addRequestedConfigs(recommendations, stepConfigs);
         return this.getRecommendationsRequest(dataToSend, onComplete);
       }
     } else {
@@ -231,14 +231,22 @@ App.EnhancedConfigsMixin = Em.Mixin.create(App.ConfigWithOverrideRecommendationP
   },
 
   /**
-   *
+   * Adds the configs to include in the request to the recommendations.blueprint object in the format required.
+   * 
    * @param recommendations
-   * @param dataToSend
-   * @param stepConfigs
+   * @param configs
    */
-  addRecommendationRequestParams: function(recommendations, dataToSend, stepConfigs) {
-    recommendations.blueprint.configurations = blueprintUtils.buildConfigsJSON(stepConfigs);
-    dataToSend.recommendations = recommendations;
+  addRequestedConfigs: function (recommendations, configs) {
+    const wizardController = this.get('wizardController');
+
+    if (wizardController) {
+      recommendations.blueprint.configurations = wizardController.getConfigsForServiceInstance('MISC', null, null, configs);
+      recommendations.blueprint.mpack_instances = wizardController.getMpackInstances(configs);
+    } else {
+      App.get('mpackInstances'); //TODO: implement this property on the App object along with a routine to populate it at startup, similar to App.allHostNames
+    }
+
+    return recommendations;
   },
 
   /**
@@ -253,7 +261,7 @@ App.EnhancedConfigsMixin = Em.Mixin.create(App.ConfigWithOverrideRecommendationP
     App.config.getConfigsByTypes(sites).done(function (configs) {
       stepConfigs = stepConfigs.concat(configs);
 
-      self.addRecommendationRequestParams(recommendations, dataToSend, stepConfigs);
+      dataToSend.recommendations = self.addRequestedConfigs(recommendations, stepConfigs);
       self.getRecommendationsRequest(dataToSend, onComplete);
     });
   },
@@ -282,37 +290,24 @@ App.EnhancedConfigsMixin = Em.Mixin.create(App.ConfigWithOverrideRecommendationP
     const params = {
       recommend: updateDependencies ? 'configuration-dependencies' : 'configurations',
       hosts: this.get('hostNames'),
-      services: this.get('serviceNames'),
       changed_configurations: updateDependencies ? changedConfigs : undefined
     };
 
-    //TODO - mpacks: Hard coded to use first mpack. Change when we are installing multiple mpacks.
-    const selectedMpacks = this.get('content.selectedMpacks');
-
-    if (selectedMpacks) {
-      params.stackName = selectedMpacks[0].name;
-      params.stackVersion = selectedMpacks[0].version;
-    }
-
     return params;
   },
 
   getRecommendationsRequest: function (dataToSend, callback) {
     const self = this;
     this.set('recommendationsInProgress', true);
-    const stackVersionUrl = App.getStackVersionUrl(dataToSend.stackName, dataToSend.stackVersion) || App.get('stackVersionURL');
     
     return App.ajax.send({
-      name: 'config.recommendations',
+      name: 'mpack.advisor.recommendations',
       sender: self,
       data: {
-        stackVersionUrl: stackVersionUrl,
-        dataToSend: {
+        data: {
           recommend: dataToSend.recommend,
           hosts: dataToSend.hosts,
-          services: dataToSend.services,
           changed_configurations: dataToSend.changed_configurations,
-          user_context: dataToSend.user_context,
           recommendations: dataToSend.recommendations
         }
       },
@@ -402,7 +397,7 @@ App.EnhancedConfigsMixin = Em.Mixin.create(App.ConfigWithOverrideRecommendationP
    * @method dependenciesSuccess
    */
   loadRecommendationsSuccess: function (data, opt, params) {
-    this._saveRecommendedValues(data, params.dataToSend.changed_configurations);
+    this._saveRecommendedValues(data, params.data.changed_configurations);
     if (this.isConfigHasInitialState()) {
       /** clearing all recommendations info **/
       this.undoRedoRecommended(this.get('recommendations'), false);
@@ -445,12 +440,11 @@ App.EnhancedConfigsMixin = Em.Mixin.create(App.ConfigWithOverrideRecommendationP
    * @private
    */
   _saveRecommendedValues: function(data, changedConfigs) {
-    Em.assert('invalid data - `data.resources[0].recommendations.blueprint.configurations` not defined ', data && data.resources[0] && Em.get(data.resources[0], 'recommendations.blueprint.configurations'));
     var recommendations = data.resources[0].recommendations;
     if (recommendations['config-groups'] && this.get('selectedConfigGroup') && !this.get('selectedConfigGroup.isDefault')) {
       this.saveConfigGroupsRecommendations(recommendations, changedConfigs);
     } else {
-      var configObject = recommendations.blueprint.configurations;
+      var configObject = this.getAllRecommendedConfigs(recommendations);
       this.get('stepConfigs').forEach(function(stepConfig) {
         this.updateConfigsByRecommendations(configObject, stepConfig.get('configs'), changedConfigs);
       }, this);
@@ -459,6 +453,12 @@ App.EnhancedConfigsMixin = Em.Mixin.create(App.ConfigWithOverrideRecommendationP
     this.cleanUpRecommendations();
   },
 
+  getAllRecommendedConfigs: function (recommendations) {
+    const serviceInstances = recommendations.blueprint.mpack_instances.reduce((result, value) => result.concat(value.service_instances), []);
+    const configs = serviceInstances.reduce((result, value) => Object.assign(result, value.configurations), {});
+    return configs;
+  },
+
   /**
    *
    * @param {object} recommendations
diff --git a/ambari-web/app/mixins/common/hosts/host_component_recommendation_mixin.js b/ambari-web/app/mixins/common/hosts/host_component_recommendation_mixin.js
index e0cbb3f..1d151a4 100644
--- a/ambari-web/app/mixins/common/hosts/host_component_recommendation_mixin.js
+++ b/ambari-web/app/mixins/common/hosts/host_component_recommendation_mixin.js
@@ -21,26 +21,29 @@ require('mixins/common/blueprint');
 var App = require('app');
 
 /**
- * @typedef {object} RecommendComponentObject
- * @property {string} componentName name of the component
- * @property {number} [size=0] desired components size
- * @property {string[]} [hosts=[]] hosts assigned to component
+ * @typedef {object} ServiceInstanceObject
+ * @property {string} name name of the service instance
+ * @property {string} type of the service instance (usually the name of the service, i.e. ZOOKEEPER)
+ */
+
+/**
+ * @typedef {object} MpackInstanceObject
+ * @property {string} name name of the mpack instances (usually the name of a service group)
+ * @property {string} type of the mpack instance (usually the name of the mpack, i.e. HDPCORE)
+ * @property {string} version of the mpack
+ * @property {ServiceInstanceObject[]} service_instances list of service instances
  */
 
 /**
  * @typedef {object} HostComponentRecommendationOptions
  * @property {string[]} hosts list of host names, in most cases all available host names
- * @property {RecommendComponentObject[]} components list of components
- * @property {string[]} services list of service names
- * @property {object} [blueprint=null] when null blueprint will be created by <code>HostComponentRecommendationOptions.components</code> attribute
+ * @property {MpackInstanceObject[]} mpack_instances list of mpack instances
  */
 
 /**
  * @typedef {object} HostRecommendationRequestData
- * @property {string} stackVersionUrl stack version url
- * @property {string[]} hosts host names
- * @property {string[]} services service names
  * @property {string} recommend recommendation type e.g. 'host_groups'
+ * @property {string[]} hosts list of host names
  * @property {object} recommendations blueprint object
  */
 
@@ -58,7 +61,6 @@ App.HostComponentRecommendationMixin = Em.Mixin.create(App.BlueprintMixin, {
    */
   getRecommendedHosts: function(options) {
     var opts = $.extend({
-      services: [],
       hosts: [],
       components: [],
       blueprint: null
@@ -77,11 +79,12 @@ App.HostComponentRecommendationMixin = Em.Mixin.create(App.BlueprintMixin, {
     var res = [];
     if (!components) return [];
     components.forEach(function(component) {
-      var componentName = Em.get(component, 'componentName');
       if (Em.get(component, 'hosts.length')) {
         Em.get(component, 'hosts').forEach(function(hostName) {
           res.push(Em.Object.create({
-            componentName: componentName,
+            componentName: Em.get(component, 'componentName'),
+            mpackInstance: Em.get(component, 'mpackInstance'),
+            serviceInstance: Em.get(component, 'serviceInstance'),
             hostName: hostName
           }));
         });
@@ -97,17 +100,17 @@ App.HostComponentRecommendationMixin = Em.Mixin.create(App.BlueprintMixin, {
    * @method getRecommendationRequestData
    */
   getRecommendationRequestData: function(options) {
-    const stackVersionUrl = App.getStackVersionUrl(options.stackName, options.stackVersion) || App.get('stackVersionURL');
-
-    return {
-      stackVersionUrl: stackVersionUrl,
-      dataToSend: {
+    const requestData = {
+      data: {
         recommend: 'host_groups',
         hosts: options.hosts,
-        services: options.services,
         recommendations: options.blueprint || this.getComponentsBlueprint(options.components)
       }
-    };
+    }
+
+    requestData.data.recommendations.blueprint.mpack_instances = options.mpack_instances;
+
+    return requestData;
   },
 
   /**
@@ -118,7 +121,7 @@ App.HostComponentRecommendationMixin = Em.Mixin.create(App.BlueprintMixin, {
    */
   loadComponentsRecommendationsFromServer: function(recommendationData) {
     return App.ajax.send({
-      name: 'config.recommendations',
+      name: 'mpack.advisor.recommendations',
       sender: this,
       data: recommendationData,
       success: 'loadRecommendationsSuccessCallback',
@@ -126,6 +129,7 @@ App.HostComponentRecommendationMixin = Em.Mixin.create(App.BlueprintMixin, {
     });
   },
 
+  //these can be overridden in the derived object
   loadRecommendationsSuccessCallback: function() {},
   loadRecommendationsErrorCallback: function() {}
 });
diff --git a/ambari-web/app/mixins/common/hosts/host_component_validation_mixin.js b/ambari-web/app/mixins/common/hosts/host_component_validation_mixin.js
index a7e752c..ee7fb84 100644
--- a/ambari-web/app/mixins/common/hosts/host_component_validation_mixin.js
+++ b/ambari-web/app/mixins/common/hosts/host_component_validation_mixin.js
@@ -21,12 +21,23 @@ require('mixins/common/blueprint');
 var App = require('app');
 
 /**
+ * @typedef {object} ServiceInstanceObject
+ * @property {string} name name of the service instance
+ * @property {string} type of the service instance (usually the name of the service, i.e. ZOOKEEPER)
+ */
+
+/**
+ * @typedef {object} MpackInstanceObject
+ * @property {string} name name of the mpack instances (usually the name of a service group)
+ * @property {string} type of the mpack instance (usually the name of the mpack, i.e. HDPCORE)
+ * @property {string} version of the mpack
+ * @property {ServiceInstanceObject[]} service_instances list of service instances
+ */
+
+/**
  * @typedef {object} HostValidationRequestData
- * @property {string} stackVersionUrl stack version url
  * @property {string[]} hosts host names
- * @property {string[]} services service names
- * @property {string} validate validation type e.g. 'host_groups'
- * @property {object} recommendations blueprint object
+ * @property {MpackInstanceObject[]} mpack_instances list of mpack instances
  */
 
 App.HostComponentValidationMixin = Em.Mixin.create(App.BlueprintMixin, {
@@ -38,7 +49,6 @@ App.HostComponentValidationMixin = Em.Mixin.create(App.BlueprintMixin, {
    */
   validateSelectedHostComponents: function(options) {
     var opts = $.extend({
-      services: [],
       blueprint: null,
       hosts: [],
       components: []
@@ -57,11 +67,12 @@ App.HostComponentValidationMixin = Em.Mixin.create(App.BlueprintMixin, {
     var res = [];
     if (!components) return [];
     components.forEach(function(component) {
-      var componentName = Em.get(component, 'componentName');
       if (Em.get(component, 'hosts.length')) {
         Em.get(component, 'hosts').forEach(function(hostName) {
           res.push(Em.Object.create({
-            componentName: componentName,
+            componentName: Em.get(component, 'componentName'),
+            mpackInstance: Em.get(component, 'mpackInstance'),
+            serviceInstance: Em.get(component, 'serviceInstance'),
             hostName: hostName
           }));
         });
@@ -76,15 +87,17 @@ App.HostComponentValidationMixin = Em.Mixin.create(App.BlueprintMixin, {
    * @return {HostValidationRequestData}
    */
   getHostComponentValidationParams: function(options) {
-    const stackVersionUrl = App.getStackVersionUrl(options.stackName, options.stackVersion) || App.get('stackVersionURL');
-
-    return {
-      stackVersionUrl: stackVersionUrl,
-      hosts: options.hosts,
-      services: options.services,
-      validate: 'host_groups',
-      recommendations: options.blueprint || this.getComponentsBlueprint(options.components)
+    const requestData = {
+      data: {
+        validate: 'host_groups',
+        hosts: options.hosts,
+        recommendations: options.blueprint || this.getComponentsBlueprint(options.components)
+      }
     };
+
+    requestData.data.recommendations.blueprint.mpack_instances = options.mpack_instances;
+
+    return requestData;
   },
 
   /**
@@ -95,7 +108,7 @@ App.HostComponentValidationMixin = Em.Mixin.create(App.BlueprintMixin, {
    */
   getHostComponentValidationRequest: function(validationData) {
     return App.ajax.send({
-      name: 'config.validations',
+      name: 'mpack.advisor.validations',
       sender: this,
       data: validationData,
       success: 'updateValidationsSuccessCallback',
@@ -103,6 +116,7 @@ App.HostComponentValidationMixin = Em.Mixin.create(App.BlueprintMixin, {
     });
   },
 
+  //these can be overridden in the derived object
   updateValidationsSuccessCallback: function() {},
   updateValidationsErrorCallback: function() {}
 });
diff --git a/ambari-web/app/mixins/common/serverValidator.js b/ambari-web/app/mixins/common/serverValidator.js
index 4b40bb1..b8e069a 100644
--- a/ambari-web/app/mixins/common/serverValidator.js
+++ b/ambari-web/app/mixins/common/serverValidator.js
@@ -114,8 +114,21 @@ App.ServerValidatorMixin = Em.Mixin.create({
    * @type {Array} of strings (hostNames)
    */
   hostGroups: function() {
-    return this.get('content.recommendationsHostGroups') || blueprintUtils.generateHostGroups(App.get('allHostNames'));
-  }.property('content.recommendationsHostGroups', 'App.allHostNames', 'App.componentToBeAdded', 'App.componentToBeDeleted'),
+    const hostGroups = this.get('content.recommendationsHostGroups')
+      || this.get('content.recommendations')
+      || blueprintUtils.generateHostGroups(App.get('allHostNames'));
+    
+    return hostGroups;
+  }.property('content.recommendationsHostGroups', 'content.recommendations', 'App.allHostNames', 'App.componentToBeAdded', 'App.componentToBeDeleted'),
+
+  getMpackInstances(configs) {
+    if (this.get('isWizard')) {
+      const wizardController = this.get('wizardController');
+      return wizardController.getMpackInstances(configs);
+    } else {
+      App.get('mpackInstances'); //TODO: implement this property on the App object along with a routine to populate it at startup, similar to App.allHostNames
+    }
+  },
 
   /**
    * controller that is child of this mixin has to contain stepConfigs
@@ -133,8 +146,7 @@ App.ServerValidatorMixin = Em.Mixin.create({
       criticalIssues: []
     }));
 
-    const mpacks = this.get('content.selectedMpacks'); //TODO - mpacks
-    this.runServerSideValidation(mpacks[0].name, mpacks[0].version).done(function() {
+    this.runServerSideValidation().done(function() {
       if (self.get('configErrorList.issues.length') || self.get('configErrorList.criticalIssues.length')) {
         App.showConfigValidationPopup(self.get('configErrorList'), primary, secondary, self);
       } else {
@@ -152,25 +164,17 @@ App.ServerValidatorMixin = Em.Mixin.create({
    * send request to validate configs
    * @returns {*}
    */
-  runServerSideValidation: function (stackName, stackVersion) {
-    var self = this;
-    var recommendations = this.get('hostGroups');
-    var stepConfigs = this.get('stepConfigs');
-    var dfd = $.Deferred();
-
-    this.getBlueprintConfigurations(this.get('stepConfigs'))
-      .done(function(blueprintConfigurations) {
-        recommendations.blueprint.configurations = blueprintConfigurations;
-        var request = self.validateSelectedConfigs({
-          hosts: self.get('hostNames'),
-          services: self.get('serviceNames'),
-          blueprint: recommendations,
-          stackName: stackName,
-          stackVersion: stackVersion
-        });
-        self.set('validationRequest', request);
-        request.done(dfd.resolve).fail(dfd.reject);
-      });
+  runServerSideValidation: function () {
+    const dfd = $.Deferred();
+
+    const request = this.validateSelectedConfigs({
+      hosts: this.get('hostNames'),
+      blueprint: this.get('hostGroups')
+    });
+
+    this.set('validationRequest', request);
+    request.done(dfd.resolve).fail(dfd.reject);
+
     return dfd.promise();
   },
 
@@ -182,7 +186,6 @@ App.ServerValidatorMixin = Em.Mixin.create({
    */
   validateSelectedConfigs: function(options) {
     var opts = $.extend({
-      services: [],
       hosts: [],
       blueprint: null
     }, options || {});
@@ -197,7 +200,7 @@ App.ServerValidatorMixin = Em.Mixin.create({
    */
   getServiceConfigsValidationRequest: function(validationData) {
     return App.ajax.send({
-      name: 'config.validations',
+      name: 'mpack.advisor.validations',
       sender: this,
       data: validationData,
       success: 'validationSuccess',
@@ -211,36 +214,16 @@ App.ServerValidatorMixin = Em.Mixin.create({
    * @returns {ConfigsValidationRequestData}
    */
   getServiceConfigsValidationParams: function(options) {
-    const stackVersionUrl = App.getStackVersionUrl(options.stackName, options.stackVersion) || App.get('stackVersionURL');
-
     return {
-      stackVersionUrl: stackVersionUrl,
-      hosts: options.hosts,
-      services: options.services,
-      validate: 'configurations',
-      recommendations: options.blueprint
+      data: {
+        validate: 'configurations',
+        hosts: options.hosts,
+        recommendations: options.blueprint
+      }
     };
   },
 
   /**
-   * Return JSON for blueprint configurations
-   * @param {App.ServiceConfigs[]} serviceConfigs
-   * @returns {*}
-   */
-  getBlueprintConfigurations: function (serviceConfigs) {
-    var dfd = $.Deferred();
-    // check if we have configs from 'cluster-env', if not, then load them, as they are mandatory for validation request
-    if (!serviceConfigs.findProperty('serviceName', 'MISC')) {
-      App.config.getConfigsByTypes([{site: 'cluster-env', serviceName: 'MISC'}]).done(function(configs) {
-        dfd.resolve(blueprintUtils.buildConfigsJSON(serviceConfigs.concat(configs)));
-      });
-    } else {
-      dfd.resolve(blueprintUtils.buildConfigsJSON(serviceConfigs));
-    }
-    return dfd.promise();
-  },
-
-  /**
    * Creates config validation error object
    *
    * @param type - error type, see <code>errorTypes<code>
@@ -384,14 +367,12 @@ App.ServerValidatorMixin = Em.Mixin.create({
   valueObserver: function () {
     var self = this;
     if (this.get('isInstallWizard') && this.get('currentTabName') === 'all-configurations') {
-      const mpacks = this.get('content.selectedMpacks'); //TODO - mpacks
-
       if (this.get('requestTimer')) clearTimeout(this.get('requestTimer'));
       self.set('requestTimer', setTimeout(function () {
         if (self.get('validationRequest')) {
           self.get('validationRequest').abort();
         }
-        self.runServerSideValidation(mpacks[0].name, mpacks[0].version).done(function () {
+        self.runServerSideValidation().done(function () {
           self.set('validationRequest', null);
           self.set('requestTimer', 0);
         });
diff --git a/ambari-web/app/mixins/wizard/assign_master_components.js b/ambari-web/app/mixins/wizard/assign_master_components.js
index d0b4bd9..69b7e2c 100644
--- a/ambari-web/app/mixins/wizard/assign_master_components.js
+++ b/ambari-web/app/mixins/wizard/assign_master_components.js
@@ -465,23 +465,13 @@ App.AssignMasterComponents = Em.Mixin.create(App.HostComponentValidationMixin, A
    */
   getRecommendationRequestData: function(options) {
     var res = this._super(options);
-    res.dataToSend.services = this.getCurrentServiceNames();
     if (!this.get('isInstallerWizard')) {
-      res.dataToSend.recommendations = this.getCurrentMasterSlaveBlueprint();
+      res.data.recommendations = this.getCurrentMasterSlaveBlueprint();
     }
     return res;
   },
 
   /**
-   * @override App.HostComponentRecommendationMixin
-   */
-  getHostComponentValidationParams: function(options) {
-    var res = this._super(options);
-    res.services = this.getCurrentServiceNames();
-    return res;
-  },
-
-  /**
    * Returns selected and installed service names
    * @return {string[]}
    */
@@ -530,12 +520,9 @@ App.AssignMasterComponents = Em.Mixin.create(App.HostComponentValidationMixin, A
         self.set('backFromNextStep', true);
       }
       
-      //TODO - mpacks: Hard-coding to only ask for recommendations for first mpack. Need to change this when we are installing multiple mpacks.
-      const selectedMpacks = self.get('content.selectedMpacks');
       self.getRecommendedHosts({
-        stackName: selectedMpacks[0].name,
-        stackVersion: selectedMpacks[0].version,
-        hosts: self.getHosts()
+        hosts: self.getHosts(),
+        mpack_instances: self.get('wizardController').getMpackInstances()
       }).then(function () {
         self.loadStepCallback(self.createComponentInstallationObjects(), self);
       });
@@ -711,7 +698,11 @@ App.AssignMasterComponents = Em.Mixin.create(App.HostComponentValidationMixin, A
         host_group.components.forEach(function(component) {
           var willBeDisplayed = true;
           var stackMasterComponent = stackMasterComponentsMap[component.name];
+          
           if (stackMasterComponent) {
+            stackMasterComponent.mpackInstance = component.mpack_instance;
+            stackMasterComponent.serviceInstance = component.service_instance;
+            
             var isMasterCreateOnConfig = this.get('mastersToCreate').contains(component.name);
             // If service is already installed and not being added as a new service then render on UI only those master components
             // that have already installed hostComponents.
@@ -757,6 +748,8 @@ App.AssignMasterComponents = Em.Mixin.create(App.HostComponentValidationMixin, A
     componentObj.component_name = componentName;
     componentObj.display_name = App.format.role(fullComponent.get('componentName'), false);
     componentObj.serviceId = fullComponent.get('serviceName');
+    componentObj.serviceInstance = fullComponent.serviceInstance;
+    componentObj.mpackInstance = fullComponent.mpackInstance;
     componentObj.isServiceCoHost = App.StackServiceComponent.find().findProperty('componentName', componentName).get('isCoHostedComponent') && !this.get('mastersToMove').contains(componentName);
     componentObj.selectedHost = savedComponent ? savedComponent.hostName : hostName;
     componentObj.isInstalled = savedComponent ? savedComponent.isInstalled || (this.get('markSavedComponentsAsInstalled') && !this.get('mastersToCreate').contains(fullComponent.get('componentName'))) : false;
@@ -818,7 +811,6 @@ App.AssignMasterComponents = Em.Mixin.create(App.HostComponentValidationMixin, A
   renderComponents: function (masterComponents) {
     var installedServices = App.StackService.find().filterProperty('isSelected').filterProperty('isInstalled', false).mapProperty('serviceName'); //list of shown services
     var result = [];
-    var serviceComponentId, previousComponentName;
 
     this.addNewMasters(masterComponents);
 
@@ -829,7 +821,6 @@ App.AssignMasterComponents = Em.Mixin.create(App.HostComponentValidationMixin, A
       if (masterComponent.get('isMasterWithMultipleInstances')) {
         showRemoveControl = installedServices.contains(masterComponent.get('stackService.serviceName')) &&
             (masterComponents.filterProperty('component_name', item.component_name).length > 1);
-        previousComponentName = item.component_name;
         componentObj.set('serviceComponentId', result.filterProperty('component_name', item.component_name).length + 1);
         componentObj.set("showRemoveControl", showRemoveControl);
       }
@@ -935,6 +926,7 @@ App.AssignMasterComponents = Em.Mixin.create(App.HostComponentValidationMixin, A
       return aValue - bValue;
     });
   },
+
   /**
    * Update dependent co-hosted components according to the change in the component host
    * @method updateCoHosts
@@ -953,7 +945,6 @@ App.AssignMasterComponents = Em.Mixin.create(App.HostComponentValidationMixin, A
     }, this);
   }.observes('selectedServicesMasters.@each.selectedHost'),
 
-
   /**
    * On change callback for inputs
    * @param {string} componentName
@@ -1165,8 +1156,9 @@ App.AssignMasterComponents = Em.Mixin.create(App.HostComponentValidationMixin, A
   },
 
   recommendAndValidate: function(callback) {
-    var self = this,
-      hostNames = this.getHosts();
+    const self = this;
+    const hostNames = this.getHosts();
+    const mpackInstances = this.get('wizardController').getMpackInstances();
 
     if (this.get('validationInProgress')) {
       this.set('runQueuedValidation', true);
@@ -1175,19 +1167,14 @@ App.AssignMasterComponents = Em.Mixin.create(App.HostComponentValidationMixin, A
 
     this.set('validationInProgress', true);
     
-    //TODO - mpacks: Hard coded to request first mpack only. Must be changed when we are installing multiple mpacks.
-    const selectedMpacks = this.get('content.selectedMpacks');
-    // load recommendations with partial request
     this.getRecommendedHosts({
       hosts: hostNames,
-      stackName: selectedMpacks[0].name,
-      stackVersion: selectedMpacks[0].version,
+      mpack_instances: mpackInstances,
       components: this.getCurrentComponentHostMap()
     }).then(function() {
       self.validateSelectedHostComponents({
         hosts: hostNames,
-        stackName: selectedMpacks[0].name,
-        stackVersion: selectedMpacks[0].version,  
+        mpack_instances: mpackInstances,
         blueprint: self.get('recommendations')
       }).then(function() {
         if (callback) {
@@ -1214,6 +1201,8 @@ App.AssignMasterComponents = Em.Mixin.create(App.HostComponentValidationMixin, A
           Em.set(component, 'size', Em.getWithDefault(component, 'hosts.length', 0));
         } else {
           acc.push({
+            mpackInstance: Em.get(i, 'mpackInstance'),
+            serviceInstance: Em.get(i, 'serviceInstance'),
             componentName: componentName,
             hosts: [hostName],
             size: 1
diff --git a/ambari-web/app/models/service.js b/ambari-web/app/models/service.js
index 0c6a64d..3bb61a4 100644
--- a/ambari-web/app/models/service.js
+++ b/ambari-web/app/models/service.js
@@ -24,6 +24,8 @@ App.Service = DS.Model.extend({
   serviceName: DS.attr('string'),
   displayName: Em.computed.formatRole('serviceName', true),
   serviceGroupName: DS.attr('string'),
+  mpackName: DS.attr('string'),
+  mpackVersion: DS.attr('string'),
   passiveState: DS.attr('string', {defaultValue: "OFF"}),
   workStatus: DS.attr('string'),
   rand: DS.attr('string'),
diff --git a/ambari-web/app/styles/bootstrap_overrides.less b/ambari-web/app/styles/bootstrap_overrides.less
index febbf93..1522875 100644
--- a/ambari-web/app/styles/bootstrap_overrides.less
+++ b/ambari-web/app/styles/bootstrap_overrides.less
@@ -85,7 +85,6 @@ select.form-control {
   background-color: #fff;
   border-radius: 0;
   .panel-heading {
-    padding: 0;
     margin-bottom: 15px;
     .panel-title {
       line-height: 34px;
@@ -94,7 +93,6 @@ select.form-control {
 }
 
 .panel .panel-body {
-  padding: 0;
   position: relative;
   min-height: 200px;
   height: 100%;
diff --git a/ambari-web/app/utils/ajax/ajax.js b/ambari-web/app/utils/ajax/ajax.js
index ab1897c..73d7bbe 100644
--- a/ambari-web/app/utils/ajax/ajax.js
+++ b/ambari-web/app/utils/ajax/ajax.js
@@ -57,7 +57,8 @@ var urls = {
   },
 
   'common.services.update.all' : {
-    'real': '/clusters/{clusterName}/servicegroups?{urlParams}',
+    //'real': '/clusters/{clusterName}/servicegroups?{urlParams}', //this is the new endpoint that should really be used for this but it isn't ready yet
+    'real': '/clusters/{clusterName}/services?{urlParams}', //this is the deprecated endpoint we have to use for now
     'format': function (data) {
       return {
         type: 'PUT',
@@ -2145,22 +2146,6 @@ var urls = {
     }
   },
 
-  'config.validations': {
-    'real': '{stackVersionUrl}/validations',
-    'mock': '/data/stacks/HDP-2.1/validations.json',
-    'type': 'POST',
-    'format': function (data) {
-      return {
-        data: JSON.stringify({
-          hosts: data.hosts,
-          services: data.services,
-          validate: data.validate,
-          recommendations: data.recommendations
-        })
-      }
-    }
-  },
-
   'preinstalled.checks': {
     'real': '/requests',
     'mock': '',
@@ -3136,6 +3121,26 @@ var urls = {
     real: '/mpacks?fields=*'
   },
 
+  'mpack.advisor.recommendations': {
+    real: '/mpacks/recommendations',
+    format: function (data) {
+      return {
+        type: 'POST',
+        data: JSON.stringify(data.data)
+      }
+    }
+  },
+
+  'mpack.advisor.validations': {
+    real: '/mpacks/validations',
+    format: function (data) {
+      return {
+        type: 'POST',
+        data: JSON.stringify(data.data)
+      }
+    }
+  },
+
   'registry.all': {
     real: '/registries?fields=mpacks/*,mpacks/versions/RegistryMpackVersionInfo/*,scenarios/*'
   },
diff --git a/ambari-web/app/utils/config.js b/ambari-web/app/utils/config.js
index d86a0bf..c95b0e6 100644
--- a/ambari-web/app/utils/config.js
+++ b/ambari-web/app/utils/config.js
@@ -763,7 +763,7 @@ App.config = Em.Object.create({
    */
   getStepConfigForProperty: function (stepConfigs, fileName) {
     return stepConfigs.find(function (s) {
-      return s.get('configTypes').contains(App.config.getConfigTagFromFileName(fileName));
+      return !!s.get('configTypes')[App.config.getConfigTagFromFileName(fileName)];
     });
   },
 
@@ -797,6 +797,7 @@ App.config = Em.Object.create({
       serviceName: preDefinedServiceConfig.get('serviceName'),
       displayName: preDefinedServiceConfig.get('displayName'),
       configCategories: preDefinedServiceConfig.get('configCategories'),
+      configTypes: preDefinedServiceConfig.get('configTypes'),
       configs: configs || [],
       configGroups: configGroups || [],
       initConfigsLength: initConfigsLength || 0
@@ -1084,7 +1085,7 @@ App.config = Em.Object.create({
     if (!serviceName || unsupportedServiceNames.contains(serviceName) || !filename) {
       return false;
     } else {
-      var stackService = App.StackService.find(serviceName);
+      var stackService = App.StackService.find().findProperty('serviceName', serviceName);
       if (!stackService) {
         return false;
       }
@@ -1103,7 +1104,7 @@ App.config = Em.Object.create({
       if (!stackServiceName) {
         return false;
       }
-      var stackService = App.StackService.find(serviceName);
+      var stackService = App.StackService.find().findProperty('serviceName', serviceName);
       return !!this.getConfigTypesInfoFromService(stackService).supportsAddingForbidden.find(function (configType) {
         return filename.startsWith(configType);
       });
diff --git a/ambari-web/app/utils/misc.js b/ambari-web/app/utils/misc.js
index ae0e49b..3fe3d9d 100644
--- a/ambari-web/app/utils/misc.js
+++ b/ambari-web/app/utils/misc.js
@@ -54,11 +54,14 @@ module.exports = {
     return ((((((+d[0])*256)+(+d[1]))*256)+(+d[2]))*256)+(+d[3]);
   },
 
-  sortByOrder: function (sortOrder, array) {
+  sortByOrder: function (sortOrder, array, sortOn) {
+    //provide default sortOn function if one is not passed in
+    sortOn = sortOn || (item => Em.get(item, 'id'));
+
     var sorted = [];
     for (var i = 0; i < sortOrder.length; i++)
       for (var j = 0; j < array.length; j++) {
-        if (sortOrder[i] == Em.get(array[j], 'id')) {
+        if (sortOrder[i] == sortOn(array[j])) {
           sorted.push(array[j]);
         }
       }
diff --git a/ambari-web/app/views/main/dashboard/widgets/hbase_links.js b/ambari-web/app/views/main/dashboard/widgets/hbase_links.js
index 9600094..f5d4cb0 100644
--- a/ambari-web/app/views/main/dashboard/widgets/hbase_links.js
+++ b/ambari-web/app/views/main/dashboard/widgets/hbase_links.js
@@ -23,7 +23,7 @@ App.HBaseLinksView = App.LinkDashboardWidgetView.extend({
   templateName: require('templates/main/dashboard/widgets/hbase_links'),
 
   port: function() {
-    return App.StackService.find('HBASE').compareCurrentVersion('1.1') > -1 ? '16010' : '60010';
+    return App.StackService.find().findProperty('serviceName', 'HBASE').compareCurrentVersion('1.1') > -1 ? '16010' : '60010';
   }.property(),
 
   componentName: 'HBASE_REGIONSERVER',
diff --git a/ambari-web/app/views/main/service/item.js b/ambari-web/app/views/main/service/item.js
index 1d4e5a6..a3694f0 100644
--- a/ambari-web/app/views/main/service/item.js
+++ b/ambari-web/app/views/main/service/item.js
@@ -353,7 +353,7 @@ App.MainServiceItemView = Em.View.extend({
   hasMetricTab: function() {
     let serviceName = this.get('controller.content.serviceName');
     let graphs = require('data/service_graph_config')[serviceName.toLowerCase()];
-    return graphs || App.StackService.find(serviceName).get('isServiceWithWidgets');
+    return graphs || App.StackService.find().findProperty('serviceName', serviceName).get('isServiceWithWidgets');
   }.property('controller.content.serviceName'),
 
   didInsertElement: function () {
diff --git a/ambari-web/app/views/main/service/reassign/step5_view.js b/ambari-web/app/views/main/service/reassign/step5_view.js
index 9c4f39d..3024a47 100644
--- a/ambari-web/app/views/main/service/reassign/step5_view.js
+++ b/ambari-web/app/views/main/service/reassign/step5_view.js
@@ -29,7 +29,7 @@ App.ReassignMasterWizardStep5View = Em.View.extend({
       return '';
     }
     var
-      atsDir = App.StackService.find('YARN').compareCurrentVersion('2.7') > -1 ? "timeline-state-store.ldb" : "leveldb-timeline-store.ldb",
+      atsDir = App.StackService.find().findProperty('serviceName', 'YARN').compareCurrentVersion('2.7') > -1 ? "timeline-state-store.ldb" : "leveldb-timeline-store.ldb",
       componentDir = this.get('controller.content.componentDir') || '',
       componentDirCmd = componentDir.replace(/,/g, ' '),
       sourceHost = this.get('controller.content.reassignHosts.source'),
diff --git a/ambari-web/app/views/main/service/service.js b/ambari-web/app/views/main/service/service.js
index 6032333..9b46dcc 100644
--- a/ambari-web/app/views/main/service/service.js
+++ b/ambari-web/app/views/main/service/service.js
@@ -124,9 +124,9 @@ App.MainDashboardServiceViewWrapper = Em.Mixin.create({
   layoutName: require('templates/main/service/service'),
 
   mpackVersion: function() {
-    const stackService = App.StackService.find(this.get('controller.content.serviceName'));
-    return `${stackService.get('stackName')} (${stackService.get('stackVersion')})`;
-  }.property('controller.content.serviceName'),
+    const service = this.get('controller.content');
+    return `${service.get('mpackName')} (${service.get('mpackVersion')})`;
+  }.property('controller.content'),
 });
 
 App.MainDashboardServiceView = Em.View.extend(App.MainDashboardServiceViewWrapper, {
diff --git a/ambari-web/app/views/main/service/widgets/create/expression_view.js b/ambari-web/app/views/main/service/widgets/create/expression_view.js
index 7d4854f..4e5195c 100644
--- a/ambari-web/app/views/main/service/widgets/create/expression_view.js
+++ b/ambari-web/app/views/main/service/widgets/create/expression_view.js
@@ -390,7 +390,7 @@ App.AddMetricExpressionView = Em.View.extend({
         serviceName: serviceName,
         //in order to support panel lists
         href: '#' + serviceName,
-        displayName: App.StackService.find(serviceName).get('displayName'),
+        displayName: App.StackService.find().findProperty('serviceName', serviceName).get('displayName'),
         count: servicesMap[serviceName].count,
         components: components
       }));
diff --git a/ambari-web/test/controllers/installer_test.js b/ambari-web/test/controllers/installer_test.js
index 42fc5d2..5aa19c3 100644
--- a/ambari-web/test/controllers/installer_test.js
+++ b/ambari-web/test/controllers/installer_test.js
@@ -824,7 +824,8 @@ describe('App.InstallerController', function () {
         {
           "component_name": "name",
           "display_name": "dname",
-          "isInstalled": false
+          "isInstalled": false,
+          "service_name": "i1"
         }
       ]);
     });
@@ -854,7 +855,8 @@ describe('App.InstallerController', function () {
             display_name: 'n1',
             component_name: 'c1',
             serviceId: 1,
-            selectedHost: 'h1'
+            selectedHost: 'h1',
+            mpackInstance: 'm1'
           })
         ])
       });
@@ -865,7 +867,8 @@ describe('App.InstallerController', function () {
           "component": "c1",
           "serviceId": 1,
           "isInstalled": false,
-          "host_id": 11
+          "host_id": 11,
+          "serviceGroupName": "m1"
         }
       ]);
     });
diff --git a/ambari-web/test/controllers/main/host/configs_service_test.js b/ambari-web/test/controllers/main/host/configs_service_test.js
index 85f98b3..ac6aef3 100644
--- a/ambari-web/test/controllers/main/host/configs_service_test.js
+++ b/ambari-web/test/controllers/main/host/configs_service_test.js
@@ -108,12 +108,20 @@ describe('App.MainHostServiceConfigsController', function () {
         return { always: Em.K };
       });
       sinon.stub(controller, 'trackRequest');
+      sinon.stub(App.StackService, 'find').returns({
+        findProperty: function () {
+          return Em.Object.create({
+            dependentServiceNames: []
+          });
+        }
+      });
     });
     afterEach(function() {
       controller.loadCurrentVersions.restore();
       controller.loadConfigTheme.restore();
       App.themesMapper.generateAdvancedTabs.restore();
       controller.trackRequest.restore();
+      App.StackService.find.restore();
     });
 		it("should set host", function () {
 			controller.set('content', {
diff --git a/ambari-web/test/controllers/main/service/info/config_test.js b/ambari-web/test/controllers/main/service/info/config_test.js
index 857ab6e..96bef9e 100644
--- a/ambari-web/test/controllers/main/service/info/config_test.js
+++ b/ambari-web/test/controllers/main/service/info/config_test.js
@@ -1069,8 +1069,10 @@ describe("App.MainServiceInfoConfigsController", function () {
       createService('YARN', ['HIVE'])
     ];
     beforeEach(function() {
-      sinon.stub(App.StackService, 'find', function(serviceName) {
-        return stackServices.findProperty('serviceName', serviceName);
+      sinon.stub(App.StackService, 'find').returns({
+        findProperty: function (prop, serviceName) {
+          return stackServices.findProperty('serviceName', serviceName);
+        }
       });
     });
     afterEach(function() {
diff --git a/ambari-web/test/controllers/main/service/item_test.js b/ambari-web/test/controllers/main/service/item_test.js
index bac09b7..81d553f 100644
--- a/ambari-web/test/controllers/main/service/item_test.js
+++ b/ambari-web/test/controllers/main/service/item_test.js
@@ -1387,8 +1387,10 @@ describe('App.MainServiceItemController', function () {
 
     beforeEach(function() {
       mainServiceItemController = App.MainServiceItemController.create({});
-      sinon.stub(App.StackService, 'find', function (serviceName) {
-        return stackServiceModel[serviceName];
+      sinon.stub(App.StackService, 'find').returns({
+        findProperty: function (prop, serviceName) {
+          return stackServiceModel[serviceName];
+        }
       });
       this.mockService = sinon.stub(App.Service, 'find');
     });
@@ -1679,8 +1681,10 @@ describe('App.MainServiceItemController', function () {
     var mainServiceItemController;
 
     beforeEach(function() {
-      sinon.stub(App.StackService, 'find', function (serviceName) {
-        return stackServiceModel[serviceName];
+      sinon.stub(App.StackService, 'find').returns({
+        findProperty: function (prop, serviceName) {
+          return stackServiceModel[serviceName];
+        }
       });
       mainServiceItemController = App.MainServiceItemController.create({
         content: {}
@@ -1939,9 +1943,13 @@ describe('App.MainServiceItemController', function () {
           serviceName: serviceName
         }
       });
-      sinon.stub(App.StackService, 'find').returns(Em.Object.create({
-        dependentServiceNames: dependentServiceNames
-      }));
+      sinon.stub(App.StackService, 'find').returns({
+        findProperty: function () {
+          return Em.Object.create({
+            dependentServiceNames: dependentServiceNames
+          });
+        }
+      });
     });
 
     afterEach(function () {
diff --git a/ambari-web/test/controllers/wizard/step5_test.js b/ambari-web/test/controllers/wizard/step5_test.js
index 1cd9902..3d74999 100644
--- a/ambari-web/test/controllers/wizard/step5_test.js
+++ b/ambari-web/test/controllers/wizard/step5_test.js
@@ -1014,7 +1014,9 @@ describe('App.WizardStep5Controller', function () {
         {
           fullComponent: Em.Object.create({
             componentName: 'c1',
-            serviceName: 's1'
+            serviceName: 's1',
+            serviceInstance: 'si1',
+            mpackInstance: 'm1'
           }),
           hostName: 'h1',
           mastersToMove: ['c1'],
@@ -1029,13 +1031,17 @@ describe('App.WizardStep5Controller', function () {
             serviceId: 's1',
             selectedHost: 'h2',
             isInstalled: true,
-            isServiceCoHost: false
+            isServiceCoHost: false,
+            serviceInstance: 'si1',
+            mpackInstance: 'm1'
           }
         },
         {
           fullComponent: Em.Object.create({
             componentName: 'c1',
-            serviceName: 's1'
+            serviceName: 's1',
+            serviceInstance: 'si1',
+            mpackInstance: 'm1'
           }),
           hostName: 'h1',
           mastersToMove: [],
@@ -1046,13 +1052,17 @@ describe('App.WizardStep5Controller', function () {
             serviceId: 's1',
             selectedHost: 'h1',
             isInstalled: false,
-            isServiceCoHost: false
+            isServiceCoHost: false,
+            serviceInstance: 'si1',
+            mpackInstance: 'm1'
           }
         },
         {
           fullComponent: Em.Object.create({
             componentName: 'c1',
-            serviceName: 's1'
+            serviceName: 's1',
+            serviceInstance: 'si1',
+            mpackInstance: 'm1'
           }),
           hostName: 'h1',
           mastersToMove: [],
@@ -1063,7 +1073,9 @@ describe('App.WizardStep5Controller', function () {
             serviceId: 's1',
             selectedHost: 'h1',
             isInstalled: false,
-            isServiceCoHost: true
+            isServiceCoHost: true,
+            serviceInstance: 'si1',
+            mpackInstance: 'm1'
           }
         }
       ]).forEach(function (test, i) {
diff --git a/ambari-web/test/controllers/wizard/step7/assign_master_controller_test.js b/ambari-web/test/controllers/wizard/step7/assign_master_controller_test.js
index 2e1839a..fb0ebe1 100644
--- a/ambari-web/test/controllers/wizard/step7/assign_master_controller_test.js
+++ b/ambari-web/test/controllers/wizard/step7/assign_master_controller_test.js
@@ -307,8 +307,10 @@ describe('App.AssignMasterOnStep7Controller', function () {
       sinon.stub(App.Service, 'find').returns([
         {serviceName: 'S1'}
       ]);
-      sinon.stub(App.StackService, 'find', function(input) {
-        return Em.Object.create({displayName: input});
+      sinon.stub(App.StackService, 'find').returns({
+        findProperty: function (prop, input) {
+          return Em.Object.create({ displayName: input });
+        }
       });
     });
 
diff --git a/ambari-web/test/controllers/wizard_test.js b/ambari-web/test/controllers/wizard_test.js
index 0f1896c..93f336d 100644
--- a/ambari-web/test/controllers/wizard_test.js
+++ b/ambari-web/test/controllers/wizard_test.js
@@ -770,8 +770,7 @@ describe('App.WizardController', function () {
         ]
       }));
       wizardController.installServices(true);
-      expect(App.ajax.send.calledThrice).to.be.true;
-      expect($.when.calledOnce).to.be.true;
+      expect(App.ajax.send.calledOnce).to.be.true;
       expect(res).to.be.eql({
         "status": "PENDING"
       });
diff --git a/ambari-web/test/mappers/stack_service_mapper_test.js b/ambari-web/test/mappers/stack_service_mapper_test.js
index 88b4b43..a381e9e 100644
--- a/ambari-web/test/mappers/stack_service_mapper_test.js
+++ b/ambari-web/test/mappers/stack_service_mapper_test.js
@@ -171,7 +171,7 @@ describe('App.stackServiceMapper', function () {
       },
       sortedServiceNames = ["HDFS", "HIVE", "ZOOKEEPER", "ACCUMULO", "KAFKA", "KERBEROS"],
       serviceResult = {
-        id: "KAFKA",
+        id: "KAFKA-HDP-2.2",
         serviceName: "KAFKA",
         displayName: "Kafka",
         configTypes: {
diff --git a/ambari-web/test/mixins/common/configs/configs_saver_test.js b/ambari-web/test/mixins/common/configs/configs_saver_test.js
index 22768af..edbaf45 100644
--- a/ambari-web/test/mixins/common/configs/configs_saver_test.js
+++ b/ambari-web/test/mixins/common/configs/configs_saver_test.js
@@ -33,9 +33,12 @@ describe('App.ConfigsSaverMixin', function() {
   });
 
   describe("#currentServices", function () {
+    var findProperty = sinon.stub().returns({});
 
     beforeEach(function() {
-      sinon.stub(App.StackService, 'find').returns({});
+      sinon.stub(App.StackService, 'find').returns({
+        findProperty: findProperty
+      });
     });
 
     afterEach(function() {
@@ -45,7 +48,7 @@ describe('App.ConfigsSaverMixin', function() {
     it("should return currentServices", function() {
       mixin.set('content.serviceName', 'S1');
       expect(mixin.get('currentServices')).to.be.eql([{}]);
-      expect(App.StackService.find.calledWith('S1')).to.be.true;
+      expect(findProperty.calledWith('serviceName', 'S1')).to.be.true;
     });
   });
 
@@ -614,7 +617,9 @@ describe('App.ConfigsSaverMixin', function() {
   describe("#allowSaveCoreSite()", function () {
 
     it("empty currentServices", function() {
-      mixin.set('currentServices', []);
+      mixin.reopen({
+        currentServices: []
+      });
       expect(mixin.allowSaveCoreSite()).to.be.false;
     });
 
@@ -1129,9 +1134,13 @@ describe('App.ConfigsSaverMixin', function() {
 
     beforeEach(function() {
       sinon.stub(App.config, 'textareaIntoFileConfigs');
-      sinon.stub(App.StackService, 'find').returns(Em.Object.create({
-        configTypes: {'k1': 't1'}
-      }));
+      sinon.stub(App.StackService, 'find').returns({
+        findProperty: function () {
+          return Em.Object.create({
+            configTypes: { 'k1': 't1' }
+          });
+        }
+      });
       sinon.stub(App.config, 'getOriginalFileName').returns('file1');
       this.mockSave = sinon.stub(mixin, 'saveSiteConfigs');
       this.mockJSON = sinon.stub(mixin, 'generateDesiredConfigsJSON');
diff --git a/ambari-web/test/mixins/common/configs/enhanced_configs_test.js b/ambari-web/test/mixins/common/configs/enhanced_configs_test.js
index 98f3182..5c58037 100644
--- a/ambari-web/test/mixins/common/configs/enhanced_configs_test.js
+++ b/ambari-web/test/mixins/common/configs/enhanced_configs_test.js
@@ -525,7 +525,6 @@ describe('App.EnhancedConfigsMixin', function () {
       sinon.stub(mock, 'onComplete');
       sinon.stub(mixin, 'getConfigRecommendationsParams').returns({});
       sinon.stub(mixin, 'modifyRecommendationConfigGroups');
-      sinon.stub(mixin, 'addRecommendationRequestParams');
       sinon.stub(mixin, 'getRecommendationsRequest');
       sinon.stub(mixin, 'loadAdditionalSites');
     });
@@ -534,7 +533,6 @@ describe('App.EnhancedConfigsMixin', function () {
       mock.onComplete.restore();
       mixin.getConfigRecommendationsParams.restore();
       mixin.modifyRecommendationConfigGroups.restore();
-      mixin.addRecommendationRequestParams.restore();
       mixin.getRecommendationsRequest.restore();
       mixin.loadAdditionalSites.restore();
     });
@@ -566,63 +564,33 @@ describe('App.EnhancedConfigsMixin', function () {
       mixin.loadConfigRecommendations([{}], mock.onComplete);
       expect(mixin.getConfigRecommendationsParams.calledWith(true)).to.be.true;
       expect(mixin.modifyRecommendationConfigGroups.calledOnce).to.be.true;
-      expect(mixin.addRecommendationRequestParams.calledOnce).to.be.true;
       expect(mixin.getRecommendationsRequest.calledOnce).to.be.true;
     });
   });
 
-  describe("#addRecommendationRequestParams()", function () {
-
-    beforeEach(function() {
-      sinon.stub(blueprintUtils, 'buildConfigsJSON').returns([{}]);
-    });
-
-    afterEach(function() {
-      blueprintUtils.buildConfigsJSON.restore();
-    });
-
-    it("recommendations should be set", function () {
-      var dataToSend = {};
-      mixin.addRecommendationRequestParams({blueprint: {}}, dataToSend, []);
-      expect(dataToSend).to.be.eql({
-        "recommendations": {
-          "blueprint": {
-            "configurations": [
-              {}
-            ]
-          }
-        }
-      });
-    });
-  });
-
   describe("#loadAdditionalSites()", function () {
 
     beforeEach(function() {
       sinon.stub(App.config, 'getConfigsByTypes').returns({
         done: function(callback) {callback([]);}
       });
-      sinon.stub(mixin, 'addRecommendationRequestParams');
       sinon.stub(mixin, 'getRecommendationsRequest');
+      sinon.stub(mixin, 'addRequestedConfigs');
       mixin.loadAdditionalSites([], [], {}, {}, Em.K);
     });
 
     afterEach(function() {
       App.config.getConfigsByTypes.restore();
-      mixin.addRecommendationRequestParams.restore();
       mixin.getRecommendationsRequest.restore();
+      mixin.addRequestedConfigs.restore();
     });
 
     it("App.config.getConfigsByTypes should be called", function() {
       expect(App.config.getConfigsByTypes.calledOnce).to.be.true;
     });
 
-    it("addRecommendationRequestParams should be called", function() {
-      expect(mixin.addRecommendationRequestParams.calledWith({}, {}, [])).to.be.true;
-    });
-
     it("getRecommendationsRequest should be called", function() {
-      expect(mixin.getRecommendationsRequest.calledWith({}, Em.K)).to.be.true;
+      expect(mixin.getRecommendationsRequest.calledOnce).to.be.true;
     });
   });
 
@@ -673,7 +641,6 @@ describe('App.EnhancedConfigsMixin', function () {
       expect(mixin.getConfigRecommendationsParams(true, [{}])).to.be.eql({
         recommend: 'configuration-dependencies',
         hosts: ['host1'],
-        services: ['S1'],
         changed_configurations: [{}]
       });
     });
@@ -684,7 +651,6 @@ describe('App.EnhancedConfigsMixin', function () {
       expect(mixin.getConfigRecommendationsParams(false, [{}])).to.be.eql({
         recommend: 'configurations',
         hosts: ['host1'],
-        services: ['S1'],
         changed_configurations: undefined
       });
     });
@@ -706,7 +672,7 @@ describe('App.EnhancedConfigsMixin', function () {
     it("App.ajax.send should be called", function() {
       mixin.getRecommendationsRequest({}, mock.callback);
       expect(mixin.get('recommendationsInProgress')).to.be.true;
-      var args = testHelpers.findAjaxRequest('name', 'config.recommendations');
+      var args = testHelpers.findAjaxRequest('name', 'mpack.advisor.recommendations');
       expect(args[0]).exists;
       args[0].callback();
       expect(mixin.get('recommendationsInProgress')).to.be.false;
@@ -847,7 +813,7 @@ describe('App.EnhancedConfigsMixin', function () {
   });
 
   describe("#loadRecommendationsSuccess()", function () {
-    var params = {dataToSend: {changed_configurations: []}};
+    var params = {data: {changed_configurations: []}};
 
     beforeEach(function() {
       sinon.stub(mixin, '_saveRecommendedValues');
@@ -962,7 +928,8 @@ describe('App.EnhancedConfigsMixin', function () {
           {
             recommendations: {
               blueprint: {
-                configurations: {}
+                configurations: {},
+                mpack_instances: []
               }
             }
           }
@@ -979,7 +946,8 @@ describe('App.EnhancedConfigsMixin', function () {
             recommendations: {
               'config-groups': [],
               blueprint: {
-                configurations: {}
+                configurations: {},
+                mpack_instances: []
               }
             }
           }
@@ -990,7 +958,8 @@ describe('App.EnhancedConfigsMixin', function () {
       expect(mixin.saveConfigGroupsRecommendations.calledWith({
         'config-groups': [],
         blueprint: {
-          configurations: {}
+          configurations: {},
+          mpack_instances: []
         }
       }, [])).to.be.true;
     });
@@ -1002,7 +971,8 @@ describe('App.EnhancedConfigsMixin', function () {
             recommendations: {
               'config-groups': [],
               blueprint: {
-                configurations: {}
+                configurations: {},
+                mpack_instances: []
               }
             }
           }
@@ -1022,7 +992,8 @@ describe('App.EnhancedConfigsMixin', function () {
             recommendations: {
               'config-groups': [],
               blueprint: {
-                configurations: {}
+                configurations: {},
+                mpack_instances: []
               }
             }
           }
@@ -1041,7 +1012,8 @@ describe('App.EnhancedConfigsMixin', function () {
           {
             recommendations: {
               blueprint: {
-                configurations: {}
+                configurations: {},
+                mpack_instances: []
               }
             }
           }
@@ -1467,5 +1439,58 @@ describe('App.EnhancedConfigsMixin', function () {
       expect(mixin.isConfigGroupAffected(['host1'], ['host2', 'host1'])).to.be.true;
     });
   });
+
+  describe('#addRequestedConfigs', function () {
+    it('adds the configs to include in the request to the recommendations.blueprint object in the format required', function () {
+      sinon.stub(blueprintUtils, 'buildConfigsJSON', function (configs) { return configs[0]; });
+      mixin.set('wizardController', App.InstallerController.create({
+        content: {
+          selectedServices: [
+            {
+              name: 'OTHER',
+              mpackName: 'MPACK',
+              mpackVersion: '1.0',
+            }
+          ]
+        }
+      }));
+
+      const actual = { blueprint: {} };
+      const configs = [
+        Em.Object.create({
+          serviceName: 'MISC',
+          configs: ['misc1', 'misc2']
+        }),
+        Em.Object.create({
+          serviceName: 'OTHER',
+          configs: ['other1', 'other2']
+        })
+      ];
+      const expected = {
+        blueprint: {
+          configurations: configs[0],
+          mpack_instances: [
+            {
+              name: 'MPACK',
+              type: 'MPACK',
+              version: '1.0',
+              service_instances: [
+                {
+                  name: 'OTHER',
+                  type: 'OTHER',
+                  configurations: configs[1]
+                }
+              ]
+            }
+          ]
+        }
+      };
+
+      mixin.addRequestedConfigs(actual, configs);
+      expect(actual).to.deep.equal(expected);
+
+      blueprintUtils.buildConfigsJSON.restore();
+    });
+  });
 });
 
diff --git a/ambari-web/test/mixins/common/hosts/host_component_recommendation_mixin_test.js b/ambari-web/test/mixins/common/hosts/host_component_recommendation_mixin_test.js
index 13db571..451cccf 100644
--- a/ambari-web/test/mixins/common/hosts/host_component_recommendation_mixin_test.js
+++ b/ambari-web/test/mixins/common/hosts/host_component_recommendation_mixin_test.js
@@ -76,7 +76,6 @@ describe('App.HostComponentRecommendationMixin', function() {
       {
         opts: null,
         e: {
-          services: [],
           hosts: [],
           components: [],
           blueprint: null
@@ -85,13 +84,11 @@ describe('App.HostComponentRecommendationMixin', function() {
       },
       {
         opts: {
-          services: ['s1'],
           hosts: ['h1'],
           components: [{componentName: 'c1'}],
           blueprint: {recommend:{}}
         },
         e: {
-          services: ['s1'],
           hosts: ['h1'],
           components: [{componentName: 'c1'}],
           blueprint: {recommend:{}}
@@ -109,9 +106,9 @@ describe('App.HostComponentRecommendationMixin', function() {
   describe('#loadComponentsRecommedationsFromServer', function() {
     it('default request options checking', function() {
       mixedObject.loadComponentsRecommendationsFromServer('someData');
-      var args = helpers.findAjaxRequest('name', 'config.recommendations');
+      var args = helpers.findAjaxRequest('name', 'mpack.advisor.recommendations');
       expect(args[0]).to.be.eql({
-        name: 'config.recommendations',
+        name: 'mpack.advisor.recommendations',
         sender: mixedObject,
         data: 'someData',
         success: 'loadRecommendationsSuccessCallback',
@@ -131,20 +128,34 @@ describe('App.HostComponentRecommendationMixin', function() {
       {
         options: {
           hosts: ['h1'],
-          services: ['s1'],
-          components: [Em.Object.create({componentName: 'c1', hostName: 'h1'})],
-          blueprint: null
+          components: [Em.Object.create({
+            componentName: 'c1',
+            hostName: 'h1',
+            mpackInstance: 'm1',
+            serviceInstance: 'si1'
+          })],
+          blueprint: null,
+          mpack_instances: []
         },
         e: {
-          dataToSend: {
+          data: {
             recommend: 'host_groups',
             hosts: ['h1'],
-            services: ['s1'],
             recommendations: {
               blueprint: {
                 host_groups: [
-                  { name: 'host-group-1', components: [{ name: 'c1' }] }
-                ]
+                  {
+                    name: 'host-group-1',
+                    components: [
+                      {
+                        name: 'c1',
+                        mpack_instance: 'm1',
+                        service_instance: 'si1'
+                      }
+                    ]
+                  }
+                ],
+                mpack_instances: []
               },
               blueprint_cluster_binding: {
                 host_groups: [
@@ -152,28 +163,27 @@ describe('App.HostComponentRecommendationMixin', function() {
                 ]
               }
             }
-          },
-          stackVersionUrl: '/stack/url'
+          }
         },
         m: 'when blueprint not passed it should be generated from components list'
       },
       {
         options: {
           hosts: ['h1'],
-          services: ['s1'],
           components: [Em.Object.create({componentName: 'c1', hostName: 'h1'})],
-          blueprint: { blueprint: {}}
+          blueprint: { blueprint: {} },
+          mpack_instances: []
         },
         e: {
-          dataToSend: {
+          data: {
             recommend: 'host_groups',
             hosts: ['h1'],
-            services: ['s1'],
             recommendations: {
-              blueprint: {}
+              blueprint: {
+                mpack_instances: []
+              }
             }
-          },
-          stackVersionUrl: '/stack/url'
+          }
         },
         m: 'when blueprint passed it should be used instead of generated blueprint'
       }
diff --git a/ambari-web/test/mixins/common/hosts/host_component_validation_mixin_test.js b/ambari-web/test/mixins/common/hosts/host_component_validation_mixin_test.js
index 9589f90..236210c 100644
--- a/ambari-web/test/mixins/common/hosts/host_component_validation_mixin_test.js
+++ b/ambari-web/test/mixins/common/hosts/host_component_validation_mixin_test.js
@@ -76,7 +76,6 @@ describe('App.HostComponentValidationMixin', function() {
       {
         opts: null,
         e: {
-          services: [],
           hosts: [],
           components: [],
           blueprint: null
@@ -85,13 +84,11 @@ describe('App.HostComponentValidationMixin', function() {
       },
       {
         opts: {
-          services: ['s1'],
           hosts: ['h1'],
           components: [{componentName: 'c1'}],
           blueprint: {recommend:{}}
         },
         e: {
-          services: ['s1'],
           hosts: ['h1'],
           components: [{componentName: 'c1'}],
           blueprint: {recommend:{}}
@@ -109,9 +106,9 @@ describe('App.HostComponentValidationMixin', function() {
   describe('#getHostComponentValidationRequest', function() {
     it('default request options checking', function() {
       mixedObject.getHostComponentValidationRequest('someData');
-      var args = helpers.findAjaxRequest('name', 'config.validations');
+      var args = helpers.findAjaxRequest('name', 'mpack.advisor.validations');
       expect(args[0]).to.be.eql({
-        name: 'config.validations',
+        name: 'mpack.advisor.validations',
         sender: mixedObject,
         data: 'someData',
         success: 'updateValidationsSuccessCallback',
@@ -131,25 +128,39 @@ describe('App.HostComponentValidationMixin', function() {
       {
         options: {
           hosts: ['h1'],
-          services: ['s1'],
-          components: [Em.Object.create({componentName: 'c1', hostName: 'h1'})],
-          blueprint: null
+          components: [
+            Em.Object.create({
+              componentName: 'c1',
+              hostName: 'h1',
+              mpackInstance: 'm1',
+              serviceInstance: 'si1'
+            })
+          ],
+          blueprint: null,
+          mpack_instances: []
         },
         e: {
-          validate: 'host_groups',
-          stackVersionUrl: '/stack/url',
-          hosts: ['h1'],
-          services: ['s1'],
-          recommendations: {
-            blueprint: {
-              host_groups: [
-                {name: 'host-group-1',components: [{name: 'c1'}]}
-              ]
-            },
-            blueprint_cluster_binding: {
-              host_groups: [
-                {name: 'host-group-1', hosts: [{fqdn: 'h1'}]}
-              ]
+          data: {
+            validate: 'host_groups',
+            hosts: ['h1'],
+            recommendations: {
+              blueprint: {
+                host_groups: [
+                  {
+                    name: 'host-group-1', components: [{
+                      name: 'c1',
+                      mpack_instance: 'm1',
+                      service_instance: 'si1' 
+                    }]
+                  }
+                ],
+                mpack_instances: []
+              },
+              blueprint_cluster_binding: {
+                host_groups: [
+                  { name: 'host-group-1', hosts: [{ fqdn: 'h1' }] }
+                ]
+              }
             }
           }
         },
@@ -158,17 +169,19 @@ describe('App.HostComponentValidationMixin', function() {
       {
         options: {
           hosts: ['h1'],
-          services: ['s1'],
           components: [Em.Object.create({componentName: 'c1', hostName: 'h1'})],
-          blueprint: { blueprint: {}}
+          blueprint: { blueprint: {} },
+          mpack_instances: []
         },
         e: {
-          validate: 'host_groups',
-          stackVersionUrl: '/stack/url',
-          hosts: ['h1'],
-          services: ['s1'],
-          recommendations: {
-            blueprint: {}
+          data: {
+            validate: 'host_groups',
+            hosts: ['h1'],
+            recommendations: {
+              blueprint: {
+                mpack_instances: []
+              }
+            }
           }
         },
         m: 'when blueprint passed it should be used instead of generated blueprint'
diff --git a/ambari-web/test/mixins/common/widgets/widget_section_test.js b/ambari-web/test/mixins/common/widgets/widget_section_test.js
index e6b8bf4..1da742d 100644
--- a/ambari-web/test/mixins/common/widgets/widget_section_test.js
+++ b/ambari-web/test/mixins/common/widgets/widget_section_test.js
@@ -38,9 +38,9 @@ describe('App.WidgetSectionMixin', function () {
       },
       {
         services: [
-          {
+          Em.Object.create({
             serviceName: 'AMBARI_METRICS'
-          }
+          })
         ],
         isAmbariMetricsInstalled: true,
         title: 'Ambari Metrics installed'
diff --git a/ambari-web/test/utils/config_test.js b/ambari-web/test/utils/config_test.js
index 05fa565..8050c2c 100644
--- a/ambari-web/test/utils/config_test.js
+++ b/ambari-web/test/utils/config_test.js
@@ -1500,8 +1500,17 @@ describe('App.config', function() {
   });
 
   describe('#getStepConfigForProperty', function () {
-    var input = [Em.Object.create({ configTypes: ['f1'] }), Em.Object.create({ configTypes: ['f2'] })];
+    var input = [
+      Em.Object.create({
+        configTypes: { f1: 'f1' }
+      }),
+      Em.Object.create({
+        configTypes: { f2: 'f2' }
+      })
+    ];
+    
     var output = input[0];
+
     it('returns stepConfig for fileName', function () {
       expect(App.config.getStepConfigForProperty(input, 'f1')).to.eql(output);
     });