host.js 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  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. var misc = require('utils/misc');
  20. App.Host = DS.Model.extend({
  21. hostName: DS.attr('string'),
  22. publicHostName: DS.attr('string'),
  23. cluster: DS.belongsTo('App.Cluster'),
  24. hostComponents: DS.hasMany('App.HostComponent'),
  25. notStartedComponents: DS.hasMany('App.HostComponent'),
  26. componentsWithStaleConfigs: DS.hasMany('App.HostComponent'),
  27. componentsInPassiveState: DS.hasMany('App.HostComponent'),
  28. cpu: DS.attr('string'),
  29. cpuPhysical: DS.attr('string'),
  30. memory: DS.attr('string'),
  31. diskTotal: DS.attr('number'),
  32. diskFree: DS.attr('number'),
  33. osArch: DS.attr('string'),
  34. ip: DS.attr('string'),
  35. rack: DS.attr('string'),
  36. healthStatus: DS.attr('string'),
  37. lastHeartBeatTime: DS.attr('number'),
  38. rawLastHeartBeatTime: DS.attr('number'),
  39. osType: DS.attr("string"),
  40. diskInfo: DS.attr('object'),
  41. loadOne:DS.attr('number'),
  42. loadFive:DS.attr('number'),
  43. loadFifteen:DS.attr('number'),
  44. memTotal:DS.attr('number'),
  45. memFree:DS.attr('number'),
  46. cpuSystem:DS.attr('number'),
  47. cpuUser:DS.attr('number'),
  48. criticalWarningAlertsCount: DS.attr('number'),
  49. alertsSummary: DS.attr('object'),
  50. passiveState: DS.attr('string'),
  51. index: DS.attr('number'),
  52. stackVersions: DS.hasMany('App.HostStackVersion'),
  53. /**
  54. * Is host checked at the main Hosts page
  55. */
  56. selected:DS.attr('boolean'),
  57. currentVersion: function () {
  58. var current = this.get('stackVersions').findProperty('isCurrent');
  59. return current ? current.get('repoVersion') : null;
  60. }.property('stackVersions.@each.isCurrent'),
  61. /**
  62. * Overall CPU usage (system and user)
  63. * @returns {Number}
  64. */
  65. cpuUsage: function () {
  66. if (this.get('cpuSystem') && this.get('cpuUser')) {
  67. return this.get('cpuSystem') + this.get('cpuUser');
  68. }
  69. return 0;
  70. }.property('cpuSystem', 'cpuUser'),
  71. /**
  72. * Percent value of used memory
  73. * @returns {Number}
  74. */
  75. memoryUsage: function () {
  76. if (this.get('memFree') && this.get('memTotal')) {
  77. var memUsed = this.get('memTotal') - this.get('memFree');
  78. return (100 * memUsed) / this.get('memTotal');
  79. }
  80. return 0;
  81. }.property('memTotal', 'memFree'),
  82. /**
  83. * @type {number}
  84. */
  85. componentsInPassiveStateCount: Em.computed.alias('componentsInPassiveState.length'),
  86. /**
  87. * Get count of host components with stale configs
  88. * @returns {Number}
  89. */
  90. componentsWithStaleConfigsCount: Em.computed.alias('componentsWithStaleConfigs.length'),
  91. /**
  92. * Count of mounted on host disks
  93. * @returns {Number}
  94. */
  95. disksMounted: Em.computed.alias('diskInfo.length'),
  96. coresFormatted: Em.computed.format('{0} ({1})', 'cpu', 'cpuPhysical'),
  97. /**
  98. * API return diskTotal and diskFree. Need to save their different
  99. * @returns {Number}
  100. */
  101. diskUsed: function(){
  102. return this.get('diskTotal') - this.get('diskFree');
  103. }.property('diskFree', 'diskTotal'),
  104. /**
  105. * Format diskUsed value to float with 2 digits (also convert to GB)
  106. * @returns {String} Format: '*** GB'
  107. */
  108. diskUsedFormatted: function() {
  109. return Math.round(this.get('diskUsed') * Math.pow(10, 2)) / Math.pow(10, 2) + 'GB';
  110. }.property('diskUsed'),
  111. /**
  112. * Format diskTotal value to float with 2 digits (also convert to GB)
  113. * @returns {String} Format: '*** GB'
  114. */
  115. diskTotalFormatted: function() {
  116. return Math.round(this.get('diskTotal') * Math.pow(10, 2)) / Math.pow(10, 2) + 'GB';
  117. }.property('diskTotal'),
  118. /**
  119. * Percent value of used disk space
  120. * @returns {Number}
  121. */
  122. diskUsage: Em.computed.percents('diskUsed', 'diskTotal', 2),
  123. /**
  124. * Format diskUsage to float with 2 digits
  125. * @returns {String} Format: '**.** %'
  126. */
  127. diskUsageFormatted: function() {
  128. if (isNaN(this.get('diskUsage')) || this.get('diskUsage') < 0) {
  129. return Em.I18n.t('hosts.host.metrics.dataUnavailable');
  130. }
  131. var s = Math.round(this.get('diskUsage') * Math.pow(10, 2)) / Math.pow(10, 2);
  132. if (isNaN(s)) {
  133. s = 0;
  134. }
  135. return s + '%';
  136. }.property('diskUsage'),
  137. /**
  138. * Formatted string with data about disk usage
  139. * @returns {String}
  140. */
  141. diskInfoBar: function() {
  142. if (isNaN(this.get('diskUsage')) || this.get('diskUsage') < 0) {
  143. return this.get('diskUsageFormatted');
  144. }
  145. return this.get('diskUsedFormatted') + '/' + this.get('diskTotalFormatted') + ' (' + this.get('diskUsageFormatted')
  146. + ' ' + Em.I18n.t('services.service.summary.diskInfoBar.used') + ')';
  147. }.property('diskUsedFormatted', 'diskTotalFormatted'),
  148. /**
  149. * Formatted bytes to appropriate value
  150. * @returns {String}
  151. */
  152. memoryFormatted: function () {
  153. return misc.formatBandwidth(this.get('memory') * 1024);
  154. }.property('memory'),
  155. /**
  156. * Return true if the host <code>healthStatus</code> is UNKNOWN
  157. * @returns {bool}
  158. */
  159. isNotHeartBeating : function() {
  160. return (App.get('testMode')) ? false : (this.get('healthStatus') === "UNKNOWN");
  161. }.property('lastHeartBeatTime'),
  162. /**
  163. * Average load
  164. * @returns {Number}
  165. */
  166. loadAvg: function() {
  167. if (this.get('loadOne') != null) return this.get('loadOne').toFixed(2);
  168. if (this.get('loadFive') != null) return this.get('loadFive').toFixed(2);
  169. if (this.get('loadFifteen') != null) return this.get('loadFifteen').toFixed(2);
  170. return null;
  171. }.property('loadOne', 'loadFive', 'loadFifteen'),
  172. /**
  173. * Host health indicator
  174. * Based on <code>healthStatus</code>
  175. * @returns {String}
  176. */
  177. healthClass: function(){
  178. if (this.get('passiveState')!= 'OFF') {
  179. return 'icon-medkit';
  180. }
  181. var statusMap = {
  182. 'UNKNOWN': 'health-status-DEAD-YELLOW',
  183. 'HEALTHY': 'health-status-LIVE',
  184. 'UNHEALTHY': 'health-status-DEAD-RED',
  185. 'ALERT': 'health-status-DEAD-ORANGE'
  186. };
  187. return statusMap[this.get('healthStatus')] || 'health-status-DEAD-YELLOW';
  188. }.property('healthStatus'),
  189. healthIconClass: Em.computed.getByKey('healthIconClassMap', 'healthClass', ''),
  190. healthIconClassMap: {
  191. 'health-status-LIVE': App.healthIconClassGreen,
  192. 'health-status-DEAD-RED': App.healthIconClassRed,
  193. 'health-status-DEAD-YELLOW': App.healthIconClassYellow,
  194. 'health-status-DEAD-ORANGE': App.healthIconClassOrange
  195. },
  196. /**
  197. * Tooltip for host indicator
  198. * Contains affected host components names (based on <code>healthClass</code>)
  199. * @returns {String}
  200. */
  201. healthToolTip: function () {
  202. var hostComponents = this.get('notStartedComponents');
  203. var output = '';
  204. if (this.get('passiveState') != 'OFF') {
  205. return Em.I18n.t('hosts.host.passive.mode');
  206. }
  207. switch (this.get('healthClass')) {
  208. case 'health-status-DEAD-RED':
  209. hostComponents = hostComponents.filterProperty('isMaster');
  210. output = Em.I18n.t('hosts.host.healthStatus.mastersDown');
  211. hostComponents.forEach(function (hc, index) {
  212. output += (index == (hostComponents.length - 1)) ? hc.get('displayName') : (hc.get('displayName') + ", ");
  213. }, this);
  214. break;
  215. case 'health-status-DEAD-YELLOW':
  216. output = Em.I18n.t('hosts.host.healthStatus.heartBeatNotReceived');
  217. break;
  218. case 'health-status-DEAD-ORANGE':
  219. hostComponents = hostComponents.filterProperty('isSlave');
  220. output = Em.I18n.t('hosts.host.healthStatus.slavesDown');
  221. hostComponents.forEach(function (hc, index) {
  222. output += (index == (hostComponents.length - 1)) ? hc.get('displayName') : (hc.get('displayName') + ", ");
  223. }, this);
  224. break;
  225. case 'health-status-LIVE':
  226. output = Em.I18n.t('hosts.host.healthStatus.allUp');
  227. break;
  228. }
  229. return output;
  230. }.property('passiveState', 'healthClass', 'notStartedComponents.@each')
  231. });
  232. App.Host.FIXTURES = [];