controls_view.js 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372
  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. /**
  20. * Abstract view for config fields.
  21. * Add popover support to control
  22. */
  23. App.ServiceConfigPopoverSupport = Ember.Mixin.create({
  24. /**
  25. * Config object. It will instance of App.ServiceConfigProperty
  26. */
  27. serviceConfig: null,
  28. attributeBindings:['readOnly'],
  29. isPopoverEnabled: true,
  30. didInsertElement: function () {
  31. $('body').tooltip({
  32. selector: '[data-toggle=tooltip]',
  33. placement: 'top'
  34. });
  35. // if description for this serviceConfig not exist, then no need to show popover
  36. if (this.get('isPopoverEnabled') !== 'false' && this.get('serviceConfig.description')) {
  37. App.popover(this.$(), {
  38. title: Em.I18n.t('installer.controls.serviceConfigPopover.title').format(
  39. this.get('serviceConfig.displayName'),
  40. (this.get('serviceConfig.displayName') == this.get('serviceConfig.name')) ? '' : this.get('serviceConfig.name')
  41. ),
  42. content: this.get('serviceConfig.description'),
  43. placement: 'right',
  44. trigger: 'hover'
  45. });
  46. }
  47. },
  48. willDestroyElement: function() {
  49. this.$().popover('destroy');
  50. },
  51. readOnly: function () {
  52. return !this.get('serviceConfig.isEditable');
  53. }.property('serviceConfig.isEditable')
  54. });
  55. /**
  56. * mixin set class that serve as unique element identificator,
  57. * id not used in order to avoid collision with ember ids
  58. */
  59. App.ServiceConfigCalculateId = Ember.Mixin.create({
  60. idClass: Ember.computed(function () {
  61. var label = Em.get(this, 'serviceConfig.name') ? Em.get(this, 'serviceConfig.name').toLowerCase().replace(/\./g, '-') : '',
  62. fileName = Em.get(this, 'serviceConfig.filename') ? Em.get(this, 'serviceConfig.filename').toLowerCase().replace(/\./g, '-') : '',
  63. group = Em.get(this, 'serviceConfig.group.name') || 'default';
  64. isOrigin = Em.get(this, 'serviceConfig.compareConfigs.length') > 0 ? '-origin' : '';
  65. return 'service-config-' + label + '-' + fileName + '-' + group + isOrigin;
  66. }),
  67. classNameBindings: 'idClass'
  68. });
  69. /**
  70. * Default input control
  71. * @type {*}
  72. */
  73. App.ServiceConfigTextField = Ember.TextField.extend(App.ServiceConfigPopoverSupport, App.ServiceConfigCalculateId, {
  74. valueBinding: 'serviceConfig.value',
  75. classNameBindings: 'textFieldClassName',
  76. placeholderBinding: 'serviceConfig.defaultValue',
  77. keyPress: function (event) {
  78. if (event.keyCode == 13) {
  79. return false;
  80. }
  81. },
  82. //Set editDone true for last edited config text field parameter
  83. focusOut: function (event) {
  84. this.get('serviceConfig').set("editDone", true);
  85. },
  86. //Set editDone false for all current category config text field parameter
  87. focusIn: function (event) {
  88. if (!this.get('serviceConfig.isOverridden') && !this.get('serviceConfig.isComparison')) {
  89. this.get("parentView.categoryConfigsAll").setEach("editDone", false);
  90. }
  91. },
  92. textFieldClassName: function () {
  93. if (this.get('serviceConfig.unit')) {
  94. return ['input-small'];
  95. } else if (this.get('serviceConfig.displayType') === 'principal') {
  96. return ['span12'];
  97. } else {
  98. return ['span9'];
  99. }
  100. }.property('serviceConfig.displayType', 'serviceConfig.unit')
  101. });
  102. /**
  103. * Customized input control with Units type specified
  104. * @type {Em.View}
  105. */
  106. App.ServiceConfigTextFieldWithUnit = Ember.View.extend(App.ServiceConfigPopoverSupport, {
  107. valueBinding: 'serviceConfig.value',
  108. classNames: ['input-append', 'with-unit'],
  109. placeholderBinding: 'serviceConfig.defaultValue',
  110. templateName: require('templates/wizard/controls_service_config_textfield_with_unit')
  111. });
  112. /**
  113. * Password control
  114. * @type {*}
  115. */
  116. App.ServiceConfigPasswordField = Ember.TextField.extend({
  117. serviceConfig: null,
  118. type: 'password',
  119. attributeBindings:['readOnly'],
  120. valueBinding: 'serviceConfig.value',
  121. classNames: [ 'span4' ],
  122. placeholder: Em.I18n.t('form.item.placeholders.typePassword'),
  123. template: Ember.Handlebars.compile('{{view view.retypePasswordView}}'),
  124. keyPress: function (event) {
  125. if (event.keyCode == 13) {
  126. return false;
  127. }
  128. },
  129. retypePasswordView: Ember.TextField.extend({
  130. placeholder: Em.I18n.t('form.passwordRetype'),
  131. attributeBindings:['readOnly'],
  132. type: 'password',
  133. classNames: [ 'span4', 'retyped-password' ],
  134. keyPress: function (event) {
  135. if (event.keyCode == 13) {
  136. return false;
  137. }
  138. },
  139. valueBinding: 'parentView.serviceConfig.retypedPassword',
  140. readOnly: function () {
  141. return !this.get('parentView.serviceConfig.isEditable');
  142. }.property('parentView.serviceConfig.isEditable')
  143. }),
  144. readOnly: function () {
  145. return !this.get('serviceConfig.isEditable');
  146. }.property('serviceConfig.isEditable')
  147. });
  148. /**
  149. * Textarea control
  150. * @type {*}
  151. */
  152. App.ServiceConfigTextArea = Ember.TextArea.extend(App.ServiceConfigPopoverSupport, App.ServiceConfigCalculateId, {
  153. valueBinding: 'serviceConfig.value',
  154. rows: 4,
  155. classNames: ['span9', 'directories']
  156. });
  157. /**
  158. * Textarea control for content type
  159. * @type {*}
  160. */
  161. App.ServiceConfigTextAreaContent = Ember.TextArea.extend(App.ServiceConfigPopoverSupport, App.ServiceConfigCalculateId, {
  162. valueBinding: 'serviceConfig.value',
  163. rows: 20,
  164. classNames: ['span10']
  165. });
  166. /**
  167. * Textarea control with bigger height
  168. * @type {*}
  169. */
  170. App.ServiceConfigBigTextArea = App.ServiceConfigTextArea.extend(App.ServiceConfigCalculateId, {
  171. rows: 10
  172. });
  173. /**
  174. * Checkbox control
  175. * @type {*}
  176. */
  177. App.ServiceConfigCheckbox = Ember.Checkbox.extend(App.ServiceConfigPopoverSupport, App.ServiceConfigCalculateId, {
  178. allowedPairs: {
  179. 'trueFalse': ["true", "false"],
  180. 'YesNo': ["Yes", "No"],
  181. 'YESNO': ["YES", "NO"],
  182. 'yesNo': ["yes", "no"]
  183. },
  184. trueValue: true,
  185. falseValue: false,
  186. checked: false,
  187. /**
  188. * set appropriate config values pair
  189. * to define which value is positive (checked) property
  190. * and what value is negative (unchecked) proeprty
  191. */
  192. didInsertElement: function() {
  193. this._super();
  194. this.addObserver('serviceConfig.value', this, 'toggleChecker');
  195. Object.keys(this.get('allowedPairs')).forEach(function(key) {
  196. if (this.get('allowedPairs')[key].contains(this.get('serviceConfig.value'))) {
  197. this.set('trueValue', this.get('allowedPairs')[key][0]);
  198. this.set('falseValue', this.get('allowedPairs')[key][1]);
  199. }
  200. }, this);
  201. this.set('checked', this.get('serviceConfig.value') === this.get('trueValue'))
  202. },
  203. willDestroyElement: function() {
  204. this.removeObserver('serviceConfig.value', this, 'checkedBinding');
  205. },
  206. /***
  207. * defines if checkbox value appropriate to the config value
  208. * @returns {boolean}
  209. */
  210. isNotAppropriateValue: function() {
  211. return this.get('serviceConfig.value') !== this.get(this.get('checked') + 'Value');
  212. },
  213. /**
  214. * change service config value if click on checkbox
  215. */
  216. toggleValue: function() {
  217. if (this.isNotAppropriateValue()){
  218. this.set('serviceConfig.value', this.get(this.get('checked') + 'Value'));
  219. this.get('serviceConfig').set("editDone", true);
  220. }
  221. }.observes('checked'),
  222. /**
  223. * change checkbox value if click on undo
  224. */
  225. toggleChecker: function() {
  226. if (this.isNotAppropriateValue())
  227. this.set('checked', !this.get('checked'));
  228. },
  229. disabled: function () {
  230. return !this.get('serviceConfig.isEditable');
  231. }.property('serviceConfig.isEditable'),
  232. //Set editDone false for all current category config text field parameter
  233. focusIn: function (event) {
  234. if (!this.get('serviceConfig.isOverridden') && !this.get('serviceConfig.isComparison')) {
  235. this.get("parentView.categoryConfigsAll").setEach("editDone", false);
  236. }
  237. }
  238. });
  239. /**
  240. * Checkbox control which can hide or show dependent properties
  241. * @type {*|void}
  242. */
  243. App.ServiceConfigCheckboxWithDependencies = App.ServiceConfigCheckbox.extend({
  244. didInsertElement: function() {
  245. this._super();
  246. this.toggleDependentConfigs();
  247. },
  248. toggleDependentConfigs: function() {
  249. if (this.get('serviceConfig.dependentConfigPattern')) {
  250. if (this.get('serviceConfig.dependentConfigPattern') === "CATEGORY") {
  251. this.disableEnableCategoryCongis();
  252. } else {
  253. this.showHideDependentConfigs();
  254. }
  255. }
  256. }.observes('checked'),
  257. disableEnableCategoryCongis: function () {
  258. this.get('categoryConfigsAll').setEach('isEditable', this.get('checked'));
  259. this.set('serviceConfig.isEditable', true);
  260. },
  261. showHideDependentConfigs: function () {
  262. this.get('categoryConfigsAll').forEach(function (c) {
  263. if (c.get('name').match(this.get('serviceConfig.dependentConfigPattern')) && c.get('name') != this.get('serviceConfig.name'))
  264. c.set('isVisible', this.get('checked'))
  265. }, this);
  266. }
  267. });
  268. App.ServiceConfigRadioButtons = Ember.View.extend(App.ServiceConfigCalculateId, {
  269. templateName: require('templates/wizard/controls_service_config_radio_buttons'),
  270. didInsertElement: function () {
  271. // on page render, automatically populate JDBC URLs only for default database settings
  272. // so as to not lose the user's customizations on these fields
  273. if (['addServiceController', 'installerController'].contains(this.get('controller.wizardController.name'))) {
  274. if (/^New\s\w+\sDatabase$/.test(this.get('serviceConfig.value')) || this.dontUseHandleDbConnection.contains(this.get('serviceConfig.name'))) {
  275. this.onOptionsChange();
  276. } else {
  277. this.handleDBConnectionProperty();
  278. }
  279. }
  280. },
  281. /**
  282. * properties with these names don'use handleDBConnectionProperty mathod
  283. */
  284. dontUseHandleDbConnection: ['DB_FLAVOR', 'authentication_method'],
  285. configs: function () {
  286. if (this.get('controller.name') == 'mainServiceInfoConfigsController') return this.get('categoryConfigsAll');
  287. return this.get('categoryConfigsAll').filterProperty('isObserved', true);
  288. }.property('categoryConfigsAll'),
  289. serviceConfig: null,
  290. categoryConfigsAll: null,
  291. onOptionsChange: function () {
  292. // The following if condition will be satisfied only for installer wizard flow
  293. if (this.get('configs').length) {
  294. var connectionUrl = this.get('connectionUrl');
  295. if (connectionUrl) {
  296. var dbClass = this.get('dbClass');
  297. var hostName = this.get('hostName');
  298. var databaseName = this.get('databaseName');
  299. var hostNameDefault;
  300. var databaseNameDefault;
  301. var connectionUrlValue = connectionUrl.get('value');
  302. var connectionUrlDefaultValue = connectionUrl.get('defaultValue');
  303. var dbClassValue = dbClass.get('value');
  304. var serviceName = this.get('serviceConfig.serviceName');
  305. var isServiceInstalled = App.Service.find().someProperty('serviceName', serviceName);
  306. var postgresUrl = 'jdbc:postgresql://{0}:5432/{1}';
  307. var oracleUrl = 'jdbc:oracle:thin:@//{0}:1521/{1}';
  308. var mssqlUrl = 'jdbc:sqlserver://{0};databaseName={1}';
  309. var mssqlIntegratedAuthUrl = 'jdbc:sqlserver://{0};databaseName={1};integratedSecurity=true';
  310. var isNotExistingMySQLServer = this.get('serviceConfig.value') !== 'Existing MSSQL Server database with integrated authentication';
  311. var categoryConfigsAll = this.get('categoryConfigsAll');
  312. if (isServiceInstalled) {
  313. hostNameDefault = this.get('hostNameProperty.defaultValue');
  314. databaseNameDefault = this.get('databaseNameProperty.defaultValue');
  315. } else {
  316. hostNameDefault = hostName;
  317. databaseNameDefault = databaseName;
  318. }
  319. switch (serviceName) {
  320. case 'HIVE':
  321. var hiveDbType = this.get('parentView.serviceConfigs').findProperty('name', 'hive_database_type');
  322. var mysqlUrl = 'jdbc:mysql://{0}/{1}?createDatabaseIfNotExist=true';
  323. switch (this.get('serviceConfig.value')) {
  324. case 'New MySQL Database':
  325. case 'Existing MySQL Database':
  326. connectionUrlValue = mysqlUrl.format(hostName, databaseName);
  327. connectionUrlDefaultValue = mysqlUrl.format(hostNameDefault, databaseNameDefault);
  328. dbClassValue = 'com.mysql.jdbc.Driver';
  329. Em.set(hiveDbType, 'value', 'mysql');
  330. break;
  331. case Em.I18n.t('services.service.config.hive.oozie.postgresql'):
  332. connectionUrlValue = postgresUrl.format(hostName, databaseName);
  333. connectionUrlDefaultValue = postgresUrl.format(hostNameDefault, databaseNameDefault);
  334. dbClassValue = 'org.postgresql.Driver';
  335. Em.set(hiveDbType, 'value', 'postgres');
  336. break;
  337. case 'Existing Oracle Database':
  338. connectionUrlValue = oracleUrl.format(hostName, databaseName);
  339. connectionUrlDefaultValue = oracleUrl.format(hostNameDefault, databaseNameDefault);
  340. dbClassValue = 'oracle.jdbc.driver.OracleDriver';
  341. Em.set(hiveDbType, 'value', 'oracle');
  342. break;
  343. case 'Existing MSSQL Server database with SQL authentication':
  344. connectionUrlValue = mssqlUrl.format(hostName, databaseName);
  345. connectionUrlDefaultValue = mssqlUrl.format(hostNameDefault, databaseNameDefault);
  346. dbClassValue = 'com.microsoft.sqlserver.jdbc.SQLServerDriver';
  347. Em.set(hiveDbType, 'value', 'mssql');
  348. break;
  349. case 'Existing MSSQL Server database with integrated authentication':
  350. connectionUrlValue = mssqlIntegratedAuthUrl.format(hostName, databaseName);
  351. connectionUrlDefaultValue = mssqlIntegratedAuthUrl.format(hostNameDefault, databaseNameDefault);
  352. dbClassValue = 'com.microsoft.sqlserver.jdbc.SQLServerDriver';
  353. Em.set(hiveDbType, 'value', 'mssql');
  354. break;
  355. }
  356. categoryConfigsAll.findProperty('name', 'javax.jdo.option.ConnectionUserName').setProperties({
  357. isVisible: isNotExistingMySQLServer,
  358. isRequired: isNotExistingMySQLServer
  359. });
  360. categoryConfigsAll.findProperty('name', 'javax.jdo.option.ConnectionPassword').setProperties({
  361. isVisible: isNotExistingMySQLServer,
  362. isRequired: isNotExistingMySQLServer
  363. });
  364. break;
  365. case 'OOZIE':
  366. var derbyUrl = 'jdbc:derby:${oozie.data.dir}/${oozie.db.schema.name}-db;create=true';
  367. var mysqlUrl = 'jdbc:mysql://{0}/{1}';
  368. switch (this.get('serviceConfig.value')) {
  369. case 'New Derby Database':
  370. connectionUrlValue = derbyUrl;
  371. connectionUrlDefaultValue = derbyUrl;
  372. dbClassValue = 'org.apache.derby.jdbc.EmbeddedDriver';
  373. break;
  374. case 'Existing MySQL Database':
  375. connectionUrlValue = mysqlUrl.format(hostName, databaseName);
  376. connectionUrlDefaultValue = mysqlUrl.format(hostNameDefault, databaseNameDefault);
  377. dbClassValue = 'com.mysql.jdbc.Driver';
  378. break;
  379. case Em.I18n.t('services.service.config.hive.oozie.postgresql'):
  380. connectionUrlValue = postgresUrl.format(hostName, databaseName);
  381. connectionUrlDefaultValue = postgresUrl.format(hostNameDefault, databaseNameDefault);
  382. dbClassValue = 'org.postgresql.Driver';
  383. break;
  384. case 'Existing Oracle Database':
  385. connectionUrlValue = oracleUrl.format(hostName, databaseName);
  386. connectionUrlDefaultValue = oracleUrl.format(hostNameDefault, databaseNameDefault);
  387. dbClassValue = 'oracle.jdbc.driver.OracleDriver';
  388. break;
  389. case 'Existing MSSQL Server database with SQL authentication':
  390. connectionUrlValue = mssqlUrl.format(hostName, databaseName);
  391. connectionUrlDefaultValue = mssqlUrl.format(hostNameDefault, databaseNameDefault);
  392. dbClassValue = 'com.microsoft.sqlserver.jdbc.SQLServerDriver';
  393. break;
  394. case 'Existing MSSQL Server database with integrated authentication':
  395. connectionUrlValue = mssqlIntegratedAuthUrl.format(hostName, databaseName);
  396. connectionUrlDefaultValue = mssqlIntegratedAuthUrl.format(hostNameDefault, databaseNameDefault);
  397. dbClassValue = 'com.microsoft.sqlserver.jdbc.SQLServerDriver';
  398. break;
  399. }
  400. categoryConfigsAll.findProperty('name', 'oozie.service.JPAService.jdbc.username').setProperties({
  401. isVisible: isNotExistingMySQLServer,
  402. isRequired: isNotExistingMySQLServer
  403. });
  404. categoryConfigsAll.findProperty('name', 'oozie.service.JPAService.jdbc.password').setProperties({
  405. isVisible: isNotExistingMySQLServer,
  406. isRequired: isNotExistingMySQLServer
  407. });
  408. break;
  409. }
  410. connectionUrl.set('value', connectionUrlValue);
  411. connectionUrl.set('defaultValue', connectionUrlDefaultValue);
  412. dbClass.set('value', dbClassValue);
  413. }
  414. }
  415. }.observes('databaseName', 'hostName'),
  416. nameBinding: 'serviceConfig.radioName',
  417. databaseNameProperty: function () {
  418. switch (this.get('serviceConfig.serviceName')) {
  419. case 'HIVE':
  420. return this.get('categoryConfigsAll').findProperty('name', 'ambari.hive.db.schema.name');
  421. case 'OOZIE':
  422. return this.get('categoryConfigsAll').findProperty('name', 'oozie.db.schema.name');
  423. default:
  424. return null;
  425. }
  426. }.property('serviceConfig.serviceName'),
  427. databaseName: function () {
  428. return this.get('databaseNameProperty.value');
  429. }.property('databaseNameProperty.value'),
  430. hostNameProperty: function () {
  431. var value = this.get('serviceConfig.value');
  432. var returnValue;
  433. var hostname;
  434. if (this.get('serviceConfig.serviceName') === 'HIVE') {
  435. switch (value) {
  436. case 'New MySQL Database':
  437. hostname = this.get('categoryConfigsAll').findProperty('name', 'hive_ambari_host');
  438. break;
  439. case 'Existing MySQL Database':
  440. hostname = this.get('categoryConfigsAll').findProperty('name', 'hive_existing_mysql_host');
  441. break;
  442. case Em.I18n.t('services.service.config.hive.oozie.postgresql'):
  443. hostname = this.get('categoryConfigsAll').findProperty('name', 'hive_existing_postgresql_host');
  444. break;
  445. case 'Existing Oracle Database':
  446. hostname = this.get('categoryConfigsAll').findProperty('name', 'hive_existing_oracle_host');
  447. break;
  448. case 'Existing MSSQL Server database with SQL authentication':
  449. hostname = this.get('categoryConfigsAll').findProperty('name', 'hive_existing_mssql_server_host');
  450. break;
  451. case 'Existing MSSQL Server database with integrated authentication':
  452. hostname = this.get('categoryConfigsAll').findProperty('name', 'hive_existing_mssql_server_2_host');
  453. break;
  454. }
  455. if (hostname) {
  456. returnValue = hostname;
  457. } else {
  458. returnValue = this.get('categoryConfigsAll').findProperty('name', 'hive_hostname');
  459. }
  460. } else if (this.get('serviceConfig.serviceName') === 'OOZIE') {
  461. switch (value) {
  462. case 'New Derby Database':
  463. hostname = this.get('categoryConfigsAll').findProperty('name', 'oozie_ambari_host');
  464. break;
  465. case 'Existing MySQL Database':
  466. hostname = this.get('categoryConfigsAll').findProperty('name', 'oozie_existing_mysql_host');
  467. break;
  468. case Em.I18n.t('services.service.config.hive.oozie.postgresql'):
  469. hostname = this.get('categoryConfigsAll').findProperty('name', 'oozie_existing_postgresql_host');
  470. break;
  471. case 'Existing Oracle Database':
  472. hostname = this.get('categoryConfigsAll').findProperty('name', 'oozie_existing_oracle_host');
  473. break;
  474. case 'Existing MSSQL Server database with SQL authentication':
  475. hostname = this.get('categoryConfigsAll').findProperty('name', 'oozie_existing_mssql_server_host');
  476. break;
  477. case 'Existing MSSQL Server database with integrated authentication':
  478. hostname = this.get('categoryConfigsAll').findProperty('name', 'oozie_existing_mssql_server_2_host');
  479. break;
  480. }
  481. if (hostname) {
  482. returnValue = hostname;
  483. } else {
  484. returnValue = this.get('categoryConfigsAll').findProperty('name', 'oozie_hostname');
  485. }
  486. }
  487. return returnValue;
  488. }.property('serviceConfig.serviceName', 'serviceConfig.value'),
  489. hostName: function () {
  490. return this.get('hostNameProperty.value');
  491. }.property('hostNameProperty.value'),
  492. connectionUrl: function () {
  493. if (this.get('serviceConfig.serviceName') === 'HIVE') {
  494. return this.get('categoryConfigsAll').findProperty('name', 'javax.jdo.option.ConnectionURL');
  495. } else {
  496. return this.get('categoryConfigsAll').findProperty('name', 'oozie.service.JPAService.jdbc.url');
  497. }
  498. }.property('serviceConfig.serviceName'),
  499. dbClass: function () {
  500. if (this.get('serviceConfig.serviceName') === 'HIVE') {
  501. return this.get('categoryConfigsAll').findProperty('name', 'javax.jdo.option.ConnectionDriverName');
  502. } else {
  503. return this.get('categoryConfigsAll').findProperty('name', 'oozie.service.JPAService.jdbc.driver');
  504. }
  505. }.property('serviceConfig.serviceName'),
  506. /**
  507. * `Observer` that add <code>additionalView</code> to <code>App.ServiceConfigProperty</code>
  508. * that responsible for (if existing db selected)
  509. * 1. checking database connection
  510. * 2. showing jdbc driver setup warning msg.
  511. *
  512. * @method handleDBConnectionProperty
  513. **/
  514. handleDBConnectionProperty: function() {
  515. if (this.dontUseHandleDbConnection.contains(this.get('serviceConfig.name')))
  516. return;
  517. var handledProperties = ['oozie_database', 'hive_database'];
  518. var currentValue = this.get('serviceConfig.value');
  519. var databases = /MySQL|PostgreSQL|Oracle|Derby|MSSQL/gi;
  520. var currentDB = currentValue.match(databases)[0];
  521. var databasesTypes = /MySQL|PostgreS|Oracle|Derby|MSSQL/gi;
  522. var currentDBType = currentValue.match(databasesTypes)[0];
  523. var existingDatabase = /existing/gi.test(currentValue);
  524. // db connection check button show up if existed db selected
  525. var propertyAppendTo1 = this.get('categoryConfigsAll').findProperty('displayName', 'Database URL');
  526. if (currentDB && existingDatabase) {
  527. if (handledProperties.contains(this.get('serviceConfig.name'))) {
  528. if (propertyAppendTo1) propertyAppendTo1.set('additionalView', App.CheckDBConnectionView.extend({databaseName: currentDB}));
  529. }
  530. } else {
  531. propertyAppendTo1.set('additionalView', null);
  532. }
  533. // warning msg under database type radio buttons, to warn the user to setup jdbc driver if existed db selected
  534. var propertyHive = this.get('categoryConfigsAll').findProperty('displayName', 'Hive Database');
  535. var propertyOozie = this.get('categoryConfigsAll').findProperty('displayName', 'Oozie Database');
  536. var propertyAppendTo2 = propertyHive ? propertyHive : propertyOozie;
  537. if (currentDB && existingDatabase) {
  538. if (handledProperties.contains(this.get('serviceConfig.name'))) {
  539. if (propertyAppendTo2) {
  540. propertyAppendTo2.set('additionalView', Ember.View.extend({
  541. template: Ember.Handlebars.compile('<div class="alert">{{{view.message}}}</div>'),
  542. message: Em.I18n.t('services.service.config.database.msg.jdbcSetup').format(currentDBType.toLowerCase(), currentDBType.toLowerCase())
  543. }));
  544. }
  545. }
  546. } else {
  547. propertyAppendTo2.set('additionalView', null);
  548. }
  549. }.observes('serviceConfig.value'),
  550. optionsBinding: 'serviceConfig.options'
  551. });
  552. App.ServiceConfigRadioButton = Ember.Checkbox.extend({
  553. tagName: 'input',
  554. attributeBindings: ['type', 'name', 'value', 'checked', 'disabled'],
  555. checked: false,
  556. type: 'radio',
  557. name: null,
  558. value: null,
  559. didInsertElement: function () {
  560. console.debug('App.ServiceConfigRadioButton.didInsertElement');
  561. if (this.get('parentView.serviceConfig.value') === this.get('value')) {
  562. console.debug(this.get('name') + ":" + this.get('value') + ' is checked');
  563. this.set('checked', true);
  564. }
  565. },
  566. click: function () {
  567. this.set('checked', true);
  568. console.debug('App.ServiceConfigRadioButton.click');
  569. this.onChecked();
  570. },
  571. onChecked: function () {
  572. // Wrapping the call with Ember.run.next prevents a problem where setting isVisible on component
  573. // causes JS error due to re-rendering. For example, this occurs when switching the Config Group
  574. // in Service Config page
  575. Em.run.next(this, function() {
  576. console.debug('App.ServiceConfigRadioButton.onChecked');
  577. this.set('parentView.serviceConfig.value', this.get('value'));
  578. var components = this.get('parentView.serviceConfig.options');
  579. if (components) {
  580. components.forEach(function (_component) {
  581. if (_component.foreignKeys) {
  582. _component.foreignKeys.forEach(function (_componentName) {
  583. if (this.get('parentView.parentView.serviceConfigs').someProperty('name', _componentName)) {
  584. var component = this.get('parentView.parentView.serviceConfigs').findProperty('name', _componentName);
  585. component.set('isVisible', _component.displayName === this.get('value'));
  586. }
  587. }, this);
  588. }
  589. }, this);
  590. }
  591. });
  592. }.observes('checked'),
  593. disabled: function () {
  594. return !this.get('parentView.serviceConfig.isEditable') ||
  595. !['addServiceController', 'installerController'].contains(this.get('controller.wizardController.name')) && /^New\s\w+\sDatabase$/.test(this.get('value'));
  596. }.property('parentView.serviceConfig.isEditable')
  597. });
  598. App.ServiceConfigComboBox = Ember.Select.extend(App.ServiceConfigPopoverSupport, App.ServiceConfigCalculateId, {
  599. contentBinding: 'serviceConfig.options',
  600. selectionBinding: 'serviceConfig.value',
  601. placeholderBinding: 'serviceConfig.defaultValue',
  602. classNames: [ 'span3' ]
  603. });
  604. /**
  605. * Base component for host config with popover support
  606. */
  607. App.ServiceConfigHostPopoverSupport = Ember.Mixin.create({
  608. /**
  609. * Config object. It will instance of App.ServiceConfigProperty
  610. */
  611. serviceConfig: null,
  612. didInsertElement: function () {
  613. App.popover(this.$(), {
  614. title: this.get('serviceConfig.displayName'),
  615. content: this.get('serviceConfig.description'),
  616. placement: 'right',
  617. trigger: 'hover'
  618. });
  619. }
  620. });
  621. /**
  622. * Master host component.
  623. * Show hostname without ability to edit it
  624. * @type {*}
  625. */
  626. App.ServiceConfigMasterHostView = Ember.View.extend(App.ServiceConfigHostPopoverSupport, App.ServiceConfigCalculateId, {
  627. classNames: ['master-host', 'span6'],
  628. valueBinding: 'serviceConfig.value',
  629. template: Ember.Handlebars.compile('{{value}}')
  630. });
  631. /**
  632. * text field property view that enables possibility
  633. * for check connectio
  634. * @type {*}
  635. */
  636. App.checkConnectionView = App.ServiceConfigTextField.extend({
  637. didInsertElement: function() {
  638. this._super();
  639. var kdc = this.get('categoryConfigsAll').findProperty('name', 'kdc_type');
  640. var propertyAppendTo = this.get('categoryConfigsAll').findProperty('name', 'domains');
  641. if (propertyAppendTo) propertyAppendTo.set('additionalView', App.CheckDBConnectionView.extend({databaseName: kdc && kdc.get('value')}));
  642. }
  643. });
  644. /**
  645. * Show value as plain label in italics
  646. * @type {*}
  647. */
  648. App.ServiceConfigLabelView = Ember.View.extend(App.ServiceConfigHostPopoverSupport, App.ServiceConfigCalculateId, {
  649. classNames: ['master-host', 'span6'],
  650. valueBinding: 'serviceConfig.value',
  651. template: Ember.Handlebars.compile('<i>{{view.value}}</i>')
  652. });
  653. /**
  654. * Base component to display Multiple hosts
  655. * @type {*}
  656. */
  657. App.ServiceConfigMultipleHostsDisplay = Ember.Mixin.create(App.ServiceConfigHostPopoverSupport, App.ServiceConfigCalculateId, {
  658. hasNoHosts: function () {
  659. console.log('view', this.get('viewName')); //to know which View cause errors
  660. console.log('controller', this.get('controller').name); //should be slaveComponentGroupsController
  661. if (!this.get('value')) {
  662. return true;
  663. }
  664. return this.get('value').length === 0;
  665. }.property('value'),
  666. hasOneHost: function () {
  667. return this.get('value').length === 1;
  668. }.property('value'),
  669. hasMultipleHosts: function () {
  670. return this.get('value').length > 1;
  671. }.property('value'),
  672. otherLength: function () {
  673. var len = this.get('value').length;
  674. if (len > 2) {
  675. return Em.I18n.t('installer.controls.serviceConfigMultipleHosts.others').format(len - 1);
  676. } else {
  677. return Em.I18n.t('installer.controls.serviceConfigMultipleHosts.other');
  678. }
  679. }.property('value')
  680. });
  681. /**
  682. * Multiple master host component.
  683. * Show hostnames without ability to edit it
  684. * @type {*}
  685. */
  686. App.ServiceConfigMasterHostsView = Ember.View.extend(App.ServiceConfigMultipleHostsDisplay, App.ServiceConfigCalculateId, {
  687. viewName: "serviceConfigMasterHostsView",
  688. valueBinding: 'serviceConfig.value',
  689. classNames: ['master-hosts', 'span6'],
  690. templateName: require('templates/wizard/master_hosts'),
  691. /**
  692. * Onclick handler for link
  693. */
  694. showHosts: function () {
  695. var serviceConfig = this.get('serviceConfig');
  696. App.ModalPopup.show({
  697. header: Em.I18n.t('installer.controls.serviceConfigMasterHosts.header').format(serviceConfig.category),
  698. bodyClass: Ember.View.extend({
  699. serviceConfig: serviceConfig,
  700. templateName: require('templates/wizard/master_hosts_popup')
  701. }),
  702. secondary: null
  703. });
  704. }
  705. });
  706. /**
  707. * Show tabs list for slave hosts
  708. * @type {*}
  709. */
  710. App.SlaveComponentGroupsMenu = Em.CollectionView.extend(App.ServiceConfigCalculateId, {
  711. content: function () {
  712. return this.get('controller.componentGroups');
  713. }.property('controller.componentGroups'),
  714. tagName: 'ul',
  715. classNames: ["nav", "nav-tabs"],
  716. itemViewClass: Em.View.extend({
  717. classNameBindings: ["active"],
  718. active: function () {
  719. return this.get('content.active');
  720. }.property('content.active'),
  721. errorCount: function () {
  722. return this.get('content.properties').filterProperty('isValid', false).filterProperty('isVisible', true).get('length');
  723. }.property('content.properties.@each.isValid', 'content.properties.@each.isVisible'),
  724. templateName: require('templates/wizard/controls_slave_component_groups_menu')
  725. })
  726. });
  727. /**
  728. * <code>Add group</code> button
  729. * @type {*}
  730. */
  731. App.AddSlaveComponentGroupButton = Ember.View.extend(App.ServiceConfigCalculateId, {
  732. tagName: 'span',
  733. slaveComponentName: null,
  734. didInsertElement: function () {
  735. App.popover(this.$(), {
  736. title: Em.I18n.t('installer.controls.addSlaveComponentGroupButton.title').format(this.get('slaveComponentName')),
  737. content: Em.I18n.t('installer.controls.addSlaveComponentGroupButton.content').format(this.get('slaveComponentName'), this.get('slaveComponentName'), this.get('slaveComponentName')),
  738. placement: 'right',
  739. trigger: 'hover'
  740. });
  741. }
  742. });
  743. /**
  744. * Multiple Slave Hosts component
  745. * @type {*}
  746. */
  747. App.ServiceConfigSlaveHostsView = Ember.View.extend(App.ServiceConfigMultipleHostsDisplay, App.ServiceConfigCalculateId, {
  748. viewName: 'serviceConfigSlaveHostsView',
  749. classNames: ['slave-hosts', 'span6'],
  750. valueBinding: 'serviceConfig.value',
  751. templateName: require('templates/wizard/slave_hosts'),
  752. /**
  753. * Onclick handler for link
  754. */
  755. showHosts: function () {
  756. var serviceConfig = this.get('serviceConfig');
  757. App.ModalPopup.show({
  758. header: Em.I18n.t('installer.controls.serviceConfigMasterHosts.header').format(serviceConfig.category),
  759. bodyClass: Ember.View.extend({
  760. serviceConfig: serviceConfig,
  761. templateName: require('templates/wizard/master_hosts_popup')
  762. }),
  763. secondary: null
  764. });
  765. }
  766. });
  767. /**
  768. * properties for present active slave group
  769. * @type {*}
  770. */
  771. App.SlaveGroupPropertiesView = Ember.View.extend(App.ServiceConfigCalculateId, {
  772. viewName: 'serviceConfigSlaveHostsView',
  773. group: function () {
  774. return this.get('controller.activeGroup');
  775. }.property('controller.activeGroup'),
  776. groupConfigs: function () {
  777. console.log("************************************************************************");
  778. console.log("The value of group is: " + this.get('group'));
  779. console.log("************************************************************************");
  780. return this.get('group.properties');
  781. }.property('group.properties.@each').cacheable(),
  782. errorCount: function () {
  783. return this.get('group.properties').filterProperty('isValid', false).filterProperty('isVisible', true).get('length');
  784. }.property('configs.@each.isValid', 'configs.@each.isVisible')
  785. });
  786. /**
  787. * DropDown component for <code>select hosts for groups</code> popup
  788. * @type {*}
  789. */
  790. App.SlaveComponentDropDownGroupView = Ember.View.extend(App.ServiceConfigCalculateId, {
  791. viewName: "slaveComponentDropDownGroupView",
  792. /**
  793. * On change handler for <code>select hosts for groups</code> popup
  794. * @param event
  795. */
  796. changeGroup: function (event) {
  797. var host = this.get('content');
  798. var groupName = $('#' + this.get('elementId') + ' select').val();
  799. this.get('controller').changeHostGroup(host, groupName);
  800. },
  801. optionTag: Ember.View.extend({
  802. /**
  803. * Whether current value(OptionTag value) equals to host value(assigned to SlaveComponentDropDownGroupView.content)
  804. */
  805. selected: function () {
  806. return this.get('parentView.content.group') === this.get('content');
  807. }.property('content')
  808. })
  809. });
  810. /**
  811. * Show info about current group
  812. * @type {*}
  813. */
  814. App.SlaveComponentChangeGroupNameView = Ember.View.extend(App.ServiceConfigCalculateId, {
  815. contentBinding: 'controller.activeGroup',
  816. classNames: ['control-group'],
  817. classNameBindings: 'error',
  818. error: false,
  819. setError: function () {
  820. this.set('error', false);
  821. }.observes('controller.activeGroup'),
  822. errorMessage: function () {
  823. return this.get('error') ? Em.I18n.t('installer.controls.slaveComponentChangeGroupName.error') : '';
  824. }.property('error'),
  825. /**
  826. * Onclick handler for saving updated group name
  827. * @param event
  828. */
  829. changeGroupName: function (event) {
  830. var inputVal = $('#' + this.get('elementId') + ' input[type="text"]').val();
  831. if (inputVal !== this.get('content.name')) {
  832. var result = this.get('controller').changeSlaveGroupName(this.get('content'), inputVal);
  833. this.set('error', result);
  834. }
  835. }
  836. });
  837. /**
  838. * View for testing connection to database.
  839. **/
  840. App.CheckDBConnectionView = Ember.View.extend({
  841. templateName: require('templates/common/form/check_db_connection'),
  842. /** @property {string} btnCaption - text for button **/
  843. btnCaption: function() {
  844. return this.get('parentView.service.serviceName') === 'KERBEROS'
  845. ? Em.I18n.t('services.service.config.kdc.btn.idle')
  846. : Em.I18n.t('services.service.config.database.btn.idle')
  847. }.property('parentView.service.serviceName'),
  848. /** @property {string} responseCaption - text for status link **/
  849. responseCaption: null,
  850. /** @property {boolean} isConnecting - is request to server activated **/
  851. isConnecting: false,
  852. /** @property {boolean} isValidationPassed - check validation for required fields **/
  853. isValidationPassed: null,
  854. /** @property {string} databaseName- name of current database **/
  855. databaseName: null,
  856. /** @property {boolean} isRequestResolved - check for finished request to server **/
  857. isRequestResolved: false,
  858. /** @property {boolean} isConnectionSuccess - check for successful connection to database **/
  859. isConnectionSuccess: null,
  860. /** @property {string} responseFromServer - message from server response **/
  861. responseFromServer: null,
  862. /** @property {Object} ambariRequiredProperties - properties that need for custom action request **/
  863. ambariRequiredProperties: null,
  864. /** @property {Number} currentRequestId - current custom action request id **/
  865. currentRequestId: null,
  866. /** @property {Number} currentTaskId - current custom action task id **/
  867. currentTaskId: null,
  868. /** @property {jQuery.Deferred} request - current $.ajax request **/
  869. request: null,
  870. /** @property {Number} pollInterval - timeout interval for ajax polling **/
  871. pollInterval: 3000,
  872. /** @property {string} hostNameProperty - host name property based on service and database names **/
  873. hostNameProperty: function() {
  874. if (!/wizard/i.test(this.get('controller.name')) && this.get('parentView.service.serviceName') === 'HIVE') {
  875. return this.get('parentView.service.serviceName').toLowerCase() + '_hostname';
  876. } else if (this.get('parentView.service.serviceName') === 'KERBEROS') {
  877. return 'kdc_host';
  878. }
  879. return '{0}_existing_{1}_host'.format(this.get('parentView.service.serviceName').toLowerCase(), this.get('databaseName').toLowerCase());
  880. }.property('databaseName'),
  881. /** @property {boolean} isBtnDisabled - disable button on failed validation or active request **/
  882. isBtnDisabled: function() {
  883. return !this.get('isValidationPassed') || this.get('isConnecting');
  884. }.property('isValidationPassed', 'isConnecting'),
  885. /** @property {object} requiredProperties - properties that necessary for database connection **/
  886. requiredProperties: function() {
  887. var propertiesMap = {
  888. OOZIE: ['oozie.db.schema.name','oozie.service.JPAService.jdbc.username','oozie.service.JPAService.jdbc.password','oozie.service.JPAService.jdbc.driver','oozie.service.JPAService.jdbc.url'],
  889. HIVE: ['ambari.hive.db.schema.name','javax.jdo.option.ConnectionUserName','javax.jdo.option.ConnectionPassword','javax.jdo.option.ConnectionDriverName','javax.jdo.option.ConnectionURL'],
  890. KERBEROS: ['kdc_host']
  891. };
  892. return propertiesMap[this.get('parentView.service.serviceName')];
  893. }.property(),
  894. /** @property {Object} propertiesPattern - check pattern according to type of connection properties **/
  895. propertiesPattern: function() {
  896. var patterns = {
  897. db_connection_url: /jdbc\.url|connectionurl|kdc_host/ig
  898. };
  899. if (this.get('parentView.service.serviceName') != "KERBEROS") {
  900. patterns.user_name = /(username|dblogin)$/ig;
  901. patterns.user_passwd = /(dbpassword|password)$/ig;
  902. }
  903. return patterns;
  904. }.property('parentView.service.serviceName'),
  905. /** @property {String} masterHostName - host name location of Master Component related to Service **/
  906. masterHostName: function() {
  907. var serviceMasterMap = {
  908. 'OOZIE': 'oozieserver_host',
  909. 'HDFS': 'hadoop_host',
  910. 'HIVE': 'hive_ambari_host',
  911. 'KERBEROS': 'kdc_host'
  912. };
  913. return this.get('parentView.categoryConfigsAll').findProperty('name', serviceMasterMap[this.get('parentView.service.serviceName')]).get('value');
  914. }.property('parentView.service.serviceName', 'parentView.categoryConfigsAll.@each.value'),
  915. /** @property {Object} connectionProperties - service specific config values mapped for custom action request **/
  916. connectionProperties: function() {
  917. var propObj = {};
  918. for (var key in this.get('propertiesPattern')) {
  919. propObj[key] = this.getConnectionProperty(this.get('propertiesPattern')[key]);
  920. }
  921. return propObj;
  922. }.property('parentView.categoryConfigsAll.@each.value'),
  923. /**
  924. * Properties that stores in local storage used for handling
  925. * last success connection.
  926. *
  927. * @property {Object} preparedDBProperties
  928. **/
  929. preparedDBProperties: function() {
  930. var propObj = {};
  931. for (var key in this.get('propertiesPattern')) {
  932. var propName = this.getConnectionProperty(this.get('propertiesPattern')[key], true);
  933. propObj[propName] = this.get('parentView.categoryConfigsAll').findProperty('name', propName).get('value');
  934. }
  935. return propObj;
  936. }.property(),
  937. /** Check validation and load ambari properties **/
  938. didInsertElement: function() {
  939. var kdc = this.get('parentView.categoryConfigsAll').findProperty('name', 'kdc_type');
  940. if (kdc) {
  941. var name = kdc.get('value') == 'Existing MIT KDC' ? 'KDC' : 'AD';
  942. App.popover(this.$(), {
  943. title: Em.I18n.t('services.service.config.database.btn.idle'),
  944. content: Em.I18n.t('installer.controls.checkConnection.popover').format(name),
  945. placement: 'right',
  946. trigger: 'hover'
  947. });
  948. }
  949. this.handlePropertiesValidation();
  950. this.getAmbariProperties();
  951. },
  952. /** On view destroy **/
  953. willDestroyElement: function() {
  954. this.set('isConnecting', false);
  955. this._super();
  956. },
  957. /**
  958. * Observer that take care about enabling/disabling button based on required properties validation.
  959. *
  960. * @method handlePropertiesValidation
  961. **/
  962. handlePropertiesValidation: function() {
  963. this.restore();
  964. var isValid = true;
  965. var properties = [].concat(this.get('requiredProperties'));
  966. properties.push(this.get('hostNameProperty'));
  967. properties.forEach(function(propertyName) {
  968. var property = this.get('parentView.categoryConfigsAll').findProperty('name', propertyName);
  969. if(property && !property.get('isValid')) isValid = false;
  970. }, this);
  971. this.set('isValidationPassed', isValid);
  972. }.observes('parentView.categoryConfigsAll.@each.isValid', 'parentView.categoryConfigsAll.@each.value', 'databaseName'),
  973. getConnectionProperty: function(regexp, isGetName) {
  974. var _this = this;
  975. var propertyName = _this.get('requiredProperties').filter(function(item) {
  976. return regexp.test(item);
  977. })[0];
  978. return (isGetName) ? propertyName : _this.get('parentView.categoryConfigsAll').findProperty('name', propertyName).get('value');
  979. },
  980. /**
  981. * Set up ambari properties required for custom action request
  982. *
  983. * @method getAmbariProperties
  984. **/
  985. getAmbariProperties: function() {
  986. var clusterController = App.router.get('clusterController');
  987. var _this = this;
  988. if (!App.isEmptyObject(App.db.get('tmp', 'ambariProperties')) && !this.get('ambariProperties')) {
  989. this.set('ambariProperties', App.db.get('tmp', 'ambariProperties'));
  990. return;
  991. }
  992. if (App.isEmptyObject(clusterController.get('ambariProperties'))) {
  993. clusterController.loadAmbariProperties().done(function(data) {
  994. _this.formatAmbariProperties(data.RootServiceComponents.properties);
  995. });
  996. } else {
  997. this.formatAmbariProperties(clusterController.get('ambariProperties'));
  998. }
  999. },
  1000. formatAmbariProperties: function(properties) {
  1001. var defaults = {
  1002. threshold: "60",
  1003. ambari_server_host: location.hostname,
  1004. check_execute_list : "db_connection_check"
  1005. };
  1006. var properties = App.permit(properties, ['jdk.name','jdk_location','java.home']);
  1007. var renameKey = function(oldKey, newKey) {
  1008. if (properties[oldKey]) {
  1009. defaults[newKey] = properties[oldKey];
  1010. delete properties[oldKey];
  1011. }
  1012. };
  1013. renameKey('java.home', 'java_home');
  1014. renameKey('jdk.name', 'jdk_name');
  1015. $.extend(properties, defaults);
  1016. App.db.set('tmp', 'ambariProperties', properties);
  1017. this.set('ambariProperties', properties);
  1018. },
  1019. /**
  1020. * `Action` method for starting connect to current database.
  1021. *
  1022. * @method connectToDatabase
  1023. **/
  1024. connectToDatabase: function() {
  1025. if (this.get('isBtnDisabled')) return;
  1026. this.set('isRequestResolved', false);
  1027. App.db.set('tmp', this.get('parentView.service.serviceName') + '_connection', {});
  1028. this.setConnectingStatus(true);
  1029. if (App.get('testMode')) {
  1030. this.startPolling();
  1031. } else {
  1032. this.runCheckConnection();
  1033. }
  1034. },
  1035. /**
  1036. * runs check connections methods depending on service
  1037. * @return {void}
  1038. * @method runCheckConnection
  1039. */
  1040. runCheckConnection: function() {
  1041. if (this.get('parentView.service.serviceName') === 'KERBEROS') {
  1042. this.runKDCCheck();
  1043. } else {
  1044. this.createCustomAction();
  1045. }
  1046. },
  1047. /**
  1048. * send ajax request to perforn kdc host check
  1049. * @return {App.ajax}
  1050. * @method runKDCCheck
  1051. */
  1052. runKDCCheck: function() {
  1053. return App.ajax.send({
  1054. name: 'admin.kerberos_security.test_connection',
  1055. sender: this,
  1056. data: {
  1057. kdcHostname: this.get('masterHostName')
  1058. },
  1059. success: 'onRunKDCCheckSuccess',
  1060. error: 'onCreateActionError'
  1061. });
  1062. },
  1063. /**
  1064. *
  1065. * @param data
  1066. */
  1067. onRunKDCCheckSuccess: function(data) {
  1068. var statusCode = {
  1069. success: 'REACHABLE',
  1070. failed: 'UNREACHABLE'
  1071. };
  1072. if (data == statusCode['success']) {
  1073. this.setResponseStatus('success');
  1074. } else {
  1075. this.setResponseStatus('failed');
  1076. }
  1077. this.set('responseFromServer', data);
  1078. },
  1079. /**
  1080. * Run custom action for database connection.
  1081. *
  1082. * @method createCustomAction
  1083. **/
  1084. createCustomAction: function() {
  1085. var dbName = this.get('databaseName').toLowerCase() === 'postgresql' ? 'postgres' : this.get('databaseName').toLowerCase();
  1086. var params = $.extend(true, {}, { db_name: dbName }, this.get('connectionProperties'), this.get('ambariProperties'));
  1087. App.ajax.send({
  1088. name: 'custom_action.create',
  1089. sender: this,
  1090. data: {
  1091. requestInfo: {
  1092. parameters: params
  1093. },
  1094. filteredHosts: [this.get('masterHostName')]
  1095. },
  1096. success: 'onCreateActionSuccess',
  1097. error: 'onCreateActionError'
  1098. });
  1099. },
  1100. /**
  1101. * Run updater if task is created successfully.
  1102. *
  1103. * @method onConnectActionS
  1104. **/
  1105. onCreateActionSuccess: function(data) {
  1106. this.set('currentRequestId', data.Requests.id);
  1107. App.ajax.send({
  1108. name: 'custom_action.request',
  1109. sender: this,
  1110. data: {
  1111. requestId: this.get('currentRequestId')
  1112. },
  1113. success: 'setCurrentTaskId'
  1114. });
  1115. },
  1116. setCurrentTaskId: function(data) {
  1117. this.set('currentTaskId', data.items[0].Tasks.id);
  1118. this.startPolling();
  1119. },
  1120. startPolling: function() {
  1121. if (this.get('isConnecting'))
  1122. this.getTaskInfo();
  1123. },
  1124. getTaskInfo: function() {
  1125. var request = App.ajax.send({
  1126. name: 'custom_action.request',
  1127. sender: this,
  1128. data: {
  1129. requestId: this.get('currentRequestId'),
  1130. taskId: this.get('currentTaskId')
  1131. },
  1132. success: 'getTaskInfoSuccess'
  1133. });
  1134. this.set('request', request);
  1135. },
  1136. getTaskInfoSuccess: function(data) {
  1137. var task = data.Tasks;
  1138. this.set('responseFromServer', {
  1139. stderr: task.stderr,
  1140. stdout: task.stdout
  1141. });
  1142. if (task.status === 'COMPLETED') {
  1143. var structuredOut = task.structured_out.db_connection_check;
  1144. if (structuredOut.exit_code != 0) {
  1145. this.set('responseFromServer', {
  1146. stderr: task.stderr,
  1147. stdout: task.stdout,
  1148. structuredOut: structuredOut.message
  1149. });
  1150. this.setResponseStatus('failed');
  1151. } else {
  1152. App.db.set('tmp', this.get('parentView.service.serviceName') + '_connection', this.get('preparedDBProperties'));
  1153. this.setResponseStatus('success');
  1154. }
  1155. }
  1156. if (task.status === 'FAILED') {
  1157. this.setResponseStatus('failed');
  1158. }
  1159. if (/PENDING|QUEUED|IN_PROGRESS/.test(task.status)) {
  1160. Em.run.later(this, function() {
  1161. this.startPolling();
  1162. }, this.get('pollInterval'));
  1163. }
  1164. },
  1165. onCreateActionError: function(jqXhr, status, errorMessage) {
  1166. this.setResponseStatus('failed');
  1167. this.set('responseFromServer', errorMessage);
  1168. },
  1169. setResponseStatus: function(isSuccess) {
  1170. var isSuccess = isSuccess == 'success';
  1171. this.setConnectingStatus(false);
  1172. this.set('responseCaption', isSuccess ? Em.I18n.t('services.service.config.database.connection.success') : Em.I18n.t('services.service.config.database.connection.failed'));
  1173. this.set('isConnectionSuccess', isSuccess);
  1174. this.set('isRequestResolved', true);
  1175. },
  1176. /**
  1177. * Switch captions and statuses for active/non-active request.
  1178. *
  1179. * @method setConnectionStatus
  1180. * @param {Boolean} [active]
  1181. */
  1182. setConnectingStatus: function(active) {
  1183. if (active) {
  1184. this.set('responseCaption', Em.I18n.t('services.service.config.database.connection.inProgress'));
  1185. }
  1186. this.set('controller.testConnectionInProgress', !!active);
  1187. this.set('btnCaption', !!active ? Em.I18n.t('services.service.config.database.btn.connecting') : Em.I18n.t('services.service.config.database.btn.idle'));
  1188. this.set('isConnecting', !!active);
  1189. },
  1190. /**
  1191. * Set view to init status.
  1192. *
  1193. * @method restore
  1194. **/
  1195. restore: function() {
  1196. if (this.get('request')) {
  1197. this.get('request').abort();
  1198. this.set('request', null);
  1199. }
  1200. this.set('responseCaption', null);
  1201. this.set('responseFromServer', null);
  1202. this.setConnectingStatus(false);
  1203. this.set('isRequestResolved', false);
  1204. },
  1205. /**
  1206. * `Action` method for showing response from server in popup.
  1207. *
  1208. * @method showLogsPopup
  1209. **/
  1210. showLogsPopup: function() {
  1211. if (this.get('isConnectionSuccess')) return;
  1212. var _this = this;
  1213. var popup = App.showAlertPopup('Error: {0} connection'.format(this.get('databaseName')));
  1214. if (typeof this.get('responseFromServer') == 'object') {
  1215. popup.set('bodyClass', Em.View.extend({
  1216. templateName: require('templates/common/error_log_body'),
  1217. openedTask: _this.get('responseFromServer')
  1218. }));
  1219. } else {
  1220. popup.set('body', this.get('responseFromServer'));
  1221. }
  1222. return popup;
  1223. }
  1224. });
  1225. /**
  1226. *
  1227. * @type {*}
  1228. */
  1229. App.BaseUrlTextField = Ember.TextField.extend({
  1230. valueBinding: 'repository.baseUrl',
  1231. keyUp: function (event) {
  1232. if (Em.get(this, 'repository.hasError')) {
  1233. Em.set(this, 'repository.hasError', false);
  1234. }
  1235. }
  1236. });