host_component.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  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.HostComponent = DS.Model.extend({
  20. workStatus: DS.attr('string'),
  21. passiveState: DS.attr('string'),
  22. componentName: DS.attr('string'),
  23. displayName: DS.attr('string'),
  24. haStatus: DS.attr('string'),
  25. displayNameAdvanced: DS.attr('string'),
  26. staleConfigs: DS.attr('boolean'),
  27. host: DS.belongsTo('App.Host'),
  28. hostName: DS.attr('string'),
  29. service: DS.belongsTo('App.Service'),
  30. adminState: DS.attr('string'),
  31. summaryLabelClassName:function(){
  32. return 'label_for_'+this.get('componentName').toLowerCase();
  33. }.property('componentName'),
  34. summaryValueClassName:function(){
  35. return 'value_for_'+this.get('componentName').toLowerCase();
  36. }.property('componentName'),
  37. /**
  38. * Determine if component is client
  39. * @returns {bool}
  40. */
  41. isClient: function () {
  42. return App.get('components.clients').contains(this.get('componentName'));
  43. }.property('componentName'),
  44. /**
  45. * Determine if component is running now
  46. * Based on <code>workStatus</code>
  47. * @returns {bool}
  48. */
  49. isRunning: Em.computed.existsIn('workStatus', ['STARTED', 'STARTING']),
  50. /**
  51. * Determines if component is not installed
  52. * Based on <code>workStatus</code>
  53. *
  54. * @type {boolean}
  55. */
  56. isNotInstalled: Em.computed.existsIn('workStatus', ['INIT', 'INSTALL_FAILED']),
  57. /**
  58. * Determine if component is master
  59. * @returns {bool}
  60. */
  61. isMaster: function () {
  62. return App.get('components.masters').contains(this.get('componentName'));
  63. }.property('componentName', 'App.components.masters'),
  64. /**
  65. * Determine if component is slave
  66. * @returns {bool}
  67. */
  68. isSlave: function () {
  69. return App.get('components.slaves').contains(this.get('componentName'));
  70. }.property('componentName'),
  71. /**
  72. * Only certain components can be deleted.
  73. * They include some from master components,
  74. * some from slave components, and rest from
  75. * client components.
  76. * @returns {bool}
  77. */
  78. isDeletable: function () {
  79. return App.get('components.deletable').contains(this.get('componentName'));
  80. }.property('componentName'),
  81. /**
  82. * A host-component is decommissioning when it is in HDFS service's list of
  83. * decomNodes.
  84. * @returns {bool}
  85. */
  86. isDecommissioning: function () {
  87. var decommissioning = false;
  88. var hostName = this.get('hostName');
  89. var componentName = this.get('componentName');
  90. var hdfsSvc = App.HDFSService.find().objectAt(0);
  91. if (componentName === 'DATANODE' && hdfsSvc) {
  92. var decomNodes = hdfsSvc.get('decommissionDataNodes');
  93. var decomNode = decomNodes != null ? decomNodes.findProperty("hostName", hostName) : null;
  94. decommissioning = decomNode != null;
  95. }
  96. return decommissioning;
  97. }.property('componentName', 'hostName', 'App.router.clusterController.isLoaded', 'App.router.updateController.isUpdated'),
  98. /**
  99. * User friendly host component status
  100. * @returns {String}
  101. */
  102. isActive: Em.computed.equal('passiveState', 'OFF'),
  103. /**
  104. * Determine if passiveState is implied from host or/and service
  105. * @returns {Boolean}
  106. */
  107. isImpliedState: Em.computed.existsIn('passiveState', ['IMPLIED_FROM_SERVICE_AND_HOST', 'IMPLIED_FROM_HOST', 'IMPLIED_FROM_SERVICE']),
  108. passiveTooltip: Em.computed.ifThenElse('isActive', '', Em.I18n.t('hosts.component.passive.mode')),
  109. /**
  110. * Determine if component is a HDP component
  111. * @returns {bool}
  112. */
  113. isHDPComponent: function () {
  114. return !App.get('components.nonHDP').contains(this.get('componentName'));
  115. }.property('componentName', 'App.components.nonHDP'),
  116. /**
  117. * Does component have Critical Alerts
  118. * @type {boolean}
  119. */
  120. hasCriticalAlerts: false,
  121. /**
  122. * Number of the Critical and Warning alerts for current component
  123. * @type {number}
  124. */
  125. alertsCount: 0,
  126. statusClass: function () {
  127. return this.get('isActive') ? this.get('workStatus') : 'icon-medkit';
  128. }.property('workStatus', 'isActive'),
  129. statusIconClass: function () {
  130. switch (this.get('statusClass')) {
  131. case 'STARTED':
  132. case 'STARTING':
  133. return App.healthIconClassGreen;
  134. break;
  135. case 'INSTALLED':
  136. case 'STOPPING':
  137. return App.healthIconClassRed;
  138. break;
  139. case 'UNKNOWN':
  140. return App.healthIconClassYellow;
  141. break;
  142. default:
  143. return "";
  144. break;
  145. }
  146. }.property('statusClass'),
  147. componentTextStatus: function () {
  148. return App.HostComponentStatus.getTextStatus(this.get("workStatus"));
  149. }.property('workStatus', 'isDecommissioning')
  150. });
  151. App.HostComponent.FIXTURES = [];
  152. /**
  153. * get particular counter of host-component by name
  154. * @param {string} componentName
  155. * @param {string} type (installedCount|startedCount|totalCount)
  156. * @returns {number}
  157. */
  158. App.HostComponent.getCount = function (componentName, type) {
  159. switch (App.StackServiceComponent.find(componentName).get('componentCategory')) {
  160. case 'MASTER':
  161. return Number(App.MasterComponent.find(componentName).get(type));
  162. case 'SLAVE':
  163. return Number(App.SlaveComponent.find(componentName).get(type));
  164. case 'CLIENT':
  165. return Number(App.ClientComponent.find(componentName).get(type));
  166. default:
  167. return 0;
  168. }
  169. };
  170. App.HostComponentStatus = {
  171. started: "STARTED",
  172. starting: "STARTING",
  173. stopped: "INSTALLED",
  174. stopping: "STOPPING",
  175. install_failed: "INSTALL_FAILED",
  176. installing: "INSTALLING",
  177. upgrade_failed: "UPGRADE_FAILED",
  178. unknown: "UNKNOWN",
  179. disabled: "DISABLED",
  180. init: "INIT",
  181. /**
  182. * Get host component status in "machine" format
  183. * @param {String} value
  184. * @returns {String}
  185. */
  186. getKeyName: function (value) {
  187. switch (value) {
  188. case this.started:
  189. return 'started';
  190. case this.starting:
  191. return 'starting';
  192. case this.stopped:
  193. return 'installed';
  194. case this.stopping:
  195. return 'stopping';
  196. case this.install_failed:
  197. return 'install_failed';
  198. case this.installing:
  199. return 'installing';
  200. case this.upgrade_failed:
  201. return 'upgrade_failed';
  202. case this.disabled:
  203. case this.unknown:
  204. return 'unknown';
  205. }
  206. return 'unknown';
  207. },
  208. /**
  209. * Get user-friendly host component status
  210. * @param {String} value
  211. * @returns {String}
  212. */
  213. getTextStatus: function (value) {
  214. switch (value) {
  215. case this.installing:
  216. return 'Installing...';
  217. case this.install_failed:
  218. return 'Install Failed';
  219. case this.stopped:
  220. return 'Stopped';
  221. case this.started:
  222. return 'Started';
  223. case this.starting:
  224. return 'Starting...';
  225. case this.stopping:
  226. return 'Stopping...';
  227. case this.unknown:
  228. return 'Heartbeat Lost';
  229. case this.upgrade_failed:
  230. return 'Upgrade Failed';
  231. case this.disabled:
  232. return 'Disabled';
  233. case this.init:
  234. return 'Install Pending...';
  235. }
  236. return 'Unknown';
  237. },
  238. /**
  239. * Get list of possible <code>App.HostComponent</code> statuses
  240. * @returns {String[]}
  241. */
  242. getStatusesList: function () {
  243. var ret = [];
  244. for (var st in this) {
  245. if (this.hasOwnProperty(st) && Em.typeOf(this[st]) == 'string') {
  246. ret.push(this[st]);
  247. }
  248. }
  249. return ret;
  250. }
  251. };
  252. App.HostComponentActionMap = {
  253. getMap: function(ctx) {
  254. var NN = ctx.get('controller.content.hostComponents').findProperty('componentName', 'NAMENODE');
  255. var RM = ctx.get('controller.content.hostComponents').findProperty('componentName', 'RESOURCEMANAGER');
  256. var RA = ctx.get('controller.content.hostComponents').findProperty('componentName', 'RANGER_ADMIN');
  257. var HM = ctx.get('controller.content.hostComponents').findProperty('componentName', 'HAWQMASTER');
  258. var HS = ctx.get('controller.content.hostComponents').findProperty('componentName', 'HAWQSTANDBY');
  259. var HMComponent = App.MasterComponent.find('HAWQMASTER');
  260. return {
  261. RESTART_ALL: {
  262. action: 'restartAllHostComponents',
  263. context: ctx.get('serviceName'),
  264. label: Em.I18n.t('restart.service.all'),
  265. cssClass: 'icon-repeat',
  266. disabled: false
  267. },
  268. RUN_SMOKE_TEST: {
  269. action: 'runSmokeTest',
  270. label: Em.I18n.t('services.service.actions.run.smoke'),
  271. cssClass: 'icon-thumbs-up-alt',
  272. disabled: ctx.get('controller.isClientsOnlyService') ? false : ctx.get('controller.isStopDisabled')
  273. },
  274. REFRESH_CONFIGS: {
  275. action: 'refreshConfigs',
  276. label: Em.I18n.t('hosts.host.details.refreshConfigs'),
  277. cssClass: 'icon-refresh',
  278. disabled: false
  279. },
  280. REFRESHQUEUES: {
  281. action: 'refreshYarnQueues',
  282. customCommand: 'REFRESHQUEUES',
  283. context : Em.I18n.t('services.service.actions.run.yarnRefreshQueues.context'),
  284. label: Em.I18n.t('services.service.actions.run.yarnRefreshQueues.menu'),
  285. cssClass: 'icon-refresh',
  286. disabled: false
  287. },
  288. ROLLING_RESTART: {
  289. action: 'rollingRestart',
  290. context: ctx.get('rollingRestartComponent'),
  291. label: Em.I18n.t('rollingrestart.dialog.title'),
  292. cssClass: 'icon-time',
  293. disabled: false
  294. },
  295. TOGGLE_PASSIVE: {
  296. action: 'turnOnOffPassive',
  297. context: ctx.get('isPassive') ? Em.I18n.t('passiveState.turnOffFor').format(ctx.get('displayName')) : Em.I18n.t('passiveState.turnOnFor').format(ctx.get('displayName')),
  298. label: ctx.get('isPassive') ? Em.I18n.t('passiveState.turnOff') : Em.I18n.t('passiveState.turnOn'),
  299. cssClass: 'icon-medkit',
  300. disabled: false
  301. },
  302. TOGGLE_NN_HA: {
  303. action: App.get('isHaEnabled') ? 'disableHighAvailability' : 'enableHighAvailability',
  304. label: App.get('isHaEnabled') ? Em.I18n.t('admin.highAvailability.button.disable') : Em.I18n.t('admin.highAvailability.button.enable'),
  305. cssClass: App.get('isHaEnabled') ? 'icon-arrow-down' : 'icon-arrow-up',
  306. isHidden: App.get('isHaEnabled'),
  307. disabled: App.get('isSingleNode') || !NN || NN.get('isNotInstalled')
  308. },
  309. TOGGLE_RM_HA: {
  310. action: 'enableRMHighAvailability',
  311. label: Em.I18n.t('admin.rm_highAvailability.button.enable'),
  312. cssClass: 'icon-arrow-up',
  313. isHidden: App.get('isRMHaEnabled'),
  314. disabled: App.get('isSingleNode') || !RM || RM.get('isNotInstalled')
  315. },
  316. TOGGLE_RA_HA: {
  317. action: 'enableRAHighAvailability',
  318. label: Em.I18n.t('admin.ra_highAvailability.button.enable'),
  319. cssClass: 'icon-arrow-up',
  320. isHidden: App.get('isRAHaEnabled'),
  321. disabled: App.get('isSingleNode') || !RA || RA.get('isNotInstalled')
  322. },
  323. MOVE_COMPONENT: {
  324. action: 'reassignMaster',
  325. context: '',
  326. isHidden: !App.isAuthorized('SERVICE.MOVE'),
  327. label: Em.I18n.t('services.service.actions.reassign.master'),
  328. cssClass: 'icon-share-alt'
  329. },
  330. STARTDEMOLDAP: {
  331. action: 'startLdapKnox',
  332. customCommand: 'STARTDEMOLDAP',
  333. context: Em.I18n.t('services.service.actions.run.startLdapKnox.context'),
  334. label: Em.I18n.t('services.service.actions.run.startLdapKnox.context'),
  335. cssClass: 'icon-play-sign',
  336. disabled: false
  337. },
  338. STOPDEMOLDAP: {
  339. action: 'stopLdapKnox',
  340. customCommand: 'STOPDEMOLDAP',
  341. context: Em.I18n.t('services.service.actions.run.stopLdapKnox.context'),
  342. label: Em.I18n.t('services.service.actions.run.stopLdapKnox.context'),
  343. cssClass: 'icon-stop',
  344. disabled: false
  345. },
  346. REBALANCEHDFS: {
  347. action: 'rebalanceHdfsNodes',
  348. customCommand: 'REBALANCEHDFS',
  349. context: Em.I18n.t('services.service.actions.run.rebalanceHdfsNodes.context'),
  350. label: Em.I18n.t('services.service.actions.run.rebalanceHdfsNodes'),
  351. cssClass: 'icon-refresh',
  352. disabled: false
  353. },
  354. DOWNLOAD_CLIENT_CONFIGS: {
  355. action: ctx.get('controller.isSeveralClients') ? '' : 'downloadClientConfigs',
  356. label: Em.I18n.t('services.service.actions.downloadClientConfigs'),
  357. cssClass: 'icon-download-alt',
  358. isHidden: !!ctx.get('controller.content.clientComponents') ? ctx.get('controller.content.clientComponents').rejectProperty('totalCount', 0).length == 0 : false,
  359. disabled: false,
  360. hasSubmenu: ctx.get('controller.isSeveralClients'),
  361. submenuOptions: ctx.get('controller.clientComponents')
  362. },
  363. DELETE_SERVICE: {
  364. action: 'deleteService',
  365. context: ctx.get('serviceName'),
  366. label: Em.I18n.t('common.delete'),
  367. cssClass: 'icon-remove'
  368. },
  369. IMMEDIATE_STOP_HAWQ_SERVICE: {
  370. action: 'executeHawqCustomCommand',
  371. customCommand: 'IMMEDIATE_STOP_HAWQ_SERVICE',
  372. context: Em.I18n.t('services.service.actions.run.immediateStopHawqService.context'),
  373. label: Em.I18n.t('services.service.actions.run.immediateStopHawqService.label'),
  374. cssClass: 'icon-stop',
  375. disabled: !HM || HM.get('workStatus') != App.HostComponentStatus.started
  376. },
  377. IMMEDIATE_STOP_HAWQ_SEGMENT: {
  378. customCommand: 'IMMEDIATE_STOP_HAWQ_SEGMENT',
  379. context: Em.I18n.t('services.service.actions.run.immediateStopHawqSegment.context'),
  380. label: Em.I18n.t('services.service.actions.run.immediateStopHawqSegment.label'),
  381. cssClass: 'icon-stop'
  382. },
  383. RESYNC_HAWQ_STANDBY: {
  384. action: 'executeHawqCustomCommand',
  385. customCommand: 'RESYNC_HAWQ_STANDBY',
  386. context: Em.I18n.t('services.service.actions.run.resyncHawqStandby.context'),
  387. label: Em.I18n.t('services.service.actions.run.resyncHawqStandby.label'),
  388. cssClass: 'icon-refresh',
  389. isHidden : App.get('isSingleNode') || !HS ,
  390. disabled: !((!!HMComponent && HMComponent.get('startedCount') === 1) && (!!HS && HS.get('workStatus') === App.HostComponentStatus.started))
  391. },
  392. TOGGLE_ADD_HAWQ_STANDBY: {
  393. action: 'addHawqStandby',
  394. label: Em.I18n.t('admin.addHawqStandby.button.enable'),
  395. cssClass: 'icon-plus',
  396. isHidden: App.get('isSingleNode') || HS,
  397. disabled: false
  398. },
  399. ACTIVATE_HAWQ_STANDBY: {
  400. action: 'activateHawqStandby',
  401. label: Em.I18n.t('admin.activateHawqStandby.button.enable'),
  402. context: Em.I18n.t('admin.activateHawqStandby.button.enable'),
  403. cssClass: 'icon-arrow-up',
  404. isHidden: App.get('isSingleNode') || !HS,
  405. disabled: false
  406. },
  407. HAWQ_CLEAR_CACHE: {
  408. action: 'executeHawqCustomCommand',
  409. customCommand: 'HAWQ_CLEAR_CACHE',
  410. context: Em.I18n.t('services.service.actions.run.clearHawqCache.label'),
  411. label: Em.I18n.t('services.service.actions.run.clearHawqCache.label'),
  412. cssClass: 'icon-refresh',
  413. isHidden : false,
  414. disabled: !HM || HM.get('workStatus') != App.HostComponentStatus.started
  415. },
  416. RUN_HAWQ_CHECK: {
  417. action: 'executeHawqCustomCommand',
  418. customCommand: 'RUN_HAWQ_CHECK',
  419. context: Em.I18n.t('services.service.actions.run.runHawqCheck.label'),
  420. label: Em.I18n.t('services.service.actions.run.runHawqCheck.label'),
  421. cssClass: 'icon-thumbs-up-alt',
  422. isHidden : false,
  423. disabled: false
  424. },
  425. MASTER_CUSTOM_COMMAND: {
  426. action: 'executeCustomCommand',
  427. cssClass: 'icon-play-circle',
  428. isHidden: false,
  429. disabled: false
  430. }
  431. };
  432. }
  433. };