service.js 10 KB

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