wizard.js 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. var App = require('app');
  19. require('models/host');
  20. App.WizardController = Em.Controller.extend(App.LocalStorage, {
  21. isStepDisabled: null,
  22. /**
  23. * map of actions which load data required by which step
  24. * used by <code>loadAllPriorSteps</code>
  25. */
  26. loadMap: {},
  27. /**
  28. * Wizard properties in local storage, which should be cleaned right after wizard has been finished
  29. */
  30. dbPropertiesToClean: [
  31. 'service',
  32. 'hosts',
  33. 'masterComponentHosts',
  34. 'slaveComponentHosts',
  35. 'cluster',
  36. 'allHostNames',
  37. 'installOptions',
  38. 'allHostNamesPattern',
  39. 'serviceComponents'
  40. ],
  41. init: function () {
  42. this.set('isStepDisabled', []);
  43. this.clusters = App.Cluster.find();
  44. this.get('isStepDisabled').pushObject(Ember.Object.create({
  45. step: 1,
  46. value: false
  47. }));
  48. for (var i = 2; i <= this.get('totalSteps'); i++) {
  49. this.get('isStepDisabled').pushObject(Ember.Object.create({
  50. step: i,
  51. value: true
  52. }));
  53. }
  54. },
  55. slaveComponents: function () {
  56. return App.StackServiceComponent.find().filterProperty('isSlave', true);
  57. }.property('App.router.clusterController.isLoaded'),
  58. allHosts: function () {
  59. var dbHosts = this.get('content.hosts');
  60. var hosts = [];
  61. var hostComponents = [];
  62. for (var hostName in dbHosts) {
  63. hostComponents = [];
  64. var disksOverallCapacity = 0;
  65. var diskFree = 0;
  66. dbHosts[hostName].hostComponents.forEach(function (componentName) {
  67. hostComponents.push(Em.Object.create({
  68. componentName: componentName,
  69. displayName: App.format.role(componentName)
  70. }));
  71. });
  72. dbHosts[hostName].disk_info.forEach(function (disk) {
  73. disksOverallCapacity += parseFloat(disk.size);
  74. diskFree += parseFloat(disk.available);
  75. });
  76. hosts.push(Em.Object.create({
  77. id: hostName,
  78. hostName: hostName,
  79. publicHostName: hostName,
  80. diskInfo: dbHosts[hostName].disk_info,
  81. diskTotal: disksOverallCapacity / (1024 * 1024),
  82. diskFree: diskFree / (1024 * 1024),
  83. disksMounted: dbHosts[hostName].disk_info.length,
  84. cpu: dbHosts[hostName].cpu,
  85. memory: dbHosts[hostName].memory,
  86. osType: dbHosts[hostName].osType ? dbHosts[hostName].osType: 0,
  87. osArch: dbHosts[hostName].osArch ? dbHosts[hostName].osArch : 0,
  88. ip: dbHosts[hostName].ip ? dbHosts[hostName].ip: 0,
  89. hostComponents: hostComponents
  90. }))
  91. }
  92. return hosts;
  93. }.property('content.hosts'),
  94. setStepsEnable: function () {
  95. for (var i = 1; i <= this.totalSteps; i++) {
  96. var step = this.get('isStepDisabled').findProperty('step', i);
  97. if (i <= this.get('currentStep')) {
  98. step.set('value', false);
  99. } else {
  100. step.set('value', true);
  101. }
  102. }
  103. }.observes('currentStep'),
  104. /**
  105. * Enable step link in left nav menu
  106. * @param step - step number
  107. */
  108. enableStep: function (step) {
  109. this.get('isStepDisabled').findProperty('step', step).set('value', false);
  110. },
  111. setLowerStepsDisable: function (stepNo) {
  112. for (var i = 1; i < stepNo; i++) {
  113. var step = this.get('isStepDisabled').findProperty('step', i);
  114. step.set('value', true);
  115. }
  116. },
  117. /**
  118. * Set current step to new value.
  119. * Method moved from App.router.setInstallerCurrentStep
  120. * @param currentStep
  121. * @param completed
  122. */
  123. currentStep: function () {
  124. return App.get('router').getWizardCurrentStep(this.get('name').substr(0, this.get('name').length - 10));
  125. }.property(),
  126. /**
  127. * Set current step to new value.
  128. * Method moved from App.router.setInstallerCurrentStep
  129. * @param currentStep
  130. * @param completed
  131. */
  132. setCurrentStep: function (currentStep, completed) {
  133. App.db.setWizardCurrentStep(this.get('name').substr(0, this.get('name').length - 10), currentStep, completed);
  134. this.set('currentStep', currentStep);
  135. },
  136. clusters: null,
  137. isStep0: function () {
  138. return this.get('currentStep') == 0;
  139. }.property('currentStep'),
  140. isStep1: function () {
  141. return this.get('currentStep') == 1;
  142. }.property('currentStep'),
  143. isStep2: function () {
  144. return this.get('currentStep') == 2;
  145. }.property('currentStep'),
  146. isStep3: function () {
  147. return this.get('currentStep') == 3;
  148. }.property('currentStep'),
  149. isStep4: function () {
  150. return this.get('currentStep') == 4;
  151. }.property('currentStep'),
  152. isStep5: function () {
  153. return this.get('currentStep') == 5;
  154. }.property('currentStep'),
  155. isStep6: function () {
  156. return this.get('currentStep') == 6;
  157. }.property('currentStep'),
  158. isStep7: function () {
  159. return this.get('currentStep') == 7;
  160. }.property('currentStep'),
  161. isStep8: function () {
  162. return this.get('currentStep') == 8;
  163. }.property('currentStep'),
  164. isStep9: function () {
  165. return this.get('currentStep') == 9;
  166. }.property('currentStep'),
  167. isStep10: function () {
  168. return this.get('currentStep') == 10;
  169. }.property('currentStep'),
  170. gotoStep: function (step, disableNaviWarning) {
  171. if (this.get('isStepDisabled').findProperty('step', step).get('value') !== false) {
  172. return false;
  173. }
  174. // if going back from Step 9 in Install Wizard, delete the checkpoint so that the user is not redirected
  175. // to Step 9
  176. if (this.get('content.controllerName') == 'installerController' && this.get('currentStep') === '9' && step < 9) {
  177. App.clusterStatus.setClusterStatus({
  178. clusterName: this.get('clusterName'),
  179. clusterState: 'CLUSTER_NOT_CREATED_1',
  180. wizardControllerName: 'installerController',
  181. localdb: App.db.data
  182. });
  183. }
  184. if ((this.get('currentStep') - step) > 1 && !disableNaviWarning) {
  185. App.ModalPopup.show({
  186. header: Em.I18n.t('installer.navigation.warning.header'),
  187. onPrimary: function () {
  188. App.router.send('gotoStep' + step);
  189. this.hide();
  190. },
  191. body: "If you proceed to go back to Step " + step + ", you will lose any changes you have made beyond this step"
  192. });
  193. } else {
  194. App.router.send('gotoStep' + step);
  195. }
  196. return true;
  197. },
  198. gotoStep0: function () {
  199. this.gotoStep(0);
  200. },
  201. gotoStep1: function () {
  202. this.gotoStep(1);
  203. },
  204. gotoStep2: function () {
  205. this.gotoStep(2);
  206. },
  207. gotoStep3: function () {
  208. this.gotoStep(3);
  209. },
  210. gotoStep4: function () {
  211. this.gotoStep(4);
  212. },
  213. gotoStep5: function () {
  214. this.gotoStep(5);
  215. },
  216. gotoStep6: function () {
  217. this.gotoStep(6);
  218. },
  219. gotoStep7: function () {
  220. this.gotoStep(7);
  221. },
  222. gotoStep8: function () {
  223. this.gotoStep(8);
  224. },
  225. gotoStep9: function () {
  226. this.gotoStep(9);
  227. },
  228. gotoStep10: function () {
  229. this.gotoStep(10);
  230. },
  231. /**
  232. * Initialize host status info for step9
  233. */
  234. setInfoForStep9: function () {
  235. var hostInfo = this.getDBProperty('hosts');
  236. for (var index in hostInfo) {
  237. hostInfo[index].status = "pending";
  238. hostInfo[index].message = 'Waiting';
  239. hostInfo[index].logTasks = [];
  240. hostInfo[index].tasks = [];
  241. hostInfo[index].progress = '0';
  242. }
  243. this.setDBProperty('hosts', hostInfo);
  244. },
  245. /**
  246. * Remove all data for installOptions step
  247. */
  248. clearInstallOptions: function () {
  249. var installOptions = this.getInstallOptions();
  250. this.set('content.installOptions', installOptions);
  251. this.setDBProperty('installOptions', installOptions);
  252. this.set('content.hosts', {});
  253. this.setDBProperty('hosts', {});
  254. },
  255. toObject: function (object) {
  256. var result = {};
  257. for (var i in object) {
  258. if (object.hasOwnProperty(i)) {
  259. result[i] = object[i];
  260. }
  261. }
  262. return result;
  263. },
  264. /**
  265. * save status of the cluster. This is called from step8 and step9 to persist install and start requestId
  266. * @param clusterStatus object with status, isCompleted, requestId, isInstallError and isStartError field.
  267. */
  268. saveClusterStatus: function (clusterStatus) {
  269. var oldStatus = this.toObject(this.get('content.cluster'));
  270. clusterStatus = jQuery.extend(oldStatus, clusterStatus);
  271. if (clusterStatus.requestId &&
  272. clusterStatus.oldRequestsId.indexOf(clusterStatus.requestId) === -1) {
  273. clusterStatus.oldRequestsId.push(clusterStatus.requestId);
  274. }
  275. this.set('content.cluster', clusterStatus);
  276. this.setDBProperty('cluster', clusterStatus);
  277. },
  278. /**
  279. * Invoke installation of selected services to the server and saves the request id returned by the server.
  280. * @param isRetry
  281. */
  282. installServices: function (isRetry, callback) {
  283. // clear requests since we are installing services
  284. // and we don't want to get tasks for previous install attempts
  285. this.set('content.cluster.oldRequestsId', []);
  286. var data;
  287. callback = callback || Em.K;
  288. if (isRetry) {
  289. data = {
  290. context: Em.I18n.t('requestInfo.installComponents'),
  291. HostRoles: {"state": "INSTALLED"},
  292. urlParams: "HostRoles/state=INSTALLED"
  293. }
  294. } else {
  295. data = {
  296. context: Em.I18n.t('requestInfo.installServices'),
  297. ServiceInfo: {"state": "INSTALLED"},
  298. urlParams: "ServiceInfo/state=INIT"
  299. }
  300. }
  301. App.ajax.send({
  302. name: isRetry ? 'common.host_components.update' : 'common.services.update',
  303. sender: this,
  304. data: data,
  305. success: 'installServicesSuccessCallback',
  306. error: 'installServicesErrorCallback'
  307. }).then(callback, callback);
  308. },
  309. installServicesSuccessCallback: function (jsonData) {
  310. var installStartTime = App.dateTime();
  311. console.log("TRACE: In success function for the installService call");
  312. if (jsonData) {
  313. var requestId = jsonData.Requests.id;
  314. console.log('requestId is: ' + requestId);
  315. var clusterStatus = {
  316. status: 'PENDING',
  317. requestId: requestId,
  318. isInstallError: false,
  319. isCompleted: false,
  320. installStartTime: installStartTime
  321. };
  322. this.saveClusterStatus(clusterStatus);
  323. } else {
  324. console.log('ERROR: Error occurred in parsing JSON data');
  325. }
  326. },
  327. installServicesErrorCallback: function (request, ajaxOptions, error) {
  328. console.log("TRACE: In error function for the installService call");
  329. console.log("TRACE: error code status is: " + request.status);
  330. console.log('Error message is: ' + request.responseText);
  331. var clusterStatus = {
  332. status: 'PENDING',
  333. requestId: this.get('content.cluster.requestId'),
  334. isInstallError: true,
  335. isCompleted: false
  336. };
  337. this.saveClusterStatus(clusterStatus);
  338. App.showAlertPopup(Em.I18n.t('common.errorPopup.header'), request.responseText);
  339. },
  340. /**
  341. * show popup, that display status of bootstrap launching
  342. * @param callback
  343. * @return {Object}
  344. */
  345. showLaunchBootstrapPopup: function (callback) {
  346. return App.ModalPopup.show({
  347. header: Em.I18n.t('installer.step2.bootStrap.header'),
  348. isError: false,
  349. serverError: null,
  350. bodyClass: Em.View.extend({
  351. templateName: require('templates/wizard/bootstrap_call_popup')
  352. }),
  353. showFooter: false,
  354. showCloseButton: false,
  355. secondary: null,
  356. /**
  357. * handle requestId when call is completed,
  358. * if it's correct call callback and hide popup
  359. * otherwise notify error and enable buttons to close popup
  360. * @param requestId
  361. * @param serverError
  362. */
  363. finishLoading: function (requestId, serverError) {
  364. if (Em.isNone(requestId)) {
  365. this.set('isError', true);
  366. this.set('showFooter', true);
  367. this.set('showCloseButton', true);
  368. this.set('serverError', serverError);
  369. } else {
  370. callback(requestId);
  371. this.hide();
  372. }
  373. }
  374. });
  375. },
  376. /**
  377. * Bootstrap selected hosts.
  378. * @param bootStrapData
  379. * @param callback
  380. * @return {Object}
  381. */
  382. launchBootstrap: function (bootStrapData, callback) {
  383. var popup = this.showLaunchBootstrapPopup(callback);
  384. App.ajax.send({
  385. name: 'wizard.launch_bootstrap',
  386. sender: this,
  387. data: {
  388. bootStrapData: bootStrapData,
  389. popup: popup
  390. },
  391. success: 'launchBootstrapSuccessCallback',
  392. error: 'launchBootstrapErrorCallback'
  393. });
  394. return popup;
  395. },
  396. launchBootstrapSuccessCallback: function (data, opt, params) {
  397. console.log("TRACE: POST bootstrap succeeded");
  398. params.popup.finishLoading(data.requestId, null);
  399. },
  400. launchBootstrapErrorCallback: function (request, ajaxOptions, error, opt, params) {
  401. console.log("ERROR: POST bootstrap failed");
  402. params.popup.finishLoading(null, error);
  403. },
  404. /**
  405. * Load <code>content.<name></code> variable from localStorage, if wasn't loaded before.
  406. * If you specify <code>reload</code> to true - it will reload it.
  407. * @param name
  408. * @param reload
  409. * @return {Boolean}
  410. */
  411. load: function (name, reload) {
  412. if (this.get('content.' + name) && !reload) {
  413. return false;
  414. }
  415. var result = this.getDBProperty(name);
  416. if (!result) {
  417. if (this['get' + name.capitalize()]) {
  418. result = this['get' + name.capitalize()]();
  419. this.setDBProperty(name, result);
  420. console.log(this.get('name') + ": created " + name, result);
  421. }
  422. else {
  423. console.debug('get' + name.capitalize(), ' not defined in the ' + this.get('name'));
  424. }
  425. }
  426. this.set('content.' + name, result);
  427. console.log(this.get('name') + ": loaded " + name, result);
  428. },
  429. save: function (name) {
  430. var value = this.toObject(this.get('content.' + name));
  431. this.setDBProperty(name, value);
  432. console.log(this.get('name') + ": saved " + name, value);
  433. },
  434. clear: function () {
  435. this.set('content', Ember.Object.create({
  436. 'controllerName': this.get('content.controllerName')
  437. }));
  438. this.set('currentStep', 0);
  439. this.clearStorageData();
  440. },
  441. clusterStatusTemplate: {
  442. name: "",
  443. status: "PENDING",
  444. isCompleted: false,
  445. requestId: null,
  446. installStartTime: null,
  447. installTime: null,
  448. isInstallError: false,
  449. isStartError: false,
  450. oldRequestsId: []
  451. },
  452. clearStorageData: function () {
  453. this.get('dbPropertiesToClean').forEach(function (key) {
  454. this.setDBProperty(key, undefined);
  455. }, this);
  456. },
  457. getInstallOptions: function() {
  458. return jQuery.extend({}, App.get('isHadoopWindowsStack') ? this.get('installWindowsOptionsTemplate') : this.get('installOptionsTemplate'));
  459. },
  460. installOptionsTemplate: {
  461. hostNames: "", //string
  462. manualInstall: false, //true, false
  463. useSsh: true, //bool
  464. javaHome: App.defaultJavaHome, //string
  465. localRepo: false, //true, false
  466. sshKey: "", //string
  467. bootRequestId: null, //string
  468. sshUser: "root", //string
  469. agentUser: "root" //string
  470. },
  471. installWindowsOptionsTemplate: {
  472. hostNames: "", //string
  473. manualInstall: true, //true, false
  474. useSsh: false, //bool
  475. javaHome: App.defaultJavaHome, //string
  476. localRepo: false, //true, false
  477. sshKey: "", //string
  478. bootRequestId: null, //string
  479. sshUser: "", //string
  480. agentUser: "" //string
  481. },
  482. loadedServiceComponents: null,
  483. /**
  484. * Generate serviceComponents as pr the stack definition and save it to localdata
  485. * called form stepController step4WizardController
  486. */
  487. loadServiceComponents: function () {
  488. return App.ajax.send({
  489. name: 'wizard.service_components',
  490. sender: this,
  491. data: {
  492. stackUrl: App.get('stackVersionURL'),
  493. stackVersion: App.get('currentStackVersionNumber')
  494. },
  495. success: 'loadServiceComponentsSuccessCallback',
  496. error: 'loadServiceComponentsErrorCallback'
  497. });
  498. },
  499. loadServiceComponentsSuccessCallback: function (jsonData) {
  500. var savedSelectedServices = this.getDBProperty('selectedServiceNames');
  501. var savedInstalledServices = this.getDBProperty('installedServiceNames');
  502. this.set('content.selectedServiceNames', savedSelectedServices);
  503. this.set('content.installedServiceNames', savedInstalledServices);
  504. if (!savedSelectedServices) {
  505. jsonData.items.forEach(function (service) {
  506. service.StackServices.is_selected = true;
  507. }, this);
  508. } else {
  509. jsonData.items.forEach(function (service) {
  510. if (savedSelectedServices.contains(service.StackServices.service_name))
  511. service.StackServices.is_selected = true;
  512. else
  513. service.StackServices.is_selected = false;
  514. }, this);
  515. }
  516. if (!savedInstalledServices) {
  517. jsonData.items.forEach(function (service) {
  518. service.StackServices.is_installed = false;
  519. }, this);
  520. } else {
  521. jsonData.items.forEach(function (service) {
  522. if (savedInstalledServices.contains(service.StackServices.service_name))
  523. service.StackServices.is_installed = true;
  524. else
  525. service.StackServices.is_installed = false;
  526. }, this);
  527. }
  528. App.stackServiceMapper.mapStackServices(jsonData);
  529. },
  530. loadServiceComponentsErrorCallback: function (request, ajaxOptions, error) {
  531. console.log("TRACE: STep5 -> In error function for the getServiceComponents call");
  532. console.log("TRACE: STep5 -> error code status is: " + request.status);
  533. console.log('Step8: Error message is: ' + request.responseText);
  534. },
  535. /**
  536. * Load config groups from local DB
  537. */
  538. loadServiceConfigGroups: function () {
  539. var serviceConfigGroups = this.getDBProperty('serviceConfigGroups'),
  540. hosts = this.getDBProperty('hosts'),
  541. host_names = Em.keys(hosts);
  542. if (Em.isNone(serviceConfigGroups)) {
  543. serviceConfigGroups = [];
  544. }
  545. else {
  546. serviceConfigGroups.forEach(function(group) {
  547. var hostNames = group.hosts.map(function(host_id) {
  548. for (var i = 0; i < host_names.length; i++) {
  549. if (hosts[host_names[i]].id === host_id) {
  550. return host_names[i];
  551. }
  552. }
  553. Em.assert('host is missing!!!!', false);
  554. });
  555. Em.set(group, 'hosts', hostNames);
  556. });
  557. }
  558. this.set('content.configGroups', serviceConfigGroups);
  559. console.log("InstallerController.configGroups: loaded config ", serviceConfigGroups);
  560. },
  561. registerErrPopup: function (header, message) {
  562. App.ModalPopup.show({
  563. header: header,
  564. secondary: false,
  565. bodyClass: Ember.View.extend({
  566. template: Ember.Handlebars.compile('<p>{{view.message}}</p>'),
  567. message: message
  568. })
  569. });
  570. },
  571. /**
  572. * Save hosts that the user confirmed to proceed with from step 3
  573. * @param stepController App.WizardStep3Controller
  574. */
  575. saveConfirmedHosts: function (stepController) {
  576. var hosts = this.get('content.hosts'),
  577. indx = 1;
  578. //add previously installed hosts
  579. for (var hostName in hosts) {
  580. if (!hosts[hostName].isInstalled) {
  581. delete hosts[hostName];
  582. }
  583. }
  584. stepController.get('confirmedHosts').forEach(function (_host) {
  585. if (_host.bootStatus == 'REGISTERED') {
  586. hosts[_host.name] = {
  587. name: _host.name,
  588. cpu: _host.cpu,
  589. memory: _host.memory,
  590. disk_info: _host.disk_info,
  591. os_type: _host.os_type,
  592. os_arch: _host.os_arch,
  593. ip: _host.ip,
  594. bootStatus: _host.bootStatus,
  595. isInstalled: false,
  596. id: indx++
  597. };
  598. }
  599. });
  600. console.log('wizardController:saveConfirmedHosts: save hosts ', hosts);
  601. this.setDBProperty('hosts', hosts);
  602. this.set('content.hosts', hosts);
  603. },
  604. /**
  605. * Save data after installation to main controller
  606. * @param stepController App.WizardStep9Controller
  607. */
  608. saveInstalledHosts: function (stepController) {
  609. var hosts = stepController.get('hosts');
  610. var hostInfo = this.getDBProperty('hosts');
  611. for (var index in hostInfo) {
  612. hostInfo[index].status = "pending";
  613. var host = hosts.findProperty('name', hostInfo[index].name);
  614. if (host) {
  615. hostInfo[index].status = host.status;
  616. hostInfo[index].message = host.message;
  617. hostInfo[index].progress = host.progress;
  618. }
  619. }
  620. this.set('content.hosts', hostInfo);
  621. this.setDBProperty('hosts', hostInfo);
  622. console.log('wizardController:saveInstalledHosts: save hosts ', hostInfo);
  623. },
  624. /**
  625. * Save slaveHostComponents to main controller
  626. * @param stepController
  627. */
  628. saveSlaveComponentHosts: function (stepController) {
  629. var hosts = stepController.get('hosts'),
  630. dbHosts = this.getDBProperty('hosts'),
  631. headers = stepController.get('headers');
  632. var formattedHosts = Ember.Object.create();
  633. headers.forEach(function (header) {
  634. formattedHosts.set(header.get('name'), []);
  635. });
  636. hosts.forEach(function (host) {
  637. var checkboxes = host.get('checkboxes');
  638. headers.forEach(function (header) {
  639. var cb = checkboxes.findProperty('title', header.get('label'));
  640. if (cb.get('checked')) {
  641. formattedHosts.get(header.get('name')).push({
  642. group: 'Default',
  643. isInstalled: cb.get('isInstalled'),
  644. host_id: dbHosts[host.hostName].id
  645. });
  646. }
  647. });
  648. });
  649. var slaveComponentHosts = [];
  650. headers.forEach(function (header) {
  651. slaveComponentHosts.push({
  652. componentName: header.get('name'),
  653. displayName: header.get('label').replace(/\s/g, ''),
  654. hosts: formattedHosts.get(header.get('name'))
  655. });
  656. });
  657. this.setDBProperty('slaveComponentHosts', slaveComponentHosts);
  658. console.log('wizardController.slaveComponentHosts: saved hosts', slaveComponentHosts);
  659. this.set('content.slaveComponentHosts', slaveComponentHosts);
  660. },
  661. /**
  662. * Return true if cluster data is loaded and false otherwise.
  663. * This is used for all wizard controllers except for installer wizard.
  664. */
  665. dataLoading: function () {
  666. var dfd = $.Deferred();
  667. this.connectOutlet('loading');
  668. if (App.router.get('clusterController.isLoaded')) {
  669. dfd.resolve();
  670. } else {
  671. var interval = setInterval(function () {
  672. if (App.router.get('clusterController.isLoaded')) {
  673. dfd.resolve();
  674. clearInterval(interval);
  675. }
  676. }, 50);
  677. }
  678. return dfd.promise();
  679. },
  680. /**
  681. * Return true if user data is loaded via App.MainServiceInfoConfigsController
  682. * This function is used in reassign master wizard right now.
  683. */
  684. usersLoading: function () {
  685. var self = this;
  686. var dfd = $.Deferred();
  687. var miscController = App.MainAdminServiceAccountsController.create({content: self.get('content')});
  688. miscController.loadUsers();
  689. var interval = setInterval(function () {
  690. if (miscController.get('dataIsLoaded')) {
  691. if (self.get("content.hdfsUser")) {
  692. self.set('content.hdfsUser', miscController.get('content.hdfsUser'));
  693. }
  694. dfd.resolve();
  695. clearInterval(interval);
  696. }
  697. }, 10);
  698. return dfd.promise();
  699. },
  700. /**
  701. * Save cluster status before going to deploy step
  702. * @param name cluster state. Unique for every wizard
  703. */
  704. saveClusterState: function (name) {
  705. App.clusterStatus.setClusterStatus({
  706. clusterName: this.get('content.cluster.name'),
  707. clusterState: name,
  708. wizardControllerName: this.get('content.controllerName'),
  709. localdb: App.db.data
  710. });
  711. },
  712. /**
  713. * load advanced configs from server
  714. */
  715. loadAdvancedConfigs: function (dependentController) {
  716. var self = this;
  717. var loadServiceConfigsFn = function(clusterProperties) {
  718. var stackServices = self.get('content.services').filter(function (service) {
  719. return service.get('isInstalled') || service.get('isSelected');
  720. });
  721. var counter = stackServices.length;
  722. var loadAdvancedConfigResult = [];
  723. dependentController.set('isAdvancedConfigLoaded', false);
  724. stackServices.forEach(function (service) {
  725. var serviceName = service.get('serviceName');
  726. App.config.loadAdvancedConfig(serviceName, function (properties) {
  727. var supportsFinal = App.config.getConfigTypesInfoFromService(service).supportsFinal;
  728. function shouldSupportFinal(filename) {
  729. var matchingConfigType = supportsFinal.find(function (configType) {
  730. return filename.startsWith(configType);
  731. });
  732. return !!matchingConfigType;
  733. }
  734. properties.forEach(function (property) {
  735. property.supportsFinal = shouldSupportFinal(property.filename);
  736. });
  737. loadAdvancedConfigResult.pushObjects(properties);
  738. counter--;
  739. //pass configs to controller after last call is completed
  740. if (counter === 0) {
  741. loadAdvancedConfigResult.pushObjects(clusterProperties);
  742. self.set('content.advancedServiceConfig', loadAdvancedConfigResult);
  743. self.setDBProperty('advancedServiceConfig', loadAdvancedConfigResult);
  744. dependentController.set('isAdvancedConfigLoaded', true);
  745. }
  746. });
  747. }, this);
  748. };
  749. App.config.loadClusterConfig(loadServiceConfigsFn);
  750. },
  751. /**
  752. * Load serviceConfigProperties to model
  753. */
  754. loadServiceConfigProperties: function () {
  755. var serviceConfigProperties = this.getDBProperty('serviceConfigProperties');
  756. this.set('content.serviceConfigProperties', serviceConfigProperties);
  757. console.log("AddHostController.loadServiceConfigProperties: loaded config ", serviceConfigProperties);
  758. },
  759. /**
  760. * Save config properties
  761. * @param stepController Step7WizardController
  762. */
  763. saveServiceConfigProperties: function (stepController) {
  764. var serviceConfigProperties = [];
  765. var fileNamesToUpdate = [];
  766. stepController.get('stepConfigs').forEach(function (_content) {
  767. if (_content.serviceName === 'YARN') {
  768. _content.set('configs', App.config.textareaIntoFileConfigs(_content.get('configs'), 'capacity-scheduler.xml'));
  769. }
  770. _content.get('configs').forEach(function (_configProperties) {
  771. var configProperty = {
  772. id: _configProperties.get('id'),
  773. name: _configProperties.get('name'),
  774. value: _configProperties.get('value'),
  775. defaultValue: _configProperties.get('defaultValue'),
  776. description: _configProperties.get('description'),
  777. serviceName: _configProperties.get('serviceName'),
  778. domain: _configProperties.get('domain'),
  779. isVisible: _configProperties.get('isVisible'),
  780. isFinal: _configProperties.get('isFinal'),
  781. defaultIsFinal: _configProperties.get('isFinal'),
  782. supportsFinal: _configProperties.get('supportsFinal'),
  783. filename: _configProperties.get('filename'),
  784. displayType: _configProperties.get('displayType'),
  785. isRequiredByAgent: _configProperties.get('isRequiredByAgent'),
  786. hasInitialValue: !!_configProperties.get('hasInitialValue'),
  787. isRequired: _configProperties.get('isRequired'), // flag that allow saving property with empty value
  788. group: !!_configProperties.get('group') ? _configProperties.get('group.name') : null,
  789. showLabel: _configProperties.get('showLabel'),
  790. category: _configProperties.get('category')
  791. };
  792. serviceConfigProperties.push(configProperty);
  793. }, this);
  794. // check for configs that need to update for installed services
  795. if (stepController.get('installedServiceNames') && stepController.get('installedServiceNames').contains(_content.get('serviceName'))) {
  796. // get only modified configs
  797. var configs = _content.get('configs').filter(function (config) {
  798. if (config.get('isNotDefaultValue') || (config.get('defaultValue') === null)) {
  799. var notAllowed = ['masterHost', 'masterHosts', 'slaveHosts', 'slaveHost'];
  800. return !notAllowed.contains(config.get('displayType')) && !!config.filename;
  801. }
  802. return false;
  803. });
  804. // if modified configs detected push all service's configs for update
  805. if (configs.length) {
  806. fileNamesToUpdate = fileNamesToUpdate.concat(configs.mapProperty('filename').uniq());
  807. }
  808. // watch for properties that are not modified but have to be updated
  809. if (_content.get('configs').someProperty('forceUpdate')) {
  810. // check for already added modified properties
  811. var forceUpdatedFileNames = _content.get('configs').filterProperty('forceUpdate', true).mapProperty('filename').uniq();
  812. fileNamesToUpdate = fileNamesToUpdate.concat(forceUpdatedFileNames).uniq();
  813. }
  814. }
  815. }, this);
  816. this.setDBProperty('serviceConfigProperties', serviceConfigProperties);
  817. this.set('content.serviceConfigProperties', serviceConfigProperties);
  818. this.setDBProperty('fileNamesToUpdate', fileNamesToUpdate);
  819. },
  820. /**
  821. * save Config groups
  822. * @param stepController
  823. * @param isAddService
  824. */
  825. saveServiceConfigGroups: function (stepController, isAddService) {
  826. var serviceConfigGroups = [],
  827. isForInstalledService = false,
  828. hosts = isAddService ? App.router.get('addServiceController').getDBProperty('hosts') : this.getDBProperty('hosts');
  829. stepController.get('stepConfigs').forEach(function (service) {
  830. // mark group of installed service
  831. if (service.get('selected') === false) isForInstalledService = true;
  832. service.get('configGroups').forEach(function (configGroup) {
  833. var properties = [];
  834. configGroup.get('properties').forEach(function (property) {
  835. properties.push({
  836. isRequiredByAgent: property.get('isRequiredByAgent'),
  837. name: property.get('name'),
  838. value: property.get('value'),
  839. isFinal: property.get('isFinal'),
  840. filename: property.get('filename')
  841. })
  842. });
  843. //configGroup copied into plain JS object to avoid Converting circular structure to JSON
  844. var hostNames = configGroup.get('hosts').map(function(host_name) {return hosts[host_name].id;});
  845. serviceConfigGroups.push({
  846. id: configGroup.get('id'),
  847. name: configGroup.get('name'),
  848. description: configGroup.get('description'),
  849. hosts: hostNames,
  850. properties: properties,
  851. isDefault: configGroup.get('isDefault'),
  852. isForInstalledService: isForInstalledService,
  853. isForUpdate: configGroup.isForUpdate || configGroup.get('hash') != this.getConfigGroupHash(configGroup, hostNames),
  854. service: {id: configGroup.get('service.id')}
  855. });
  856. }, this)
  857. }, this);
  858. this.setDBProperty('serviceConfigGroups', serviceConfigGroups);
  859. this.set('content.configGroups', serviceConfigGroups);
  860. },
  861. /**
  862. * generate string hash for config group
  863. * @param {Object} configGroup
  864. * @param {Array|undefined} hosts
  865. * @returns {String|null}
  866. * @method getConfigGroupHash
  867. */
  868. getConfigGroupHash: function(configGroup, hosts) {
  869. if (!Em.get(configGroup, 'properties.length') && !Em.get(configGroup, 'hosts.length') && !hosts) {
  870. return null;
  871. }
  872. var hash = {};
  873. Em.get(configGroup, 'properties').forEach(function (config) {
  874. hash[Em.get(config, 'name')] = {value: Em.get(config, 'value'), isFinal: Em.get(config, 'isFinal')};
  875. });
  876. hash['hosts'] = hosts || Em.get(configGroup, 'hosts');
  877. return JSON.stringify(hash);
  878. },
  879. /**
  880. * return slaveComponents bound to hosts
  881. * @return {Array}
  882. */
  883. getSlaveComponentHosts: function () {
  884. var components = this.get('slaveComponents');
  885. var result = [];
  886. var installedServices = App.Service.find().mapProperty('serviceName');
  887. var selectedServices = App.StackService.find().filterProperty('isSelected', true).mapProperty('serviceName');
  888. var installedComponentsMap = {};
  889. var uninstalledComponents = [];
  890. components.forEach(function (component) {
  891. if (installedServices.contains(component.get('serviceName'))) {
  892. installedComponentsMap[component.get('componentName')] = [];
  893. } else if (selectedServices.contains(component.get('serviceName'))) {
  894. uninstalledComponents.push(component);
  895. }
  896. }, this);
  897. installedComponentsMap['HDFS_CLIENT'] = [];
  898. App.HostComponent.find().forEach(function (hostComponent) {
  899. if (installedComponentsMap[hostComponent.get('componentName')]) {
  900. installedComponentsMap[hostComponent.get('componentName')].push(hostComponent.get('hostName'));
  901. }
  902. }, this);
  903. for (var componentName in installedComponentsMap) {
  904. var name = (componentName === 'HDFS_CLIENT') ? 'CLIENT' : componentName;
  905. var component = {
  906. componentName: name,
  907. displayName: App.format.role(name),
  908. hosts: [],
  909. isInstalled: true
  910. };
  911. installedComponentsMap[componentName].forEach(function (hostName) {
  912. component.hosts.push({
  913. group: "Default",
  914. hostName: hostName,
  915. isInstalled: true
  916. });
  917. }, this);
  918. result.push(component);
  919. }
  920. uninstalledComponents.forEach(function (component) {
  921. var hosts = jQuery.extend(true, [], result.findProperty('componentName', 'DATANODE').hosts);
  922. hosts.setEach('isInstalled', false);
  923. result.push({
  924. componentName: component.get('componentName'),
  925. displayName: App.format.role(component.get('componentName')),
  926. hosts: hosts,
  927. isInstalled: false
  928. })
  929. });
  930. return result;
  931. },
  932. /**
  933. * Load master component hosts data for using in required step controllers
  934. */
  935. loadMasterComponentHosts: function () {
  936. var masterComponentHosts = this.getDBProperty('masterComponentHosts');
  937. var stackMasterComponents = App.get('components.masters').uniq();
  938. if (!masterComponentHosts) {
  939. masterComponentHosts = [];
  940. App.HostComponent.find().filter(function(component) {
  941. return stackMasterComponents.contains(component.get('componentName'));
  942. }).forEach(function (item) {
  943. masterComponentHosts.push({
  944. component: item.get('componentName'),
  945. hostName: item.get('hostName'),
  946. isInstalled: true,
  947. serviceId: item.get('service.id'),
  948. display_name: item.get('displayName')
  949. })
  950. });
  951. this.setDBProperty('masterComponentHosts', masterComponentHosts);
  952. }
  953. this.set("content.masterComponentHosts", masterComponentHosts);
  954. },
  955. /**
  956. * Load information about hosts with clients components
  957. */
  958. loadClients: function () {
  959. var clients = this.getDBProperty('clientInfo');
  960. this.set('content.clients', clients);
  961. console.log(this.get('content.controllerName') + ".loadClients: loaded list ", clients);
  962. },
  963. /**
  964. * load methods assigned to each step
  965. * methods executed in exact order as they described in map
  966. * @return {object}
  967. */
  968. loadAllPriorSteps: function () {
  969. var currentStep = this.get('currentStep');
  970. var loadMap = this.get('loadMap');
  971. var operationStack = [];
  972. var dfd = $.Deferred();
  973. for (var s in loadMap) {
  974. if (parseInt(s) <= parseInt(currentStep)) {
  975. operationStack.pushObjects(loadMap[s]);
  976. }
  977. }
  978. var sequence = App.actionSequence.create({context: this});
  979. sequence.setSequence(operationStack).onFinish(function () {
  980. dfd.resolve();
  981. }).start();
  982. return dfd.promise();
  983. },
  984. /**
  985. * return new object extended from clusterStatusTemplate
  986. * @return Object
  987. */
  988. getCluster: function () {
  989. return jQuery.extend({}, this.get('clusterStatusTemplate'), {name: App.router.getClusterName()});
  990. },
  991. /**
  992. * Load services data from server.
  993. */
  994. loadServicesFromServer: function () {
  995. var services = this.getDBProperty('services');
  996. if (!services) {
  997. services = {
  998. selectedServices: [],
  999. installedServices: []
  1000. };
  1001. App.StackService.find().forEach(function(item){
  1002. var isInstalled = App.Service.find().someProperty('id', item.get('serviceName'));
  1003. item.set('isSelected', isInstalled);
  1004. item.set('isInstalled', isInstalled);
  1005. if (isInstalled) {
  1006. services.selectedServices.push(item.get('serviceName'));
  1007. services.installedServices.push(item.get('serviceName'));
  1008. }
  1009. },this);
  1010. this.setDBProperty('services',services);
  1011. } else {
  1012. App.StackService.find().forEach(function(item) {
  1013. var isSelected = services.selectedServices.contains(item.get('serviceName'));
  1014. var isInstalled = services.installedServices.contains(item.get('serviceName'));
  1015. item.set('isSelected', isSelected);
  1016. item.set('isInstalled', isInstalled);
  1017. },this);
  1018. }
  1019. this.set('content.services', App.StackService.find());
  1020. },
  1021. /**
  1022. * Load confirmed hosts.
  1023. * Will be used at <code>Assign Masters(step5)</code> step
  1024. */
  1025. loadConfirmedHosts: function () {
  1026. var hosts = App.db.getHosts();
  1027. if (hosts) {
  1028. this.set('content.hosts', hosts);
  1029. }
  1030. },
  1031. /**
  1032. * Determine if <code>Assign Slaves and Clients</code> step should be skipped
  1033. * @method setSkipSlavesStep
  1034. * @param services
  1035. * @param step
  1036. */
  1037. setSkipSlavesStep: function (services, step) {
  1038. var hasServicesWithSlave = services.someProperty('hasSlave');
  1039. var hasServicesWithClient = services.someProperty('hasClient');
  1040. var hasServicesWithCustomAssignedNonMasters = services.someProperty('hasNonMastersWithCustomAssignment');
  1041. this.set('content.skipSlavesStep', !hasServicesWithSlave && !hasServicesWithClient || !hasServicesWithCustomAssignedNonMasters);
  1042. if (this.get('content.skipSlavesStep')) {
  1043. this.get('isStepDisabled').findProperty('step', step).set('value', this.get('content.skipSlavesStep'));
  1044. }
  1045. },
  1046. /**
  1047. * Load config themes for enhanced config layout.
  1048. *
  1049. * @method loadConfigThemes
  1050. * @return {$.Deferred}
  1051. */
  1052. loadConfigThemes: function() {
  1053. var self = this;
  1054. var dfd = $.Deferred();
  1055. if (App.get('supports.enhancedConfigs') && !this.get('stackConfigsLoaded')) {
  1056. var serviceNames = App.StackService.find().filter(function(s) {
  1057. return s.get('isSelected') || s.get('isInstalled');
  1058. }).mapProperty('serviceName');
  1059. // Load stack configs before loading themes
  1060. App.config.loadConfigsFromStack(serviceNames).done(function() {
  1061. App.config.loadConfigThemeForServices(serviceNames).always(function() {
  1062. self.set('stackConfigsLoaded', true);
  1063. App.themesMapper.generateAdvancedTabs(serviceNames);
  1064. dfd.resolve();
  1065. });
  1066. });
  1067. }
  1068. else {
  1069. dfd.resolve();
  1070. this.set('stackConfigsLoaded', true);
  1071. }
  1072. return dfd.promise();
  1073. }
  1074. });