ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jonathanhur...@apache.org
Subject [1/2] ambari git commit: AMBARI-22695 - Implement download configuration options and custom (i.e. local) repo support (Jason Golieb via jonathanhurley)
Date Tue, 02 Jan 2018 14:55:41 GMT
Repository: ambari
Updated Branches:
  refs/heads/branch-feature-AMBARI-14714-ui c72a3bff5 -> 50e28dff0


http://git-wip-us.apache.org/repos/asf/ambari/blob/50e28dff/ambari-web/app/models/repository.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/repository.js b/ambari-web/app/models/repository.js
index c50750f..07a5f0e 100644
--- a/ambari-web/app/models/repository.js
+++ b/ambari-web/app/models/repository.js
@@ -34,6 +34,7 @@ App.Repository = DS.Model.extend({
   operatingSystem: DS.belongsTo('App.OperatingSystem'),
   components: DS.attr('string'),
   distribution: DS.attr('string'),
+  unique: DS.attr('boolean'),
 
   validation: DS.attr('string', {defaultValue: ''}),
   validationClassName: Em.computed.getByKey('validationClassNameMap', 'validation', ''),

http://git-wip-us.apache.org/repos/asf/ambari/blob/50e28dff/ambari-web/app/router.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/router.js b/ambari-web/app/router.js
index d0b1714..844b750 100644
--- a/ambari-web/app/router.js
+++ b/ambari-web/app/router.js
@@ -44,10 +44,16 @@ App.WizardRoute = Em.Route.extend({
   gotoStep10: Em.Router.transitionTo('step10'),
 
   gotoConfigureDownload: Em.Router.transitionTo('configureDownload'),
-
+  
   gotoSelectMpacks: Em.Router.transitionTo('selectMpacks'),
   
-  gotoDownloadProducts: Em.Router.transitionTo('downloadProducts'),
+  gotoCustomMpackRepos: Em.Router.transitionTo('customMpackRepos'),
+
+  gotoDownloadMpacks: Em.Router.transitionTo('downloadMpacks'),
+  
+  gotoCustomProductRepos: Em.Router.transitionTo('customProductRepos'),
+  
+  gotoVerifyProducts: Em.Router.transitionTo('verifyProducts'),
 
   isRoutable: function() {
     return typeof this.get('route') === 'string' && App.router.get('loggedIn');

http://git-wip-us.apache.org/repos/asf/ambari/blob/50e28dff/ambari-web/app/routes/installer.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/routes/installer.js b/ambari-web/app/routes/installer.js
index 80cf116..25dd9d8 100644
--- a/ambari-web/app/routes/installer.js
+++ b/ambari-web/app/routes/installer.js
@@ -92,12 +92,16 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
 
   step0: Em.Route.extend({
     route: '/step0',
+
     connectOutlets: function (router) {
       console.time('step0 connectOutlets');
       var self = this;
       var controller = router.get('installerController');
+      var wizardStep0Controller = router.get('wizardStep0Controller');
+      wizardStep0Controller.set('wizardController', controller);
       controller.setCurrentStep('step0');
       controller.loadAllPriorSteps().done(function () {
+        controller.setStepsEnable();
         controller.connectOutlet('wizardStep0', controller.get('content'));
         self.scrollTop();
         console.timeEnd('step0 connectOutlets');
@@ -119,86 +123,29 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
     }
   }),
 
-  // step1: Em.Route.extend({
-  //   route: '/step1',
-  //   connectOutlets: function (router) {
-  //     console.time('step1 connectOutlets');
-  //     var self = this;
-  //     var controller = router.get('installerController');
-  //     var wizardStep1Controller = router.get('wizardStep1Controller');
-  //     wizardStep1Controller.set('skipValidationChecked', false);
-  //     wizardStep1Controller.set('optionsToSelect', {
-  //       'usePublicRepo': {
-  //         index: 0,
-  //         isSelected: true
-  //       },
-  //       'useLocalRepo': {
-  //         index: 1,
-  //         isSelected: false,
-  //         'uploadFile': {
-  //           index: 0,
-  //           name: 'uploadFile',
-  //           file: '',
-  //           hasError: false,
-  //           isSelected: true
-  //         },
-  //         'enterUrl': {
-  //           index: 1,
-  //           name: 'enterUrl',
-  //           url: '',
-  //           placeholder: Em.I18n.t('installer.step1.useLocalRepo.enterUrl.placeholder'),
-  //           hasError: false,
-  //           isSelected: false
-  //         }
-  //       }
-  //     });
-  //     controller.setCurrentStep('step1');
-  //     controller.loadAllPriorSteps().done(function () {
-  //       wizardStep1Controller.set('wizardController', controller);
-  //       controller.connectOutlet('wizardStep1', controller.get('content'));
-  //       self.scrollTop();
-  //       console.timeEnd('step1 connectOutlets');
-  //     });
-  //   },
-  //   back: Em.Router.transitionTo('selectMpacks'),
-  //   next: function (router) {
-  //     console.time('step1 next');
-  //     if(router.get('btnClickInProgress')) {
-  //       return;
-  //     }
-  //     var wizardStep1Controller = router.get('wizardStep1Controller');
-  //     var installerController = router.get('installerController');
-  //     installerController.validateJDKVersion(function() {
-  //       installerController.checkRepoURL(wizardStep1Controller).done(function () {
-  //         App.set('router.nextBtnClickInProgress', true);
-  //         installerController.setDBProperty('service', undefined);
-  //         installerController.setStacks();
-  //         router.transitionTo('step4');
-  //         console.timeEnd('step1 next');
-  //       });
-  //     }, function() {});
-  //   }
-  // }),
-
   step2: Em.Route.extend({
     route: '/step2',
+    
     connectOutlets: function (router, context) {
       console.time('step2 connectOutlets');
       var self = this;
       var controller = router.get('installerController');
+      var wizardStep2Controller = router.get('wizardStep2Controller');
+      wizardStep2Controller.set('wizardController', controller);
       var newStepIndex = controller.getStepIndex('step2');
       router.setNavigationFlow(newStepIndex);
       //controller.clearInstallOptions();
       controller.setCurrentStep('step2');
-      var wizardStep2Controller = router.get('wizardStep2Controller');
-      wizardStep2Controller.set('wizardController', controller);
       controller.loadAllPriorSteps().done(function () {
+        controller.setStepsEnable();
         self.scrollTop();
         controller.connectOutlet('wizardStep2', controller.get('content'));
         console.timeEnd('step2 connectOutlets');
       });
     },
+    
     back: Em.Router.transitionTo('step0'),
+    
     next: function (router) {
       console.time('step2 next');
       if (!router.get('btnClickInProgress')) {
@@ -216,14 +163,16 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
 
   step3: App.StepRoute.extend({
     route: '/step3',
+    
     connectOutlets: function (router) {
       console.time('step3 connectOutlets');
       var self = this;
       var controller = router.get('installerController');
-      controller.setCurrentStep('step3');
       var wizardStep3Controller = router.get('wizardStep3Controller');
       wizardStep3Controller.set('wizardController', controller);
+      controller.setCurrentStep('step3');
       controller.loadAllPriorSteps().done(function () {
+        controller.setStepsEnable();
         controller.connectOutlet('wizardStep3', controller.get('content'));
         self.scrollTop();
         console.timeEnd('step3 connectOutlets');
@@ -278,22 +227,26 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
 
   configureDownload: Em.Route.extend({
     route: '/configureDownload',
+    
     connectOutlets: function (router) {
       console.time('configureDownload connectOutlets');
       var self = this;
       var controller = router.get('installerController');
+      var configureDownloadController = router.get('wizardConfigureDownloadController');
+      configureDownloadController.set('wizardController', controller);
       var newStepIndex = controller.getStepIndex('configureDownload');
       router.setNavigationFlow(newStepIndex);
       controller.setCurrentStep('configureDownload');
-      var configureDownloadController = router.get('wizardConfigureDownloadController');
-      configureDownloadController.set('wizardController', controller);
       controller.loadAllPriorSteps().done(function () {
+        controller.setStepsEnable();
         controller.connectOutlet('wizardConfigureDownload', controller.get('content'));
         self.scrollTop();
         console.timeEnd('configureDownload connectOutlets');
       });
     },
+    
     back: Em.Router.transitionTo('step3'),
+    
     next: function (router) {
       console.time('configureDownload next');
       if(router.get('btnClickInProgress')) {
@@ -319,6 +272,7 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
       var wizardSelectMpacksController = router.get('wizardSelectMpacksController');
       wizardSelectMpacksController.set('wizardController', controller);
       controller.loadAllPriorSteps().done(function () {
+        controller.setStepsEnable();
         controller.connectOutlet('wizardSelectMpacks', controller.get('content'));
         self.scrollTop();
         console.timeEnd('selectMpacks connectOutlets');
@@ -350,27 +304,43 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
           wizardStep6Controller.set('isClientsSet', false);
         }
         controller.setStepSaved('selectMpacks');
-        router.transitionTo('downloadProducts');
+        const downloadConfig = controller.get('content.downloadConfig');
+        if (downloadConfig && downloadConfig.useCustomRepo) {
+          router.transitionTo('customMpackRepos');
+        } else {
+          router.transitionTo('downloadMpacks');
+        }  
         console.timeEnd('selectMpacks next');
       }
     },
   }),
 
-  downloadProducts: App.StepRoute.extend({
-    route: '/downloadProducts',
+  customMpackRepos: App.StepRoute.extend({
+    route: '/customMpackRepos',
+    
     connectOutlets: function (router) {
-      console.time('downloadProducts connectOutlets');
+      console.time('customMpackRepos connectOutlets');
       var self = this;
       var controller = router.get('installerController');
-      var newStepIndex = controller.getStepIndex('downloadProducts');
+      const downloadConfig = controller.get('content.downloadConfig');
+      
+      //do not allow navigation to this step unless we are using custom repos
+      if (downloadConfig && !downloadConfig.useCustomRepo) {
+        Em.run.next(function () {
+          router.transitionTo('downloadMpacks');
+        });
+      }  
+
+      var customMpackReposController = router.get('wizardCustomMpackReposController');
+      customMpackReposController.set('wizardController', controller);
+      var newStepIndex = controller.getStepIndex('customMpackRepos');
       router.setNavigationFlow(newStepIndex);
-      controller.setCurrentStep('downloadProducts');
-      var downloadProductsController = router.get('wizardDownloadProductsController');
-      downloadProductsController.set('wizardController', controller);
+      controller.setCurrentStep('customMpackRepos');
       controller.loadAllPriorSteps().done(function () {
-        controller.connectOutlet('wizardDownloadProducts', controller.get('content'));
+        controller.setStepsEnable();
+        controller.connectOutlet('wizardCustomMpackRepos', controller.get('content'));
         self.scrollTop();
-        console.timeEnd('downloadProducts connectOutlets');
+        console.timeEnd('customMpackRepos connectOutlets');
       });
     },
 
@@ -379,13 +349,164 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
     },
 
     next: function (router) {
-      console.time('downloadProducts next');
+      console.time('customMpackRepos next');
+      if (!router.get('btnClickInProgress')) {
+        App.set('router.nextBtnClickInProgress', true);
+        const controller = router.get('installerController');
+        controller.save('selectedMpacks');
+        controller.setStepSaved('customMpackRepos');
+        router.transitionTo('downloadMpacks');
+        console.timeEnd('customMpackRepos next');
+      }  
+    }
+  }),
+  
+  downloadMpacks: App.StepRoute.extend({
+    route: '/downloadMpacks',
+    connectOutlets: function (router) {
+      console.time('downloadMpacks connectOutlets');
+      var self = this;
+      var controller = router.get('installerController');
+      var downloadMpacksController = router.get('wizardDownloadMpacksController');
+      downloadMpacksController.set('wizardController', controller);
+      var newStepIndex = controller.getStepIndex('downloadMpacks');
+      router.setNavigationFlow(newStepIndex);
+      controller.setCurrentStep('downloadMpacks');
+      
+      //disable customMpackRepos step (even though it is an earlier step) if not using custom repos
+      // Em.run.next(function () {
+      //   controller.get('isStepDisabled')
+      //     .findProperty('step', controller.getStepIndex('customMpackRepos'))
+      //     .set('value', !controller.get('content.downloadConfig.useCustomRepo'));
+      // });
+
+      controller.loadAllPriorSteps().done(function () {
+        controller.setStepsEnable();
+        controller.connectOutlet('wizardDownloadMpacks', controller.get('content'));
+        self.scrollTop();
+        console.timeEnd('downloadMpacks connectOutlets');
+      });
+    },
+
+    backTransition: function (router) {
+      const controller = router.get('installerController');
+      const downloadConfig = controller.get('content.downloadConfig');
+      if (downloadConfig && downloadConfig.useCustomRepo) {
+        router.transitionTo('customMpackRepos');
+      } else {
+        router.transitionTo('selectMpacks');
+      }
+    },
+
+    next: function (router) {
+      console.time('downloadMpacks next');
       if(router.get('btnClickInProgress')) {
         return;
       }
       App.set('router.nextBtnClickInProgress', true);
-      router.transitionTo('step5');
-      console.timeEnd('downloadProducts next');
+      const controller = router.get('installerController');
+      const downloadConfig = controller.get('content.downloadConfig');
+      if (downloadConfig && downloadConfig.useCustomRepo) {
+        router.transitionTo('customProductRepos');
+      } else {
+        router.transitionTo('verifyProducts');
+      }  
+      console.timeEnd('downloadMpacks next');
+    }
+  }),
+
+  customProductRepos: App.StepRoute.extend({
+    route: '/customProductRepos',
+
+    connectOutlets: function (router) {
+      console.time('customProductRepos connectOutlets');
+      var self = this;
+      var controller = router.get('installerController');
+      const downloadConfig = controller.get('content.downloadConfig');
+      
+      //disable navigation to this step unless we are using custom repos
+      if (downloadConfig && !downloadConfig.useCustomRepo) {
+        Em.run.next(function () {
+          router.transitionTo('verifyProducts');
+        });
+      }  
+      
+      var customMpackReposController = router.get('wizardCustomMpackReposController');
+      customMpackReposController.set('wizardController', controller);
+      var newStepIndex = controller.getStepIndex('customProductRepos');
+      router.setNavigationFlow(newStepIndex);
+      controller.setCurrentStep('customProductRepos');
+      controller.loadAllPriorSteps().done(function () {
+        controller.setStepsEnable();
+        controller.connectOutlet('wizardCustomProductRepos', controller.get('content'));
+        self.scrollTop();
+        console.timeEnd('customProductRepos connectOutlets');
+      });
+    },
+
+    backTransition: function (router) {
+      router.transitionTo('downloadMpacks');
+    },
+
+    next: function (router) {
+      console.time('customProductRepos next');
+      if (!router.get('btnClickInProgress')) {
+        App.set('router.nextBtnClickInProgress', true);
+        const controller = router.get('installerController');
+        controller.save('selectedMpacks');
+        controller.setStepSaved('customProductRepos');
+        router.transitionTo('verifyProducts');
+        console.timeEnd('customProductRepos next');
+      }
+    }
+  }),
+
+  verifyProducts: App.StepRoute.extend({
+    route: '/verifyProducts',
+    connectOutlets: function (router) {
+      console.time('verifyProducts connectOutlets');
+      var self = this;
+      var controller = router.get('installerController');
+      var verifyProductsController = router.get('wizardVerifyProductsController');
+      verifyProductsController.set('wizardController', controller);
+      var newStepIndex = controller.getStepIndex('verifyProducts');
+      router.setNavigationFlow(newStepIndex);
+      controller.setCurrentStep('verifyProducts');
+
+      //disable customProductRepos step (even though it is an earlier step) if not using custom repos
+      // Em.run.next(function () {
+      //   controller.get('isStepDisabled')
+      //     .findProperty('step', controller.getStepIndex('customProductRepos'))
+      //     .set('value', !controller.get('content.downloadConfig.useCustomRepo'));
+      // });
+
+      controller.loadAllPriorSteps().done(function () {
+        controller.setStepsEnable();
+        controller.connectOutlet('wizardVerifyProducts', controller.get('content'));
+        self.scrollTop();
+        console.timeEnd('verifyProducts connectOutlets');
+      });
+    },
+
+    backTransition: function (router) {
+      const controller = router.get('installerController');
+      const downloadConfig = controller.get('content.downloadConfig');
+      if (downloadConfig && downloadConfig.useCustomRepo) {
+        router.transitionTo('customProductRepos');
+      } else {
+        router.transitionTo('downloadMpacks');
+      }
+    },
+
+    next: function (router) {
+      console.time('verifyProducts next');
+      if (router.get('btnClickInProgress')) {
+        return;
+      }
+      App.set('router.nextBtnClickInProgress', true);
+      const controller = router.get('installerController');
+      router.transitionTo(controller.getNextStepName());
+      console.timeEnd('verifyProducts next');
     }
   }),
 
@@ -395,12 +516,13 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
       console.time('step4 connectOutlets');
       var self = this;
       var controller = router.get('installerController');
+      var wizardStep4Controller = router.get('wizardStep4Controller');
+      wizardStep4Controller.set('wizardController', controller);
       var newStepIndex = controller.getStepIndex('step4');
       router.setNavigationFlow(newStepIndex);
       controller.setCurrentStep('step4');
-      var wizardStep4Controller = router.get('wizardStep4Controller');
-      wizardStep4Controller.set('wizardController', controller);
       controller.loadAllPriorSteps().done(function () {
+        controller.setStepsEnable();
         controller.connectOutlet('wizardStep4', App.StackService.find().filterProperty('isInstallable', true));
         self.scrollTop();
         console.timeEnd('step4 connectOutlets');
@@ -437,23 +559,24 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
       console.time('step5 connectOutlets');
       var self = this;
       var controller = router.get('installerController');
+      var wizardStep5Controller = router.get('wizardStep5Controller');
+      wizardStep5Controller.set('wizardController', controller);
       var newStepIndex = controller.getStepIndex('step5');
       router.setNavigationFlow(newStepIndex);
-      var wizardStep5Controller = router.get('wizardStep5Controller');
       wizardStep5Controller.setProperties({
         servicesMasters: [],
         isInitialLayout: true
       });
-      wizardStep5Controller.set('wizardController', controller);
       controller.setCurrentStep('step5');
       controller.loadAllPriorSteps().done(function () {
+        controller.setStepsEnable();
         controller.connectOutlet('wizardStep5', controller.get('content'));
         self.scrollTop();
         console.timeEnd('step5 connectOutlets');
       });
     },
     backTransition: function(router) {
-      router.transitionTo('downloadProducts');
+      router.transitionTo('verifyProducts');
     },
     next: function (router) {
       console.time('step5 next');
@@ -482,13 +605,14 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
       console.time('step6 connectOutlets');
       var self = this;
       var controller = router.get('installerController');
+      var wizardStep6Controller = router.get('wizardStep6Controller');
+      wizardStep6Controller.set('wizardController', controller);
       var newStepIndex = controller.getStepIndex('step6');
       router.setNavigationFlow(newStepIndex);
       controller.setCurrentStep('step6');
-      var wizardStep6Controller = router.get('wizardStep6Controller');
       wizardStep6Controller.set('hosts', []);
-      wizardStep6Controller.set('wizardController', controller);
       controller.loadAllPriorSteps().done(function () {
+        controller.setStepsEnable();
         controller.connectOutlet('wizardStep6', controller.get('content'));
         self.scrollTop();
         console.timeEnd('step6 connectOutlets');
@@ -531,21 +655,18 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
   step7: App.StepRoute.extend({
     route: '/step7',
 
-    enter: function (router) {
-      console.time('step7 enter');
-      var controller = router.get('installerController');
-      controller.setCurrentStep('step7');
-      console.timeEnd('step7 enter');
-    },
-
     connectOutlets: function (router, context) {
       console.time('step7 connectOutlets');
       var self = this;
       var controller = router.get('installerController');
-      router.get('preInstallChecksController').loadStep();
       var wizardStep7Controller = router.get('wizardStep7Controller');
       wizardStep7Controller.set('wizardController', controller);
+      var newStepIndex = controller.getStepIndex('step7');
+      router.setNavigationFlow(newStepIndex);
+      controller.setCurrentStep('step7');     
+      router.get('preInstallChecksController').loadStep();
       controller.loadAllPriorSteps().done(function () {
+        controller.setStepsEnable();
         controller.connectOutlet('wizardStep7', controller.get('content'));
         self.scrollTop();
         console.timeEnd('step7 connectOutlets');
@@ -593,12 +714,15 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
     route: '/step8',
     connectOutlets: function (router, context) {
       console.time('step8 connectOutlets');
-      var controller = router.get('installerController');
       var self = this;
-      controller.setCurrentStep('step8');
+      var controller = router.get('installerController');
       var wizardStep8Controller = router.get('wizardStep8Controller');
       wizardStep8Controller.set('wizardController', controller);
+      var newStepIndex = controller.getStepIndex('step8');
+      router.setNavigationFlow(newStepIndex);
+      controller.setCurrentStep('step8');
       controller.loadAllPriorSteps().done(function () {
+        controller.setStepsEnable();
         controller.connectOutlet('wizardStep8', controller.get('content'));
         self.scrollTop();
         console.timeEnd('step8 connectOutlets');
@@ -630,6 +754,7 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
 
   step9: Em.Route.extend({
     route: '/step9',
+
     connectOutlets: function (router, context) {
       console.time('step9 connectOutlets');
       var self = this;
@@ -638,7 +763,10 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
       wizardStep9Controller.set('wizardController', controller);
       controller.loadAllPriorSteps().done(function () {
         wizardStep9Controller.loadDoServiceChecksFlag().done(function () {
+          var newStepIndex = controller.getStepIndex('step7');
+          router.setNavigationFlow(newStepIndex);
           controller.setCurrentStep('step9');
+          controller.setStepsEnable();
           if (!App.get('testMode')) {
             controller.setLowerStepsDisable(9);
           }
@@ -648,7 +776,9 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
         });
       });
     },
+
     back: Em.Router.transitionTo('step8'),
+
     retry: function (router) {
       console.time('step9 retry');
       var controller = router.get('installerController');
@@ -669,6 +799,7 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
         console.timeEnd('step9 retry');
       }
     },
+
     unroutePath: function (router, context) {
       // exclusion for transition to Admin view or Views view
       if (context === '/adminView' ||
@@ -678,6 +809,7 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
         return false;
       }
     },
+
     next: function (router) {
       console.time('step9 next');
       if(!router.get('btnClickInProgress')) {
@@ -694,19 +826,27 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
 
   step10: Em.Route.extend({
     route: '/step10',
+
     connectOutlets: function (router, context) {
       var self = this;
       var controller = router.get('installerController');
+      var wizardStep10Controller = router.get('wizardStep10Controller');
+      wizardStep10Controller.set('wizardController', controller);
       controller.loadAllPriorSteps().done(function () {
         if (!App.get('testMode')) {
+          var newStepIndex = controller.getStepIndex('step10');
+          router.setNavigationFlow(newStepIndex);
           controller.setCurrentStep('step10');
+          controller.setStepsEnable();
           controller.setLowerStepsDisable(10);
         }
         controller.connectOutlet('wizardStep10', controller.get('content'));
         self.scrollTop();
       });
     },
+    
     back: Em.Router.transitionTo('step9'),
+    
     complete: function (router, context) {
       var controller = router.get('installerController');
       controller.finish();
@@ -746,6 +886,12 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
 
   gotoSelectMpacks: Em.Router.transitionTo('selectMpacks'),
 
-  gotoDownloadProducts: Em.Router.transitionTo('downloadProducts')
+  gotoCustomMpackRepos: Em.Router.transitionTo('customMpackRepos'),
+
+  gotoDownloadMpacks: Em.Router.transitionTo('downloadMpacks'),
+
+  gotoCustomProductRepos: Em.Router.transitionTo('customProductRepos'),
+
+  gotoVerifyProducts: Em.Router.transitionTo('verifyProducts')
 
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/50e28dff/ambari-web/app/styles/theme/bootstrap-ambari.css
----------------------------------------------------------------------
diff --git a/ambari-web/app/styles/theme/bootstrap-ambari.css b/ambari-web/app/styles/theme/bootstrap-ambari.css
index 97419c7..3b1ebb2 100644
--- a/ambari-web/app/styles/theme/bootstrap-ambari.css
+++ b/ambari-web/app/styles/theme/bootstrap-ambari.css
@@ -301,6 +301,15 @@
 .dropdown .btn.dropdown-toggle[disabled] {
   opacity: 0.6;
 }
+.dropdown-menu > li > div {
+  display: block;
+  padding: 3px 20px;
+  clear: both;
+  font-weight: normal;
+  line-height: 1.42857143;
+  color: #333;
+  white-space: nowrap;
+}
 input.form-control {
   font-size: 14px;
   border-radius: 2px;
@@ -394,6 +403,10 @@ h2.table-title {
   top: 4px;
   margin-bottom: 0;
 }
+.table .dropdown input[type="checkbox"] + label {
+  font-size: inherit;
+  top: unset;
+}
 .table thead > tr > th {
   border-bottom-color: #EEE;
 }
@@ -585,6 +598,18 @@ h2.table-title {
   margin-bottom: -99999px;
   padding-bottom: 99999px;
 }
+
+.wizard .wizard-body .wizard-nav ol.nav {
+  list-style: none;
+  margin: 0;
+  padding: 0;
+  counter-reset: items;
+}
+.wizard .wizard-body .wizard-nav ol.nav li .step-index:before {
+  counter-increment: items;
+  content: counter(items);
+}
+
 .wizard .wizard-body .wizard-nav .nav li {
   padding: 0px 15px;
 }
@@ -638,7 +663,8 @@ h2.table-title {
   padding-left: 2px;
 }
 .wizard .wizard-body .wizard-nav .nav li.completed .step-marker .step-index {
-  display: none;
+  visibility: hidden;
+  position: absolute;
 }
 .wizard .wizard-body .wizard-nav .nav li.completed .step-marker:after {
   font-family: "Glyphicons Halflings";

http://git-wip-us.apache.org/repos/asf/ambari/blob/50e28dff/ambari-web/app/styles/wizard.less
----------------------------------------------------------------------
diff --git a/ambari-web/app/styles/wizard.less b/ambari-web/app/styles/wizard.less
index 4330c6a..d48a8b7 100644
--- a/ambari-web/app/styles/wizard.less
+++ b/ambari-web/app/styles/wizard.less
@@ -787,6 +787,20 @@
   }
 }
 
+#customProductRepos, #verifyProductRepos {
+  .table.table-hover > tbody {
+    > tr, > tr:hover > td {
+      border-width: 0;
+    }
+    > tr.mpack-firstOs.os-firstRepo {
+      border-top-width: 1px;
+    }
+    > tr:last-of-type {
+      border-bottom-width: 1px;
+    }
+  }
+}
+
 @media all and (max-width: 2560px) {
    .wizard-content {
     #serviceConfig {

http://git-wip-us.apache.org/repos/asf/ambari/blob/50e28dff/ambari-web/app/templates/installer.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/installer.hbs b/ambari-web/app/templates/installer.hbs
index 47e63cc..d93e55d 100644
--- a/ambari-web/app/templates/installer.hbs
+++ b/ambari-web/app/templates/installer.hbs
@@ -24,20 +24,23 @@
   <div class="wizard">
     <div class="wizard-body row">
       <div class="wizard-nav col-md-3">
-        <ul class="nav nav-pills nav-stacked" {{QAAttr "wizard-nav"}}>
-          <li {{QAAttr "wizard-nav-step"}} {{bindAttr class="isStep0:active view.isStep0Disabled:disabled view.isStep0Completed:completed"}}><a href="javascript:void(null);" {{action gotoStep0 target="controller"}}><i class="step-marker"><span class="step-index">0</span></i><p class="step-name">{{t installer.step0.header}}</p></a></li>
-          <li {{QAAttr "wizard-nav-step"}} {{bindAttr class="isStep2:active view.isStep2Disabled:disabled view.isStep2Completed:completed"}}><a href="javascript:void(null);" {{action gotoStep2 target="controller"}}><i class="step-marker"><span class="step-index">1</span></i><p class="step-name">{{t installer.step2.header}}</p></a></li>
-          <li {{QAAttr "wizard-nav-step"}} {{bindAttr class="isStep3:active view.isStep3Disabled:disabled view.isStep3Completed:completed"}}><a href="javascript:void(null);" {{action gotoStep3 target="controller"}}><i class="step-marker"><span class="step-index">2</span></i><p class="step-name">{{t installer.step3.header}}</p></a></li>
-          <li {{QAAttr "wizard-nav-step"}} {{bindAttr class="isConfigureDownload:active view.isConfigureDownloadDisabled:disabled view.isConfigureDownloadCompleted:completed"}}><a href="javascript:void(null);" {{action gotoConfigureDownload target="controller"}}><i class="step-marker"><span class="step-index">3</span></i><p class="step-name">{{t installer.configureDownload.header}}</p></a></li>
-          <li {{QAAttr "wizard-nav-step"}} {{bindAttr class="isSelectMpacks:active view.isSelectMpacksDisabled:disabled view.isSelectMpacksCompleted:completed"}}><a href="javascript:void(null);" {{action gotoSelectMpacks target="controller"}}><i class="step-marker"><span class="step-index">4</span></i><p class="step-name">{{t installer.selectMpacks.header}}</p></a></li>
-          <li {{QAAttr "wizard-nav-step"}} {{bindAttr class="isDownloadProducts:active view.isDownloadProductsDisabled:disabled view.isDownloadProductsCompleted:completed"}}><a href="javascript:void(null);" {{action gotoDownloadProducts target="controller"}}><i class="step-marker"><span class="step-index">5</span></i><p class="step-name">{{t installer.downloadProducts.header}}</p></a></li>
-          <li {{QAAttr "wizard-nav-step"}} {{bindAttr class="isStep5:active view.isStep5Disabled:disabled view.isStep5Completed:completed"}}><a href="javascript:void(null);" {{action gotoStep5 target="controller"}}><i class="step-marker"><span class="step-index">6</span></i><p class="step-name">{{t installer.step5.header}}</p></a></li>
-          <li {{QAAttr "wizard-nav-step"}} {{bindAttr class="isStep6:active view.isStep6Disabled:disabled view.isStep6Completed:completed"}}><a href="javascript:void(null);" {{action gotoStep6 target="controller"}}><i class="step-marker"><span class="step-index">7</span></i><p class="step-name">{{t installer.step6.header}}</p></a></li>
-          <li {{QAAttr "wizard-nav-step"}} {{bindAttr class="isStep7:active view.isStep7Disabled:disabled view.isStep7Completed:completed"}}><a href="javascript:void(null);" {{action gotoStep7 target="controller"}}><i class="step-marker"><span class="step-index">8</span></i><p class="step-name">{{t installer.step7.header}}</p></a></li>
-          <li {{QAAttr "wizard-nav-step"}} {{bindAttr class="isStep8:active view.isStep8Disabled:disabled view.isStep8Completed:completed"}}><a href="javascript:void(null);" {{action gotoStep8 target="controller"}}><i class="step-marker"><span class="step-index">9</span></i><p class="step-name">{{t installer.step8.header}}</p></a></li>
-          <li {{QAAttr "wizard-nav-step"}} {{bindAttr class="isStep9:active view.isStep9Disabled:disabled view.isStep9Completed:completed"}}><a href="javascript:void(null);" {{action gotoStep9 target="controller"}}><i class="step-marker"><span class="step-index">10</span></i><p class="step-name">{{t installer.step9.header}}</p></a></li>
-          <li {{QAAttr "wizard-nav-step"}} {{bindAttr class="isStep10:active view.isStep10Disabled:disabled view.isStep10Completed:completed"}}><a href="javascript:void(null);" {{action gotoStep10 target="controller"}}><i class="step-marker"><span class="step-index">11</span></i><p class="step-name">{{t installer.step10.header}}</p></a></li>
-        </ul>
+        <ol class="nav nav-pills nav-stacked" {{QAAttr "wizard-nav"}}>
+          <li {{QAAttr "wizard-nav-step"}} {{bindAttr class="isStep0:active view.isStep0Disabled:disabled view.isStep0Completed:completed"}}><a href="javascript:void(null);" {{action gotoStep0 target="controller"}}><i class="step-marker"><span class="step-index"></span></i><p class="step-name">{{t installer.step0.header}}</p></a></li>
+          <li {{QAAttr "wizard-nav-step"}} {{bindAttr class="isStep2:active view.isStep2Disabled:disabled view.isStep2Completed:completed"}}><a href="javascript:void(null);" {{action gotoStep2 target="controller"}}><i class="step-marker"><span class="step-index"></span></i><p class="step-name">{{t installer.step2.header}}</p></a></li>
+          <li {{QAAttr "wizard-nav-step"}} {{bindAttr class="isStep3:active view.isStep3Disabled:disabled view.isStep3Completed:completed"}}><a href="javascript:void(null);" {{action gotoStep3 target="controller"}}><i class="step-marker"><span class="step-index"></span></i><p class="step-name">{{t installer.step3.header}}</p></a></li>
+          <li {{QAAttr "wizard-nav-step"}} {{bindAttr class="isConfigureDownload:active view.isConfigureDownloadDisabled:disabled view.isConfigureDownloadCompleted:completed"}}><a href="javascript:void(null);" {{action gotoConfigureDownload target="controller"}}><i class="step-marker"><span class="step-index"></span></i><p class="step-name">{{t installer.configureDownload.header}}</p></a></li>
+          <li {{QAAttr "wizard-nav-step"}} {{bindAttr class="isSelectMpacks:active view.isSelectMpacksDisabled:disabled view.isSelectMpacksCompleted:completed"}}><a href="javascript:void(null);" {{action gotoSelectMpacks target="controller"}}><i class="step-marker"><span class="step-index"></span></i><p class="step-name">{{t installer.selectMpacks.header}}</p></a></li>
+          <li {{QAAttr "wizard-nav-step"}} {{bindAttr class="isCustomMpackRepos:active view.isCustomMpackReposDisabled:disabled view.isCustomMpackReposCompleted:completed"}}><a href="javascript:void(null);" {{action gotoCustomMpackRepos target="controller"}}><i class="step-marker"><span class="step-index"></span></i><p class="step-name">{{t installer.customMpackRepos.header}}</p></a></li>
+          <li {{QAAttr "wizard-nav-step"}} {{bindAttr class="isDownloadMpacks:active view.isDownloadMpacksDisabled:disabled view.isDownloadMpacksCompleted:completed"}}><a href="javascript:void(null);" {{action gotoDownloadMpacks target="controller"}}><i class="step-marker"><span class="step-index"></span></i><p class="step-name">{{t installer.downloadMpacks.header}}</p></a></li>
+          <li {{QAAttr "wizard-nav-step"}} {{bindAttr class="isCustomProductRepos:active view.isCustomProductReposDisabled:disabled view.isCustomProductReposCompleted:completed"}}><a href="javascript:void(null);" {{action gotoCustomProductRepos target="controller"}}><i class="step-marker"><span class="step-index"></span></i><p class="step-name">{{t installer.customProductRepos.header}}</p></a></li>
+          <li {{QAAttr "wizard-nav-step"}} {{bindAttr class="isVerifyProducts:active view.isVerifyProductsDisabled:disabled view.isVerifyProductsCompleted:completed"}}><a href="javascript:void(null);" {{action gotoVerifyProducts target="controller"}}><i class="step-marker"><span class="step-index"></span></i><p class="step-name">{{t installer.verifyProducts.header}}</p></a></li>
+          <li {{QAAttr "wizard-nav-step"}} {{bindAttr class="isStep5:active view.isStep5Disabled:disabled view.isStep5Completed:completed"}}><a href="javascript:void(null);" {{action gotoStep5 target="controller"}}><i class="step-marker"><span class="step-index"></span></i><p class="step-name">{{t installer.step5.header}}</p></a></li>
+          <li {{QAAttr "wizard-nav-step"}} {{bindAttr class="isStep6:active view.isStep6Disabled:disabled view.isStep6Completed:completed"}}><a href="javascript:void(null);" {{action gotoStep6 target="controller"}}><i class="step-marker"><span class="step-index"></span></i><p class="step-name">{{t installer.step6.header}}</p></a></li>
+          <li {{QAAttr "wizard-nav-step"}} {{bindAttr class="isStep7:active view.isStep7Disabled:disabled view.isStep7Completed:completed"}}><a href="javascript:void(null);" {{action gotoStep7 target="controller"}}><i class="step-marker"><span class="step-index"></span></i><p class="step-name">{{t installer.step7.header}}</p></a></li>
+          <li {{QAAttr "wizard-nav-step"}} {{bindAttr class="isStep8:active view.isStep8Disabled:disabled view.isStep8Completed:completed"}}><a href="javascript:void(null);" {{action gotoStep8 target="controller"}}><i class="step-marker"><span class="step-index"></span></i><p class="step-name">{{t installer.step8.header}}</p></a></li>
+          <li {{QAAttr "wizard-nav-step"}} {{bindAttr class="isStep9:active view.isStep9Disabled:disabled view.isStep9Completed:completed"}}><a href="javascript:void(null);" {{action gotoStep9 target="controller"}}><i class="step-marker"><span class="step-index"></span></i><p class="step-name">{{t installer.step9.header}}</p></a></li>
+          <li {{QAAttr "wizard-nav-step"}} {{bindAttr class="isStep10:active view.isStep10Disabled:disabled view.isStep10Completed:completed"}}><a href="javascript:void(null);" {{action gotoStep10 target="controller"}}><i class="step-marker"><span class="step-index"></span></i><p class="step-name">{{t installer.step10.header}}</p></a></li>
+        </ol>
       </div>
         {{! outlet includes body and footer }}
       {{outlet}}

http://git-wip-us.apache.org/repos/asf/ambari/blob/50e28dff/ambari-web/app/templates/wizard/customMpackRepos.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/wizard/customMpackRepos.hbs b/ambari-web/app/templates/wizard/customMpackRepos.hbs
new file mode 100644
index 0000000..59c5f90
--- /dev/null
+++ b/ambari-web/app/templates/wizard/customMpackRepos.hbs
@@ -0,0 +1,78 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+
+<div id="customMpackRepos" class="wizard-content col-md-9" {{QAAttr "select-stack-page"}}>
+  <h4 class="step-header">{{t installer.customMpackRepos.header}}</h4>
+
+  <div class="panel panel-default">
+    <div class="panel-body">
+      {{#if App.router.nextBtnClickInProgress}}
+        {{view App.SpinnerView}}
+      {{else}}
+        <div class="panel panel-default">
+          <div class="step-title">
+            <p>{{t installer.customMpackRepos.body.title}}</p>
+          </div>
+          <p class="step-description">{{t installer.customMpackRepos.body.description}}</p>
+
+          <div class="panel-body version-contents-body">
+            <table class="table table-hover">
+              <thead>
+                <tr>
+                  <th class="col-sm-4">{{t common.mpack}}</th>
+                  <th class="col-sm-2">{{t common.public}} {{t common.link}}</th>
+                  <th class="col-sm-6">{{t common.download}} {{t common.url}}</th>
+                </tr>
+              </thead>
+              <tbody>
+                {{#each mpack in mpacks}}
+                <tr>
+                  <td class="col-sm-4">{{mpack.displayName}}&nbsp;{{mpack.version}}</td>
+                  <td class="col-sm-2">
+                    <a target="_blank" {{bindAttr href="mpack.publicUrl"}}><span class="glyphicon glyphicon-new-window"></span></a>
+                  </td>
+                  <td class="col-sm-6">
+                    {{view Em.TextField class="form-control required" valueBinding="mpack.downloadUrl"}} <button type="button" {{bindAttr title="view.revertButtonTooltip" value="mpack.id"}} {{action revertUrl target="view"}}><span class="glyphicon glyphicon-repeat" style="transform: scaleX(-1)"></span></button>
+                  </td>
+                </tr>
+                {{/each}}
+              </tbody>
+            </table>
+          </div>
+        </div>
+      {{/if}}
+
+    </div>
+  </div>
+
+</div>
+
+<div class="wizard-footer col-md-12">
+  <button type="button" class="btn btn-default pull-left installer-back-btn" {{bindAttr disabled="App.router.btnClickInProgress"}} {{action back}} {{QAAttr "wizard-back"}}>
+    &larr; {{t common.back}}
+    {{#if App.router.backBtnClickInProgress}}
+      {{view App.SpinnerView tagName="span" classNames="service-button-spinner"}}
+    {{/if}}
+  </button>
+  <button type="button" class="btn btn-success pull-right" {{bindAttr disabled="controller.isSubmitDisabled"}} {{action submit target="controller"}} {{QAAttr "wizard-next"}}>
+    {{#if App.router.nextBtnClickInProgress}}
+      {{view App.SpinnerView tagName="span" classNames="service-button-spinner"}}
+    {{/if}}
+    {{t common.next}} &rarr;
+  </button>
+</div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/50e28dff/ambari-web/app/templates/wizard/customProductRepos.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/wizard/customProductRepos.hbs b/ambari-web/app/templates/wizard/customProductRepos.hbs
new file mode 100644
index 0000000..c4bb9ac
--- /dev/null
+++ b/ambari-web/app/templates/wizard/customProductRepos.hbs
@@ -0,0 +1,120 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+
+<div id="customProductRepos" class="wizard-content col-md-9" {{QAAttr "select-stack-page"}}>
+  <h4 class="step-header">{{t installer.customProductRepos.header}}</h4>
+
+  <div class="panel panel-default">
+    <div class="panel-body">
+      {{#if App.router.nextBtnClickInProgress}}
+        {{view App.SpinnerView}}
+      {{else}}
+        <div class="panel panel-default">
+          <div class="step-title">
+            <p>{{t installer.customProductRepos.body.title}}</p>
+          </div>
+          <p class="step-description">{{t installer.customProductRepos.body.description}}</p>
+
+          <div class="panel-body version-contents-body">
+            <table class="table table-hover">
+              <thead>
+                <tr>
+                  <th class="col-sm-2">{{t common.mpack}}</th>
+                  <th class="col-sm-1">{{t common.operatingSystem}}</th>
+                  <th class="col-sm-1">{{t common.repository}}</th>
+                  <th class="col-sm-1">{{t common.public}} {{t common.link}}</th>
+                  <th class="col-sm-7">
+                    {{t common.download}} {{t common.url}} 
+                    <div class="dropdown pull-right">
+                      <button id="osMenu" type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">{{t installer.customProductRepos.addRemoveOs}}</button>
+                      <ul class="dropdown-menu" aria-labelledby="osMenu">
+                        {{#each os in operatingSystems}}
+                        <li>
+                          {{view App.CheckboxView nameBinding="os.type" checkedBinding="os.selected" labelBinding="os.type" changeBinding="view.selectedOsChanged"}}
+                        </li>
+                        {{/each}}
+                      </ul>
+                    </div>
+                  </th>
+                </tr>
+              </thead>
+              <tbody>
+                {{#if controller.anySelectedOs}}
+                  {{#each mpack in mpacks}}
+                    {{#each os in mpack.operatingSystems}}
+                      {{#if os.selected}}
+                        {{#each repo in os.repos}}
+                        <tr {{bindAttr class="os.isFirstSelected:mpack-firstOs repo.isFirst:os-firstRepo"}}>
+                          {{#if os.isFirstSelected}}
+                            {{#if repo.isFirst}}
+                            <td class="col-sm-2">{{mpack.displayName}}&nbsp;{{mpack.version}}</td>
+                            {{else}}
+                            <td class="col-sm-2"></td>
+                            {{/if}}
+                          {{else}}
+                          <td class="col-sm-2"></td>
+                          {{/if}}
+                          {{#if repo.isFirst}}
+                          <td class="col-sm-1">{{os.type}}</td>
+                          {{else}}
+                          <td class="col-sm-1"></td>
+                          {{/if}}
+                          <td class="col-sm-1">{{repo.repoId}}</td>
+                          <td class="col-sm-1">
+                            <a target="_blank" {{bindAttr href="repo.publicUrl"}}><span class="glyphicon glyphicon-new-window"></span></a>
+                          </td>
+                          <td class="col-sm-7">
+                            {{view Em.TextField class="form-control required" valueBinding="repo.downloadUrl"}} <button type="button" {{bindAttr title="view.revertButtonTooltip" value="repo.id"}} {{action revertUrl target="view"}}><span class="glyphicon glyphicon-repeat" style="transform: scaleX(-1)"></span></button>
+                          </td>
+                        </tr>
+                        {{/each}}
+                      {{/if}}
+                    {{/each}}
+                  {{/each}}
+                {{else}}
+                <tr>
+                  <td class="table-placeholder" colspan="5">
+                    {{t installer.customProductRepos.noSelectedOs}}
+                  </td>
+                </tr>
+                {{/if}}
+              </tbody>
+            </table>
+          </div>
+        </div>
+      {{/if}}
+
+    </div>
+  </div>
+
+</div>
+
+<div class="wizard-footer col-md-12">
+  <button type="button" class="btn btn-default pull-left installer-back-btn" {{bindAttr disabled="App.router.btnClickInProgress"}} {{action back}} {{QAAttr "wizard-back"}}>
+    &larr; {{t common.back}}
+    {{#if App.router.backBtnClickInProgress}}
+      {{view App.SpinnerView tagName="span" classNames="service-button-spinner"}}
+    {{/if}}
+  </button>
+  <button type="button" class="btn btn-success pull-right" {{bindAttr disabled="controller.isSubmitDisabled"}} {{action submit target="controller"}} {{QAAttr "wizard-next"}}>
+    {{#if App.router.nextBtnClickInProgress}}
+      {{view App.SpinnerView tagName="span" classNames="service-button-spinner"}}
+    {{/if}}
+    {{t common.next}} &rarr;
+  </button>
+</div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/50e28dff/ambari-web/app/templates/wizard/downloadMpacks.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/wizard/downloadMpacks.hbs b/ambari-web/app/templates/wizard/downloadMpacks.hbs
new file mode 100644
index 0000000..4d570fd
--- /dev/null
+++ b/ambari-web/app/templates/wizard/downloadMpacks.hbs
@@ -0,0 +1,97 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+
+<div id="download-step-content" class="wizard-content col-md-9" {{QAAttr "select-stack-page"}}>
+  <h4 class="step-header">{{t installer.downloadMpacks.header}}</h4>
+
+  <div class="panel panel-default">
+    <div class="panel-body">
+      {{#if App.router.nextBtnClickInProgress}}
+        {{view App.SpinnerView}}
+      {{else}}
+        <div class="panel panel-default">
+          <div class="step-title">
+            <p>{{t installer.downloadMpacks.body.title}}</p>
+          </div>
+          <p class="step-description">{{t installer.downloadMpacks.body.description}}</p>
+
+          <div class="panel-body version-contents-body">
+            <table class="table table-hover">
+              <thead>
+                <tr>
+                  <th class="col-sm-5">{{t common.mpack}}</th>
+                  <th class="col-sm-4">{{t common.status}}</th>
+                  <th class="col-sm-2">{{t common.actions}}</th>
+                </tr>
+              </thead>
+              <tbody>
+                {{#each mpack in mpacks}}
+                  <tr>
+                    <td class="col-sm-5">{{mpack.displayName}}&nbsp;{{mpack.version}}</td>
+                    <td class="download-status col-sm-4">
+                      {{#if mpack.inProgress}}
+                        <div class="progress-wrapper col-sm-8">
+                          <div class="progress">
+                            <div class="active progress-bar-striped progress-bar"}}></div>
+                          </div>
+                        </div>
+                      {{else}}
+                        {{#if mpack.succeeded}}
+                          <i class="glyphicon glyphicon-ok"></i>&nbsp;
+                          {{t common.download}}&nbsp;{{t common.complete}}
+                        {{else}}
+                          <i class="glyphicon glyphicon-remove"></i>&nbsp;
+                          {{t common.download}}&nbsp;{{t common.failed}}
+                        {{/if}}
+                      {{/if}}
+                    </td>
+                    <td class="col-sm-2">
+                      {{#if mpack.failed}}
+                        <button type="button" class="btn btn-default btn-xs" {{action retryDownload mpack target="controller"}}>
+                          <i class="icon icon-repeat"></i>
+                          {{t common.retry}}
+                        </button>
+                      {{/if}}
+                    </td>
+                  </tr>
+                {{/each}}
+              </tbody>
+            </table>
+          </div>
+        </div>
+      {{/if}}
+
+    </div>
+  </div>
+
+</div>
+
+<div class="wizard-footer col-md-12">
+  <button type="button" class="btn btn-default pull-left installer-back-btn" {{bindAttr disabled="App.router.btnClickInProgress"}} {{action back}} {{QAAttr "wizard-back"}}>
+    &larr; {{t common.back}}
+    {{#if App.router.backBtnClickInProgress}}
+      {{view App.SpinnerView tagName="span" classNames="service-button-spinner"}}
+    {{/if}}
+  </button>
+  <button type="button" class="btn btn-success pull-right" {{bindAttr disabled="controller.isSubmitDisabled"}} {{action submit target="controller"}} {{QAAttr "wizard-next"}}>
+    {{#if App.router.nextBtnClickInProgress}}
+      {{view App.SpinnerView tagName="span" classNames="service-button-spinner"}}
+    {{/if}}
+    {{t common.next}} &rarr;
+  </button>
+</div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/50e28dff/ambari-web/app/templates/wizard/downloadProducts.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/wizard/downloadProducts.hbs b/ambari-web/app/templates/wizard/downloadProducts.hbs
deleted file mode 100644
index a426225..0000000
--- a/ambari-web/app/templates/wizard/downloadProducts.hbs
+++ /dev/null
@@ -1,97 +0,0 @@
-{{!
-* Licensed to the Apache Software Foundation (ASF) under one
-* or more contributor license agreements.  See the NOTICE file
-* distributed with this work for additional information
-* regarding copyright ownership.  The ASF licenses this file
-* to you under the Apache License, Version 2.0 (the
-* "License"); you may not use this file except in compliance
-* with the License.  You may obtain a copy of the License at
-*
-*     http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-}}
-
-<div id="download-step-content" class="wizard-content col-md-9" {{QAAttr "select-stack-page"}}>
-  <h4 class="step-header">{{t installer.downloadProducts.header}}</h4>
-
-  <div class="panel panel-default">
-    <div class="panel-body">
-      {{#if App.router.nextBtnClickInProgress}}
-        {{view App.SpinnerView}}
-      {{else}}
-        <div class="panel panel-default">
-          <div class="step-title">
-            <p>{{t installer.downloadProducts.body.title}}</p>
-          </div>
-          <p class="step-description">{{t installer.downloadProducts.body.description}}</p>
-
-          <div class="panel-body version-contents-body">
-            <table class="table table-hover">
-              <thead>
-                <tr>
-                  <th class="col-sm-5">{{t common.mpack}}</th>
-                  <th class="col-sm-4">{{t common.status}}</th>
-                  <th class="col-sm-2">{{t common.actions}}</th>
-                </tr>
-              </thead>
-              <tbody>
-                {{#each mpack in mpacks}}
-                  <tr>
-                    <td class="col-sm-5">{{mpack.displayName}}&nbsp;{{mpack.version}}</td>
-                    <td class="download-status col-sm-4">
-                      {{#if mpack.inProgress}}
-                        <div class="progress-wrapper col-sm-8">
-                          <div class="progress">
-                            <div class="active progress-bar-striped progress-bar"}}></div>
-                          </div>
-                        </div>
-                      {{else}}
-                        {{#if mpack.success}}
-                          <i class="glyphicon glyphicon-ok"></i>&nbsp;
-                          {{t common.download}}&nbsp;{{t common.complete}}
-                        {{else}}
-                          <i class="glyphicon glyphicon-remove"></i>&nbsp;
-                          {{t common.download}}&nbsp;{{t common.failed}}
-                        {{/if}}
-                      {{/if}}
-                    </td>
-                    <td class="col-sm-2">
-                      {{#if mpack.failed}}
-                        <button type="button" class="btn btn-default btn-xs" {{action retryDownload mpack target="controller"}}>
-                          <i class="icon icon-repeat"></i>
-                          {{t common.retry}}
-                        </button>
-                      {{/if}}
-                    </td>
-                  </tr>
-                {{/each}}
-              </tbody>
-            </table>
-          </div>
-        </div>
-      {{/if}}
-
-    </div>
-  </div>
-
-</div>
-
-<div class="wizard-footer col-md-12">
-  <button type="button" class="btn btn-default pull-left installer-back-btn" {{bindAttr disabled="App.router.btnClickInProgress"}} {{action back}} {{QAAttr "wizard-back"}}>
-    &larr; {{t common.back}}
-    {{#if App.router.backBtnClickInProgress}}
-      {{view App.SpinnerView tagName="span" classNames="service-button-spinner"}}
-    {{/if}}
-  </button>
-  <button type="button" class="btn btn-success pull-right" {{bindAttr disabled="controller.isSubmitDisabled"}} {{action submit target="controller"}} {{QAAttr "wizard-next"}}>
-    {{#if App.router.nextBtnClickInProgress}}
-      {{view App.SpinnerView tagName="span" classNames="service-button-spinner"}}
-    {{/if}}
-    {{t common.next}} &rarr;
-  </button>
-</div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/50e28dff/ambari-web/app/templates/wizard/selectMpacks.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/wizard/selectMpacks.hbs b/ambari-web/app/templates/wizard/selectMpacks.hbs
index d78861e..1dc6bad 100644
--- a/ambari-web/app/templates/wizard/selectMpacks.hbs
+++ b/ambari-web/app/templates/wizard/selectMpacks.hbs
@@ -16,7 +16,7 @@
 * limitations under the License.
 }}
 <div id="select-mpacks" class="wizard-content col-md-9">
-  <h4 class="step-title">{{t installer.selectMpacks.body.header}}</h4>
+  <h4 class="step-header">{{t installer.selectMpacks.body.header}}</h4>
   {{#if isSaved}}
   <div class="alert alert-warning" role="alert"><strong>{{t installer.warning.changes.header}}</strong> {{t installer.warning.changes}}</div>
   {{/if}}

http://git-wip-us.apache.org/repos/asf/ambari/blob/50e28dff/ambari-web/app/templates/wizard/verifyProducts.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/wizard/verifyProducts.hbs b/ambari-web/app/templates/wizard/verifyProducts.hbs
new file mode 100644
index 0000000..685d447
--- /dev/null
+++ b/ambari-web/app/templates/wizard/verifyProducts.hbs
@@ -0,0 +1,117 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+
+<div id="verifyProductRepos" class="wizard-content col-md-9" {{QAAttr "select-stack-page"}}>
+  <h4 class="step-header">{{t installer.verifyProducts.header}}</h4>
+
+  <div class="panel panel-default">
+    <div class="panel-body">
+      {{#if App.router.nextBtnClickInProgress}}
+        {{view App.SpinnerView}}
+      {{else}}
+        <div class="panel panel-default">
+          <div class="step-title">
+            <p>{{t installer.customProductRepos.body.title}}</p>
+          </div>
+          <p class="step-description">{{t installer.customProductRepos.body.description}}</p>
+        
+          <div class="panel-body version-contents-body">
+            <table class="table table-hover">
+              <thead>
+                <tr>
+                  <th class="col-sm-3">{{t common.mpack}}</th>
+                  <th class="col-sm-1">{{t common.operatingSystem}}</th>
+                  <th class="col-sm-3">{{t common.repository}}</th>
+                  <th class="col-sm-3">{{t common.status}}</th>
+                  <th class="col-sm-2">{{t common.actions}}</th>
+                </tr>
+              </thead>
+              <tbody>
+                {{#each mpack in mpacks}} 
+                  {{#each os in mpack.operatingSystems}} 
+                    {{#if os.selected}} 
+                      {{#each repo in os.repos}}
+                      <tr {{bindAttr class="os.isFirstSelected:mpack-firstOs repo.isFirst:os-firstRepo" }}>
+                        {{#if os.isFirstSelected}} 
+                          {{#if repo.isFirst}}
+                          <td class="col-sm-3">{{mpack.displayName}}&nbsp;{{mpack.version}}</td>
+                          {{else}}
+                          <td class="col-sm-3"></td>
+                          {{/if}} 
+                        {{else}}
+                        <td class="col-sm-3"></td>
+                        {{/if}} 
+                        {{#if repo.isFirst}}
+                        <td class="col-sm-1">{{os.type}}</td>
+                        {{else}}
+                        <td class="col-sm-1"></td>
+                        {{/if}}
+                        <td class="col-sm-3">{{repo.repoId}}</td>
+                        <td class="download-status col-sm-3">
+                          {{#if repo.inProgress}}
+                            <div class="progress-wrapper col-sm-8">
+                              <div class="progress">
+                                <div class="active progress-bar-striped progress-bar"}}></div>
+                              </div>
+                            </div>
+                          {{else}}
+                            {{#if repo.succeeded}}
+                              <i class="glyphicon glyphicon-ok"></i>&nbsp;
+                              {{t common.verification}}&nbsp;{{t common.complete}}
+                            {{else}}
+                              <i class="glyphicon glyphicon-remove"></i>&nbsp;
+                              {{t common.verification}}&nbsp;{{t common.failed}}
+                            {{/if}}
+                          {{/if}}
+                        </td>
+                        <td class="col-sm-2">
+                          {{#if repo.failed}}
+                            <button type="button" class="btn btn-default btn-xs" {{action retryVerifyRepo repo target="controller"}}>
+                              <i class="icon icon-repeat"></i>
+                              {{t common.retry}}
+                            </button>
+                          {{/if}}
+                        </td>
+                      </tr>
+                      {{/each}} 
+                    {{/if}} 
+                  {{/each}}
+                {{/each}}
+              </tbody>
+            </table>
+          </div>
+        </div>
+      {{/if}}
+      </div>
+    </div>
+</div>
+
+<div class="wizard-footer col-md-12">
+  <button type="button" class="btn btn-default pull-left installer-back-btn" {{bindAttr disabled="App.router.btnClickInProgress"}} {{action back}} {{QAAttr "wizard-back"}}>
+    &larr; {{t common.back}}
+    {{#if App.router.backBtnClickInProgress}}
+      {{view App.SpinnerView tagName="span" classNames="service-button-spinner"}}
+    {{/if}}
+  </button>
+  <button type="button" class="btn btn-success pull-right" {{bindAttr disabled="controller.isSubmitDisabled"}} {{action submit target="controller"}} {{QAAttr "wizard-next"}}>
+    {{#if App.router.nextBtnClickInProgress}}
+      {{view App.SpinnerView tagName="span" classNames="service-button-spinner"}}
+    {{/if}}
+    {{t common.next}} &rarr;
+  </button>
+</div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/50e28dff/ambari-web/app/views.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views.js b/ambari-web/app/views.js
index 8810f13..a198c56 100644
--- a/ambari-web/app/views.js
+++ b/ambari-web/app/views.js
@@ -368,7 +368,11 @@ require('views/wizard/step3/hostLogPopupBody_view');
 require('views/wizard/step3/hostWarningPopupBody_view');
 require('views/wizard/step3/hostWarningPopupFooter_view');
 require('views/wizard/configureDownload_view');
-require('views/wizard/downloadProducts_view');
+require('views/wizard/selectMpacks_view');
+require('views/wizard/customMpackRepos_view');
+require('views/wizard/downloadMpacks_view');
+require('views/wizard/customProductRepos_view');
+require('views/wizard/verifyProducts_view');
 require('views/wizard/step4_view');
 require('views/wizard/step5_view');
 require('views/wizard/step6_view');
@@ -379,7 +383,6 @@ require('views/wizard/step8_view');
 require('views/wizard/step9_view');
 require('views/wizard/step9/hostLogPopupBody_view');
 require('views/wizard/step10_view');
-require('views/wizard/selectMpacks_view');
 require('views/loading');
 
 require('views/experimental');

http://git-wip-us.apache.org/repos/asf/ambari/blob/50e28dff/ambari-web/app/views/wizard/configureDownload_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/wizard/configureDownload_view.js b/ambari-web/app/views/wizard/configureDownload_view.js
index 71c6527..3ff649f 100644
--- a/ambari-web/app/views/wizard/configureDownload_view.js
+++ b/ambari-web/app/views/wizard/configureDownload_view.js
@@ -38,10 +38,19 @@ App.WizardConfigureDownloadView = Em.View.extend({
     this.setProxyAuth(selectedProxyAuth, true);
   },
 
-  useRedHatSatelliteChanged: function () {
+  useRedHatSatelliteChanged: function (event) {
     this.set('controller.content.downloadConfig.useProxy', false);
     const self = this.useProxyChanged ? this : this.get('parentView'); //parentView is actually just this view, but this function gets called from a sub-view on the template so we have to reference this way
     self.useProxyChanged();
+
+    if (event && event.currentTarget && event.currentTarget.checked) {
+      App.ModalPopup.show({
+        header: Em.I18n.t('common.important'),
+        encodeBody: false,
+        secondary: false,
+        body: Em.I18n.t('installer.step1.advancedRepo.useRedhatSatellite.warning')
+      });
+    }
   },
 
   useProxyChanged: function () {

http://git-wip-us.apache.org/repos/asf/ambari/blob/50e28dff/ambari-web/app/views/wizard/customMpackRepos_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/wizard/customMpackRepos_view.js b/ambari-web/app/views/wizard/customMpackRepos_view.js
new file mode 100644
index 0000000..b4bf357
--- /dev/null
+++ b/ambari-web/app/views/wizard/customMpackRepos_view.js
@@ -0,0 +1,35 @@
+/**
+ * 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.WizardCustomMpackReposView = Em.View.extend({
+
+  templateName: require('templates/wizard/customMpackRepos'),
+
+  didInsertElement: function () {
+    this._super();
+  },
+
+  revertButtonTooltip: Em.I18n.t('common.revert'),
+
+  revertUrl: function (event) {
+    const mpackId = event.currentTarget.value;
+    const mpack = this.get('controller.mpacks').findProperty('id', mpackId);
+    Em.set(mpack, 'downloadUrl', mpack.publicUrl);
+  }
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/50e28dff/ambari-web/app/views/wizard/customProductRepos_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/wizard/customProductRepos_view.js b/ambari-web/app/views/wizard/customProductRepos_view.js
new file mode 100644
index 0000000..9de257c
--- /dev/null
+++ b/ambari-web/app/views/wizard/customProductRepos_view.js
@@ -0,0 +1,73 @@
+/**
+ * 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.WizardCustomProductReposView = Em.View.extend({
+
+  templateName: require('templates/wizard/customProductRepos'),
+
+  didInsertElement: function () {
+    this._super();
+    this.get('controller').loadStep();
+    
+    const operatingSystems = this.get('controller.operatingSystems'); 
+    operatingSystems.forEach(os => this.updateOsState(os.get('type')));
+  },
+
+  /**
+   *  Change first and last selected flags now that we've changed the selection.
+   *  This is used by the template to display the first and last items differently.
+   */
+  updateOsState: function (osType) {
+    const os = this.get('controller.operatingSystems').findProperty('type', osType);
+    
+    if (os) {
+      const mpacks = os.get('mpacks');
+      mpacks.forEach(mpack => {
+        const selectedOperatingSystems = mpack.get('operatingSystems').filterProperty('selected');
+        selectedOperatingSystems.forEach((os, index, array) => {
+          if (index === 0) {
+            os.set('isFirstSelected', true);
+          } else {
+            os.set('isFirstSelected', false);
+          }
+
+          if (index === array.length - 1) {
+            os.set('isLastSelected', true);
+          } else {
+            os.set('isLastSelected', false);
+          }
+        });
+      });
+    }
+  },
+
+  revertButtonTooltip: Em.I18n.t('common.revert'),
+
+  revertUrl: function (event) {
+    const repoId = event.currentTarget.value;
+    const repo = this.get('controller').findRepoById(repoId);
+    repo.set('downloadUrl', repo.get('publicUrl'));
+  },
+
+  selectedOsChanged: function (event) {
+    const os = event.srcElement.name;
+    this.get('controller').toggleOs(os);
+    this.get('parentView').updateOsState(os);
+  }
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/50e28dff/ambari-web/app/views/wizard/downloadMpacks_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/wizard/downloadMpacks_view.js b/ambari-web/app/views/wizard/downloadMpacks_view.js
new file mode 100644
index 0000000..76c6142
--- /dev/null
+++ b/ambari-web/app/views/wizard/downloadMpacks_view.js
@@ -0,0 +1,35 @@
+/**
+ * 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.WizardDownloadMpacksView = Em.View.extend({
+
+  templateName: require('templates/wizard/downloadMpacks'),
+
+  didInsertElement: function () {
+    this._super();
+    var controller = this.get('controller');
+    controller.addMpacks();
+    controller.registerMpacks();
+  },
+
+  willDestroyElement: function () {
+    this.get('controller.mpacks').clear();
+  }
+
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/50e28dff/ambari-web/app/views/wizard/downloadProducts_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/wizard/downloadProducts_view.js b/ambari-web/app/views/wizard/downloadProducts_view.js
deleted file mode 100644
index b70275a..0000000
--- a/ambari-web/app/views/wizard/downloadProducts_view.js
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * 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.WizardDownloadProductsView = Em.View.extend({
-
-  templateName: require('templates/wizard/downloadProducts'),
-
-  didInsertElement: function () {
-    this._super();
-    var controller = this.get('controller');
-    controller.addMpacks();
-    controller.registerMpacks();
-  },
-
-  willDestroyElement: function () {
-    this.get('controller.mpacks').clear();
-  }
-
-});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/50e28dff/ambari-web/app/views/wizard/verifyProducts_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/wizard/verifyProducts_view.js b/ambari-web/app/views/wizard/verifyProducts_view.js
new file mode 100644
index 0000000..fd5bb1d
--- /dev/null
+++ b/ambari-web/app/views/wizard/verifyProducts_view.js
@@ -0,0 +1,33 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+var App = require('app');
+
+App.WizardVerifyProductsView = Em.View.extend({
+
+  templateName: require('templates/wizard/verifyProducts'),
+
+  didInsertElement: function () {
+    this._super();
+    this.get('controller').loadStep();
+  },
+
+  verifyRepo: function (event) {
+    const repo = event.target; //something like that
+    this.get('controller').verifyRepo(repo);
+  }
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/50e28dff/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 88289b2..575ad06 100644
--- a/ambari-web/test/controllers/installer_test.js
+++ b/ambari-web/test/controllers/installer_test.js
@@ -398,31 +398,32 @@ describe('App.InstallerController', function () {
   })
 
   describe('#setStepsEnable', function() {
-
     beforeEach(function () {
       var steps = Em.A([
         Em.Object.create({
           step: 0,
-          value: false
+          value: true
         }),
         Em.Object.create({
           step: 1,
-          value: false
+          value: true
         }),
         Em.Object.create({
           step: 2,
-          value: false
+          value: true
         }),
         Em.Object.create({
           step: 3,
-          value: false
+          value: true
         }),
         Em.Object.create({
           step: 4,
-          value: false
+          value: true
         })
       ]);
+      
       installerController.set('isStepDisabled', steps);
+      
       installerController.set('steps', [
         "step0",
         "step1",
@@ -430,11 +431,19 @@ describe('App.InstallerController', function () {
         "step3",
         "step4"
       ]);
-      //installerController.totalSteps = steps.length - 1;
-      installerController.set('currentStep',2);
+      
+      installerController.set('currentStep', 2);
     });
 
-    it ('Should enable next steps', function() {
+    it('Should enable next steps', function() {
+      var stepController = Em.Object.create({
+        isStepDisabled: function () {
+          return false;
+        }
+      });
+
+      sinon.stub(installerController, 'getStepController').returns(stepController);
+
       var expected = [
         {
           "step": 0,
@@ -442,23 +451,28 @@ describe('App.InstallerController', function () {
         },
         {
           "step": 1,
-          "value": true
+          "value": false
         },
         {
           "step": 2,
-          "value": true
+          "value": false
         },
         {
           "step": 3,
-          "value": true
+          "value": false
         },
         {
           "step": 4,
-          "value": true
+          "value": false
         }
       ];
+
+      installerController.setStepsEnable();
+
       var res = JSON.parse(JSON.stringify(installerController.get('isStepDisabled')));
       expect(res).to.eql(expected);
+
+      installerController.getStepController.restore();
     });
   });
 
@@ -544,7 +558,7 @@ describe('App.InstallerController', function () {
       };
 
       beforeEach(function () {
-        installerController.loadMap['step5'][1].callback.call(checker);
+        installerController.loadMap['step5'][0].callback.call(checker);
       });
 
       it('confirmed hosts are loaded', function() {

http://git-wip-us.apache.org/repos/asf/ambari/blob/50e28dff/ambari-web/test/controllers/wizard/selectMpacks_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/wizard/selectMpacks_test.js b/ambari-web/test/controllers/wizard/selectMpacks_test.js
index 13e28ce..963a0f0 100644
--- a/ambari-web/test/controllers/wizard/selectMpacks_test.js
+++ b/ambari-web/test/controllers/wizard/selectMpacks_test.js
@@ -1025,15 +1025,19 @@ describe('App.WizardSelectMpacksController', function () {
 
       var expectedSelectedMpacks = [
         {
+          id: "mpackName1-1.0.0.0",
           name: "mpackName1",
           displayName: "displayName1",
-          url: "http://someurl.com/mpack1",
+          publicUrl: "http://someurl.com/mpack1",
+          downloadUrl: "http://someurl.com/mpack1",
           version: "1.0.0.0"
         },
         {
+          id: "mpackName2-1.0.0.0",
           name: "mpackName2",
           displayName: "displayName2",
-          url: "http://someurl.com/mpack2",
+          publicUrl: "http://someurl.com/mpack2",
+          downloadUrl: "http://someurl.com/mpack2",
           version: "1.0.0.0"
         }
       ];


Mime
View raw message