details.js 36 KB

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