definition_configs_controller.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  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').set('isDisabled', false).set('options', this.get('allServices')).set('value', this.get('allServices')[0]);
  80. this.get('configs').findProperty('name', 'component').set('isDisabled', false).set('value', 'No component');
  81. this.get('configs').findProperty('name', 'scope').set('isDisabled', false).set('options', this.get('allScopes')).set('value', this.get('allScopes')[0]);
  82. } else {
  83. this.get('configs').findProperty('name', 'service').set('isDisabled', true).set('options', ['Ambari']).set('value', 'Ambari');
  84. this.get('configs').findProperty('name', 'component').set('isDisabled', true).set('options', ['Ambari Agent']).set('value', 'Ambari Agent');
  85. this.get('configs').findProperty('name', 'scope').set('isDisabled', true).set('options', ['Host']).set('value', 'Host');
  86. }
  87. },
  88. /**
  89. * @return {string|Null}
  90. * @method getThresholdsProperty
  91. */
  92. getThresholdsProperty: function (type, property) {
  93. var warning = this.get('content.reporting').findProperty('type', type);
  94. if (warning && warning.get(property)) {
  95. return warning.get(property);
  96. } else {
  97. return null;
  98. }
  99. },
  100. /**
  101. * Render array of configs for appropriate alert definition type
  102. * @method renderConfigs
  103. */
  104. renderConfigs: function () {
  105. var alertDefinitionType = this.get('alertDefinitionType');
  106. var configs = [];
  107. switch (alertDefinitionType) {
  108. case 'PORT':
  109. configs = this.renderPortConfigs();
  110. break;
  111. case 'METRIC':
  112. configs = this.renderMetricConfigs();
  113. break;
  114. case 'WEB':
  115. configs = this.renderWebConfigs();
  116. break;
  117. case 'SCRIPT':
  118. configs = this.renderScriptConfigs();
  119. break;
  120. case 'AGGREGATE':
  121. configs = this.renderAggregateConfigs();
  122. break;
  123. default:
  124. console.error('Incorrect Alert Definition Type: ', alertDefinitionType);
  125. }
  126. configs.setEach('isDisabled', !this.get('canEdit'));
  127. configs.setEach('allConfigs', configs);
  128. this.set('configs', configs);
  129. },
  130. /**
  131. * Render config properties for port-type alert definition
  132. * @method renderPortConfigs
  133. * @returns {App.AlertConfigProperty[]}
  134. */
  135. renderPortConfigs: function () {
  136. var result = [];
  137. var alertDefinition = this.get('content');
  138. var isWizard = this.get('isWizard');
  139. if (this.get('isWizard')) {
  140. result = result.concat(this.renderCommonWizardConfigs());
  141. }
  142. result = result.concat([
  143. App.AlertConfigProperties.Description.create({
  144. value: isWizard ? '' : alertDefinition.get('description')
  145. }),
  146. App.AlertConfigProperties.Interval.create({
  147. value: isWizard ? '' : alertDefinition.get('interval')
  148. }),
  149. App.AlertConfigProperties.Thresholds.OkThreshold.create({
  150. label: 'Thresholds',
  151. showInputForValue: false,
  152. text: isWizard ? '' : this.getThresholdsProperty('ok', 'text'),
  153. value: isWizard ? '' : this.getThresholdsProperty('ok', 'value')
  154. }),
  155. App.AlertConfigProperties.Thresholds.WarningThreshold.create({
  156. valueMetric: 'Sec',
  157. text: isWizard ? '' : this.getThresholdsProperty('warning', 'text'),
  158. value: isWizard ? '' : this.getThresholdsProperty('warning', 'value')
  159. }),
  160. App.AlertConfigProperties.Thresholds.CriticalThreshold.create({
  161. valueMetric: 'Sec',
  162. text: isWizard ? '' : this.getThresholdsProperty('critical', 'text'),
  163. value: isWizard ? '' : this.getThresholdsProperty('critical', 'value')
  164. })
  165. ]);
  166. return result;
  167. },
  168. /**
  169. * Render config properties for metric-type alert definition
  170. * @method renderMetricConfigs
  171. * @returns {App.AlertConfigProperty[]}
  172. */
  173. renderMetricConfigs: function () {
  174. var result = [];
  175. var alertDefinition = this.get('content');
  176. var isWizard = this.get('isWizard');
  177. if (this.get('isWizard')) {
  178. result = result.concat(this.renderCommonWizardConfigs());
  179. }
  180. result = result.concat([
  181. App.AlertConfigProperties.Description.create({
  182. value: isWizard ? '' : alertDefinition.get('description')
  183. }),
  184. App.AlertConfigProperties.Interval.create({
  185. value: isWizard ? '' : alertDefinition.get('interval')
  186. }),
  187. App.AlertConfigProperties.Thresholds.OkThreshold.create({
  188. label: 'Thresholds',
  189. showInputForValue: false,
  190. text: isWizard ? '' : this.getThresholdsProperty('ok', 'text'),
  191. value: isWizard ? '' : this.getThresholdsProperty('ok', 'value')
  192. }),
  193. App.AlertConfigProperties.Thresholds.WarningThreshold.create({
  194. text: isWizard ? '' : this.getThresholdsProperty('warning', 'text'),
  195. value: isWizard ? '' : this.getThresholdsProperty('warning', 'value')
  196. }),
  197. App.AlertConfigProperties.Thresholds.CriticalThreshold.create({
  198. text: isWizard ? '' : this.getThresholdsProperty('critical', 'text'),
  199. value: isWizard ? '' : this.getThresholdsProperty('critical', 'value')
  200. })
  201. ]);
  202. return result;
  203. },
  204. /**
  205. * Render config properties for web-type alert definition
  206. * @method renderWebConfigs
  207. * @returns {App.AlertConfigProperty[]}
  208. */
  209. renderWebConfigs: function () {
  210. var result = [];
  211. var alertDefinition = this.get('content');
  212. var isWizard = this.get('isWizard');
  213. if (this.get('isWizard')) {
  214. result = result.concat(this.renderCommonWizardConfigs());
  215. }
  216. result = result.concat([
  217. App.AlertConfigProperties.Description.create({
  218. value: isWizard ? '' : alertDefinition.get('description')
  219. }),
  220. App.AlertConfigProperties.Interval.create({
  221. value: isWizard ? '' : alertDefinition.get('interval')
  222. }),
  223. App.AlertConfigProperties.Thresholds.OkThreshold.create({
  224. label: 'Thresholds',
  225. showInputForValue: false,
  226. text: isWizard ? '' : this.getThresholdsProperty('ok', 'text'),
  227. value: isWizard ? '' : this.getThresholdsProperty('ok', 'value')
  228. }),
  229. App.AlertConfigProperties.Thresholds.WarningThreshold.create({
  230. showInputForValue: false,
  231. text: isWizard ? '' : this.getThresholdsProperty('warning', 'text'),
  232. value: isWizard ? '' : this.getThresholdsProperty('warning', 'value')
  233. }),
  234. App.AlertConfigProperties.Thresholds.CriticalThreshold.create({
  235. showInputForValue: false,
  236. text: isWizard ? '' : this.getThresholdsProperty('critical', 'text'),
  237. value: isWizard ? '' : this.getThresholdsProperty('critical', 'value')
  238. })
  239. ]);
  240. return result;
  241. },
  242. /**
  243. * Render config properties for script-type alert definition
  244. * @method renderScriptConfigs
  245. * @returns {App.AlertConfigProperty[]}
  246. */
  247. renderScriptConfigs: function () {
  248. var result = [];
  249. var alertDefinition = this.get('content');
  250. var isWizard = this.get('isWizard');
  251. if (this.get('isWizard')) {
  252. result = result.concat(this.renderCommonWizardConfigs());
  253. }
  254. result = result.concat([
  255. App.AlertConfigProperties.Description.create({
  256. value: isWizard ? '' : alertDefinition.get('description')
  257. }),
  258. App.AlertConfigProperties.Interval.create({
  259. value: isWizard ? '' : alertDefinition.get('interval')
  260. }),
  261. App.AlertConfigProperties.Thresholds.OkThreshold.create({
  262. label: 'Thresholds',
  263. showInputForValue: false,
  264. text: isWizard ? '' : this.getThresholdsProperty('ok', 'text'),
  265. value: isWizard ? '' : this.getThresholdsProperty('ok', 'value')
  266. }),
  267. App.AlertConfigProperties.Thresholds.WarningThreshold.create({
  268. showInputForValue: false,
  269. text: isWizard ? '' : this.getThresholdsProperty('warning', 'text'),
  270. value: isWizard ? '' : this.getThresholdsProperty('warning', 'value')
  271. }),
  272. App.AlertConfigProperties.Thresholds.CriticalThreshold.create({
  273. showInputForValue: false,
  274. text: isWizard ? '' : this.getThresholdsProperty('critical', 'text'),
  275. value: isWizard ? '' : this.getThresholdsProperty('critical', 'value')
  276. })
  277. ]);
  278. return result;
  279. },
  280. /**
  281. * Render config properties for aggregate-type alert definition
  282. * @method renderAggregateConfigs
  283. * @returns {App.AlertConfigProperty[]}
  284. */
  285. renderAggregateConfigs: function () {
  286. var isWizard = this.get('isWizard');
  287. var alertDefinition = this.get('content');
  288. return [
  289. App.AlertConfigProperties.Description.create({
  290. value: isWizard ? '' : alertDefinition.get('description')
  291. }),
  292. App.AlertConfigProperties.Thresholds.OkThreshold.create({
  293. label: 'Thresholds',
  294. showInputForValue: false,
  295. text: isWizard ? '' : this.getThresholdsProperty('ok', 'text'),
  296. value: isWizard ? '' : this.getThresholdsProperty('ok', 'value')
  297. }),
  298. App.AlertConfigProperties.Thresholds.WarningThreshold.create({
  299. text: isWizard ? '' : this.getThresholdsProperty('warning', 'text'),
  300. value: isWizard ? '' : this.getThresholdsProperty('warning', 'value'),
  301. valueMetric: '%'
  302. }),
  303. App.AlertConfigProperties.Thresholds.CriticalThreshold.create({
  304. text: isWizard ? '' : this.getThresholdsProperty('critical', 'text'),
  305. value: isWizard ? '' : this.getThresholdsProperty('critical', 'value'),
  306. valueMetric: '%'
  307. })
  308. ];
  309. },
  310. /**
  311. * Render common list of configs used in almost all alert types in wizard
  312. * @returns {App.AlertConfigProperty[]}
  313. */
  314. renderCommonWizardConfigs: function () {
  315. return [
  316. App.AlertConfigProperties.AlertName.create({
  317. value: ''
  318. }),
  319. App.AlertConfigProperties.ServiceAlertType.create({
  320. value: true
  321. }),
  322. App.AlertConfigProperties.Service.create({
  323. options: this.get('allServices'),
  324. value: this.get('allServices')[0],
  325. isShifted: true
  326. }),
  327. App.AlertConfigProperties.Component.create({
  328. options: this.get('allComponents'),
  329. value: 'No component',
  330. isShifted: true
  331. }),
  332. App.AlertConfigProperties.Scope.create({
  333. options: this.get('allScopes'),
  334. isShifted: true
  335. }),
  336. App.AlertConfigProperties.HostAlertType.create({
  337. value: false
  338. })
  339. ];
  340. },
  341. /**
  342. * Edit configs button handler
  343. * @method editConfigs
  344. */
  345. editConfigs: function () {
  346. this.get('configs').forEach(function (property) {
  347. property.set('previousValue', property.get('value'));
  348. property.set('previousText', property.get('text'));
  349. });
  350. this.get('configs').setEach('isDisabled', false);
  351. this.set('canEdit', true);
  352. },
  353. /**
  354. * Cancel edit configs button handler
  355. * @method cancelEditConfigs
  356. */
  357. cancelEditConfigs: function () {
  358. this.get('configs').forEach(function (property) {
  359. property.set('value', property.get('previousValue'));
  360. property.set('text', property.get('previousText'));
  361. });
  362. this.get('configs').setEach('isDisabled', true);
  363. this.set('canEdit', false);
  364. },
  365. /**
  366. * Save edit configs button handler
  367. * @method saveConfigs
  368. * @return {$.ajax}
  369. */
  370. saveConfigs: function () {
  371. this.get('configs').setEach('isDisabled', true);
  372. this.set('canEdit', false);
  373. return App.ajax.send({
  374. name: 'alerts.update_alert_definition',
  375. sender: this,
  376. data: {
  377. id: this.get('content.id'),
  378. data: this.getPropertiesToUpdate(true)
  379. },
  380. success: 'saveConfigsSuccessCallback'
  381. });
  382. },
  383. /**
  384. * Success-callback for saveConfigs-request
  385. * @method saveConfigsSuccessCallback
  386. */
  387. saveConfigsSuccessCallback: function () {
  388. App.router.get('updateController').updateAlertDefinitions(Em.K);
  389. },
  390. /**
  391. * Create object with new values to put it on server
  392. * @param {boolean} onlyChanged
  393. * @method getPropertiesToUpdate
  394. * @returns {Object}
  395. */
  396. getPropertiesToUpdate: function (onlyChanged) {
  397. var propertiesToUpdate = {};
  398. var configs = onlyChanged ? this.get('configs').filterProperty('wasChanged') : this.get('configs');
  399. configs.forEach(function (property) {
  400. var apiProperties = property.get('apiProperty');
  401. var apiFormattedValues = property.get('apiFormattedValue');
  402. if (!Em.isArray(property.get('apiProperty'))) {
  403. apiProperties = [property.get('apiProperty')];
  404. apiFormattedValues = [property.get('apiFormattedValue')];
  405. }
  406. apiProperties.forEach(function (apiProperty, i) {
  407. if (apiProperty.contains('source.')) {
  408. if (!propertiesToUpdate['AlertDefinition/source']) {
  409. if (this.get('content.rawSourceData')) {
  410. propertiesToUpdate['AlertDefinition/source'] = this.get('content.rawSourceData');
  411. }
  412. }
  413. if (this.get('content.rawSourceData')) {
  414. // use rawSourceData to populate propertiesToUpdate
  415. var sourcePath = propertiesToUpdate['AlertDefinition/source'];
  416. apiProperty.replace('source.', '').split('.').forEach(function (path, index, array) {
  417. // check if it is last path
  418. if (array.length - index === 1) {
  419. sourcePath[path] = apiFormattedValues[i];
  420. } else {
  421. sourcePath = sourcePath[path];
  422. }
  423. });
  424. }
  425. else {
  426. if (!propertiesToUpdate['AlertDefinition/source']) {
  427. propertiesToUpdate['AlertDefinition/source'] = {};
  428. }
  429. Ember.setFullPath(propertiesToUpdate['AlertDefinition/source'], apiProperty.replace('source.', ''), apiFormattedValues[i]);
  430. }
  431. }
  432. else {
  433. if (apiProperty) {
  434. propertiesToUpdate['AlertDefinition/' + apiProperty] = apiFormattedValues[i];
  435. }
  436. }
  437. }, this);
  438. }, this);
  439. return propertiesToUpdate;
  440. },
  441. /**
  442. * Return array of all config values
  443. * used to save configs to local db in wizard
  444. * @method getConfigsValues
  445. * @returns {Array}
  446. */
  447. getConfigsValues: function () {
  448. return this.get('configs').map(function (property) {
  449. return {
  450. name: property.get('name'),
  451. value: property.get('value')
  452. }
  453. });
  454. },
  455. /**
  456. * Define whether critical threshold >= critical threshold
  457. * @type {Boolean}
  458. */
  459. hasThresholdsError: function () {
  460. var smallValue = Em.get(this.get('configs').findProperty('name', 'warning_threshold'), 'value');
  461. var smallValid = Em.get(this.get('configs').findProperty('name', 'warning_threshold'), 'isValid');
  462. var largeValue = Em.get(this.get('configs').findProperty('name', 'critical_threshold'), 'value');
  463. var largeValid = Em.get(this.get('configs').findProperty('name', 'critical_threshold'), 'isValid');
  464. return smallValid && largeValid ? !(smallValue <= largeValue) : false;
  465. }.property('configs.@each.value'),
  466. /**
  467. * Define whether all configs are valid
  468. * @type {Boolean}
  469. */
  470. hasErrors: function () {
  471. return this.get('configs').someProperty('isValid', false) || this.get('hasThresholdsError');
  472. }.property('configs.@each.isValid', 'hasThresholdsError')
  473. });