configs.js 86 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317
  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 lazyLoading = require('utils/lazy_loading');
  22. App.MainServiceInfoConfigsController = Em.Controller.extend({
  23. name: 'mainServiceInfoConfigsController',
  24. isHostsConfigsPage: false,
  25. forceTransition: false,
  26. dataIsLoaded: false,
  27. stepConfigs: [], //contains all field properties that are viewed in this service
  28. selectedService: null,
  29. serviceConfigTags: null,
  30. selectedConfigGroup: null,
  31. configTypesInfo: {
  32. items: [],
  33. supportsFinal: []
  34. },
  35. selectedServiceConfigTypes: [],
  36. selectedServiceSupportsFinal: [],
  37. configGroups: [],
  38. allConfigs: [],
  39. uiConfigs: [],
  40. customConfig: [],
  41. isApplyingChanges: false,
  42. saveConfigsFlag: true,
  43. putClusterConfigsCallsNumber: null,
  44. compareServiceVersion: null,
  45. // contain Service Config Property, when user proceed from Select Config Group dialog
  46. overrideToAdd: null,
  47. serviceConfigs: function () {
  48. return App.config.get('preDefinedServiceConfigs');
  49. }.property('App.config.preDefinedServiceConfigs'),
  50. customConfigs: function () {
  51. return App.config.get('preDefinedCustomConfigs');
  52. }.property('App.config.preDefinedCustomConfigs'),
  53. configMapping: function () {
  54. return App.config.get('configMapping');
  55. }.property('App.config.configMapping'),
  56. configs: function () {
  57. return App.config.get('preDefinedSiteProperties');
  58. }.property('App.config.preDefinedSiteProperties'),
  59. secureConfigs: function () {
  60. if (App.get('isHadoop2Stack')) {
  61. return require('data/HDP2/secure_mapping');
  62. } else {
  63. return require('data/secure_mapping');
  64. }
  65. }.property('App.isHadoop2Stack'),
  66. /**
  67. * Map, which contains relation between group and site
  68. * to upload overridden properties
  69. */
  70. loadedGroupToOverrideSiteToTagMap: {},
  71. /**
  72. * During page load time the cluster level site to tag
  73. * mapping is stored here.
  74. *
  75. * Example:
  76. * {
  77. * 'hdfs-site': 'version1',
  78. * 'core-site': 'version1'
  79. * }
  80. */
  81. loadedClusterSiteToTagMap: {},
  82. /**
  83. * Holds the actual base service-config server data uploaded.
  84. * This is used by the host-override mechanism to update host
  85. * specific values.
  86. */
  87. savedSiteNameToServerServiceConfigDataMap: {},
  88. isSubmitDisabled: function () {
  89. return (!(this.stepConfigs.everyProperty('errorCount', 0)) || this.get('isApplyingChanges'));
  90. }.property('stepConfigs.@each.errorCount', 'isApplyingChanges'),
  91. slaveComponentGroups: null,
  92. /**
  93. * Filter text will be located here
  94. */
  95. filter: '',
  96. /**
  97. * List of filters for config properties to populate filter combobox
  98. */
  99. propertyFilters: [
  100. {
  101. attributeName: 'isOverridden',
  102. caption: 'common.combobox.dropdown.overridden'
  103. },
  104. {
  105. attributeName: 'isFinal',
  106. caption: 'common.combobox.dropdown.final'
  107. }
  108. ],
  109. /**
  110. * Dropdown menu items in filter combobox
  111. */
  112. filterColumns: function () {
  113. return this.get('propertyFilters').map(function(filter) {
  114. return Ember.Object.create({
  115. attributeName: filter.attributeName,
  116. name: this.t(filter.caption),
  117. selected: false
  118. })
  119. }, this);
  120. }.property('propertyFilters'),
  121. /**
  122. * clear and set properties to default value
  123. */
  124. clearStep: function () {
  125. this.set("isApplyingChanges", false)
  126. this.set('isInit', true);
  127. this.set('hash', null);
  128. this.set('forceTransition', false);
  129. this.set('dataIsLoaded', false);
  130. this.set('filter', '');
  131. this.get('filterColumns').setEach('selected', false);
  132. this.get('stepConfigs').clear();
  133. this.get('allConfigs').clear();
  134. this.get('uiConfigs').clear();
  135. this.get('customConfig').clear();
  136. this.set('loadedGroupToOverrideSiteToTagMap', {});
  137. this.set('savedSiteNameToServerServiceConfigDataMap', {});
  138. if (this.get('serviceConfigTags')) {
  139. this.set('serviceConfigTags', null);
  140. }
  141. },
  142. serviceConfigProperties: function () {
  143. return App.db.getServiceConfigProperties();
  144. }.property('content'),
  145. /**
  146. * "Finger-print" of the <code>stepConfigs</code>. Filled after first configGroup selecting
  147. * Used to determine if some changes were made (when user navigates away from this page)
  148. * {String}
  149. */
  150. hash: null,
  151. /**
  152. * Is this initial config group changing
  153. * {Boolean}
  154. */
  155. isInit: true,
  156. restartHosts: Em.A(),
  157. defaultsInfo: null,
  158. /**
  159. * On load function
  160. */
  161. loadStep: function () {
  162. console.log("TRACE: Loading configure for service");
  163. this.clearStep();
  164. this.loadServiceConfigs();
  165. },
  166. getHash: function () {
  167. if (!this.get('stepConfigs')[0]) {
  168. return null;
  169. }
  170. var hash = {};
  171. this.get('stepConfigs')[0].configs.forEach(function (config) {
  172. hash[config.get('name')] = {value: config.get('value'), overrides: []};
  173. if (!config.get('overrides')) return;
  174. if (!config.get('overrides.length')) return;
  175. config.get('overrides').forEach(function (override) {
  176. hash[config.get('name')].overrides.push(override.get('value'));
  177. });
  178. });
  179. return JSON.stringify(hash);
  180. },
  181. /**
  182. * Loads service configurations
  183. */
  184. loadServiceConfigs: function () {
  185. var advancedConfigs = [];
  186. var self = this;
  187. var serviceName = this.get('content.serviceName');
  188. var stackService = App.StackService.find().findProperty('serviceName', serviceName);
  189. if (stackService) {
  190. self.set('configTypesInfo', App.config.getConfigTypesInfoFromService(stackService));
  191. }
  192. App.config.loadAdvancedConfig(serviceName, function (properties) {
  193. advancedConfigs.pushObjects(properties);
  194. self.set('advancedConfigs', advancedConfigs);
  195. self.loadServiceTags();
  196. });
  197. },
  198. /**
  199. * load config tags of service
  200. */
  201. loadServiceTags: function () {
  202. App.ajax.send({
  203. name: 'config.tags_and_groups',
  204. sender: this,
  205. data: {
  206. serviceName: this.get('content.serviceName'),
  207. serviceConfigsDef: this.get('serviceConfigs').findProperty('serviceName', this.get('content.serviceName')),
  208. urlParams: "&config_groups/ConfigGroup/tag=" + this.get('content.serviceName')
  209. },
  210. success: 'loadServiceConfigsSuccess'
  211. });
  212. },
  213. loadServiceConfigsSuccess: function (data, opt, params) {
  214. if (data) {
  215. this.setConfigGroups.apply(this, Array.prototype.slice.call(arguments, 0));
  216. } else {
  217. App.ajax.send({
  218. name: 'config.tags',
  219. sender: this,
  220. data: App.permit(params, ['clusterName', 'serviceConfigsDef', 'serviceName']),
  221. success: 'setConfigGroups'
  222. });
  223. }
  224. },
  225. setConfigGroups: function (data, opt, params) {
  226. var serviceConfigsDef = params.serviceConfigsDef;
  227. var serviceName = this.get('content.serviceName');
  228. var displayName = this.get('content.displayName');
  229. console.debug("loadServiceConfigs(): data=", data);
  230. // Create default configuration group
  231. var selectedConfigGroup;
  232. var siteToTagMap = {};
  233. var hostsLength = App.router.get('mainHostController.hostsCountMap.TOTAL');
  234. var configTypesRendered = Object.keys(serviceConfigsDef.get('configTypesRendered'));
  235. configTypesRendered.forEach(function (siteName) {
  236. if (data.Clusters.desired_configs[siteName]) {
  237. siteToTagMap[siteName] = data.Clusters.desired_configs[siteName].tag;
  238. } else {
  239. siteToTagMap[siteName] = 'version1';
  240. }
  241. }, this);
  242. this.loadedClusterSiteToTagMap = siteToTagMap;
  243. //parse loaded config groups
  244. if (App.supports.hostOverrides) {
  245. var configGroups = [];
  246. if (data.config_groups && data.config_groups.length) {
  247. data.config_groups.forEach(function (item) {
  248. item = item.ConfigGroup;
  249. if (item.tag === this.get('content.serviceName')) {
  250. var groupHosts = item.hosts.mapProperty('host_name');
  251. var newConfigGroup = App.ConfigGroup.create({
  252. id: item.id,
  253. name: item.group_name,
  254. description: item.description,
  255. isDefault: false,
  256. parentConfigGroup: null,
  257. service: App.Service.find().findProperty('serviceName', item.tag),
  258. hosts: groupHosts,
  259. configSiteTags: []
  260. });
  261. hostsLength -= groupHosts.length;
  262. item.desired_configs.forEach(function (config) {
  263. newConfigGroup.configSiteTags.push(App.ConfigSiteTag.create({
  264. site: config.type,
  265. tag: config.tag
  266. }));
  267. }, this);
  268. // select default selected group for hosts page
  269. if (!selectedConfigGroup && this.get('isHostsConfigsPage') && newConfigGroup.get('hosts').contains(this.get('host.hostName')) && this.get('content.serviceName') === item.tag) {
  270. selectedConfigGroup = newConfigGroup;
  271. }
  272. configGroups.push(newConfigGroup);
  273. }
  274. }, this);
  275. }
  276. this.set('configGroups', configGroups);
  277. }
  278. var defaultConfigGroup = App.ConfigGroup.create({
  279. name: displayName + " Default",
  280. description: "Default cluster level " + serviceName + " configuration",
  281. isDefault: true,
  282. hosts: {
  283. length: hostsLength
  284. },
  285. parentConfigGroup: null,
  286. service: this.get('content'),
  287. serviceName: serviceName,
  288. configSiteTags: []
  289. });
  290. if (!selectedConfigGroup) {
  291. selectedConfigGroup = defaultConfigGroup;
  292. }
  293. this.get('configGroups').sort(function (configGroupA, configGroupB) {
  294. return (configGroupA.name > configGroupB.name);
  295. });
  296. this.get('configGroups').unshift(defaultConfigGroup);
  297. this.set('selectedConfigGroup', selectedConfigGroup);
  298. },
  299. onConfigGroupChange: function () {
  300. var self = this;
  301. this.get('stepConfigs').clear();
  302. var selectedConfigGroup = this.get('selectedConfigGroup');
  303. var serviceName = this.get('content.serviceName');
  304. //STEP 1: handle tags from JSON data for host overrides
  305. this.loadedGroupToOverrideSiteToTagMap = {};
  306. var configGroupsWithOverrides = selectedConfigGroup.get('isDefault') && !this.get('isHostsConfigsPage') ? this.get('configGroups') : [selectedConfigGroup];
  307. configGroupsWithOverrides.forEach(function (item) {
  308. var groupName = item.get('name');
  309. this.loadedGroupToOverrideSiteToTagMap[groupName] = {};
  310. item.get('configSiteTags').forEach(function (siteTag) {
  311. var site = siteTag.get('site');
  312. this.loadedGroupToOverrideSiteToTagMap[groupName][site] = siteTag.get('tag');
  313. }, this);
  314. }, this);
  315. //STEP 2: Create an array of objects defining tag names to be polled and new tag names to be set after submit
  316. this.setServiceConfigTags(this.loadedClusterSiteToTagMap);
  317. //STEP 3: Load advanced configs
  318. var advancedConfigs = this.get('advancedConfigs');
  319. //STEP 4: Load on-site config by service from server
  320. App.router.get('configurationController').getConfigsByTags(this.get('serviceConfigTags')).done(function(configGroups){
  321. //STEP 5: Merge on-site configs with pre-defined
  322. var configSet = App.config.mergePreDefinedWithLoaded(configGroups, advancedConfigs, self.get('serviceConfigTags'), serviceName);
  323. configSet = App.config.syncOrderWithPredefined(configSet);
  324. //var serviceConfigs = this.getSitesConfigProperties(advancedConfigs);
  325. var configs = configSet.configs;
  326. //STEP 6: add advanced configs
  327. App.config.addAdvancedConfigs(configs, advancedConfigs, serviceName);
  328. //STEP 7: add custom configs
  329. App.config.addCustomConfigs(configs);
  330. //put properties from capacity-scheduler.xml into one config with textarea view
  331. if (self.get('content.serviceName') === 'YARN' && !App.supports.capacitySchedulerUi) {
  332. configs = App.config.fileConfigsIntoTextarea(configs, 'capacity-scheduler.xml');
  333. }
  334. self.set('allConfigs', configs);
  335. //STEP 8: add configs as names of host components
  336. self.addHostNamesToConfig();
  337. //STEP load configs of version being compared against
  338. self.loadCompareVersionConfigs(self.get('allConfigs')).done(function () {
  339. //STEP 9: Load and add overriden configs of group
  340. App.config.loadServiceConfigGroupOverrides(self.get('allConfigs'), self.get('loadedGroupToOverrideSiteToTagMap'), self.get('configGroups'), self.onLoadOverrides, self);
  341. });
  342. });
  343. }.observes('selectedConfigGroup'),
  344. /**
  345. * load version configs for comparison
  346. * @param allConfigs
  347. * @return {object}
  348. */
  349. loadCompareVersionConfigs: function (allConfigs) {
  350. var dfd = $.Deferred();
  351. var self = this;
  352. var compareServiceVersion = this.get('compareServiceVersion');
  353. if (compareServiceVersion) {
  354. this.getCompareVersionConfigs(compareServiceVersion).done(function (json) {
  355. var serviceVersionMap = {};
  356. json.items[0].configurations.forEach(function (configuration) {
  357. for (var prop in configuration.properties) {
  358. serviceVersionMap[prop] = {
  359. name: prop,
  360. value: configuration.properties[prop],
  361. type: configuration.type,
  362. tag: configuration.tag,
  363. version: configuration.version
  364. }
  365. }
  366. });
  367. allConfigs.forEach(function (serviceConfig) {
  368. var compareConfig = serviceVersionMap[serviceConfig.name];
  369. if (compareConfig) {
  370. serviceConfig.compareConfig = App.ServiceConfigProperty.create(serviceConfig);
  371. serviceConfig.compareConfig.set('value', compareConfig.value);
  372. serviceConfig.compareConfig.set('serviceVersion', compareServiceVersion);
  373. serviceConfig.isComparison = true;
  374. }
  375. });
  376. self.set('compareServiceVersion', null)
  377. dfd.resolve();
  378. }).fail(function () {
  379. dfd.resolve();
  380. });
  381. } else {
  382. allConfigs.setEach('isComparison', false);
  383. dfd.resolve();
  384. }
  385. return dfd.promise();
  386. },
  387. /**
  388. * get configs of chosen version from server to compare
  389. * @param compareServiceVersion
  390. * @return {$.ajax}
  391. */
  392. getCompareVersionConfigs: function (compareServiceVersion) {
  393. return App.ajax.send({
  394. name: 'service.config.version.get',
  395. sender: this,
  396. data: {
  397. serviceVersion: compareServiceVersion,
  398. url: '/data/configurations/service_version.json'
  399. }
  400. })
  401. },
  402. checkDatabaseProperties: function (serviceConfig) {
  403. if (!['OOZIE', 'HIVE'].contains(this.get('content.serviceName'))) return;
  404. var configsToHide = ['oozie_hostname', 'hive_hostname'];
  405. configsToHide.forEach(function (configName) {
  406. var property = serviceConfig.configs.findProperty('name', configName);
  407. if (property) property.set('isVisible', false);
  408. });
  409. },
  410. onLoadOverrides: function (allConfigs) {
  411. var serviceName = this.get('content.serviceName');
  412. var advancedConfigs = this.get('advancedConfigs');
  413. //STEP 10: creation of serviceConfig object which contains configs for current service
  414. var serviceConfig = App.config.createServiceConfig(serviceName);
  415. //STEP11: Make SecondaryNameNode invisible on enabling namenode HA
  416. if (serviceConfig.get('serviceName') === 'HDFS') {
  417. App.config.OnNnHAHideSnn(serviceConfig);
  418. }
  419. if (serviceName || serviceConfig.serviceName === 'MISC') {
  420. // set recommended Defaults first then load the configs (including set validator)
  421. var s = App.StackService.find().findProperty('serviceName', this.get('content.serviceName'));
  422. var defaultsProvider = s.get('defaultsProviders');
  423. if (defaultsProvider) {
  424. this.getInfoForDefaults(defaultsProvider);
  425. } else {
  426. Em.run(this, 'setDefaults');
  427. }
  428. } else {
  429. this.set('selectedService', this.get('stepConfigs').objectAt(0));
  430. this.checkForSecureConfig(this.get('selectedService'));
  431. this.set('dataIsLoaded', true);
  432. this.set('hash', this.getHash());
  433. this.set('isInit', false);
  434. }
  435. },
  436. setDefaults: function(){
  437. var serviceConfig = App.config.createServiceConfig(this.get('content.serviceName'));
  438. this.loadConfigs(this.get('allConfigs'), serviceConfig);
  439. this.checkOverrideProperty(serviceConfig);
  440. this.checkDatabaseProperties(serviceConfig);
  441. this.get('stepConfigs').pushObject(serviceConfig);
  442. this.set('selectedService', this.get('stepConfigs').objectAt(0));
  443. this.checkForSecureConfig(this.get('selectedService'));
  444. this.set('dataIsLoaded', true);
  445. this.set('hash', this.getHash());
  446. this.set('isInit', false);
  447. }.observes('defaultsInfo'),
  448. /**
  449. * Changes format from Object to Array
  450. *
  451. * {
  452. * 'core-site': 'version1',
  453. * 'hdfs-site': 'version1',
  454. * ...
  455. * }
  456. *
  457. * to
  458. *
  459. * [
  460. * {
  461. * siteName: 'core-site',
  462. * tagName: 'version1',
  463. * newTageName: null
  464. * },
  465. * ...
  466. * ]
  467. *
  468. * set tagnames for configuration of the *-site.xml
  469. */
  470. setServiceConfigTags: function (desiredConfigsSiteTags) {
  471. console.debug("setServiceConfigTags(): Trying to set ", desiredConfigsSiteTags);
  472. var newServiceConfigTags = [];
  473. for (var index in desiredConfigsSiteTags) {
  474. newServiceConfigTags.pushObject({
  475. siteName: index,
  476. tagName: desiredConfigsSiteTags[index],
  477. newTagName: null
  478. }, this);
  479. }
  480. console.debug("setServiceConfigTags(): Setting 'serviceConfigTags' to ", newServiceConfigTags);
  481. this.set('serviceConfigTags', newServiceConfigTags);
  482. },
  483. /**
  484. * check whether the config property is a security related knob
  485. * @param serviceConfig
  486. */
  487. checkForSecureConfig: function (serviceConfig) {
  488. serviceConfig.get('configs').forEach(function (_config) {
  489. this.get('secureConfigs').forEach(function (_secureConfig) {
  490. if (_config.get('name') === _secureConfig.name) {
  491. _config.set('isSecureConfig', true);
  492. }
  493. }, this)
  494. }, this)
  495. },
  496. /**
  497. * Get info about hosts and host components to configDefaultsProviders
  498. * @returns {{masterComponentHosts: Array, slaveComponentHosts: Array, hosts: {}}}
  499. */
  500. getInfoForDefaults: function (providers) {
  501. var requiredComponents = [];
  502. providers.forEach(function (provider) {
  503. requiredComponents = provider.get('slaveHostDependency').concat(provider.get('masterHostDependency'));
  504. });
  505. if (requiredComponents.length > 0) {
  506. App.ajax.send({
  507. name: 'hosts.by_component.' + ((requiredComponents.length === 1) ? 'one' : 'all'),
  508. sender: this,
  509. data: {
  510. componentNames: requiredComponents.join(',')
  511. },
  512. success: 'getInfoForDefaultsSuccessCallback'
  513. });
  514. } else {
  515. //if no components required then slaveComponentHosts and hosts stay empty
  516. this.set('defaultsInfo', {
  517. masterComponentHosts: this.getMasterComponents(),
  518. slaveComponentHosts: [],
  519. hosts: {}
  520. });
  521. }
  522. },
  523. getInfoForDefaultsSuccessCallback: function (response) {
  524. var defaultsInfo = {
  525. masterComponentHosts: this.getMasterComponents(),
  526. slaveComponentHosts: this.getSlaveComponents(response),
  527. hosts: this.getHostsInfo(response)
  528. };
  529. this.set('defaultsInfo', defaultsInfo);
  530. this.setRecommendedDefaults(this.get('advancedConfigs'));
  531. },
  532. /**
  533. * parse json response and build slave components array
  534. * @param response
  535. * @return {Array}
  536. */
  537. getSlaveComponents: function (response) {
  538. var hostComponentMap = {};
  539. var slaves = App.StackServiceComponent.find().filterProperty('isSlave').mapProperty('componentName');
  540. var slaveComponentHosts = [];
  541. response.items.forEach(function (host) {
  542. host.host_components.forEach(function (hostComponent) {
  543. if (slaves.contains(hostComponent.HostRoles.component_name)) {
  544. if (!hostComponentMap[hostComponent.HostRoles.component_name]) {
  545. hostComponentMap[hostComponent.HostRoles.component_name] = [];
  546. }
  547. hostComponentMap[hostComponent.HostRoles.component_name].push({hostName: host.Hosts.host_name});
  548. }
  549. })
  550. });
  551. for (var componentName in hostComponentMap) {
  552. slaveComponentHosts.push({
  553. componentName: componentName,
  554. hosts: hostComponentMap[componentName]
  555. });
  556. }
  557. return slaveComponentHosts;
  558. },
  559. /**
  560. * build master components array of data from HostComponent model
  561. * @return {Array}
  562. */
  563. getMasterComponents: function () {
  564. var masterComponentHosts = [];
  565. App.HostComponent.find().filterProperty('isMaster').forEach(function (masterComponent) {
  566. masterComponentHosts.push({
  567. component: masterComponent.get('componentName'),
  568. serviceId: masterComponent.get('service.serviceName'),
  569. host: masterComponent.get('hostName')
  570. });
  571. });
  572. return masterComponentHosts;
  573. },
  574. /**
  575. * parse json response and build hosts map
  576. * @param response
  577. * @return {Object}
  578. */
  579. getHostsInfo: function (response) {
  580. var hosts = {};
  581. response.items.mapProperty('Hosts').map(function (host) {
  582. hosts[host.host_name] = {
  583. name: host.host_name,
  584. cpu: host.cpu_count,
  585. memory: host.total_mem,
  586. disk_info: host.disk_info
  587. };
  588. });
  589. return hosts;
  590. },
  591. /**
  592. * Load child components to service config object
  593. * @param {Array} configs - array of configs
  594. * @param {Object} componentConfig - component config object
  595. * @method loadConfigs
  596. */
  597. loadConfigs: function (configs, componentConfig) {
  598. var serviceConfigsData = App.StackService.find().findProperty('serviceName', this.get('content.serviceName'));
  599. var defaultGroupSelected = this.get('selectedConfigGroup.isDefault');
  600. configs.forEach(function (_serviceConfigProperty) {
  601. var serviceConfigProperty = this.createConfigProperty(_serviceConfigProperty, defaultGroupSelected, serviceConfigsData);
  602. componentConfig.configs.pushObject(serviceConfigProperty);
  603. serviceConfigProperty.validate();
  604. }, this);
  605. },
  606. /**
  607. * create {Em.Object} service_cfg_property based on {Object}_serviceConfigProperty and additional info
  608. * @param {Object} _serviceConfigProperty - config object
  609. * @param {Boolean} defaultGroupSelected - true if selected cfg group is default
  610. * @param {Object} serviceConfigsData - service cfg object
  611. * @returns {Ember.Object|null}
  612. * @method createConfigProperty
  613. */
  614. createConfigProperty: function (_serviceConfigProperty, defaultGroupSelected, serviceConfigsData) {
  615. console.log("config", _serviceConfigProperty);
  616. if (!_serviceConfigProperty) return null;
  617. var overrides = _serviceConfigProperty.overrides;
  618. // we will populate the override properties below
  619. Em.set(_serviceConfigProperty, 'overrides', null);
  620. _serviceConfigProperty.isOverridable = Em.isNone(_serviceConfigProperty.isOverridable) ? true : _serviceConfigProperty.isOverridable;
  621. var serviceConfigProperty = App.ServiceConfigProperty.create(_serviceConfigProperty);
  622. this.setValueForCheckBox(serviceConfigProperty);
  623. this.setValidator(serviceConfigProperty, serviceConfigsData);
  624. this.setValuesForOverrides(overrides, _serviceConfigProperty, serviceConfigProperty, defaultGroupSelected);
  625. this.setEditability(serviceConfigProperty, defaultGroupSelected);
  626. this.setSupportsFinal(serviceConfigProperty);
  627. return serviceConfigProperty;
  628. },
  629. /**
  630. * trigger addOverrideProperty
  631. * @param {Object} componentConfig
  632. * @method checkOverrideProperty
  633. */
  634. checkOverrideProperty: function (componentConfig) {
  635. var overrideToAdd = this.get('overrideToAdd');
  636. if (overrideToAdd) {
  637. overrideToAdd = componentConfig.configs.filter(function(c){
  638. return c.name == overrideToAdd.name && c.filename == overrideToAdd.filename;
  639. });
  640. if (overrideToAdd[0]) {
  641. this.addOverrideProperty(overrideToAdd[0]);
  642. this.set('overrideToAdd', null);
  643. }
  644. }
  645. },
  646. /**
  647. * set recommended defaults for advanced configs for current service
  648. * @param {Array} advancedConfigs
  649. * @mrethod setRecommendedDefaults
  650. */
  651. setRecommendedDefaults: function (advancedConfigs) {
  652. var s = App.StackService.find().findProperty('serviceName', this.get('content.serviceName'));
  653. var defaultsProvider = s.get('defaultsProviders');
  654. var configsValidator = s.get('configsValidator');
  655. var localDB = this.get('defaultsInfo');
  656. var recommendedDefaults = {};
  657. if (defaultsProvider) {
  658. defaultsProvider.forEach(function (defaultsProvider) {
  659. var d = defaultsProvider.getDefaults(localDB);
  660. for (var name in d) {
  661. if (!!d[name]) {
  662. recommendedDefaults[name] = d[name];
  663. } else {
  664. var defaultValueFromStack = advancedConfigs.findProperty('name', name);
  665. // If property default value is not declared on client, fetch it from stack definition
  666. // If it's not declared with any valid value in both server stack and client, then js reference error is expected to be thrown
  667. recommendedDefaults[name] = defaultValueFromStack && defaultValueFromStack.value
  668. }
  669. }
  670. });
  671. }
  672. if (configsValidator) {
  673. configsValidator.set('recommendedDefaults', recommendedDefaults);
  674. }
  675. },
  676. /**
  677. * set isEditable property of config for admin
  678. * if default cfg group and not on the host config page
  679. * @param {Ember.Object} serviceConfigProperty
  680. * @param {Boolean} defaultGroupSelected
  681. * @method setEditability
  682. */
  683. setEditability: function (serviceConfigProperty, defaultGroupSelected) {
  684. serviceConfigProperty.set('isEditable', false);
  685. if (App.get('isAdmin') && defaultGroupSelected && !this.get('isHostsConfigsPage') && !serviceConfigProperty.get('group')) {
  686. serviceConfigProperty.set('isEditable', serviceConfigProperty.get('isReconfigurable') && !serviceConfigProperty.get('isComparison'));
  687. } else if (serviceConfigProperty.get('group') && this.get('selectedConfigGroup.name') === serviceConfigProperty.get('group.name')) {
  688. serviceConfigProperty.set('isEditable', true);
  689. }
  690. },
  691. /**
  692. * set supportsFinal property of config for admin
  693. * @param {Ember.Object} serviceConfigProperty
  694. * @method setSupportsFinal
  695. */
  696. setSupportsFinal: function (serviceConfigProperty) {
  697. var fileName = serviceConfigProperty.get('filename');
  698. var matchingConfigType = this.get('configTypesInfo').supportsFinal.find(function(configType) {
  699. return fileName.startsWith(configType);
  700. });
  701. serviceConfigProperty.set('supportsFinal', !!matchingConfigType);
  702. },
  703. /**
  704. * set serviceValidator for config property
  705. * hide properties for other services
  706. * @param {Ember.Object} serviceConfigProperty
  707. * @param {Object} serviceConfigsData
  708. * @method setValidator
  709. */
  710. setValidator: function (serviceConfigProperty, serviceConfigsData) {
  711. if (serviceConfigProperty.get('serviceName') === this.get('content.serviceName')) {
  712. if (serviceConfigsData.get('configsValidator')) {
  713. for (var validatorName in serviceConfigsData.get('configsValidator.configValidators')) {
  714. if (serviceConfigProperty.get("name") == validatorName) {
  715. serviceConfigProperty.set('serviceValidator', serviceConfigsData.get('configsValidator'));
  716. }
  717. }
  718. }
  719. console.log("config result", serviceConfigProperty);
  720. } else {
  721. serviceConfigProperty.set('isVisible', false);
  722. }
  723. },
  724. /**
  725. * set override values
  726. * @param overrides
  727. * @param _serviceConfigProperty
  728. * @param serviceConfigProperty
  729. * @param defaultGroupSelected
  730. */
  731. setValuesForOverrides: function (overrides, _serviceConfigProperty, serviceConfigProperty, defaultGroupSelected) {
  732. if (Em.isNone(overrides)) return;
  733. overrides.forEach(function (override) {
  734. var newSCP = this.createNewSCP(override, _serviceConfigProperty, serviceConfigProperty, defaultGroupSelected);
  735. var parentOverridesArray = serviceConfigProperty.get('overrides');
  736. if (parentOverridesArray == null) {
  737. parentOverridesArray = Em.A([]);
  738. serviceConfigProperty.set('overrides', parentOverridesArray);
  739. }
  740. parentOverridesArray.pushObject(newSCP);
  741. console.debug("createOverrideProperty(): Added:", newSCP, " to main-property:", serviceConfigProperty)
  742. }, this);
  743. },
  744. /**
  745. * create new overridden property and set appropriate fields
  746. * @param override
  747. * @param _serviceConfigProperty
  748. * @param serviceConfigProperty
  749. * @param defaultGroupSelected
  750. * @returns {*}
  751. */
  752. createNewSCP: function (override, _serviceConfigProperty, serviceConfigProperty, defaultGroupSelected) {
  753. var newSCP = App.ServiceConfigProperty.create(_serviceConfigProperty);
  754. newSCP.set('value', override.value);
  755. newSCP.set('isOriginalSCP', false); // indicated this is overridden value,
  756. newSCP.set('parentSCP', serviceConfigProperty);
  757. if (App.supports.hostOverrides && defaultGroupSelected) {
  758. newSCP.set('group', override.group);
  759. newSCP.set('isEditable', false);
  760. }
  761. return newSCP;
  762. },
  763. /**
  764. * convert string values to boolean for checkboxes
  765. * @param {Ember.Object} serviceConfigProperty
  766. */
  767. setValueForCheckBox: function (serviceConfigProperty) {
  768. if (serviceConfigProperty.get("displayType") == 'checkbox') {
  769. switch (serviceConfigProperty.get("value")) {
  770. case 'true':
  771. serviceConfigProperty.set("value", true);
  772. serviceConfigProperty.set("defaultValue", true);
  773. break;
  774. case 'false':
  775. serviceConfigProperty.set("value", false);
  776. serviceConfigProperty.set("defaultValue", false);
  777. break;
  778. }
  779. }
  780. },
  781. /**
  782. * Initialize save configs popup
  783. */
  784. restartServicePopup: function () {
  785. if (this.get("isSubmitDisabled")) {
  786. return;
  787. }
  788. this.set("isApplyingChanges", true);
  789. var self = this;
  790. var header, message, messageClass, status;
  791. var serviceName = this.get('content.serviceName'),
  792. displayName = this.get('content.displayName'),
  793. urlParams = '';
  794. if (App.supports.hostOverrides ||
  795. (serviceName !== 'HDFS' && this.get('content.isStopped') === true) ||
  796. ((serviceName === 'HDFS') && this.get('content.isStopped') === true && (!App.Service.find().someProperty('id', 'MAPREDUCE') || App.Service.find('MAPREDUCE').get('isStopped')))) {
  797. if (this.isDirChanged()) {
  798. App.showConfirmationPopup(function () {
  799. self.saveConfigs();
  800. }, Em.I18n.t('services.service.config.confirmDirectoryChange').format(displayName), function () {
  801. self.set('isApplyingChanges', false)
  802. });
  803. } else {
  804. this.saveConfigs();
  805. }
  806. } else {
  807. status = 'started';
  808. if (this.get('content.serviceName') !== 'HDFS' || (this.get('content.serviceName') === 'HDFS' && !App.Service.find().someProperty('id', 'MAPREDUCE'))) {
  809. header = Em.I18n.t('services.service.config.notSaved');
  810. message = Em.I18n.t('services.service.config.msgServiceStop');
  811. } else {
  812. header = Em.I18n.t('services.service.config.notSaved');
  813. message = Em.I18n.t('services.service.config.msgHDFSMapRServiceStop');
  814. urlParams += '&ServiceComponentInfo/service_name.in(HDFS,MAPREDUCE)';
  815. }
  816. messageClass = 'alert alert-error';
  817. this.showSaveConfigsPopup(header, false, message, messageClass, null, status, urlParams);
  818. }
  819. },
  820. /**
  821. * Define if user has changed some dir properties
  822. * @return {Boolean}
  823. */
  824. isDirChanged: function () {
  825. var dirChanged = false;
  826. var serviceName = this.get('content.serviceName');
  827. if (serviceName === 'HDFS') {
  828. var hdfsConfigs = this.get('stepConfigs').findProperty('serviceName', 'HDFS').get('configs');
  829. if (App.get('isHadoop2Stack')) {
  830. if (hdfsConfigs.findProperty('name', 'dfs.namenode.name.dir').get('isNotDefaultValue') ||
  831. hdfsConfigs.findProperty('name', 'dfs.namenode.checkpoint.dir').get('isNotDefaultValue') ||
  832. hdfsConfigs.findProperty('name', 'dfs.datanode.data.dir').get('isNotDefaultValue')) {
  833. dirChanged = true;
  834. }
  835. } else {
  836. if (hdfsConfigs.findProperty('name', 'dfs.name.dir').get('isNotDefaultValue') ||
  837. hdfsConfigs.findProperty('name', 'fs.checkpoint.dir').get('isNotDefaultValue') ||
  838. hdfsConfigs.findProperty('name', 'dfs.data.dir').get('isNotDefaultValue')) {
  839. dirChanged = true;
  840. }
  841. }
  842. } else if (serviceName === 'MAPREDUCE') {
  843. var mapredConfigs = this.get('stepConfigs').findProperty('serviceName', 'MAPREDUCE').get('configs');
  844. if (mapredConfigs.findProperty('name', 'mapred.local.dir').get('isNotDefaultValue') ||
  845. mapredConfigs.findProperty('name', 'mapred.system.dir').get('isNotDefaultValue')) {
  846. dirChanged = true;
  847. }
  848. }
  849. return dirChanged;
  850. },
  851. /**
  852. * Save changed configs and config groups
  853. */
  854. saveConfigs: function () {
  855. var selectedConfigGroup = this.get('selectedConfigGroup');
  856. var configs = this.get('stepConfigs').findProperty('serviceName', this.get('content.serviceName')).get('configs');
  857. var self = this;
  858. if (selectedConfigGroup.get('isDefault')) {
  859. if (this.get('content.serviceName') === 'YARN' && !App.supports.capacitySchedulerUi) {
  860. configs = App.config.textareaIntoFileConfigs(configs, 'capacity-scheduler.xml');
  861. }
  862. this.saveSiteConfigs(configs.filterProperty('group', null));
  863. /**
  864. * First we put cluster configurations, which automatically creates /configurations
  865. * resources. Next we update host level overrides.
  866. */
  867. this.doPUTClusterConfigurations();
  868. } else {
  869. var overridenConfigs = [];
  870. var groupHosts = [];
  871. configs.filterProperty('isOverridden', true).forEach(function (config) {
  872. overridenConfigs = overridenConfigs.concat(config.get('overrides'));
  873. });
  874. // find custom original properties that assigned to selected config group
  875. overridenConfigs = overridenConfigs.concat(configs.filterProperty('group')
  876. .filter(function(config) { return config.get('group.name') == self.get('selectedConfigGroup.name'); }));
  877. this.formatConfigValues(overridenConfigs);
  878. selectedConfigGroup.get('hosts').forEach(function (hostName) {
  879. groupHosts.push({"host_name": hostName});
  880. });
  881. this.putConfigGroupChanges({
  882. ConfigGroup: {
  883. "id": selectedConfigGroup.get('id'),
  884. "cluster_name": App.get('clusterName'),
  885. "group_name": selectedConfigGroup.get('name'),
  886. "tag": selectedConfigGroup.get('service.id'),
  887. "description": selectedConfigGroup.get('description'),
  888. "hosts": groupHosts,
  889. "desired_configs": this.buildGroupDesiredConfigs(overridenConfigs)
  890. }
  891. }, true);
  892. }
  893. },
  894. /**
  895. * On save configs handler. Open save configs popup with appropriate message.
  896. */
  897. onDoPUTClusterConfigurations: function () {
  898. var header, message, messageClass, value, status, urlParams = '',
  899. result = {
  900. flag: this.get('saveConfigsFlag'),
  901. message: null,
  902. value: null
  903. },
  904. extendedModel = App.Service.extendedModel[this.get('content.serviceName')],
  905. currentService = extendedModel ? App[extendedModel].find(this.get('content.serviceName')) : App.Service.find(this.get('content.serviceName'));
  906. if (!result.flag) {
  907. result.message = Em.I18n.t('services.service.config.failSaveConfig');
  908. } else {
  909. if (!result.flag) {
  910. result.message = Em.I18n.t('services.service.config.failSaveConfigHostOverrides');
  911. }
  912. }
  913. App.router.get('clusterController').updateClusterData();
  914. App.router.get('updateController').updateComponentConfig(function () {
  915. });
  916. var flag = result.flag;
  917. if (result.flag === true) {
  918. header = Em.I18n.t('services.service.config.saved');
  919. message = Em.I18n.t('services.service.config.saved.message');
  920. messageClass = 'alert alert-success';
  921. // warn the user if any of the components are in UNKNOWN state
  922. status = 'unknown';
  923. urlParams += ',ServiceComponentInfo/installed_count,ServiceComponentInfo/total_count';
  924. if (this.get('content.serviceName') === 'HDFS' || App.Service.find().someProperty('id', 'MAPREDUCE')) {
  925. urlParams += '&ServiceComponentInfo/service_name.in(HDFS,MAPREDUCE)'
  926. }
  927. } else {
  928. header = Em.I18n.t('common.failure');
  929. message = result.message;
  930. messageClass = 'alert alert-error';
  931. value = result.value;
  932. }
  933. if(currentService){
  934. App.QuickViewLinks.proto().set('content', currentService);
  935. App.QuickViewLinks.proto().loadTags();
  936. }
  937. this.showSaveConfigsPopup(header, flag, message, messageClass, value, status, urlParams);
  938. },
  939. /**
  940. * Show save configs popup
  941. */
  942. showSaveConfigsPopup: function (header, flag, message, messageClass, value, status, urlParams) {
  943. var self = this;
  944. App.ModalPopup.show({
  945. header: header,
  946. primary: Em.I18n.t('ok'),
  947. secondary: null,
  948. onPrimary: function () {
  949. this.hide();
  950. if (flag) {
  951. self.loadStep();
  952. } else {
  953. self.set('isApplyingChanges', false)
  954. }
  955. },
  956. onClose: function () {
  957. this.hide();
  958. self.set('isApplyingChanges', false)
  959. },
  960. disablePrimary: true,
  961. bodyClass: Ember.View.extend({
  962. flag: flag,
  963. message: function () {
  964. return this.get('isLoaded') ? message : Em.I18n.t('services.service.config.saving.message');
  965. }.property('isLoaded'),
  966. messageClass: function () {
  967. return this.get('isLoaded') ? messageClass : 'alert alert-info';
  968. }.property('isLoaded'),
  969. setDisablePrimary: function () {
  970. this.get('parentView').set('disablePrimary', !this.get('isLoaded'));
  971. }.observes('isLoaded'),
  972. runningHosts: [],
  973. runningComponentCount: 0,
  974. unknownHosts: [],
  975. unknownComponentCount: 0,
  976. siteProperties: value,
  977. isLoaded: false,
  978. componentsFilterSuccessCallback: function (response) {
  979. var count = 0,
  980. view = this,
  981. lazyLoadHosts = function (dest) {
  982. lazyLoading.run({
  983. initSize: 20,
  984. chunkSize: 50,
  985. delay: 50,
  986. destination: dest,
  987. source: hosts,
  988. context: view
  989. });
  990. },
  991. setComponents = function (item, components) {
  992. item.host_components.forEach(function (c) {
  993. var name = c.HostRoles.host_name;
  994. if (!components[name]) {
  995. components[name] = [];
  996. } else {
  997. components[name].push(App.format.role(item.ServiceComponentInfo.component_name));
  998. }
  999. });
  1000. return components;
  1001. },
  1002. setHosts = function (components) {
  1003. var hosts = [];
  1004. Em.keys(components).forEach(function (key) {
  1005. hosts.push({
  1006. name: key,
  1007. components: components[key].join(', ')
  1008. });
  1009. });
  1010. return hosts;
  1011. },
  1012. components = {},
  1013. hosts = [];
  1014. switch (status) {
  1015. case 'unknown':
  1016. response.items.filter(function (item) {
  1017. return (item.ServiceComponentInfo.total_count > item.ServiceComponentInfo.started_count + item.ServiceComponentInfo.installed_count);
  1018. }).forEach(function (item) {
  1019. var total = item.ServiceComponentInfo.total_count,
  1020. started = item.ServiceComponentInfo.started_count,
  1021. installed = item.ServiceComponentInfo.installed_count,
  1022. unknown = total - started + installed;
  1023. components = setComponents(item, components);
  1024. count += unknown;
  1025. });
  1026. hosts = setHosts(components);
  1027. this.set('unknownComponentCount', count);
  1028. lazyLoadHosts(this.get('unknownHosts'));
  1029. break;
  1030. case 'started':
  1031. response.items.filterProperty('ServiceComponentInfo.started_count').forEach(function (item) {
  1032. var started = item.ServiceComponentInfo.started_count;
  1033. components = setComponents(item, components);
  1034. count += started;
  1035. hosts = setHosts(components);
  1036. });
  1037. this.set('runningComponentCount', count);
  1038. lazyLoadHosts(this.get('runningHosts'));
  1039. break;
  1040. }
  1041. },
  1042. componentsFilterErrorCallback: function () {
  1043. this.set('isLoaded', true);
  1044. },
  1045. didInsertElement: function () {
  1046. App.ajax.send({
  1047. name: 'components.filter_by_status',
  1048. sender: this,
  1049. data: {
  1050. clusterName: App.get('clusterName'),
  1051. urlParams: urlParams
  1052. },
  1053. success: 'componentsFilterSuccessCallback',
  1054. error: 'componentsFilterErrorCallback'
  1055. });
  1056. },
  1057. getDisplayMessage: function () {
  1058. var displayMsg = [];
  1059. var siteProperties = this.get('siteProperties');
  1060. if (siteProperties) {
  1061. siteProperties.forEach(function (_siteProperty) {
  1062. var displayProperty = _siteProperty.siteProperty;
  1063. var displayNames = _siteProperty.displayNames;
  1064. if (displayNames && displayNames.length) {
  1065. if (displayNames.length === 1) {
  1066. displayMsg.push(displayProperty + Em.I18n.t('as') + displayNames[0]);
  1067. } else {
  1068. var name;
  1069. displayNames.forEach(function (_name, index) {
  1070. if (index === 0) {
  1071. name = _name;
  1072. } else if (index === siteProperties.length - 1) {
  1073. name = name + Em.I18n.t('and') + _name;
  1074. } else {
  1075. name = name + ', ' + _name;
  1076. }
  1077. }, this);
  1078. displayMsg.push(displayProperty + Em.I18n.t('as') + name);
  1079. }
  1080. } else {
  1081. displayMsg.push(displayProperty);
  1082. }
  1083. }, this);
  1084. }
  1085. return displayMsg;
  1086. }.property('siteProperties'),
  1087. runningHostsMessage: function () {
  1088. return Em.I18n.t('services.service.config.stopService.runningHostComponents').format(this.get('runningComponentCount'), this.get('runningHosts.length'));
  1089. }.property('runningComponentCount', 'runningHosts.length'),
  1090. unknownHostsMessage: function () {
  1091. return Em.I18n.t('services.service.config.stopService.unknownHostComponents').format(this.get('unknownComponentCount'), this.get('unknownHosts.length'));
  1092. }.property('unknownComponentCount', 'unknownHosts.length'),
  1093. templateName: require('templates/main/service/info/configs_save_popup')
  1094. })
  1095. })
  1096. },
  1097. /**
  1098. * construct desired_configs for config groups from overriden properties
  1099. * @param configs
  1100. * @param timeTag
  1101. * @return {Array}
  1102. */
  1103. buildGroupDesiredConfigs: function (configs, timeTag) {
  1104. var sites = [];
  1105. var time = timeTag || (new Date).getTime();
  1106. var siteFileNames = configs.mapProperty('filename');
  1107. sites = siteFileNames.map(function (filename) {
  1108. return {
  1109. type: filename.replace('.xml', ''),
  1110. tag: 'version' + time,
  1111. properties: []
  1112. };
  1113. });
  1114. configs.forEach(function (config) {
  1115. var type = config.get('filename').replace('.xml', '');
  1116. var site = sites.findProperty('type', type);
  1117. site.properties.push(config);
  1118. });
  1119. return sites.map(function (site) {
  1120. return this.createSiteObj(site.type, site.tag, site.properties);
  1121. }, this);
  1122. },
  1123. /**
  1124. * persist properties of config groups to server
  1125. * show result popup if <code>showPopup</code> is true
  1126. * @param data {Object}
  1127. * @param showPopup {Boolean}
  1128. */
  1129. putConfigGroupChanges: function (data, showPopup) {
  1130. var ajaxOptions = {
  1131. name: 'config_groups.update_config_group',
  1132. sender: this,
  1133. data: {
  1134. id: data.ConfigGroup.id,
  1135. configGroup: data
  1136. }
  1137. };
  1138. if (showPopup) {
  1139. ajaxOptions.success = "putConfigGroupChangesSuccess";
  1140. }
  1141. App.ajax.send(ajaxOptions);
  1142. },
  1143. putConfigGroupChangesSuccess: function () {
  1144. this.set('saveConfigsFlag', true);
  1145. this.onDoPUTClusterConfigurations();
  1146. },
  1147. /**
  1148. * set hive hostnames in configs
  1149. * @param configs
  1150. */
  1151. setHiveHostName: function (configs) {
  1152. if (configs.someProperty('name', 'hive_database')) {
  1153. var hiveDb = configs.findProperty('name', 'hive_database');
  1154. if (hiveDb.value === 'New MySQL Database') {
  1155. var ambariHost = configs.findProperty('name', 'hive_ambari_host');
  1156. if (ambariHost) {
  1157. ambariHost.name = 'hive_hostname';
  1158. }
  1159. configs = configs.without(configs.findProperty('name', 'hive_existing_mysql_host'));
  1160. configs = configs.without(configs.findProperty('name', 'hive_existing_mysql_database'));
  1161. configs = configs.without(configs.findProperty('name', 'hive_existing_oracle_host'));
  1162. configs = configs.without(configs.findProperty('name', 'hive_existing_oracle_database'));
  1163. configs = configs.without(configs.findProperty('name', 'hive_existing_postgresql_host'));
  1164. configs = configs.without(configs.findProperty('name', 'hive_existing_postgresql_database'));
  1165. } else if (hiveDb.value === 'Existing MySQL Database') {
  1166. var existingMySqlHost = configs.findProperty('name', 'hive_existing_mysql_host');
  1167. if (existingMySqlHost) {
  1168. existingMySqlHost.name = 'hive_hostname';
  1169. }
  1170. configs = configs.without(configs.findProperty('name', 'hive_ambari_host'));
  1171. configs = configs.without(configs.findProperty('name', 'hive_ambari_database'));
  1172. configs = configs.without(configs.findProperty('name', 'hive_existing_oracle_host'));
  1173. configs = configs.without(configs.findProperty('name', 'hive_existing_oracle_database'));
  1174. configs = configs.without(configs.findProperty('name', 'hive_existing_postgresql_host'));
  1175. configs = configs.without(configs.findProperty('name', 'hive_existing_postgresql_database'));
  1176. } else if (hiveDb.value === Em.I18n.t('services.service.config.hive.oozie.postgresql')) {
  1177. var existingPostgreSqlHost = configs.findProperty('name', 'hive_existing_postgresql_host');
  1178. if (existingPostgreSqlHost) {
  1179. existingPostgreSqlHost.name = 'hive_hostname';
  1180. }
  1181. configs = configs.without(configs.findProperty('name', 'hive_ambari_host'));
  1182. configs = configs.without(configs.findProperty('name', 'hive_ambari_database'));
  1183. configs = configs.without(configs.findProperty('name', 'hive_existing_mysql_host'));
  1184. configs = configs.without(configs.findProperty('name', 'hive_existing_mysql_database'));
  1185. configs = configs.without(configs.findProperty('name', 'hive_existing_oracle_host'));
  1186. configs = configs.without(configs.findProperty('name', 'hive_existing_oracle_database'));
  1187. }
  1188. else { //existing oracle database
  1189. var existingOracleHost = configs.findProperty('name', 'hive_existing_oracle_host');
  1190. if (existingOracleHost) {
  1191. existingOracleHost.name = 'hive_hostname';
  1192. }
  1193. configs = configs.without(configs.findProperty('name', 'hive_ambari_host'));
  1194. configs = configs.without(configs.findProperty('name', 'hive_ambari_database'));
  1195. configs = configs.without(configs.findProperty('name', 'hive_existing_mysql_host'));
  1196. configs = configs.without(configs.findProperty('name', 'hive_existing_mysql_database'));
  1197. configs = configs.without(configs.findProperty('name', 'hive_existing_postgresql_host'));
  1198. configs = configs.without(configs.findProperty('name', 'hive_existing_postgresql_database'));
  1199. }
  1200. }
  1201. },
  1202. /**
  1203. * set oozie hostnames in configs
  1204. * @param configs
  1205. */
  1206. setOozieHostName: function (configs) {
  1207. var dbHostPropertyName = null;
  1208. if (configs.someProperty('name', 'oozie_database')) {
  1209. var oozieDb = configs.findProperty('name', 'oozie_database');
  1210. if (oozieDb.value === 'New Derby Database') {
  1211. configs = configs.without(configs.findProperty('name', 'oozie_ambari_host'));
  1212. configs = configs.without(configs.findProperty('name', 'oozie_ambari_database'));
  1213. configs = configs.without(configs.findProperty('name', 'oozie_existing_mysql_host'));
  1214. configs = configs.without(configs.findProperty('name', 'oozie_existing_mysql_database'));
  1215. configs = configs.without(configs.findProperty('name', 'oozie_existing_oracle_host'));
  1216. configs = configs.without(configs.findProperty('name', 'oozie_existing_oracle_database'));
  1217. configs = configs.without(configs.findProperty('name', 'oozie_existing_postgresql_host'));
  1218. configs = configs.without(configs.findProperty('name', 'oozie_existing_postgresql_database'));
  1219. } else if (oozieDb.value === 'New MySQL Database') {
  1220. var ambariHost = configs.findProperty('name', 'oozie_ambari_host');
  1221. if (ambariHost) {
  1222. ambariHost.name = 'oozie_hostname';
  1223. }
  1224. configs = configs.without(configs.findProperty('name', 'oozie_existing_mysql_host'));
  1225. configs = configs.without(configs.findProperty('name', 'oozie_existing_mysql_database'));
  1226. configs = configs.without(configs.findProperty('name', 'oozie_existing_oracle_host'));
  1227. configs = configs.without(configs.findProperty('name', 'oozie_existing_oracle_database'));
  1228. configs = configs.without(configs.findProperty('name', 'oozie_derby_database'));
  1229. configs = configs.without(configs.findProperty('name', 'oozie_existing_postgresql_host'));
  1230. configs = configs.without(configs.findProperty('name', 'oozie_existing_postgresql_database'));
  1231. } else if (oozieDb.value === 'Existing MySQL Database') {
  1232. var existingMySqlHost = configs.findProperty('name', 'oozie_existing_mysql_host');
  1233. if (existingMySqlHost) {
  1234. dbHostPropertyName = 'oozie_existing_mysql_host';
  1235. }
  1236. configs = configs.without(configs.findProperty('name', 'oozie_ambari_host'));
  1237. configs = configs.without(configs.findProperty('name', 'oozie_ambari_database'));
  1238. configs = configs.without(configs.findProperty('name', 'oozie_existing_oracle_host'));
  1239. configs = configs.without(configs.findProperty('name', 'oozie_existing_oracle_database'));
  1240. configs = configs.without(configs.findProperty('name', 'oozie_derby_database'));
  1241. configs = configs.without(configs.findProperty('name', 'oozie_existing_postgresql_host'));
  1242. configs = configs.without(configs.findProperty('name', 'oozie_existing_postgresql_database'));
  1243. } else if (oozieDb.value === Em.I18n.t('services.service.config.hive.oozie.postgresql')) {
  1244. var existingPostgreSqlHost = configs.findProperty('name', 'oozie_existing_postgresql_host');
  1245. if (existingPostgreSqlHost) {
  1246. dbHostPropertyName = 'oozie_existing_postgresql_host';
  1247. }
  1248. configs = configs.without(configs.findProperty('name', 'oozie_ambari_host'));
  1249. configs = configs.without(configs.findProperty('name', 'oozie_ambari_database'));
  1250. configs = configs.without(configs.findProperty('name', 'oozie_existing_mysql_host'));
  1251. configs = configs.without(configs.findProperty('name', 'oozie_existing_mysql_database'));
  1252. configs = configs.without(configs.findProperty('name', 'oozie_existing_oracle_host'));
  1253. configs = configs.without(configs.findProperty('name', 'oozie_existing_oracle_database'));
  1254. }
  1255. else { //existing oracle database
  1256. var existingOracleHost = configs.findProperty('name', 'oozie_existing_oracle_host');
  1257. if (existingOracleHost) {
  1258. dbHostPropertyName = 'oozie_existing_oracle_host';
  1259. }
  1260. configs = configs.without(configs.findProperty('name', 'oozie_ambari_host'));
  1261. configs = configs.without(configs.findProperty('name', 'oozie_ambari_database'));
  1262. configs = configs.without(configs.findProperty('name', 'oozie_existing_mysql_host'));
  1263. configs = configs.without(configs.findProperty('name', 'oozie_existing_mysql_database'));
  1264. configs = configs.without(configs.findProperty('name', 'oozie_derby_database'));
  1265. }
  1266. }
  1267. if (dbHostPropertyName) {
  1268. var oozieHostNameProperty = App.ServiceConfigProperty.create(App.config.get('preDefinedSiteProperties').findProperty('name', 'oozie_hostname'));
  1269. oozieHostNameProperty.set('value', configs.findProperty('name', dbHostPropertyName).get('value'));
  1270. configs.pushObject(oozieHostNameProperty);
  1271. }
  1272. },
  1273. /**
  1274. * save site configs
  1275. * @param configs
  1276. */
  1277. saveSiteConfigs: function (configs) {
  1278. //storedConfigs contains custom configs as well
  1279. this.setHiveHostName(configs);
  1280. this.setOozieHostName(configs);
  1281. this.formatConfigValues(configs);
  1282. var mappedConfigs = App.config.excludeUnsupportedConfigs(this.get('configMapping').all(), App.Service.find().mapProperty('serviceName'));
  1283. var allUiConfigs = this.loadUiSideConfigs(mappedConfigs);
  1284. this.set('uiConfigs', configs.concat(allUiConfigs));
  1285. },
  1286. formatConfigValues: function (serviceConfigProperties) {
  1287. serviceConfigProperties.forEach(function (_config) {
  1288. if (typeof _config.get('value') === "boolean") _config.set('value', _config.value.toString());
  1289. _config.set('value', App.config.trimProperty(_config, true));
  1290. });
  1291. },
  1292. /**
  1293. * return configs from the UI side
  1294. * @param configMapping array with configs
  1295. * @return {Array}
  1296. */
  1297. loadUiSideConfigs: function (configMapping) {
  1298. var uiConfig = [];
  1299. var configs = configMapping.filterProperty('foreignKey', null);
  1300. this.addDynamicProperties(configs);
  1301. configs.forEach(function (_config) {
  1302. var valueWithOverrides = this.getGlobConfigValueWithOverrides(_config.templateName, _config.value);
  1303. if (valueWithOverrides !== null) {
  1304. uiConfig.pushObject({
  1305. "id": "site property",
  1306. "name": _config.name,
  1307. "value": valueWithOverrides.value,
  1308. "filename": _config.filename,
  1309. "overrides": valueWithOverrides.overrides
  1310. });
  1311. }
  1312. }, this);
  1313. return uiConfig;
  1314. },
  1315. addDynamicProperties: function (configs) {
  1316. var allConfigs = this.get('stepConfigs').findProperty('serviceName', this.get('content.serviceName')).get('configs');
  1317. var templetonHiveProperty = allConfigs.someProperty('name', 'templeton.hive.properties');
  1318. if (!templetonHiveProperty && this.get('content.serviceName') === 'WEBHCAT') {
  1319. configs.pushObject({
  1320. "name": "templeton.hive.properties",
  1321. "templateName": ["hivemetastore_host"],
  1322. "foreignKey": null,
  1323. "value": "hive.metastore.local=false,hive.metastore.uris=thrift://<templateName[0]>:9083,hive.metastore.sasl.enabled=yes,hive.metastore.execute.setugi=true,hive.metastore.warehouse.dir=/apps/hive/warehouse",
  1324. "filename": "webhcat-site.xml"
  1325. });
  1326. }
  1327. },
  1328. /**
  1329. * return config value
  1330. * @param templateName
  1331. * @param expression
  1332. * @return {Object}
  1333. * example: <code>{
  1334. * value: '...',
  1335. * overrides: {
  1336. * 'value1': [h1, h2],
  1337. * 'value2': [h3]
  1338. * }
  1339. * }</code>
  1340. */
  1341. getGlobConfigValueWithOverrides: function (templateName, expression) {
  1342. var express = expression.match(/<(.*?)>/g);
  1343. var value = expression;
  1344. var overrideHostToValue = {};
  1345. if (express != null) {
  1346. express.forEach(function (_express) {
  1347. var index = parseInt(_express.match(/\[([\d]*)(?=\])/)[1]);
  1348. var globalObj = this.get('allConfigs').findProperty('name', templateName[index]);
  1349. if (globalObj) {
  1350. var globOverride = globalObj.overrides;
  1351. if (globOverride != null) {
  1352. for (var ov in globOverride) {
  1353. globOverride[ov].forEach(function (host) {
  1354. var replacedVal = (host in overrideHostToValue) ? overrideHostToValue[host] : expression;
  1355. overrideHostToValue[host] = replacedVal.replace(_express, ov);
  1356. }, this);
  1357. }
  1358. }
  1359. value = expression.replace(_express, globalObj.value);
  1360. } else {
  1361. value = null;
  1362. }
  1363. }, this);
  1364. }
  1365. return this.getValueWithOverrides(value, overrideHostToValue)
  1366. },
  1367. getValueWithOverrides: function (value, overrideHostToValue) {
  1368. var valueWithOverrides = {
  1369. value: value,
  1370. overrides: {}
  1371. };
  1372. if (!jQuery.isEmptyObject(overrideHostToValue)) {
  1373. for (var host in overrideHostToValue) {
  1374. var hostVal = overrideHostToValue[host];
  1375. if (!(hostVal in valueWithOverrides.overrides)) {
  1376. valueWithOverrides.overrides[hostVal] = [];
  1377. }
  1378. valueWithOverrides.overrides[hostVal].push(host);
  1379. }
  1380. }
  1381. return valueWithOverrides;
  1382. },
  1383. /**
  1384. * Saves cluster level configurations for all necessary sites.
  1385. * PUT calls are made to /api/v1/clusters/clusterName for each site.
  1386. * @return {Boolean}
  1387. * @method doPUTClusterConfigurations
  1388. */
  1389. doPUTClusterConfigurations: function () {
  1390. this.set('saveConfigsFlag', true);
  1391. var serviceConfigTags = this.get('serviceConfigTags');
  1392. this.setNewTagNames(serviceConfigTags);
  1393. var siteNameToServerDataMap = {};
  1394. this.set('putClusterConfigsCallsNumber', serviceConfigTags.length);
  1395. serviceConfigTags.forEach(function (_serviceTags) {
  1396. var configs = this.createConfigObject(_serviceTags.siteName, _serviceTags.newTagName);
  1397. if (configs) {
  1398. this.doPUTClusterConfiguration(_serviceTags.siteName, configs);
  1399. siteNameToServerDataMap[_serviceTags.siteName] = configs;
  1400. } else {
  1401. if (this.decrementProperty('putClusterConfigsCallsNumber') === 0) {
  1402. this.onDoPUTClusterConfigurations();
  1403. }
  1404. }
  1405. }, this);
  1406. this.set("savedSiteNameToServerServiceConfigDataMap", siteNameToServerDataMap);
  1407. },
  1408. /**
  1409. * create different config object depending on siteName
  1410. * @param {String} siteName
  1411. * @param {String} tagName
  1412. * @returns {Object|null}
  1413. * @method createConfigObject
  1414. */
  1415. createConfigObject: function (siteName, tagName) {
  1416. console.log("TRACE: Inside " + siteName);
  1417. var configObject;
  1418. switch (siteName) {
  1419. case 'core-site':
  1420. if (this.get('content.serviceName') === 'HDFS' || this.get('content.serviceName') === 'GLUSTERFS') {
  1421. configObject = this.createCoreSiteObj(tagName);
  1422. } else {
  1423. return null;
  1424. }
  1425. break;
  1426. default:
  1427. var filename = (App.config.get('filenameExceptions').contains(siteName)) ? siteName : siteName + '.xml';
  1428. if (filename === 'mapred-queue-acls.xml' && !App.supports.capacitySchedulerUi) {
  1429. return null;
  1430. }
  1431. return this.createSiteObj(siteName, tagName, this.get('uiConfigs').filterProperty('filename', filename));
  1432. }
  1433. return configObject;
  1434. },
  1435. /**
  1436. * load existen properties and compare them with current if there are
  1437. * differences - trigger doPUTClusterConfigurationSite to save new properties
  1438. * @param {String} siteName
  1439. * @param {Object} newConfig
  1440. * @method doPUTClusterConfiguration
  1441. */
  1442. doPUTClusterConfiguration: function (siteName, newConfig) {
  1443. var oldConfig = App.router.get('configurationController').getConfigsByTags([
  1444. {siteName: siteName, tagName: this.loadedClusterSiteToTagMap[siteName]}
  1445. ]);
  1446. oldConfig = oldConfig[0] || {};
  1447. var oldProperties = oldConfig.properties || {};
  1448. var oldAttributes = oldConfig["properties_attributes"] || {};
  1449. var newProperties = newConfig.properties || {};
  1450. var newAttributes = newConfig["properties_attributes"] || {};
  1451. if (this.isAttributesChanged(oldAttributes, newAttributes) || this.isConfigChanged(oldProperties, newProperties)) {
  1452. this.doPUTClusterConfigurationSite(newConfig);
  1453. } else {
  1454. if (this.decrementProperty('putClusterConfigsCallsNumber') === 0) {
  1455. this.onDoPUTClusterConfigurations();
  1456. }
  1457. }
  1458. },
  1459. /**
  1460. * Compares the loaded config values with the saving config values.
  1461. * @param {Object} loadedConfig -
  1462. * loadedConfig: {
  1463. * configName1: "configValue1",
  1464. * configName2: "configValue2"
  1465. * }
  1466. * @param {Object} savingConfig
  1467. * savingConfig: {
  1468. * configName1: "configValue1",
  1469. * configName2: "configValue2"
  1470. * }
  1471. * @returns {boolean}
  1472. * @method isConfigChanged
  1473. */
  1474. isConfigChanged: function (loadedConfig, savingConfig) {
  1475. if (loadedConfig != null && savingConfig != null) {
  1476. var seenLoadKeys = [];
  1477. for (var loadKey in loadedConfig) {
  1478. if (!loadedConfig.hasOwnProperty(loadKey)) continue;
  1479. seenLoadKeys.push(loadKey);
  1480. var loadValue = loadedConfig[loadKey];
  1481. var saveValue = savingConfig[loadKey];
  1482. if ("boolean" == typeof(saveValue)) {
  1483. saveValue = saveValue.toString();
  1484. }
  1485. if (saveValue == null) {
  1486. saveValue = "null";
  1487. }
  1488. if (loadValue !== saveValue) {
  1489. return true;
  1490. }
  1491. }
  1492. for (var saveKey in savingConfig) {
  1493. if (seenLoadKeys.indexOf(saveKey) < 0) {
  1494. return true;
  1495. }
  1496. }
  1497. }
  1498. return false;
  1499. },
  1500. /**
  1501. * Compares the loaded config properties attributes with the saving config properties attributes.
  1502. * @param {Object} oldAttributes -
  1503. * oldAttributes: {
  1504. * supports: {
  1505. * final: {
  1506. * "configValue1" : "true",
  1507. * "configValue2" : "true"
  1508. * }
  1509. * }
  1510. * }
  1511. * @param {Object} newAttributes
  1512. * newAttributes: {
  1513. * supports: {
  1514. * final: {
  1515. * "configValue1" : "true",
  1516. * "configValue2" : "true"
  1517. * }
  1518. * }
  1519. * }
  1520. * @returns {boolean}
  1521. * @method isConfigChanged
  1522. */
  1523. isAttributesChanged: function (oldAttributes, newAttributes) {
  1524. oldAttributes = oldAttributes.final || {};
  1525. newAttributes = newAttributes.final || {};
  1526. var key;
  1527. for (key in oldAttributes) {
  1528. if (oldAttributes.hasOwnProperty(key)
  1529. && (!newAttributes.hasOwnProperty(key) || newAttributes[key] !== oldAttributes[key])) {
  1530. return true;
  1531. }
  1532. }
  1533. for (key in newAttributes) {
  1534. if (newAttributes.hasOwnProperty(key)
  1535. && (!oldAttributes.hasOwnProperty(key) || newAttributes[key] !== oldAttributes[key])) {
  1536. return true;
  1537. }
  1538. }
  1539. return false;
  1540. },
  1541. /**
  1542. * Saves configuration of a particular site. The provided data
  1543. * contains the site name and tag to be used.
  1544. * @param {Object} data
  1545. * @method doPUTClusterConfigurationSite
  1546. */
  1547. doPUTClusterConfigurationSite: function (data) {
  1548. App.ajax.send({
  1549. name: 'config.cluster_configuration.put',
  1550. sender: this,
  1551. data: {
  1552. data: JSON.stringify({
  1553. Clusters: {
  1554. desired_config: data
  1555. }
  1556. }),
  1557. cluster: App.router.getClusterName()
  1558. },
  1559. success: 'doPUTClusterConfigurationSiteSuccessCallback',
  1560. error: 'doPUTClusterConfigurationSiteErrorCallback'
  1561. });
  1562. },
  1563. doPUTClusterConfigurationSiteSuccessCallback: function () {
  1564. if (this.decrementProperty('putClusterConfigsCallsNumber') === 0) {
  1565. this.onDoPUTClusterConfigurations();
  1566. }
  1567. },
  1568. doPUTClusterConfigurationSiteErrorCallback: function () {
  1569. this.set('saveConfigsFlag', false);
  1570. this.doPUTClusterConfigurationSiteSuccessCallback();
  1571. },
  1572. /**
  1573. * add newTagName property to each config in serviceConfigs
  1574. * @param serviceConfigs
  1575. */
  1576. setNewTagNames: function (serviceConfigs) {
  1577. var time = (new Date).getTime();
  1578. serviceConfigs.forEach(function (_serviceConfigs) {
  1579. _serviceConfigs.newTagName = 'version' + time;
  1580. }, this);
  1581. },
  1582. /**
  1583. * Save "final" attribute for properties
  1584. * @param {Array} properties - array of properties
  1585. * @returns {Object|null}
  1586. * */
  1587. getConfigAttributes: function(properties) {
  1588. var attributes = {
  1589. final: {}
  1590. };
  1591. var finalAttributes = attributes.final;
  1592. var hasAttributes = false;
  1593. properties.forEach(function (property) {
  1594. if (property.isRequiredByAgent !== false && property.isFinal) {
  1595. hasAttributes = true;
  1596. finalAttributes[property.name] = "true";
  1597. }
  1598. });
  1599. if (hasAttributes) {
  1600. return attributes;
  1601. }
  1602. return null;
  1603. },
  1604. /**
  1605. * create core site object
  1606. * @param tagName
  1607. * @return {{"type": String, "tag": String, "properties": Object}}
  1608. * @method createCoreSiteObj
  1609. */
  1610. createCoreSiteObj: function (tagName) {
  1611. var coreSiteObj = this.get('uiConfigs').filterProperty('filename', 'core-site.xml');
  1612. var coreSiteProperties = {};
  1613. coreSiteObj.forEach(function (_coreSiteObj) {
  1614. coreSiteProperties[_coreSiteObj.name] = App.config.escapeXMLCharacters(_coreSiteObj.value);
  1615. //this.recordHostOverride(_coreSiteObj, 'core-site', tagName, this);
  1616. }, this);
  1617. var result = {"type": "core-site", "tag": tagName, "properties": coreSiteProperties};
  1618. var attributes = this.getConfigAttributes(coreSiteObj);
  1619. if (attributes) {
  1620. result['properties_attributes'] = attributes;
  1621. }
  1622. return result;
  1623. },
  1624. /**
  1625. * create site object
  1626. * @param siteName
  1627. * @param tagName
  1628. * @param siteObj
  1629. * @return {Object}
  1630. */
  1631. createSiteObj: function (siteName, tagName, siteObj) {
  1632. var heapsizeException = ['hadoop_heapsize', 'yarn_heapsize', 'nodemanager_heapsize', 'resourcemanager_heapsize', 'apptimelineserver_heapsize', 'jobhistory_heapsize'];
  1633. var siteProperties = {};
  1634. siteObj.forEach(function (_siteObj) {
  1635. if (_siteObj.isRequiredByAgent == false) return;
  1636. if (/_heapsize|_newsize|_maxnewsize$/.test(_siteObj.name) && !heapsizeException.contains(_siteObj.name)) {
  1637. Em.set(_siteObj, "value", _siteObj.value + "m");
  1638. }
  1639. siteProperties[_siteObj.name] = App.config.escapeXMLCharacters(_siteObj.value);
  1640. switch (siteName) {
  1641. case 'falcon-startup.properties':
  1642. case 'falcon-runtime.properties':
  1643. case 'pig-properties':
  1644. siteProperties[_siteObj.name] = _siteObj.value;
  1645. break;
  1646. default:
  1647. siteProperties[_siteObj.name] = this.setServerConfigValue(_siteObj.name, _siteObj.value);
  1648. }
  1649. }, this);
  1650. var result = {"type": siteName, "tag": tagName, "properties": siteProperties};
  1651. var attributes = this.getConfigAttributes(siteObj);
  1652. if (attributes) {
  1653. result['properties_attributes'] = attributes;
  1654. }
  1655. return result;
  1656. },
  1657. /**
  1658. * This method will be moved to config's decorators class.
  1659. *
  1660. * For now, provide handling for special properties that need
  1661. * be specified in special format required for server.
  1662. *
  1663. * @param configName {String} - name of config property
  1664. * @param value {Mixed} - value of config property
  1665. *
  1666. * @return {String} - formated value
  1667. */
  1668. setServerConfigValue: function (configName, value) {
  1669. switch (configName) {
  1670. case 'storm.zookeeper.servers':
  1671. if( Object.prototype.toString.call( value ) === '[object Array]' ) {
  1672. return JSON.stringify(value).replace(/"/g, "'");
  1673. } else {
  1674. return value;
  1675. }
  1676. break;
  1677. case 'content':
  1678. return value;
  1679. break;
  1680. default:
  1681. return App.config.escapeXMLCharacters(value);
  1682. }
  1683. },
  1684. /**
  1685. * Array of Objects
  1686. * {
  1687. * hostProperty - hostName property name for current component
  1688. * componentName - master componentName
  1689. * serviceName - serviceName of component
  1690. * serviceUseThis - services that use hostname property of component(componentName)
  1691. * m(multiple) - true if can be more than one components installed on cluster
  1692. * }
  1693. */
  1694. hostComponentsmapping: [
  1695. {
  1696. hostProperty: 'snamenode_host',
  1697. componentName: 'SECONDARY_NAMENODE',
  1698. serviceName: 'HDFS',
  1699. serviceUseThis: []
  1700. },
  1701. {
  1702. hostProperty: 'jobtracker_host',
  1703. componentName: 'JOBTRACKER',
  1704. serviceName: 'MAPREDUCE',
  1705. serviceUseThis: []
  1706. },
  1707. {
  1708. hostProperty: 'jobtracker_host',
  1709. componentName: 'JOBTRACKER',
  1710. serviceName: 'MAPREDUCE2',
  1711. serviceUseThis: []
  1712. },
  1713. {
  1714. hostProperty: 'hs_host',
  1715. componentName: 'HISTORYSERVER',
  1716. serviceName: 'MAPREDUCE2',
  1717. serviceUseThis: ['YARN']
  1718. },
  1719. {
  1720. hostProperty: 'ats_host',
  1721. componentName: 'APP_TIMELINE_SERVER',
  1722. serviceName: 'YARN',
  1723. serviceUseThis: []
  1724. },
  1725. {
  1726. hostProperty: 'rm_host',
  1727. componentName: 'RESOURCEMANAGER',
  1728. serviceName: 'YARN',
  1729. serviceUseThis: []
  1730. },
  1731. {
  1732. hostProperty: 'hivemetastore_host',
  1733. componentName: 'HIVE_SERVER',
  1734. serviceName: 'HIVE',
  1735. serviceUseThis: ['WEBHCAT']
  1736. },
  1737. {
  1738. hostProperty: 'oozieserver_host',
  1739. componentName: 'OOZIE_SERVER',
  1740. serviceName: 'OOZIE',
  1741. serviceUseThis: []
  1742. },
  1743. {
  1744. hostProperty: 'hbasemaster_host',
  1745. componentName: 'HBASE_MASTER',
  1746. serviceName: 'HBASE',
  1747. serviceUseThis: [],
  1748. m: true
  1749. },
  1750. {
  1751. hostProperty: 'hueserver_host',
  1752. componentName: 'HUE_SERVER',
  1753. serviceName: 'HUE',
  1754. serviceUseThis: []
  1755. },
  1756. {
  1757. hostProperty: 'webhcatserver_host',
  1758. componentName: 'WEBHCAT_SERVER',
  1759. serviceName: 'WEBHCAT',
  1760. serviceUseThis: [],
  1761. m: true
  1762. },
  1763. {
  1764. hostProperty: 'zookeeperserver_hosts',
  1765. componentName: 'ZOOKEEPER_SERVER',
  1766. serviceName: 'ZOOKEEPER',
  1767. serviceUseThis: ['HBASE', 'WEBHCAT'],
  1768. m: true
  1769. },
  1770. {
  1771. hostProperty: 'stormuiserver_host',
  1772. componentName: 'STORM_UI_SERVER',
  1773. serviceName: 'STORM',
  1774. serviceUseThis: []
  1775. },
  1776. {
  1777. hostProperty: 'drpcserver_host',
  1778. componentName: 'DRPC_SERVER',
  1779. serviceName: 'STORM',
  1780. serviceUseThis: []
  1781. },
  1782. {
  1783. hostProperty: 'storm_rest_api_host',
  1784. componentName: 'STORM_REST_API',
  1785. serviceName: 'STORM',
  1786. serviceUseThis: []
  1787. },
  1788. {
  1789. hostProperty: 'supervisor_hosts',
  1790. componentName: 'SUPERVISOR',
  1791. serviceName: 'STORM',
  1792. serviceUseThis: [],
  1793. m: true
  1794. }
  1795. ],
  1796. /**
  1797. * Adds host name of master component to config;
  1798. * @method addHostNamesToGlobalConfig
  1799. */
  1800. addHostNamesToConfig: function () {
  1801. var serviceName = this.get('content.serviceName');
  1802. var configs = this.get('allConfigs');
  1803. //namenode_host is required to derive "fs.default.name" a property of core-site
  1804. try {
  1805. this.setHostForService('HDFS', 'NAMENODE', 'namenode_host', true);
  1806. } catch (err) {
  1807. console.log("No NameNode Host available. This is expected if you're using GLUSTERFS rather than HDFS.");
  1808. }
  1809. var hostProperties = this.get('hostComponentsmapping').filter(function (h) {
  1810. return h.serviceUseThis.contains(serviceName) || h.serviceName == serviceName;
  1811. });
  1812. hostProperties.forEach(function (h) {
  1813. this.setHostForService(h.serviceName, h.componentName, h.hostProperty, h.m);
  1814. }, this);
  1815. if (serviceName === 'HIVE') {
  1816. var hiveDb = configs.findProperty('name', 'hive_database').value;
  1817. if (['Existing MySQL Database', 'Existing Oracle Database', 'Existing PostgreSQL Database'].contains(hiveDb)) {
  1818. configs.findProperty('name', 'hive_hostname').isVisible = true;
  1819. }
  1820. }
  1821. if (serviceName === 'OOZIE') {
  1822. var oozieDb = configs.findProperty('name', 'oozie_database').value;
  1823. if (['Existing MySQL Database', 'Existing Oracle Database', 'Existing PostgreSQL Database'].contains(oozieDb)) {
  1824. configs.findProperty('name', 'oozie_hostname').isVisible = true;
  1825. }
  1826. }
  1827. },
  1828. /**
  1829. * set host name(s) property for component
  1830. * @param {String} serviceName - service name of component
  1831. * @param {String} componentName - component name whic host we want to know
  1832. * @param {String} hostProperty - name of host property for current component
  1833. * @param {Boolean} multiple - true if can be more than one component
  1834. * @method setHostForService
  1835. */
  1836. setHostForService: function (serviceName, componentName, hostProperty, multiple) {
  1837. var configs = this.get('allConfigs');
  1838. var serviceConfigs = this.get('serviceConfigs').findProperty('serviceName', serviceName).get('configs');
  1839. var hostConfig = serviceConfigs.findProperty('name', hostProperty);
  1840. if (hostConfig) {
  1841. hostConfig.defaultValue = this.getMasterComponentHostValue(componentName, multiple);
  1842. configs.push(hostConfig);
  1843. }
  1844. },
  1845. /**
  1846. * get hostName of component
  1847. * @param {String} componentName
  1848. * @param {Boolean} multiple - true if can be more than one component installed on cluster
  1849. * @return {String|Array|Boolean} hostName|hostNames|false if missing component
  1850. * @method getMasterComponentHostValue
  1851. */
  1852. getMasterComponentHostValue: function (componentName, multiple) {
  1853. var components = this.get('content.hostComponents').filterProperty('componentName', componentName);
  1854. if (components.length > 0) {
  1855. return multiple ? components.mapProperty('hostName') : components[0].get('hostName');
  1856. }
  1857. return false;
  1858. },
  1859. /**
  1860. * Provides service component name and display-name information for
  1861. * the current selected service.
  1862. * @return {Em.Array} validComponents - array of valid components
  1863. * @method getCurrentServiceComponents
  1864. */
  1865. getCurrentServiceComponents: function () {
  1866. var components = this.get('content.hostComponents');
  1867. var validComponents = Ember.A([]);
  1868. var seenComponents = {};
  1869. components.forEach(function (component) {
  1870. var cn = component.get('componentName');
  1871. var cdn = component.get('displayName');
  1872. if (!seenComponents[cn]) {
  1873. validComponents.push(Ember.Object.create({
  1874. componentName: cn,
  1875. displayName: cdn,
  1876. selected: false
  1877. }));
  1878. seenComponents[cn] = cn;
  1879. }
  1880. });
  1881. return validComponents;
  1882. }.property('content'),
  1883. /**
  1884. * trigger loadStep
  1885. * @method loadStep
  1886. */
  1887. doCancel: function () {
  1888. this.loadStep();
  1889. },
  1890. /**
  1891. * trigger restartAllServiceHostComponents(batchUtils) if confirmed in popup
  1892. * @method restartAllStaleConfigComponents
  1893. * @return App.showConfirmationFeedBackPopup
  1894. */
  1895. restartAllStaleConfigComponents: function () {
  1896. var self = this;
  1897. var serviceDisplayName = this.get('content.displayName');
  1898. var bodyMessage = Em.Object.create({
  1899. confirmMsg: Em.I18n.t('services.service.restartAll.confirmMsg').format(serviceDisplayName),
  1900. confirmButton: Em.I18n.t('services.service.restartAll.confirmButton'),
  1901. additionalWarningMsg: this.get('content.passiveState') === 'OFF' ? Em.I18n.t('services.service.restartAll.warningMsg.turnOnMM').format(serviceDisplayName) : null
  1902. });
  1903. return App.showConfirmationFeedBackPopup(function (query) {
  1904. var selectedService = self.get('content.id');
  1905. batchUtils.restartAllServiceHostComponents(selectedService, true, query);
  1906. }, bodyMessage);
  1907. },
  1908. /**
  1909. * trigger launchHostComponentRollingRestart(batchUtils)
  1910. * @method rollingRestartStaleConfigSlaveComponents
  1911. */
  1912. rollingRestartStaleConfigSlaveComponents: function (componentName) {
  1913. batchUtils.launchHostComponentRollingRestart(componentName.context, this.get('content.displayName'), this.get('content.passiveState') === "ON", true);
  1914. },
  1915. /**
  1916. * trigger showItemsShouldBeRestarted popup with hosts that requires resetart
  1917. * @method showHostsShouldBeRestarted
  1918. */
  1919. showHostsShouldBeRestarted: function () {
  1920. var hosts = [];
  1921. for (var hostName in this.get('content.restartRequiredHostsAndComponents')) {
  1922. hosts.push(hostName);
  1923. }
  1924. var hostsText = hosts.length == 1 ? Em.I18n.t('common.host') : Em.I18n.t('common.hosts');
  1925. hosts = hosts.join(', ');
  1926. this.showItemsShouldBeRestarted(hosts, Em.I18n.t('service.service.config.restartService.shouldBeRestarted').format(hostsText));
  1927. },
  1928. /**
  1929. * trigger showItemsShouldBeRestarted popup with components that requires resetart
  1930. * @method showComponentsShouldBeRestarted
  1931. */
  1932. showComponentsShouldBeRestarted: function () {
  1933. var rhc = this.get('content.restartRequiredHostsAndComponents');
  1934. var hostsComponets = [];
  1935. var componentsObject = {};
  1936. for (var hostName in rhc) {
  1937. rhc[hostName].forEach(function (hostComponent) {
  1938. hostsComponets.push(hostComponent);
  1939. if (componentsObject[hostComponent] != undefined) {
  1940. componentsObject[hostComponent]++;
  1941. } else {
  1942. componentsObject[hostComponent] = 1;
  1943. }
  1944. })
  1945. }
  1946. var componentsList = [];
  1947. for (var obj in componentsObject) {
  1948. var componentDisplayName = (componentsObject[obj] > 1) ? obj + 's' : obj;
  1949. componentsList.push(componentsObject[obj] + ' ' + componentDisplayName);
  1950. }
  1951. var componentsText = componentsList.length == 1 ? Em.I18n.t('common.component') : Em.I18n.t('common.components');
  1952. hostsComponets = componentsList.join(', ');
  1953. this.showItemsShouldBeRestarted(hostsComponets, Em.I18n.t('service.service.config.restartService.shouldBeRestarted').format(componentsText));
  1954. },
  1955. showItemsShouldBeRestarted: function (content, header) {
  1956. App.ModalPopup.show({
  1957. content: content,
  1958. header: header,
  1959. bodyClass: Em.View.extend({
  1960. templateName: require('templates/common/selectable_popup'),
  1961. textareaVisible: false,
  1962. textTrigger: function () {
  1963. this.set('textareaVisible', !this.get('textareaVisible'));
  1964. },
  1965. putContentToTextarea: function () {
  1966. var content = this.get('parentView.content');
  1967. if (this.get('textareaVisible')) {
  1968. var wrapper = $(".task-detail-log-maintext");
  1969. $('.task-detail-log-clipboard').html(content).width(wrapper.width()).height(wrapper.height());
  1970. Em.run.next(function () {
  1971. $('.task-detail-log-clipboard').select();
  1972. });
  1973. }
  1974. }.observes('textareaVisible')
  1975. }),
  1976. secondary: null
  1977. });
  1978. },
  1979. /**
  1980. * add new overridden property to config property object
  1981. * @param {object} serviceConfigProperty - config property object
  1982. * @method addOverrideProperty
  1983. */
  1984. addOverrideProperty: function (serviceConfigProperty) {
  1985. var overrides = serviceConfigProperty.get('overrides');
  1986. if (!overrides) {
  1987. overrides = [];
  1988. serviceConfigProperty.set('overrides', overrides);
  1989. }
  1990. // create new override with new value
  1991. var newSCP = App.ServiceConfigProperty.create(serviceConfigProperty);
  1992. newSCP.set('value', '');
  1993. newSCP.set('isOriginalSCP', false); // indicated this is overridden value,
  1994. newSCP.set('parentSCP', serviceConfigProperty);
  1995. newSCP.set('isEditable', true);
  1996. console.debug("createOverrideProperty(): Added:", newSCP, " to main-property:", serviceConfigProperty);
  1997. overrides.pushObject(newSCP);
  1998. },
  1999. /**
  2000. * trigger manageConfigurationGroups
  2001. * @method manageConfigurationGroup
  2002. */
  2003. manageConfigurationGroup: function () {
  2004. this.manageConfigurationGroups();
  2005. },
  2006. manageConfigurationGroups: function (controller) {
  2007. var serviceData = (controller && controller.get('selectedService')) || this.get('content');
  2008. var serviceName = serviceData.get('serviceName');
  2009. var displayName = serviceData.get('displayName');
  2010. App.router.get('manageConfigGroupsController').set('isInstaller', !!controller);
  2011. App.router.get('manageConfigGroupsController').set('serviceName', serviceName);
  2012. if (controller) {
  2013. App.router.get('manageConfigGroupsController').set('isAddService', controller.get('content.controllerName') == 'addServiceController');
  2014. }
  2015. return App.ModalPopup.show({
  2016. header: Em.I18n.t('services.service.config_groups_popup.header').format(displayName),
  2017. bodyClass: App.MainServiceManageConfigGroupView.extend({
  2018. serviceName: serviceName,
  2019. displayName: displayName,
  2020. controllerBinding: 'App.router.manageConfigGroupsController'
  2021. }),
  2022. classNames: ['sixty-percent-width-modal', 'manage-configuration-group-popup'],
  2023. primary: Em.I18n.t('common.save'),
  2024. onPrimary: function () {
  2025. var modifiedConfigGroups = this.get('subViewController.hostsModifiedConfigGroups');
  2026. // Save modified config-groups
  2027. if (!!controller) {
  2028. controller.set('selectedService.configGroups', App.router.get('manageConfigGroupsController.configGroups'));
  2029. controller.selectedServiceObserver();
  2030. if (controller.get('name') == "wizardStep7Controller") {
  2031. if (controller.get('selectedService.selected') === false && modifiedConfigGroups.toDelete.length > 0) {
  2032. controller.setGroupsToDelete(modifiedConfigGroups.toDelete);
  2033. }
  2034. App.config.persistWizardStep7ConfigGroups();
  2035. this.updateConfigGroupOnServicePage();
  2036. }
  2037. this.hide();
  2038. return;
  2039. }
  2040. console.log("manageConfigurationGroups(): Saving modified config-groups: ", modifiedConfigGroups);
  2041. var self = this;
  2042. var errors = [];
  2043. var deleteQueriesCounter = modifiedConfigGroups.toClearHosts.length + modifiedConfigGroups.toDelete.length;
  2044. var createQueriesCounter = modifiedConfigGroups.toSetHosts.length + modifiedConfigGroups.toCreate.length;
  2045. var deleteQueriesRun = false;
  2046. var createQueriesRun = false;
  2047. var runNextQuery = function () {
  2048. if (!deleteQueriesRun && deleteQueriesCounter > 0) {
  2049. deleteQueriesRun = true;
  2050. modifiedConfigGroups.toClearHosts.forEach(function (cg) {
  2051. App.config.clearConfigurationGroupHosts(cg, finishFunction, finishFunction);
  2052. }, this);
  2053. modifiedConfigGroups.toDelete.forEach(function (cg) {
  2054. App.config.deleteConfigGroup(cg, finishFunction, finishFunction);
  2055. }, this);
  2056. } else if (!createQueriesRun && deleteQueriesCounter < 1) {
  2057. createQueriesRun = true;
  2058. modifiedConfigGroups.toSetHosts.forEach(function (cg) {
  2059. App.config.updateConfigurationGroup(cg, finishFunction, finishFunction);
  2060. }, this);
  2061. modifiedConfigGroups.toCreate.forEach(function (cg) {
  2062. App.config.postNewConfigurationGroup(cg, finishFunction);
  2063. }, this);
  2064. }
  2065. };
  2066. var finishFunction = function (xhr, text, errorThrown) {
  2067. if (xhr && errorThrown) {
  2068. var error = xhr.status + "(" + errorThrown + ") ";
  2069. try {
  2070. var json = $.parseJSON(xhr.responseText);
  2071. error += json.message;
  2072. } catch (err) {
  2073. }
  2074. console.error('Error updating Config Group:', error);
  2075. errors.push(error);
  2076. }
  2077. if (createQueriesRun) {
  2078. createQueriesCounter--;
  2079. } else {
  2080. deleteQueriesCounter--;
  2081. }
  2082. if (deleteQueriesCounter + createQueriesCounter < 1) {
  2083. if (errors.length > 0) {
  2084. console.log(errors);
  2085. self.get('subViewController').set('errorMessage', errors.join(". "));
  2086. } else {
  2087. self.updateConfigGroupOnServicePage();
  2088. self.hide();
  2089. }
  2090. } else {
  2091. runNextQuery();
  2092. }
  2093. };
  2094. runNextQuery();
  2095. },
  2096. onSecondary: function () {
  2097. this.hide();
  2098. },
  2099. onClose: function () {
  2100. this.hide();
  2101. },
  2102. subViewController: function () {
  2103. return App.router.get('manageConfigGroupsController');
  2104. }.property('App.router.manageConfigGroupsController'),
  2105. updateConfigGroupOnServicePage: function () {
  2106. var subViewController = this.get('subViewController');
  2107. var selectedConfigGroup = subViewController.get('selectedConfigGroup');
  2108. var managedConfigGroups = subViewController.get('configGroups');
  2109. if (!controller) {
  2110. controller = App.router.get('mainServiceInfoConfigsController');
  2111. controller.set('configGroups', managedConfigGroups);
  2112. } else {
  2113. controller.set('selectedService.configGroups', managedConfigGroups);
  2114. }
  2115. //check whether selectedConfigGroup was selected
  2116. if (selectedConfigGroup && controller.get('configGroups').someProperty('name', selectedConfigGroup.get('name'))) {
  2117. controller.set('selectedConfigGroup', selectedConfigGroup);
  2118. } else {
  2119. controller.set('selectedConfigGroup', managedConfigGroups.findProperty('isDefault', true));
  2120. }
  2121. },
  2122. updateButtons: function () {
  2123. var modified = this.get('subViewController.isHostsModified');
  2124. this.set('disablePrimary', !modified);
  2125. }.observes('subViewController.isHostsModified'),
  2126. secondary: Em.I18n.t('common.cancel'),
  2127. didInsertElement: Em.K
  2128. });
  2129. },
  2130. /**
  2131. * If user changes cfg group if some configs was changed popup with propose to save changes must be shown
  2132. * @param {object} event - triggered event for selecting another config-group
  2133. * @method selectConfigGroup
  2134. */
  2135. selectConfigGroup: function (event) {
  2136. if (!this.get('isInit')) {
  2137. if (this.hasUnsavedChanges()) {
  2138. this.showSavePopup(null, event);
  2139. return;
  2140. }
  2141. }
  2142. this.set('selectedConfigGroup', event.context);
  2143. },
  2144. /**
  2145. * Are some unsaved changes available
  2146. * @returns {boolean}
  2147. */
  2148. hasUnsavedChanges: function () {
  2149. return this.get('hash') != this.getHash();
  2150. },
  2151. /**
  2152. * If some configs are changed and user navigates away or select another config-group, show this popup with propose to save changes
  2153. * @param {String} path
  2154. * @param {object} event - triggered event for selecting another config-group
  2155. * @method showSavePopup
  2156. */
  2157. showSavePopup: function (path, event) {
  2158. var self = this;
  2159. return App.ModalPopup.show({
  2160. header: Em.I18n.t('common.warning'),
  2161. body: Em.I18n.t('services.service.config.exitPopup.body'),
  2162. footerClass: Ember.View.extend({
  2163. templateName: require('templates/main/service/info/save_popup_footer'),
  2164. isSaveDisabled: function () {
  2165. return self.get('isSubmitDisabled');
  2166. }.property()
  2167. }),
  2168. primary: Em.I18n.t('common.save'),
  2169. secondary: Em.I18n.t('common.cancel'),
  2170. onSave: function () {
  2171. self.restartServicePopup();
  2172. this.hide();
  2173. },
  2174. onDiscard: function () {
  2175. if (path) {
  2176. self.set('forceTransition', true);
  2177. App.router.route(path);
  2178. } else if (event) {
  2179. // Prevent multiple popups
  2180. self.set('hash', self.getHash());
  2181. self.selectConfigGroup(event);
  2182. }
  2183. this.hide();
  2184. },
  2185. onCancel: function () {
  2186. this.hide();
  2187. }
  2188. });
  2189. }
  2190. });