configs.js 96 KB

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