summary.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with this
  4. * work for additional information regarding copyright ownership. The ASF
  5. * licenses this file to you under the Apache License, Version 2.0 (the
  6. * "License"); you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  13. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  14. * License for the specific language governing permissions and limitations under
  15. * the License.
  16. */
  17. var App = require('app');
  18. App.MainServiceInfoSummaryController = Em.Controller.extend({
  19. name: 'mainServiceInfoSummaryController',
  20. selectedFlumeAgent: null,
  21. /**
  22. * Indicates whether Ranger plugins status update polling is active
  23. * @type {boolean}
  24. */
  25. isRangerUpdateWorking: false,
  26. /**
  27. * Indicates whether array with initial Ranger plugins data is set
  28. * @type {boolean}
  29. */
  30. isRangerPluginsArraySet: false,
  31. /**
  32. * Indicates whether previous AJAX request for Ranger plugins config properties has failed
  33. * @type {boolean}
  34. */
  35. isPreviousRangerConfigsCallFailed: false,
  36. /**
  37. * UI section name
  38. */
  39. sectionName: function() {
  40. return this.get('content.serviceName') + "_SUMMARY";
  41. }.property('content.serviceName'),
  42. /**
  43. * Ranger plugins data
  44. * @type {array}
  45. */
  46. rangerPlugins: [
  47. {
  48. serviceName: 'HDFS',
  49. type: 'ranger-hdfs-plugin-properties',
  50. propertyName: 'ranger-hdfs-plugin-enabled'
  51. },
  52. {
  53. serviceName: 'HIVE',
  54. type: 'ranger-hive-plugin-properties',
  55. propertyName: 'ranger-hive-plugin-enabled'
  56. },
  57. {
  58. serviceName: 'HBASE',
  59. type: 'ranger-hbase-plugin-properties',
  60. propertyName: 'ranger-hbase-plugin-enabled'
  61. },
  62. {
  63. serviceName: 'KNOX',
  64. type: 'ranger-knox-plugin-properties',
  65. propertyName: 'ranger-knox-plugin-enabled'
  66. },
  67. {
  68. serviceName: 'STORM',
  69. type: 'ranger-storm-plugin-properties',
  70. propertyName: 'ranger-storm-plugin-enabled'
  71. }
  72. ],
  73. /**
  74. * Set initial Ranger plugins data
  75. * @method setRangerPlugins
  76. */
  77. setRangerPlugins: function () {
  78. if (App.get('router.clusterController.isLoaded') && !this.get('isRangerPluginsArraySet')) {
  79. this.setProperties({
  80. rangerPlugins: this.get('rangerPlugins').map(function (item) {
  81. var stackService = App.StackService.find().findProperty('serviceName', item.serviceName);
  82. var displayName = (stackService) ? stackService.get('displayName') : item.serviceName;
  83. return $.extend(item, {
  84. pluginTitle: Em.I18n.t('services.service.summary.ranger.plugin.title').format(displayName),
  85. isDisplayed: App.Service.find().someProperty('serviceName', item.serviceName),
  86. status: Em.I18n.t('services.service.summary.ranger.plugin.loadingStatus')
  87. });
  88. }),
  89. isRangerPluginsArraySet: true
  90. });
  91. }
  92. }.observes('App.router.clusterController.isLoaded'),
  93. /**
  94. * Get latest config tags
  95. * @method updateRangerPluginsStatus
  96. * @param callback
  97. */
  98. updateRangerPluginsStatus: function (callback) {
  99. App.ajax.send({
  100. name: 'config.tags',
  101. sender: this,
  102. success: 'getRangerPluginsStatus',
  103. callback: callback
  104. });
  105. },
  106. /**
  107. * Get latest Ranger plugins config properties
  108. * @method getRangerPluginsStatus
  109. * @param data
  110. */
  111. getRangerPluginsStatus: function (data) {
  112. var urlParams = [];
  113. this.get('rangerPlugins').forEach(function (item) {
  114. if (App.Service.find().someProperty('serviceName', item.serviceName)) {
  115. var currentTag = data.Clusters.desired_configs[item.type].tag;
  116. var isTagChanged = item.tag != currentTag;
  117. Em.set(item, 'isDisplayed', true);
  118. //Request for properties should be sent either if configs have changed or if previous Ranger plugins config properties has failed
  119. if (isTagChanged || this.get('isPreviousRangerConfigsCallFailed')) {
  120. Em.set(item, 'tag', currentTag);
  121. urlParams.push('(type=' + item.type + '&tag=' + currentTag + ')');
  122. }
  123. } else {
  124. Em.set(item, 'isDisplayed', false);
  125. }
  126. }, this);
  127. if (urlParams.length) {
  128. App.ajax.send({
  129. name: 'reassign.load_configs',
  130. sender: this,
  131. data: {
  132. urlParams: urlParams.join('|')
  133. },
  134. success: 'getRangerPluginsStatusSuccess',
  135. error: 'getRangerPluginsStatusError'
  136. });
  137. }
  138. },
  139. /**
  140. * Set Ranger plugins statuses
  141. * @method getRangerPluginsStatusSuccess
  142. * @param data
  143. */
  144. getRangerPluginsStatusSuccess: function (data) {
  145. this.set('isPreviousRangerConfigsCallFailed', false);
  146. data.items.forEach(function (item) {
  147. var serviceName = this.get('rangerPlugins').findProperty('type', item.type).serviceName;
  148. var propertyName = this.get('rangerPlugins').findProperty('type', item.type).propertyName;
  149. var statusMap = {
  150. Yes: 'alerts.table.state.enabled',
  151. No: 'alerts.table.state.disabled'
  152. };
  153. var statusString = statusMap[item.properties[propertyName]] || 'common.unknown';
  154. Em.set(this.get('rangerPlugins').findProperty('serviceName', serviceName), 'status', Em.I18n.t(statusString));
  155. }, this);
  156. },
  157. /**
  158. * Method executed if Ranger plugins config properties request has failed
  159. * @method getRangerPluginsStatusError
  160. */
  161. getRangerPluginsStatusError: function () {
  162. this.set('isPreviousRangerConfigsCallFailed', true);
  163. },
  164. /**
  165. * Send start command for selected Flume Agent
  166. * @method startFlumeAgent
  167. */
  168. startFlumeAgent: function () {
  169. var selectedFlumeAgent = arguments[0].context;
  170. if (selectedFlumeAgent && selectedFlumeAgent.get('status') === 'NOT_RUNNING') {
  171. var self = this;
  172. App.showConfirmationPopup(function () {
  173. var state = 'STARTED';
  174. var context = Em.I18n.t('services.service.summary.flume.start.context').format(selectedFlumeAgent.get('name'));
  175. self.sendFlumeAgentCommandToServer(state, context, selectedFlumeAgent);
  176. });
  177. }
  178. },
  179. /**
  180. * Send stop command for selected Flume Agent
  181. * @method stopFlumeAgent
  182. */
  183. stopFlumeAgent: function () {
  184. var selectedFlumeAgent = arguments[0].context;
  185. if (selectedFlumeAgent && selectedFlumeAgent.get('status') === 'RUNNING') {
  186. var self = this;
  187. App.showConfirmationPopup(function () {
  188. var state = 'INSTALLED';
  189. var context = Em.I18n.t('services.service.summary.flume.stop.context').format(selectedFlumeAgent.get('name'));
  190. self.sendFlumeAgentCommandToServer(state, context, selectedFlumeAgent);
  191. });
  192. }
  193. },
  194. /**
  195. * Send command for Flume Agent to server
  196. * @param {string} state
  197. * @param {string} context
  198. * @param {Object} agent
  199. * @method sendFlumeAgentCommandToServer
  200. */
  201. sendFlumeAgentCommandToServer: function (state, context, agent) {
  202. App.ajax.send({
  203. name: 'service.flume.agent.command',
  204. sender: this,
  205. data: {
  206. state: state,
  207. context: context,
  208. agentName: agent.get('name'),
  209. host: agent.get('hostName')
  210. },
  211. success: 'commandSuccessCallback'
  212. });
  213. },
  214. /**
  215. * Callback, that shows Background operations popup if request was successful
  216. */
  217. commandSuccessCallback: function () {
  218. console.log('Send request for refresh configs successfully');
  219. // load data (if we need to show this background operations popup) from persist
  220. App.router.get('applicationController').dataLoading().done(function (showPopup) {
  221. if (showPopup) {
  222. App.router.get('backgroundOperationsController').showPopup();
  223. }
  224. });
  225. },
  226. gotoConfigs: function () {
  227. App.router.get('mainServiceItemController').set('routeToConfigs', true);
  228. App.router.transitionTo('main.services.service.configs', this.get('content'));
  229. App.router.get('mainServiceItemController').set('routeToConfigs', false);
  230. },
  231. showServiceAlertsPopup: function (event) {
  232. var service = event.context;
  233. return App.ModalPopup.show({
  234. header: Em.I18n.t('services.service.summary.alerts.popup.header').format(service.get('displayName')),
  235. autoHeight: false,
  236. bodyClass: Em.View.extend({
  237. templateName: require('templates/main/service/info/service_alert_popup'),
  238. classNames: ['service-alerts'],
  239. controllerBinding: 'App.router.mainAlertDefinitionsController',
  240. didInsertElement: function () {
  241. Em.run.next(this, function () {
  242. App.tooltip($(".timeago"));
  243. });
  244. },
  245. alerts: function () {
  246. var serviceDefinitions = this.get('controller.content').filterProperty('service', service);
  247. // definitions should be sorted in order: critical, warning, ok, unknown, other
  248. var criticalDefinitions = [], warningDefinitions = [], okDefinitions = [], unknownDefinitions = [];
  249. serviceDefinitions.forEach(function (definition) {
  250. if (definition.get('isCritical')) {
  251. criticalDefinitions.push(definition);
  252. serviceDefinitions = serviceDefinitions.without(definition);
  253. } else if (definition.get('isWarning')) {
  254. warningDefinitions.push(definition);
  255. serviceDefinitions = serviceDefinitions.without(definition);
  256. } else if (definition.get('isOK')) {
  257. okDefinitions.push(definition);
  258. serviceDefinitions = serviceDefinitions.without(definition);
  259. } else if (definition.get('isUnknown')) {
  260. unknownDefinitions.push(definition);
  261. serviceDefinitions = serviceDefinitions.without(definition);
  262. }
  263. });
  264. serviceDefinitions = criticalDefinitions.concat(warningDefinitions, okDefinitions, unknownDefinitions, serviceDefinitions);
  265. return serviceDefinitions;
  266. }.property('controller.content'),
  267. gotoAlertDetails: function (event) {
  268. if (event && event.context) {
  269. this.get('parentView').hide();
  270. App.router.transitionTo('main.alerts.alertDetails', event.context);
  271. }
  272. },
  273. closePopup: function () {
  274. this.get('parentView').hide();
  275. }
  276. }),
  277. isHideBodyScroll: false,
  278. primary: Em.I18n.t('common.close'),
  279. secondary: null
  280. });
  281. },
  282. /**
  283. * @type {boolean}
  284. */
  285. isWidgetsLoaded: false,
  286. /**
  287. * @type {boolean}
  288. */
  289. isWidgetLayoutsLoaded: false,
  290. /**
  291. * @type {Em.A}
  292. */
  293. widgets: function() {
  294. return App.Widget.find().filterProperty('sectionName', this.get('content.serviceName') + '_SUMMARY');
  295. }.property('isWidgetsLoaded'),
  296. /**
  297. * @type {Em.A}
  298. */
  299. widgetLayouts: function() {
  300. return App.WidgetLayout.find().filterProperty('serviceName', this.get('content.serviceName'));
  301. }.property('isWidgetLayoutsLoaded'),
  302. /**
  303. * load widget layouts across all users in CLUSTER scope
  304. * @returns {$.ajax}
  305. */
  306. loadWidgetLayouts: function() {
  307. this.set('isWidgetLayoutsLoaded', false);
  308. return App.ajax.send({
  309. name: 'widgets.layouts.get',
  310. sender: this,
  311. data: {
  312. sectionName: this.get('sectionName')
  313. },
  314. success: 'loadWidgetLayoutsSuccessCallback'
  315. });
  316. },
  317. loadWidgetLayoutsSuccessCallback: function(data) {
  318. App.widgetLayoutMapper.map(data);
  319. this.set('isWidgetLayoutsLoaded', true);
  320. },
  321. /**
  322. * load widgets defined by user
  323. * @returns {$.ajax}
  324. */
  325. loadWidgets: function () {
  326. this.set('isWidgetsLoaded', false);
  327. return App.ajax.send({
  328. name: 'widgets.layout.userDefined.get',
  329. sender: this,
  330. data: {
  331. loginName: App.router.get('loginName'),
  332. sectionName: this.get('sectionName')
  333. },
  334. success: 'loadWidgetsSuccessCallback'
  335. });
  336. },
  337. /**
  338. * success callback of <code>loadWidgets()</code>
  339. * @param {object|null} data
  340. */
  341. loadWidgetsSuccessCallback: function (data) {
  342. if (data.items[0]) {
  343. App.widgetMapper.map(data.items[0], this.get('content.serviceName'));
  344. this.set('isWidgetsLoaded', true);
  345. } else {
  346. this.loadStackWidgetsLayout();
  347. }
  348. },
  349. /**
  350. * load widgets defined by stack
  351. * @returns {$.ajax}
  352. */
  353. loadStackWidgetsLayout: function () {
  354. return App.ajax.send({
  355. name: 'widgets.layout.stackDefined.get',
  356. sender: this,
  357. data: {
  358. stackVersionURL: App.get('stackVersionURL'),
  359. serviceName: this.get('content.serviceName')
  360. },
  361. success: 'loadStackWidgetsLayoutSuccessCallback'
  362. });
  363. },
  364. /**
  365. * success callback of <code>loadStackWidgetsLayout()</code>
  366. * @param {object|null} data
  367. */
  368. loadStackWidgetsLayoutSuccessCallback: function (data) {
  369. App.widgetMapper.map(data.artifact_data.layouts.findProperty('section_name', this.get('sectionName')), this.get('content.serviceName'));
  370. this.set('isWidgetsLoaded', true);
  371. },
  372. /**
  373. * add widgets
  374. */
  375. addWidgets: function (event) {
  376. var widgets = event.context.filterProperty('selected');
  377. },
  378. /**
  379. * delete widgets
  380. */
  381. deleteWidgets: function (event) {
  382. var widgets = event.context.filterProperty('selected');
  383. },
  384. /**
  385. * save layout
  386. */
  387. saveLayout: function () {
  388. },
  389. /**
  390. * create widget
  391. */
  392. createWidget: function () {
  393. App.router.send('addServiceWidget', this.get('content'));
  394. }
  395. });