step4.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  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.MainAdminSecurityAddStep4Controller = App.MainAdminSecurityProgressController.extend({
  20. name: 'mainAdminSecurityAddStep4Controller',
  21. serviceUsersBinding: 'App.router.mainAdminSecurityController.serviceUsers',
  22. /**
  23. * component configs which should be added to global
  24. */
  25. componentsConfig: [
  26. {
  27. serviceName: 'OOZIE',
  28. componentName: 'OOZIE_SERVER',
  29. configName: 'oozieserver_host'
  30. },
  31. {
  32. serviceName: 'HIVE',
  33. componentName: 'HIVE_METASTORE',
  34. configName: 'hivemetastore_host'
  35. },
  36. {
  37. serviceName: 'WEBHCAT',
  38. componentName: 'WEBHCAT_SERVER',
  39. configName: 'webhcat_server'
  40. }
  41. ],
  42. /**
  43. * mock users used in testMode
  44. */
  45. testModeUsers: [
  46. {
  47. name: 'hdfs_user',
  48. value: 'hdfs'
  49. },
  50. {
  51. name: 'mapred_user',
  52. value: 'mapred'
  53. },
  54. {
  55. name: 'hbase_user',
  56. value: 'hbase'
  57. },
  58. {
  59. name: 'hive_user',
  60. value: 'hive'
  61. }
  62. ],
  63. /**
  64. * security configs, which values should be modified after APPLY CONFIGURATIONS stage
  65. */
  66. secureConfigs: [
  67. {
  68. name: 'nagios_principal_name',
  69. serviceName: 'NAGIOS'
  70. },
  71. {
  72. name: 'zookeeper_principal_name',
  73. serviceName: 'ZOOKEEPER'
  74. },
  75. {
  76. name: 'storm_principal_name',
  77. serviceName: 'STORM'
  78. }
  79. ],
  80. secureServices: function() {
  81. return this.get('content.services');
  82. }.property('content.services'),
  83. isBackBtnDisabled: function () {
  84. return !this.get('commands').someProperty('isError');
  85. }.property('commands.@each.isCompleted'),
  86. isSecurityApplied: function () {
  87. return this.get('commands').someProperty('name', 'START_SERVICES') && this.get('commands').findProperty('name', 'START_SERVICES').get('isSuccess');
  88. }.property('commands.@each.isCompleted'),
  89. /**
  90. * control disabled property of completion button
  91. */
  92. enableSubmit: function () {
  93. var addSecurityController = App.router.get('addSecurityController');
  94. if (this.get('commands').someProperty('isError') || this.get('commands').everyProperty('isSuccess')) {
  95. this.set('isSubmitDisabled', false);
  96. if (this.get('commands').someProperty('isError')) {
  97. addSecurityController.setStepsEnable();
  98. }
  99. } else {
  100. this.set('isSubmitDisabled', true);
  101. addSecurityController.setLowerStepsDisable(4);
  102. }
  103. }.observes('commands.@each.isCompleted'),
  104. /**
  105. * clear step info
  106. */
  107. clearStep: function () {
  108. this.set('commands', []);
  109. this.set('isSubmitDisabled', true);
  110. this.get('serviceConfigTags').clear();
  111. },
  112. loadCommands: function () {
  113. this._super();
  114. // no need to remove ATS component if YARN and ATS are not installed
  115. if (this.get('secureServices').findProperty('serviceName', 'YARN') && App.Service.find('YARN').get('hostComponents').someProperty('componentName', 'APP_TIMELINE_SERVER')) {
  116. this.get('commands').splice(2, 0, App.Poll.create({name: 'DELETE_ATS', label: Em.I18n.translations['admin.addSecurity.apply.delete.ats'], isPolling: false}));
  117. }
  118. },
  119. /**
  120. * load step info
  121. */
  122. loadStep: function () {
  123. this.clearStep();
  124. this.prepareSecureConfigs();
  125. if (!this.resumeSavedCommands()) {
  126. this.loadCommands();
  127. this.addInfoToCommands();
  128. this.syncStopServicesOperation();
  129. this.addObserverToCommands();
  130. this.moveToNextCommand();
  131. }
  132. },
  133. /**
  134. * synchronize "STOP_SERVICES" operation from BO with command of step
  135. * @return {Boolean}
  136. */
  137. syncStopServicesOperation: function () {
  138. var runningOperations = App.router.get('backgroundOperationsController.services').filterProperty('isRunning');
  139. var stopAllOperation = runningOperations.findProperty('name', 'Stop All Services');
  140. var stopCommand = this.get('commands').findProperty('name', 'STOP_SERVICES');
  141. if (stopCommand && stopAllOperation) {
  142. stopCommand.set('requestId', stopAllOperation.get('id'));
  143. return true;
  144. }
  145. return false;
  146. },
  147. /**
  148. * resume previously saved commands
  149. * @return {Boolean}
  150. */
  151. resumeSavedCommands: function () {
  152. var commands = App.db.getSecurityDeployCommands();
  153. if (Em.isNone(commands) || commands.length === 0) return false;
  154. commands.forEach(function (_command, index) {
  155. commands[index] = App.Poll.create(_command);
  156. }, this);
  157. if (commands.someProperty('isError')) {
  158. this.get('commands').pushObjects(commands);
  159. this.addObserverToCommands();
  160. return true;
  161. } else if (commands.filterProperty('isStarted').someProperty('isCompleted', false)) {
  162. var runningCommand = commands.filterProperty('isStarted').findProperty('isCompleted', false);
  163. runningCommand.set('isStarted', false);
  164. this.get('commands').pushObjects(commands);
  165. } else {
  166. this.get('commands').pushObjects(commands);
  167. }
  168. this.addObserverToCommands();
  169. this.moveToNextCommand();
  170. return true;
  171. },
  172. /**
  173. * load configs from UI side
  174. * @return {Array}
  175. */
  176. loadUiSideConfigs: function () {
  177. var uiConfig = [];
  178. var configs = this.get('secureMapping').filterProperty('foreignKey', null);
  179. configs.forEach(function (_config) {
  180. var value = _config.value;
  181. if (_config.hasOwnProperty('dependedServiceName')) {
  182. value = this.checkServiceForConfigValue(value, _config.dependedServiceName);
  183. }
  184. value = this.getGlobConfigValue(_config.templateName, value);
  185. uiConfig.push({
  186. "id": "site property",
  187. "name": _config.name,
  188. "value": value,
  189. "filename": _config.filename
  190. });
  191. }, this);
  192. var dependentConfig = this.get('secureMapping').filterProperty('foreignKey');
  193. dependentConfig.forEach(function (_config) {
  194. if (App.Service.find().mapProperty('serviceName').contains(_config.serviceName)) {
  195. this.setConfigValue(_config);
  196. this.formatConfigName(uiConfig, _config);
  197. uiConfig.push({
  198. "id": "site property",
  199. "name": _config._name || _config.name,
  200. "value": _config.value,
  201. "filename": _config.filename
  202. });
  203. }
  204. }, this);
  205. return uiConfig;
  206. },
  207. /**
  208. * erase template rules from config value if service is not loaded
  209. * @param value
  210. * @param services
  211. * @return {*}
  212. */
  213. checkServiceForConfigValue: function (value, services) {
  214. services.forEach(function (_service) {
  215. if (!App.Service.find(_service.name).get('isLoaded')) {
  216. value = value.replace(_service.replace, '');
  217. }
  218. }, this);
  219. return value;
  220. },
  221. /**
  222. * Set all site property that are derived from other puppet-variable
  223. * @param templateName
  224. * @param expression
  225. * @return {String|null}
  226. */
  227. getGlobConfigValue: function (templateName, expression) {
  228. var express = expression.match(/<(.*?)>/g);
  229. var value = expression;
  230. if (Em.isNone(express)) return expression;
  231. express.forEach(function (_express) {
  232. var index = parseInt(_express.match(/\[([\d]*)(?=\])/)[1]);
  233. var globalConfig = this.get('globalProperties').findProperty('name', templateName[index]);
  234. if (!!value) {
  235. value = (globalConfig) ? value.replace(_express, globalConfig.value) : null;
  236. }
  237. }, this);
  238. return value;
  239. },
  240. /**
  241. * format name of config values of global configs which match foreignKey
  242. * @param uiConfig
  243. * @param config
  244. * @return {Boolean}
  245. */
  246. formatConfigName: function (uiConfig, config) {
  247. if (Em.isNone(config.value)) return false;
  248. var fkValue = config.name.match(/<(foreignKey.*?)>/g);
  249. if (fkValue) {
  250. fkValue.forEach(function (_fkValue) {
  251. var index = parseInt(_fkValue.match(/\[([\d]*)(?=\])/)[1]);
  252. var globalValue;
  253. if (uiConfig.someProperty('name', config.foreignKey[index])) {
  254. globalValue = uiConfig.findProperty('name', config.foreignKey[index]).value;
  255. config._name = config.name.replace(_fkValue, globalValue);
  256. } else if (this.get('globalProperties').someProperty('name', config.foreignKey[index])) {
  257. globalValue = this.get('globalProperties').findProperty('name', config.foreignKey[index]).value;
  258. config._name = config.name.replace(_fkValue, globalValue);
  259. }
  260. }, this);
  261. return true;
  262. }
  263. return false;
  264. },
  265. /**
  266. * Set config value with values of global configs which match template
  267. * @param config
  268. * @return {Boolean}
  269. */
  270. setConfigValue: function (config) {
  271. if (Em.isNone(config.value)) return false;
  272. //For properties in the configMapping file having foreignKey and templateName properties.
  273. var templateValue = config.value.match(/<(templateName.*?)>/g);
  274. if (templateValue) {
  275. templateValue.forEach(function (_value) {
  276. var index = parseInt(_value.match(/\[([\d]*)(?=\])/)[1]);
  277. var globValue = this.get('globalProperties').findProperty('name', config.templateName[index]);
  278. config.value = (globValue) ? config.value.replace(_value, globValue.value) : null;
  279. }, this);
  280. return true;
  281. }
  282. return false;
  283. },
  284. /**
  285. * prepare secure configs
  286. */
  287. prepareSecureConfigs: function () {
  288. this.loadGlobals();
  289. var storedConfigs = this.get('content.serviceConfigProperties').filterProperty('id', 'site property');
  290. var uiConfigs = this.loadUiSideConfigs();
  291. this.set('configs', storedConfigs.concat(uiConfigs));
  292. },
  293. /**
  294. * load global configs
  295. */
  296. loadGlobals: function () {
  297. var globals = this.get('content.serviceConfigProperties').filterProperty('id', 'puppet var');
  298. this.set('globalProperties', globals);
  299. this.loadStaticGlobal(); //Hack for properties which are declared in global_properties.js and not able to retrieve values declared in secure_properties.js
  300. this.loadUsersToGlobal();
  301. this.loadHostNamesToGlobal();
  302. this.loadPrimaryNamesToGlobals();
  303. },
  304. /**
  305. * push users to global configs
  306. */
  307. loadUsersToGlobal: function () {
  308. if (!this.get('serviceUsers').length) {
  309. this.loadUsersFromServer();
  310. }
  311. App.router.get('mainAdminSecurityController.serviceUsers').forEach(function (_user) {
  312. this.get('globalProperties').pushObject(_user);
  313. }, this);
  314. },
  315. /**
  316. * add component config that contain host name as value
  317. * @param serviceName
  318. * @param componentName
  319. * @param configName
  320. * @return {Boolean}
  321. */
  322. addHostConfig: function(serviceName, componentName, configName) {
  323. var service = App.Service.find(serviceName);
  324. var isServiceSecure = this.get('secureServices').someProperty('serviceName', serviceName);
  325. if (service.get('isLoaded') && isServiceSecure) {
  326. var hostComponent = service.get('hostComponents').findProperty('componentName', componentName);
  327. if (hostComponent) {
  328. var hostName = hostComponent.get('hostName');
  329. this.get('globalProperties').push({
  330. id: 'puppet var',
  331. name: configName,
  332. value: hostName
  333. });
  334. return true;
  335. }
  336. }
  337. return false;
  338. },
  339. /**
  340. * add hosts' names to global configs
  341. */
  342. loadHostNamesToGlobal: function () {
  343. var componentsConfig = this.get('componentsConfig');
  344. componentsConfig.forEach(function (host) {
  345. this.addHostConfig(host.serviceName, host.componentName, host.configName);
  346. }, this);
  347. },
  348. /**
  349. * load static global
  350. */
  351. loadStaticGlobal: function () {
  352. this.get('globalProperties').forEach(function (_property) {
  353. switch (_property.name) {
  354. case 'security_enabled':
  355. _property.value = 'true';
  356. break;
  357. }
  358. }, this);
  359. },
  360. /**
  361. * add principals to global properties
  362. */
  363. loadPrimaryNamesToGlobals: function () {
  364. var principalProperties = this.getPrincipalNames();
  365. principalProperties.forEach(function (_principalProperty) {
  366. var name = _principalProperty.name.replace('principal', 'primary');
  367. var value = _principalProperty.value.split('/')[0];
  368. this.get('globalProperties').push({name: name, value: value});
  369. }, this);
  370. },
  371. /**
  372. * gather and return global properties with "principal_name"
  373. * @return {Array}
  374. */
  375. getPrincipalNames: function () {
  376. var principalNames = [];
  377. this.get('globalProperties').forEach(function (_globalProperty) {
  378. if (/principal_name?$/.test(_globalProperty.name)) {
  379. principalNames.push(_globalProperty);
  380. }
  381. }, this);
  382. this.get('secureProperties').forEach(function (_secureProperty) {
  383. if (/principal_name?$/.test(_secureProperty.name)) {
  384. var principalName = principalNames.findProperty('name', _secureProperty.name);
  385. if (!principalName) {
  386. _secureProperty.value = _secureProperty.defaultValue;
  387. principalNames.push(_secureProperty);
  388. }
  389. }
  390. }, this);
  391. return principalNames;
  392. },
  393. /**
  394. * load users from server
  395. */
  396. loadUsersFromServer: function () {
  397. if (App.testMode) {
  398. var serviceUsers = this.get('serviceUsers');
  399. this.get('testModeUsers').forEach(function (user) {
  400. user.id = 'puppet var';
  401. serviceUsers.push(user);
  402. }, this);
  403. } else {
  404. App.router.set('mainAdminSecurityController.serviceUsers', App.db.getSecureUserInfo());
  405. }
  406. },
  407. /**
  408. * manage secure configs
  409. * @return {Boolean}
  410. */
  411. manageSecureConfigs: function () {
  412. var serviceConfigTags = this.get('serviceConfigTags');
  413. var secureConfigs = this.get('secureConfigs');
  414. var siteProperties = this.get('configs').filterProperty('id', 'site property');
  415. var globalProperties = this.get('globalProperties');
  416. if (serviceConfigTags) {
  417. serviceConfigTags.forEach(function (_serviceConfigTags) {
  418. _serviceConfigTags.newTagName = 'version' + (new Date).getTime();
  419. if (_serviceConfigTags.siteName === 'global') {
  420. secureConfigs.forEach(function (config) {
  421. this.setPrincipalValue(config.serviceName, config.name);
  422. }, this);
  423. globalProperties.forEach(function (_globalProperty) {
  424. if (!/_hosts?$/.test(_globalProperty.name)) {
  425. _serviceConfigTags.configs[_globalProperty.name] = _globalProperty.value;
  426. }
  427. }, this);
  428. } else {
  429. siteProperties.filterProperty('filename', _serviceConfigTags.siteName + '.xml').forEach(function (_config) {
  430. _serviceConfigTags.configs[_config.name] = _config.value;
  431. }, this);
  432. }
  433. }, this);
  434. return true;
  435. } else {
  436. var command = this.get('commands').findProperty('name', 'APPLY_CONFIGURATIONS');
  437. command.set('isSuccess', false);
  438. command.set('isError', true);
  439. this.onJsError();
  440. return false;
  441. }
  442. },
  443. /**
  444. * set value of principal property
  445. * @param serviceName
  446. * @param principalName
  447. * @return {Boolean}
  448. */
  449. setPrincipalValue: function (serviceName, principalName) {
  450. var globalProperties = this.get('globalProperties');
  451. var realmName = globalProperties.findProperty('name', 'kerberos_domain');
  452. if (this.get('secureServices').someProperty('serviceName', serviceName)) {
  453. var principalProperty = globalProperties.findProperty('name', principalName);
  454. principalProperty.value = principalProperty.value + '@' + realmName.value;
  455. return true;
  456. }
  457. return false;
  458. },
  459. /**
  460. * send DELETE command to server to delete component
  461. * @param componentName
  462. * @param hostName
  463. */
  464. deleteComponents: function(componentName, hostName) {
  465. App.ajax.send({
  466. name: 'common.delete.host_component',
  467. sender: this,
  468. data: {
  469. componentName: componentName,
  470. hostName: hostName
  471. },
  472. success: 'onDeleteComplete',
  473. error: 'onDeleteError'
  474. });
  475. },
  476. /**
  477. * callback on successful deletion of component
  478. */
  479. onDeleteComplete: function () {
  480. var deleteAtsCommand = this.get('commands').findProperty('name', 'DELETE_ATS');
  481. console.warn('APP_TIMELINE_SERVER doesn\'t support security mode. It has been removed from YARN service ');
  482. deleteAtsCommand.set('isError', false);
  483. deleteAtsCommand.set('isSuccess', true);
  484. },
  485. /**
  486. * callback on failed deletion of component
  487. */
  488. onDeleteError: function () {
  489. console.warn('Error: Can\'t delete APP_TIMELINE_SERVER');
  490. },
  491. /**
  492. * show popup when js error occurred
  493. */
  494. onJsError: function () {
  495. App.ModalPopup.show({
  496. header: Em.I18n.t('common.error'),
  497. secondary: false,
  498. bodyClass: Ember.View.extend({
  499. template: Ember.Handlebars.compile('<p>{{t admin.security.apply.configuration.error}}</p>')
  500. })
  501. });
  502. }
  503. });