configs.js 104 KB

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