service.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  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.Service = DS.Model.extend({
  20. serviceName: DS.attr('string'),
  21. workStatus: DS.attr('string'),
  22. rand: DS.attr('string'),
  23. alerts: DS.hasMany('App.Alert'),
  24. quickLinks: DS.hasMany('App.QuickLinks'),
  25. hostComponents: DS.hasMany('App.HostComponent'),
  26. serviceConfigsTemplate: require('data/service_configs'),
  27. runningHostComponents: null,
  28. isStartDisabled: function () {
  29. return !(this.get('healthStatus') == 'red');
  30. }.property('healthStatus'),
  31. isStopDisabled: function () {
  32. return !(this.get('healthStatus') == 'green');
  33. }.property('healthStatus'),
  34. // Instead of making healthStatus a computed property that listens on hostComponents.@each.workStatus,
  35. // we are creating a separate observer _updateHealthStatus. This is so that healthStatus is updated
  36. // only once after the run loop. This is because Ember invokes the computed property every time
  37. // a property that it depends on changes. For example, App.statusMapper's map function would invoke
  38. // the computed property too many times and freezes the UI without this hack.
  39. // See http://stackoverflow.com/questions/12467345/ember-js-collapsing-deferring-expensive-observers-or-computed-properties
  40. healthStatus: '',
  41. updateHealthStatus: function () {
  42. // console.log('model:service.healthStatus ' + this.get('serviceName'));
  43. var components = this.get('hostComponents').filterProperty('isMaster', true);
  44. var isGreen = (this.get('serviceName') === 'HBASE' && App.supports.multipleHBaseMasters ?
  45. components.someProperty('workStatus', App.HostComponentStatus.started) :
  46. components.everyProperty('workStatus', App.HostComponentStatus.started));
  47. if (isGreen) {
  48. this.set('healthStatus', 'green');
  49. } else if (components.someProperty('workStatus', App.HostComponentStatus.starting)) {
  50. this.set('healthStatus', 'green-blinking');
  51. } else if (components.someProperty('workStatus', App.HostComponentStatus.stopped) || components.someProperty('workStatus', App.HostComponentStatus.start_failed)) {
  52. this.set('healthStatus', 'red');
  53. } else if (components.someProperty('workStatus', App.HostComponentStatus.unknown)) {
  54. this.set('healthStatus', 'yellow');
  55. } else {
  56. this.set('healthStatus', 'red-blinking');
  57. }
  58. if (this.get('serviceName') === 'HBASE') {
  59. var active = this.get('hostComponents').findProperty('haStatus', 'active');
  60. if (!active) {
  61. this.set('healthStatus', 'red');
  62. }
  63. }
  64. },
  65. /**
  66. * Every time when changes workStatus of any component we schedule recalculating values related from them
  67. */
  68. _updateHealthStatus: (function() {
  69. Ember.run.once(this, 'updateHealthStatus');
  70. Ember.run.once(this, 'updateIsStopped');
  71. Ember.run.once(this, 'updateIsStarted');
  72. }).observes('hostComponents.@each.workStatus'),
  73. isStopped: false,
  74. isStarted: false,
  75. updateIsStopped: function () {
  76. var components = this.get('hostComponents');
  77. var flag = true;
  78. var runningHCs = [];
  79. var unknownHCs = [];
  80. components.forEach(function (_component) {
  81. if (
  82. _component.get('workStatus') !== App.HostComponentStatus.stopped &&
  83. _component.get('workStatus') !== App.HostComponentStatus.install_failed &&
  84. _component.get('workStatus') !== App.HostComponentStatus.unknown
  85. ) {
  86. flag = false;
  87. runningHCs.addObject(_component);
  88. } else if (_component.get('workStatus') == App.HostComponentStatus.unknown) {
  89. unknownHCs.addObject(_component);
  90. }
  91. }, this);
  92. this.set('runningHostComponents', runningHCs);
  93. this.set('unknownHostComponents', unknownHCs);
  94. this.set('isStopped', flag);
  95. },
  96. updateIsStarted: function () {
  97. var components = this.get('hostComponents').filterProperty('isMaster', true);
  98. this.set('isStarted',
  99. components.everyProperty('workStatus', App.HostComponentStatus.started)
  100. );
  101. },
  102. isConfigurable: function () {
  103. var configurableServices = [
  104. "HDFS",
  105. "MAPREDUCE",
  106. "HBASE",
  107. "OOZIE",
  108. "HIVE",
  109. "WEBHCAT",
  110. "ZOOKEEPER",
  111. "PIG",
  112. "SQOOP",
  113. "NAGIOS",
  114. "HUE"
  115. ];
  116. return configurableServices.contains(this.get('serviceName'));
  117. }.property('serviceName'),
  118. displayName: function () {
  119. switch (this.get('serviceName').toLowerCase()) {
  120. case 'hdfs':
  121. return 'HDFS';
  122. case 'mapreduce':
  123. return 'MapReduce';
  124. case 'hbase':
  125. return 'HBase';
  126. case 'oozie':
  127. return 'Oozie';
  128. case 'hive':
  129. return 'Hive/HCat';
  130. case 'hcatalog':
  131. return 'HCat';
  132. case 'zookeeper':
  133. return 'ZooKeeper';
  134. case 'pig':
  135. return 'Pig';
  136. case 'sqoop':
  137. return 'Sqoop';
  138. case 'webhcat':
  139. return 'WebHCat';
  140. case 'ganglia':
  141. return 'Ganglia';
  142. case 'nagios':
  143. return 'Nagios';
  144. case 'hue':
  145. return 'Hue';
  146. }
  147. return this.get('serviceName');
  148. }.property('serviceName'),
  149. /**
  150. * For each host-component, if the desired_configs dont match the
  151. * actual_configs, then a restart is required. Except for Global site
  152. * properties, which need to be checked with map.
  153. */
  154. isRestartRequired: function () {
  155. var restartRequired = false;
  156. var restartRequiredHostsAndComponents = {};
  157. var clusterDesiredConfigs = App.router.get('mainServiceController.cluster.desiredConfigs');
  158. var serviceTemplate = this.serviceConfigsTemplate.findProperty('serviceName', this.get('serviceName'));
  159. if (clusterDesiredConfigs != null && serviceTemplate!=null) {
  160. var clusterToDesiredMap = {};
  161. clusterDesiredConfigs.forEach(function (config) {
  162. clusterToDesiredMap[config.site] = config;
  163. });
  164. this.get('hostComponents').forEach(function(hostComponent){
  165. var host = hostComponent.get('host');
  166. var hostName = host.get('hostName');
  167. hostComponent.get('actualConfigs').forEach(function(config){
  168. if(serviceTemplate.sites.contains(config.site)){
  169. var desiredClusterTag = clusterToDesiredMap[config.site].tag;
  170. var desiredHostOverrideTag = clusterToDesiredMap[config.site].hostOverrides[hostName];
  171. var actualClusterTag = config.tag;
  172. var actualHostOverrideTag = config.hostOverrides[hostName];
  173. var siteRestartRequired = false;
  174. if(actualClusterTag !== desiredClusterTag || actualHostOverrideTag !== desiredHostOverrideTag){
  175. var publicHostName = host.get('publicHostName');
  176. if(config.site=='global'){
  177. var serviceName = hostComponent.get('service.serviceName');
  178. if(actualClusterTag !== desiredClusterTag){
  179. siteRestartRequired = App.config.isServiceEffectedByGlobalChange(serviceName, actualClusterTag, desiredClusterTag);
  180. }
  181. if(actualHostOverrideTag !== desiredHostOverrideTag){
  182. siteRestartRequired = App.config.isServiceEffectedByGlobalChange(serviceName, actualHostOverrideTag, desiredHostOverrideTag);
  183. }
  184. }else{
  185. siteRestartRequired = true
  186. }
  187. if(siteRestartRequired){
  188. restartRequired = true;
  189. if(!(publicHostName in restartRequiredHostsAndComponents)){
  190. restartRequiredHostsAndComponents[publicHostName] = [];
  191. }
  192. var hostComponentName = hostComponent.get('displayName');
  193. if(restartRequiredHostsAndComponents[publicHostName].indexOf(hostComponentName)<0){
  194. restartRequiredHostsAndComponents[publicHostName].push(hostComponentName);
  195. }
  196. }
  197. }
  198. }
  199. });
  200. });
  201. }
  202. this.set('restartRequiredHostsAndComponents', restartRequiredHostsAndComponents);
  203. return restartRequired;
  204. }.property('serviceName', 'hostComponents', 'hostComponents.@each.actualConfigs', 'hostComponents.@each.actualConfigs.@each.tag',
  205. 'App.router.mainServiceController.cluster.desiredConfigs', 'App.router.mainServiceController.cluster.desiredConfigs.@each.tag'),
  206. /**
  207. * Contains a map of which hosts and host_components
  208. * need a restart. This is populated when calculating
  209. * #isRestartRequired()
  210. * Example:
  211. * {
  212. * 'publicHostName1': ['TaskTracker'],
  213. * 'publicHostName2': ['JobTracker', 'TaskTracker']
  214. * }
  215. */
  216. restartRequiredHostsAndComponents: {},
  217. /**
  218. * Based on the information in #restartRequiredHostsAndComponents
  219. */
  220. restartRequiredMessage: function () {
  221. var restartHC = this.get('restartRequiredHostsAndComponents');
  222. var hostCount = 0;
  223. var hcCount = 0;
  224. var hostsMsg = "<ul>";
  225. for(var host in restartHC){
  226. hostCount++;
  227. hostsMsg += "<li>"+host+"</li><ul>";
  228. restartHC[host].forEach(function(c){
  229. hcCount++;
  230. hostsMsg += "<li>"+c+"</li>";
  231. })
  232. hostsMsg += "</ul>";
  233. }
  234. hostsMsg += "</ul>"
  235. return this.t('services.service.config.restartService.TooltipMessage').format(hcCount, hostCount, hostsMsg);
  236. }.property('restartRequiredHostsAndComponents')
  237. });
  238. App.Service.Health = {
  239. live: "LIVE",
  240. dead: "DEAD-RED",
  241. starting: "STARTING",
  242. stopping: "STOPPING",
  243. unknown: "DEAD-YELLOW",
  244. getKeyName: function (value) {
  245. switch (value) {
  246. case this.live:
  247. return 'live';
  248. case this.dead:
  249. return 'dead';
  250. case this.starting:
  251. return 'starting';
  252. case this.stopping:
  253. return 'stopping';
  254. case this.unknown:
  255. return 'unknown';
  256. }
  257. return 'none';
  258. }
  259. };
  260. App.Service.FIXTURES = [];