summary.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  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. App.MainHostSummaryView = Em.View.extend({
  20. templateName: require('templates/main/host/summary'),
  21. content: function () {
  22. return App.router.get('mainHostDetailsController.content');
  23. }.property('App.router.mainHostDetailsController.content'),
  24. showGangliaCharts: function () {
  25. var name = this.get('content.hostName');
  26. var gangliaMobileUrl = App.router.get('clusterController.gangliaUrl') + "/mobile_helper.php?show_host_metrics=1&h=" + name + "&c=HDPNameNode&r=hour&cs=&ce=";
  27. window.open(gangliaMobileUrl);
  28. },
  29. /**
  30. * @type: [{String}]
  31. */
  32. decommissionDataNodeHostNames: null,
  33. loadDecommissionNodesList: function () {
  34. var self = this;
  35. var clusterName = App.router.get('clusterController.clusterName');
  36. var persistUrl = App.apiPrefix + '/persist';
  37. var clusterUrl = App.apiPrefix + '/clusters/' + clusterName;
  38. var getConfigAjax = {
  39. type: 'GET',
  40. url: persistUrl,
  41. dataType: 'json',
  42. timeout: App.timeout,
  43. success: function (data) {
  44. if (data && data.decommissionDataNodesTag) {
  45. // We know the tag which contains the decommisioned nodes.
  46. var configsUrl = clusterUrl + '/configurations?type=hdfs-exclude-file&tag=' + data.decommissionDataNodesTag;
  47. var decomNodesAjax = {
  48. type: 'GET',
  49. url: configsUrl,
  50. dataType: 'json',
  51. timeout: App.timeout,
  52. success: function (data) {
  53. if (data && data.items) {
  54. var csv = data.items[0].properties.datanodes;
  55. self.set('decommissionDataNodeHostNames', csv.split(','));
  56. }
  57. },
  58. error: function (xhr, textStatus, errorThrown) {
  59. console.log(textStatus);
  60. console.log(errorThrown);
  61. }
  62. };
  63. jQuery.ajax(decomNodesAjax);
  64. }
  65. },
  66. error: function (xhr, textStatus, errorThrown) {
  67. // No tag pointer in persist. Rely on service's decomNodes.
  68. var hdfsSvcs = App.HDFSService.find();
  69. if (hdfsSvcs && hdfsSvcs.get('length') > 0) {
  70. var hdfsSvc = hdfsSvcs.objectAt(0);
  71. if (hdfsSvc) {
  72. var hostNames = [];
  73. var decomNodes = hdfsSvc.get('decommissionDataNodes');
  74. decomNodes.forEach(function (decomNode) {
  75. hostNames.push(decomNode.get('hostName'));
  76. });
  77. self.set('decommissionDataNodeHostNames', hostNames);
  78. }
  79. }
  80. }
  81. }
  82. jQuery.ajax(getConfigAjax);
  83. },
  84. didInsertElement: function () {
  85. this.loadDecommissionNodesList();
  86. },
  87. sortedComponents: function() {
  88. var slaveComponents = [];
  89. var masterComponents = [];
  90. this.get('content.hostComponents').forEach(function(component){
  91. if(component.get('workStatus') != 'INSTALLING'){
  92. if(component.get('isMaster')){
  93. masterComponents.push(component);
  94. } else if(component.get('isSlave')) {
  95. slaveComponents.push(component);
  96. }
  97. }
  98. }, this);
  99. return masterComponents.concat(slaveComponents);
  100. }.property('content', 'content.hostComponents.length'),
  101. clients: function(){
  102. var clients = [];
  103. this.get('content.hostComponents').forEach(function(component){
  104. if(!component.get('componentName')){
  105. //temporary fix because of different data in hostComponents and serviceComponents
  106. return;
  107. }
  108. if (!component.get('isSlave') && !component.get('isMaster')) {
  109. if (clients.length) {
  110. clients[clients.length-1].set('isLast', false);
  111. }
  112. component.set('isLast', true);
  113. clients.push(component);
  114. }
  115. }, this);
  116. return clients;
  117. }.property('content'),
  118. addableComponentObject: Em.Object.extend({
  119. componentName: '',
  120. displayName: function(){
  121. return App.format.role(this.get('componentName'));
  122. }.property('componentName')
  123. }),
  124. isAddComponent: function(){
  125. return this.get('content.healthClass') !== 'health-status-DEAD-YELLOW';
  126. }.property('content.healthClass'),
  127. addableComponents:function(){
  128. var components = [];
  129. var services = App.Service.find();
  130. var dataNodeExists = false;
  131. var taskTrackerExists = false;
  132. var regionServerExists = false;
  133. this.get('content.hostComponents').forEach(function(component) {
  134. switch (component.get('componentName')) {
  135. case 'DATANODE':
  136. dataNodeExists = true;
  137. break;
  138. case 'TASKTRACKER':
  139. taskTrackerExists = true;
  140. break;
  141. case 'HBASE_REGIONSERVER':
  142. regionServerExists = true;
  143. break;
  144. }
  145. }, this);
  146. if (!dataNodeExists) {
  147. components.pushObject(this.addableComponentObject.create({ 'componentName': 'DATANODE' }));
  148. }
  149. if (!taskTrackerExists && services.findProperty('serviceName', 'MAPREDUCE')) {
  150. components.pushObject(this.addableComponentObject.create({ 'componentName': 'TASKTRACKER' }));
  151. }
  152. if (!regionServerExists && services.findProperty('serviceName', 'HBASE')) {
  153. components.pushObject(this.addableComponentObject.create({ 'componentName': 'HBASE_REGIONSERVER' }));
  154. }
  155. return components;
  156. }.property('content', 'content.hostComponents.length'),
  157. ComponentView: Em.View.extend({
  158. content: null,
  159. didInsertElement: function () {
  160. if (this.get('isInProgress')) {
  161. this.doBlinking();
  162. }
  163. },
  164. hostComponent: function(){
  165. var hostComponent = null;
  166. var serviceComponent = this.get('content');
  167. var host = App.router.get('mainHostDetailsController.content');
  168. if(host){
  169. var hostComponent = host.get('hostComponents').findProperty('componentName', serviceComponent.get('componentName'));
  170. }
  171. return hostComponent;
  172. }.property('content', 'App.router.mainHostDetailsController.content'),
  173. workStatus: function(){
  174. var workStatus = this.get('content.workStatus');
  175. var hostComponent = this.get('hostComponent');
  176. if(hostComponent){
  177. workStatus = hostComponent.get('workStatus');
  178. }
  179. return workStatus;
  180. }.property('content.workStatus','hostComponent.workStatus'),
  181. statusClass: function(){
  182. var statusClass = null;
  183. if(this.get('isDataNode')){
  184. if(this.get('isDataNodeRecommissionAvailable') && this.get('isStart')){
  185. // Orange is shown only when service is started/starting and it is decommissioned.
  186. return 'health-status-DEAD-ORANGE';
  187. }
  188. }
  189. if(this.get('workStatus') === App.HostComponentStatus.install_failed){
  190. return 'icon-remove';
  191. }
  192. return 'health-status-' + App.HostComponentStatus.getKeyName(this.get('workStatus'));
  193. }.property('workStatus', 'isDataNodeRecommissionAvailable'),
  194. /**
  195. * For Upgrade failed state
  196. */
  197. isUpgradeFailed:function(){
  198. return App.HostComponentStatus.getKeyName(this.get('workStatus')) === "upgrade_failed";
  199. }.property("workStatus"),
  200. /**
  201. * For Install failed state
  202. */
  203. isInstallFailed:function(){
  204. return App.HostComponentStatus.getKeyName(this.get('workStatus')) === "install_failed";
  205. }.property("workStatus"),
  206. /**
  207. * Disable element while component is starting/stopping
  208. */
  209. disabledClass:function(){
  210. var workStatus = this.get('workStatus');
  211. if([App.HostComponentStatus.starting, App.HostComponentStatus.stopping, App.HostComponentStatus.unknown].contains(workStatus) ){
  212. return 'disabled';
  213. } else {
  214. return '';
  215. }
  216. }.property('workStatus'),
  217. /**
  218. * Do blinking for 1 minute
  219. */
  220. doBlinking : function(){
  221. var workStatus = this.get('workStatus');
  222. var self = this;
  223. var pulsate = [ App.HostComponentStatus.starting, App.HostComponentStatus.stopping ].contains(workStatus);
  224. if (!pulsate && this.get('isDataNode')) {
  225. var dataNodeComponent = this.get('content');
  226. if (dataNodeComponent)
  227. pulsate = dataNodeComponent.get('isDecommissioning');
  228. }
  229. if (pulsate) {
  230. this.$('.components-health').effect("pulsate", null, 1000, function () {
  231. self.doBlinking();
  232. });
  233. }
  234. },
  235. /**
  236. * Start blinking when host component is starting/stopping
  237. */
  238. startBlinking:function(){
  239. this.$('.components-health').stop(true, true);
  240. this.$('.components-health').css({opacity: 1.0});
  241. this.doBlinking();
  242. }.observes('workStatus'),
  243. isStart : function() {
  244. return (this.get('workStatus') === App.HostComponentStatus.started || this.get('workStatus') === App.HostComponentStatus.starting);
  245. }.property('workStatus'),
  246. isInProgress : function() {
  247. return (this.get('workStatus') === App.HostComponentStatus.stopping || this.get('workStatus') === App.HostComponentStatus.starting);
  248. }.property('workStatus'),
  249. /**
  250. * Shows whether we need to show Decommision/Recomission buttons
  251. */
  252. isDataNode: function() {
  253. return this.get('content.componentName') === 'DATANODE';
  254. }.property('content'),
  255. /**
  256. * Set in template via binding from parent view
  257. */
  258. decommissionDataNodeHostNames: null,
  259. /**
  260. * Decommission is available whenever the service is started.
  261. */
  262. isDataNodeDecommissionAvailable: function () {
  263. return this.get('isStart') && !this.get('isDataNodeRecommissionAvailable');
  264. }.property('isStart', 'isDataNodeRecommissionAvailable'),
  265. /**
  266. * Recommission is available only when this hostname shows up in the
  267. * 'decommissionDataNodeHostNames'
  268. */
  269. isDataNodeRecommissionAvailable: function () {
  270. var decommissionHostNames = this.get('decommissionDataNodeHostNames');
  271. var hostName = App.router.get('mainHostDetailsController.content.hostName');
  272. return decommissionHostNames!=null && decommissionHostNames.contains(hostName);
  273. }.property('App.router.mainHostDetailsController.content', 'decommissionDataNodeHostNames')
  274. }),
  275. timeSinceHeartBeat: function () {
  276. var d = this.get('content.lastHeartBeatTime');
  277. if (d) {
  278. return $.timeago(d);
  279. }
  280. return "";
  281. }.property('content.lastHeartBeatTime')
  282. });