configs.js 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
  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('controllers/wizard/slave_component_groups_controller');
  20. var batchUtils = require('utils/batch_scheduled_requests');
  21. var databaseUtils = require('utils/configs/database');
  22. App.MainServiceInfoConfigsController = Em.Controller.extend(App.ConfigsLoader, App.ServerValidatorMixin, App.EnhancedConfigsMixin, App.ThemesMappingMixin, App.VersionsMappingMixin, App.ConfigsSaverMixin, App.ConfigsComparator, {
  23. name: 'mainServiceInfoConfigsController',
  24. isHostsConfigsPage: false,
  25. forceTransition: false,
  26. isRecommendedLoaded: true,
  27. dataIsLoaded: false,
  28. stepConfigs: [], //contains all field properties that are viewed in this service
  29. selectedService: null,
  30. selectedConfigGroup: null,
  31. selectedServiceNameTrigger: null,
  32. requestsInProgress: [],
  33. groupsStore: App.ServiceConfigGroup.find(),
  34. /**
  35. * config groups for current service
  36. * @type {App.ConfigGroup[]}
  37. */
  38. configGroups: function() {
  39. return this.get('groupsStore').filterProperty('serviceName', this.get('content.serviceName'));
  40. }.property('content.serviceName', 'groupsStore'),
  41. dependentConfigGroups: function() {
  42. if (this.get('dependentServiceNames.length') === 0) return [];
  43. return this.get('groupsStore').filter(function(group) {
  44. return this.get('dependentServiceNames').contains(group.get('serviceName'));
  45. }, this);
  46. }.property('content.serviceName', 'dependentServiceNames', 'groupsStore.length', 'groupStore.@each.name'),
  47. allConfigs: [],
  48. /**
  49. * Determines if save configs is in progress
  50. * @type {boolean}
  51. */
  52. saveInProgress: false,
  53. isCompareMode: false,
  54. preSelectedConfigVersion: null,
  55. /**
  56. * contain Service Config Property, when user proceed from Select Config Group dialog
  57. */
  58. overrideToAdd: null,
  59. /**
  60. * version selected to view
  61. */
  62. selectedVersion: null,
  63. /**
  64. * note passed on configs save
  65. * @type {string}
  66. */
  67. serviceConfigVersionNote: '',
  68. versionLoaded: false,
  69. /**
  70. * Determines when data about config groups is loaded
  71. * Including recommendations with information about hosts in the each group
  72. * @type {boolean}
  73. */
  74. configGroupsAreLoaded: false,
  75. dependentServiceNames: [],
  76. /**
  77. * defines which service configs need to be loaded to stepConfigs
  78. * @type {string[]}
  79. */
  80. servicesToLoad: function() {
  81. return [this.get('content.serviceName')].concat(this.get('dependentServiceNames')).uniq();
  82. }.property('content.serviceName', 'dependentServiceNames.length'),
  83. /**
  84. * @type {boolean}
  85. */
  86. isCurrentSelected: function () {
  87. return App.ServiceConfigVersion.find(this.get('content.serviceName') + "_" + this.get('selectedVersion')).get('isCurrent');
  88. }.property('selectedVersion', 'content.serviceName', 'dataIsLoaded', 'versionLoaded'),
  89. /**
  90. * @type {boolean}
  91. */
  92. canEdit: function () {
  93. return (this.get('selectedVersion') == this.get('currentDefaultVersion') || !this.get('selectedConfigGroup.isDefault'))
  94. && !this.get('isCompareMode') && App.isAccessible('MANAGER') && !this.get('isHostsConfigsPage');
  95. }.property('selectedVersion', 'isCompareMode', 'currentDefaultVersion', 'selectedConfigGroup.isDefault'),
  96. serviceConfigs: function () {
  97. return App.config.get('preDefinedServiceConfigs');
  98. }.property('App.config.preDefinedServiceConfigs'),
  99. /**
  100. * Number of errors in the configs in the selected service (only for AdvancedTab if App supports Enhanced Configs)
  101. * @type {number}
  102. */
  103. errorsCount: function () {
  104. return this.get('selectedService.configs').filter(function (config) {
  105. return Em.isNone(config.get('widgetType'));
  106. }).filter(function(config) {
  107. return !config.get('isValid') || (config.get('overrides') || []).someProperty('isValid', false);
  108. }).filterProperty('isVisible').length;
  109. }.property('selectedService.configs.@each.isValid', 'selectedService.configs.@each.isVisible', 'selectedService.configs.@each.overrideErrorTrigger'),
  110. /**
  111. * Determines if Save-button should be disabled
  112. * Disabled if some configs have invalid values for selected service
  113. * or save-process currently in progress
  114. *
  115. * @type {boolean}
  116. */
  117. isSubmitDisabled: function () {
  118. if (!this.get('selectedService')) return true;
  119. return this.get('selectedService').get('errorCount') !== 0 || this.get('saveInProgress');
  120. }.property('selectedService.errorCount', 'saveInProgress'),
  121. /**
  122. * Determines if some config value is changed
  123. * @type {boolean}
  124. */
  125. isPropertiesChanged: function(){
  126. return this.get('stepConfigs').someProperty('isPropertiesChanged', true);
  127. }.property('stepConfigs.@each.isPropertiesChanged'),
  128. /**
  129. * Filter text will be located here
  130. * @type {string}
  131. */
  132. filter: '',
  133. /**
  134. * List of filters for config properties to populate filter combobox
  135. * @type {{attributeName: string, attributeValue: boolean, caption: string}[]}
  136. */
  137. propertyFilters: [
  138. {
  139. attributeName: 'isOverridden',
  140. attributeValue: true,
  141. caption: 'common.combobox.dropdown.overridden'
  142. },
  143. {
  144. attributeName: 'isFinal',
  145. attributeValue: true,
  146. caption: 'common.combobox.dropdown.final'
  147. },
  148. {
  149. attributeName: 'hasCompareDiffs',
  150. attributeValue: true,
  151. caption: 'common.combobox.dropdown.changed',
  152. dependentOn: 'isCompareMode'
  153. },
  154. {
  155. attributeName: 'hasIssues',
  156. attributeValue: true,
  157. caption: 'common.combobox.dropdown.issues'
  158. }
  159. ],
  160. /**
  161. * get array of config properties that are shown in settings tab
  162. * @type {App.StackConfigProperty[]}
  163. */
  164. settingsTabProperties: function() {
  165. var properties = [];
  166. App.Tab.find(this.get('content.serviceName') + '_settings').get('sections').forEach(function(s) {
  167. s.get('subSections').forEach(function(ss) {
  168. properties = properties.concat(ss.get('configProperties').filterProperty('id'));
  169. });
  170. });
  171. return properties;
  172. }.property('content.serviceName', 'App.router.clusterController.isStackConfigsLoaded'),
  173. /**
  174. * Dropdown menu items in filter combobox
  175. * @type {{attributeName: string, attributeValue: string, name: string, selected: boolean}[]}
  176. */
  177. filterColumns: function () {
  178. var filterColumns = [];
  179. this.get('propertyFilters').forEach(function(filter) {
  180. if (Em.isNone(filter.dependentOn) || this.get(filter.dependentOn)) {
  181. filterColumns.push(Ember.Object.create({
  182. attributeName: filter.attributeName,
  183. attributeValue: filter.attributeValue,
  184. name: this.t(filter.caption),
  185. selected: filter.dependentOn ? this.get(filter.dependentOn) : false
  186. }));
  187. }
  188. }, this);
  189. return filterColumns;
  190. }.property('propertyFilters', 'isCompareMode'),
  191. /**
  192. * Detects of some of the `password`-configs has not default value
  193. *
  194. * @type {boolean}
  195. */
  196. passwordConfigsAreChanged: function () {
  197. return this.get('stepConfigs')
  198. .findProperty('serviceName', this.get('selectedService.serviceName'))
  199. .get('configs')
  200. .filterProperty('displayType', 'password')
  201. .someProperty('isNotDefaultValue');
  202. }.property('stepConfigs.[].configs', 'selectedService.serviceName'),
  203. /**
  204. * indicate whether service config version belongs to default config group
  205. * @param {object} version
  206. * @return {Boolean}
  207. * @private
  208. * @method isVersionDefault
  209. */
  210. isVersionDefault: function(version) {
  211. return (App.ServiceConfigVersion.find(this.get('content.serviceName') + "_" + version).get('groupId') == -1);
  212. },
  213. /**
  214. * register request to view to track his progress
  215. * @param {$.ajax} request
  216. * @method trackRequest
  217. */
  218. trackRequest: function (request) {
  219. this.get('requestsInProgress').push(request);
  220. },
  221. /**
  222. * clear and set properties to default value
  223. * @method clearStep
  224. */
  225. clearStep: function () {
  226. this.get('requestsInProgress').forEach(function(r) {
  227. if (r && r.readyState !== 4) {
  228. r.abort();
  229. }
  230. });
  231. this.get('requestsInProgress').clear();
  232. this.clearLoadInfo();
  233. this.clearSaveInfo();
  234. this.clearDependentConfigs();
  235. this.setProperties({
  236. saveInProgress: false,
  237. isInit: true,
  238. hash: null,
  239. forceTransition: false,
  240. dataIsLoaded: false,
  241. versionLoaded: false,
  242. filter: '',
  243. serviceConfigVersionNote: '',
  244. dependentServiceNames: [],
  245. configGroupsAreLoaded: false
  246. });
  247. this.get('filterColumns').setEach('selected', false);
  248. this.clearConfigs();
  249. },
  250. clearConfigs: function() {
  251. this.get('selectedConfigGroup', null);
  252. this.get('allConfigs').invoke('destroy');
  253. this.get('stepConfigs').invoke('destroy');
  254. this.set('stepConfigs', []);
  255. this.set('allConfigs', []);
  256. this.set('selectedService', null);
  257. },
  258. /**
  259. * "Finger-print" of the <code>stepConfigs</code>. Filled after first configGroup selecting
  260. * Used to determine if some changes were made (when user navigates away from this page)
  261. * @type {String|null}
  262. */
  263. hash: null,
  264. /**
  265. * Is this initial config group changing
  266. * @type {Boolean}
  267. */
  268. isInit: true,
  269. /**
  270. * On load function
  271. * @method loadStep
  272. */
  273. loadStep: function () {
  274. var self = this;
  275. var serviceName = this.get('content.serviceName');
  276. this.clearStep();
  277. this.set('dependentServiceNames', App.StackService.find(serviceName).get('dependentServiceNames'));
  278. if (App.get('isClusterSupportsEnhancedConfigs')) {
  279. this.loadConfigTheme(serviceName).always(function() {
  280. App.themesMapper.generateAdvancedTabs([serviceName]);
  281. // Theme mapper has UI only configs that needs to be merged with current service version configs
  282. // This requires calling `loadCurrentVersions` after theme has loaded
  283. self.loadCurrentVersions();
  284. });
  285. }
  286. else {
  287. this.loadCurrentVersions();
  288. }
  289. this.loadServiceConfigVersions();
  290. },
  291. /**
  292. * Generate "finger-print" for current <code>stepConfigs[0]</code>
  293. * Used to determine, if user has some unsaved changes (comparing with <code>hash</code>)
  294. * @returns {string|null}
  295. * @method getHash
  296. */
  297. getHash: function () {
  298. if (!this.get('selectedService.configs.length')) {
  299. return null;
  300. }
  301. var hash = {};
  302. this.get('selectedService.configs').forEach(function (config) {
  303. hash[config.get('name')] = {value: App.config.formatPropertyValue(config), overrides: [], isFinal: config.get('isFinal')};
  304. if (!config.get('overrides')) return;
  305. if (!config.get('overrides.length')) return;
  306. config.get('overrides').forEach(function (override) {
  307. hash[config.get('name')].overrides.push(App.config.formatPropertyValue(override));
  308. });
  309. });
  310. return JSON.stringify(hash);
  311. },
  312. parseConfigData: function(data) {
  313. this.prepareConfigObjects(data, this.get('content.serviceName'));
  314. var self = this;
  315. this.loadCompareVersionConfigs(this.get('allConfigs')).done(function() {
  316. self.addOverrides(data, self.get('allConfigs'));
  317. self.onLoadOverrides(self.get('allConfigs'));
  318. });
  319. },
  320. prepareConfigObjects: function(data, serviceName) {
  321. this.get('stepConfigs').clear();
  322. var configGroups = [];
  323. data.items.forEach(function (v) {
  324. if (v.group_name == 'default') {
  325. v.configurations.forEach(function (c) {
  326. configGroups.pushObject(c);
  327. });
  328. }
  329. });
  330. var configs = App.config.mergePredefinedWithSaved(configGroups, serviceName, this.get('selectedConfigGroup'), this.get('canEdit'));
  331. configs = App.config.sortConfigs(configs);
  332. /**
  333. * if property defined in stack but somehow it missed from cluster properties (can be after stack upgrade)
  334. * ui should add this properties to step configs
  335. */
  336. configs = this.mergeWithStackProperties(configs);
  337. //put properties from capacity-scheduler.xml into one config with textarea view
  338. if (this.get('content.serviceName') === 'YARN') {
  339. var configsToSkip = this.get('settingsTabProperties').filterProperty('filename', 'capacity-scheduler.xml');
  340. configs = App.config.fileConfigsIntoTextarea(configs, 'capacity-scheduler.xml', configsToSkip);
  341. }
  342. if (this.get('content.serviceName') === 'KERBEROS') {
  343. var kdc_type = configs.findProperty('name', 'kdc_type');
  344. if (kdc_type.get('value') === 'none') {
  345. configs.findProperty('name', 'kdc_host').set('isRequired', false).set('isVisible', false);
  346. configs.findProperty('name', 'admin_server_host').set('isRequired', false).set('isVisible', false);
  347. configs.findProperty('name', 'domains').set('isRequired', false).set('isVisible', false);
  348. } else if (kdc_type.get('value') === 'active-directory') {
  349. configs.findProperty('name', 'container_dn').set('isVisible', true);
  350. configs.findProperty('name', 'ldap_url').set('isVisible', true);
  351. }
  352. }
  353. this.set('allConfigs', configs);
  354. //add configs as names of host components
  355. this.addDBProperties(configs);
  356. },
  357. /**
  358. * This method should add UI properties that are market as <code>'isRequiredByAgent': false<code>
  359. * @param configs
  360. */
  361. addDBProperties: function(configs) {
  362. if (this.get('content.serviceName') === 'HIVE') {
  363. var propertyToAdd = App.config.get('preDefinedSitePropertiesMap')[App.config.configId('hive_hostname','hive-env')],
  364. cfg = App.config.createDefaultConfig(propertyToAdd.name, propertyToAdd.serviceName, propertyToAdd.filename, true, propertyToAdd),
  365. connectionUrl = configs.findProperty('name', 'javax.jdo.option.ConnectionURL');
  366. if (cfg && connectionUrl) {
  367. cfg.savedValue = cfg.value = databaseUtils.getDBLocationFromJDBC(connectionUrl.get('value'));
  368. configs.pushObject(App.ServiceConfigProperty.create(cfg));
  369. }
  370. }
  371. },
  372. /**
  373. * adds properties form stack that doesn't belong to cluster
  374. * to step configs
  375. * also set recommended value if isn't exists
  376. *
  377. * @return {App.ServiceConfigProperty[]}
  378. * @method mergeWithStackProperties
  379. */
  380. mergeWithStackProperties: function (configs) {
  381. this.get('settingsTabProperties').forEach(function (advanced) {
  382. if (!configs.someProperty('name', advanced.get('name'))) {
  383. configs.pushObject(App.ServiceConfigProperty.create({
  384. name: advanced.get('name'),
  385. displayName: advanced.get('displayName'),
  386. value: advanced.get('value'),
  387. savedValue: null,
  388. filename: advanced.get('fileName'),
  389. isUserProperty: false,
  390. isNotSaved: true,
  391. recommendedValue: advanced.get('value'),
  392. isFinal: advanced.get('isFinal'),
  393. recommendedIsFinal: advanced.get('recommendedIsFinal'),
  394. serviceName: advanced.get('serviceName'),
  395. supportsFinal: advanced.get('supportsFinal'),
  396. category: 'Advanced ' + App.config.getConfigTagFromFileName(advanced.get('fileName')),
  397. widget: advanced.get('widget'),
  398. widgetType: advanced.get('widgetType')
  399. }));
  400. }
  401. });
  402. return configs;
  403. },
  404. addOverrides: function(data, allConfigs) {
  405. var self = this;
  406. data.items.forEach(function(group) {
  407. if (group.group_name != 'default') {
  408. var configGroup = App.ServiceConfigGroup.find().filterProperty('serviceName', group.service_name).findProperty('name', group.group_name);
  409. group.configurations.forEach(function(config) {
  410. for (var prop in config.properties) {
  411. var fileName = App.config.getOriginalFileName(config.type);
  412. var serviceConfig = allConfigs.filterProperty('name', prop).findProperty('filename', fileName);
  413. if (serviceConfig) {
  414. var value = App.config.formatPropertyValue(serviceConfig, config.properties[prop]);
  415. var isFinal = !!(config.properties_attributes && config.properties_attributes.final && config.properties_attributes.final[prop]);
  416. if (self.get('selectedConfigGroup.isDefault') || configGroup.get('name') == self.get('selectedConfigGroup.name')) {
  417. var overridePlainObject = {
  418. "value": value,
  419. "savedValue": value,
  420. "isFinal": isFinal,
  421. "savedIsFinal": isFinal,
  422. "isEditable": self.get('canEdit') && configGroup.get('name') == self.get('selectedConfigGroup.name')
  423. };
  424. App.config.createOverride(serviceConfig, overridePlainObject, configGroup);
  425. }
  426. } else {
  427. var isEditable = self.get('canEdit') && configGroup.get('name') == self.get('selectedConfigGroup.name');
  428. allConfigs.push(App.config.createCustomGroupConfig(prop, config, configGroup, isEditable));
  429. }
  430. }
  431. });
  432. }
  433. });
  434. },
  435. /**
  436. * @param allConfigs
  437. * @private
  438. * @method onLoadOverrides
  439. */
  440. onLoadOverrides: function (allConfigs) {
  441. this.get('servicesToLoad').forEach(function(serviceName) {
  442. var configGroups = serviceName == this.get('content.serviceName') ? this.get('configGroups') : this.get('dependentConfigGroups').filterProperty('serviceName', serviceName);
  443. var serviceNames = [ serviceName ];
  444. if(serviceName === 'OOZIE') {
  445. // For Oozie, also add ELService properties which are marked as FALCON properties.
  446. serviceNames.push('FALCON');
  447. }
  448. var configsByService = this.get('allConfigs').filter(function (c) {
  449. return serviceNames.contains(c.get('serviceName'));
  450. });
  451. var serviceConfig = App.config.createServiceConfig(serviceName, configGroups, configsByService, configsByService.length);
  452. if (serviceConfig.get('serviceName') === 'HDFS') {
  453. if (App.get('isHaEnabled')) {
  454. var c = serviceConfig.configs,
  455. removedConfigs = c.filterProperty('category', 'SECONDARY_NAMENODE');
  456. removedConfigs.setEach('isVisible', false);
  457. serviceConfig.configs = c;
  458. }
  459. }
  460. this.addHostNamesToConfigs(serviceConfig);
  461. this.get('stepConfigs').pushObject(serviceConfig);
  462. }, this);
  463. var selectedService = this.get('stepConfigs').findProperty('serviceName', this.get('content.serviceName'));
  464. if (this.get('selectedService.serviceName') != selectedService.get('serviceName')) {
  465. this.propertyDidChange('selectedServiceNameTrigger');
  466. }
  467. this.set('selectedService', selectedService);
  468. this.checkOverrideProperty(selectedService);
  469. if (!App.Service.find().someProperty('serviceName', 'RANGER')) {
  470. App.config.removeRangerConfigs(this.get('stepConfigs'));
  471. } else {
  472. this.setVisibilityForRangerProperties(selectedService);
  473. }
  474. this._onLoadComplete();
  475. this.getRecommendationsForDependencies(null, true, Em.K, this.get('selectedConfigGroup'));
  476. App.loadTimer.finish('Service Configs Page');
  477. },
  478. /**
  479. * @method _getRecommendationsForDependenciesCallback
  480. */
  481. _onLoadComplete: function () {
  482. this.get('stepConfigs').forEach(function(serviceConfig){
  483. serviceConfig.set('initConfigsLength', serviceConfig.get('configs.length'));
  484. });
  485. this.setProperties({
  486. dataIsLoaded: true,
  487. versionLoaded: true,
  488. isInit: false,
  489. hash: this.getHash()
  490. });
  491. },
  492. /**
  493. * hide properties from Advanced ranger category that match pattern
  494. * if property with dependentConfigPattern is false otherwise don't hide
  495. * @param serviceConfig
  496. * @private
  497. * @method setVisibilityForRangerProperties
  498. */
  499. setVisibilityForRangerProperties: function(serviceConfig) {
  500. var category = "Advanced ranger-{0}-plugin-properties".format(this.get('content.serviceName').toLowerCase());
  501. if (serviceConfig.configCategories.findProperty('name', category)) {
  502. var patternConfig = serviceConfig.configs.findProperty('dependentConfigPattern');
  503. if (patternConfig) {
  504. var value = patternConfig.get('value') === true || ["yes", "true"].contains(patternConfig.get('value').toLowerCase());
  505. serviceConfig.configs.filter(function(c) {
  506. if (c.get('category') === category && c.get('name').match(patternConfig.get('dependentConfigPattern')) && c.get('name') != patternConfig.get('name'))
  507. c.set('isVisible', value);
  508. });
  509. }
  510. }
  511. },
  512. /**
  513. * trigger App.config.createOverride
  514. * @param {Object[]} stepConfig
  515. * @private
  516. * @method checkOverrideProperty
  517. */
  518. checkOverrideProperty: function (stepConfig) {
  519. var overrideToAdd = this.get('overrideToAdd');
  520. var value = !!this.get('overrideToAdd.widget') ? Em.get(overrideToAdd, 'value') : '';
  521. if (overrideToAdd) {
  522. overrideToAdd = stepConfig.configs.filter(function(c){
  523. return c.name == overrideToAdd.name && c.filename == overrideToAdd.filename;
  524. });
  525. if (overrideToAdd[0]) {
  526. App.config.createOverride(overrideToAdd[0], {"isEditable": true, "value": value}, this.get('selectedConfigGroup'));
  527. this.set('overrideToAdd', null);
  528. }
  529. }
  530. },
  531. /**
  532. *
  533. * @param serviceConfig
  534. */
  535. addHostNamesToConfigs: function(serviceConfig) {
  536. serviceConfig.get('configCategories').forEach(function(c) {
  537. if (c.showHost) {
  538. var stackComponent = App.StackServiceComponent.find(c.name);
  539. var component = stackComponent.get('isMaster') ? App.MasterComponent.find(c.name) : App.SlaveComponent.find(c.name);
  540. var hProperty = App.config.createHostNameProperty(serviceConfig.get('serviceName'), c.name, component.get('hostNames') || [], stackComponent);
  541. serviceConfig.get('configs').push(App.ServiceConfigProperty.create(hProperty));
  542. }
  543. }, this);
  544. },
  545. /**
  546. * Trigger loadSelectedVersion
  547. * @method doCancel
  548. */
  549. doCancel: function () {
  550. this.set('preSelectedConfigVersion', null);
  551. this.clearDependentConfigs();
  552. this.loadSelectedVersion(this.get('selectedVersion'), this.get('selectedConfigGroup'));
  553. },
  554. /**
  555. * trigger restartAllServiceHostComponents(batchUtils) if confirmed in popup
  556. * @method restartAllStaleConfigComponents
  557. * @return App.showConfirmationFeedBackPopup
  558. */
  559. restartAllStaleConfigComponents: function () {
  560. var self = this;
  561. var serviceDisplayName = this.get('content.displayName');
  562. var bodyMessage = Em.Object.create({
  563. confirmMsg: Em.I18n.t('services.service.restartAll.confirmMsg').format(serviceDisplayName),
  564. confirmButton: Em.I18n.t('services.service.restartAll.confirmButton'),
  565. additionalWarningMsg: this.get('content.passiveState') === 'OFF' ? Em.I18n.t('services.service.restartAll.warningMsg.turnOnMM').format(serviceDisplayName) : null
  566. });
  567. var isNNAffected = false;
  568. var restartRequiredHostsAndComponents = this.get('content.restartRequiredHostsAndComponents');
  569. for (var hostName in restartRequiredHostsAndComponents) {
  570. restartRequiredHostsAndComponents[hostName].forEach(function (hostComponent) {
  571. if (hostComponent == 'NameNode')
  572. isNNAffected = true;
  573. })
  574. }
  575. if (this.get('content.serviceName') == 'HDFS' && isNNAffected &&
  576. this.get('content.hostComponents').filterProperty('componentName', 'NAMENODE').someProperty('workStatus', App.HostComponentStatus.started)) {
  577. App.router.get('mainServiceItemController').checkNnLastCheckpointTime(function () {
  578. return App.showConfirmationFeedBackPopup(function (query) {
  579. var selectedService = self.get('content.id');
  580. batchUtils.restartAllServiceHostComponents(serviceDisplayName, selectedService, true, query);
  581. }, bodyMessage);
  582. });
  583. } else {
  584. return App.showConfirmationFeedBackPopup(function (query) {
  585. var selectedService = self.get('content.id');
  586. batchUtils.restartAllServiceHostComponents(serviceDisplayName, selectedService, true, query);
  587. }, bodyMessage);
  588. }
  589. },
  590. /**
  591. * trigger launchHostComponentRollingRestart(batchUtils)
  592. * @method rollingRestartStaleConfigSlaveComponents
  593. */
  594. rollingRestartStaleConfigSlaveComponents: function (componentName) {
  595. batchUtils.launchHostComponentRollingRestart(componentName.context, this.get('content.displayName'), this.get('content.passiveState') === "ON", true);
  596. },
  597. /**
  598. * trigger showItemsShouldBeRestarted popup with hosts that requires restart
  599. * @param {{context: object}} event
  600. * @method showHostsShouldBeRestarted
  601. */
  602. showHostsShouldBeRestarted: function (event) {
  603. var restartRequiredHostsAndComponents = event.context.restartRequiredHostsAndComponents;
  604. var hosts = [];
  605. for (var hostName in restartRequiredHostsAndComponents) {
  606. hosts.push(hostName);
  607. }
  608. var hostsText = hosts.length == 1 ? Em.I18n.t('common.host') : Em.I18n.t('common.hosts');
  609. hosts = hosts.join(', ');
  610. this.showItemsShouldBeRestarted(hosts, Em.I18n.t('service.service.config.restartService.shouldBeRestarted').format(hostsText));
  611. },
  612. /**
  613. * trigger showItemsShouldBeRestarted popup with components that requires restart
  614. * @param {{context: object}} event
  615. * @method showComponentsShouldBeRestarted
  616. */
  617. showComponentsShouldBeRestarted: function (event) {
  618. var restartRequiredHostsAndComponents = event.context.restartRequiredHostsAndComponents;
  619. var hostsComponets = [];
  620. var componentsObject = {};
  621. for (var hostName in restartRequiredHostsAndComponents) {
  622. restartRequiredHostsAndComponents[hostName].forEach(function (hostComponent) {
  623. hostsComponets.push(hostComponent);
  624. if (componentsObject[hostComponent] != undefined) {
  625. componentsObject[hostComponent]++;
  626. } else {
  627. componentsObject[hostComponent] = 1;
  628. }
  629. })
  630. }
  631. var componentsList = [];
  632. for (var obj in componentsObject) {
  633. var componentDisplayName = (componentsObject[obj] > 1) ? obj + 's' : obj;
  634. componentsList.push(componentsObject[obj] + ' ' + componentDisplayName);
  635. }
  636. var componentsText = componentsList.length == 1 ? Em.I18n.t('common.component') : Em.I18n.t('common.components');
  637. hostsComponets = componentsList.join(', ');
  638. this.showItemsShouldBeRestarted(hostsComponets, Em.I18n.t('service.service.config.restartService.shouldBeRestarted').format(componentsText));
  639. },
  640. /**
  641. * Show popup with selectable (@see App.SelectablePopupBodyView) list of items
  642. * @param {string} content string with comma-separated list of hostNames or componentNames
  643. * @param {string} header popup header
  644. * @returns {App.ModalPopup}
  645. * @method showItemsShouldBeRestarted
  646. */
  647. showItemsShouldBeRestarted: function (content, header) {
  648. return App.ModalPopup.show({
  649. content: content,
  650. header: header,
  651. bodyClass: App.SelectablePopupBodyView,
  652. secondary: null
  653. });
  654. },
  655. /**
  656. * trigger manageConfigurationGroups
  657. * @method manageConfigurationGroup
  658. */
  659. manageConfigurationGroup: function () {
  660. App.router.get('manageConfigGroupsController').manageConfigurationGroups(null, this.get('content'));
  661. },
  662. /**
  663. * If user changes cfg group if some configs was changed popup with propose to save changes must be shown
  664. * @param {object} event - triggered event for selecting another config-group
  665. * @method selectConfigGroup
  666. */
  667. selectConfigGroup: function (event) {
  668. var self = this;
  669. function callback() {
  670. self.doSelectConfigGroup(event);
  671. }
  672. if (!this.get('isInit')) {
  673. if (this.hasUnsavedChanges()) {
  674. this.showSavePopup(null, callback);
  675. return;
  676. }
  677. }
  678. callback();
  679. },
  680. /**
  681. * switch view to selected group
  682. * @param event
  683. * @method selectConfigGroup
  684. */
  685. doSelectConfigGroup: function (event) {
  686. App.loadTimer.start('Service Configs Page');
  687. var configGroupVersions = App.ServiceConfigVersion.find().filterProperty('groupId', event.context.get('configGroupId'));
  688. //check whether config group has config versions
  689. if (event.context.get('configGroupId') == -1) {
  690. this.loadCurrentVersions();
  691. } else if (configGroupVersions.length > 0) {
  692. this.loadSelectedVersion(configGroupVersions.findProperty('isCurrent').get('version'), event.context);
  693. } else {
  694. this.loadSelectedVersion(null, event.context);
  695. }
  696. }
  697. });