stack_and_upgrade_controller.js 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522
  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. var stringUtils = require('utils/string_utils');
  20. App.MainAdminStackAndUpgradeController = Em.Controller.extend(App.LocalStorage, {
  21. name: 'mainAdminStackAndUpgradeController',
  22. /**
  23. * @type {boolean}
  24. */
  25. isLoaded: false,
  26. /**
  27. * @type {object}
  28. * @default null
  29. */
  30. upgradeData: null,
  31. /**
  32. * @type {number}
  33. * @default null
  34. */
  35. upgradeId: null,
  36. /**
  37. * @type {string}
  38. * @default null
  39. */
  40. upgradeVersion: null,
  41. /**
  42. * @type {string}
  43. * @default null
  44. */
  45. upgradeType: null,
  46. /**
  47. * @type {boolean}
  48. * @default true
  49. */
  50. downgradeAllowed: true,
  51. /**
  52. * @type {string}
  53. * @default null
  54. */
  55. upgradeTypeDisplayName: null,
  56. /**
  57. * @type {object}
  58. * @default null
  59. */
  60. failuresTolerance: null,
  61. /**
  62. * @type {boolean}
  63. * @default false
  64. */
  65. isDowngrade: false,
  66. /**
  67. * version that currently applied to server
  68. * should be plain object, because stored to localStorage
  69. * @type {object|null}
  70. */
  71. currentVersion: null,
  72. /**
  73. * versions to which cluster could be upgraded
  74. * @type {Array}
  75. */
  76. targetVersions: [],
  77. /**
  78. * @type {object}
  79. * @default null
  80. */
  81. slaveComponentStructuredInfo: null,
  82. /**
  83. * @type {Array}
  84. */
  85. serviceCheckFailuresServicenames: [],
  86. /**
  87. * methods through which cluster could be upgraded, "allowed" indicated if the method is allowed
  88. * by stack upgrade path
  89. * @type {Array}
  90. */
  91. upgradeMethods: [
  92. Em.Object.create({
  93. displayName: Em.I18n.t('admin.stackVersions.version.upgrade.upgradeOptions.RU.title'),
  94. type: 'ROLLING',
  95. icon: "icon-dashboard",
  96. description: Em.I18n.t('admin.stackVersions.version.upgrade.upgradeOptions.RU.description'),
  97. selected: false,
  98. allowed: true
  99. }),
  100. Em.Object.create({
  101. displayName: Em.I18n.t('admin.stackVersions.version.upgrade.upgradeOptions.EU.title'),
  102. type: 'NON_ROLLING',
  103. icon: "icon-bolt",
  104. description: Em.I18n.t('admin.stackVersions.version.upgrade.upgradeOptions.EU.description'),
  105. selected: false,
  106. allowed: true
  107. })
  108. ],
  109. /**
  110. * @type {boolean} true if some request that should disable actions is in progress
  111. */
  112. requestInProgress: false,
  113. /**
  114. * @type {boolean} true while no updated upgrade info is loaded after retry
  115. */
  116. isRetryPending: false,
  117. /**
  118. * properties that stored to localStorage to resume wizard progress
  119. */
  120. wizardStorageProperties: [
  121. 'upgradeId',
  122. 'upgradeVersion',
  123. 'currentVersion',
  124. 'upgradeTypeDisplayName',
  125. 'upgradeType',
  126. 'failuresTolerance',
  127. 'isDowngrade',
  128. 'downgradeAllowed',
  129. 'isSuspended'
  130. ],
  131. /**
  132. * mutable properties of Upgrade Task
  133. * @type {Array}
  134. */
  135. taskDetailsProperties: ['status', 'stdout', 'stderr', 'error_log', 'host_name', 'output_log'],
  136. /**
  137. * Context for Finalize item
  138. * @type {string}
  139. */
  140. finalizeContext: 'Confirm Finalize',
  141. /**
  142. * Context for Slave component failures manual item
  143. * @type {string}
  144. */
  145. slaveFailuresContext: "Check Component Versions",
  146. /**
  147. * Context for Service check (may include slave component) failures manual item
  148. * @type {string}
  149. */
  150. serviceCheckFailuresContext: "Verifying Skipped Failures",
  151. /**
  152. * Check if current item is Finalize
  153. * @type {boolean}
  154. */
  155. isFinalizeItem: false,
  156. isLoadUpgradeDataPending: false,
  157. /**
  158. * path to the mock json
  159. * @type {String}
  160. */
  161. mockRepoUrl: '/data/stack_versions/repo_versions_all.json',
  162. /**
  163. * api to get RepoVersions
  164. * @type {String}
  165. */
  166. realRepoUrl: function () {
  167. return App.get('apiPrefix') + App.get('stackVersionURL') +
  168. '/compatible_repository_versions?fields=*,operating_systems/*,operating_systems/repositories/*';
  169. }.property('App.stackVersionURL'),
  170. /**
  171. * path to the mock json
  172. * @type {String}
  173. */
  174. mockStackUrl: '/data/stack_versions/stack_version_all.json',
  175. /**
  176. * api to get ClusterStackVersions with repository_versions (use to init data load)
  177. * @type {String}
  178. */
  179. realStackUrl: function () {
  180. return App.get('apiPrefix') + '/clusters/' + App.get('clusterName') +
  181. '/stack_versions?fields=*,repository_versions/*,repository_versions/operating_systems/repositories/*';
  182. }.property('App.clusterName'),
  183. /**
  184. * api to get ClusterStackVersions without repository_versions (use to update data)
  185. * @type {String}
  186. */
  187. realUpdateUrl: function () {
  188. return App.get('apiPrefix') + '/clusters/' + App.get('clusterName') + '/stack_versions?fields=ClusterStackVersions/*';
  189. }.property('App.clusterName'),
  190. /**
  191. * Determines if list of services with checks that failed and were skipped by user during the upgrade is loaded
  192. * @type {boolean}
  193. */
  194. areSkippedServiceChecksLoaded: false,
  195. /**
  196. * List of services with checks that failed and were skipped by user during the upgrade
  197. * @type {array}
  198. */
  199. skippedServiceChecks: [],
  200. /**
  201. * status of tasks/items/groups which should be grayed out and disabled
  202. * @type {Array}
  203. */
  204. nonActiveStates: ['PENDING', 'ABORTED'],
  205. /**
  206. * status of Upgrade request
  207. * @type {string}
  208. */
  209. requestStatus: function () {
  210. if (this.get('isSuspended')) {
  211. return 'SUSPENDED';
  212. } else if (this.get('upgradeData.Upgrade')){
  213. return this.get('upgradeData.Upgrade.request_status');
  214. } else {
  215. return '';
  216. }
  217. }.property('isSuspended', 'upgradeData.Upgrade.request_status'),
  218. init: function () {
  219. this.initDBProperties();
  220. },
  221. /**
  222. * restore data from localStorage
  223. */
  224. initDBProperties: function () {
  225. var props = this.getDBProperties(this.get('wizardStorageProperties'));
  226. Em.keys(props).forEach(function (k) {
  227. if (!Em.isNone(props[k])) {
  228. this.set(k, props[k]);
  229. }
  230. }, this);
  231. },
  232. /**
  233. * load all data:
  234. * - upgrade data
  235. * - stack versions
  236. * - repo versions
  237. */
  238. load: function () {
  239. var dfd = $.Deferred();
  240. var self = this;
  241. this.loadUpgradeData(true).done(function() {
  242. self.loadStackVersionsToModel(true).done(function () {
  243. self.loadRepoVersionsToModel().done(function() {
  244. var currentVersion = App.StackVersion.find().findProperty('state', 'CURRENT');
  245. if (currentVersion) {
  246. self.set('currentVersion', {
  247. repository_version: currentVersion.get('repositoryVersion.repositoryVersion'),
  248. repository_name: currentVersion.get('repositoryVersion.displayName')
  249. });
  250. }
  251. dfd.resolve();
  252. });
  253. });
  254. });
  255. return dfd.promise();
  256. },
  257. /**
  258. * load upgrade tasks by upgrade id
  259. * @return {$.Deferred}
  260. * @param {boolean} onlyState
  261. */
  262. loadUpgradeData: function (onlyState) {
  263. var upgradeId = this.get('upgradeId'),
  264. deferred = $.Deferred(),
  265. self = this;
  266. if (Em.isNone(upgradeId)) {
  267. deferred.resolve();
  268. } else {
  269. this.set('isLoadUpgradeDataPending', true);
  270. App.ajax.send({
  271. name: (onlyState) ? 'admin.upgrade.state' : 'admin.upgrade.data',
  272. sender: this,
  273. data: {
  274. id: upgradeId
  275. },
  276. success: 'loadUpgradeDataSuccessCallback'
  277. }).then(deferred.resolve).complete(function () {
  278. self.set('isLoadUpgradeDataPending', false);
  279. });
  280. }
  281. return deferred.promise();
  282. },
  283. /**
  284. * parse and push upgrade tasks to controller
  285. * @param data
  286. */
  287. loadUpgradeDataSuccessCallback: function (data) {
  288. if (Em.isNone(data)) return;
  289. App.set('upgradeState', data.Upgrade.request_status);
  290. this.setDBProperty('upgradeState', data.Upgrade.request_status);
  291. if (data.upgrade_groups) {
  292. this.updateUpgradeData(data);
  293. }
  294. if (this.get('isRetryPending') && data.Upgrade.request_status != 'ABORTED') {
  295. this.setProperties({
  296. requestInProgress: false,
  297. isRetryPending: false
  298. });
  299. }
  300. },
  301. /**
  302. * update data of Upgrade
  303. * @param {object} newData
  304. */
  305. updateUpgradeData: function (newData) {
  306. var oldData = this.get('upgradeData'),
  307. nonActiveStates = this.get('nonActiveStates'),
  308. groupsMap = {},
  309. itemsMap = {};
  310. if (Em.isNone(oldData) || (newData.upgrade_groups.length !== oldData.upgradeGroups.length)) {
  311. this.initUpgradeData(newData);
  312. } else {
  313. //create entities maps
  314. newData.upgrade_groups.forEach(function (newGroup) {
  315. groupsMap[newGroup.UpgradeGroup.group_id] = newGroup.UpgradeGroup;
  316. newGroup.upgrade_items.forEach(function (item) {
  317. itemsMap[item.UpgradeItem.stage_id] = item.UpgradeItem;
  318. })
  319. });
  320. //update existed entities with new data
  321. oldData.upgradeGroups.forEach(function (oldGroup) {
  322. oldGroup.set('status', groupsMap[oldGroup.get('group_id')].status);
  323. oldGroup.set('progress_percent', groupsMap[oldGroup.get('group_id')].progress_percent);
  324. oldGroup.set('completed_task_count', groupsMap[oldGroup.get('group_id')].completed_task_count);
  325. oldGroup.upgradeItems.forEach(function (item) {
  326. item.set('status', itemsMap[item.get('stage_id')].status);
  327. item.set('progress_percent', itemsMap[item.get('stage_id')].progress_percent);
  328. });
  329. var hasExpandableItems = oldGroup.upgradeItems.some(function (item) {
  330. return !nonActiveStates.contains(item.get('status'));
  331. });
  332. oldGroup.set('hasExpandableItems', hasExpandableItems);
  333. });
  334. oldData.set('Upgrade', newData.Upgrade);
  335. }
  336. },
  337. /**
  338. * change structure of Upgrade
  339. * In order to maintain nested views in template object should have direct link to its properties, for example
  340. * item.UpgradeItem.<properties> -> item.<properties>
  341. * @param {object} newData
  342. */
  343. initUpgradeData: function (newData) {
  344. var upgradeGroups = [],
  345. nonActiveStates = this.get('nonActiveStates');
  346. //wrap all entities into App.upgradeEntity
  347. newData.upgrade_groups.forEach(function (newGroup) {
  348. var hasExpandableItems = newGroup.upgrade_items.some(function (item) {
  349. return !nonActiveStates.contains(item.UpgradeItem.status);
  350. }),
  351. oldGroup = App.upgradeEntity.create({type: 'GROUP', hasExpandableItems: hasExpandableItems}, newGroup.UpgradeGroup),
  352. upgradeItems = [];
  353. newGroup.upgrade_items.forEach(function (item) {
  354. var oldItem = App.upgradeEntity.create({type: 'ITEM'}, item.UpgradeItem);
  355. oldItem.set('tasks', []);
  356. upgradeItems.pushObject(oldItem);
  357. });
  358. upgradeItems.reverse();
  359. oldGroup.set('upgradeItems', upgradeItems);
  360. upgradeGroups.pushObject(oldGroup);
  361. });
  362. upgradeGroups.reverse();
  363. this.set('upgradeData', Em.Object.create({
  364. upgradeGroups: upgradeGroups,
  365. Upgrade: newData.Upgrade
  366. }));
  367. this.set('downgradeAllowed', newData.Upgrade.downgrade_allowed);
  368. this.setDBProperty('downgradeAllowed', newData.Upgrade.downgrade_allowed);
  369. },
  370. /**
  371. * request Upgrade Item and its tasks from server
  372. * @param {Em.Object} item
  373. * @param {Function} customCallback
  374. * @return {$.ajax}
  375. */
  376. getUpgradeItem: function (item, customCallback) {
  377. return App.ajax.send({
  378. name: 'admin.upgrade.upgrade_item',
  379. sender: this,
  380. data: {
  381. upgradeId: item.get('request_id'),
  382. groupId: item.get('group_id'),
  383. stageId: item.get('stage_id')
  384. },
  385. success: customCallback || 'getUpgradeItemSuccessCallback'
  386. });
  387. },
  388. /**
  389. * success callback of <code>getTasks</code>
  390. * @param {object} data
  391. */
  392. getUpgradeItemSuccessCallback: function (data) {
  393. this.get('upgradeData.upgradeGroups').forEach(function (group) {
  394. if (group.get('group_id') === data.UpgradeItem.group_id) {
  395. group.get('upgradeItems').forEach(function (item) {
  396. if (item.get('stage_id') === data.UpgradeItem.stage_id) {
  397. if (item.get('tasks.length')) {
  398. item.set('isTasksLoaded', true);
  399. data.tasks.forEach(function (task) {
  400. var currentTask = item.get('tasks').findProperty('id', task.Tasks.id);
  401. this.get('taskDetailsProperties').forEach(function (property) {
  402. currentTask.set(property, task.Tasks[property]);
  403. }, this);
  404. }, this);
  405. } else {
  406. var tasks = [];
  407. data.tasks.forEach(function (task) {
  408. tasks.pushObject(App.upgradeEntity.create({type: 'TASK'}, task.Tasks));
  409. });
  410. item.set('tasks', tasks);
  411. }
  412. item.set('isTasksLoaded', true);
  413. }
  414. }, this);
  415. }
  416. }, this);
  417. },
  418. /**
  419. * Failures info may includes service_check and host_component failures. These two types should be displayed separately.
  420. */
  421. getServiceCheckItemSuccessCallback: function(data) {
  422. var task = data.tasks[0];
  423. var info = {
  424. hosts: [],
  425. host_detail: {}
  426. };
  427. if (task && task.Tasks && task.Tasks.structured_out && task.Tasks.structured_out.failures) {
  428. this.set('serviceCheckFailuresServicenames', task.Tasks.structured_out.failures.service_check || []);
  429. if (task.Tasks.structured_out.failures.host_component) {
  430. for (var hostname in task.Tasks.structured_out.failures.host_component){
  431. info.hosts.push(hostname);
  432. }
  433. info.host_detail = task.Tasks.structured_out.failures.host_component;
  434. }
  435. this.set('slaveComponentStructuredInfo', info);
  436. }
  437. },
  438. getSlaveComponentItemSuccessCallback: function(data) {
  439. var info = data.tasks[0];
  440. if (info && info.Tasks && info.Tasks.structured_out) {
  441. this.set('slaveComponentStructuredInfo', info.Tasks.structured_out);
  442. }
  443. },
  444. /**
  445. * downgrade confirmation popup
  446. * @param {object} event
  447. */
  448. confirmDowngrade: function (event) {
  449. var self = this;
  450. var currentVersion = this.get('currentVersion');
  451. return App.showConfirmationPopup(
  452. function() {
  453. self.downgrade.call(self, currentVersion, event);
  454. },
  455. Em.I18n.t('admin.stackUpgrade.downgrade.body').format(currentVersion.repository_name),
  456. null,
  457. Em.I18n.t('admin.stackUpgrade.dialog.downgrade.header').format(currentVersion.repository_name),
  458. Em.I18n.t('admin.stackUpgrade.downgrade.proceed')
  459. );
  460. },
  461. /**
  462. * make call to start downgrade process
  463. * @param {object} currentVersion
  464. * @param {object} event
  465. */
  466. downgrade: function (currentVersion, event) {
  467. this.set('requestInProgress', true);
  468. this.abortUpgrade();
  469. App.ajax.send({
  470. name: 'admin.downgrade.start',
  471. sender: this,
  472. data: {
  473. from: App.RepositoryVersion.find().findProperty('displayName', this.get('upgradeVersion')).get('repositoryVersion'),
  474. value: currentVersion.repository_version,
  475. label: currentVersion.repository_name,
  476. isDowngrade: true,
  477. upgradeType: this.get('upgradeType')
  478. },
  479. success: 'upgradeSuccessCallback',
  480. callback: function() {
  481. this.sender.set('requestInProgress', false);
  482. }
  483. });
  484. },
  485. /**
  486. * abort upgrade (in order to start Downgrade)
  487. */
  488. abortUpgrade: function () {
  489. return App.ajax.send({
  490. name: 'admin.upgrade.abort',
  491. sender: this,
  492. data: {
  493. upgradeId: this.get('upgradeId')
  494. }
  495. });
  496. },
  497. retryUpgrade: function () {
  498. this.setProperties({
  499. requestInProgress: true,
  500. isRetryPending: true
  501. });
  502. return App.ajax.send({
  503. name: 'admin.upgrade.retry',
  504. sender: this,
  505. data: {
  506. upgradeId: this.get('upgradeId')
  507. }
  508. });
  509. },
  510. /**
  511. * make call to start upgrade process and show popup with current progress
  512. * @param {object} version
  513. */
  514. upgrade: function (version) {
  515. this.set('requestInProgress', true);
  516. App.ajax.send({
  517. name: 'admin.upgrade.start',
  518. sender: this,
  519. data: version,
  520. success: 'upgradeSuccessCallback',
  521. callback: function() {
  522. this.sender.set('requestInProgress', false);
  523. }
  524. });
  525. this.setDBProperty('currentVersion', this.get('currentVersion'));
  526. },
  527. /**
  528. * success callback of <code>upgrade()</code>
  529. * @param {object} data
  530. */
  531. upgradeSuccessCallback: function (data, opt, params) {
  532. this.set('upgradeData', null);
  533. this.set('upgradeId', data.resources[0].Upgrade.request_id);
  534. this.set('upgradeVersion', params.label);
  535. this.set('isDowngrade', !!params.isDowngrade);
  536. var upgradeMethod = this.get('upgradeMethods').findProperty('type', params.type);
  537. var upgradeTypeDisplayName = null;
  538. var upgradeType = null;
  539. if (upgradeMethod) {
  540. upgradeTypeDisplayName = upgradeMethod.get('displayName');
  541. upgradeType = upgradeMethod.get('type');
  542. }
  543. this.set('upgradeType', upgradeType);
  544. this.set('upgradeTypeDisplayName', upgradeTypeDisplayName);
  545. this.set('failuresTolerance', Em.Object.create({
  546. skipComponentFailures: params.skipComponentFailures == 'true',
  547. skipSCFailures: params.skipSCFailures == 'true'
  548. }));
  549. this.setDBProperties({
  550. upgradeVersion: params.label,
  551. upgradeId: data.resources[0].Upgrade.request_id,
  552. upgradeState: 'PENDING',
  553. isDowngrade: !!params.isDowngrade,
  554. upgradeType: upgradeType,
  555. upgradeTypeDisplayName: upgradeTypeDisplayName,
  556. failuresTolerance: Em.Object.create({
  557. skipComponentFailures: params.skipComponentFailures == 'true',
  558. skipSCFailures: params.skipSCFailures == 'true'
  559. })
  560. });
  561. App.set('upgradeState', 'PENDING');
  562. App.clusterStatus.setClusterStatus({
  563. wizardControllerName: this.get('name'),
  564. localdb: App.db.data
  565. });
  566. this.load();
  567. this.openUpgradeDialog();
  568. },
  569. /**
  570. * success callback of updating upgrade options including failures tolerance. etc
  571. * @param {object} data
  572. */
  573. updateOptionsSuccessCallback: function (data, opt, params) {
  574. this.set('failuresTolerance', Em.Object.create({
  575. skipComponentFailures: params.skipComponentFailures == 'true',
  576. skipSCFailures: params.skipSCFailures == 'true'
  577. }));
  578. },
  579. /**
  580. * run upgrade checks and add results to each method object and set selected method
  581. * @param {Em.Object} version
  582. */
  583. runUpgradeMethodChecks: function(version) {
  584. this.get('upgradeMethods').forEach(function (method) {
  585. if (method.get('allowed')) {
  586. this.runPreUpgradeCheckOnly({
  587. value: version.get('repositoryVersion'),
  588. label: version.get('displayName'),
  589. type: method.get('type')
  590. });
  591. }
  592. }, this);
  593. },
  594. /**
  595. * Open upgrade options window: upgrade type and failures tolerance
  596. * @param {boolean} isInUpgradeWizard
  597. * @param {object} version
  598. * @return App.ModalPopup
  599. */
  600. upgradeOptions: function (isInUpgradeWizard, version) {
  601. var self = this;
  602. if (!isInUpgradeWizard) {
  603. this.getSupportedUpgradeTypes(Ember.Object.create({
  604. stackName: App.get('currentStackVersion').split('-')[0],
  605. stackVersion: App.get('currentStackVersion').split('-')[1],
  606. toVersion: version.get('repositoryVersion')
  607. })).done(function(){
  608. self.runUpgradeMethodChecks(version);
  609. });
  610. }
  611. return App.ModalPopup.show({
  612. encodeBody: false,
  613. primary: isInUpgradeWizard ? Em.I18n.t('ok') : Em.I18n.t('common.proceed'),
  614. primaryClass: 'btn-success',
  615. classNames: ['upgrade-options-popup'],
  616. header: Em.I18n.t('admin.stackVersions.version.upgrade.upgradeOptions.header'),
  617. bodyClass: Em.View.extend({
  618. templateName: require('templates/main/admin/stack_upgrade/upgrade_options'),
  619. didInsertElement: function () {
  620. App.tooltip($(".failure-tolerance-tooltip"), {
  621. placement: "top",
  622. title: Em.I18n.t('admin.stackVersions.version.upgrade.upgradeOptions.tolerance.tooltip')
  623. });
  624. App.tooltip($(".not-allowed-by-version"), {
  625. placement: "bottom",
  626. title: Em.I18n.t('admin.stackVersions.version.upgrade.upgradeOptions.notAllowed')
  627. });
  628. Em.run.later(this, function () {
  629. App.tooltip($(".thumbnail.check-failed"), {
  630. placement: "bottom",
  631. title: Em.I18n.t('admin.stackVersions.version.upgrade.upgradeOptions.preCheck.failed.tooltip')
  632. });
  633. }, 1000);
  634. },
  635. upgradeMethods: function () {
  636. self.updateSelectedMethod(isInUpgradeWizard);
  637. return self.get('upgradeMethods');
  638. }.property().volatile(),
  639. isInUpgradeWizard: isInUpgradeWizard,
  640. versionText: isInUpgradeWizard ? '' : Em.I18n.t('admin.stackVersions.version.upgrade.upgradeOptions.bodyMsg.version').format(version.get('displayName')),
  641. selectMethod: function (event) {
  642. if (isInUpgradeWizard || !event.context.get('allowed') || event.context.get('isPrecheckFailed')) return;
  643. var selectedMethod = event.context;
  644. self.updateSelectedMethod(isInUpgradeWizard);
  645. self.get('upgradeMethods').forEach(function (method) {
  646. method.set('selected', false);
  647. });
  648. selectedMethod.set('selected', true);
  649. this.set('parentView.selectedMethod', selectedMethod);
  650. },
  651. openMessage: function (event) {
  652. if (isInUpgradeWizard || !event.context.get('allowed')) return;
  653. var data = event.context.get('precheckResultsData');
  654. var header = Em.I18n.t('popup.clusterCheck.Upgrade.header').format(version.get('displayName')),
  655. failTitle = Em.I18n.t('popup.clusterCheck.Upgrade.fail.title'),
  656. failAlert = new Em.Handlebars.SafeString(Em.I18n.t('popup.clusterCheck.Upgrade.fail.alert')),
  657. warningTitle = Em.I18n.t('popup.clusterCheck.Upgrade.warning.title'),
  658. warningAlert = new Em.Handlebars.SafeString(Em.I18n.t('popup.clusterCheck.Upgrade.warning.alert')),
  659. configsMergeWarning = data.items.findProperty('UpgradeChecks.id', "CONFIG_MERGE"),
  660. configs = [];
  661. if (configsMergeWarning && Em.get(configsMergeWarning, 'UpgradeChecks.status') === 'WARNING') {
  662. data.items = data.items.rejectProperty('UpgradeChecks.id', 'CONFIG_MERGE');
  663. var configsMergeCheckData = Em.get(configsMergeWarning, 'UpgradeChecks.failed_detail');
  664. if (configsMergeCheckData) {
  665. configs = configsMergeCheckData.map(function (item) {
  666. var isDeprecated = Em.isNone(item.new_stack_value),
  667. willBeRemoved = Em.isNone(item.result_value);
  668. return {
  669. type: item.type,
  670. name: item.property,
  671. currentValue: item.current,
  672. recommendedValue: isDeprecated ? Em.I18n.t('popup.clusterCheck.Upgrade.configsMerge.deprecated') : item.new_stack_value,
  673. isDeprecated: isDeprecated,
  674. resultingValue: willBeRemoved ? Em.I18n.t('popup.clusterCheck.Upgrade.configsMerge.willBeRemoved') : item.result_value,
  675. willBeRemoved: willBeRemoved
  676. };
  677. });
  678. }
  679. }
  680. App.showPreUpgradeCheckPopup(data, header, failTitle, failAlert, warningTitle, warningAlert, function () {
  681. self.runPreUpgradeCheckOnly.call(self, {
  682. value: version.get('repositoryVersion'),
  683. label: version.get('displayName'),
  684. type: event.context.get('type')
  685. });
  686. }, configs, version.get('displayName'));
  687. }
  688. }),
  689. /**
  690. * @type {Em.Object}
  691. * @default null
  692. */
  693. selectedMethod: null,
  694. skipComponentFailures: self.get('failuresTolerance.skipComponentFailures'),
  695. skipSCFailures: self.get('failuresTolerance.skipSCFailures'),
  696. disablePrimary: function () {
  697. if (isInUpgradeWizard) return false;
  698. var selectedMethod = self.get('upgradeMethods').findProperty('selected');
  699. return selectedMethod ? selectedMethod.get('isPrecheckFailed') : true;
  700. }.property('selectedMethod'),
  701. onPrimary: function () {
  702. this.hide();
  703. if (isInUpgradeWizard) {
  704. return App.ajax.send({
  705. name: 'admin.upgrade.update.options',
  706. sender: self,
  707. data: {
  708. upgradeId: self.get('upgradeId'),
  709. skipComponentFailures: Boolean(this.get('skipComponentFailures')).toString(),
  710. skipSCFailures: Boolean(this.get('skipSCFailures')).toString()
  711. },
  712. success: 'updateOptionsSuccessCallback'
  713. });
  714. } else {
  715. var upgradeMethod = self.get('upgradeMethods').findProperty('selected');
  716. version.upgradeType = upgradeMethod.get('type');
  717. version.upgradeTypeDisplayName = upgradeMethod.get('displayName');
  718. version.skipComponentFailures = this.get('skipComponentFailures');
  719. version.skipSCFailures = this.get('skipSCFailures');
  720. var fromVersion = self.get('upgradeVersion') || App.RepositoryVersion.find().findProperty('status', 'CURRENT').get('displayName');
  721. var toVersion = version.get('displayName');
  722. var bodyMessage = Em.Object.create({
  723. confirmButton: Em.I18n.t('yes'),
  724. confirmMsg: upgradeMethod.get('type') === 'ROLLING' ?
  725. Em.I18n.t('admin.stackVersions.version.upgrade.upgradeOptions.RU.confirm.msg').format(fromVersion, toVersion) :
  726. Em.I18n.t('admin.stackVersions.version.upgrade.upgradeOptions.EU.confirm.msg').format(fromVersion, toVersion)
  727. });
  728. return App.showConfirmationFeedBackPopup(function (query) {
  729. return self.runPreUpgradeCheck.call(self, version);
  730. }, bodyMessage);
  731. }
  732. }
  733. });
  734. },
  735. /**
  736. * open upgrade options from upgrade wizard
  737. */
  738. openUpgradeOptions: function () {
  739. if (this.get('isDowngrade')) return;
  740. this.upgradeOptions(true, null);
  741. },
  742. /**
  743. * upgrade confirmation popup including upgrade options: upgrade type and failures tolerance
  744. * @param {object} version
  745. * @return App.ModalPopup
  746. */
  747. confirmUpgrade: function (version) {
  748. this.upgradeOptions(false, version);
  749. },
  750. /**
  751. * send request for pre upgrade check only
  752. */
  753. runPreUpgradeCheckOnly: function(data) {
  754. if (App.get('supports.preUpgradeCheck')) {
  755. App.ajax.send({
  756. name: "admin.upgrade.pre_upgrade_check",
  757. sender: this,
  758. data: data,
  759. success: "runPreUpgradeCheckOnlySuccess",
  760. error: "runPreUpgradeCheckError"
  761. });
  762. }
  763. },
  764. /**
  765. * send request to get available upgrade tye names
  766. */
  767. getSupportedUpgradeTypes: function(data) {
  768. return App.ajax.send({
  769. name: "admin.upgrade.get_supported_upgradeTypes",
  770. sender: this,
  771. data: data,
  772. success: "getSupportedUpgradeTypesSuccess",
  773. error: "getSupportedUpgradeTypesError"
  774. });
  775. },
  776. /**
  777. * success callback of <code>getSupportedUpgradeTypes()</code>
  778. * @param data {object}
  779. */
  780. getSupportedUpgradeTypesSuccess: function (data) {
  781. var supportedUpgradeTypes = data.items[0] && data.items[0].CompatibleRepositoryVersions.upgrade_types;
  782. this.get('upgradeMethods').forEach(function (method) {
  783. method.set('allowed', supportedUpgradeTypes && !!supportedUpgradeTypes.contains(method.get('type')));
  784. });
  785. },
  786. /**
  787. * success callback of <code>runPreUpgradeCheckOnly()</code>
  788. * Show a message how many fails/warnings/passed
  789. * on clicking that message a popup window show up
  790. * @param data {object}
  791. * @param opt {object}
  792. * @param params {object}
  793. */
  794. runPreUpgradeCheckOnlySuccess: function (data, opt, params) {
  795. var self = this;
  796. var message = '';
  797. var messageClass = 'GREEN';
  798. var messageIconClass = 'icon-ok';
  799. if (data.items.someProperty('UpgradeChecks.status', 'WARNING')) {
  800. message = message + data.items.filterProperty('UpgradeChecks.status', 'WARNING').length + ' Warning ';
  801. messageClass = 'ORANGE';
  802. messageIconClass = 'icon-warning-sign';
  803. }
  804. if (data.items.someProperty('UpgradeChecks.status', 'FAIL')) {
  805. message = data.items.filterProperty('UpgradeChecks.status', 'FAIL').length + ' Required ' + message;
  806. messageClass = 'RED';
  807. messageIconClass = 'icon-remove';
  808. }
  809. if (!message) {
  810. message = Em.I18n.t('admin.stackVersions.version.upgrade.upgradeOptions.preCheck.allPassed');
  811. }
  812. var method = self.get('upgradeMethods').findProperty('type', params.type);
  813. method.set('precheckResultsMessage', message);
  814. method.set('precheckResultsMessageClass', messageClass);
  815. method.set('isPrecheckFailed', messageClass == 'RED');
  816. method.set('precheckResultsMessageIconClass', messageIconClass);
  817. method.set('precheckResultsData', data);
  818. this.updateSelectedMethod(false);
  819. Em.run.later(this, function () {
  820. // add tooltip for the type with preCheck errors
  821. App.tooltip($(".thumbnail.check-failed"), {
  822. placement: "bottom",
  823. title: Em.I18n.t('admin.stackVersions.version.upgrade.upgradeOptions.preCheck.failed.tooltip')
  824. });
  825. // destroy the tooltip for the type wo preCheck errors
  826. $(".thumbnail").not(".check-failed").not(".not-allowed-by-version").tooltip("destroy");
  827. }, 1000);
  828. },
  829. /**
  830. * In Upgrade Wizard: update which method already been selected on open
  831. * Not in upgrade wizard: de-select the method with pre-check errors
  832. * @param isInUpgradeWizard {boolean}
  833. */
  834. updateSelectedMethod: function(isInUpgradeWizard) {
  835. var self = this;
  836. if (isInUpgradeWizard) {
  837. this.get('upgradeMethods').forEach(function(method){
  838. if (method.get('type') == self.get('upgradeType')) {
  839. method.set('selected', true);
  840. } else {
  841. method.set('selected', false);
  842. }
  843. });
  844. } else {
  845. var ruMethod = this.get('upgradeMethods').findProperty('type', 'ROLLING');
  846. var euMethod = this.get('upgradeMethods').findProperty('type', 'NON_ROLLING');
  847. if (ruMethod && ruMethod.get('isPrecheckFailed')) ruMethod.set('selected', false);
  848. if (euMethod && euMethod.get('isPrecheckFailed')) euMethod.set('selected', false);
  849. }
  850. },
  851. /**
  852. * send request for pre upgrade check
  853. * @param version
  854. */
  855. runPreUpgradeCheck: function(version) {
  856. var params = {
  857. value: version.get('repositoryVersion'),
  858. label: version.get('displayName'),
  859. type: version.get('upgradeType'),
  860. skipComponentFailures: version.get('skipComponentFailures') ? 'true' : 'false',
  861. skipSCFailures: version.get('skipSCFailures') ? 'true' : 'false'
  862. };
  863. if (App.get('supports.preUpgradeCheck')) {
  864. this.set('requestInProgress', true);
  865. App.ajax.send({
  866. name: "admin.upgrade.pre_upgrade_check",
  867. sender: this,
  868. data: params,
  869. success: "runPreUpgradeCheckSuccess",
  870. error: "runPreUpgradeCheckError"
  871. });
  872. } else {
  873. this.upgrade(params);
  874. }
  875. },
  876. /**
  877. * success callback of <code>runPreUpgradeCheckSuccess()</code>
  878. * if there are some fails - it shows popup else run upgrade
  879. * @param data {object}
  880. * @param opt {object}
  881. * @param params {object}
  882. * @returns {App.ModalPopup|undefined}
  883. */
  884. runPreUpgradeCheckSuccess: function (data, opt, params) {
  885. var self = this;
  886. if (data.items.someProperty('UpgradeChecks.status', 'FAIL') || data.items.someProperty('UpgradeChecks.status', 'WARNING')) {
  887. this.set('requestInProgress', false);
  888. var header = Em.I18n.t('popup.clusterCheck.Upgrade.header').format(params.label),
  889. failTitle = Em.I18n.t('popup.clusterCheck.Upgrade.fail.title'),
  890. failAlert = new Em.Handlebars.SafeString(Em.I18n.t('popup.clusterCheck.Upgrade.fail.alert')),
  891. warningTitle = Em.I18n.t('popup.clusterCheck.Upgrade.warning.title'),
  892. warningAlert = new Em.Handlebars.SafeString(Em.I18n.t('popup.clusterCheck.Upgrade.warning.alert')),
  893. configsMergeWarning = data.items.findProperty('UpgradeChecks.id', "CONFIG_MERGE"),
  894. configs = [];
  895. if (configsMergeWarning && Em.get(configsMergeWarning, 'UpgradeChecks.status') === 'WARNING') {
  896. data.items = data.items.rejectProperty('UpgradeChecks.id', 'CONFIG_MERGE');
  897. var configsMergeCheckData = Em.get(configsMergeWarning, 'UpgradeChecks.failed_detail');
  898. if (configsMergeCheckData) {
  899. configs = configsMergeCheckData.map(function (item) {
  900. var isDeprecated = Em.isNone(item.new_stack_value),
  901. willBeRemoved = Em.isNone(item.result_value);
  902. return {
  903. type: item.type,
  904. name: item.property,
  905. currentValue: item.current,
  906. recommendedValue: isDeprecated ? Em.I18n.t('popup.clusterCheck.Upgrade.configsMerge.deprecated') : item.new_stack_value,
  907. isDeprecated: isDeprecated,
  908. resultingValue: willBeRemoved ? Em.I18n.t('popup.clusterCheck.Upgrade.configsMerge.willBeRemoved') : item.result_value,
  909. willBeRemoved: willBeRemoved
  910. };
  911. });
  912. }
  913. }
  914. App.showClusterCheckPopup(data, header, failTitle, failAlert, warningTitle, warningAlert, function () {
  915. self.upgrade(params);
  916. }, configs, params.label);
  917. } else {
  918. this.upgrade(params);
  919. }
  920. },
  921. runPreUpgradeCheckError: function() {
  922. this.set('requestInProgress', false);
  923. },
  924. confirmRetryUpgrade: function (version) {
  925. var self = this;
  926. return App.showConfirmationPopup(
  927. function () {
  928. self.retryUpgrade();
  929. },
  930. Em.I18n.t('admin.stackUpgrade.upgrade.retry.confirm.body').format(version.get('displayName')),
  931. null,
  932. Em.I18n.t('admin.stackUpgrade.dialog.header').format(version.get('upgradeTypeDislayName'), version.get('displayName'))
  933. );
  934. },
  935. confirmRetryDowngrade: function () {
  936. var self = this,
  937. currentVersion = this.get('currentVersion');
  938. return App.showConfirmationPopup(
  939. function() {
  940. self.retryUpgrade();
  941. },
  942. Em.I18n.t('admin.stackUpgrade.downgrade.retry.body').format(currentVersion.repository_name),
  943. null,
  944. Em.I18n.t('admin.stackUpgrade.dialog.downgrade.header').format(currentVersion.repository_name),
  945. Em.I18n.t('admin.stackUpgrade.downgrade.proceed')
  946. );
  947. },
  948. /**
  949. * confirmation popup before install repository version
  950. */
  951. installRepoVersionConfirmation: function (repo) {
  952. var self = this;
  953. return App.showConfirmationPopup(function () {
  954. self.installRepoVersion(repo);
  955. },
  956. Em.I18n.t('admin.stackVersions.version.install.confirm').format(repo.get('displayName'))
  957. );
  958. },
  959. /**
  960. * sends request to install repoVersion to the cluster
  961. * and create clusterStackVersion resourse
  962. * @param {Em.Object} repo
  963. * @return {$.ajax}
  964. * @method installRepoVersion
  965. */
  966. installRepoVersion: function (repo) {
  967. this.set('requestInProgress', true);
  968. var data = {
  969. ClusterStackVersions: {
  970. stack: repo.get('stackVersionType'),
  971. version: repo.get('stackVersionNumber'),
  972. repository_version: repo.get('repositoryVersion')
  973. },
  974. id: repo.get('id')
  975. };
  976. return App.ajax.send({
  977. name: 'admin.stack_version.install.repo_version',
  978. sender: this,
  979. data: data,
  980. success: 'installRepoVersionSuccess',
  981. callback: function() {
  982. this.sender.set('requestInProgress', false);
  983. }
  984. });
  985. },
  986. /**
  987. * transform repo data into json for
  988. * saving changes to repository version
  989. * @param {Em.Object} repo
  990. * @returns {{operating_systems: Array}}
  991. */
  992. prepareRepoForSaving: function(repo) {
  993. var repoVersion = { "operating_systems": [] };
  994. repo.get('operatingSystems').forEach(function (os, k) {
  995. repoVersion.operating_systems.push({
  996. "OperatingSystems": {
  997. "os_type": os.get("osType")
  998. },
  999. "repositories": []
  1000. });
  1001. os.get('repositories').forEach(function (repository) {
  1002. repoVersion.operating_systems[k].repositories.push({
  1003. "Repositories": {
  1004. "base_url": repository.get('baseUrl'),
  1005. "repo_id": repository.get('repoId'),
  1006. "repo_name": repository.get('repoName')
  1007. }
  1008. });
  1009. });
  1010. });
  1011. return repoVersion;
  1012. },
  1013. /**
  1014. * Return stack version for the repo object
  1015. * @param {Em.Object} repo
  1016. * */
  1017. getStackVersionNumber: function(repo){
  1018. var stackVersionNumber = repo.get('stackVersion');
  1019. if(null == stackVersionNumber)
  1020. stackVersionNumber = App.get('currentStackVersion');
  1021. return stackVersionNumber;
  1022. },
  1023. /**
  1024. * perform validation if <code>skip<code> is false and run save if
  1025. * validation successfull or run save without validation is <code>skip<code> is true
  1026. * @param {Em.Object} repo
  1027. * @param {boolean} skip
  1028. * @returns {$.Deferred}
  1029. */
  1030. saveRepoOS: function (repo, skip) {
  1031. var self = this;
  1032. var deferred = $.Deferred();
  1033. this.validateRepoVersions(repo, skip).done(function(data) {
  1034. if (data.length > 0) {
  1035. deferred.resolve(data);
  1036. } else {
  1037. var repoVersion = self.prepareRepoForSaving(repo);
  1038. var stackVersionNumber = self.getStackVersionNumber(repo);
  1039. App.ajax.send({
  1040. name: 'admin.stack_versions.edit.repo',
  1041. sender: this,
  1042. data: {
  1043. stackName: App.get('currentStackName'),
  1044. stackVersion: stackVersionNumber,
  1045. repoVersionId: repo.get('repoVersionId'),
  1046. repoVersion: repoVersion
  1047. }
  1048. }).success(function() {
  1049. deferred.resolve([]);
  1050. });
  1051. }
  1052. });
  1053. return deferred.promise();
  1054. },
  1055. /**
  1056. * send request for validation for each repository
  1057. * @param {Em.Object} repo
  1058. * @param {boolean} skip
  1059. * @returns {*}
  1060. */
  1061. validateRepoVersions: function(repo, skip) {
  1062. var deferred = $.Deferred(),
  1063. totalCalls = 0,
  1064. invalidUrls = [];
  1065. if (skip) {
  1066. deferred.resolve(invalidUrls);
  1067. } else {
  1068. var stackVersionNumber = this.getStackVersionNumber(repo);
  1069. repo.get('operatingSystems').forEach(function (os) {
  1070. if (os.get('isSelected')) {
  1071. os.get('repositories').forEach(function (repo) {
  1072. totalCalls++;
  1073. App.ajax.send({
  1074. name: 'admin.stack_versions.validate.repo',
  1075. sender: this,
  1076. data: {
  1077. repo: repo,
  1078. repoId: repo.get('repoId'),
  1079. baseUrl: repo.get('baseUrl'),
  1080. osType: os.get('osType'),
  1081. stackName: App.get('currentStackName'),
  1082. stackVersion: stackVersionNumber
  1083. }
  1084. })
  1085. .success(function () {
  1086. totalCalls--;
  1087. if (totalCalls === 0) deferred.resolve(invalidUrls);
  1088. })
  1089. .error(function () {
  1090. repo.set('hasError', true);
  1091. invalidUrls.push(repo);
  1092. totalCalls--;
  1093. if (totalCalls === 0) deferred.resolve(invalidUrls);
  1094. });
  1095. });
  1096. } else {
  1097. return deferred.resolve(invalidUrls);
  1098. }
  1099. });
  1100. }
  1101. return deferred.promise();
  1102. },
  1103. /**
  1104. * success callback for <code>installRepoVersion()<code>
  1105. * saves request id to the db
  1106. * @param data
  1107. * @param opt
  1108. * @param params
  1109. * @method installStackVersionSuccess
  1110. */
  1111. installRepoVersionSuccess: function (data, opt, params) {
  1112. var version = App.RepositoryVersion.find(params.id);
  1113. App.db.set('repoVersionInstall', 'id', [data.Requests.id]);
  1114. App.clusterStatus.setClusterStatus({
  1115. wizardControllerName: this.get('name'),
  1116. localdb: App.db.data
  1117. });
  1118. version.set('defaultStatus', 'INSTALLING');
  1119. if (version.get('stackVersion')) {
  1120. version.set('stackVersion.state', 'INSTALLING');
  1121. }
  1122. },
  1123. /**
  1124. * opens a popup with installations state per host
  1125. * @param {Em.Object} version
  1126. * @method showProgressPopup
  1127. */
  1128. showProgressPopup: function(version) {
  1129. var popupTitle = Em.I18n.t('admin.stackVersions.details.install.hosts.popup.title').format(version.get('displayName'));
  1130. var requestIds = App.get('testMode') ? [1] : App.db.get('repoVersionInstall', 'id');
  1131. var hostProgressPopupController = App.router.get('highAvailabilityProgressPopupController');
  1132. hostProgressPopupController.initPopup(popupTitle, requestIds, this);
  1133. },
  1134. /**
  1135. * reset upgradeState to INIT when upgrade is COMPLETED
  1136. * and clean auxiliary data
  1137. */
  1138. finish: function () {
  1139. if (App.get('upgradeState') === 'COMPLETED') {
  1140. var upgradeVersion = this.get('upgradeVersion') && this.get('upgradeVersion').match(/[a-zA-Z]+\-\d+\.\d+/);
  1141. this.setDBProperties({
  1142. upgradeId: undefined,
  1143. upgradeState: 'INIT',
  1144. upgradeVersion: undefined,
  1145. currentVersion: undefined,
  1146. upgradeTypeDisplayName: undefined,
  1147. upgradeType: undefined,
  1148. failuresTolerance: undefined,
  1149. isDowngrade: undefined,
  1150. downgradeAllowed: undefined
  1151. });
  1152. App.clusterStatus.setClusterStatus({
  1153. localdb: App.db.data
  1154. });
  1155. if (upgradeVersion && upgradeVersion[0]) {
  1156. App.set('currentStackVersion', upgradeVersion[0]);
  1157. }
  1158. App.set('upgradeState', 'INIT');
  1159. }
  1160. }.observes('App.upgradeState'),
  1161. /**
  1162. * Check <code>App.upgradeState</code> for HOLDING
  1163. * If it is, send request to check if current item is Finalize
  1164. * @method updateFinalize
  1165. */
  1166. updateFinalize: function () {
  1167. var upgradeState = App.get('upgradeState');
  1168. if (upgradeState === 'HOLDING') {
  1169. return App.ajax.send({
  1170. name: 'admin.upgrade.finalizeContext',
  1171. sender: this,
  1172. success: 'updateFinalizeSuccessCallback',
  1173. error: 'updateFinalizeErrorCallback'
  1174. })
  1175. }
  1176. else {
  1177. this.set('isFinalizeItem', false);
  1178. }
  1179. }.observes('App.upgradeState'),
  1180. /**
  1181. *
  1182. * @param {object|null} data
  1183. * @method updateFinalizeSuccessCallback
  1184. */
  1185. updateFinalizeSuccessCallback: function (data) {
  1186. var context = data ? Em.get(data, 'items.firstObject.upgrade_groups.firstObject.upgrade_items.firstObject.UpgradeItem.context') : '';
  1187. this.set('isFinalizeItem', context === this.get('finalizeContext'));
  1188. },
  1189. updateFinalizeErrorCallback: function() {
  1190. this.set('isFinalizeItem', false);
  1191. },
  1192. /**
  1193. * show dialog with tasks of upgrade
  1194. * @return {App.ModalPopup}
  1195. */
  1196. openUpgradeDialog: function () {
  1197. App.router.transitionTo('admin.stackUpgrade');
  1198. },
  1199. /**
  1200. * returns url to get data for repoVersion or clusterStackVersion
  1201. * @param {Boolean} stack true if load clusterStackVersion
  1202. * @param {Boolean} fullLoad true if load all data
  1203. * @returns {String}
  1204. * @method getUrl
  1205. */
  1206. getUrl: function(stack, fullLoad) {
  1207. if (App.get('testMode')) {
  1208. return stack ? this.get('mockStackUrl') : this.get('mockRepoUrl')
  1209. } else {
  1210. if (fullLoad) {
  1211. return stack ? this.get('realStackUrl') : this.get('realRepoUrl');
  1212. } else {
  1213. return this.get('realUpdateUrl');
  1214. }
  1215. }
  1216. },
  1217. /**
  1218. * get stack versions from server and push it to model
  1219. * @return {*}
  1220. * @method loadStackVersionsToModel
  1221. */
  1222. loadStackVersionsToModel: function (fullLoad) {
  1223. var dfd = $.Deferred();
  1224. App.HttpClient.get(this.getUrl(true, fullLoad), App.stackVersionMapper, {
  1225. complete: function () {
  1226. dfd.resolve();
  1227. }
  1228. });
  1229. return dfd.promise();
  1230. },
  1231. /**
  1232. * get repo versions from server and push it to model
  1233. * @return {*}
  1234. * @params {Boolean} isUpdate - if true loads part of data that need to be updated
  1235. * @method loadRepoVersionsToModel()
  1236. */
  1237. loadRepoVersionsToModel: function () {
  1238. var dfd = $.Deferred();
  1239. App.HttpClient.get(this.getUrl(false, true), App.repoVersionMapper, {
  1240. complete: function () {
  1241. dfd.resolve();
  1242. }
  1243. });
  1244. return dfd.promise();
  1245. },
  1246. /**
  1247. * set status to Upgrade item
  1248. * @param item
  1249. * @param status
  1250. */
  1251. setUpgradeItemStatus: function(item, status) {
  1252. this.set('requestInProgress', true);
  1253. return App.ajax.send({
  1254. name: 'admin.upgrade.upgradeItem.setState',
  1255. sender: this,
  1256. data: {
  1257. upgradeId: item.get('request_id'),
  1258. itemId: item.get('stage_id'),
  1259. groupId: item.get('group_id'),
  1260. status: status
  1261. },
  1262. callback: function() {
  1263. this.sender.set('requestInProgress', false);
  1264. }
  1265. }).done(function () {
  1266. item.set('status', status);
  1267. });
  1268. },
  1269. currentVersionObserver: function () {
  1270. var versionNumber = this.get('currentVersion.repository_version');
  1271. var currentVersionObject = App.RepositoryVersion.find().findProperty('status', 'CURRENT');
  1272. var versionName = currentVersionObject && currentVersionObject.get('stackVersionType');
  1273. App.set('isStormMetricsSupported', versionName != 'HDP' || stringUtils.compareVersions(versionNumber, '2.2.2') > -1 || !versionNumber);
  1274. }.observes('currentVersion.repository_version'),
  1275. /**
  1276. * get the installed repositories of HDP from server
  1277. */
  1278. loadRepositories: function () {
  1279. if (App.router.get('clusterController.isLoaded')) {
  1280. var nameVersionCombo = App.get('currentStackVersion');
  1281. var stackName = nameVersionCombo.split('-')[0];
  1282. var stackVersion = nameVersionCombo.split('-')[1];
  1283. App.ajax.send({
  1284. name: 'cluster.load_repositories',
  1285. sender: this,
  1286. data: {
  1287. stackName: stackName,
  1288. stackVersion: stackVersion
  1289. },
  1290. success: 'loadRepositoriesSuccessCallback',
  1291. error: 'loadRepositoriesErrorCallback'
  1292. });
  1293. }
  1294. }.observes('App.router.clusterController.isLoaded'),
  1295. loadRepositoriesSuccessCallback: function (data) {
  1296. var allRepos = [];
  1297. data.items.forEach(function (os) {
  1298. os.repositories.forEach(function (repository) {
  1299. var osType = repository.Repositories.os_type;
  1300. var repo = Em.Object.create({
  1301. baseUrl: repository.Repositories.base_url,
  1302. osType: osType,
  1303. repoId: repository.Repositories.repo_id,
  1304. repoName : repository.Repositories.repo_name,
  1305. stackName : repository.Repositories.stack_name,
  1306. stackVersion : repository.Repositories.stack_version,
  1307. isFirst: false
  1308. });
  1309. var group = allRepos.findProperty('name', osType);
  1310. if (!group) {
  1311. group = {
  1312. name: osType,
  1313. repositories: []
  1314. };
  1315. repo.set('isFirst', true);
  1316. allRepos.push(group);
  1317. }
  1318. group.repositories.push(repo);
  1319. });
  1320. }, this);
  1321. allRepos.stackVersion = App.get('currentStackVersionNumber');
  1322. this.set('allRepos', allRepos);
  1323. },
  1324. loadRepositoriesErrorCallback: function (request, ajaxOptions, error) {
  1325. },
  1326. /**
  1327. * @returns {$.ajax}
  1328. */
  1329. suspendUpgrade: function () {
  1330. var self = this;
  1331. return this.abortUpgrade().done(function () {
  1332. App.set('upgradeState', 'ABORTED');
  1333. self.set('isSuspended', true);
  1334. self.setDBProperty('upgradeState', 'ABORTED');
  1335. self.setDBProperty('isSuspended', true);
  1336. App.clusterStatus.setClusterStatus({
  1337. wizardControllerName: self.get('name'),
  1338. localdb: App.db.data
  1339. });
  1340. });
  1341. },
  1342. /**
  1343. * @returns {$.ajax}
  1344. */
  1345. resumeUpgrade: function() {
  1346. var self = this;
  1347. this.retryUpgrade().done(function () {
  1348. App.set('upgradeState', 'PENDING');
  1349. App.propertyDidChange('upgradeAborted');
  1350. self.set('isSuspended', false);
  1351. self.setDBProperty('upgradeState', 'PENDING');
  1352. self.setDBProperty('isSuspended', false);
  1353. App.clusterStatus.setClusterStatus({
  1354. wizardControllerName: self.get('name'),
  1355. localdb: App.db.data
  1356. });
  1357. });
  1358. },
  1359. /**
  1360. * restore last Upgrade data
  1361. * @param {object} lastUpgradeData
  1362. */
  1363. restoreLastUpgrade: function(lastUpgradeData) {
  1364. var self = this;
  1365. var upgradeType = this.get('upgradeMethods').findProperty('type', lastUpgradeData.Upgrade.upgrade_type);
  1366. this.setDBProperties({
  1367. upgradeId: lastUpgradeData.Upgrade.request_id,
  1368. isDowngrade: lastUpgradeData.Upgrade.direction === 'DOWNGRADE',
  1369. upgradeState: lastUpgradeData.Upgrade.request_status,
  1370. upgradeType: lastUpgradeData.Upgrade.upgrade_type,
  1371. downgradeAllowed: lastUpgradeData.Upgrade.downgrade_allowed,
  1372. upgradeTypeDisplayName: upgradeType.get('displayName'),
  1373. failuresTolerance: Em.Object.create({
  1374. skipComponentFailures: lastUpgradeData.Upgrade.skip_failures,
  1375. skipSCFailures: lastUpgradeData.Upgrade.skip_service_check_failures
  1376. })
  1377. });
  1378. this.loadRepoVersionsToModel().done(function () {
  1379. var toVersion = App.RepositoryVersion.find().findProperty('repositoryVersion', lastUpgradeData.Upgrade.to_version);
  1380. self.setDBProperty('upgradeVersion', toVersion && toVersion.get('displayName'));
  1381. self.initDBProperties();
  1382. self.loadUpgradeData(true);
  1383. });
  1384. },
  1385. /**
  1386. * Build table from configs list and open new window to show this table
  1387. * @param configs
  1388. */
  1389. openConfigsInNewWindow: function (configs) {
  1390. var newWindow;
  1391. var output = '';
  1392. output += '<table style="text-align: left;"><thead><tr>' +
  1393. '<th>' + Em.I18n.t('popup.clusterCheck.Upgrade.configsMerge.configType') + '</th>' +
  1394. '<th>' + Em.I18n.t('popup.clusterCheck.Upgrade.configsMerge.propertyName') + '</th>' +
  1395. '<th>' + Em.I18n.t('popup.clusterCheck.Upgrade.configsMerge.currentValue') + '</th>' +
  1396. '<th>' + Em.I18n.t('popup.clusterCheck.Upgrade.configsMerge.recommendedValue') + '</th>' +
  1397. '<th>' + Em.I18n.t('popup.clusterCheck.Upgrade.configsMerge.resultingValue') + '</th>' +
  1398. '</tr></thead><tbody>';
  1399. configs.context.forEach(function (config) {
  1400. output += '<tr>' +
  1401. '<td>' + config.type + '</td>' +
  1402. '<td>' + config.name + '</td>' +
  1403. '<td>' + config.currentValue + '</td>' +
  1404. '<td>' + config.recommendedValue + '</td>' +
  1405. '<td>' + config.resultingValue + '</td>' +
  1406. '</tr>';
  1407. });
  1408. output += '</tbody></table>';
  1409. newWindow = window.open();
  1410. newWindow.document.write(output);
  1411. newWindow.focus();
  1412. }
  1413. });