definition_configs_controller.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  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. App.MainAlertDefinitionConfigsController = Em.Controller.extend({
  19. name: 'mainAlertDefinitionConfigsController',
  20. /**
  21. * All configurable properties of alert definition
  22. * @type {Array}
  23. */
  24. configs: [],
  25. /**
  26. * Define whether configs are editable
  27. * binds to property populated in template
  28. * @type {Boolean}
  29. */
  30. canEdit: true,
  31. /**
  32. * Define configs view mode (Wizard or Definition Details page)
  33. * @type {Boolean}
  34. */
  35. isWizard: false,
  36. /**
  37. * Alert Definition type
  38. * binding is set in template
  39. * @type {String}
  40. */
  41. alertDefinitionType: '',
  42. /**
  43. * Array of displayNames of all services
  44. * is used for "Service" config options
  45. * @type {Array}
  46. */
  47. allServices: function () {
  48. return App.Service.find().mapProperty('displayName');
  49. }.property(),
  50. /**
  51. * All possible values for scope propery
  52. * @type {Array}
  53. */
  54. allScopes: ['Any', 'Host', 'Service'],
  55. /**
  56. * Array of all aggregate-alerts names
  57. * @type {Array}
  58. */
  59. aggregateAlertNames: function () {
  60. return App.AggregateAlertDefinition.find().mapProperty('name');
  61. }.property(),
  62. /**
  63. * Change options of "Component", after changing value of "Service" config
  64. * @method onServiceSelect
  65. */
  66. onServiceSelect: function () {
  67. var serviceProperty = this.get('configs').findProperty('name', 'service');
  68. if (serviceProperty && serviceProperty.get('value') !== 'Ambari') {
  69. var componentsProperty = this.get('configs').findProperty('name', 'component');
  70. componentsProperty.set('options', ['No component'].concat(App.HostComponent.find().filterProperty('service.displayName', serviceProperty.get('value')).mapProperty('displayName').uniq()));
  71. }
  72. }.observes('configs.@each.value'),
  73. /**
  74. * OnSelect handler for <code>select_type</code> property
  75. * disable fields related to definition type and set options to select lists
  76. */
  77. changeType: function (selectedType) {
  78. if (selectedType === 'alert_type_service') {
  79. this.get('configs').findProperty('name', 'service').setProperties({
  80. isDisabled: false,
  81. options: this.get('allServices'),
  82. value: this.get('allServices')[0]
  83. });
  84. this.get('configs').findProperty('name', 'component').setProperties({
  85. isDisabled: false,
  86. value: 'No component'
  87. });
  88. this.get('configs').findProperty('name', 'scope').setProperties({
  89. isDisabled: false,
  90. options: this.get('allScopes'),
  91. value: this.get('allScopes')[0]
  92. });
  93. } else {
  94. this.get('configs').findProperty('name', 'service').setProperties({
  95. isDisabled: true,
  96. options: ['Ambari'],
  97. value: 'Ambari'
  98. });
  99. this.get('configs').findProperty('name', 'component').setProperties({
  100. isDisabled: true,
  101. options: ['Ambari Agent'],
  102. value: 'Ambari Agent'
  103. });
  104. this.get('configs').findProperty('name', 'scope').setProperties({
  105. isDisabled: true,
  106. options: ['Host'],
  107. value: 'Host'
  108. });
  109. }
  110. },
  111. /**
  112. * @return {string|Null}
  113. * @method getThresholdsProperty
  114. */
  115. getThresholdsProperty: function (type, property) {
  116. var warning = this.get('content.reporting').findProperty('type', type);
  117. return warning && warning.get(property) ? warning.get(property) : null;
  118. },
  119. /**
  120. * Render array of configs for appropriate alert definition type
  121. * @method renderConfigs
  122. */
  123. renderConfigs: function () {
  124. var alertDefinitionType = this.get('alertDefinitionType');
  125. var configs = [];
  126. switch (alertDefinitionType) {
  127. case 'PORT':
  128. configs = this.renderPortConfigs();
  129. break;
  130. case 'METRIC':
  131. configs = this.renderMetricConfigs();
  132. break;
  133. case 'WEB':
  134. configs = this.renderWebConfigs();
  135. break;
  136. case 'SCRIPT':
  137. configs = this.renderScriptConfigs();
  138. break;
  139. case 'AGGREGATE':
  140. configs = this.renderAggregateConfigs();
  141. break;
  142. case 'SERVER':
  143. configs = this.renderServerConfigs();
  144. break;
  145. case 'RECOVERY':
  146. configs = this.renderWebConfigs();
  147. break;
  148. default:
  149. }
  150. configs.setEach('isDisabled', !this.get('canEdit'));
  151. this.set('configs', configs);
  152. },
  153. /**
  154. * Render config properties for port-type alert definition
  155. * @method renderPortConfigs
  156. * @returns {App.AlertConfigProperty[]}
  157. */
  158. renderPortConfigs: function () {
  159. var result = [];
  160. var alertDefinition = this.get('content');
  161. var isWizard = this.get('isWizard');
  162. if (this.get('isWizard')) {
  163. result = result.concat(this.renderCommonWizardConfigs());
  164. }
  165. result = result.concat([
  166. App.AlertConfigProperties.Description.create({
  167. value: isWizard ? '' : alertDefinition.get('description')
  168. }),
  169. App.AlertConfigProperties.Interval.create({
  170. value: isWizard ? '' : alertDefinition.get('interval')
  171. }),
  172. App.AlertConfigProperties.Thresholds.OkThreshold.create({
  173. label: 'Thresholds',
  174. showInputForValue: false,
  175. text: isWizard ? '' : this.getThresholdsProperty('ok', 'text'),
  176. value: isWizard ? '' : this.getThresholdsProperty('ok', 'value')
  177. }),
  178. App.AlertConfigProperties.Thresholds.WarningThreshold.create(App.AlertConfigProperties.Thresholds.PositiveMixin, {
  179. valueMetric: 'Seconds',
  180. text: isWizard ? '' : this.getThresholdsProperty('warning', 'text'),
  181. value: isWizard ? '' : this.getThresholdsProperty('warning', 'value')
  182. }),
  183. App.AlertConfigProperties.Thresholds.CriticalThreshold.create(App.AlertConfigProperties.Thresholds.PositiveMixin, {
  184. valueMetric: 'Seconds',
  185. text: isWizard ? '' : this.getThresholdsProperty('critical', 'text'),
  186. value: isWizard ? '' : this.getThresholdsProperty('critical', 'value')
  187. })
  188. ]);
  189. return result;
  190. },
  191. /**
  192. * Render config properties for metric-type alert definition
  193. * @method renderMetricConfigs
  194. * @returns {App.AlertConfigProperty[]}
  195. */
  196. renderMetricConfigs: function () {
  197. var result = [];
  198. var alertDefinition = this.get('content');
  199. var isWizard = this.get('isWizard');
  200. var units = this.get('content.reporting').findProperty('type','units') ?
  201. this.get('content.reporting').findProperty('type','units').get('text'): null;
  202. if (this.get('isWizard')) {
  203. result = result.concat(this.renderCommonWizardConfigs());
  204. }
  205. result = result.concat([
  206. App.AlertConfigProperties.Description.create({
  207. value: isWizard ? '' : alertDefinition.get('description')
  208. }),
  209. App.AlertConfigProperties.Interval.create({
  210. value: isWizard ? '' : alertDefinition.get('interval')
  211. }),
  212. App.AlertConfigProperties.Thresholds.OkThreshold.create({
  213. label: 'Thresholds',
  214. showInputForValue: false,
  215. text: isWizard ? '' : this.getThresholdsProperty('ok', 'text'),
  216. value: isWizard ? '' : this.getThresholdsProperty('ok', 'value')
  217. }),
  218. App.AlertConfigProperties.Thresholds.WarningThreshold.create({
  219. valueMetric: units,
  220. text: isWizard ? '' : this.getThresholdsProperty('warning', 'text'),
  221. value: isWizard ? '' : this.getThresholdsProperty('warning', 'value')
  222. }),
  223. App.AlertConfigProperties.Thresholds.CriticalThreshold.create({
  224. valueMetric: units,
  225. text: isWizard ? '' : this.getThresholdsProperty('critical', 'text'),
  226. value: isWizard ? '' : this.getThresholdsProperty('critical', 'value')
  227. })
  228. ]);
  229. return result;
  230. },
  231. /**
  232. * Render config properties for web-type alert definition
  233. * @method renderWebConfigs
  234. * @returns {App.AlertConfigProperty[]}
  235. */
  236. renderWebConfigs: function () {
  237. var result = [];
  238. var alertDefinition = this.get('content');
  239. var isWizard = this.get('isWizard');
  240. if (this.get('isWizard')) {
  241. result = result.concat(this.renderCommonWizardConfigs());
  242. }
  243. result = result.concat([
  244. App.AlertConfigProperties.Description.create({
  245. value: isWizard ? '' : alertDefinition.get('description')
  246. }),
  247. App.AlertConfigProperties.Interval.create({
  248. value: isWizard ? '' : alertDefinition.get('interval')
  249. }),
  250. App.AlertConfigProperties.Thresholds.OkThreshold.create({
  251. label: 'Thresholds',
  252. showInputForValue: false,
  253. text: isWizard ? '' : this.getThresholdsProperty('ok', 'text'),
  254. value: isWizard ? '' : this.getThresholdsProperty('ok', 'value')
  255. }),
  256. App.AlertConfigProperties.Thresholds.WarningThreshold.create({
  257. showInputForValue: false,
  258. text: isWizard ? '' : this.getThresholdsProperty('warning', 'text'),
  259. value: isWizard ? '' : this.getThresholdsProperty('warning', 'value')
  260. }),
  261. App.AlertConfigProperties.Thresholds.CriticalThreshold.create({
  262. showInputForValue: false,
  263. text: isWizard ? '' : this.getThresholdsProperty('critical', 'text'),
  264. value: isWizard ? '' : this.getThresholdsProperty('critical', 'value')
  265. }),
  266. App.AlertConfigProperties.ConnectionTimeout.create({
  267. value: alertDefinition.get('uri.connectionTimeout')
  268. })
  269. ]);
  270. return result;
  271. },
  272. /**
  273. * Render config properties for script-type alert definition
  274. * @method renderScriptConfigs
  275. * @returns {App.AlertConfigProperty[]}
  276. */
  277. renderScriptConfigs: function () {
  278. var result = [];
  279. var alertDefinition = this.get('content');
  280. var isWizard = this.get('isWizard');
  281. if (this.get('isWizard')) {
  282. result = result.concat(this.renderCommonWizardConfigs());
  283. }
  284. result = result.concat([
  285. App.AlertConfigProperties.Description.create({
  286. value: isWizard ? '' : alertDefinition.get('description')
  287. }),
  288. App.AlertConfigProperties.Interval.create({
  289. value: isWizard ? '' : alertDefinition.get('interval')
  290. })
  291. ]);
  292. var mixins = {
  293. STRING: App.AlertConfigProperties.Parameters.StringMixin,
  294. NUMERIC: App.AlertConfigProperties.Parameters.NumericMixin,
  295. PERCENT: App.AlertConfigProperties.Parameters.PercentageMixin
  296. };
  297. alertDefinition.get('parameters').forEach(function (parameter) {
  298. var mixin = mixins[parameter.get('type')] || {}; // validation depends on parameter-type
  299. result.push(App.AlertConfigProperties.Parameter.create(mixin, {
  300. value: isWizard ? '' : parameter.get('value'),
  301. apiProperty: parameter.get('name'),
  302. label: isWizard ? '' : parameter.get('displayName'),
  303. threshold: isWizard ? '' : parameter.get('threshold'),
  304. units: isWizard ? '' : parameter.get('units'),
  305. type: isWizard ? '' : parameter.get('type'),
  306. }));
  307. });
  308. return result;
  309. },
  310. /**
  311. * Render config properties for aggregate-type alert definition
  312. * @method renderAggregateConfigs
  313. * @returns {App.AlertConfigProperty[]}
  314. */
  315. renderAggregateConfigs: function () {
  316. var isWizard = this.get('isWizard');
  317. var alertDefinition = this.get('content');
  318. return [
  319. App.AlertConfigProperties.Description.create({
  320. value: isWizard ? '' : alertDefinition.get('description')
  321. }),
  322. App.AlertConfigProperties.Interval.create({
  323. value: isWizard ? '' : alertDefinition.get('interval')
  324. }),
  325. App.AlertConfigProperties.Thresholds.OkThreshold.create({
  326. label: 'Thresholds',
  327. showInputForValue: false,
  328. text: isWizard ? '' : this.getThresholdsProperty('ok', 'text'),
  329. value: isWizard ? '' : this.getThresholdsProperty('ok', 'value')
  330. }),
  331. App.AlertConfigProperties.Thresholds.WarningThreshold.create(App.AlertConfigProperties.Thresholds.PercentageMixin, {
  332. text: isWizard ? '' : this.getThresholdsProperty('warning', 'text'),
  333. value: isWizard ? '' : this.getThresholdsProperty('warning', 'value'),
  334. valueMetric: '%'
  335. }),
  336. App.AlertConfigProperties.Thresholds.CriticalThreshold.create(App.AlertConfigProperties.Thresholds.PercentageMixin, {
  337. text: isWizard ? '' : this.getThresholdsProperty('critical', 'text'),
  338. value: isWizard ? '' : this.getThresholdsProperty('critical', 'value'),
  339. valueMetric: '%'
  340. })
  341. ];
  342. },
  343. /**
  344. * Render config properties for server-type alert definition
  345. * @method renderScriptConfigs
  346. * @returns {App.AlertConfigProperty[]}
  347. */
  348. renderServerConfigs: function () {
  349. var result = [];
  350. var alertDefinition = this.get('content');
  351. var isWizard = this.get('isWizard');
  352. if (this.get('isWizard')) {
  353. result = result.concat(this.renderCommonWizardConfigs());
  354. }
  355. result = result.concat([
  356. App.AlertConfigProperties.Description.create({
  357. value: isWizard ? '' : alertDefinition.get('description')
  358. }),
  359. App.AlertConfigProperties.Interval.create({
  360. value: isWizard ? '' : alertDefinition.get('interval')
  361. })
  362. ]);
  363. return result;
  364. },
  365. /**
  366. * Render common list of configs used in almost all alert types in wizard
  367. * @returns {App.AlertConfigProperty[]}
  368. */
  369. renderCommonWizardConfigs: function () {
  370. return [
  371. App.AlertConfigProperties.AlertName.create({
  372. value: ''
  373. }),
  374. App.AlertConfigProperties.ServiceAlertType.create({
  375. value: true
  376. }),
  377. App.AlertConfigProperties.Service.create({
  378. options: this.get('allServices'),
  379. value: this.get('allServices')[0],
  380. isShifted: true
  381. }),
  382. App.AlertConfigProperties.Component.create({
  383. options: this.get('allComponents'),
  384. value: 'No component',
  385. isShifted: true
  386. }),
  387. App.AlertConfigProperties.Scope.create({
  388. options: this.get('allScopes'),
  389. isShifted: true
  390. }),
  391. App.AlertConfigProperties.HostAlertType.create({
  392. value: false
  393. })
  394. ];
  395. },
  396. /**
  397. * Edit configs button handler
  398. * @method editConfigs
  399. */
  400. editConfigs: function () {
  401. this.get('configs').forEach(function (property) {
  402. property.set('previousValue', property.get('value'));
  403. property.set('previousText', property.get('text'));
  404. });
  405. this.get('configs').setEach('isDisabled', false);
  406. this.set('canEdit', true);
  407. },
  408. /**
  409. * Cancel edit configs button handler
  410. * @method cancelEditConfigs
  411. */
  412. cancelEditConfigs: function () {
  413. this.get('configs').forEach(function (property) {
  414. property.set('value', property.get('previousValue'));
  415. property.set('text', property.get('previousText'));
  416. });
  417. this.get('configs').setEach('isDisabled', true);
  418. this.set('canEdit', false);
  419. },
  420. /**
  421. * Save edit configs button handler
  422. * @method saveConfigs
  423. * @return {$.ajax}
  424. */
  425. saveConfigs: function () {
  426. this.get('configs').setEach('isDisabled', true);
  427. this.set('canEdit', false);
  428. return App.ajax.send({
  429. name: 'alerts.update_alert_definition',
  430. sender: this,
  431. data: {
  432. id: this.get('content.id'),
  433. data: this.getPropertiesToUpdate(true)
  434. },
  435. success: 'saveConfigsSuccessCallback'
  436. });
  437. },
  438. /**
  439. * Success-callback for saveConfigs-request
  440. * @method saveConfigsSuccessCallback
  441. */
  442. saveConfigsSuccessCallback: function () {
  443. App.router.get('updateController').updateAlertDefinitions(Em.K);
  444. },
  445. /**
  446. * Create object with new values to put it on server
  447. * @param {boolean} onlyChanged
  448. * @method getPropertiesToUpdate
  449. * @returns {Object}
  450. */
  451. getPropertiesToUpdate: function (onlyChanged) {
  452. var propertiesToUpdate = {};
  453. var configs = onlyChanged ? this.get('configs').filterProperty('wasChanged') : this.get('configs');
  454. configs = configs.filter(function (c) {
  455. return c.get('name') !== 'parameter';
  456. });
  457. configs.forEach(function (property) {
  458. var apiProperties = property.get('apiProperty');
  459. var apiFormattedValues = property.get('apiFormattedValue');
  460. if (!Em.isArray(property.get('apiProperty'))) {
  461. apiProperties = [property.get('apiProperty')];
  462. apiFormattedValues = [property.get('apiFormattedValue')];
  463. }
  464. apiProperties.forEach(function (apiProperty, i) {
  465. if (apiProperty.contains('source.')) {
  466. if (!propertiesToUpdate['AlertDefinition/source']) {
  467. if (this.get('content.rawSourceData')) {
  468. propertiesToUpdate['AlertDefinition/source'] = this.get('content.rawSourceData');
  469. }
  470. }
  471. if (this.get('content.rawSourceData')) {
  472. // use rawSourceData to populate propertiesToUpdate
  473. var sourcePath = propertiesToUpdate['AlertDefinition/source'];
  474. apiProperty.replace('source.', '').split('.').forEach(function (path, index, array) {
  475. // check if it is last path
  476. if (array.length - index === 1) {
  477. sourcePath[path] = apiFormattedValues[i];
  478. } else {
  479. sourcePath = sourcePath[path];
  480. }
  481. });
  482. }
  483. else {
  484. if (!propertiesToUpdate['AlertDefinition/source']) {
  485. propertiesToUpdate['AlertDefinition/source'] = {};
  486. }
  487. Ember.setFullPath(propertiesToUpdate['AlertDefinition/source'], apiProperty.replace('source.', ''), apiFormattedValues[i]);
  488. }
  489. }
  490. else {
  491. if (apiProperty) {
  492. propertiesToUpdate['AlertDefinition/' + apiProperty] = apiFormattedValues[i];
  493. }
  494. }
  495. }, this);
  496. }, this);
  497. // `source.parameters` is an array and should be updated separately from other configs
  498. if (this.get('content.parameters.length')) {
  499. propertiesToUpdate['AlertDefinition/source/parameters'] = this.get('content.rawSourceData.parameters');
  500. var parameterConfigs = this.get('configs').filterProperty('name', 'parameter');
  501. parameterConfigs.forEach(function (parameter) {
  502. propertiesToUpdate['AlertDefinition/source/parameters'].findProperty('name', parameter.get('apiProperty')).value = parameter.get('apiFormattedValue');
  503. });
  504. }
  505. return propertiesToUpdate;
  506. },
  507. /**
  508. * Return array of all config values
  509. * used to save configs to local db in wizard
  510. * @method getConfigsValues
  511. * @returns {Array}
  512. */
  513. getConfigsValues: function () {
  514. return this.get('configs').map(function (property) {
  515. return {
  516. name: property.get('name'),
  517. value: property.get('value')
  518. }
  519. });
  520. },
  521. /**
  522. * Define whether critical threshold >= critical threshold
  523. * @type {Boolean}
  524. */
  525. hasThresholdsError: function () {
  526. var smallValue, smallValid, largeValue, largeValid;
  527. if (this.get('configs').findProperty('name', 'warning_threshold')) {
  528. smallValue = Em.get(this.get('configs').findProperty('name', 'warning_threshold'), 'value');
  529. smallValid = Em.get(this.get('configs').findProperty('name', 'warning_threshold'), 'isValid');
  530. }
  531. if (this.get('configs').findProperty('name', 'critical_threshold')) {
  532. largeValue = Em.get(this.get('configs').findProperty('name', 'critical_threshold'), 'value');
  533. largeValid = Em.get(this.get('configs').findProperty('name', 'critical_threshold'), 'isValid');
  534. }
  535. return smallValid && largeValid ? Number(smallValue) > Number(largeValue) : false;
  536. }.property('configs.@each.value'),
  537. someConfigIsInvalid: Em.computed.someBy('configs', 'isValid', false),
  538. /**
  539. * Define whether all configs are valid
  540. * @type {Boolean}
  541. */
  542. hasErrors: Em.computed.or('someConfigIsInvalid', 'hasThresholdsError')
  543. });