service.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  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: App.config.get('preDefinedServiceConfigs'),
  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)) {
  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. "YARN",
  106. "MAPREDUCE",
  107. "MAPREDUCE2",
  108. "HBASE",
  109. "OOZIE",
  110. "HIVE",
  111. "WEBHCAT",
  112. "ZOOKEEPER",
  113. "PIG",
  114. "SQOOP",
  115. "NAGIOS",
  116. "HUE"
  117. ];
  118. return configurableServices.contains(this.get('serviceName'));
  119. }.property('serviceName'),
  120. displayName: function () {
  121. switch (this.get('serviceName').toLowerCase()) {
  122. case 'hdfs':
  123. return 'HDFS';
  124. case 'yarn':
  125. return 'YARN';
  126. case 'mapreduce':
  127. return 'MapReduce';
  128. case 'mapreduce2':
  129. return 'MapReduce2';
  130. case 'tez':
  131. return 'Tez';
  132. case 'hbase':
  133. return 'HBase';
  134. case 'oozie':
  135. return 'Oozie';
  136. case 'hive':
  137. return 'Hive/HCat';
  138. case 'hcatalog':
  139. return 'HCat';
  140. case 'zookeeper':
  141. return 'ZooKeeper';
  142. case 'pig':
  143. return 'Pig';
  144. case 'sqoop':
  145. return 'Sqoop';
  146. case 'webhcat':
  147. return 'WebHCat';
  148. case 'ganglia':
  149. return 'Ganglia';
  150. case 'nagios':
  151. return 'Nagios';
  152. case 'hue':
  153. return 'Hue';
  154. }
  155. return this.get('serviceName');
  156. }.property('serviceName'),
  157. /**
  158. * For each host-component, if the desired_configs dont match the
  159. * actual_configs, then a restart is required. Except for Global site
  160. * properties, which need to be checked with map.
  161. */
  162. isRestartRequired: function () {
  163. var restartRequired = false;
  164. var restartRequiredHostsAndComponents = {};
  165. var clusterDesiredConfigs = App.router.get('mainServiceController.cluster.desiredConfigs');
  166. var serviceTemplate = this.serviceConfigsTemplate.findProperty('serviceName', this.get('serviceName'));
  167. if (clusterDesiredConfigs != null && serviceTemplate!=null) {
  168. var clusterToDesiredMap = {};
  169. clusterDesiredConfigs.forEach(function (config) {
  170. clusterToDesiredMap[config.site] = config;
  171. });
  172. this.get('hostComponents').forEach(function(hostComponent){
  173. var host = hostComponent.get('host');
  174. var hostName = host.get('hostName');
  175. hostComponent.get('actualConfigs').forEach(function(config){
  176. if(serviceTemplate.sites.contains(config.site)){
  177. var desiredClusterTag = clusterToDesiredMap[config.site].tag;
  178. var desiredHostOverrideTag = clusterToDesiredMap[config.site].hostOverrides[hostName];
  179. var actualClusterTag = config.tag;
  180. var actualHostOverrideTag = config.hostOverrides[hostName];
  181. var siteRestartRequired = false;
  182. if(actualClusterTag !== desiredClusterTag || actualHostOverrideTag !== desiredHostOverrideTag){
  183. var publicHostName = host.get('publicHostName');
  184. if(config.site=='global'){
  185. var serviceName = hostComponent.get('service.serviceName');
  186. if(actualClusterTag !== desiredClusterTag){
  187. siteRestartRequired = App.config.isServiceEffectedByGlobalChange(serviceName, actualClusterTag, desiredClusterTag);
  188. }
  189. if(actualHostOverrideTag !== desiredHostOverrideTag){
  190. siteRestartRequired = App.config.isServiceEffectedByGlobalChange(serviceName, actualHostOverrideTag, desiredHostOverrideTag);
  191. }
  192. }else{
  193. siteRestartRequired = true
  194. }
  195. if(siteRestartRequired){
  196. restartRequired = true;
  197. if(!(publicHostName in restartRequiredHostsAndComponents)){
  198. restartRequiredHostsAndComponents[publicHostName] = [];
  199. }
  200. var hostComponentName = hostComponent.get('displayName');
  201. if(restartRequiredHostsAndComponents[publicHostName].indexOf(hostComponentName)<0){
  202. restartRequiredHostsAndComponents[publicHostName].push(hostComponentName);
  203. }
  204. }
  205. }
  206. }
  207. });
  208. });
  209. }
  210. this.set('restartRequiredHostsAndComponents', restartRequiredHostsAndComponents);
  211. return restartRequired;
  212. }.property('serviceName', 'hostComponents', 'hostComponents.@each.actualConfigs', 'hostComponents.@each.actualConfigs.@each.tag',
  213. 'App.router.mainServiceController.cluster.desiredConfigs', 'App.router.mainServiceController.cluster.desiredConfigs.@each.tag'),
  214. /**
  215. * Contains a map of which hosts and host_components
  216. * need a restart. This is populated when calculating
  217. * #isRestartRequired()
  218. * Example:
  219. * {
  220. * 'publicHostName1': ['TaskTracker'],
  221. * 'publicHostName2': ['JobTracker', 'TaskTracker']
  222. * }
  223. */
  224. restartRequiredHostsAndComponents: {},
  225. /**
  226. * Based on the information in #restartRequiredHostsAndComponents
  227. */
  228. restartRequiredMessage: function () {
  229. var restartHC = this.get('restartRequiredHostsAndComponents');
  230. var hostCount = 0;
  231. var hcCount = 0;
  232. var hostsMsg = "<ul>";
  233. for(var host in restartHC){
  234. hostCount++;
  235. hostsMsg += "<li>"+host+"</li><ul>";
  236. restartHC[host].forEach(function(c){
  237. hcCount++;
  238. hostsMsg += "<li>"+c+"</li>";
  239. })
  240. hostsMsg += "</ul>";
  241. }
  242. hostsMsg += "</ul>"
  243. return this.t('services.service.config.restartService.TooltipMessage').format(hcCount, hostCount, hostsMsg);
  244. }.property('restartRequiredHostsAndComponents')
  245. });
  246. App.Service.Health = {
  247. live: "LIVE",
  248. dead: "DEAD-RED",
  249. starting: "STARTING",
  250. stopping: "STOPPING",
  251. unknown: "DEAD-YELLOW",
  252. getKeyName: function (value) {
  253. switch (value) {
  254. case this.live:
  255. return 'live';
  256. case this.dead:
  257. return 'dead';
  258. case this.starting:
  259. return 'starting';
  260. case this.stopping:
  261. return 'stopping';
  262. case this.unknown:
  263. return 'unknown';
  264. }
  265. return 'none';
  266. }
  267. };
  268. App.Service.FIXTURES = [];