stack_and_upgrade_controller.js 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925
  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 {boolean}
  43. * @default false
  44. */
  45. isDowngrade: false,
  46. /**
  47. * version that currently applied to server
  48. * should be plain object, because stored to localStorage
  49. * @type {object|null}
  50. */
  51. currentVersion: null,
  52. /**
  53. * versions to which cluster could be upgraded
  54. * @type {Array}
  55. */
  56. targetVersions: [],
  57. /**
  58. * @type {boolean} true if some request that should disable actions is in progress
  59. */
  60. requestInProgress: false,
  61. /**
  62. * @type {boolean} true while no updated upgrade info is loaded after retry
  63. */
  64. isRetryPending: false,
  65. /**
  66. * properties that stored to localStorage to resume wizard progress
  67. */
  68. wizardStorageProperties: ['upgradeId', 'upgradeVersion', 'currentVersion', 'isDowngrade'],
  69. /**
  70. * mutable properties of Upgrade Task
  71. * @type {Array}
  72. */
  73. taskDetailsProperties: ['status', 'stdout', 'stderr', 'error_log', 'host_name', 'output_log'],
  74. isLoadUpgradeDataPending: false,
  75. /**
  76. * path to the mock json
  77. * @type {String}
  78. */
  79. mockRepoUrl: '/data/stack_versions/repo_versions_all.json',
  80. /**
  81. * api to get RepoVersions
  82. * @type {String}
  83. */
  84. realRepoUrl: function () {
  85. return App.get('apiPrefix') + App.get('stackVersionURL') +
  86. '/compatible_repository_versions?fields=*,operating_systems/*,operating_systems/repositories/*';
  87. }.property('App.stackVersionURL'),
  88. /**
  89. * path to the mock json
  90. * @type {String}
  91. */
  92. mockStackUrl: '/data/stack_versions/stack_version_all.json',
  93. /**
  94. * api to get ClusterStackVersions with repository_versions (use to init data load)
  95. * @type {String}
  96. */
  97. realStackUrl: function () {
  98. return App.get('apiPrefix') + '/clusters/' + App.get('clusterName') +
  99. '/stack_versions?fields=*,repository_versions/*,repository_versions/operating_systems/repositories/*';
  100. }.property('App.clusterName'),
  101. /**
  102. * api to get ClusterStackVersions without repository_versions (use to update data)
  103. * @type {String}
  104. */
  105. realUpdateUrl: function () {
  106. return App.get('apiPrefix') + '/clusters/' + App.get('clusterName') + '/stack_versions?fields=ClusterStackVersions/*';
  107. }.property('App.clusterName'),
  108. /**
  109. * Determines if list of services with checks that failed and were skipped by user during the upgrade is loaded
  110. * @type {boolean}
  111. */
  112. areSkippedServiceChecksLoaded: false,
  113. /**
  114. * List of services with checks that failed and were skipped by user during the upgrade
  115. * @type {array}
  116. */
  117. skippedServiceChecks: [],
  118. init: function () {
  119. this.initDBProperties();
  120. },
  121. /**
  122. * restore data from localStorage
  123. */
  124. initDBProperties: function () {
  125. this.get('wizardStorageProperties').forEach(function (property) {
  126. if (this.getDBProperty(property)) {
  127. this.set(property, this.getDBProperty(property));
  128. }
  129. }, this);
  130. },
  131. /**
  132. * load all data:
  133. * - upgrade data
  134. * - stack versions
  135. * - repo versions
  136. */
  137. load: function () {
  138. var dfd = $.Deferred();
  139. var self = this;
  140. this.loadUpgradeData(true).done(function() {
  141. self.loadStackVersionsToModel(true).done(function () {
  142. self.loadRepoVersionsToModel().done(function() {
  143. var currentVersion = App.StackVersion.find().findProperty('state', 'CURRENT');
  144. if (currentVersion) {
  145. self.set('currentVersion', {
  146. repository_version: currentVersion.get('repositoryVersion.repositoryVersion'),
  147. repository_name: currentVersion.get('repositoryVersion.displayName')
  148. });
  149. }
  150. dfd.resolve();
  151. });
  152. });
  153. });
  154. return dfd.promise();
  155. },
  156. /**
  157. * load upgrade tasks by upgrade id
  158. * @return {$.Deferred}
  159. * @param {boolean} onlyState
  160. */
  161. loadUpgradeData: function (onlyState) {
  162. var upgradeId = this.get('upgradeId'),
  163. deferred = $.Deferred(),
  164. self = this;
  165. if (Em.isNone(upgradeId)) {
  166. deferred.resolve();
  167. console.log('Upgrade in INIT state');
  168. } else {
  169. this.set('isLoadUpgradeDataPending', true);
  170. App.ajax.send({
  171. name: (onlyState) ? 'admin.upgrade.state' : 'admin.upgrade.data',
  172. sender: this,
  173. data: {
  174. id: upgradeId
  175. },
  176. success: 'loadUpgradeDataSuccessCallback'
  177. }).then(deferred.resolve).complete(function () {
  178. self.set('isLoadUpgradeDataPending', false);
  179. });
  180. }
  181. return deferred.promise();
  182. },
  183. /**
  184. * parse and push upgrade tasks to controller
  185. * @param data
  186. */
  187. loadUpgradeDataSuccessCallback: function (data) {
  188. if (Em.isNone(data)) return;
  189. App.set('upgradeState', data.Upgrade.request_status);
  190. this.setDBProperty('upgradeState', data.Upgrade.request_status);
  191. if (data.upgrade_groups) {
  192. this.updateUpgradeData(data);
  193. }
  194. if (this.get('isRetryPending') && data.Upgrade.request_status != 'ABORTED') {
  195. this.setProperties({
  196. requestInProgress: false,
  197. isRetryPending: false
  198. });
  199. }
  200. },
  201. /**
  202. * update data of Upgrade
  203. * @param {object} newData
  204. */
  205. updateUpgradeData: function (newData) {
  206. var oldData = this.get('upgradeData'),
  207. groupsMap = {},
  208. itemsMap = {};
  209. if (Em.isNone(oldData) || (newData.upgrade_groups.length !== oldData.upgradeGroups.length)) {
  210. this.initUpgradeData(newData);
  211. } else {
  212. //create entities maps
  213. newData.upgrade_groups.forEach(function (newGroup) {
  214. groupsMap[newGroup.UpgradeGroup.group_id] = newGroup.UpgradeGroup;
  215. newGroup.upgrade_items.forEach(function (item) {
  216. itemsMap[item.UpgradeItem.stage_id] = item.UpgradeItem;
  217. })
  218. });
  219. //update existed entities with new data
  220. oldData.upgradeGroups.forEach(function (oldGroup) {
  221. oldGroup.set('status', groupsMap[oldGroup.get('group_id')].status);
  222. oldGroup.set('progress_percent', groupsMap[oldGroup.get('group_id')].progress_percent);
  223. oldGroup.set('completed_task_count', groupsMap[oldGroup.get('group_id')].completed_task_count);
  224. oldGroup.upgradeItems.forEach(function (item) {
  225. item.set('status', itemsMap[item.get('stage_id')].status);
  226. item.set('progress_percent', itemsMap[item.get('stage_id')].progress_percent);
  227. })
  228. });
  229. oldData.set('Upgrade', newData.Upgrade);
  230. }
  231. },
  232. /**
  233. * change structure of Upgrade
  234. * In order to maintain nested views in template object should have direct link to its properties, for example
  235. * item.UpgradeItem.<properties> -> item.<properties>
  236. * @param {object} newData
  237. */
  238. initUpgradeData: function (newData) {
  239. var upgradeGroups = [];
  240. //wrap all entities into App.upgradeEntity
  241. newData.upgrade_groups.forEach(function (newGroup) {
  242. var oldGroup = App.upgradeEntity.create({type: 'GROUP'}, newGroup.UpgradeGroup);
  243. var upgradeItems = [];
  244. newGroup.upgrade_items.forEach(function (item) {
  245. var oldItem = App.upgradeEntity.create({type: 'ITEM'}, item.UpgradeItem);
  246. oldItem.set('tasks', []);
  247. upgradeItems.pushObject(oldItem);
  248. });
  249. upgradeItems.reverse();
  250. oldGroup.set('upgradeItems', upgradeItems);
  251. upgradeGroups.pushObject(oldGroup);
  252. });
  253. upgradeGroups.reverse();
  254. this.set('upgradeData', Em.Object.create({
  255. upgradeGroups: upgradeGroups,
  256. Upgrade: newData.Upgrade
  257. }));
  258. },
  259. /**
  260. * request Upgrade Item and its tasks from server
  261. * @return {$.ajax}
  262. */
  263. getUpgradeItem: function (item) {
  264. return App.ajax.send({
  265. name: 'admin.upgrade.upgrade_item',
  266. sender: this,
  267. data: {
  268. upgradeId: item.get('request_id'),
  269. groupId: item.get('group_id'),
  270. stageId: item.get('stage_id')
  271. },
  272. success: 'getUpgradeItemSuccessCallback'
  273. });
  274. },
  275. /**
  276. * success callback of <code>getTasks</code>
  277. * @param {object} data
  278. */
  279. getUpgradeItemSuccessCallback: function (data) {
  280. this.get('upgradeData.upgradeGroups').forEach(function (group) {
  281. if (group.get('group_id') === data.UpgradeItem.group_id) {
  282. group.get('upgradeItems').forEach(function (item) {
  283. if (item.get('stage_id') === data.UpgradeItem.stage_id) {
  284. if (item.get('tasks.length')) {
  285. item.set('isTasksLoaded', true);
  286. data.tasks.forEach(function (task) {
  287. var currentTask = item.get('tasks').findProperty('id', task.Tasks.id);
  288. this.get('taskDetailsProperties').forEach(function (property) {
  289. currentTask.set(property, task.Tasks[property]);
  290. }, this);
  291. }, this);
  292. } else {
  293. var tasks = [];
  294. data.tasks.forEach(function (task) {
  295. tasks.pushObject(App.upgradeEntity.create({type: 'TASK'}, task.Tasks));
  296. });
  297. item.set('tasks', tasks);
  298. }
  299. item.set('isTasksLoaded', true);
  300. }
  301. }, this);
  302. }
  303. }, this);
  304. },
  305. /**
  306. * downgrade confirmation popup
  307. * @param {object} event
  308. */
  309. confirmDowngrade: function (event) {
  310. var self = this;
  311. var currentVersion = this.get('currentVersion');
  312. return App.showConfirmationPopup(
  313. function() {
  314. self.downgrade.call(self, currentVersion, event);
  315. },
  316. Em.I18n.t('admin.stackUpgrade.downgrade.body').format(currentVersion.repository_name),
  317. null,
  318. Em.I18n.t('admin.stackUpgrade.dialog.downgrade.header').format(currentVersion.repository_name),
  319. Em.I18n.t('admin.stackUpgrade.downgrade.proceed')
  320. );
  321. },
  322. /**
  323. * make call to start downgrade process
  324. * @param {object} currentVersion
  325. * @param {object} event
  326. */
  327. downgrade: function (currentVersion, event) {
  328. this.set('requestInProgress', true);
  329. this.abortUpgrade();
  330. App.ajax.send({
  331. name: 'admin.downgrade.start',
  332. sender: this,
  333. data: {
  334. from: App.RepositoryVersion.find().findProperty('displayName', this.get('upgradeVersion')).get('repositoryVersion'),
  335. value: currentVersion.repository_version,
  336. label: currentVersion.repository_name,
  337. isDowngrade: true
  338. },
  339. success: 'upgradeSuccessCallback',
  340. callback: function() {
  341. this.sender.set('requestInProgress', false);
  342. }
  343. });
  344. },
  345. /**
  346. * abort upgrade (in order to start Downgrade)
  347. */
  348. abortUpgrade: function () {
  349. return App.ajax.send({
  350. name: 'admin.upgrade.abort',
  351. sender: this,
  352. data: {
  353. upgradeId: this.get('upgradeId')
  354. }
  355. });
  356. },
  357. retryUpgrade: function () {
  358. this.setProperties({
  359. requestInProgress: true,
  360. isRetryPending: true
  361. });
  362. return App.ajax.send({
  363. name: 'admin.upgrade.retry',
  364. sender: this,
  365. data: {
  366. upgradeId: this.get('upgradeId')
  367. }
  368. });
  369. },
  370. /**
  371. * make call to start upgrade process and show popup with current progress
  372. * @param {object} version
  373. */
  374. upgrade: function (version) {
  375. this.set('requestInProgress', true);
  376. App.ajax.send({
  377. name: 'admin.upgrade.start',
  378. sender: this,
  379. data: version,
  380. success: 'upgradeSuccessCallback',
  381. callback: function() {
  382. this.sender.set('requestInProgress', false);
  383. }
  384. });
  385. this.setDBProperty('currentVersion', this.get('currentVersion'));
  386. },
  387. /**
  388. * success callback of <code>upgrade()</code>
  389. * @param {object} data
  390. */
  391. upgradeSuccessCallback: function (data, opt, params) {
  392. this.set('upgradeData', null);
  393. this.set('upgradeId', data.resources[0].Upgrade.request_id);
  394. this.set('upgradeVersion', params.label);
  395. this.set('isDowngrade', !!params.isDowngrade);
  396. this.setDBProperty('upgradeVersion', params.label);
  397. this.setDBProperty('upgradeId', data.resources[0].Upgrade.request_id);
  398. this.setDBProperty('upgradeState', 'PENDING');
  399. this.setDBProperty('isDowngrade', !!params.isDowngrade);
  400. App.set('upgradeState', 'PENDING');
  401. App.clusterStatus.setClusterStatus({
  402. wizardControllerName: this.get('name'),
  403. localdb: App.db.data
  404. });
  405. this.load();
  406. this.openUpgradeDialog();
  407. },
  408. /**
  409. * upgrade confirmation popup
  410. * @param {object} version
  411. * @return App.ModalPopup
  412. */
  413. confirmUpgrade: function (version) {
  414. var self = this;
  415. return App.showConfirmationPopup(
  416. function () {
  417. self.runPreUpgradeCheck.call(self, version);
  418. },
  419. Em.I18n.t('admin.stackUpgrade.upgrade.confirm.body').format(version.get('displayName')),
  420. null,
  421. Em.I18n.t('admin.stackUpgrade.dialog.header').format(version.get('displayName'))
  422. );
  423. },
  424. /**
  425. * send request for pre upgrade check
  426. * @param version
  427. */
  428. runPreUpgradeCheck: function(version) {
  429. var params = {
  430. value: version.get('repositoryVersion'),
  431. label: version.get('displayName')
  432. };
  433. if (App.get('supports.preUpgradeCheck')) {
  434. this.set('requestInProgress', true);
  435. App.ajax.send({
  436. name: "admin.rolling_upgrade.pre_upgrade_check",
  437. sender: this,
  438. data: params,
  439. success: "runPreUpgradeCheckSuccess",
  440. error: "runPreUpgradeCheckError"
  441. });
  442. } else {
  443. this.upgrade(params);
  444. }
  445. },
  446. /**
  447. * success callback of <code>runPreUpgradeCheckSuccess()</code>
  448. * if there are some fails - it shows popup else run upgrade
  449. * @param data {object}
  450. * @param opt {object}
  451. * @param params {object}
  452. * @returns {App.ModalPopup|undefined}
  453. */
  454. runPreUpgradeCheckSuccess: function (data, opt, params) {
  455. var self = this;
  456. if (data.items.someProperty('UpgradeChecks.status', 'FAIL') || data.items.someProperty('UpgradeChecks.status', 'WARNING')) {
  457. this.set('requestInProgress', false);
  458. var header = Em.I18n.t('popup.clusterCheck.Upgrade.header').format(params.label),
  459. failTitle = Em.I18n.t('popup.clusterCheck.Upgrade.fail.title'),
  460. failAlert = new Em.Handlebars.SafeString(Em.I18n.t('popup.clusterCheck.Upgrade.fail.alert')),
  461. warningTitle = Em.I18n.t('popup.clusterCheck.Upgrade.warning.title'),
  462. warningAlert = new Em.Handlebars.SafeString(Em.I18n.t('popup.clusterCheck.Upgrade.warning.alert')),
  463. configsMergeWarning = data.items.findProperty('UpgradeChecks.id', "CONFIG_MERGE"),
  464. configs = [];
  465. if (configsMergeWarning && Em.get(configsMergeWarning, 'UpgradeChecks.status') === 'WARNING') {
  466. data.items = data.items.rejectProperty('UpgradeChecks.id', 'CONFIG_MERGE');
  467. var configsMergeCheckData = Em.get(configsMergeWarning, 'UpgradeChecks.failed_detail');
  468. if (configsMergeCheckData) {
  469. configs = configsMergeCheckData.map(function (item) {
  470. var isDeprecated = Em.isNone(item.new_stack_value),
  471. willBeRemoved = Em.isNone(item.result_value);
  472. return {
  473. type: item.type,
  474. name: item.property,
  475. currentValue: item.current,
  476. recommendedValue: isDeprecated ? Em.I18n.t('popup.clusterCheck.Upgrade.configsMerge.deprecated') : item.new_stack_value,
  477. isDeprecated: isDeprecated,
  478. resultingValue: willBeRemoved ? Em.I18n.t('popup.clusterCheck.Upgrade.configsMerge.willBeRemoved') : item.result_value,
  479. willBeRemoved: willBeRemoved
  480. };
  481. });
  482. }
  483. }
  484. App.showClusterCheckPopup(data, header, failTitle, failAlert, warningTitle, warningAlert, function () {
  485. self.upgrade(params);
  486. }, configs, params.label);
  487. } else {
  488. this.upgrade(params);
  489. }
  490. },
  491. runPreUpgradeCheckError: function() {
  492. this.set('requestInProgress', false);
  493. },
  494. confirmRetryUpgrade: function (version) {
  495. var self = this;
  496. return App.showConfirmationPopup(
  497. function () {
  498. self.retryUpgrade();
  499. },
  500. Em.I18n.t('admin.stackUpgrade.upgrade.retry.confirm.body').format(version.get('displayName')),
  501. null,
  502. Em.I18n.t('admin.stackUpgrade.dialog.header').format(version.get('displayName'))
  503. );
  504. },
  505. confirmRetryDowngrade: function () {
  506. var self = this,
  507. currentVersion = this.get('currentVersion');
  508. return App.showConfirmationPopup(
  509. function() {
  510. self.retryUpgrade();
  511. },
  512. Em.I18n.t('admin.stackUpgrade.downgrade.retry.body').format(currentVersion.repository_name),
  513. null,
  514. Em.I18n.t('admin.stackUpgrade.dialog.downgrade.header').format(currentVersion.repository_name),
  515. Em.I18n.t('admin.stackUpgrade.downgrade.proceed')
  516. );
  517. },
  518. /**
  519. * confirmation popup before install repository version
  520. */
  521. installRepoVersionConfirmation: function (repo) {
  522. var self = this;
  523. return App.showConfirmationPopup(function () {
  524. self.installRepoVersion(repo);
  525. },
  526. Em.I18n.t('admin.stackVersions.version.install.confirm').format(repo.get('displayName'))
  527. );
  528. },
  529. /**
  530. * sends request to install repoVersion to the cluster
  531. * and create clusterStackVersion resourse
  532. * @param {Em.Object} repo
  533. * @return {$.ajax}
  534. * @method installRepoVersion
  535. */
  536. installRepoVersion: function (repo) {
  537. this.set('requestInProgress', true);
  538. var data = {
  539. ClusterStackVersions: {
  540. stack: repo.get('stackVersionType'),
  541. version: repo.get('stackVersionNumber'),
  542. repository_version: repo.get('repositoryVersion')
  543. },
  544. id: repo.get('id')
  545. };
  546. return App.ajax.send({
  547. name: 'admin.stack_version.install.repo_version',
  548. sender: this,
  549. data: data,
  550. success: 'installRepoVersionSuccess',
  551. callback: function() {
  552. this.sender.set('requestInProgress', false);
  553. }
  554. });
  555. },
  556. /**
  557. * transform repo data into json for
  558. * saving changes to repository version
  559. * @param {Em.Object} repo
  560. * @returns {{operating_systems: Array}}
  561. */
  562. prepareRepoForSaving: function(repo) {
  563. var repoVersion = { "operating_systems": [] };
  564. repo.get('operatingSystems').forEach(function (os, k) {
  565. repoVersion.operating_systems.push({
  566. "OperatingSystems": {
  567. "os_type": os.get("osType")
  568. },
  569. "repositories": []
  570. });
  571. os.get('repositories').forEach(function (repository) {
  572. repoVersion.operating_systems[k].repositories.push({
  573. "Repositories": {
  574. "base_url": repository.get('baseUrl'),
  575. "repo_id": repository.get('repoId'),
  576. "repo_name": repository.get('repoName')
  577. }
  578. });
  579. });
  580. });
  581. return repoVersion;
  582. },
  583. /**
  584. * Return stack version for the repo object
  585. * @param {Em.Object} repo
  586. * */
  587. getStackVersionNumber: function(repo){
  588. var stackVersionNumber = repo.get('stackVersion');
  589. if(null == stackVersionNumber)
  590. stackVersionNumber = App.get('currentStackVersion');
  591. return stackVersionNumber;
  592. },
  593. /**
  594. * perform validation if <code>skip<code> is false and run save if
  595. * validation successfull or run save without validation is <code>skip<code> is true
  596. * @param {Em.Object} repo
  597. * @param {boolean} skip
  598. * @returns {$.Deferred}
  599. */
  600. saveRepoOS: function (repo, skip) {
  601. var self = this;
  602. var deferred = $.Deferred();
  603. this.validateRepoVersions(repo, skip).done(function(data) {
  604. if (data.length > 0) {
  605. deferred.resolve(data);
  606. } else {
  607. var repoVersion = self.prepareRepoForSaving(repo);
  608. var stackVersionNumber = self.getStackVersionNumber(repo);
  609. console.log("Repository stack version:"+stackVersionNumber);
  610. App.ajax.send({
  611. name: 'admin.stack_versions.edit.repo',
  612. sender: this,
  613. data: {
  614. stackName: App.get('currentStackName'),
  615. stackVersion: stackVersionNumber,
  616. repoVersionId: repo.get('repoVersionId'),
  617. repoVersion: repoVersion
  618. }
  619. }).success(function() {
  620. deferred.resolve([]);
  621. });
  622. }
  623. });
  624. return deferred.promise();
  625. },
  626. /**
  627. * send request for validation for each repository
  628. * @param {Em.Object} repo
  629. * @param {boolean} skip
  630. * @returns {*}
  631. */
  632. validateRepoVersions: function(repo, skip) {
  633. var deferred = $.Deferred(),
  634. totalCalls = 0,
  635. invalidUrls = [];
  636. if (skip) {
  637. deferred.resolve(invalidUrls);
  638. } else {
  639. var stackVersionNumber = this.getStackVersionNumber(repo);
  640. repo.get('operatingSystems').forEach(function (os) {
  641. if (os.get('isSelected')) {
  642. os.get('repositories').forEach(function (repo) {
  643. totalCalls++;
  644. App.ajax.send({
  645. name: 'admin.stack_versions.validate.repo',
  646. sender: this,
  647. data: {
  648. repo: repo,
  649. repoId: repo.get('repoId'),
  650. baseUrl: repo.get('baseUrl'),
  651. osType: os.get('osType'),
  652. stackName: App.get('currentStackName'),
  653. stackVersion: stackVersionNumber
  654. }
  655. })
  656. .success(function () {
  657. totalCalls--;
  658. if (totalCalls === 0) deferred.resolve(invalidUrls);
  659. })
  660. .error(function () {
  661. repo.set('hasError', true);
  662. invalidUrls.push(repo);
  663. totalCalls--;
  664. if (totalCalls === 0) deferred.resolve(invalidUrls);
  665. });
  666. });
  667. } else {
  668. return deferred.resolve(invalidUrls);
  669. }
  670. });
  671. }
  672. return deferred.promise();
  673. },
  674. /**
  675. * success callback for <code>installRepoVersion()<code>
  676. * saves request id to the db
  677. * @param data
  678. * @param opt
  679. * @param params
  680. * @method installStackVersionSuccess
  681. */
  682. installRepoVersionSuccess: function (data, opt, params) {
  683. var version = App.RepositoryVersion.find(params.id);
  684. App.db.set('repoVersionInstall', 'id', [data.Requests.id]);
  685. App.clusterStatus.setClusterStatus({
  686. wizardControllerName: this.get('name'),
  687. localdb: App.db.data
  688. });
  689. version.set('defaultStatus', 'INSTALLING');
  690. if (version.get('stackVersion')) {
  691. version.set('stackVersion.state', 'INSTALLING');
  692. }
  693. },
  694. /**
  695. * opens a popup with installations state per host
  696. * @param {Em.Object} version
  697. * @method showProgressPopup
  698. */
  699. showProgressPopup: function(version) {
  700. var popupTitle = Em.I18n.t('admin.stackVersions.details.install.hosts.popup.title').format(version.get('displayName'));
  701. var requestIds = App.get('testMode') ? [1] : App.db.get('repoVersionInstall', 'id');
  702. var hostProgressPopupController = App.router.get('highAvailabilityProgressPopupController');
  703. hostProgressPopupController.initPopup(popupTitle, requestIds, this);
  704. },
  705. /**
  706. * reset upgradeState to INIT when upgrade is COMPLETED
  707. * and clean auxiliary data
  708. */
  709. finish: function () {
  710. if (App.get('upgradeState') === 'COMPLETED') {
  711. this.setDBProperty('upgradeId', undefined);
  712. this.setDBProperty('upgradeState', 'INIT');
  713. this.setDBProperty('upgradeVersion', undefined);
  714. this.setDBProperty('currentVersion', undefined);
  715. this.setDBProperty('isDowngrade', undefined);
  716. App.clusterStatus.setClusterStatus({
  717. localdb: App.db.data
  718. });
  719. App.set('upgradeState', 'INIT');
  720. }
  721. }.observes('App.upgradeState'),
  722. /**
  723. * show dialog with tasks of upgrade
  724. * @return {App.ModalPopup}
  725. */
  726. openUpgradeDialog: function () {
  727. App.router.transitionTo('admin.stackUpgrade');
  728. },
  729. /**
  730. * returns url to get data for repoVersion or clusterStackVersion
  731. * @param {Boolean} stack true if load clusterStackVersion
  732. * @param {Boolean} fullLoad true if load all data
  733. * @returns {String}
  734. * @method getUrl
  735. */
  736. getUrl: function(stack, fullLoad) {
  737. if (App.get('testMode')) {
  738. return stack ? this.get('mockStackUrl') : this.get('mockRepoUrl')
  739. } else {
  740. if (fullLoad) {
  741. return stack ? this.get('realStackUrl') : this.get('realRepoUrl');
  742. } else {
  743. return this.get('realUpdateUrl');
  744. }
  745. }
  746. },
  747. /**
  748. * get stack versions from server and push it to model
  749. * @return {*}
  750. * @method loadStackVersionsToModel
  751. */
  752. loadStackVersionsToModel: function (fullLoad) {
  753. var dfd = $.Deferred();
  754. App.HttpClient.get(this.getUrl(true, fullLoad), App.stackVersionMapper, {
  755. complete: function () {
  756. dfd.resolve();
  757. }
  758. });
  759. return dfd.promise();
  760. },
  761. /**
  762. * get repo versions from server and push it to model
  763. * @return {*}
  764. * @params {Boolean} isUpdate - if true loads part of data that need to be updated
  765. * @method loadRepoVersionsToModel()
  766. */
  767. loadRepoVersionsToModel: function () {
  768. var dfd = $.Deferred();
  769. App.HttpClient.get(this.getUrl(false, true), App.repoVersionMapper, {
  770. complete: function () {
  771. dfd.resolve();
  772. }
  773. });
  774. return dfd.promise();
  775. },
  776. /**
  777. * set status to Upgrade item
  778. * @param item
  779. * @param status
  780. */
  781. setUpgradeItemStatus: function(item, status) {
  782. this.set('requestInProgress', true);
  783. return App.ajax.send({
  784. name: 'admin.upgrade.upgradeItem.setState',
  785. sender: this,
  786. data: {
  787. upgradeId: item.get('request_id'),
  788. itemId: item.get('stage_id'),
  789. groupId: item.get('group_id'),
  790. status: status
  791. },
  792. callback: function() {
  793. this.sender.set('requestInProgress', false);
  794. }
  795. }).done(function () {
  796. item.set('status', status);
  797. });
  798. },
  799. currentVersionObserver: function () {
  800. var versionNumber = this.get('currentVersion.repository_version');
  801. var currentVersionObject = App.RepositoryVersion.find().findProperty('status', 'CURRENT');
  802. var versionName = currentVersionObject && currentVersionObject.get('stackVersionType');
  803. App.set('isStormMetricsSupported', versionName != 'HDP' || stringUtils.compareVersions(versionNumber, '2.2.2') > -1 || !versionNumber);
  804. }.observes('currentVersion.repository_version'),
  805. /**
  806. * get the installed repositories of HDP from server
  807. */
  808. loadRepositories: function () {
  809. if (App.router.get('clusterController.isLoaded')) {
  810. var nameVersionCombo = App.get('currentStackVersion');
  811. var stackName = nameVersionCombo.split('-')[0];
  812. var stackVersion = nameVersionCombo.split('-')[1];
  813. App.ajax.send({
  814. name: 'cluster.load_repositories',
  815. sender: this,
  816. data: {
  817. stackName: stackName,
  818. stackVersion: stackVersion
  819. },
  820. success: 'loadRepositoriesSuccessCallback',
  821. error: 'loadRepositoriesErrorCallback'
  822. });
  823. }
  824. }.observes('App.router.clusterController.isLoaded'),
  825. loadRepositoriesSuccessCallback: function (data) {
  826. var allRepos = [];
  827. data.items.forEach(function (os) {
  828. os.repositories.forEach(function (repository) {
  829. var osType = repository.Repositories.os_type;
  830. var repo = Em.Object.create({
  831. baseUrl: repository.Repositories.base_url,
  832. osType: osType,
  833. repoId: repository.Repositories.repo_id,
  834. repoName : repository.Repositories.repo_name,
  835. stackName : repository.Repositories.stack_name,
  836. stackVersion : repository.Repositories.stack_version,
  837. isFirst: false
  838. });
  839. var group = allRepos.findProperty('name', osType);
  840. if (!group) {
  841. group = {
  842. name: osType,
  843. repositories: []
  844. };
  845. repo.set('isFirst', true);
  846. allRepos.push(group);
  847. }
  848. group.repositories.push(repo);
  849. });
  850. }, this);
  851. allRepos.stackVersion = App.get('currentStackVersionNumber');
  852. this.set('allRepos', allRepos);
  853. },
  854. loadRepositoriesErrorCallback: function (request, ajaxOptions, error) {
  855. console.log('Error message is: ' + request.responseText);
  856. }
  857. });