details.js 35 KB

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