details.js 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290
  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 batchUtils = require('utils/batch_scheduled_requests');
  20. App.MainHostDetailsController = Em.Controller.extend({
  21. name: 'mainHostDetailsController',
  22. content: null,
  23. isFromHosts: false,
  24. /**
  25. * path to page visited before
  26. */
  27. referer: '',
  28. /**
  29. * open dashboard page
  30. */
  31. routeHome: function () {
  32. App.router.transitionTo('main.dashboard');
  33. },
  34. /**
  35. * open summary page of the selected service
  36. * @param event
  37. */
  38. routeToService: function(event){
  39. var service = event.context;
  40. App.router.transitionTo('main.services.service.summary',service);
  41. },
  42. /**
  43. * Send specific command to server
  44. * @param url
  45. * @param _method
  46. * @param postData
  47. * @param callback
  48. */
  49. sendCommandToServer : function(url, postData, _method, callback){
  50. var url = (App.testMode) ?
  51. '/data/wizard/deploy/poll_1.json' : //content is the same as ours
  52. App.apiPrefix + '/clusters/' + App.router.getClusterName() + url;
  53. var method = App.testMode ? 'GET' : _method;
  54. $.ajax({
  55. type: method,
  56. url: url,
  57. data: JSON.stringify(postData),
  58. dataType: 'json',
  59. timeout: App.timeout,
  60. success: function(data){
  61. if(data && data.Requests){
  62. callback(data.Requests.id);
  63. } else{
  64. callback(null);
  65. console.log('cannot get request id from ', data);
  66. }
  67. },
  68. error: function (request, ajaxOptions, error) {
  69. //do something
  70. console.log('error on change component host status');
  71. App.ajax.defaultErrorHandler(request, url, method);
  72. },
  73. statusCode: require('data/statusCodes')
  74. });
  75. },
  76. /**
  77. * send command to server to start selected host component
  78. * @param event
  79. */
  80. startComponent: function (event) {
  81. var self = this;
  82. App.showConfirmationPopup(function() {
  83. var component = event.context;
  84. var context = Em.I18n.t('requestInfo.startHostComponent') + " " + component.get('displayName');
  85. self.sendStartComponentCommand(component, context);
  86. });
  87. },
  88. /**
  89. * PUTs a command to server to start a component. If no
  90. * specific component is provided, all components are started.
  91. * @param component When <code>null</code> all startable components are started.
  92. * @param context Context under which this command is beign sent.
  93. */
  94. sendStartComponentCommand: function(component, context) {
  95. var url = component !== null ?
  96. '/hosts/' + this.get('content.hostName') + '/host_components/' + component.get('componentName').toUpperCase() :
  97. '/hosts/' + this.get('content.hostName') + '/host_components?HostRoles/maintenance_state=OFF';
  98. var dataToSend = {
  99. RequestInfo : {
  100. "context" : context
  101. },
  102. Body:{
  103. HostRoles:{
  104. state: 'STARTED'
  105. }
  106. }
  107. };
  108. if (component === null) {
  109. var allComponents = this.get('content.hostComponents');
  110. var startable = [];
  111. allComponents.forEach(function (c) {
  112. if (c.get('passiveState') == 'OFF') {
  113. if (c.get('isMaster') || c.get('isSlave')) {
  114. startable.push(c.get('componentName'));
  115. }
  116. }
  117. });
  118. dataToSend.RequestInfo.query = "HostRoles/component_name.in(" + startable.join(',') + ")";
  119. }
  120. this.sendCommandToServer(url, dataToSend, 'PUT',
  121. function(requestId){
  122. if(!requestId){
  123. return;
  124. }
  125. console.log('Send request for STARTING successfully');
  126. if (App.testMode) {
  127. if(component === null){
  128. var allComponents = this.get('content.hostComponents');
  129. allComponents.forEach(function(component){
  130. component.set('workStatus', App.HostComponentStatus.stopping);
  131. setTimeout(function(){
  132. component.set('workStatus', App.HostComponentStatus.stopped);
  133. },App.testModeDelayForActions);
  134. });
  135. } else {
  136. component.set('workStatus', App.HostComponentStatus.starting);
  137. setTimeout(function(){
  138. component.set('workStatus', App.HostComponentStatus.started);
  139. },App.testModeDelayForActions);
  140. }
  141. } else {
  142. App.router.get('clusterController').loadUpdatedStatusDelayed(500);
  143. }
  144. // load data (if we need to show this background operations popup) from persist
  145. App.router.get('applicationController').dataLoading().done(function (initValue) {
  146. if (initValue) {
  147. App.router.get('backgroundOperationsController').showPopup();
  148. }
  149. });
  150. });
  151. },
  152. /**
  153. * send command to server to delete selected host component
  154. *
  155. */
  156. deleteComponent: function (event) {
  157. var self = this;
  158. var component = event.context;
  159. var componentName = component.get('componentName');
  160. var displayName = component.get('displayName');
  161. var isLastComponent = (App.HostComponent.find().filterProperty('componentName', componentName).get('length') === 1);
  162. App.ModalPopup.show({
  163. header: Em.I18n.t('popup.confirmation.commonHeader'),
  164. bodyClass: Ember.View.extend({
  165. templateName: require('templates/main/host/details/deleteComponentPopup')
  166. }),
  167. enablePrimary: false,
  168. lastComponent: function() {
  169. if (isLastComponent) {
  170. this.set('enablePrimary',false);
  171. return true;
  172. } else {
  173. this.set('enablePrimary',true);
  174. return false;
  175. }
  176. }.property(),
  177. lastComponentError: Em.View.extend({
  178. template: Ember.Handlebars.compile(Em.I18n.t('hosts.host.deleteComponent.popup.warning').format(displayName))
  179. }),
  180. deleteComponentMsg: function() {
  181. return Em.I18n.t('hosts.host.deleteComponent.popup.msg').format(displayName);
  182. }.property(),
  183. onPrimary: function () {
  184. if (!this.get('enablePrimary')) return;
  185. self._doDeleteHostComponent(component);
  186. self.set('redrawComponents', true);
  187. this.hide();
  188. }
  189. });
  190. },
  191. /**
  192. * Trigger to reset list of master/slaves components on the view
  193. * @type {bool}
  194. */
  195. redrawComponents: false,
  196. /**
  197. * Deletes the given host component, or all host components.
  198. *
  199. * @param component When <code>null</code> all host components are deleted.
  200. * @return <code>null</code> when components get deleted.
  201. * <code>{xhr: XhrObj, url: "http://", method: "DELETE"}</code>
  202. * when components failed to get deleted.
  203. */
  204. _doDeleteHostComponent: function(component) {
  205. var url = component !== null ?
  206. '/hosts/' + this.get('content.hostName') + '/host_components/' + component.get('componentName').toUpperCase() :
  207. '/hosts/' + this.get('content.hostName') + '/host_components';
  208. url = App.apiPrefix + '/clusters/' + App.router.getClusterName() + url;
  209. var deleted = null;
  210. $.ajax({
  211. type: 'DELETE',
  212. url: url,
  213. timeout: App.timeout,
  214. async: false,
  215. success: function (data) {
  216. deleted = null;
  217. },
  218. error: function (xhr, textStatus, errorThrown) {
  219. console.log('Error deleting host component');
  220. console.log(textStatus);
  221. console.log(errorThrown);
  222. deleted = {xhr: xhr, url: url, method: 'DELETE'};
  223. },
  224. statusCode: require('data/statusCodes')
  225. });
  226. return deleted;
  227. },
  228. /**
  229. * send command to server to upgrade selected host component
  230. * @param event
  231. */
  232. upgradeComponent: function (event) {
  233. var self = this;
  234. var component = event.context;
  235. App.showConfirmationPopup(function() {
  236. self.sendCommandToServer('/hosts/' + self.get('content.hostName') + '/host_components/' + component.get('componentName').toUpperCase(),{
  237. RequestInfo : {
  238. "context" : Em.I18n.t('requestInfo.upgradeHostComponent') + " " + component.get('displayName')
  239. },
  240. Body:{
  241. HostRoles:{
  242. stack_id: 'HDP-1.2.2',
  243. state: 'INSTALLED'
  244. }
  245. }
  246. }, 'PUT',
  247. function(requestId){
  248. if(!requestId){
  249. return;
  250. }
  251. console.log('Send request for UPGRADE successfully');
  252. if (App.testMode) {
  253. component.set('workStatus', App.HostComponentStatus.starting);
  254. setTimeout(function(){
  255. component.set('workStatus', App.HostComponentStatus.started);
  256. },App.testModeDelayForActions);
  257. } else {
  258. App.router.get('clusterController').loadUpdatedStatusDelayed(500);
  259. }
  260. // load data (if we need to show this background operations popup) from persist
  261. App.router.get('applicationController').dataLoading().done(function (initValue) {
  262. if (initValue) {
  263. App.router.get('backgroundOperationsController').showPopup();
  264. }
  265. });
  266. });
  267. });
  268. },
  269. /**
  270. * send command to server to stop selected host component
  271. * @param event
  272. */
  273. stopComponent: function (event) {
  274. var self = this;
  275. App.showConfirmationPopup(function() {
  276. var component = event.context;
  277. var context = Em.I18n.t('requestInfo.stopHostComponent')+ " " + component.get('displayName');
  278. self.sendStopComponentCommand(component, context);
  279. });
  280. },
  281. /**
  282. * PUTs a command to server to stop a component. If no
  283. * specific component is provided, all components are stopped.
  284. * @param component When <code>null</code> all components are stopped.
  285. * @param context Context under which this command is beign sent.
  286. */
  287. sendStopComponentCommand: function(component, context){
  288. var url = component !== null ?
  289. '/hosts/' + this.get('content.hostName') + '/host_components/' + component.get('componentName').toUpperCase() :
  290. '/hosts/' + this.get('content.hostName') + '/host_components?HostRoles/maintenance_state=OFF';
  291. var dataToSend = {
  292. RequestInfo : {
  293. "context" : context
  294. },
  295. Body:{
  296. HostRoles:{
  297. state: 'INSTALLED'
  298. }
  299. }
  300. };
  301. if (component === null) {
  302. var allComponents = this.get('content.hostComponents');
  303. var startable = [];
  304. allComponents.forEach(function (c) {
  305. if (c.get('passiveState') == 'OFF') {
  306. if (c.get('isMaster') || c.get('isSlave')) {
  307. startable.push(c.get('componentName'));
  308. }
  309. }
  310. });
  311. dataToSend.RequestInfo.query = "HostRoles/component_name.in(" + startable.join(',') + ")";
  312. }
  313. this.sendCommandToServer( url, dataToSend, 'PUT',
  314. function(requestId){
  315. if(!requestId){
  316. return;
  317. }
  318. console.log('Send request for STOPPING successfully');
  319. if (App.testMode) {
  320. if(component === null){
  321. var allComponents = this.get('content.hostComponents');
  322. allComponents.forEach(function(component){
  323. component.set('workStatus', App.HostComponentStatus.stopping);
  324. setTimeout(function(){
  325. component.set('workStatus', App.HostComponentStatus.stopped);
  326. },App.testModeDelayForActions);
  327. });
  328. } else {
  329. component.set('workStatus', App.HostComponentStatus.stopping);
  330. setTimeout(function(){
  331. component.set('workStatus', App.HostComponentStatus.stopped);
  332. },App.testModeDelayForActions);
  333. }
  334. } else {
  335. App.router.get('clusterController').loadUpdatedStatusDelayed(500);
  336. }
  337. // load data (if we need to show this background operations popup) from persist
  338. App.router.get('applicationController').dataLoading().done(function (initValue) {
  339. if (initValue) {
  340. App.router.get('backgroundOperationsController').showPopup();
  341. }
  342. });
  343. });
  344. },
  345. restartComponent: function(event) {
  346. var component = event.context;
  347. App.showConfirmationPopup(function(){
  348. batchUtils.restartHostComponents([component]);
  349. });
  350. },
  351. /**
  352. * send command to server to install selected host component
  353. * @param event
  354. */
  355. addComponent: function (event) {
  356. var self = this;
  357. var component = event.context;
  358. var componentName = component.get('componentName').toUpperCase().toString();
  359. var subComponentNames = component.get('subComponentNames');
  360. var displayName = component.get('displayName');
  361. var securityEnabled = App.router.get('mainAdminSecurityController').getUpdatedSecurityStatus();
  362. if (componentName === 'ZOOKEEPER_SERVER') {
  363. App.showConfirmationPopup(function() {
  364. self.primary(component);
  365. }, Em.I18n.t('hosts.host.addComponent.addZooKeeper'));
  366. }
  367. else {
  368. if (securityEnabled) {
  369. App.showConfirmationPopup(function() {
  370. self.primary(component);
  371. }, Em.I18n.t('hosts.host.addComponent.securityNote').format(componentName,self.get('content.hostName')));
  372. }
  373. else {
  374. var dn = displayName;
  375. if (subComponentNames !== null && subComponentNames.length > 0) {
  376. var dns = [];
  377. subComponentNames.forEach(function(scn){
  378. dns.push(App.format.role(scn));
  379. });
  380. dn += " ("+dns.join(", ")+")";
  381. }
  382. App.ModalPopup.show({
  383. primary: Em.I18n.t('yes'),
  384. secondary: Em.I18n.t('no'),
  385. header: Em.I18n.t('popup.confirmation.commonHeader'),
  386. addComponentMsg: function() {
  387. return Em.I18n.t('hosts.host.addComponent.msg').format(dn);
  388. }.property(),
  389. bodyClass: Ember.View.extend({
  390. templateName: require('templates/main/host/details/addComponentPopup')
  391. }),
  392. onPrimary: function () {
  393. this.hide();
  394. if (component.get('componentName') === 'CLIENTS') {
  395. // Clients component has many sub-components which
  396. // need to be installed.
  397. var scs = component.get('subComponentNames');
  398. scs.forEach(function (sc, index) {
  399. var c = Em.Object.create({
  400. displayName: App.format.role(sc),
  401. componentName: sc
  402. });
  403. self.primary(c, scs.length - index === 1);
  404. });
  405. } else {
  406. self.primary(component, true);
  407. }
  408. }
  409. });
  410. }
  411. }
  412. },
  413. primary: function(component, showPopup) {
  414. var self = this;
  415. var componentName = component.get('componentName').toUpperCase().toString();
  416. var displayName = component.get('displayName');
  417. self.sendCommandToServer('/hosts?Hosts/host_name=' + self.get('content.hostName'), {
  418. RequestInfo: {
  419. "context": Em.I18n.t('requestInfo.installHostComponent') + " " + displayName
  420. },
  421. Body: {
  422. host_components: [
  423. {
  424. HostRoles: {
  425. component_name: componentName
  426. }
  427. }
  428. ]
  429. }
  430. },
  431. 'POST',
  432. function (requestId) {
  433. console.log('Send request for ADDING NEW COMPONENT successfully');
  434. self.sendCommandToServer('/host_components?HostRoles/host_name=' + self.get('content.hostName') + '\&HostRoles/component_name=' + componentName + '\&HostRoles/state=INIT', {
  435. RequestInfo: {
  436. "context": Em.I18n.t('requestInfo.installNewHostComponent') + " " + displayName
  437. },
  438. Body: {
  439. HostRoles: {
  440. state: 'INSTALLED'
  441. }
  442. }
  443. },
  444. 'PUT',
  445. function (requestId) {
  446. if (!requestId) {
  447. return;
  448. }
  449. console.log('Send request for INSTALLING NEW COMPONENT successfully');
  450. if (App.testMode) {
  451. component.set('workStatus', App.HostComponentStatus.installing);
  452. setTimeout(function () {
  453. component.set('workStatus', App.HostComponentStatus.stopped);
  454. }, App.testModeDelayForActions);
  455. } else {
  456. App.router.get('clusterController').loadUpdatedStatusDelayed(500);
  457. }
  458. // load data (if we need to show this background operations popup) from persist
  459. App.router.get('applicationController').dataLoading().done(function (initValue) {
  460. if (initValue) {
  461. App.router.get('backgroundOperationsController').showPopup();
  462. }
  463. if (componentName === 'ZOOKEEPER_SERVER') {
  464. self.set('zkRequestId', requestId);
  465. self.addObserver('App.router.backgroundOperationsController.serviceTimestamp', self, self.checkZkConfigs);
  466. self.checkZkConfigs();
  467. }
  468. });
  469. });
  470. });
  471. },
  472. /**
  473. * Load tags
  474. */
  475. checkZkConfigs: function() {
  476. var bg = App.router.get('backgroundOperationsController.services').findProperty('id', this.get('zkRequestId'));
  477. if (!bg) return;
  478. if (!bg.get('isRunning')) {
  479. this.loadConfigs();
  480. }
  481. },
  482. loadConfigs: function() {
  483. this.removeObserver('App.router.backgroundOperationsController.serviceTimestamp', this, this.checkZkConfigs);
  484. App.ajax.send({
  485. name: 'config.tags',
  486. sender: this,
  487. success: 'loadConfigsSuccessCallback'
  488. });
  489. },
  490. /**
  491. * Load needed configs
  492. * @param data
  493. */
  494. loadConfigsSuccessCallback: function(data) {
  495. var urlParams = [];
  496. urlParams.push('(type=core-site&tag=' + data.Clusters.desired_configs['core-site'].tag + ')');
  497. if (App.Service.find().someProperty('serviceName', 'HBASE')) {
  498. urlParams.push('(type=hbase-site&tag=' + data.Clusters.desired_configs['hbase-site'].tag + ')');
  499. }
  500. if (App.Service.find().someProperty('serviceName', 'HIVE')) {
  501. urlParams.push('(type=webhcat-site&tag=' + data.Clusters.desired_configs['webhcat-site'].tag + ')');
  502. }
  503. if (App.Service.find().someProperty('serviceName', 'STORM')) {
  504. urlParams.push('(type=storm-site&tag=' + data.Clusters.desired_configs['storm-site'].tag + ')');
  505. }
  506. App.ajax.send({
  507. name: 'reassign.load_configs',
  508. sender: this,
  509. data: {
  510. urlParams: urlParams.join('|')
  511. },
  512. success: 'setNewZkConfigs'
  513. });
  514. },
  515. /**
  516. * Set new values for some configs (based on available ZooKeeper Servers)
  517. * @param data
  518. */
  519. setNewZkConfigs: function(data) {
  520. var configs = [];
  521. data.items.forEach(function (item) {
  522. configs[item.type] = item.properties;
  523. }, this);
  524. var zks = this.getZkServerHosts();
  525. var zks_with_port = '';
  526. zks.forEach(function(zk) {
  527. zks_with_port += zk + ':2181,';
  528. });
  529. zks_with_port = zks_with_port.slice(0,-1);
  530. if (App.get('isHaEnabled')) {
  531. configs['core-site']['ha.zookeeper.quorum'] = zks_with_port;
  532. }
  533. if (configs['hbase-site']) {
  534. configs['hbase-site']['hbase.zookeeper.quorum'] = zks.join(',');
  535. }
  536. if (configs['webhcat-site']) {
  537. configs['webhcat-site']['templeton.zookeeper.hosts'] = zks_with_port;
  538. }
  539. if (configs['storm-site']) {
  540. configs['storm-site']['storm.zookeeper.servers'] = JSON.stringify(zks).replace(/"/g, "'");
  541. }
  542. for (var site in configs) {
  543. if (!configs.hasOwnProperty(site)) continue;
  544. App.ajax.send({
  545. name: 'reassign.save_configs',
  546. sender: this,
  547. data: {
  548. siteName: site,
  549. properties: configs[site]
  550. }
  551. });
  552. }
  553. },
  554. /**
  555. * Is deleteHost action id fired
  556. */
  557. fromDeleteHost: false,
  558. getZkServerHosts: function() {
  559. var zks = App.HostComponent.find().filterProperty('componentName', 'ZOOKEEPER_SERVER').mapProperty('host.hostName');
  560. if (this.get('fromDeleteHost')) {
  561. this.set('fromDeleteHost', false);
  562. return zks.without(this.get('content.hostName'));
  563. }
  564. return zks;
  565. },
  566. /**
  567. * send command to server to install selected host component
  568. * @param event
  569. * @param context
  570. */
  571. installComponent: function (event, context) {
  572. var self = this;
  573. var component = event.context;
  574. var componentName = component.get('componentName').toUpperCase().toString();
  575. var displayName = component.get('displayName');
  576. App.ModalPopup.show({
  577. primary: Em.I18n.t('yes'),
  578. secondary: Em.I18n.t('no'),
  579. header: Em.I18n.t('popup.confirmation.commonHeader'),
  580. installComponentMessage: function(){
  581. return Em.I18n.t('hosts.host.installComponent.msg').format(displayName);
  582. }.property(),
  583. bodyClass: Ember.View.extend({
  584. templateName: require('templates/main/host/details/installComponentPopup')
  585. }),
  586. onPrimary: function () {
  587. this.hide();
  588. self.sendCommandToServer('/hosts/' + self.get('content.hostName') + '/host_components/' + component.get('componentName').toUpperCase(), {
  589. RequestInfo: {
  590. "context": Em.I18n.t('requestInfo.installHostComponent') + " " + displayName
  591. },
  592. Body: {
  593. HostRoles: {
  594. state: 'INSTALLED'
  595. }
  596. }
  597. },
  598. 'PUT',
  599. function (requestId) {
  600. if (!requestId) {
  601. return;
  602. }
  603. console.log('Send request for REINSTALL COMPONENT successfully');
  604. if (App.testMode) {
  605. component.set('workStatus', App.HostComponentStatus.installing);
  606. setTimeout(function () {
  607. component.set('workStatus', App.HostComponentStatus.stopped);
  608. }, App.testModeDelayForActions);
  609. } else {
  610. App.router.get('clusterController').loadUpdatedStatusDelayed(500);
  611. }
  612. // load data (if we need to show this background operations popup) from persist
  613. App.router.get('applicationController').dataLoading().done(function (initValue) {
  614. if (initValue) {
  615. App.router.get('backgroundOperationsController').showPopup();
  616. }
  617. });
  618. });
  619. }
  620. });
  621. },
  622. /**
  623. * send command to server to run decommission on DATANODE, TASKTRACKER, NODEMANAGER, REGIONSERVER
  624. * @param event
  625. */
  626. decommission: function(event){
  627. var self = this;
  628. App.showConfirmationPopup(function(){
  629. var component = event.context;
  630. var svcName = component.get('service.serviceName');
  631. var hostName = self.get('content.hostName');
  632. // HDFS service, decommission DataNode
  633. if (svcName === "HDFS") {
  634. self.doDecommission(hostName, svcName, "NAMENODE", "DATANODE");
  635. }
  636. // YARN service, decommission NodeManager
  637. if (svcName === "YARN") {
  638. self.doDecommission(hostName, svcName, "RESOURCEMANAGER", "NODEMANAGER");
  639. }
  640. // MAPREDUCE service, decommission TaskTracker
  641. if (svcName === "MAPREDUCE") {
  642. self.doDecommission(hostName, svcName, "JOBTRACKER", "TASKTRACKER");
  643. }
  644. // HBASE service, decommission RegionServer
  645. if (svcName === "HBASE") {
  646. self.doDecommissionRegionServer(hostName, svcName, "HBASE_MASTER", "HBASE_REGIONSERVER");
  647. }
  648. // load data (if we need to show this background operations popup) from persist
  649. App.router.get('applicationController').dataLoading().done(function (initValue) {
  650. if (initValue) {
  651. App.router.get('backgroundOperationsController').showPopup();
  652. }
  653. });
  654. });
  655. },
  656. /**
  657. * send command to server to run recommission on DATANODE, TASKTRACKER, NODEMANAGER
  658. * @param event
  659. */
  660. recommission: function(event){
  661. var self = this;
  662. App.showConfirmationPopup(function(){
  663. var component = event.context;
  664. var svcName = component.get('service.serviceName');
  665. var hostName = self.get('content.hostName');
  666. // HDFS service, Recommission datanode
  667. if (svcName === "HDFS") {
  668. self.doRecommissionAndStart(hostName, svcName, "NAMENODE", "DATANODE");
  669. }
  670. // YARN service, Recommission nodeManager
  671. if (svcName === "YARN") {
  672. self.doRecommissionAndStart(hostName, svcName, "RESOURCEMANAGER", "NODEMANAGER");
  673. }
  674. // MAPREDUCE service, Recommission taskTracker
  675. if (svcName === "MAPREDUCE") {
  676. self.doRecommissionAndRestart(hostName, svcName, "JOBTRACKER", "TASKTRACKER");
  677. }
  678. // HBASE service, Recommission RegionServer
  679. if (svcName === "HBASE") {
  680. self.doRecommissionAndStart(hostName, svcName, "HBASE_MASTER", "HBASE_REGIONSERVER");
  681. }
  682. // load data (if we need to show this background operations popup) from persist
  683. App.router.get('applicationController').dataLoading().done(function (initValue) {
  684. if (initValue) {
  685. App.router.get('backgroundOperationsController').showPopup();
  686. }
  687. });
  688. });
  689. },
  690. /**
  691. * Performs Decommission (for DN, TT and NM)
  692. */
  693. doDecommission: function(hostName, serviceName, componentName, slaveType){
  694. var contextNameString = 'hosts.host.' + slaveType.toLowerCase() + '.decommission';
  695. var context = Em.I18n.t(contextNameString);
  696. App.ajax.send({
  697. name: 'host.host_component.decommission_slave',
  698. sender: this,
  699. data: {
  700. context: context,
  701. command: 'DECOMMISSION',
  702. hostName: hostName,
  703. serviceName: serviceName ,
  704. componentName: componentName,
  705. slaveType: slaveType
  706. },
  707. success: 'decommissionSuccessCallback',
  708. error: 'decommissionErrorCallback'
  709. });
  710. },
  711. /**
  712. * Performs Decommission (for RegionServer)
  713. */
  714. doDecommissionRegionServer: function(hostNames, serviceName, componentName, slaveType){
  715. App.ajax.send({
  716. name: 'host.host_component.recommission_and_restart',
  717. sender: this,
  718. data: {
  719. intervalTimeSeconds: 1,
  720. tolerateSize : 0,
  721. batches:[
  722. {
  723. "order_id" : 1,
  724. "type" : "POST",
  725. "uri" : App.apiPrefix + "/clusters/" + App.get('clusterName') + "/requests",
  726. "RequestBodyInfo" : {
  727. "RequestInfo" : {
  728. "context" : Em.I18n.t('hosts.host.regionserver.decommission.batch1'),
  729. "command" : "DECOMMISSION",
  730. "service_name" : serviceName,
  731. "component_name" : componentName,
  732. "parameters" : {
  733. "slave_type": slaveType,
  734. "excluded_hosts": hostNames
  735. }
  736. }
  737. }
  738. },
  739. {
  740. "order_id": 2,
  741. "type": "PUT",
  742. "uri" : App.apiPrefix + "/clusters/" + App.get('clusterName') + "/host_components",
  743. "RequestBodyInfo" : {
  744. "RequestInfo" : {
  745. context: Em.I18n.t('hosts.host.regionserver.decommission.batch2'),
  746. query: 'HostRoles/component_name=' + slaveType + '&HostRoles/host_name.in(' + hostNames + ')&HostRoles/maintenance_state=OFF'
  747. },
  748. "Body": {
  749. HostRoles: {
  750. state: "INSTALLED"
  751. }
  752. }
  753. }
  754. },
  755. {
  756. "order_id" : 3,
  757. "type" : "POST",
  758. "uri" : App.apiPrefix + "/clusters/" + App.get('clusterName') + "/requests",
  759. "RequestBodyInfo" : {
  760. "RequestInfo" : {
  761. "context" : Em.I18n.t('hosts.host.regionserver.decommission.batch3'),
  762. "command" : "DECOMMISSION",
  763. "service_name" : serviceName,
  764. "component_name" : componentName,
  765. "parameters" : {
  766. "slave_type": slaveType,
  767. "excluded_hosts": hostNames,
  768. "mark_draining_only": "true"
  769. }
  770. }
  771. }
  772. }
  773. ]
  774. },
  775. success: 'decommissionSuccessCallback',
  776. error: 'decommissionErrorCallback'
  777. });
  778. },
  779. decommissionErrorCallback: function (request, ajaxOptions, error) {
  780. console.log('ERROR: '+ error);
  781. },
  782. /**
  783. * Success ajax response for Recommission/Decommission slaves
  784. * @param data
  785. * @param ajaxOptions
  786. */
  787. decommissionSuccessCallback: function(data, ajaxOptions) {
  788. if(data && (data.Requests || data.resources[0].RequestSchedule) ) {
  789. if (!App.testMode) {
  790. App.router.get('clusterController').loadUpdatedStatusDelayed(500);
  791. }
  792. // load data (if we need to show this background operations popup) from persist
  793. App.router.get('applicationController').dataLoading().done(function (initValue) {
  794. if (initValue) {
  795. App.router.get('backgroundOperationsController').showPopup();
  796. }
  797. });
  798. }
  799. else {
  800. console.log('cannot get request id from ', data);
  801. }
  802. },
  803. doRecommissionAndStart: function(hostNames, serviceName, componentName, slaveType){
  804. var contextNameString_1 = 'hosts.host.' + slaveType.toLowerCase() + '.recommission';
  805. var context_1 = Em.I18n.t(contextNameString_1);
  806. var contextNameString_2 = 'requestInfo.startHostComponent.' + slaveType.toLowerCase();
  807. var startContext = Em.I18n.t(contextNameString_2);
  808. App.ajax.send({
  809. name: 'host.host_component.recommission_and_restart',
  810. sender: this,
  811. data: {
  812. intervalTimeSeconds: 1,
  813. tolerateSize : 1,
  814. batches:[
  815. {
  816. "order_id" : 1,
  817. "type" : "POST",
  818. "uri" : App.apiPrefix + "/clusters/" + App.get('clusterName') + "/requests",
  819. "RequestBodyInfo" : {
  820. "RequestInfo" : {
  821. "context" : context_1,
  822. "command" : "DECOMMISSION",
  823. "service_name" : serviceName,
  824. "component_name" : componentName,
  825. "parameters" : {
  826. "slave_type": slaveType,
  827. "included_hosts": hostNames
  828. }
  829. }
  830. }
  831. },
  832. {
  833. "order_id": 2,
  834. "type": "PUT",
  835. "uri" : App.apiPrefix + "/clusters/" + App.get('clusterName') + "/host_components",
  836. "RequestBodyInfo" : {
  837. "RequestInfo" : {
  838. context: startContext,
  839. query: 'HostRoles/component_name=' + slaveType + '&HostRoles/host_name.in(' + hostNames + ')&HostRoles/maintenance_state=OFF'
  840. },
  841. "Body": {
  842. HostRoles: {
  843. state: "STARTED"
  844. }
  845. }
  846. }
  847. }
  848. ]
  849. },
  850. success: 'decommissionSuccessCallback',
  851. error: 'decommissionErrorCallback'
  852. });
  853. },
  854. doRecommissionAndRestart: function(hostNames, serviceName, componentName, slaveType){
  855. var contextNameString_1 = 'hosts.host.' + slaveType.toLowerCase() + '.recommission';
  856. var context_1 = Em.I18n.t(contextNameString_1);
  857. var contextNameString_2 = 'hosts.host.' + slaveType.toLowerCase() + '.restart';
  858. var context_2 = Em.I18n.t(contextNameString_2);
  859. App.ajax.send({
  860. name: 'host.host_component.recommission_and_restart',
  861. sender: this,
  862. data: {
  863. intervalTimeSeconds: 1,
  864. tolerateSize : 1,
  865. batches:[
  866. {
  867. "order_id" : 1,
  868. "type" : "POST",
  869. "uri" : App.apiPrefix + "/clusters/" + App.get('clusterName') + "/requests",
  870. "RequestBodyInfo" : {
  871. "RequestInfo" : {
  872. "context" : context_1,
  873. "command" : "DECOMMISSION",
  874. "service_name" : serviceName,
  875. "component_name" : componentName,
  876. "parameters" : {
  877. "slave_type": slaveType,
  878. "included_hosts": hostNames
  879. }
  880. }
  881. }
  882. },
  883. {
  884. "order_id" : 2,
  885. "type" : "POST",
  886. "uri" : App.apiPrefix + "/clusters/" + App.get('clusterName') + "/requests",
  887. "RequestBodyInfo" : {
  888. "RequestInfo" : {
  889. "context" : context_2,
  890. "command" : "RESTART",
  891. "service_name" : serviceName,
  892. "component_name" : slaveType,
  893. "hosts" : hostNames
  894. }
  895. }
  896. }
  897. ]
  898. },
  899. success: 'decommissionSuccessCallback',
  900. error: 'decommissionErrorCallback'
  901. });
  902. },
  903. doAction: function(option) {
  904. switch (option.context.action) {
  905. case "deleteHost":
  906. this.validateAndDeleteHost();
  907. break;
  908. case "startAllComponents":
  909. if (!this.get('content.isNotHeartBeating')) this.doStartAllComponents();
  910. break;
  911. case "stopAllComponents":
  912. if (!this.get('content.isNotHeartBeating')) this.doStopAllComponents();
  913. break;
  914. case "restartAllComponents":
  915. if (!this.get('content.isNotHeartBeating')) this.doRestartAllComponents();
  916. break;
  917. case "onOffPassiveModeForHost":
  918. this.onOffPassiveModeForHost(option.context);
  919. break;
  920. default:
  921. break;
  922. }
  923. },
  924. onOffPassiveModeForHost: function(context) {
  925. var state = context.active ? 'ON' : 'OFF';
  926. var self = this;
  927. var message = context.label + ' for host';
  928. App.showConfirmationPopup(function() {
  929. self.hostPassiveModeRequest(state, message)
  930. },
  931. Em.I18n.t('hosts.passiveMode.popup').format(context.active ? 'On' : 'Off',this.get('content.hostName'))
  932. );
  933. },
  934. hostPassiveModeRequest: function(state,message) {
  935. App.ajax.send({
  936. name: 'bulk_request.hosts.passive_state',
  937. sender: this,
  938. data: {
  939. hostNames: this.get('content.hostName'),
  940. passive_state: state,
  941. requestInfo: message
  942. },
  943. success: 'updateHost'
  944. });
  945. },
  946. updateHost: function(data, opt, params) {
  947. this.set('content.passiveState', params.passive_state);
  948. App.router.get('clusterController').loadUpdatedStatus(function(){});
  949. },
  950. doStartAllComponents: function() {
  951. var self = this;
  952. var components = this.get('content.hostComponents');
  953. var componentsLength = components == null ? 0 : components.get('length');
  954. if (componentsLength > 0) {
  955. App.showConfirmationPopup(function() {
  956. self.sendStartComponentCommand(null,
  957. Em.I18n.t('hosts.host.maintainance.startAllComponents.context'));
  958. });
  959. }
  960. },
  961. doStopAllComponents: function() {
  962. var self = this;
  963. var components = this.get('content.hostComponents');
  964. var componentsLength = components == null ? 0 : components.get('length');
  965. if (componentsLength > 0) {
  966. App.showConfirmationPopup(function() {
  967. self.sendStopComponentCommand(null,
  968. Em.I18n.t('hosts.host.maintainance.stopAllComponents.context'));
  969. });
  970. }
  971. },
  972. doRestartAllComponents: function() {
  973. var components = this.get('content.hostComponents').filterProperty('passiveState','OFF');
  974. var componentsLength = components == null ? 0 : components.get('length');
  975. if (componentsLength > 0) {
  976. App.showConfirmationPopup(function() {
  977. batchUtils.restartHostComponents(components);
  978. });
  979. }
  980. },
  981. /**
  982. * Deletion of hosts not supported for this version
  983. */
  984. validateAndDeleteHost: function () {
  985. if (!App.supports.deleteHost) {
  986. return;
  987. }
  988. var stoppedStates = [App.HostComponentStatus.stopped,
  989. App.HostComponentStatus.install_failed,
  990. App.HostComponentStatus.upgrade_failed,
  991. App.HostComponentStatus.unknown];
  992. var masterComponents = [];
  993. var runningComponents = [];
  994. var unknownComponents = [];
  995. var nonDeletableComponents = [];
  996. var lastComponents = [];
  997. var componentsOnHost = this.get('content.hostComponents');
  998. var allComponents = App.HostComponent.find();
  999. var zkServerInstalled = false;
  1000. if (componentsOnHost && componentsOnHost.get('length') > 0) {
  1001. componentsOnHost.forEach(function (cInstance) {
  1002. if (cInstance.get('componentName') === 'ZOOKEEPER_SERVER') {
  1003. zkServerInstalled = true;
  1004. }
  1005. if (allComponents.filterProperty('componentName', cInstance.get('componentName')).get('length') === 1) {
  1006. lastComponents.push(cInstance.get('displayName'));
  1007. }
  1008. var workStatus = cInstance.get('workStatus');
  1009. if (cInstance.get('isMaster') && !cInstance.get('isDeletable')) {
  1010. masterComponents.push(cInstance.get('displayName'));
  1011. }
  1012. if (stoppedStates.indexOf(workStatus) < 0) {
  1013. runningComponents.push(cInstance.get('displayName'));
  1014. }
  1015. if (!cInstance.get('isDeletable')) {
  1016. nonDeletableComponents.push(cInstance.get('displayName'));
  1017. }
  1018. if (workStatus === App.HostComponentStatus.unknown) {
  1019. unknownComponents.push(cInstance.get('displayName'));
  1020. }
  1021. });
  1022. }
  1023. if (masterComponents.length > 0) {
  1024. this.raiseDeleteComponentsError(masterComponents, 'masterList');
  1025. return;
  1026. } else if (nonDeletableComponents.length > 0) {
  1027. this.raiseDeleteComponentsError(nonDeletableComponents, 'nonDeletableList');
  1028. return;
  1029. } else if (runningComponents.length > 0) {
  1030. this.raiseDeleteComponentsError(runningComponents, 'runningList');
  1031. return;
  1032. }
  1033. if (zkServerInstalled) {
  1034. var self = this;
  1035. App.showConfirmationPopup(function() {
  1036. self._doDeleteHost(unknownComponents, lastComponents);
  1037. }, Em.I18n.t('hosts.host.addComponent.deleteHostWithZooKeeper'));
  1038. }
  1039. else {
  1040. this._doDeleteHost(unknownComponents, lastComponents);
  1041. }
  1042. },
  1043. raiseDeleteComponentsError: function (components, type) {
  1044. App.ModalPopup.show({
  1045. header: Em.I18n.t('hosts.cant.do.popup.title'),
  1046. type: type,
  1047. showBodyEnd: function() {
  1048. return this.get('type') === 'runningList' || this.get('type') === 'masterList';
  1049. }.property(),
  1050. components: components,
  1051. componentsStr: function() {
  1052. return this.get('components').join(", ");
  1053. }.property(),
  1054. componentsBody: function() {
  1055. return Em.I18n.t('hosts.cant.do.popup.'+type+'.body').format(this.get('components').length);
  1056. }.property(),
  1057. componentsBodyEnd: function() {
  1058. if (this.get('showBodyEnd')) {
  1059. return Em.I18n.t('hosts.cant.do.popup.'+type+'.body.end');
  1060. }
  1061. return '';
  1062. }.property(),
  1063. bodyClass: Em.View.extend({
  1064. templateName: require('templates/main/host/details/raiseDeleteComponentErrorPopup')
  1065. }),
  1066. secondary: null
  1067. })
  1068. },
  1069. /**
  1070. * show confirmation popup to delete host
  1071. */
  1072. _doDeleteHost: function(unknownComponents,lastComponents) {
  1073. var self = this;
  1074. App.ModalPopup.show({
  1075. header: Em.I18n.t('hosts.delete.popup.title'),
  1076. deletePopupBody: function() {
  1077. return Em.I18n.t('hosts.delete.popup.body').format(self.get('content.publicHostName'));
  1078. }.property(),
  1079. lastComponent: function() {
  1080. if (lastComponents && lastComponents.length) {
  1081. this.set('enablePrimary',false);
  1082. return true;
  1083. } else {
  1084. this.set('enablePrimary',true);
  1085. return false;
  1086. }
  1087. }.property(),
  1088. enablePrimary: false,
  1089. lastComponentError: Em.View.extend({
  1090. template: Ember.Handlebars.compile(Em.I18n.t('hosts.delete.popup.body.msg4').format(lastComponents))
  1091. }),
  1092. unknownComponents: function() {
  1093. if (unknownComponents && unknownComponents.length) {
  1094. return unknownComponents.join(", ");
  1095. }
  1096. return '';
  1097. }.property(),
  1098. bodyClass: Em.View.extend({
  1099. templateName: require('templates/main/host/details/doDeleteHostPopup')
  1100. }),
  1101. onPrimary: function() {
  1102. if (!this.get('enablePrimary')) return;
  1103. self.set('fromDeleteHost', true);
  1104. var allComponents = self.get('content.hostComponents');
  1105. var deleteError = null;
  1106. allComponents.forEach(function(component){
  1107. if (!deleteError) {
  1108. deleteError = self._doDeleteHostComponent(component);
  1109. }
  1110. });
  1111. if (!deleteError) {
  1112. App.ajax.send({
  1113. name: 'host.delete',
  1114. sender: this,
  1115. data: {
  1116. hostName: self.get('content.hostName')
  1117. },
  1118. success: 'deleteHostSuccessCallback',
  1119. error: 'deleteHostErrorCallback'
  1120. });
  1121. }
  1122. else {
  1123. this.hide();
  1124. deleteError.xhr.responseText = "{\"message\": \"" + deleteError.xhr.statusText + "\"}";
  1125. App.ajax.defaultErrorHandler(deleteError.xhr, deleteError.url, deleteError.method, deleteError.xhr.status);
  1126. }
  1127. },
  1128. deleteHostSuccessCallback: function(data) {
  1129. var dialogSelf = this;
  1130. App.router.get('updateController').updateHost(function(){
  1131. self.loadConfigs();
  1132. dialogSelf.hide();
  1133. App.router.transitionTo('hosts.index');
  1134. });
  1135. },
  1136. deleteHostErrorCallback: function (xhr, textStatus, errorThrown, opt) {
  1137. console.log('Error deleting host.');
  1138. console.log(textStatus);
  1139. console.log(errorThrown);
  1140. xhr.responseText = "{\"message\": \"" + xhr.statusText + "\"}";
  1141. self.loadConfigs();
  1142. this.hide();
  1143. App.ajax.defaultErrorHandler(xhr, opt.url, 'DELETE', xhr.status);
  1144. }
  1145. })
  1146. },
  1147. restartAllStaleConfigComponents: function() {
  1148. var staleComponents = this.get('content.componentsWithStaleConfigs');
  1149. batchUtils.restartHostComponents(staleComponents);
  1150. },
  1151. /**
  1152. * open Reassign Master Wizard with selected component
  1153. * @param event
  1154. */
  1155. moveComponent: function (event) {
  1156. App.showConfirmationPopup(function() {
  1157. var component = event.context;
  1158. var reassignMasterController = App.router.get('reassignMasterController');
  1159. reassignMasterController.saveComponentToReassign(component);
  1160. reassignMasterController.getSecurityStatus();
  1161. reassignMasterController.setCurrentStep('1');
  1162. App.router.transitionTo('reassign');
  1163. });
  1164. },
  1165. turnOnOffPassiveConfirmation: function(event){
  1166. var self = this;
  1167. var component = event.context;
  1168. var state, onOff, message;
  1169. if (component.get("passiveState") == "ON") {
  1170. onOff = "Off";
  1171. state = "OFF";
  1172. message = Em.I18n.t('passiveState.turnOffFor').format(component.get('displayName'));
  1173. } else {
  1174. onOff = "On";
  1175. state = "ON";
  1176. message = Em.I18n.t('passiveState.turnOnFor').format(component.get('displayName'));
  1177. }
  1178. App.showConfirmationPopup(function() {
  1179. self.turnOnOffPassive(state, component, message)
  1180. },
  1181. Em.I18n.t('hosts.passiveMode.popup').format(onOff,component.get('displayName'))
  1182. );
  1183. },
  1184. turnOnOffPassive: function(state,component,message) {
  1185. var hostName = this.get('content.hostName');
  1186. App.ajax.send({
  1187. name: 'host_component.passive',
  1188. sender: this,
  1189. data: {
  1190. component: component,
  1191. hostName: hostName,
  1192. componentName: component.get('componentName'),
  1193. passive_state: state,
  1194. requestInfo: message
  1195. },
  1196. success: 'updateComponentPassiveState'
  1197. });
  1198. },
  1199. updateComponentPassiveState: function(data, opt, params) {
  1200. params.component.set('passiveState',params.passive_state);
  1201. },
  1202. /**
  1203. * Restart clients host components to apply config changes
  1204. */
  1205. refreshConfigs: function(event) {
  1206. var components = event.context.filter(function(component) {
  1207. return component.get('staleConfigs');
  1208. });
  1209. if (components.get('length') > 0) {
  1210. App.showConfirmationPopup(function() {
  1211. batchUtils.restartHostComponents(components);
  1212. });
  1213. }
  1214. }
  1215. });