summary.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  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.AlertItemView = Em.View.extend({
  19. tagName:"li",
  20. templateName: require('templates/main/service/info/summary_alert'),
  21. classNameBindings: ["status"],
  22. status: function () {
  23. return "status-" + this.get("content.status");
  24. }.property('content'),
  25. didInsertElement: function () {
  26. // Tooltips for alerts need to be enabled.
  27. $("div[rel=tooltip]").tooltip();
  28. $(".tooltip").remove();
  29. }
  30. })
  31. App.MainServiceInfoSummaryView = Em.View.extend({
  32. templateName: require('templates/main/service/info/summary'),
  33. attributes:null,
  34. serviceStatus:{
  35. hdfs:false,
  36. yarn:false,
  37. mapreduce:false,
  38. mapreduce2:false,
  39. hbase:false,
  40. zookeeper:false,
  41. oozie:false,
  42. hive:false,
  43. ganglia:false,
  44. nagios:false,
  45. hue: false,
  46. flume: false
  47. },
  48. sumMasterComponentView : Em.View.extend({
  49. templateName: require('templates/main/service/info/summary/master_components'),
  50. mastersComp : function(){
  51. return this.get('parentView.service.hostComponents').filterProperty('isMaster', true);
  52. }.property("service")
  53. }),
  54. noTemplateService: function () {
  55. var serviceName = this.get("service.serviceName");
  56. if(serviceName == "WEBHCAT" || serviceName == "NAGIOS"){
  57. return true;
  58. }else{
  59. return false;
  60. }
  61. }.property('controller.content'),
  62. clients: function () {
  63. var service = this.get('controller.content');
  64. if (["OOZIE", "ZOOKEEPER", "HIVE", "MAPREDUCE2"].contains(service.get("id"))) {
  65. return service.get('hostComponents').filterProperty('isClient');
  66. }
  67. return [];
  68. }.property('controller.content'),
  69. hasManyServers: function () {
  70. if (this.get('servers').length > 1) {
  71. return true;
  72. }
  73. return false;
  74. }.property('servers'),
  75. clientsHostText: function () {
  76. if(this.get("hasManyClients")){
  77. return Em.I18n.t('services.service.summary.viewHosts');
  78. }else{
  79. return Em.I18n.t('services.service.summary.viewHost');
  80. }
  81. }.property("hasManyClients"),
  82. hasManyClients: function () {
  83. if (this.get('clients').length > 1) {
  84. return true;
  85. }
  86. return false;
  87. }.property('clients'),
  88. servers: function () {
  89. var result = [];
  90. var service = this.get('controller.content');
  91. if (service.get("id") == "ZOOKEEPER" || service.get("id") == "FLUME") {
  92. var servers = service.get('hostComponents').filterProperty('isMaster');
  93. if (servers.length > 0) {
  94. result = [{
  95. 'host': servers[0].get('displayName'),
  96. 'isComma': false,
  97. 'isAnd': false
  98. }];
  99. }
  100. if (servers.length > 1) {
  101. result[0].isComma = true;
  102. result.push({
  103. 'host': servers[1].get('displayName'),
  104. 'isComma': false,
  105. 'isAnd': false
  106. });
  107. }
  108. if (servers.length > 2) {
  109. result[1].isAnd = true;
  110. result.push({
  111. 'host': Em.I18n.t('services.service.info.summary.serversHostCount').format(servers.length - 2),
  112. 'isComma': false,
  113. 'isAnd': false
  114. });
  115. }
  116. }
  117. return result;
  118. }.property('controller.content'),
  119. historyServerUI: function(){
  120. var service=this.get('controller.content');
  121. return (App.singleNodeInstall ? "http://" + App.singleNodeAlias + ":19888" : "http://" + service.get("hostComponents").findProperty('isMaster', true).get("host").get("publicHostName")+":19888");
  122. }.property('controller.content'),
  123. monitors: function () {
  124. var result = '';
  125. var service = this.get('controller.content');
  126. if (service.get("id") == "GANGLIA") {
  127. var monitors = service.get('hostComponents').filterProperty('isMaster', false);
  128. var liveMonitors = monitors.filterProperty("workStatus","STARTED").length;
  129. if (monitors.length) {
  130. result = Em.I18n.t('services.service.info.summary.hostsRunningMonitor').format(liveMonitors, monitors.length);
  131. }
  132. }
  133. return result;
  134. }.property('controller.content'),
  135. hasManyMonitors: function () {
  136. var service = this.get('controller.content');
  137. if (service.get("id") == "GANGLIA") {
  138. var monitors = service.get('hostComponents').filterProperty('isMaster', false);
  139. if (monitors.length > 1){
  140. return Em.I18n.t('services.service.summary.viewHosts');
  141. }else{
  142. return Em.I18n.t('services.service.summary.viewHost');
  143. }
  144. }
  145. return result;
  146. }.property('controller.content'),
  147. /**
  148. * Property related to GANGLIA service, is unused for other services
  149. * @return {Object}
  150. */
  151. monitorsObj: function(){
  152. var service = this.get('controller.content');
  153. if (service.get("id") == "GANGLIA") {
  154. var monitors = service.get('hostComponents').filterProperty('isMaster', false);
  155. if (monitors.length) {
  156. return monitors[0];
  157. }
  158. }
  159. return {};
  160. }.property('controller.content'),
  161. /**
  162. * Property related to ZOOKEEPER service, is unused for other services
  163. * @return {Object}
  164. */
  165. serversHost: function() {
  166. var service = this.get('controller.content');
  167. if (service.get("id") == "ZOOKEEPER" || service.get("id") == "FLUME") {
  168. var servers = service.get('hostComponents').filterProperty('isMaster');
  169. if (servers.length > 0) {
  170. return servers[0];
  171. }
  172. }
  173. return {};
  174. }.property('controller.content'),
  175. /**
  176. * Property related to OOZIE and ZOOKEEPER services, is unused for other services
  177. * HIVE is supported too
  178. * @return {Object}
  179. */
  180. clientObj: function() {
  181. var service = this.get('controller.content');
  182. if (["OOZIE", "ZOOKEEPER", "HIVE", "MAPREDUCE2"].contains(service.get("id"))) {
  183. var clients = service.get('hostComponents').filterProperty('isClient', true);
  184. if (clients.length > 0) {
  185. return clients[0];
  186. }
  187. }
  188. return {};
  189. }.property('controller.content'),
  190. data:{
  191. hive:{
  192. "database":"PostgreSQL",
  193. "databaseName":"hive",
  194. "user":"hive"
  195. }
  196. },
  197. /**
  198. * Array of the hostComponents for service
  199. */
  200. components: [],
  201. /**
  202. * Copy hostComponents from controller to view to avoid flickering Summary block while data is updating in the controller
  203. * rand - just marker in the Service model for determining that Service was updated (value changes in the service_mapper)
  204. */
  205. hostComponentsUpd: function() {
  206. var components = [];
  207. this.get('controller.content.hostComponents').forEach(function(component) {
  208. var obj = {};
  209. for(var prop in component){
  210. if( component.hasOwnProperty(prop)
  211. && prop.indexOf('__ember') < 0
  212. && prop.indexOf('_super') < 0
  213. && Ember.typeOf(component.get(prop)) !== 'function'
  214. ) {
  215. obj[prop] = component.get(prop);
  216. }
  217. }
  218. obj.displayName = component.get('displayName'); // this is computed property and wasn't copied in the top block of code
  219. // suppressing MySQL server from being displayed, because Ambari always installs MySQL server no matter what
  220. // database type is selected, and shows an incorrect link in the summary to point to the host that's hosting
  221. // the MySQL server
  222. if (component.get('componentName') !== 'MYSQL_SERVER') {
  223. components.push(obj);
  224. }
  225. });
  226. if(!this.get('isDestroyed') && !this.get('isDestroying')){
  227. this.set('components', components);
  228. }
  229. },
  230. _hostComponentsUpd: function() {
  231. Ember.run.once(this, 'hostComponentsUpd');
  232. }.observes('controller.content.rand', 'controller.content.hostComponents.@each.isMaster', 'controller.content.hostComponents.@each.host'),
  233. /**
  234. * Wrapper for displayName. used to render correct display name for mysql_server
  235. */
  236. componentNameView: Ember.View.extend({
  237. template: Ember.Handlebars.compile('{{view.displayName}}'),
  238. comp : null,
  239. displayName: function(){
  240. if(this.get('comp.componentName') == 'MYSQL_SERVER'){
  241. return this.t('services.hive.databaseComponent');
  242. }
  243. return this.get('comp.displayName');
  244. }.property('comp')
  245. }),
  246. service:function () {
  247. var svc = this.get('controller.content');
  248. var svcName = svc.get('serviceName');
  249. if (svcName) {
  250. switch (svcName.toLowerCase()) {
  251. case 'hdfs':
  252. svc = App.HDFSService.find().objectAt(0);
  253. break;
  254. case 'yarn':
  255. svc = App.YARNService.find().objectAt(0);
  256. break;
  257. case 'mapreduce':
  258. svc = App.MapReduceService.find().objectAt(0);
  259. break;
  260. case 'hbase':
  261. svc = App.HBaseService.find().objectAt(0);
  262. break;
  263. case 'flume':
  264. svc = App.FlumeService.find().objectAt(0);
  265. break;
  266. default:
  267. break;
  268. }
  269. }
  270. return svc;
  271. }.property('controller.content.serviceName').volatile(),
  272. isHide:true,
  273. moreStatsView:Em.View.extend({
  274. tagName:"a",
  275. template:Ember.Handlebars.compile('{{t services.service.summary.moreStats}}'),
  276. attributeBindings:[ 'href' ],
  277. classNames:[ 'more-stats' ],
  278. click:function (event) {
  279. this._parentView._parentView.set('isHide', false);
  280. this.remove();
  281. },
  282. href:'javascript:void(null)'
  283. }),
  284. serviceName:function () {
  285. return this.get('service.serviceName');
  286. }.property('service'),
  287. oldServiceName:'',
  288. /**
  289. * Contains graphs for this particular service
  290. */
  291. serviceMetricGraphs:function () {
  292. var svcName = this.get('service.serviceName');
  293. var graphs = [];
  294. if (svcName) {
  295. switch (svcName.toLowerCase()) {
  296. case 'hdfs':
  297. graphs = [ [App.ChartServiceMetricsHDFS_SpaceUtilization.extend(),
  298. App.ChartServiceMetricsHDFS_FileOperations.extend(),
  299. App.ChartServiceMetricsHDFS_BlockStatus.extend(),
  300. App.ChartServiceMetricsHDFS_IO.extend()],
  301. [App.ChartServiceMetricsHDFS_RPC.extend(),
  302. App.ChartServiceMetricsHDFS_GC.extend(),
  303. App.ChartServiceMetricsHDFS_JVMHeap.extend(),
  304. App.ChartServiceMetricsHDFS_JVMThreads.extend()]];
  305. break;
  306. case 'yarn':
  307. graphs = /*[[App.ChartServiceMetricsYARN_JobsStatus.extend(),
  308. App.ChartServiceMetricsYARN_TasksRunningWaiting.extend(),
  309. App.ChartServiceMetricsYARN_MapSlots.extend(),
  310. App.ChartServiceMetricsYARN_ReduceSlots.extend()]*/
  311. [[App.ChartServiceMetricsYARN_RPC.extend(),
  312. App.ChartServiceMetricsYARN_GC.extend(),
  313. App.ChartServiceMetricsYARN_JVMHeap.extend(),
  314. App.ChartServiceMetricsYARN_JVMThreads.extend()],
  315. [App.ChartServiceMetricsYARN_AllocatedMemory.extend(),
  316. App.ChartServiceMetricsYARN_AllocatedContainer.extend(),
  317. App.ChartServiceMetricsYARN_NMS.extend(),
  318. App.ChartServiceMetricsYARN_QMR.extend()]];
  319. break;
  320. case 'mapreduce':
  321. graphs = [ [App.ChartServiceMetricsMapReduce_JobsStatus.extend(),
  322. App.ChartServiceMetricsMapReduce_TasksRunningWaiting.extend(),
  323. App.ChartServiceMetricsMapReduce_MapSlots.extend(),
  324. App.ChartServiceMetricsMapReduce_ReduceSlots.extend()],
  325. [App.ChartServiceMetricsMapReduce_GC.extend(),
  326. App.ChartServiceMetricsMapReduce_RPC.extend(),
  327. App.ChartServiceMetricsMapReduce_JVMHeap.extend(),
  328. App.ChartServiceMetricsMapReduce_JVMThreads.extend()]];
  329. break;
  330. case 'hbase':
  331. graphs = [ [App.ChartServiceMetricsHBASE_ClusterRequests.extend(),
  332. App.ChartServiceMetricsHBASE_RegionServerReadWriteRequests.extend(),
  333. App.ChartServiceMetricsHBASE_RegionServerRegions.extend(),
  334. App.ChartServiceMetricsHBASE_RegionServerQueueSize.extend()],
  335. [App.ChartServiceMetricsHBASE_HlogSplitTime.extend(),
  336. App.ChartServiceMetricsHBASE_HlogSplitSize.extend()]];
  337. break;
  338. case 'flume':
  339. graphs = [[App.ChartServiceMetricsFlume_ChannelFillPercent.extend(),
  340. App.ChartServiceMetricsFlume_ChannelSize.extend(),
  341. App.ChartServiceMetricsFlume_SourceAcceptedCount.extend(),
  342. App.ChartServiceMetricsFlume_SinkDrainSuccessCount.extend()],
  343. [App.ChartServiceMetricsFlume_SinkConnectionFailedCount.extend(),
  344. //App.ChartServiceMetricsFlume_GarbageCollection.extend(),
  345. //App.ChartServiceMetricsFlume_JVMHeapUsed.extend(),
  346. //App.ChartServiceMetricsFlume_JVMThreadsRunnable.extend(),
  347. App.ChartServiceMetricsFlume_CPUUser.extend()]];
  348. break;
  349. default:
  350. break;
  351. }
  352. }
  353. return graphs;
  354. }.property(''),
  355. loadServiceSummary:function (serviceName) {
  356. var serviceName = this.get('serviceName');
  357. if (!serviceName) {
  358. return;
  359. }
  360. if (this.get('oldServiceName')) {
  361. // do not delete it!
  362. return;
  363. }
  364. var summaryView = this;
  365. var serviceStatus = summaryView.get('serviceStatus');
  366. $.each(serviceStatus, function (key, value) {
  367. if (key.toUpperCase() == serviceName) {
  368. summaryView.set('serviceStatus.' + key, true);
  369. } else {
  370. summaryView.set('serviceStatus.' + key, false);
  371. }
  372. });
  373. console.log('load ', serviceName, ' info');
  374. this.set('oldServiceName', serviceName);
  375. serviceName = serviceName.toLowerCase();
  376. }.observes('serviceName'),
  377. gangliaUrl:function () {
  378. var gangliaUrl = App.router.get('clusterController.gangliaUrl');
  379. var svcName = this.get('service.serviceName');
  380. if (svcName) {
  381. switch (svcName.toLowerCase()) {
  382. case 'hdfs':
  383. gangliaUrl += "/?r=hour&cs=&ce=&m=&s=by+name&c=HDPNameNode&tab=m&vn=";
  384. break;
  385. case 'mapreduce':
  386. gangliaUrl += "/?r=hour&cs=&ce=&m=&s=by+name&c=HDPJobTracker&tab=m&vn=";
  387. break;
  388. case 'hbase':
  389. gangliaUrl += "?r=hour&cs=&ce=&m=&s=by+name&c=HDPHBaseMaster&tab=m&vn=";
  390. break;
  391. default:
  392. break;
  393. }
  394. }
  395. return gangliaUrl;
  396. }.property('App.router.clusterController.gangliaUrl', 'service.serviceName'),
  397. didInsertElement:function () {
  398. // We have to make the height of the Alerts section
  399. // match the height of the Summary section.
  400. var summaryTable = document.getElementById('summary-info');
  401. var alertsList = document.getElementById('summary-alerts-list');
  402. if (summaryTable && alertsList) {
  403. var rows = $(summaryTable).find('tr');
  404. if (rows != null && rows.length > 0) {
  405. var minimumHeightSum = 20;
  406. var minimumHeightAlert = 50;
  407. var calculatedHeight = summaryTable.clientHeight;
  408. if (calculatedHeight < minimumHeightAlert) {
  409. $(alertsList).attr('style', "height:" + minimumHeightAlert + "px;");
  410. $(summaryTable).attr('style', "height:" + minimumHeightSum + "px;");
  411. } else {
  412. $(alertsList).attr('style', "height:" + calculatedHeight + "px;");
  413. }
  414. } else if (alertsList.clientHeight > 0) {
  415. $(summaryTable).append('<tr><td></td></tr>');
  416. $(summaryTable).attr('style', "height:" + alertsList.clientHeight + "px;");
  417. }
  418. }
  419. },
  420. clientHosts:App.Host.find(),
  421. clientHostsLength:function () {
  422. var text = this.t('services.service.summary.clientCount');
  423. var self = this;
  424. return text.format(self.get('clientHosts.length'));
  425. }.property('clientHosts'),
  426. clientComponents:function () {
  427. return App.HostComponent.find().filterProperty('isClient', true);
  428. }.property(),
  429. clientComponentsString:function () {
  430. var components = this.get('clientComponents');
  431. var names = [];
  432. components.forEach(function (component) {
  433. if (names.indexOf(component.get('displayName')) == -1) {
  434. names.push(component.get('displayName'));
  435. }
  436. });
  437. return names.length ? names.join(', ') : false;
  438. }.property('clientComponents')
  439. });