You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by ja...@apache.org on 2014/09/25 21:22:15 UTC

[2/2] git commit: AMBARI-7482. Create ember data models for stack, operating system and repository. (jaimin)

AMBARI-7482. Create ember data models for stack, operating system and repository. (jaimin)


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

Branch: refs/heads/trunk
Commit: 5a154221c9ac9e67cec7b572174bf5fa20dfdcff
Parents: 2df5f25
Author: Jaimin Jetly <ja...@hortonworks.com>
Authored: Thu Sep 25 12:20:15 2014 -0700
Committer: Jaimin Jetly <ja...@hortonworks.com>
Committed: Thu Sep 25 12:20:15 2014 -0700

----------------------------------------------------------------------
 .../stacks/HDP/2.1/services/FLUME/metainfo.xml  |   2 +-
 ambari-web/app/assets/test/tests.js             |   1 +
 ambari-web/app/config.js                        |   2 +-
 ambari-web/app/controllers/installer.js         | 252 +++-----
 .../app/controllers/wizard/step1_controller.js  |  12 +-
 .../app/controllers/wizard/step8_controller.js  |  52 +-
 ambari-web/app/mappers.js                       |   1 +
 ambari-web/app/mappers/stack_mapper.js          | 114 ++++
 ambari-web/app/mappers/stack_service_mapper.js  |   2 +
 ambari-web/app/models.js                        |   3 +
 ambari-web/app/models/operating_system.js       |  33 +
 ambari-web/app/models/repository.js             |  67 ++
 ambari-web/app/models/stack.js                  |  70 ++
 ambari-web/app/models/stack_service.js          |   1 +
 ambari-web/app/routes/installer.js              |  32 +-
 ambari-web/app/templates/wizard/step1.hbs       |  14 +-
 ambari-web/app/views/wizard/step1_view.js       | 214 ++-----
 ambari-web/test/controllers/installer_test.js   |  47 +-
 .../test/controllers/wizard/step8_test.js       |  56 --
 ambari-web/test/mappers/stack_mapper_test.js    | 285 +++++++++
 ambari-web/test/stack.js                        | 265 ++++++++
 ambari-web/test/utils/helper_test.js            |   4 +-
 ambari-web/test/views/wizard/step1_view_test.js | 633 ++++++++-----------
 23 files changed, 1310 insertions(+), 852 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/5a154221/ambari-server/src/main/resources/stacks/HDP/2.1/services/FLUME/metainfo.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.1/services/FLUME/metainfo.xml b/ambari-server/src/main/resources/stacks/HDP/2.1/services/FLUME/metainfo.xml
index f29689b..12ad809 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.1/services/FLUME/metainfo.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/2.1/services/FLUME/metainfo.xml
@@ -19,7 +19,7 @@
   <schemaVersion>2.0</schemaVersion>
   <services>
     <service>
-      <name>FLUME</name>>
+      <name>FLUME</name>
       <version>1.4.0.2.1</version>
     </service>
   </services>

http://git-wip-us.apache.org/repos/asf/ambari/blob/5a154221/ambari-web/app/assets/test/tests.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/test/tests.js b/ambari-web/app/assets/test/tests.js
index 0c5f875..652c751 100644
--- a/ambari-web/app/assets/test/tests.js
+++ b/ambari-web/app/assets/test/tests.js
@@ -101,6 +101,7 @@ var files = ['test/init_model_test',
   'test/mappers/service_mapper_test',
   'test/mappers/status_mapper_test',
   'test/mappers/users_mapper_test',
+  'test/mappers/stack_mapper_test',
   'test/mixins/common/chart/storm_linear_time_test',
   'test/mixins/common/localStorage_test',
   'test/mixins/main/host/details/host_components/decommissionable_test',

http://git-wip-us.apache.org/repos/asf/ambari/blob/5a154221/ambari-web/app/config.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/config.js b/ambari-web/app/config.js
index c7bb9d0..563e547 100644
--- a/ambari-web/app/config.js
+++ b/ambari-web/app/config.js
@@ -27,7 +27,7 @@ App.alwaysGoToInstaller = false;
 App.testEnableSecurity = true; // By default enable security is tested; turning it false tests disable security
 App.testNameNodeHA = true;
 App.apiPrefix = '/api/v1';
-App.defaultStackVersion = 'HDP-2.0.5';
+App.defaultStackVersion = 'HDP-2.1';
 App.defaultJavaHome = '/usr/jdk/jdk1.6.0_31';
 App.timeout = 180000; // default AJAX timeout
 App.maxRetries = 3; // max number of retries for certain AJAX calls

http://git-wip-us.apache.org/repos/asf/ambari/blob/5a154221/ambari-web/app/controllers/installer.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/installer.js b/ambari-web/app/controllers/installer.js
index d6d6151..e09f116 100644
--- a/ambari-web/app/controllers/installer.js
+++ b/ambari-web/app/controllers/installer.js
@@ -37,7 +37,7 @@ App.InstallerController = App.WizardController.extend({
     configGroups: [],
     slaveGroupProperties: null,
     stacks: null,
-    clients:[],
+    clients: [],
     /**
      * recommendations for host groups loaded from server
      */
@@ -228,18 +228,14 @@ App.InstallerController = App.WizardController.extend({
   stackNames: [],
 
   /**
-   * Load stacks data from server or take exist data from local db
+   * Load stacks data from server or take exist data from in memory variable {{content.stacks}}
+   * The series of API calls will be called  When landing first time on Select Stacks page
+   * or on hitting refresh post select stacks page in installer wizard
    */
   loadStacks: function () {
-    var stacks = App.db.getStacks();
+    var stacks = this.get('content.stacks');
     var dfd = $.Deferred();
-    if (stacks && stacks.length) {
-      var convertedStacks = [];
-      stacks.forEach(function (stack) {
-        convertedStacks.pushObject(Ember.Object.create(stack));
-      });
-      App.set('currentStackVersion', convertedStacks.findProperty('isSelected').get('name'));
-      this.set('content.stacks', convertedStacks);
+    if (stacks && stacks.get('length')) {
       dfd.resolve(true);
     } else {
       App.ajax.send({
@@ -248,8 +244,8 @@ App.InstallerController = App.WizardController.extend({
         success: 'loadStacksSuccessCallback',
         error: 'loadStacksErrorCallback'
       }).complete(function () {
-          dfd.resolve(false);
-        });
+        dfd.resolve(false);
+      });
     }
     return dfd.promise();
   },
@@ -263,25 +259,6 @@ App.InstallerController = App.WizardController.extend({
   },
 
   /**
-   * set stacks from server to content and local DB
-   */
-  setStacks: function() {
-    var result = this.get('stacks');
-    if (!result.length) {
-      console.log('Error: there are no active stacks');
-    } else {
-      var defaultStackVersion = result.findProperty('name', App.defaultStackVersion);
-      if (defaultStackVersion) {
-        defaultStackVersion.set('isSelected', true)
-      } else {
-        result.objectAt(0).set('isSelected', true);
-      }
-    }
-    App.db.setStacks(result);
-    this.set('content.stacks', result);
-  },
-
-  /**
    * onError callback for loading stacks data
    */
   loadStacksErrorCallback: function () {
@@ -312,62 +289,27 @@ App.InstallerController = App.WizardController.extend({
    * Parse loaded data and create array of stacks objects
    */
   loadStacksVersionsSuccessCallback: function (data) {
-    var result = [];
-    var stackVersions = data.items.filterProperty('Versions.active');
-    stackVersions.sortProperty('Versions.stack_version').reverse().forEach(function (version) {
-      /*
-       * operatingSystems:[
-       *  {
-       *    osType: 'centos5',
-       *    baseUrl: 'http://...',
-       *    originalBaseUrl: 'http://...',
-       *    defaultBaseUrl: 'http://...',
-       *    latestBaseUrl: 'http://...',
-       *    mirrorsList: '';
-       *  },
-       *  {
-       *    osType: 'centos6',
-       *    baseUrl: 'http://...',
-       *    originalBaseUrl: 'http://...',
-       *    defaultBaseUrl: 'http://...',
-       *    latestBaseUrl: 'http://...',
-       *    mirrorsList: '';
-       *  },
-       * ]
-       */
-      var oses = [];
-      if (version.operatingSystems) {
-        version.operatingSystems.forEach(function (os) {
-          if (os.repositories) {
-            os.repositories.forEach(function (repo) {
-              var defaultBaseUrl = repo.Repositories.default_base_url || repo.Repositories.base_url;
-              var latestBaseUrl = repo.Repositories.latest_base_url || defaultBaseUrl;
-              if (!App.supports.ubuntu && os.OperatingSystems.os_type == 'ubuntu12') return; // @todo: remove after Ubuntu support confirmation
-              oses.push({
-                osType: os.OperatingSystems.os_type,
-                baseUrl: latestBaseUrl,
-                latestBaseUrl: latestBaseUrl,
-                originalLatestBaseUrl: latestBaseUrl,
-                originalBaseUrl: repo.Repositories.base_url,
-                defaultBaseUrl: defaultBaseUrl,
-                mirrorsList: repo.Repositories.mirrors_list,
-                id: os.OperatingSystems.os_type + repo.Repositories.repo_name,
-                repoId: repo.Repositories.repo_id,
-                selected: true
-              });
-            });
-          }
-        });
+    var stacks = App.db.getStacks();
+    var isStacksExistInDb = stacks && stacks.length;
+    if (isStacksExistInDb) {
+      stacks.forEach(function (_stack) {
+        var stack = data.items.filterProperty('Versions.stack_name', _stack.stack_name).findProperty('Versions.stack_version', _stack.stack_version);
+        if (stack) {
+          stack.Versions.is_selected = _stack.is_selected;
+        }
+      }, this);
+    }
+    App.stackMapper.map(data);
+    if (!isStacksExistInDb) {
+      var defaultStackVersion = App.Stack.find().findProperty('id', App.defaultStackVersion);
+      if (defaultStackVersion) {
+        defaultStackVersion.set('isSelected', true)
+      } else {
+        App.Stack.find().objectAt(0).set('isSelected', true);
       }
-      result.push(
-        Em.Object.create({
-          name: version.Versions.stack_name + "-" + version.Versions.stack_version,
-          isSelected: false,
-          operatingSystems: oses
-        })
-      );
-    }, this);
-    this.get('stacks').pushObjects(result);
+    }
+    this.set('content.stacks', App.Stack.find());
+    App.set('currentStackVersion', App.Stack.find().findProperty('isSelected').get('id'));
   },
 
   /**
@@ -412,6 +354,16 @@ App.InstallerController = App.WizardController.extend({
   },
 
   /**
+   * set stacks from server to content and local DB
+   */
+  setStacks: function () {
+    var result = App.Stack.find() || [];
+    Em.assert('Stack model is not populated', result.get('length'));
+    App.db.setStacks(result.slice());
+    this.set('content.stacks', result);
+  },
+
+  /**
    * Save data to model
    * @param stepController App.WizardStep4Controller
    */
@@ -479,15 +431,15 @@ App.InstallerController = App.WizardController.extend({
     this.set("content.masterComponentHosts", masterComponentHosts);
   },
 
-  loadRecommendations: function() {
+  loadRecommendations: function () {
     this.set("content.recommendations", this.getDBProperty('recommendations'));
   },
 
-  loadCurrentHostGroups: function() {
+  loadCurrentHostGroups: function () {
     this.set("content.recommendationsHostGroups", this.getDBProperty('recommendationsHostGroups'));
   },
 
-  loadRecommendationsConfigs: function() {
+  loadRecommendationsConfigs: function () {
     App.router.set("wizardStep7Controller.recommendationsConfigs", this.getDBProperty('recommendationsConfigs'));
   },
 
@@ -545,77 +497,66 @@ App.InstallerController = App.WizardController.extend({
   },
 
   /**
-   * Save stacks data to local db
-   * @param stepController step1WizardController
-   */
-  saveStacks: function (stepController) {
-    var stacks = stepController.get('content.stacks');
-    if (stacks.length) {
-      App.set('currentStackVersion', stacks.findProperty('isSelected').get('name'));
-    } else {
-      App.set('currentStackVersion', App.defaultStackVersion);
-    }
-    App.db.setStacks(stacks);
-    this.set('content.stacks', stacks);
-  },
-
-  /**
    * Check validation of the customized local urls
    */
-  checkRepoURL: function () {
+  checkRepoURL: function (wizardStep1Controller) {
     var selectedStack = this.get('content.stacks').findProperty('isSelected', true);
     selectedStack.set('reload', true);
-    var nameVersionCombo = selectedStack.name;
+    var nameVersionCombo = selectedStack.get('id');
     var stackName = nameVersionCombo.split('-')[0];
     var stackVersion = nameVersionCombo.split('-')[1];
-    if (selectedStack && selectedStack.operatingSystems) {
-      this.set('validationCnt', selectedStack.get('operatingSystems').filterProperty('selected', true).length);
-      this.set('invalidCnt', 0);
-      selectedStack.operatingSystems.forEach(function (os) {
-        os.errorTitle = null;
-        os.errorContent = null;
-        var verifyBaseUrl = os.skipValidation ? false : true;
-        if (os.selected) {
-          os.validation = 'icon-repeat';
-          selectedStack.set('reload', !selectedStack.get('reload'));
-          App.ajax.send({
-            name: 'wizard.advanced_repositories.valid_url',
-            sender: this,
-            data: {
-              stackName: stackName,
-              stackVersion: stackVersion,
-              repoId: os.repoId,
-              osType: os.osType,
-              osId: os.id,
+    var dfd = $.Deferred();
+    if (selectedStack && selectedStack.get('operatingSystems')) {
+      this.set('validationCnt', selectedStack.get('repositories').filterProperty('isSelected').length);
+      var verifyBaseUrl = !wizardStep1Controller.get('skipValidationChecked');
+      selectedStack.get('operatingSystems').forEach(function (os) {
+        if (os.get('isSelected')) {
+          os.get('repositories').forEach(function (repo) {
+            repo.set('errorTitle', '');
+            repo.set('errorContent', '');
+            repo.set('validation', App.Repository.validation['INPROGRESS']);
+            App.ajax.send({
+              name: 'wizard.advanced_repositories.valid_url',
+              sender: this,
               data: {
-                'Repositories': {
-                  'base_url': os.baseUrl,
-                  "verify_base_url": verifyBaseUrl
+                stackName: stackName,
+                stackVersion: stackVersion,
+                repoId: repo.get('repoId'),
+                osType: os.get('osType'),
+                osId: os.get('id'),
+                dfd: dfd,
+                data: {
+                  'Repositories': {
+                    'base_url': repo.get('baseUrl'),
+                    "verify_base_url": verifyBaseUrl
+                  }
                 }
-              }
-            },
-            success: 'checkRepoURLSuccessCallback',
-            error: 'checkRepoURLErrorCallback'
-          });
+              },
+              success: 'checkRepoURLSuccessCallback',
+              error: 'checkRepoURLErrorCallback'
+            });
+          }, this);
         }
       }, this);
     }
+    return dfd.promise();
   },
-  setInvalidUrlCnt: function () {
-    var selectedStack = this.get('content.stacks').findProperty('isSelected', true);
-    selectedStack.set('invalidCnt', this.get('invalidCnt'));
-  }.observes('invalidCnt'),
   /**
    * onSuccess callback for check Repo URL.
    */
   checkRepoURLSuccessCallback: function (response, request, data) {
     console.log('Success in check Repo URL. data osType: ' + data.osType);
-    var selectedStack = this.get('content.stacks').findProperty('isSelected', true);
-    if (selectedStack && selectedStack.operatingSystems) {
-      var os = selectedStack.operatingSystems.findProperty('id', data.osId);
-      os.validation = 'icon-ok';
-      selectedStack.set('reload', !selectedStack.get('reload'));
-      this.set('validationCnt', this.get('validationCnt') - 1);
+    var selectedStack = this.get('content.stacks').findProperty('isSelected');
+    if (selectedStack && selectedStack.get('operatingSystems')) {
+      var os = selectedStack.get('operatingSystems').findProperty('id', data.osId);
+      var repo = os.get('repositories').findProperty('repoId', data.repoId);
+      if (repo) {
+        repo.set('validation', App.Repository.validation['OK']);
+      }
+    }
+    this.set('validationCnt', this.get('validationCnt') - 1);
+    if (!this.get('validationCnt')) {
+      data.dfd.resolve();
     }
   },
 
@@ -625,15 +566,16 @@ App.InstallerController = App.WizardController.extend({
   checkRepoURLErrorCallback: function (request, ajaxOptions, error, data, params) {
     console.log('Error in check Repo URL. The baseURL sent is:  ' + data.data);
     var selectedStack = this.get('content.stacks').findProperty('isSelected', true);
-    if (selectedStack && selectedStack.operatingSystems) {
-      var os = selectedStack.operatingSystems.findProperty('id', params.osId);
-      os.validation = 'icon-exclamation-sign';
-      os.errorTitle = request.status + ":" + request.statusText;
-      os.errorContent = $.parseJSON(request.responseText) ? $.parseJSON(request.responseText).message : "";
-      selectedStack.set('reload', !selectedStack.get('reload'));
-      this.set('validationCnt', this.get('validationCnt') - 1);
-      this.set('invalidCnt', this.get('invalidCnt') + 1);
+    if (selectedStack && selectedStack.get('operatingSystems')) {
+      var os = selectedStack.get('operatingSystems').findProperty('id', params.osId);
+      var repo = os.get('repositories').findProperty('repoId', params.repoId);
+      if (repo) {
+        repo.set('validation', App.Repository.validation['INVALID']);
+        repo.set('errorTitle', request.status + ":" + request.statusText);
+        repo.set('errorContent', $.parseJSON(request.responseText) ? $.parseJSON(request.responseText).message : "");
+      }
     }
+    params.dfd.reject();
   },
 
   loadMap: {
@@ -667,14 +609,6 @@ App.InstallerController = App.WizardController.extend({
 
           return dfd.promise();
         }
-      },
-      {
-        type: 'sync',
-        callback: function (stacksLoaded) {
-          if (!stacksLoaded) {
-            this.setStacks();
-          }
-        }
       }
     ],
     '2': [

http://git-wip-us.apache.org/repos/asf/ambari/blob/5a154221/ambari-web/app/controllers/wizard/step1_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/wizard/step1_controller.js b/ambari-web/app/controllers/wizard/step1_controller.js
index 0ae3165..34e121e 100644
--- a/ambari-web/app/controllers/wizard/step1_controller.js
+++ b/ambari-web/app/controllers/wizard/step1_controller.js
@@ -20,6 +20,16 @@ var App = require('app');
 
 App.WizardStep1Controller = Em.Controller.extend({
 
-  name: 'wizardStep1Controller'
+  name: 'wizardStep1Controller',
+  /**
+   * Skip repo-validation
+   * @type {bool}
+   */
+  skipValidationChecked: false,
+
+  selectedStack: function() {
+    return App.Stack.find().findProperty('isSelected');
+  }.property('content.stacks.@each.isSelected')
+
 
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/5a154221/ambari-web/app/controllers/wizard/step8_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/wizard/step8_controller.js b/ambari-web/app/controllers/wizard/step8_controller.js
index f8021c4..185420a 100644
--- a/ambari-web/app/controllers/wizard/step8_controller.js
+++ b/ambari-web/app/controllers/wizard/step8_controller.js
@@ -561,16 +561,18 @@ App.WizardStep8Controller = Em.Controller.extend(App.AddSecurityConfigs, {
       this.loadRepoInfo();
     } else {
       // from install wizard
-      var selectedStack = this.get('content.stacks').findProperty('isSelected', true);
+      var selectedStack = App.Stack.find().findProperty('isSelected');
       var allRepos = [];
-      if (selectedStack && selectedStack.operatingSystems) {
-        selectedStack.operatingSystems.forEach(function (os) {
-          if (os.selected) {
-            allRepos.push(Em.Object.create({
-              base_url: os.baseUrl,
-              os_type: os.osType,
-              repo_id: os.repoId
-            }));
+      if (selectedStack && selectedStack.get('operatingSystems')) {
+        selectedStack.get('operatingSystems').forEach(function (os) {
+          if (os.get('isSelected')) {
+            os.get('repositories').forEach(function(repo) {
+              allRepos.push(Em.Object.create({
+                base_url: repo.get('baseUrl'),
+                os_type: repo.get('osType'),
+                repo_id: repo.get('repoId')
+              }));  
+            }, this);
           }
         }, this);
       }
@@ -966,7 +968,6 @@ App.WizardStep8Controller = Em.Controller.extend(App.AddSecurityConfigs, {
 
   deleteClustersCallback: function (response, request, data) {
     if (data.isLast) {
-      this.setLocalRepositories();
       this.createCluster();
       this.createSelectedServices();
       if (this.get('content.controllerName') !== 'addHostController') {
@@ -993,37 +994,6 @@ App.WizardStep8Controller = Em.Controller.extend(App.AddSecurityConfigs, {
     }
   },
 
-  /**
-   * Updates local repositories for the Ambari server.
-   * @method setLocalRepositories
-   * @return {bool} true - requests are sent, false - requests not sent
-   */
-  setLocalRepositories: function () {
-    if (this.get('content.controllerName') !== 'installerController' || !App.get('supports.localRepositories')) return false;
-    var self = this,
-      stack = this.get('content.stacks').findProperty('isSelected', true);
-    stack.operatingSystems.forEach(function (os) {
-      if (os.baseUrl !== os.originalBaseUrl) {
-        console.log("Updating local repository URL from " + os.originalBaseUrl + " -> " + os.baseUrl + ". ", os);
-        self.addRequestToAjaxQueue({
-          name: 'wizard.step8.set_local_repos',
-          data: {
-            osType: os.osType,
-            repoId: os.repoId,
-            stackVersionURL: App.get('stackVersionURL'),
-            data: JSON.stringify({
-              "Repositories": {
-                "base_url": os.baseUrl,
-                "verify_base_url": false
-              }
-            })
-          }
-        });
-      }
-    });
-    return true;
-  },
-
 
   /**
    * *******************************************************************

http://git-wip-us.apache.org/repos/asf/ambari/blob/5a154221/ambari-web/app/mappers.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mappers.js b/ambari-web/app/mappers.js
index aa7aea0..9300d1a 100644
--- a/ambari-web/app/mappers.js
+++ b/ambari-web/app/mappers.js
@@ -19,6 +19,7 @@
 //load all mappers
 require('mappers/server_data_mapper');
 require('mappers/stack_service_mapper');
+require('mappers/stack_mapper');
 require('mappers/hosts_mapper');
 require('mappers/jobs_mapper');
 require('mappers/cluster_mapper');

http://git-wip-us.apache.org/repos/asf/ambari/blob/5a154221/ambari-web/app/mappers/stack_mapper.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mappers/stack_mapper.js b/ambari-web/app/mappers/stack_mapper.js
new file mode 100644
index 0000000..8319f87
--- /dev/null
+++ b/ambari-web/app/mappers/stack_mapper.js
@@ -0,0 +1,114 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+var App = require('app');
+
+App.stackMapper = App.QuickDataMapper.create({
+  modelStack: App.Stack,
+  modelOS: App.OperatingSystem,
+  modelRepo: App.Repository,
+  
+  configStack: {
+    id: 'id',
+    stack_name: 'stack_name',
+    stack_version: 'stack_version',
+    active: 'active',
+    parent_stack_version: 'parent_stack_version',
+    min_upgrade_version: 'min_upgrade_version',
+    is_selected: 'is_selected',
+    config_types: 'config_types',
+    operating_systems_key: 'operating_systems',
+    operating_systems_type: 'array',
+    operating_systems: {
+      item: 'id'
+    }
+  },
+  
+  configOS: {
+    id: 'id',
+    os_type: 'os_type',
+    stack_name: 'stack_name',
+    stack_version: 'stack_version',
+    stack_id: 'stack_id',
+    repositories_key: 'repositories',
+    repositories_type: 'array',
+    repositories: {
+      item: 'id'
+    }
+  },
+  
+  configRepository: {
+    id: 'id',
+    base_url: 'base_url',
+    default_base_url: 'default_base_url',
+    latest_base_url: 'latest_base_url',
+    mirrors_list: 'mirrors_list',
+    os_type: 'os_type',
+    repo_id: 'repo_id',
+    repo_name: 'repo_name',
+    stack_name: 'stack_name',
+    stack_version: 'stack_version',
+    operating_system_id: 'os_id'
+  },
+  
+  map: function(json) {
+    var modelStack = this.get('modelStack');
+    var modelOS = this.get('modelOS');
+    var modelRepo = this.get('modelRepo');
+    var resultStack = [];
+    var resulOS = [];
+    var resultRepo = [];
+
+    var stackVersions =   json.items.filterProperty('Versions.active');
+    stackVersions.sortProperty('Versions.stack_version').reverse().forEach(function(item) {
+      var stack = item.Versions;
+      var operatingSystemsArray = [];
+
+      stack.id = stack.stack_name + "-" + stack.stack_version;
+
+      item.operatingSystems.forEach(function(ops) {
+        var operatingSystems = ops.OperatingSystems;
+
+        var repositoriesArray = [];
+        ops.repositories.forEach(function(repo) {
+          repo.Repositories.id = repo.Repositories.os_type + "-" + repo.Repositories.repo_id;
+          repo.Repositories.os_id = repo.Repositories.stack_name + "-" + repo.Repositories.stack_version + "-" + repo.Repositories.os_type;
+          resultRepo.push(this.parseIt(repo.Repositories, this.get('configRepository')));
+          repositoriesArray.pushObject(repo.Repositories);
+        }, this);
+
+
+        operatingSystems.id = operatingSystems.stack_name + "-" + operatingSystems.stack_version + "-" + operatingSystems.os_type;
+        operatingSystems.stack_id = operatingSystems.stack_name + "-" + operatingSystems.stack_version;
+        operatingSystems.repositories = repositoriesArray;
+        resulOS.push(this.parseIt(operatingSystems, this.get('configOS')));
+        operatingSystemsArray.pushObject(operatingSystems);
+        
+      }, this);
+      
+
+      stack.operating_systems = operatingSystemsArray;
+      resultStack.push(this.parseIt(stack, this.get('configStack')));
+      
+    }, this);
+
+    App.store.loadMany(modelRepo, resultRepo);
+    App.store.loadMany(modelOS, resulOS);
+    App.store.loadMany(modelStack, resultStack);
+
+  }
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/5a154221/ambari-web/app/mappers/stack_service_mapper.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mappers/stack_service_mapper.js b/ambari-web/app/mappers/stack_service_mapper.js
index e74308d..04860b5 100644
--- a/ambari-web/app/mappers/stack_service_mapper.js
+++ b/ambari-web/app/mappers/stack_service_mapper.js
@@ -23,6 +23,7 @@ App.stackServiceMapper = App.QuickDataMapper.create({
 
   config: {
     id: 'service_name',
+    stack_id: 'stack_id',
     service_name: 'service_name',
     display_name: 'display_name',
     config_types: 'config_types',
@@ -84,6 +85,7 @@ App.stackServiceMapper = App.QuickDataMapper.create({
           serviceComponents.push(serviceComponent.StackServiceComponents);
           stackServiceComponents.push(this.parseIt(serviceComponent.StackServiceComponents, this.get('component_config')));
         }, this);
+        stackService.stack_id = stackService.stack_name + '-' + stackService.stack_version;
         stackService.service_components = serviceComponents;
         result.push(this.parseIt(stackService, this.get('config')));
       }

http://git-wip-us.apache.org/repos/asf/ambari/blob/5a154221/ambari-web/app/models.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models.js b/ambari-web/app/models.js
index 49b0498..c127515 100644
--- a/ambari-web/app/models.js
+++ b/ambari-web/app/models.js
@@ -24,6 +24,9 @@ require('models/authentication');
 require('models/cluster');
 require('models/cluster_states');
 require('models/hosts');
+require('models/stack');
+require('models/operating_system');
+require('models/repository');
 require('models/stack_service');
 require('models/stack_service_component');
 require('models/quick_links');

http://git-wip-us.apache.org/repos/asf/ambari/blob/5a154221/ambari-web/app/models/operating_system.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/operating_system.js b/ambari-web/app/models/operating_system.js
new file mode 100644
index 0000000..9fa221a
--- /dev/null
+++ b/ambari-web/app/models/operating_system.js
@@ -0,0 +1,33 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+var App = require('app');
+
+App.OperatingSystem = DS.Model.extend({
+  id:  DS.attr('string'), // This is ${stackName}-${stackVersion}-${osType}.
+  osType: DS.attr('string'),
+  stackName: DS.attr('string'),
+  stackVersion: DS.attr('string'),
+  repositories: DS.hasMany('App.Repository'),
+  stack: DS.belongsTo('App.Stack'),
+  isSelected: DS.attr('boolean', {defaultValue: true})
+});
+
+
+App.OperatingSystem.FIXTURES = [];
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/5a154221/ambari-web/app/models/repository.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/repository.js b/ambari-web/app/models/repository.js
new file mode 100644
index 0000000..16d245f
--- /dev/null
+++ b/ambari-web/app/models/repository.js
@@ -0,0 +1,67 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+var App = require('app');
+
+App.Repository = DS.Model.extend({
+  id:  DS.attr('string'), // This is ${osType}-${repoId}.
+  repoId: DS.attr('string'),
+  osType: DS.attr('string'),
+  baseUrl: DS.attr('string'),
+  defaultBaseUrl: DS.attr('string'),
+  latestBaseUrl: DS.attr('string'),
+  repoName: DS.attr('string'),
+  stackName: DS.attr('string'),
+  stackVersion: DS.attr('string'),
+  operatingSystem: DS.belongsTo('App.OperatingSystem'),
+
+  validation: DS.attr('string', {defaultValue: ''}),
+  errorContent: DS.attr('string', {defaultValue: ''}),
+  errorTitle: DS.attr('string', {defaultValue: ''}),
+
+  isSelected: function() {
+    return this.get('operatingSystem.isSelected');
+  }.property('id'),
+
+  emptyError: function() {
+    return !this.get('baseUrl');
+  }.property('baseUrl'),
+
+  invalidError: function() {
+    return this.get('validation') == App.Repository.validation['INVALID'];
+  }.property('validation'),
+
+  undo: function() {
+    return this.get('baseUrl') != this.get('latestBaseUrl');
+  }.property('baseUrl','latestBaseUrl'),
+
+  clearAll: function() {
+    return this.get('baseUrl')
+  }.property('baseUrl')
+});
+
+App.Repository.validation = {
+  PENDING: '',
+  INVALID: 'icon-exclamation-sign',
+  OK: 'icon-ok',
+  INPROGRESS: 'icon-repeat'
+};
+
+
+App.Repository.FIXTURES = [];
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/5a154221/ambari-web/app/models/stack.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/stack.js b/ambari-web/app/models/stack.js
new file mode 100644
index 0000000..e6cd0d8
--- /dev/null
+++ b/ambari-web/app/models/stack.js
@@ -0,0 +1,70 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var App = require('app');
+
+App.Stack = DS.Model.extend({
+  id: DS.attr('string'), //  ${stackName}-${stackVersion}.
+  stackName: DS.attr('string'),
+  stackVersion: DS.attr('string'),
+  active: DS.attr('boolean'),  // All of the instances should have this value to true. We should map only those stacks that has active flag set to true
+  parentStackVersion: DS.attr('string'),
+  minUpgradeVersion: DS.attr('string'),
+  configTypes: DS.attr('object'),
+  operatingSystems: DS.hasMany('App.OperatingSystem'),
+  isSelected: DS.attr('boolean', {defaultValue: false}),
+
+  /**
+   * @return: {Array} returns supported repositories for all OperatingSystem's supported by a stack instance
+   */
+  repositories: function () {
+    var operatingSystems = this.get('operatingSystems');
+    var repositories = [];
+    operatingSystems.forEach(function (os) {
+      os.get('repositories').forEach(function (repository) {
+        repositories.pushObject(repository);
+      }, this);
+    }, this);
+    return repositories;
+  }.property('id'),
+
+  /**
+   * @return: {Array} App.StackService instances for selected stack instance. For non-selected stack instance returns empty array
+   */
+  services: function () {
+    var result = [];
+    var isStackSelected = this.get('isSelected');
+    var stackServices = App.StackService.find().get('length');
+    if (isStackSelected && stackServices) {
+      result = App.StackService.find();
+    }
+    return result;
+  }.property('isSelected'),
+
+  /**
+   * Right now there ambari-web is not fetching this information from the server as it does not need as of present.
+   * @TODO: This should return stack level configurations for selected stack instance i.e properties of cluster-env file
+   */
+  configurations: function() {
+    return [];
+  }.property('isSelected')
+
+});
+
+
+App.Stack.FIXTURES = [];

http://git-wip-us.apache.org/repos/asf/ambari/blob/5a154221/ambari-web/app/models/stack_service.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/stack_service.js b/ambari-web/app/models/stack_service.js
index 55878ec..d4b7e68 100644
--- a/ambari-web/app/models/stack_service.js
+++ b/ambari-web/app/models/stack_service.js
@@ -47,6 +47,7 @@ App.StackService = DS.Model.extend({
   stackVersion: DS.attr('string'),
   isSelected: DS.attr('boolean', {defaultValue: true}),
   isInstalled: DS.attr('boolean', {defaultValue: false}),
+  stack: DS.belongsTo('App.Stack'),
   serviceComponents: DS.hasMany('App.StackServiceComponent'),
   configs: DS.attr('array'),
   requiredServices: DS.attr('array'),

http://git-wip-us.apache.org/repos/asf/ambari/blob/5a154221/ambari-web/app/routes/installer.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/routes/installer.js b/ambari-web/app/routes/installer.js
index 2a081ea..8042093 100644
--- a/ambari-web/app/routes/installer.js
+++ b/ambari-web/app/routes/installer.js
@@ -127,6 +127,8 @@ module.exports = Em.Route.extend({
     next: function (router) {
       var installerController = router.get('installerController');
       installerController.save('cluster');
+      App.db.setStacks(undefined);
+      installerController.set('content.stacks',undefined);
       router.transitionTo('step1');
     }
   }),
@@ -145,28 +147,12 @@ module.exports = Em.Route.extend({
     next: function (router) {
       var wizardStep1Controller = router.get('wizardStep1Controller');
       var installerController = router.get('installerController');
-      if (App.get('testMode')) {
-        installerController.set('validationCnt', 0);
-        installerController.set('invalidCnt', 0);
-      } else {
-        installerController.checkRepoURL();
-      }
-      // make sure got all validations feedback and no invalid url, then proceed
-      var myVar = setInterval(
-        function () {
-          var cnt = installerController.get('validationCnt');
-          var invalidCnt = installerController.get('invalidCnt');
-          if (cnt == 0 && invalidCnt == 0) { // all feedback exist and no invalid url
-            installerController.saveStacks(wizardStep1Controller);
-            installerController.setDBProperty('service', undefined);
-            installerController.clearInstallOptions();
-            router.transitionTo('step2');
-            clearInterval(myVar);
-          } else if (cnt == 0 && invalidCnt != 0) {
-            clearInterval(myVar);
-          }
-        },
-        1000);
+      installerController.checkRepoURL(wizardStep1Controller).done(function () {
+        installerController.setDBProperty('service', undefined);
+        installerController.setStacks();
+        installerController.clearInstallOptions();
+        router.transitionTo('step2');
+      });
     }
   }),
 
@@ -301,7 +287,7 @@ module.exports = Em.Route.extend({
       var wizardStep7Controller = router.get('wizardStep7Controller');
 
       if (!wizardStep6Controller.get('submitDisabled')) {
-        wizardStep6Controller.showValidationIssuesAcceptBox(function() {
+        wizardStep6Controller.showValidationIssuesAcceptBox(function () {
           controller.saveSlaveComponentHosts(wizardStep6Controller);
           controller.get('content').set('serviceConfigProperties', null);
           controller.setDBProperty('serviceConfigProperties', null);

http://git-wip-us.apache.org/repos/asf/ambari/blob/5a154221/ambari-web/app/templates/wizard/step1.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/wizard/step1.hbs b/ambari-web/app/templates/wizard/step1.hbs
index d13922a..b1e323f 100644
--- a/ambari-web/app/templates/wizard/step1.hbs
+++ b/ambari-web/app/templates/wizard/step1.hbs
@@ -52,24 +52,24 @@
               <div class="th url-th">{{t installer.step1.advancedRepo.localRepo.column.baseUrl}}</div>
             </div>
             <div class="tbody">
-              {{#each repoGroup in view.allRepositoriesGroups}}
+              {{#each operatingSystem in view.operatingSystems}}
                 <div class="trow">
                   <div class="os-td">
                     <label>
-                      {{view Ember.Checkbox checkedBinding="repoGroup.checked"}}
-                      <span {{bindAttr class=":os repoGroup.checked::disabled-label"}}>{{repoGroup.name}}</span>
+                      {{view Ember.Checkbox checkedBinding="operatingSystem.isSelected"}}
+                      <span {{bindAttr class=":os operatingSystem.isSelected::disabled-label"}}>{{operatingSystem.osType}}</span>
                     </label>
                   </div>
                   <div style="width:83%">
-                    {{#each repository in repoGroup.repositories}}
+                    {{#each repository in operatingSystem.repositories}}
                         <div class="sub-trow">
                           <div class="name-td">{{repository.repoId}}</div>
                           <div class="validation-td">
                             {{#if repository.validation}}
-                              {{view view.popoverView repoGroupBinding="repository"}}
+                              {{view view.popoverView repositoryBinding="repository"}}
                             {{/if}}
                           </div>
-                          <div {{bindAttr class=":url-td repoGroup.checked::disabled-textfield repository.empty-error:textfield-error repository.invalid-error:textfield-error"}}>
+                          <div {{bindAttr class=":url-td operatingSystem.isSelected::disabled-textfield repository.emptyError:textfield-error repository.invalidError:textfield-error"}}>
                             {{view Ember.TextField valueBinding="repository.baseUrl"}}
                           </div>
                           <div class="clear-td">
@@ -94,7 +94,7 @@
             </div>
           </div>
           <div id="skip-validation">
-            <label>{{view Ember.Checkbox checkedBinding="view.skipValidationChecked" class="checkbox"}}{{t installer.step1.advancedRepo.skipValidation.message}}
+            <label>{{view Ember.Checkbox checkedBinding="skipValidationChecked" class="checkbox"}}{{t installer.step1.advancedRepo.skipValidation.message}}
               <i class="icon-question-sign" rel="skip-validation-tooltip"
                  data-toggle="tooltip" {{translateAttr title="installer.step1.advancedRepo.skipValidation.tooltip"}}></i></label>
           </div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/5a154221/ambari-web/app/views/wizard/step1_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/wizard/step1_view.js b/ambari-web/app/views/wizard/step1_view.js
index 9fe3120..886543e 100644
--- a/ambari-web/app/views/wizard/step1_view.js
+++ b/ambari-web/app/views/wizard/step1_view.js
@@ -21,96 +21,97 @@ App.WizardStep1View = Em.View.extend({
 
   templateName: require('templates/wizard/step1'),
 
+  didInsertElement: function () {
+    if (this.get('isRLCollapsed')) {
+      this.$('.accordion-body').hide();
+    }
+    $("[rel=skip-validation-tooltip]").tooltip({ placement: 'right'});
+  },
+
   /**
    * List of available stacks
    * @type {Em.Object[]}
    */
   stacks: function () {
-    return this.get('controller.content.stacks').map(function (stack) {
+    return this.get('controller.content.stacks').toArray().map(function (stack) {
       return Em.Object.create({
-        name: stack.get('name').replace('-', ' '),
+        name: stack.get('id').replace('-', ' '),
         isSelected: stack.get('isSelected')
       });
     });
-  }.property('controller.content.stacks.@each.isSelected'),
+  }.property('controller.selectedStack'),
 
-  /**
-   * List of all repositories
-   * @type {Array}
-   */
-  allRepositories: [],
+  operatingSystems: function () {
+    var selectedStack = this.get('controller.selectedStack');
+    var result = [];
+    if (!!selectedStack)
+      result = selectedStack.get('operatingSystems');
+    return result;
+  }.property('controller.selectedStack'),
 
   /**
-   * List of all repo-groups
-   * @type {Array}
+   * List of all repositories under selected stack operatingSystems
+   * API and ember data model structure:
+   * stack = [{OS-1},{OS-2}]
+   * OS-1 = [{repository-1},{repository-2}]
+   * OS-2 = [{repository-3},{repository-4}]
+   * @return: [{repository-1},{repository-2},{repository-3},{repository-4}]
    */
-  allRepositoriesGroups: function () {
+  allRepositories: function () {
+    var selectedStack = this.get('controller.selectedStack');
     var result = [];
-    var stacks = this.get('controller.content.stacks');
-    if (stacks && stacks.length) {
-      var selectedStack = stacks.findProperty('isSelected', true);
-      var allRepositories = this.get('allRepositories');
-      var OSNames = allRepositories.mapProperty('osType').uniq();
-      OSNames.forEach(function (os) {
-        result.push(Ember.Object.create({
-          checked: selectedStack.operatingSystems.findProperty('osType', os).selected,
-          name: os,
-          repositories: allRepositories.filterProperty('osType', os)
-        }));
-      });
-    }
+    if (!!selectedStack)
+      result = selectedStack.get('repositories');
     return result;
-  }.property('allRepositories.length', 'controller.content.stacks'),
+  }.property('controller.selectedStack'),
 
   /**
    * Verify if some repo has empty base-url
    * @type {bool}
    */
   emptyRepoExist: function () {
-    return this.get('allRepositories').someProperty('empty-error', true);
-  }.property('allRepositories.@each.empty-error'),
+    return this.get('allRepositories').someProperty('emptyError', true);
+  }.property('allRepositories.@each.emptyError'),
 
   /**
    * Disable submit button flag
    * @type {bool}
    */
   isSubmitDisabled: function () {
-    return this.get('emptyRepoExist') || this.get('allRepoUnchecked') || this.get('invalidUrlExist');
-  }.property('emptyRepoExist', 'allRepoUnchecked', 'invalidUrlExist'),
+    return this.get('emptyRepoExist') || this.get('isNoOsChecked') || this.get('invalidUrlExist');
+  }.property('emptyRepoExist', 'isNoOsChecked', 'invalidUrlExist'),
 
   /**
    * Verify if some invalid repo-urls exist
    * @type {bool}
    */
   invalidUrlExist: function () {
-    var selectedStack = this.get('controller.content.stacks').findProperty('isSelected', true);
-    var invalidExist = this.get('allRepositories').someProperty('validation', 'icon-exclamation-sign');
-    return (selectedStack.get('invalidCnt') > 0) && invalidExist;
-  }.property('controller.content.stacks.@each.invalidCnt', 'allRepositories.@each.validation'),
+    return this.get('allRepositories').someProperty('validation', App.Repository.validation['INVALID']);
+  }.property('allRepositories.@each.validation'),
 
   /**
    * If all repo links are unchecked
    * @type {bool}
    */
-  allRepoUnchecked: function () {
-    return !this.get('allRepositoriesGroups').someProperty('checked', true);
-  }.property('allRepositoriesGroups.@each.checked'),
+  isNoOsChecked: function () {
+    return this.get('operatingSystems').everyProperty('isSelected', false);
+  }.property('operatingSystems.@each.isSelected'),
 
   /**
    * Overall errors count
    * @type {number}
    */
   totalErrorCnt: function () {
-    var emptyCnt = this.get('allRepositories').filterProperty('empty-error', true).length;
-    var invalidCnt = this.get('allRepositories').filterProperty('validation', 'icon-exclamation-sign').length;
-    if (this.get('allRepoUnchecked')) {
+    var emptyCnt = this.get('allRepositories').filterProperty('emptyError').length;
+    var invalidCnt = this.get('allRepositories').filterProperty('validation', App.Repository.validation['INVALID']).length;
+    if (this.get('isNoOsChecked')) {
       return 1;
     } else if (emptyCnt || invalidCnt) {
       return emptyCnt + invalidCnt;
     } else {
       return 0;
     }
-  }.property('allRepositories.@each.empty-error', 'allRepoUnchecked', 'allRepositories.@each.validation'),
+  }.property('allRepositories.@each.emptyError', 'isNoOsChecked', 'allRepositories.@each.validation'),
 
   /**
    * Is Repositories Accordion collapsed
@@ -119,19 +120,6 @@ App.WizardStep1View = Em.View.extend({
   isRLCollapsed: true,
 
   /**
-   * Skip repo-validation
-   * @type {bool}
-   */
-  skipValidationChecked: false,
-
-  didInsertElement: function () {
-    if (this.get('isRLCollapsed')) {
-      this.$('.accordion-body').hide();
-    }
-    $("[rel=skip-validation-tooltip]").tooltip({ placement: 'right'});
-  },
-
-  /**
    * Checkbox for each stack
    * @type {Ember.Checkbox}
    */
@@ -145,7 +133,7 @@ App.WizardStep1View = Em.View.extend({
 
     click: function () {
       this.get('controller.content.stacks').setEach('isSelected', false);
-      this.get('controller.content.stacks').findProperty('name', this.get('content.name').replace(' ', '-')).set('isSelected', true);
+      this.get('controller.content.stacks').findProperty('id', this.get('content.name').replace(' ', '-')).set('isSelected', true);
     }
   }),
 
@@ -155,8 +143,8 @@ App.WizardStep1View = Em.View.extend({
    */
   popoverView: Em.View.extend({
     tagName: 'i',
-    classNameBindings: ['repoGroup.validation'],
-    attributeBindings: ['repoGroup.errorTitle:title', 'repoGroup.errorContent:data-content'],
+    classNameBindings: ['repository.validation'],
+    attributeBindings: ['repository.errorTitle:title', 'repository.errorContent:data-content'],
     didInsertElement: function () {
       App.popover($(this.get('element')), {'trigger': 'hover'});
     }
@@ -175,37 +163,9 @@ App.WizardStep1View = Em.View.extend({
    * Onclick handler for recheck repos urls. Used in Advanced Repository Options.
    */
   retryRepoUrls: function () {
-    App.router.get('installerController').checkRepoURL();
+    App.router.get('installerController').checkRepoURL(this.get('controller'));
   },
 
-  /**
-   * Format repo values and set it to <code>allRepositories</code>
-   * @method loadRepositories
-   */
-  loadRepositories: function () {
-    var selectedStack = this.get('controller.content.stacks').findProperty('isSelected', true);
-    var repos = [];
-    if (selectedStack && selectedStack.operatingSystems) {
-      selectedStack.operatingSystems.forEach(function (os) {
-        repos.push(Ember.Object.create({
-          'id': os.id,
-          'repoId': os.repoId,
-          'baseUrl': os.baseUrl,
-          'osType': os.osType,
-          'latestBaseUrl': os.latestBaseUrl,
-          'defaultBaseUrl': os.defaultBaseUrl,
-          'empty-error': !os.baseUrl,
-          'invalid-error': os.validation == 'icon-exclamation-sign',
-          'validation': os.validation,
-          'undo': os.baseUrl != os.latestBaseUrl,
-          'clearAll': os.baseUrl,
-          'errorTitle': os.errorTitle,
-          'errorContent': os.errorContent
-        }));
-      }, this);
-    }
-    this.set('allRepositories', repos);
-  }.observes('controller.content.stacks.@each.isSelected', 'controller.content.stacks.@each.reload'),
 
   /**
    * Onclick handler for checkbox of each repo group
@@ -213,37 +173,24 @@ App.WizardStep1View = Em.View.extend({
    */
   updateByCheckbox: function () {
     //upload to content
-    var repos = this.get('allRepositories');
-    var selectedStack = this.get('controller.content.stacks').findProperty('isSelected', true);
-    var allRepositoriesGroups = this.get('allRepositoriesGroups');
-    if (selectedStack && selectedStack.operatingSystems) {
-      selectedStack.operatingSystems.forEach(function (os) {
-        var targetRepo = repos.findProperty('id', os.id);
-        var repoGroup = allRepositoriesGroups.findProperty('name', targetRepo.get('osType'));
-        if (repoGroup && !repoGroup.get('checked')) {
-          os.baseUrl = os.latestBaseUrl;
-          os.validation = null;
-          os.selected = false;
-          targetRepo.set('baseUrl', os.latestBaseUrl);
-          targetRepo.set('latestBaseUrl', os.latestBaseUrl);
-          targetRepo.set('undo', targetRepo.get('baseUrl') != targetRepo.get('latestBaseUrl'));
-          targetRepo.set('invalid-error', false);
-          targetRepo.set('validation', null);
-          targetRepo.set('clearAll', false);
-          targetRepo.set('empty-error', !targetRepo.get('baseUrl'));
+    var operatingSystems = this.get('operatingSystems');
+    if (operatingSystems) {
+      operatingSystems.forEach(function (os) {
+        if (!os.get('isSelected')) {
+          os.get('repositories').forEach(function (repository) {
+            repository.set('baseUrl', repository.get('latestBaseUrl'));
+            repository.set('validation', App.Repository.validation['PENDING']);
+          });
         } else {
-          os.selected = true;
-          os.skipValidation = this.get('skipValidationChecked');
-          if (os.skipValidation) {
-            targetRepo.set('validation', null);
-            targetRepo.set('invalid-error', false);
-          }
-          targetRepo.set('clearAll', targetRepo.get('baseUrl'));
-          targetRepo.set('empty-error', !targetRepo.get('baseUrl'));
+          os.get('repositories').forEach(function (repository) {
+            if (this.get('controller.skipValidationChecked')) {
+              repository.set('validation', App.Repository.validation['PENDING']);
+            }
+          }, this);
         }
       }, this);
     }
-  }.observes('allRepositoriesGroups.@each.checked', 'skipValidationChecked'),
+  }.observes('operatingSystems.@each.isSelected', 'controller.skipValidationChecked'),
 
   /**
    * Onclick handler for undo action of each repo group
@@ -251,7 +198,8 @@ App.WizardStep1View = Em.View.extend({
    * @param {object} event
    */
   undoGroupLocalRepository: function (event) {
-    this.doActionForGroupLocalRepository(event, 'latestBaseUrl');
+    event.context.set('baseUrl', event.context.get('latestBaseUrl'));
+    event.context.set('validation', App.Repository.validation['PENDING']);
   },
 
   /**
@@ -260,21 +208,8 @@ App.WizardStep1View = Em.View.extend({
    * @param {object} event
    */
   clearGroupLocalRepository: function (event) {
-    this.doActionForGroupLocalRepository(event, '');
-  },
-
-  /**
-   * Common handler for repo groups actions
-   * @method doActionForGroupLocalRepository
-   * @param {object} event
-   * @param {string} newBaseUrlField
-   */
-  doActionForGroupLocalRepository: function (event, newBaseUrlField) {
-    var selectedStack = this.get('controller.content.stacks').findProperty('isSelected', true);
-    var cos = selectedStack.operatingSystems.findProperty('id', event.context.get('id'));
-    cos.baseUrl = Em.isEmpty(newBaseUrlField) ? '' : Em.get(cos, newBaseUrlField);
-    cos.validation = null;
-    this.loadRepositories();
+    event.context.set('baseUrl', '');
+    event.context.set('validation', App.Repository.validation['PENDING']);
   },
 
   /**
@@ -283,22 +218,13 @@ App.WizardStep1View = Em.View.extend({
    */
   editLocalRepository: function () {
     //upload to content
-    var repos = this.get('allRepositories');
-    var selectedStack = this.get('controller.content.stacks').findProperty('isSelected', true);
-    if (selectedStack && selectedStack.operatingSystems) {
-      selectedStack.operatingSystems.forEach(function (os) {
-        var targetRepo = repos.findProperty('id', os.id);
-        if (os.baseUrl != targetRepo.get('baseUrl')) {
-          os.baseUrl = targetRepo.get('baseUrl');
-          os.validation = null;
-          targetRepo.set('undo', targetRepo.get('baseUrl') != targetRepo.get('latestBaseUrl'));
-          targetRepo.set('invalid-error', false);
-          targetRepo.set('validation', null);
-          targetRepo.set('clearAll', os.baseUrl);
-          targetRepo.set('empty-error', !targetRepo.get('baseUrl'));
-        }
-      });
-    }
+    var repositories = this.get('allRepositories');
+    repositories.forEach(function (repository) {
+      if (repository.get('lastBaseUrl') != repository.get('baseUrl')) {
+        repository.set('lastBaseUrl', repository.get('baseUrl'));
+        repository.set('validation', App.Repository.validation['PENDING']);
+      }
+    }, this);
   }.observes('allRepositories.@each.baseUrl')
 
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/5a154221/ambari-web/test/controllers/installer_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/installer_test.js b/ambari-web/test/controllers/installer_test.js
index a92007f..b6b5d94 100644
--- a/ambari-web/test/controllers/installer_test.js
+++ b/ambari-web/test/controllers/installer_test.js
@@ -27,50 +27,11 @@ describe('App.InstallerController', function () {
   var installerController = App.InstallerController.create();
 
   describe('#loadStacksVersionsSuccessCallback', function() {
-    var test_data = {
-      "items" : [
-        {
-          "Versions" : {
-            "active" : false,
-            "min_upgrade_version" : null,
-            "stack_name" : "HDP",
-            "stack_version" : "1.2.0"
-          }
-        },
-        {
-          "Versions" : {
-            "active" : true,
-            "min_upgrade_version" : null,
-            "stack_name" : "HDP",
-            "stack_version" : "1.2.1"
-          }
-        },
-        {
-          "Versions" : {
-            "active" : true,
-            "min_upgrade_version" : "1.2.0",
-            "stack_name" : "HDP",
-            "stack_version" : "1.3.0"
-          }
-        },
-        {
-          "Versions" : {
-            "active" : false,
-            "min_upgrade_version" : null,
-            "stack_name" : "HDP",
-            "stack_version" : "2.0.1"
-          }
-        }
-      ]
-    };
     it ('Correct data', function() {
-      installerController.loadStacksVersionsSuccessCallback(test_data);
-      expect(installerController.get('stacks.length')).to.equal(2);
-      expect(installerController.get('stacks').everyProperty('isSelected')).to.equal(false);
-      expect(installerController.get('stacks').mapProperty('name')).to.eql(['HDP-1.3.0', 'HDP-1.2.1']);
+      installerController.loadStacksVersionsSuccessCallback(require('test/stack'));
+      expect(installerController.get('content.stacks.length')).to.equal(2);
+      expect(installerController.get('content.stacks').everyProperty('isSelected')).to.equal(false);
+      expect(installerController.get('content.stacks').mapProperty('id')).to.eql(['HDP-2.1','HDP-1.3']);
     });
   });
-
-
-
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/5a154221/ambari-web/test/controllers/wizard/step8_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/wizard/step8_test.js b/ambari-web/test/controllers/wizard/step8_test.js
index 3a7774b..3f061d0 100644
--- a/ambari-web/test/controllers/wizard/step8_test.js
+++ b/ambari-web/test/controllers/wizard/step8_test.js
@@ -1313,62 +1313,6 @@ describe('App.WizardStep8Controller', function () {
 
     });
 
-    describe('#setLocalRepositories', function() {
-
-      it('shouldn\'t do nothing', function () {
-        installerStep8Controller.set('content', {controllerName: 'addServiceController'});
-        sinon.stub(App, 'get', function (k) {
-          if ('supports.localRepositories' === k) return false;
-          return Em.get(App, k);
-        });
-        expect(installerStep8Controller.setLocalRepositories()).to.equal(false);
-        App.get.restore();
-      });
-
-      it('shouldn\'t do requests', function() {
-        installerStep8Controller.set('content', {
-          controllerName: 'installerController',
-          stacks: [
-            {
-              isSelected: true,
-              operatingSystems: [
-                {baseUrl: 'u1', originalBaseUrl: 'u1'},
-                {baseUrl: 'u2', originalBaseUrl: 'u2'}
-              ]
-            }
-          ]
-        });
-        installerStep8Controller.setLocalRepositories();
-        expect(installerStep8Controller.addRequestToAjaxQueue.called).to.equal(false);
-      });
-
-      it('should do 2 requests', function() {
-        installerStep8Controller.set('content', {
-          controllerName: 'installerController',
-          stacks: [
-            {
-              isSelected: true,
-              operatingSystems: [
-                {baseUrl: 'new_u1', originalBaseUrl: 'u1', osType: 'o1', repoId: 'r1'},
-                {baseUrl: 'new_u2', originalBaseUrl: 'u2', osType: 'o2', repoId: 'r2'}
-              ]
-            }
-          ]
-        });
-        installerStep8Controller.setLocalRepositories();
-        expect(installerStep8Controller.addRequestToAjaxQueue.calledTwice).to.equal(true);
-        var firstRequestData = installerStep8Controller.addRequestToAjaxQueue.args[0][0].data;
-        expect(firstRequestData.osType).to.equal('o1');
-        expect(firstRequestData.repoId).to.equal('r1');
-        expect(JSON.parse(firstRequestData.data).Repositories.base_url).to.equal('new_u1');
-
-        var secondRequestData = installerStep8Controller.addRequestToAjaxQueue.args[1][0].data;
-        expect(secondRequestData.osType).to.equal('o2');
-        expect(secondRequestData.repoId).to.equal('r2');
-        expect(JSON.parse(secondRequestData.data).Repositories.base_url).to.equal('new_u2');
-      });
-
-    });
 
     describe('#createAdditionalHostComponents', function() {
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/5a154221/ambari-web/test/mappers/stack_mapper_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/mappers/stack_mapper_test.js b/ambari-web/test/mappers/stack_mapper_test.js
new file mode 100644
index 0000000..2f8b10d
--- /dev/null
+++ b/ambari-web/test/mappers/stack_mapper_test.js
@@ -0,0 +1,285 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var Ember = require('ember');
+var App = require('app');
+require('mappers/server_data_mapper');
+require('mappers/stack_mapper');
+require('models/stack');
+require('models/operating_system');
+require('models/repository');
+
+describe('App.stackMapper', function () {
+	describe("#map", function() {
+    
+    var test_data = {
+        items: [{
+          "Versions" : {
+            "active" : true,
+            "min_upgrade_version" : null,
+            "parent_stack_version" : "1.3.3",
+            "stack_name" : "HDP",
+            "stack_version" : "1.3"
+          },
+          "operatingSystems" : [
+            {
+              "OperatingSystems" : {
+                "os_type" : "redhat5",
+                "stack_name" : "HDP",
+                "stack_version" : "1.3"
+              },
+              "repositories" : [
+                {
+                   "Repositories" : {
+                    "base_url" : "http://public-repo-1.hortonworks.com/HDP/centos5/1.x/updates/1.3.7.0",
+                    "default_base_url" : "http://public-repo-1.hortonworks.com/HDP/centos5/1.x/updates/1.3.7.0",
+                    "latest_base_url" : "http://public-repo-1.hortonworks.com/HDP/centos5/1.x/updates/1.3.8.0",
+                    "mirrors_list" : null,
+                    "os_type" : "redhat5",
+                    "repo_id" : "HDP-1.3",
+                    "repo_name" : "HDP",
+                    "stack_name" : "HDP",
+                    "stack_version" : "1.3"
+                  }
+                },{
+                  "Repositories" : {
+                    "base_url" : "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.16/repos/centos5",
+                    "default_base_url" : "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.16/repos/centos5",
+                    "latest_base_url" : "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.16/repos/centos5",
+                    "mirrors_list" : null,
+                    "os_type" : "redhat5",
+                    "repo_id" : "HDP-UTILS-1.1.0.16",
+                    "repo_name" : "HDP-UTILS",
+                    "stack_name" : "HDP",
+                    "stack_version" : "1.3"
+                  }
+                }]
+            },{
+              "OperatingSystems" : {
+                "os_type" : "redhat6",
+                "stack_name" : "HDP",
+                "stack_version" : "1.3"
+              }, "repositories" : [
+                  {
+                    "Repositories" : {
+                      "base_url" : "http://public-repo-1.hortonworks.com/HDP/centos6/1.x/updates/1.3.7.0",
+                      "default_base_url" : "http://public-repo-1.hortonworks.com/HDP/centos6/1.x/updates/1.3.7.0",
+                      "latest_base_url" : "http://public-repo-1.hortonworks.com/HDP/centos6/1.x/updates/1.3.8.0",
+                      "mirrors_list" : null,
+                      "os_type" : "redhat6",
+                      "repo_id" : "HDP-1.3",
+                      "repo_name" : "HDP",
+                      "stack_name" : "HDP",
+                      "stack_version" : "1.3"
+                    }
+                  },
+                  {
+                    "Repositories" : {
+                      "base_url" : "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.16/repos/centos6",
+                      "default_base_url" : "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.16/repos/centos6",
+                      "latest_base_url" : "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.16/repos/centos6",
+                      "mirrors_list" : null,
+                      "os_type" : "redhat6",
+                      "repo_id" : "HDP-UTILS-1.1.0.16",
+                      "repo_name" : "HDP-UTILS",
+                      "stack_name" : "HDP",
+                      "stack_version" : "1.3"
+                    }
+                  }
+                ]
+            }]
+      },{
+        "Versions" : {
+          "active" : false,
+          "min_upgrade_version" : null,
+          "parent_stack_version" : null,
+          "stack_name" : "HDP",
+          "stack_version" : "2.0.6"
+        },
+        "operatingSystems" : [
+          {
+            "OperatingSystems" : {
+              "os_type" : "redhat5",
+              "stack_name" : "HDP",
+              "stack_version" : "2.0.6"
+            },
+            "repositories" : [
+              {
+                "Repositories" : {
+                  "base_url" : "http://public-repo-1.hortonworks.com/HDP/centos5/2.x/updates/2.0.6.1",
+                  "default_base_url" : "http://public-repo-1.hortonworks.com/HDP/centos5/2.x/updates/2.0.6.1",
+                  "latest_base_url" : "http://public-repo-1.hortonworks.com/HDP/centos5/2.x/updates/2.0.6.1",
+                  "mirrors_list" : null,
+                  "os_type" : "redhat5",
+                  "repo_id" : "HDP-2.0.6",
+                  "repo_name" : "HDP",
+                  "stack_name" : "HDP",
+                  "stack_version" : "2.0.6"
+                }
+              },
+              {
+                "Repositories" : {
+                  "base_url" : "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.17/repos/centos5",
+                  "default_base_url" : "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.17/repos/centos5",
+                  "latest_base_url" : "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.17/repos/centos5",
+                  "mirrors_list" : null,
+                  "os_type" : "redhat5",
+                  "repo_id" : "HDP-UTILS-1.1.0.17",
+                  "repo_name" : "HDP-UTILS",
+                  "stack_name" : "HDP",
+                  "stack_version" : "2.0.6"
+                }
+              }]
+          }, {
+            "OperatingSystems" : {
+              "os_type" : "redhat6",
+              "stack_name" : "HDP",
+              "stack_version" : "2.0.6"
+            },
+            "repositories" : [
+              {
+                "Repositories" : {
+                  "base_url" : "http://public-repo-1.hortonworks.com/HDP/centos6/2.x/updates/2.0.6.1",
+                  "default_base_url" : "http://public-repo-1.hortonworks.com/HDP/centos6/2.x/updates/2.0.6.1",
+                  "latest_base_url" : "http://public-repo-1.hortonworks.com/HDP/centos6/2.x/updates/2.0.6.1",
+                  "mirrors_list" : null,
+                  "os_type" : "redhat6",
+                  "repo_id" : "HDP-2.0.6",
+                  "repo_name" : "HDP",
+                  "stack_name" : "HDP",
+                  "stack_version" : "2.0.6"
+                }
+              }, {
+                "Repositories" : {
+                  "base_url" : "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.17/repos/centos6",
+                  "default_base_url" : "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.17/repos/centos6",
+                  "latest_base_url" : "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.17/repos/centos6",
+                  "mirrors_list" : null,
+                  "os_type" : "redhat6",
+                  "repo_id" : "HDP-UTILS-1.1.0.17",
+                  "repo_name" : "HDP-UTILS",
+                  "stack_name" : "HDP",
+                  "stack_version" : "2.0.6"
+                }
+              }]
+          }]
+      },{
+        "Versions" : {
+          "active" : true,
+          "min_upgrade_version" : null,
+          "parent_stack_version" : null,
+          "stack_name" : "HDP",
+          "stack_version" : "2.1"
+        },
+        "operatingSystems" : [
+          {
+            "OperatingSystems" : {
+              "os_type" : "redhat5",
+              "stack_name" : "HDP",
+              "stack_version" : "2.1"
+            },
+            "repositories" : [
+              {
+                "Repositories" : {
+                  "base_url" : "http://public-repo-1.hortonworks.com/HDP/centos5/2.x/updates/2.0.6.1",
+                  "default_base_url" : "http://public-repo-1.hortonworks.com/HDP/centos5/2.x/updates/2.0.6.1",
+                  "latest_base_url" : "http://public-repo-1.hortonworks.com/HDP/centos5/2.x/updates/2.0.6.1",
+                  "mirrors_list" : null,
+                  "os_type" : "redhat5",
+                  "repo_id" : "HDP-2.1",
+                  "repo_name" : "HDP",
+                  "stack_name" : "HDP",
+                  "stack_version" : "2.1"
+                }
+              },
+              {
+                "Repositories" : {
+                  "base_url" : "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.17/repos/centos5",
+                  "default_base_url" : "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.17/repos/centos5",
+                  "latest_base_url" : "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.17/repos/centos5",
+                  "mirrors_list" : null,
+                  "os_type" : "redhat5",
+                  "repo_id" : "HDP-UTILS-1.1.0.17",
+                  "repo_name" : "HDP-UTILS",
+                  "stack_name" : "HDP",
+                  "stack_version" : "2.1"
+                }
+              }]
+          }, {
+            "OperatingSystems" : {
+              "os_type" : "redhat6",
+              "stack_name" : "HDP",
+              "stack_version" : "2.1"
+            },
+            "repositories" : [
+              {
+                "Repositories" : {
+                  "base_url" : "http://public-repo-1.hortonworks.com/HDP/centos6/2.x/updates/2.0.6.1",
+                  "default_base_url" : "http://public-repo-1.hortonworks.com/HDP/centos6/2.x/updates/2.0.6.1",
+                  "latest_base_url" : "http://public-repo-1.hortonworks.com/HDP/centos6/2.x/updates/2.0.6.1",
+                  "mirrors_list" : null,
+                  "os_type" : "redhat6",
+                  "repo_id" : "HDP-2.1",
+                  "repo_name" : "HDP",
+                  "stack_name" : "HDP",
+                  "stack_version" : "2.1"
+                }
+              }, {
+                "Repositories" : {
+                  "base_url" : "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.17/repos/centos6",
+                  "default_base_url" : "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.17/repos/centos6",
+                  "latest_base_url" : "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.17/repos/centos6",
+                  "mirrors_list" : null,
+                  "os_type" : "redhat6",
+                  "repo_id" : "HDP-UTILS-1.1.0.17",
+                  "repo_name" : "HDP-UTILS",
+                  "stack_name" : "HDP",
+                  "stack_version" : "2.1"
+                }
+              }]
+          }]
+      }] 
+    };
+
+    beforeEach(function () {
+      App.resetDsStoreTypeMap(App.Repository);
+      App.resetDsStoreTypeMap(App.OperatingSystem);
+      App.resetDsStoreTypeMap(App.Stack);
+    });
+
+		
+    it ('should map active Stack data', function() {
+      App.stackMapper.map(test_data);
+      expect(App.Stack.find().get('length')).to.equal(2);
+      expect(App.Stack.find().everyProperty('active')).to.equal(true);
+      expect(App.Stack.find().everyProperty('isSelected')).to.equal(false);
+      expect(App.Stack.find().mapProperty('id')).to.eql(['HDP-2.1','HDP-1.3']);
+    });
+
+    it ('should map Operating System data', function() {
+      App.stackMapper.map(test_data);
+      expect(App.OperatingSystem.find().get('length')).to.equal(4);
+      expect(App.OperatingSystem.find().mapProperty('id')).to.eql(['HDP-2.1-redhat5', 'HDP-2.1-redhat6', 'HDP-1.3-redhat5', 'HDP-1.3-redhat6']);
+    });
+    
+    it ('should map Repository data', function() {
+      App.stackMapper.map(test_data);
+      expect(App.Repository.find().get('length')).to.equal(8);
+    });
+  });
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/5a154221/ambari-web/test/stack.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/stack.js b/ambari-web/test/stack.js
new file mode 100644
index 0000000..c9e0432
--- /dev/null
+++ b/ambari-web/test/stack.js
@@ -0,0 +1,265 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+module.exports = {
+  "items": [
+    {
+      "Versions": {
+        "active": true,
+        "min_upgrade_version": null,
+        "parent_stack_version": "1.3.3",
+        "stack_name": "HDP",
+        "stack_version": "1.3"
+      },
+      "operatingSystems": [
+        {
+          "OperatingSystems": {
+            "os_type": "redhat5",
+            "stack_name": "HDP",
+            "stack_version": "1.3"
+          },
+          "repositories": [
+            {
+              "Repositories": {
+                "base_url": "http://public-repo-1.hortonworks.com/HDP/centos5/1.x/updates/1.3.7.0",
+                "default_base_url": "http://public-repo-1.hortonworks.com/HDP/centos5/1.x/updates/1.3.7.0",
+                "latest_base_url": "http://public-repo-1.hortonworks.com/HDP/centos5/1.x/updates/1.3.8.0",
+                "mirrors_list": null,
+                "os_type": "redhat5",
+                "repo_id": "HDP-1.3",
+                "repo_name": "HDP",
+                "stack_name": "HDP",
+                "stack_version": "1.3"
+              }
+            },
+            {
+              "Repositories": {
+                "base_url": "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.16/repos/centos5",
+                "default_base_url": "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.16/repos/centos5",
+                "latest_base_url": "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.16/repos/centos5",
+                "mirrors_list": null,
+                "os_type": "redhat5",
+                "repo_id": "HDP-UTILS-1.1.0.16",
+                "repo_name": "HDP-UTILS",
+                "stack_name": "HDP",
+                "stack_version": "1.3"
+              }
+            }
+          ]
+        },
+        {
+          "OperatingSystems": {
+            "os_type": "redhat6",
+            "stack_name": "HDP",
+            "stack_version": "1.3"
+          }, "repositories": [
+          {
+            "Repositories": {
+              "base_url": "http://public-repo-1.hortonworks.com/HDP/centos6/1.x/updates/1.3.7.0",
+              "default_base_url": "http://public-repo-1.hortonworks.com/HDP/centos6/1.x/updates/1.3.7.0",
+              "latest_base_url": "http://public-repo-1.hortonworks.com/HDP/centos6/1.x/updates/1.3.8.0",
+              "mirrors_list": null,
+              "os_type": "redhat6",
+              "repo_id": "HDP-1.3",
+              "repo_name": "HDP",
+              "stack_name": "HDP",
+              "stack_version": "1.3"
+            }
+          },
+          {
+            "Repositories": {
+              "base_url": "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.16/repos/centos6",
+              "default_base_url": "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.16/repos/centos6",
+              "latest_base_url": "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.16/repos/centos6",
+              "mirrors_list": null,
+              "os_type": "redhat6",
+              "repo_id": "HDP-UTILS-1.1.0.16",
+              "repo_name": "HDP-UTILS",
+              "stack_name": "HDP",
+              "stack_version": "1.3"
+            }
+          }
+        ]
+        }
+      ]
+    },
+    {
+      "Versions": {
+        "active": false,
+        "min_upgrade_version": null,
+        "parent_stack_version": null,
+        "stack_name": "HDP",
+        "stack_version": "2.0.6"
+      },
+      "operatingSystems": [
+        {
+          "OperatingSystems": {
+            "os_type": "redhat5",
+            "stack_name": "HDP",
+            "stack_version": "2.0.6"
+          },
+          "repositories": [
+            {
+              "Repositories": {
+                "base_url": "http://public-repo-1.hortonworks.com/HDP/centos5/2.x/updates/2.0.6.1",
+                "default_base_url": "http://public-repo-1.hortonworks.com/HDP/centos5/2.x/updates/2.0.6.1",
+                "latest_base_url": "http://public-repo-1.hortonworks.com/HDP/centos5/2.x/updates/2.0.6.1",
+                "mirrors_list": null,
+                "os_type": "redhat5",
+                "repo_id": "HDP-2.0.6",
+                "repo_name": "HDP",
+                "stack_name": "HDP",
+                "stack_version": "2.0.6"
+              }
+            },
+            {
+              "Repositories": {
+                "base_url": "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.17/repos/centos5",
+                "default_base_url": "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.17/repos/centos5",
+                "latest_base_url": "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.17/repos/centos5",
+                "mirrors_list": null,
+                "os_type": "redhat5",
+                "repo_id": "HDP-UTILS-1.1.0.17",
+                "repo_name": "HDP-UTILS",
+                "stack_name": "HDP",
+                "stack_version": "2.0.6"
+              }
+            }
+          ]
+        },
+        {
+          "OperatingSystems": {
+            "os_type": "redhat6",
+            "stack_name": "HDP",
+            "stack_version": "2.0.6"
+          },
+          "repositories": [
+            {
+              "Repositories": {
+                "base_url": "http://public-repo-1.hortonworks.com/HDP/centos6/2.x/updates/2.0.6.1",
+                "default_base_url": "http://public-repo-1.hortonworks.com/HDP/centos6/2.x/updates/2.0.6.1",
+                "latest_base_url": "http://public-repo-1.hortonworks.com/HDP/centos6/2.x/updates/2.0.6.1",
+                "mirrors_list": null,
+                "os_type": "redhat6",
+                "repo_id": "HDP-2.0.6",
+                "repo_name": "HDP",
+                "stack_name": "HDP",
+                "stack_version": "2.0.6"
+              }
+            },
+            {
+              "Repositories": {
+                "base_url": "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.17/repos/centos6",
+                "default_base_url": "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.17/repos/centos6",
+                "latest_base_url": "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.17/repos/centos6",
+                "mirrors_list": null,
+                "os_type": "redhat6",
+                "repo_id": "HDP-UTILS-1.1.0.17",
+                "repo_name": "HDP-UTILS",
+                "stack_name": "HDP",
+                "stack_version": "2.0.6"
+              }
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Versions": {
+        "active": true,
+        "min_upgrade_version": null,
+        "parent_stack_version": null,
+        "stack_name": "HDP",
+        "stack_version": "2.1"
+      },
+      "operatingSystems": [
+        {
+          "OperatingSystems": {
+            "os_type": "redhat5",
+            "stack_name": "HDP",
+            "stack_version": "2.1"
+          },
+          "repositories": [
+            {
+              "Repositories": {
+                "base_url": "http://public-repo-1.hortonworks.com/HDP/centos5/2.x/updates/2.0.6.1",
+                "default_base_url": "http://public-repo-1.hortonworks.com/HDP/centos5/2.x/updates/2.0.6.1",
+                "latest_base_url": "http://public-repo-1.hortonworks.com/HDP/centos5/2.x/updates/2.0.6.1",
+                "mirrors_list": null,
+                "os_type": "redhat5",
+                "repo_id": "HDP-2.1",
+                "repo_name": "HDP",
+                "stack_name": "HDP",
+                "stack_version": "2.1"
+              }
+            },
+            {
+              "Repositories": {
+                "base_url": "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.17/repos/centos5",
+                "default_base_url": "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.17/repos/centos5",
+                "latest_base_url": "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.17/repos/centos5",
+                "mirrors_list": null,
+                "os_type": "redhat5",
+                "repo_id": "HDP-UTILS-1.1.0.17",
+                "repo_name": "HDP-UTILS",
+                "stack_name": "HDP",
+                "stack_version": "2.1"
+              }
+            }
+          ]
+        },
+        {
+          "OperatingSystems": {
+            "os_type": "redhat6",
+            "stack_name": "HDP",
+            "stack_version": "2.1"
+          },
+          "repositories": [
+            {
+              "Repositories": {
+                "base_url": "http://public-repo-1.hortonworks.com/HDP/centos6/2.x/updates/2.0.6.1",
+                "default_base_url": "http://public-repo-1.hortonworks.com/HDP/centos6/2.x/updates/2.0.6.1",
+                "latest_base_url": "http://public-repo-1.hortonworks.com/HDP/centos6/2.x/updates/2.0.6.1",
+                "mirrors_list": null,
+                "os_type": "redhat6",
+                "repo_id": "HDP-2.1",
+                "repo_name": "HDP",
+                "stack_name": "HDP",
+                "stack_version": "2.1"
+              }
+            },
+            {
+              "Repositories": {
+                "base_url": "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.17/repos/centos6",
+                "default_base_url": "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.17/repos/centos6",
+                "latest_base_url": "http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.17/repos/centos6",
+                "mirrors_list": null,
+                "os_type": "redhat6",
+                "repo_id": "HDP-UTILS-1.1.0.17",
+                "repo_name": "HDP-UTILS",
+                "stack_name": "HDP",
+                "stack_version": "2.1"
+              }
+            }
+          ]
+        }
+      ]
+    }
+  ]
+};

http://git-wip-us.apache.org/repos/asf/ambari/blob/5a154221/ambari-web/test/utils/helper_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/utils/helper_test.js b/ambari-web/test/utils/helper_test.js
index bd90d09..f75c1e4 100644
--- a/ambari-web/test/utils/helper_test.js
+++ b/ambari-web/test/utils/helper_test.js
@@ -228,8 +228,7 @@ describe('utils/helper', function() {
           'HBASE_MASTER': 'HBase Master',
           'HBASE_REGIONSERVER': 'RegionServer',
           'HBASE_SERVICE_CHECK': 'HBase Service Check',
-          'HCAT': 'HCat',
-          'HCAT_SERVICE_CHECK': 'HCat Service Check',
+          'HCAT': 'HCat Client',
           'HDFS': 'HDFS',
           'HDFS_CLIENT': 'HDFS Client',
           'HDFS_SERVICE_CHECK': 'HDFS Service Check',
@@ -272,7 +271,6 @@ describe('utils/helper', function() {
           'TASKTRACKER': 'TaskTracker',
           'TEZ_CLIENT': 'Tez Client',
           'WEBHCAT_SERVER': 'WebHCat Server',
-          'WEBHCAT_SERVICE_CHECK': 'WebHCat Service Check',
           'YARN_CLIENT': 'YARN Client',
           'YARN_SERVICE_CHECK': 'YARN Service Check',
           'ZKFC': 'ZKFailoverController',