service.js 10 KB

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