|
@@ -20,7 +20,6 @@ var App = require('app');
|
|
|
var numberUtils = require('utils/number_utils');
|
|
|
|
|
|
App.WizardStep5Controller = Em.Controller.extend({
|
|
|
-
|
|
|
name: "wizardStep5Controller",
|
|
|
|
|
|
/**
|
|
@@ -215,11 +214,20 @@ App.WizardStep5Controller = Em.Controller.extend({
|
|
|
console.log("WizardStep5Controller: Loading step5: Assign Masters");
|
|
|
this.clearStep();
|
|
|
this.renderHostInfo();
|
|
|
- this.renderComponents(this.loadComponents());
|
|
|
- this.get('addableComponents').forEach(function (componentName) {
|
|
|
- this.updateComponent(componentName);
|
|
|
- }, this);
|
|
|
- if (!this.get("selectedServicesMasters").filterProperty('isInstalled', false).length) {
|
|
|
+ this.loadComponentRecommendations(this.loadStepCallback);
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Callback after load controller data (hosts, host components etc)
|
|
|
+ * @method loadStepCallback
|
|
|
+ */
|
|
|
+ loadStepCallback: function(components, self) {
|
|
|
+ self.renderComponents(components);
|
|
|
+
|
|
|
+ self.get('addableComponents').forEach(function (componentName) {
|
|
|
+ self.updateComponent(componentName);
|
|
|
+ }, self);
|
|
|
+ if (!self.get("selectedServicesMasters").filterProperty('isInstalled', false).length) {
|
|
|
console.log('no master components to add');
|
|
|
App.router.send('next');
|
|
|
}
|
|
@@ -289,81 +297,144 @@ App.WizardStep5Controller = Em.Controller.extend({
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
- * Load services info to appropriate variable and return masterComponentHosts
|
|
|
+ * Get recommendations info from API
|
|
|
+ * @return {undefined}
|
|
|
+ */
|
|
|
+ loadComponentRecommendations: function(callback) {
|
|
|
+ var self = this;
|
|
|
+
|
|
|
+ if (App.router.get('installerController.recommendations') !== undefined) {
|
|
|
+ // Don't do AJAX call if recommendations has been already received
|
|
|
+ // But if user returns to previous step (selecting services), stored recommendations will be cleared in routers' next handler and AJAX call will be made again
|
|
|
+ callback(self.createComponentInstalltationObjects(), self);
|
|
|
+ } else {
|
|
|
+ var selectedServices = App.StackService.find().filterProperty('isSelected').mapProperty('serviceName');
|
|
|
+ var installedServices = App.StackService.find().filterProperty('isInstalled').mapProperty('serviceName');
|
|
|
+ var services = installedServices.concat(selectedServices).uniq();
|
|
|
+
|
|
|
+ var hostNames = self.get('hosts').mapProperty('host_name');
|
|
|
+
|
|
|
+ return App.ajax.send({
|
|
|
+ name: 'wizard.step5.recommendations',
|
|
|
+ sender: self,
|
|
|
+ data: {
|
|
|
+ stackVersionUrl: App.get('stackVersionURL'),
|
|
|
+ hosts: hostNames,
|
|
|
+ services: services
|
|
|
+ },
|
|
|
+ success: 'loadRecommendationsSuccessCallback'
|
|
|
+ }).
|
|
|
+ retry({
|
|
|
+ times: App.maxRetries,
|
|
|
+ timeout: App.timeout
|
|
|
+ }).
|
|
|
+ then(function () {
|
|
|
+ callback(self.createComponentInstalltationObjects(), self);
|
|
|
+ },
|
|
|
+ function () {
|
|
|
+ App.showReloadPopup();
|
|
|
+ console.log('Load recommendations failed');
|
|
|
+ }
|
|
|
+ );
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Create components for displaying component-host comboboxes in UI assign dialog
|
|
|
+ * expects installerController.recommendations will be filled with recommendations API call result
|
|
|
* @return {Object[]}
|
|
|
*/
|
|
|
- loadComponents: function () {
|
|
|
- var selectedServices = App.StackService.find().filterProperty('isSelected').mapProperty('serviceName');
|
|
|
- var installedServices = App.StackService.find().filterProperty('isInstalled').mapProperty('serviceName');
|
|
|
- var services = installedServices.concat(selectedServices).uniq();
|
|
|
- var selectedNotInstalledServices = this.get('content.services').filterProperty('isSelected').filterProperty('isInstalled', false).mapProperty('serviceName');
|
|
|
+ createComponentInstalltationObjects: function() {
|
|
|
+ var self = this;
|
|
|
|
|
|
var masterComponents = [];
|
|
|
- //get full list from mock data
|
|
|
- if (this.get('isAddServiceWizard')) {
|
|
|
+ if (self.get('isAddServiceWizard')) {
|
|
|
masterComponents = App.StackServiceComponent.find().filterProperty('isShownOnAddServiceAssignMasterPage');
|
|
|
} else {
|
|
|
masterComponents = App.StackServiceComponent.find().filterProperty('isShownOnInstallerAssignMasterPage');
|
|
|
}
|
|
|
- var masterHosts = this.get('content.masterComponentHosts'); //saved to local storage info
|
|
|
|
|
|
- var resultComponents = [];
|
|
|
+ var masterHosts = self.get('content.masterComponentHosts'); //saved to local storage info
|
|
|
+ var selectedNotInstalledServices = self.get('content.services').filterProperty('isSelected').filterProperty('isInstalled', false).mapProperty('serviceName');
|
|
|
+ var recommendations = App.router.get('installerController.recommendations');
|
|
|
|
|
|
- for (var index = 0; index < services.length; index++) {
|
|
|
- var componentInfo = masterComponents.filterProperty('serviceName', services[index]);
|
|
|
- // If service is already installed and not being added as a new service then render on UI only those master components
|
|
|
- // that have already installed hostComponents.
|
|
|
- // NOTE: On upgrade there might be a prior installed service with non-installed newly introduced serviceComponent
|
|
|
- var isNotSelectedService = !selectedNotInstalledServices.contains(services[index]);
|
|
|
- if (isNotSelectedService) {
|
|
|
- componentInfo = componentInfo.filter(function (_component) {
|
|
|
- return App.HostComponent.find().someProperty('componentName',_component.get('componentName'));
|
|
|
+ var resultComponents = [];
|
|
|
+ var multipleComponentHasBeenAdded = {};
|
|
|
+
|
|
|
+ recommendations.blueprint.host_groups.forEach(function(host_group) {
|
|
|
+ var hosts = recommendations.blueprint_cluster_binding.host_groups.findProperty('name', host_group.name).hosts;
|
|
|
+
|
|
|
+ hosts.forEach(function(host) {
|
|
|
+ host_group.components.forEach(function(component) {
|
|
|
+ var willBeAdded = true;
|
|
|
+ var fullComponent = masterComponents.findProperty('componentName', component.name);
|
|
|
+ // If it's master component which should be shown
|
|
|
+ if (fullComponent) {
|
|
|
+ // If service is already installed and not being added as a new service then render on UI only those master components
|
|
|
+ // that have already installed hostComponents.
|
|
|
+ // NOTE: On upgrade there might be a prior installed service with non-installed newly introduced serviceComponent
|
|
|
+ var isNotSelectedService = !selectedNotInstalledServices.contains(fullComponent.get('serviceName'));
|
|
|
+ if (isNotSelectedService) {
|
|
|
+ willBeAdded = App.HostComponent.find().someProperty('componentName', component.name);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (willBeAdded) {
|
|
|
+ var savedComponents = masterHosts.filterProperty('component', component.name);
|
|
|
+
|
|
|
+ if (self.get('multipleComponents').contains(component.name) && savedComponents.length > 0) {
|
|
|
+ if (!multipleComponentHasBeenAdded[component.name]) {
|
|
|
+ multipleComponentHasBeenAdded[component.name] = true;
|
|
|
+
|
|
|
+ savedComponents.forEach(function(saved) {
|
|
|
+ resultComponents.push(self.createComponentInstalltationObject(fullComponent, host.fqdn, saved));
|
|
|
+ });
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ var savedComponent = masterHosts.findProperty('component', component.name);
|
|
|
+ resultComponents.push(self.createComponentInstalltationObject(fullComponent, host.fqdn, savedComponent));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
});
|
|
|
- }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ return resultComponents;
|
|
|
+ },
|
|
|
|
|
|
- componentInfo.forEach(function (_componentInfo) {
|
|
|
- if (this.get('multipleComponents').contains(_componentInfo.get('componentName'))) {
|
|
|
- var savedComponents = masterHosts.filterProperty('component', _componentInfo.get('componentName'));
|
|
|
- if (savedComponents.length) {
|
|
|
- savedComponents.forEach(function (item) {
|
|
|
- var multipleMasterHost = {};
|
|
|
- multipleMasterHost.component_name = _componentInfo.get('componentName');
|
|
|
- multipleMasterHost.display_name = _componentInfo.get('displayName');
|
|
|
- multipleMasterHost.selectedHost = item.hostName;
|
|
|
- multipleMasterHost.serviceId = services[index];
|
|
|
- multipleMasterHost.isInstalled = item.isInstalled;
|
|
|
- multipleMasterHost.isServiceCoHost = false;
|
|
|
- resultComponents.push(multipleMasterHost);
|
|
|
- })
|
|
|
- } else {
|
|
|
- var multipleMasterHosts = this.selectHost(_componentInfo.get('componentName'));
|
|
|
- multipleMasterHosts.forEach(function (_host) {
|
|
|
- var multipleMasterHost = {};
|
|
|
- multipleMasterHost.component_name = _componentInfo.get('componentName');
|
|
|
- multipleMasterHost.display_name = _componentInfo.get('displayName');
|
|
|
- multipleMasterHost.selectedHost = _host;
|
|
|
- multipleMasterHost.serviceId = services[index];
|
|
|
- multipleMasterHost.isInstalled = false;
|
|
|
- multipleMasterHost.isServiceCoHost = false;
|
|
|
- resultComponents.push(multipleMasterHost);
|
|
|
- });
|
|
|
+ /**
|
|
|
+ * Create component for displaying component-host comboboxes in UI assign dialog
|
|
|
+ * @param fullComponent - full component description
|
|
|
+ * @param hostName - host fqdn where component will be installed
|
|
|
+ * @param savedComponent - the same object which function returns but created before
|
|
|
+ * @return {Object}
|
|
|
+ */
|
|
|
+ createComponentInstalltationObject: function(fullComponent, hostName, savedComponent) {
|
|
|
+ var componentName = fullComponent.get('componentName');
|
|
|
|
|
|
- }
|
|
|
- } else {
|
|
|
- var savedComponent = masterHosts.findProperty('component', _componentInfo.get('componentName'));
|
|
|
- var componentObj = {};
|
|
|
- componentObj.component_name = _componentInfo.get('componentName');
|
|
|
- componentObj.display_name = _componentInfo.get('displayName');
|
|
|
- componentObj.selectedHost = savedComponent ? savedComponent.hostName : this.selectHost(_componentInfo.get('componentName')); // call the method that plays selectNode algorithm or fetches from server
|
|
|
- componentObj.isInstalled = savedComponent ? savedComponent.isInstalled : false;
|
|
|
- componentObj.serviceId = services[index];
|
|
|
- componentObj.isServiceCoHost = App.StackServiceComponent.find().findProperty('componentName', _componentInfo.get('componentName')).get('isCoHostedComponent') && !this.get('isReassignWizard');
|
|
|
- resultComponents.push(componentObj);
|
|
|
- }
|
|
|
- }, this);
|
|
|
+ var componentObj = {};
|
|
|
+ componentObj.component_name = componentName;
|
|
|
+ componentObj.display_name = fullComponent.get('displayName');
|
|
|
+ componentObj.serviceId = fullComponent.get('serviceName');
|
|
|
+ componentObj.isServiceCoHost = App.StackServiceComponent.find().findProperty('componentName', componentName).get('isCoHostedComponent') && !this.get('isReassignWizard');
|
|
|
+
|
|
|
+ if (savedComponent) {
|
|
|
+ componentObj.selectedHost = savedComponent.hostName;
|
|
|
+ componentObj.isInstalled = savedComponent.isInstalled;
|
|
|
+ } else {
|
|
|
+ componentObj.selectedHost = hostName;
|
|
|
+ componentObj.isInstalled = false;
|
|
|
}
|
|
|
|
|
|
- return resultComponents;
|
|
|
+ return componentObj;
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Success-callback for recommendations request
|
|
|
+ * @param {object} data
|
|
|
+ * @method loadRecommendationsSuccessCallback
|
|
|
+ */
|
|
|
+ loadRecommendationsSuccessCallback: function (data) {
|
|
|
+ App.router.set('installerController.recommendations', data.resources[0].recommendations);
|
|
|
},
|
|
|
|
|
|
/**
|
|
@@ -429,83 +500,6 @@ App.WizardStep5Controller = Em.Controller.extend({
|
|
|
}, this);
|
|
|
}.observes('selectedServicesMasters.@each.selectedHost'),
|
|
|
|
|
|
- /**
|
|
|
- * select and return host for component by scheme
|
|
|
- * Scheme is an object that has keys which compared to number of hosts,
|
|
|
- * if key more that number of hosts, then return value of that key.
|
|
|
- * Value is index of host in hosts array.
|
|
|
- *
|
|
|
- * @param {object} componentName
|
|
|
- * @param {object} hosts
|
|
|
- * @return {string}
|
|
|
- * @method getHostForComponent
|
|
|
- */
|
|
|
- getHostForComponent: function (componentName, hosts) {
|
|
|
- var component = App.StackServiceComponent.find().findProperty('componentName', componentName);
|
|
|
- if (component) {
|
|
|
- var selectionScheme = App.StackServiceComponent.find().findProperty('componentName', componentName).get('selectionSchemeForMasterComponent');
|
|
|
- } else {
|
|
|
- return hosts[0];
|
|
|
- }
|
|
|
-
|
|
|
- if (hosts.length === 1 || $.isEmptyObject(selectionScheme)) {
|
|
|
- return hosts[0];
|
|
|
- } else {
|
|
|
- for (var i in selectionScheme) {
|
|
|
- if (window.isFinite(i)) {
|
|
|
- if (hosts.length < window.parseInt(i)) {
|
|
|
- return hosts[selectionScheme[i]];
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return hosts[selectionScheme['else']]
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- /**
|
|
|
- * Get list of host names for master component with multiple instances
|
|
|
- * @param {Object} component
|
|
|
- * @param {Object} hosts
|
|
|
- * @returns {string[]}
|
|
|
- * @method getHostsForComponent
|
|
|
- */
|
|
|
- getHostsForComponent: function (component, hosts) {
|
|
|
- var defaultNoOfMasterHosts = component.get('defaultNoOfMasterHosts');
|
|
|
- var masterHosts = [];
|
|
|
- if (hosts.length < defaultNoOfMasterHosts) {
|
|
|
- defaultNoOfMasterHosts = hosts.length;
|
|
|
- }
|
|
|
- for (var index = 0; index < defaultNoOfMasterHosts; index++) {
|
|
|
- masterHosts.push(hosts[index]);
|
|
|
- }
|
|
|
- return masterHosts;
|
|
|
- },
|
|
|
-
|
|
|
- /**
|
|
|
- * Return hostName of masterNode for specified service
|
|
|
- * @param componentName
|
|
|
- * @return {string|string[]}
|
|
|
- * @method selectHost
|
|
|
- */
|
|
|
- selectHost: function (componentName) {
|
|
|
- var component = App.StackServiceComponent.find().findProperty('componentName', componentName);
|
|
|
- var hostNames = this.get('hosts').mapProperty('host_name');
|
|
|
- if (hostNames.length > 1 && App.StackServiceComponent.find().filterProperty('isNotPreferableOnAmbariServerHost').mapProperty('componentName').contains(componentName)) {
|
|
|
- hostNames = this.get('hosts').mapProperty('host_name').filter(function (item) {
|
|
|
- return item !== location.hostname;
|
|
|
- }, this);
|
|
|
- }
|
|
|
- if (this.get('multipleComponents').contains(componentName)) {
|
|
|
- if (component.get('defaultNoOfMasterHosts') > 1) {
|
|
|
- return this.getHostsForComponent(component, hostNames);
|
|
|
- } else {
|
|
|
- return [this.getHostForComponent(componentName, hostNames)];
|
|
|
- }
|
|
|
- } else {
|
|
|
- return this.getHostForComponent(componentName, hostNames);
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
/**
|
|
|
* On change callback for inputs
|
|
|
* @param {string} componentName
|