details.js 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069
  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. var reassignMasterController = App.router.get('reassignMasterController');
  1005. reassignMasterController.saveComponentToReassign(component);
  1006. reassignMasterController.getSecurityStatus();
  1007. reassignMasterController.setCurrentStep('1');
  1008. App.router.transitionTo('services.reassign');
  1009. });
  1010. }
  1011. });