wizard.js 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186
  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, App.ThemesMappingMixin, {
  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. var clusterStatus = {
  302. status: 'PENDING'
  303. };
  304. this.saveClusterStatus(clusterStatus);
  305. App.ajax.send({
  306. name: isRetry ? 'common.host_components.update' : 'common.services.update',
  307. sender: this,
  308. data: data,
  309. success: 'installServicesSuccessCallback',
  310. error: 'installServicesErrorCallback'
  311. }).then(callback, callback);
  312. },
  313. installServicesSuccessCallback: function (jsonData) {
  314. var installStartTime = App.dateTime();
  315. console.log("TRACE: In success function for the installService call");
  316. if (jsonData) {
  317. var requestId = jsonData.Requests.id;
  318. console.log('requestId is: ' + requestId);
  319. var clusterStatus = {
  320. status: 'PENDING',
  321. requestId: requestId,
  322. isInstallError: false,
  323. isCompleted: false,
  324. installStartTime: installStartTime
  325. };
  326. this.saveClusterStatus(clusterStatus);
  327. } else {
  328. console.log('ERROR: Error occurred in parsing JSON data');
  329. }
  330. },
  331. installServicesErrorCallback: function (request, ajaxOptions, error) {
  332. console.log("TRACE: In error function for the installService call");
  333. console.log("TRACE: error code status is: " + request.status);
  334. console.log('Error message is: ' + request.responseText);
  335. var clusterStatus = {
  336. status: 'PENDING',
  337. requestId: this.get('content.cluster.requestId'),
  338. isInstallError: true,
  339. isCompleted: false
  340. };
  341. this.saveClusterStatus(clusterStatus);
  342. App.showAlertPopup(Em.I18n.t('common.errorPopup.header'), request.responseText);
  343. },
  344. /**
  345. * show popup, that display status of bootstrap launching
  346. * @param callback
  347. * @return {Object}
  348. */
  349. showLaunchBootstrapPopup: function (callback) {
  350. return App.ModalPopup.show({
  351. header: Em.I18n.t('installer.step2.bootStrap.header'),
  352. isError: false,
  353. serverError: null,
  354. bodyClass: Em.View.extend({
  355. templateName: require('templates/wizard/bootstrap_call_popup')
  356. }),
  357. showFooter: false,
  358. showCloseButton: false,
  359. secondary: null,
  360. /**
  361. * handle requestId when call is completed,
  362. * if it's correct call callback and hide popup
  363. * otherwise notify error and enable buttons to close popup
  364. * @param requestId
  365. * @param serverError
  366. */
  367. finishLoading: function (requestId, serverError) {
  368. if (Em.isNone(requestId)) {
  369. this.set('isError', true);
  370. this.set('showFooter', true);
  371. this.set('showCloseButton', true);
  372. this.set('serverError', serverError);
  373. } else {
  374. callback(requestId);
  375. this.hide();
  376. }
  377. }
  378. });
  379. },
  380. /**
  381. * Bootstrap selected hosts.
  382. * @param bootStrapData
  383. * @param callback
  384. * @return {Object}
  385. */
  386. launchBootstrap: function (bootStrapData, callback) {
  387. var popup = this.showLaunchBootstrapPopup(callback);
  388. App.ajax.send({
  389. name: 'wizard.launch_bootstrap',
  390. sender: this,
  391. data: {
  392. bootStrapData: bootStrapData,
  393. popup: popup
  394. },
  395. success: 'launchBootstrapSuccessCallback',
  396. error: 'launchBootstrapErrorCallback'
  397. });
  398. return popup;
  399. },
  400. launchBootstrapSuccessCallback: function (data, opt, params) {
  401. console.log("TRACE: POST bootstrap succeeded");
  402. params.popup.finishLoading(data.requestId, null);
  403. },
  404. launchBootstrapErrorCallback: function (request, ajaxOptions, error, opt, params) {
  405. console.log("ERROR: POST bootstrap failed");
  406. params.popup.finishLoading(null, error);
  407. },
  408. /**
  409. * Load <code>content.<name></code> variable from localStorage, if wasn't loaded before.
  410. * If you specify <code>reload</code> to true - it will reload it.
  411. * @param name
  412. * @param reload
  413. * @return {Boolean}
  414. */
  415. load: function (name, reload) {
  416. if (this.get('content.' + name) && !reload) {
  417. return false;
  418. }
  419. var result = this.getDBProperty(name);
  420. if (!result) {
  421. if (this['get' + name.capitalize()]) {
  422. result = this['get' + name.capitalize()]();
  423. this.setDBProperty(name, result);
  424. console.log(this.get('name') + ": created " + name, result);
  425. }
  426. else {
  427. console.debug('get' + name.capitalize(), ' not defined in the ' + this.get('name'));
  428. }
  429. }
  430. this.set('content.' + name, result);
  431. console.log(this.get('name') + ": loaded " + name, result);
  432. },
  433. save: function (name) {
  434. var value = this.toObject(this.get('content.' + name));
  435. this.setDBProperty(name, value);
  436. console.log(this.get('name') + ": saved " + name, value);
  437. },
  438. clear: function () {
  439. this.set('content', Ember.Object.create({
  440. 'controllerName': this.get('content.controllerName')
  441. }));
  442. this.set('currentStep', 0);
  443. this.clearStorageData();
  444. },
  445. clusterStatusTemplate: {
  446. name: "",
  447. status: "PENDING",
  448. isCompleted: false,
  449. requestId: null,
  450. installStartTime: null,
  451. installTime: null,
  452. isInstallError: false,
  453. isStartError: false,
  454. oldRequestsId: []
  455. },
  456. clearStorageData: function () {
  457. this.get('dbPropertiesToClean').forEach(function (key) {
  458. this.setDBProperty(key, undefined);
  459. }, this);
  460. },
  461. getInstallOptions: function() {
  462. return jQuery.extend({}, App.get('isHadoopWindowsStack') ? this.get('installWindowsOptionsTemplate') : this.get('installOptionsTemplate'));
  463. },
  464. installOptionsTemplate: {
  465. hostNames: "", //string
  466. manualInstall: false, //true, false
  467. useSsh: true, //bool
  468. javaHome: App.defaultJavaHome, //string
  469. localRepo: false, //true, false
  470. sshKey: "", //string
  471. bootRequestId: null, //string
  472. sshUser: "root", //string
  473. agentUser: "root" //string
  474. },
  475. installWindowsOptionsTemplate: {
  476. hostNames: "", //string
  477. manualInstall: false, //true, false
  478. useSsh: true, //bool
  479. javaHome: App.defaultJavaHome, //string
  480. localRepo: false, //true, false
  481. sshKey: "", //string
  482. bootRequestId: null, //string
  483. sshUser: "", //string
  484. agentUser: "" //string
  485. },
  486. loadedServiceComponents: null,
  487. /**
  488. * Generate serviceComponents as pr the stack definition and save it to localdata
  489. * called form stepController step4WizardController
  490. */
  491. loadServiceComponents: function () {
  492. return App.ajax.send({
  493. name: 'wizard.service_components',
  494. sender: this,
  495. data: {
  496. stackUrl: App.get('stackVersionURL'),
  497. stackVersion: App.get('currentStackVersionNumber')
  498. },
  499. success: 'loadServiceComponentsSuccessCallback',
  500. error: 'loadServiceComponentsErrorCallback'
  501. });
  502. },
  503. loadServiceComponentsSuccessCallback: function (jsonData) {
  504. var savedSelectedServices = this.getDBProperty('selectedServiceNames');
  505. var savedInstalledServices = this.getDBProperty('installedServiceNames');
  506. this.set('content.selectedServiceNames', savedSelectedServices);
  507. this.set('content.installedServiceNames', savedInstalledServices);
  508. if (!savedSelectedServices) {
  509. jsonData.items.forEach(function (service) {
  510. service.StackServices.is_selected = true;
  511. }, this);
  512. } else {
  513. jsonData.items.forEach(function (service) {
  514. if (savedSelectedServices.contains(service.StackServices.service_name))
  515. service.StackServices.is_selected = true;
  516. else
  517. service.StackServices.is_selected = false;
  518. }, this);
  519. }
  520. if (!savedInstalledServices) {
  521. jsonData.items.forEach(function (service) {
  522. service.StackServices.is_installed = false;
  523. }, this);
  524. } else {
  525. jsonData.items.forEach(function (service) {
  526. if (savedInstalledServices.contains(service.StackServices.service_name))
  527. service.StackServices.is_installed = true;
  528. else
  529. service.StackServices.is_installed = false;
  530. }, this);
  531. }
  532. App.stackServiceMapper.mapStackServices(jsonData);
  533. },
  534. loadServiceComponentsErrorCallback: function (request, ajaxOptions, error) {
  535. console.log("TRACE: STep5 -> In error function for the getServiceComponents call");
  536. console.log("TRACE: STep5 -> error code status is: " + request.status);
  537. console.log('Step8: Error message is: ' + request.responseText);
  538. },
  539. /**
  540. * Load config groups from local DB
  541. */
  542. loadServiceConfigGroups: function () {
  543. var serviceConfigGroups = this.getDBProperty('serviceConfigGroups'),
  544. hosts = this.getDBProperty('hosts'),
  545. host_names = Em.keys(hosts);
  546. if (Em.isNone(serviceConfigGroups)) {
  547. serviceConfigGroups = [];
  548. }
  549. else {
  550. serviceConfigGroups.forEach(function(group) {
  551. var hostNames = group.hosts.map(function(host_id) {
  552. for (var i = 0; i < host_names.length; i++) {
  553. if (hosts[host_names[i]].id === host_id) {
  554. return host_names[i];
  555. }
  556. }
  557. Em.assert('host is missing!!!!', false);
  558. });
  559. Em.set(group, 'hosts', hostNames);
  560. });
  561. }
  562. this.set('content.configGroups', serviceConfigGroups);
  563. console.log("InstallerController.configGroups: loaded config ", serviceConfigGroups);
  564. },
  565. registerErrPopup: function (header, message) {
  566. App.ModalPopup.show({
  567. header: header,
  568. secondary: false,
  569. bodyClass: Ember.View.extend({
  570. template: Ember.Handlebars.compile('<p>{{view.message}}</p>'),
  571. message: message
  572. })
  573. });
  574. },
  575. /**
  576. * Save hosts that the user confirmed to proceed with from step 3
  577. * @param stepController App.WizardStep3Controller
  578. */
  579. saveConfirmedHosts: function (stepController) {
  580. var hosts = this.get('content.hosts'),
  581. indx = 1;
  582. //add previously installed hosts
  583. for (var hostName in hosts) {
  584. if (!hosts[hostName].isInstalled) {
  585. delete hosts[hostName];
  586. }
  587. }
  588. stepController.get('confirmedHosts').forEach(function (_host) {
  589. if (_host.bootStatus == 'REGISTERED') {
  590. hosts[_host.name] = {
  591. name: _host.name,
  592. cpu: _host.cpu,
  593. memory: _host.memory,
  594. disk_info: _host.disk_info,
  595. os_type: _host.os_type,
  596. os_arch: _host.os_arch,
  597. ip: _host.ip,
  598. bootStatus: _host.bootStatus,
  599. isInstalled: false,
  600. id: indx++
  601. };
  602. }
  603. });
  604. console.log('wizardController:saveConfirmedHosts: save hosts ', hosts);
  605. this.setDBProperty('hosts', hosts);
  606. this.set('content.hosts', hosts);
  607. },
  608. /**
  609. * Save data after installation to main controller
  610. * @param stepController App.WizardStep9Controller
  611. */
  612. saveInstalledHosts: function (stepController) {
  613. var hosts = stepController.get('hosts');
  614. var hostInfo = this.getDBProperty('hosts');
  615. for (var index in hostInfo) {
  616. hostInfo[index].status = "pending";
  617. var host = hosts.findProperty('name', hostInfo[index].name);
  618. if (host) {
  619. hostInfo[index].status = host.status;
  620. hostInfo[index].message = host.message;
  621. hostInfo[index].progress = host.progress;
  622. }
  623. }
  624. this.set('content.hosts', hostInfo);
  625. this.setDBProperty('hosts', hostInfo);
  626. console.log('wizardController:saveInstalledHosts: save hosts ', hostInfo);
  627. },
  628. /**
  629. * Save slaveHostComponents to main controller
  630. * @param stepController
  631. */
  632. saveSlaveComponentHosts: function (stepController) {
  633. var hosts = stepController.get('hosts'),
  634. dbHosts = this.getDBProperty('hosts'),
  635. headers = stepController.get('headers');
  636. var formattedHosts = Ember.Object.create();
  637. headers.forEach(function (header) {
  638. formattedHosts.set(header.get('name'), []);
  639. });
  640. hosts.forEach(function (host) {
  641. var checkboxes = host.get('checkboxes');
  642. headers.forEach(function (header) {
  643. var cb = checkboxes.findProperty('title', header.get('label'));
  644. if (cb.get('checked')) {
  645. formattedHosts.get(header.get('name')).push({
  646. group: 'Default',
  647. isInstalled: cb.get('isInstalled'),
  648. host_id: dbHosts[host.hostName].id
  649. });
  650. }
  651. });
  652. });
  653. var slaveComponentHosts = [];
  654. headers.forEach(function (header) {
  655. slaveComponentHosts.push({
  656. componentName: header.get('name'),
  657. displayName: header.get('label').replace(/\s/g, ''),
  658. hosts: formattedHosts.get(header.get('name'))
  659. });
  660. });
  661. this.setDBProperty('slaveComponentHosts', slaveComponentHosts);
  662. console.log('wizardController.slaveComponentHosts: saved hosts', slaveComponentHosts);
  663. this.set('content.slaveComponentHosts', slaveComponentHosts);
  664. },
  665. /**
  666. * Return true if cluster data is loaded and false otherwise.
  667. * This is used for all wizard controllers except for installer wizard.
  668. */
  669. dataLoading: function () {
  670. var dfd = $.Deferred();
  671. this.connectOutlet('loading');
  672. if (App.router.get('clusterController.isLoaded')) {
  673. dfd.resolve();
  674. } else {
  675. var interval = setInterval(function () {
  676. if (App.router.get('clusterController.isLoaded')) {
  677. dfd.resolve();
  678. clearInterval(interval);
  679. }
  680. }, 50);
  681. }
  682. return dfd.promise();
  683. },
  684. /**
  685. * Return true if user data is loaded via App.MainServiceInfoConfigsController
  686. * This function is used in reassign master wizard right now.
  687. */
  688. usersLoading: function () {
  689. var self = this;
  690. var dfd = $.Deferred();
  691. var miscController = App.MainAdminServiceAccountsController.create({content: self.get('content')});
  692. miscController.loadUsers();
  693. var interval = setInterval(function () {
  694. if (miscController.get('dataIsLoaded')) {
  695. if (self.get("content.hdfsUser")) {
  696. self.set('content.hdfsUser', miscController.get('content.hdfsUser'));
  697. }
  698. dfd.resolve();
  699. clearInterval(interval);
  700. }
  701. }, 10);
  702. return dfd.promise();
  703. },
  704. /**
  705. * Save cluster status before going to deploy step
  706. * @param name cluster state. Unique for every wizard
  707. */
  708. saveClusterState: function (name) {
  709. App.clusterStatus.setClusterStatus({
  710. clusterName: this.get('content.cluster.name'),
  711. clusterState: name,
  712. wizardControllerName: this.get('content.controllerName'),
  713. localdb: App.db.data
  714. });
  715. },
  716. /**
  717. * load advanced configs from server
  718. */
  719. loadAdvancedConfigs: function (dependentController) {
  720. var self = this;
  721. var loadServiceConfigsFn = function(clusterProperties) {
  722. var stackServices = self.get('content.services').filter(function (service) {
  723. return service.get('isInstalled') || service.get('isSelected');
  724. });
  725. var counter = stackServices.length;
  726. var loadAdvancedConfigResult = [];
  727. dependentController.set('isAdvancedConfigLoaded', false);
  728. stackServices.forEach(function (service) {
  729. var serviceName = service.get('serviceName');
  730. App.config.loadAdvancedConfig(serviceName, function (properties) {
  731. var supportsFinal = App.config.getConfigTypesInfoFromService(service).supportsFinal;
  732. function shouldSupportFinal(filename) {
  733. var matchingConfigType = supportsFinal.find(function (configType) {
  734. return filename.startsWith(configType);
  735. });
  736. return !!matchingConfigType;
  737. }
  738. properties.forEach(function (property) {
  739. property.supportsFinal = shouldSupportFinal(property.filename);
  740. });
  741. loadAdvancedConfigResult.pushObjects(properties);
  742. counter--;
  743. //pass configs to controller after last call is completed
  744. if (counter === 0) {
  745. loadAdvancedConfigResult.pushObjects(clusterProperties);
  746. self.set('content.advancedServiceConfig', loadAdvancedConfigResult);
  747. self.setDBProperty('advancedServiceConfig', loadAdvancedConfigResult);
  748. dependentController.set('isAdvancedConfigLoaded', true);
  749. }
  750. });
  751. }, this);
  752. };
  753. App.config.loadClusterConfig(loadServiceConfigsFn);
  754. },
  755. /**
  756. * Load serviceConfigProperties to model
  757. */
  758. loadServiceConfigProperties: function () {
  759. var serviceConfigProperties = this.getDBProperty('serviceConfigProperties');
  760. this.set('content.serviceConfigProperties', serviceConfigProperties);
  761. console.log("AddHostController.loadServiceConfigProperties: loaded config ", serviceConfigProperties);
  762. },
  763. /**
  764. * Save config properties
  765. * @param stepController Step7WizardController
  766. */
  767. saveServiceConfigProperties: function (stepController) {
  768. var serviceConfigProperties = [];
  769. var fileNamesToUpdate = [];
  770. stepController.get('stepConfigs').forEach(function (_content) {
  771. if (_content.serviceName === 'YARN') {
  772. _content.set('configs', App.config.textareaIntoFileConfigs(_content.get('configs'), 'capacity-scheduler.xml'));
  773. }
  774. _content.get('configs').forEach(function (_configProperties) {
  775. var configProperty = {
  776. id: _configProperties.get('id'),
  777. name: _configProperties.get('name'),
  778. value: _configProperties.get('value'),
  779. defaultValue: _configProperties.get('defaultValue'),
  780. description: _configProperties.get('description'),
  781. serviceName: _configProperties.get('serviceName'),
  782. domain: _configProperties.get('domain'),
  783. isVisible: _configProperties.get('isVisible'),
  784. isFinal: _configProperties.get('isFinal'),
  785. defaultIsFinal: _configProperties.get('isFinal'),
  786. supportsFinal: _configProperties.get('supportsFinal'),
  787. filename: _configProperties.get('filename'),
  788. displayType: _configProperties.get('displayType'),
  789. isRequiredByAgent: _configProperties.get('isRequiredByAgent'),
  790. hasInitialValue: !!_configProperties.get('hasInitialValue'),
  791. isRequired: _configProperties.get('isRequired'), // flag that allow saving property with empty value
  792. group: !!_configProperties.get('group') ? _configProperties.get('group.name') : null,
  793. showLabel: _configProperties.get('showLabel'),
  794. category: _configProperties.get('category')
  795. };
  796. serviceConfigProperties.push(configProperty);
  797. }, this);
  798. // check for configs that need to update for installed services
  799. if (stepController.get('installedServiceNames') && stepController.get('installedServiceNames').contains(_content.get('serviceName'))) {
  800. // get only modified configs
  801. var configs = _content.get('configs').filter(function (config) {
  802. if (config.get('isNotDefaultValue') || (config.get('defaultValue') === null)) {
  803. var notAllowed = ['masterHost', 'masterHosts', 'slaveHosts', 'slaveHost'];
  804. return !notAllowed.contains(config.get('displayType')) && !!config.filename;
  805. }
  806. return false;
  807. });
  808. // if modified configs detected push all service's configs for update
  809. if (configs.length) {
  810. fileNamesToUpdate = fileNamesToUpdate.concat(configs.mapProperty('filename').uniq());
  811. }
  812. // watch for properties that are not modified but have to be updated
  813. if (_content.get('configs').someProperty('forceUpdate')) {
  814. // check for already added modified properties
  815. var forceUpdatedFileNames = _content.get('configs').filterProperty('forceUpdate', true).mapProperty('filename').uniq();
  816. fileNamesToUpdate = fileNamesToUpdate.concat(forceUpdatedFileNames).uniq();
  817. }
  818. }
  819. }, this);
  820. this.setDBProperty('serviceConfigProperties', serviceConfigProperties);
  821. this.set('content.serviceConfigProperties', serviceConfigProperties);
  822. this.setDBProperty('fileNamesToUpdate', fileNamesToUpdate);
  823. },
  824. /**
  825. * save Config groups
  826. * @param stepController
  827. * @param isAddService
  828. */
  829. saveServiceConfigGroups: function (stepController, isAddService) {
  830. var serviceConfigGroups = [],
  831. isForInstalledService = false,
  832. hosts = isAddService ? App.router.get('addServiceController').getDBProperty('hosts') : this.getDBProperty('hosts');
  833. stepController.get('stepConfigs').forEach(function (service) {
  834. // mark group of installed service
  835. if (service.get('selected') === false) isForInstalledService = true;
  836. service.get('configGroups').forEach(function (configGroup) {
  837. var properties = [];
  838. configGroup.get('properties').forEach(function (property) {
  839. properties.push({
  840. isRequiredByAgent: property.get('isRequiredByAgent'),
  841. name: property.get('name'),
  842. value: property.get('value'),
  843. isFinal: property.get('isFinal'),
  844. filename: property.get('filename')
  845. })
  846. });
  847. //configGroup copied into plain JS object to avoid Converting circular structure to JSON
  848. var hostNames = configGroup.get('hosts').map(function(host_name) {return hosts[host_name].id;});
  849. serviceConfigGroups.push({
  850. id: configGroup.get('id'),
  851. name: configGroup.get('name'),
  852. description: configGroup.get('description'),
  853. hosts: hostNames,
  854. properties: properties,
  855. isDefault: configGroup.get('isDefault'),
  856. isForInstalledService: isForInstalledService,
  857. isForUpdate: configGroup.isForUpdate || configGroup.get('hash') != this.getConfigGroupHash(configGroup, hostNames),
  858. service: {id: configGroup.get('service.id')}
  859. });
  860. }, this)
  861. }, this);
  862. this.setDBProperty('serviceConfigGroups', serviceConfigGroups);
  863. this.set('content.configGroups', serviceConfigGroups);
  864. },
  865. /**
  866. * generate string hash for config group
  867. * @param {Object} configGroup
  868. * @param {Array|undefined} hosts
  869. * @returns {String|null}
  870. * @method getConfigGroupHash
  871. */
  872. getConfigGroupHash: function(configGroup, hosts) {
  873. if (!Em.get(configGroup, 'properties.length') && !Em.get(configGroup, 'hosts.length') && !hosts) {
  874. return null;
  875. }
  876. var hash = {};
  877. Em.get(configGroup, 'properties').forEach(function (config) {
  878. hash[Em.get(config, 'name')] = {value: Em.get(config, 'value'), isFinal: Em.get(config, 'isFinal')};
  879. });
  880. hash['hosts'] = hosts || Em.get(configGroup, 'hosts');
  881. return JSON.stringify(hash);
  882. },
  883. /**
  884. * return slaveComponents bound to hosts
  885. * @return {Array}
  886. */
  887. getSlaveComponentHosts: function () {
  888. var components = this.get('slaveComponents');
  889. var result = [];
  890. var installedServices = App.Service.find().mapProperty('serviceName');
  891. var selectedServices = App.StackService.find().filterProperty('isSelected', true).mapProperty('serviceName');
  892. var installedComponentsMap = {};
  893. var uninstalledComponents = [];
  894. components.forEach(function (component) {
  895. if (installedServices.contains(component.get('serviceName'))) {
  896. installedComponentsMap[component.get('componentName')] = [];
  897. } else if (selectedServices.contains(component.get('serviceName'))) {
  898. uninstalledComponents.push(component);
  899. }
  900. }, this);
  901. installedComponentsMap['HDFS_CLIENT'] = [];
  902. App.HostComponent.find().forEach(function (hostComponent) {
  903. if (installedComponentsMap[hostComponent.get('componentName')]) {
  904. installedComponentsMap[hostComponent.get('componentName')].push(hostComponent.get('hostName'));
  905. }
  906. }, this);
  907. for (var componentName in installedComponentsMap) {
  908. var name = (componentName === 'HDFS_CLIENT') ? 'CLIENT' : componentName;
  909. var component = {
  910. componentName: name,
  911. displayName: App.format.role(name),
  912. hosts: [],
  913. isInstalled: true
  914. };
  915. installedComponentsMap[componentName].forEach(function (hostName) {
  916. component.hosts.push({
  917. group: "Default",
  918. hostName: hostName,
  919. isInstalled: true
  920. });
  921. }, this);
  922. result.push(component);
  923. }
  924. uninstalledComponents.forEach(function (component) {
  925. var hosts = jQuery.extend(true, [], result.findProperty('componentName', 'DATANODE').hosts);
  926. hosts.setEach('isInstalled', false);
  927. result.push({
  928. componentName: component.get('componentName'),
  929. displayName: App.format.role(component.get('componentName')),
  930. hosts: hosts,
  931. isInstalled: false
  932. })
  933. });
  934. return result;
  935. },
  936. /**
  937. * Load master component hosts data for using in required step controllers
  938. */
  939. loadMasterComponentHosts: function () {
  940. var masterComponentHosts = this.getDBProperty('masterComponentHosts');
  941. var stackMasterComponents = App.get('components.masters').uniq();
  942. if (!masterComponentHosts) {
  943. masterComponentHosts = [];
  944. App.HostComponent.find().filter(function(component) {
  945. return stackMasterComponents.contains(component.get('componentName'));
  946. }).forEach(function (item) {
  947. masterComponentHosts.push({
  948. component: item.get('componentName'),
  949. hostName: item.get('hostName'),
  950. isInstalled: true,
  951. serviceId: item.get('service.id'),
  952. display_name: item.get('displayName')
  953. })
  954. });
  955. this.setDBProperty('masterComponentHosts', masterComponentHosts);
  956. }
  957. this.set("content.masterComponentHosts", masterComponentHosts);
  958. },
  959. /**
  960. * Load information about hosts with clients components
  961. */
  962. loadClients: function () {
  963. var clients = this.getDBProperty('clientInfo');
  964. this.set('content.clients', clients);
  965. console.log(this.get('content.controllerName') + ".loadClients: loaded list ", clients);
  966. },
  967. /**
  968. * load methods assigned to each step
  969. * methods executed in exact order as they described in map
  970. * @return {object}
  971. */
  972. loadAllPriorSteps: function () {
  973. var currentStep = this.get('currentStep');
  974. var loadMap = this.get('loadMap');
  975. var operationStack = [];
  976. var dfd = $.Deferred();
  977. for (var s in loadMap) {
  978. if (parseInt(s) <= parseInt(currentStep)) {
  979. operationStack.pushObjects(loadMap[s]);
  980. }
  981. }
  982. var sequence = App.actionSequence.create({context: this});
  983. sequence.setSequence(operationStack).onFinish(function () {
  984. dfd.resolve();
  985. }).start();
  986. return dfd.promise();
  987. },
  988. /**
  989. * return new object extended from clusterStatusTemplate
  990. * @return Object
  991. */
  992. getCluster: function () {
  993. return jQuery.extend({}, this.get('clusterStatusTemplate'), {name: App.router.getClusterName()});
  994. },
  995. /**
  996. * Load services data from server.
  997. */
  998. loadServicesFromServer: function () {
  999. var services = this.getDBProperty('services');
  1000. if (!services) {
  1001. services = {
  1002. selectedServices: [],
  1003. installedServices: []
  1004. };
  1005. App.StackService.find().forEach(function(item){
  1006. var isInstalled = App.Service.find().someProperty('id', item.get('serviceName'));
  1007. item.set('isSelected', isInstalled);
  1008. item.set('isInstalled', isInstalled);
  1009. if (isInstalled) {
  1010. services.selectedServices.push(item.get('serviceName'));
  1011. services.installedServices.push(item.get('serviceName'));
  1012. }
  1013. },this);
  1014. this.setDBProperty('services',services);
  1015. } else {
  1016. App.StackService.find().forEach(function(item) {
  1017. var isSelected = services.selectedServices.contains(item.get('serviceName'));
  1018. var isInstalled = services.installedServices.contains(item.get('serviceName'));
  1019. item.set('isSelected', isSelected);
  1020. item.set('isInstalled', isInstalled);
  1021. },this);
  1022. }
  1023. this.set('content.services', App.StackService.find());
  1024. },
  1025. /**
  1026. * Load confirmed hosts.
  1027. * Will be used at <code>Assign Masters(step5)</code> step
  1028. */
  1029. loadConfirmedHosts: function () {
  1030. var hosts = App.db.getHosts();
  1031. if (hosts) {
  1032. this.set('content.hosts', hosts);
  1033. }
  1034. },
  1035. /**
  1036. * Determine if <code>Assign Slaves and Clients</code> step should be skipped
  1037. * @method setSkipSlavesStep
  1038. * @param services
  1039. * @param step
  1040. */
  1041. setSkipSlavesStep: function (services, step) {
  1042. var hasServicesWithSlave = services.someProperty('hasSlave');
  1043. var hasServicesWithClient = services.someProperty('hasClient');
  1044. var hasServicesWithCustomAssignedNonMasters = services.someProperty('hasNonMastersWithCustomAssignment');
  1045. this.set('content.skipSlavesStep', !hasServicesWithSlave && !hasServicesWithClient || !hasServicesWithCustomAssignedNonMasters);
  1046. if (this.get('content.skipSlavesStep')) {
  1047. this.get('isStepDisabled').findProperty('step', step).set('value', this.get('content.skipSlavesStep'));
  1048. }
  1049. },
  1050. /**
  1051. * Load config themes for enhanced config layout.
  1052. *
  1053. * @method loadConfigThemes
  1054. * @return {$.Deferred}
  1055. */
  1056. loadConfigThemes: function() {
  1057. var self = this;
  1058. var dfd = $.Deferred();
  1059. if (App.get('supports.enhancedConfigs') && !this.get('stackConfigsLoaded')) {
  1060. var serviceNames = App.StackService.find().filter(function(s) {
  1061. return s.get('isSelected') || s.get('isInstalled');
  1062. }).mapProperty('serviceName');
  1063. // Load stack configs before loading themes
  1064. App.config.loadConfigsFromStack(serviceNames).done(function() {
  1065. self.loadConfigThemeForServices(serviceNames).always(function() {
  1066. self.set('stackConfigsLoaded', true);
  1067. App.themesMapper.generateAdvancedTabs(serviceNames);
  1068. dfd.resolve();
  1069. });
  1070. });
  1071. }
  1072. else {
  1073. dfd.resolve();
  1074. this.set('stackConfigsLoaded', true);
  1075. }
  1076. return dfd.promise();
  1077. }
  1078. });