service_config.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. var App = require('app');
  19. var validator = require('utils/validator');
  20. App.ConfigProperties = Ember.ArrayProxy.extend({
  21. content: require('data/config_properties').configProperties
  22. });
  23. App.ServiceConfig = Ember.Object.extend({
  24. serviceName: '',
  25. configCategories: [],
  26. configs: null,
  27. errorCount: function () {
  28. var masterErrors = this.get('configs').filterProperty('isValid', false).filterProperty('isVisible', true).get('length');
  29. var slaveErrors = 0;
  30. this.get('configCategories').forEach(function(_category){
  31. slaveErrors += _category.get('slaveErrorCount');
  32. },this);
  33. return masterErrors + slaveErrors;
  34. }.property('configs.@each.isValid', 'configs.@each.isVisible', 'configCategories.@each.slaveErrorCount')
  35. });
  36. App.ServiceConfigCategory = Ember.Object.extend({
  37. name: null,
  38. slaveConfigs: null,
  39. primaryName: function () {
  40. switch (this.get('name')) {
  41. case 'DataNode':
  42. return 'DATANODE';
  43. break;
  44. case 'TaskTracker':
  45. return 'TASKTRACKER';
  46. break;
  47. case 'RegionServer':
  48. return 'HBASE_REGIONSERVER';
  49. }
  50. }.property('name'),
  51. isForMasterComponent: function () {
  52. var masterServices = [ 'NameNode', 'SNameNode', 'JobTracker', 'HBase Master', 'Oozie Master',
  53. 'Hive Metastore', 'WebHCat Server', 'ZooKeeper Server', 'Nagios', 'Ganglia' ];
  54. return (masterServices.contains(this.get('name')));
  55. }.property('name'),
  56. isForSlaveComponent: function () {
  57. return this.get('name') === 'DataNode' || this.get('name') === 'TaskTracker' ||
  58. this.get('name') === 'RegionServer';
  59. }.property('name'),
  60. slaveErrorCount: function () {
  61. var length = 0;
  62. if (this.get('slaveConfigs.groups')) {
  63. this.get('slaveConfigs.groups').forEach(function (_group) {
  64. length += _group.get('errorCount');
  65. }, this);
  66. }
  67. return length;
  68. }.property('slaveConfigs.groups.@each.errorCount')
  69. });
  70. App.SlaveConfigs = Ember.Object.extend({
  71. componentName: null,
  72. displayName: null,
  73. hosts: null,
  74. groups: null
  75. });
  76. App.Group = Ember.Object.extend({
  77. name: null,
  78. hostNames: null,
  79. properties: null,
  80. errorCount: function () {
  81. if (this.get('properties')) {
  82. return this.get('properties').filterProperty('isValid', false).filterProperty('isVisible', true).get('length');
  83. }
  84. }.property('properties.@each.isValid', 'properties.@each.isVisible')
  85. });
  86. App.ServiceConfigProperty = Ember.Object.extend({
  87. id: '', //either 'puppet var' or 'site property'
  88. name: '',
  89. displayName: '',
  90. value: '',
  91. defaultValue: '',
  92. defaultDirectory: '',
  93. description: '',
  94. displayType: 'string', // string, digits, number, directories, custom
  95. unit: '',
  96. category: 'General',
  97. isRequired: true, // by default a config property is required
  98. isReconfigurable: true, // by default a config property is reconfigurable
  99. isEditable: true, // by default a config property is editable
  100. isVisible: true,
  101. errorMessage: '',
  102. serviceConfig: null, // points to the parent App.ServiceConfig object
  103. filename: '',
  104. init: function () {
  105. if (this.get('id') === 'puppet var') {
  106. this.set('value', this.get('defaultValue'));
  107. }
  108. // TODO: remove mock data
  109. },
  110. initialValue: function () {
  111. var masterComponentHostsInDB = App.db.getMasterComponentHosts();
  112. //console.log("value in initialvalue: " + JSON.stringify(masterComponentHostsInDB));
  113. var hostsInfo = App.db.getHosts(); // which we are setting in installerController in step3.
  114. var slaveComponentHostsInDB = App.db.getSlaveComponentHosts();
  115. var isOnlyFirstOneNeeded = true;
  116. switch (this.get('name')) {
  117. case 'namenode_host':
  118. var temp = masterComponentHostsInDB.findProperty('component', 'NAMENODE');
  119. this.set('value', temp.hostName);
  120. break;
  121. case 'snamenode_host':
  122. this.set('value', masterComponentHostsInDB.findProperty('component', 'SECONDARY_NAMENODE').hostName);
  123. break;
  124. case 'datanode_hosts':
  125. this.set('value', slaveComponentHostsInDB.findProperty('componentName', 'DATANODE').hosts.mapProperty('hostName'));
  126. break;
  127. case 'jobtracker_host':
  128. this.set('value', masterComponentHostsInDB.findProperty('component', 'JOBTRACKER').hostName);
  129. break;
  130. case 'tasktracker_hosts':
  131. this.set('value', slaveComponentHostsInDB.findProperty('componentName', 'TASKTRACKER').hosts.mapProperty('hostName'));
  132. break;
  133. case 'hbasemaster_host':
  134. this.set('value', masterComponentHostsInDB.findProperty('component', 'HBASE_MASTER').hostName);
  135. break;
  136. case 'regionserver_hosts':
  137. this.set('value', slaveComponentHostsInDB.findProperty('componentName', 'HBASE_REGIONSERVER').hosts.mapProperty('hostName'));
  138. break;
  139. case 'hivemetastore_host':
  140. this.set('value', masterComponentHostsInDB.findProperty('component', 'HIVE_SERVER').hostName);
  141. break;
  142. case 'hive_ambari_host':
  143. this.set('value', masterComponentHostsInDB.findProperty('component', 'HIVE_SERVER').hostName);
  144. break;
  145. case 'oozieserver_host':
  146. this.set('value', masterComponentHostsInDB.findProperty('component', 'OOZIE_SERVER').hostName);
  147. break;
  148. case 'oozie_ambari_host':
  149. this.set('value', masterComponentHostsInDB.findProperty('component', 'OOZIE_SERVER').hostName);
  150. break;
  151. case 'zookeeperserver_hosts':
  152. this.set('value', masterComponentHostsInDB.filterProperty('component', 'ZOOKEEPER_SERVER').mapProperty('hostName'));
  153. break;
  154. case 'dfs_name_dir':
  155. case 'dfs_data_dir':
  156. case 'mapred_local_dir':
  157. this.unionAllMountPoints(!isOnlyFirstOneNeeded);
  158. break;
  159. case 'fs_checkpoint_dir':
  160. case 'zk_data_dir':
  161. case 'oozie_data_dir':
  162. this.unionAllMountPoints(isOnlyFirstOneNeeded);
  163. break;
  164. }
  165. },
  166. unionAllMountPoints: function (isOnlyFirstOneNeeded) {
  167. var hostname = '';
  168. var mountPointsPerHost = [];
  169. var mountPointAsRoot;
  170. var masterComponentHostsInDB = App.db.getMasterComponentHosts();
  171. var slaveComponentHostsInDB = App.db.getSlaveComponentHosts();
  172. var hostsInfo = App.db.getHosts(); // which we are setting in installerController in step3.
  173. App.Host.find().forEach(function(item){
  174. if(!hostsInfo[item.get('id')]){
  175. hostsInfo[item.get('id')] = {
  176. name: item.get('id'),
  177. cpu: item.get('cpu'),
  178. memory: item.get('memory'),
  179. disk_info: item.get('diskInfo'),
  180. bootStatus: "REGISTERED",
  181. isInstalled: true
  182. };
  183. }
  184. });
  185. var temp = '';
  186. var setOfHostNames = [];
  187. switch (this.get('name')) {
  188. case 'dfs_name_dir':
  189. var components = masterComponentHostsInDB.filterProperty('component', 'NAMENODE');
  190. components.forEach(function (component) {
  191. setOfHostNames.push(component.hostName);
  192. }, this);
  193. break;
  194. case 'fs_checkpoint_dir':
  195. var components = masterComponentHostsInDB.filterProperty('component', 'SECONDARY_NAMENODE');
  196. components.forEach(function (component) {
  197. setOfHostNames.push(component.hostName);
  198. }, this);
  199. break;
  200. case 'dfs_data_dir':
  201. temp = slaveComponentHostsInDB.findProperty('componentName', 'DATANODE');
  202. temp.hosts.forEach(function (host) {
  203. setOfHostNames.push(host.hostName);
  204. }, this);
  205. break;
  206. case 'mapred_local_dir':
  207. temp = slaveComponentHostsInDB.findProperty('componentName', 'TASKTRACKER');
  208. temp.hosts.forEach(function (host) {
  209. setOfHostNames.push(host.hostName);
  210. }, this);
  211. break;
  212. case 'zk_data_dir':
  213. var components = masterComponentHostsInDB.filterProperty('component', 'ZOOKEEPER_SERVER');
  214. components.forEach(function (component) {
  215. setOfHostNames.push(component.hostName);
  216. }, this);
  217. break;
  218. case 'oozie_data_dir':
  219. var components = masterComponentHostsInDB.filterProperty('component', 'OOZIE_SERVER');
  220. components.forEach(function (component) {
  221. setOfHostNames.push(component.hostName);
  222. }, this);
  223. break;
  224. }
  225. // In Add Host Wizard, if we did not select this slave component for any host, then we don't process any further.
  226. if (setOfHostNames.length === 0) {
  227. return;
  228. }
  229. var allMountPoints = [];
  230. for (var i = 0; i < setOfHostNames.length; i++) {
  231. hostname = setOfHostNames[i];
  232. mountPointsPerHost = hostsInfo[hostname].disk_info;
  233. mountPointAsRoot = mountPointsPerHost.findProperty('mountpoint', '/');
  234. mountPointsPerHost = mountPointsPerHost.filter(function (mPoint) {
  235. return !(['/', '/home', '/boot'].contains(mPoint.mountpoint) || ['devtmpfs', 'tmpfs', 'vboxsf'].contains(mPoint.type));
  236. });
  237. mountPointsPerHost.forEach(function (mPoint) {
  238. if( !allMountPoints.findProperty("mountpoint", mPoint.mountpoint)) {
  239. allMountPoints.push(mPoint);
  240. }
  241. }, this);
  242. }
  243. if (allMountPoints.length == 0) {
  244. allMountPoints.push(mountPointAsRoot);
  245. }
  246. this.set('value', '');
  247. if (!isOnlyFirstOneNeeded) {
  248. allMountPoints.forEach(function (eachDrive) {
  249. var mPoint = this.get('value');
  250. if (!mPoint) {
  251. mPoint = "";
  252. }
  253. if (eachDrive.mountpoint === "/") {
  254. mPoint += this.get('defaultDirectory') + "\n";
  255. } else {
  256. mPoint += eachDrive.mountpoint + this.get('defaultDirectory') + "\n";
  257. }
  258. this.set('value', mPoint);
  259. this.set('defaultValue', mPoint);
  260. }, this);
  261. } else {
  262. var mPoint = allMountPoints[0].mountpoint;
  263. if (mPoint === "/") {
  264. mPoint = this.get('defaultDirectory') + "\n";
  265. } else {
  266. mPoint = mPoint + this.get('defaultDirectory') + "\n";
  267. }
  268. this.set('value', mPoint);
  269. this.set('defaultValue', mPoint);
  270. }
  271. },
  272. isValid: function () {
  273. return this.get('errorMessage') === '';
  274. }.property('errorMessage'),
  275. viewClass: function () {
  276. switch (this.get('displayType')) {
  277. case 'checkbox':
  278. return App.ServiceConfigCheckbox;
  279. case 'password':
  280. return App.ServiceConfigPasswordField;
  281. case 'combobox':
  282. return App.ServiceConfigComboBox;
  283. case 'radio button':
  284. return App.ServiceConfigRadioButtons;
  285. break;
  286. case 'directories':
  287. return App.ServiceConfigTextArea;
  288. break;
  289. case 'custom':
  290. return App.ServiceConfigBigTextArea;
  291. case 'masterHost':
  292. return App.ServiceConfigMasterHostView;
  293. case 'masterHosts':
  294. return App.ServiceConfigMasterHostsView;
  295. case 'slaveHosts':
  296. return App.ServiceConfigSlaveHostsView;
  297. default:
  298. if (this.get('unit')) {
  299. return App.ServiceConfigTextFieldWithUnit;
  300. } else {
  301. return App.ServiceConfigTextField;
  302. }
  303. }
  304. }.property('displayType'),
  305. validate: function () {
  306. var value = this.get('value');
  307. var isError = false;
  308. if (typeof value === 'string' && value.trim().length === 0) {
  309. if (this.get('isRequired')) {
  310. this.set('errorMessage', 'This is required');
  311. isError = true;
  312. } else {
  313. return;
  314. }
  315. }
  316. if (!isError) {
  317. switch (this.get('displayType')) {
  318. case 'int':
  319. if (!validator.isValidInt(value)) {
  320. this.set('errorMessage', 'Must contain digits only');
  321. isError = true;
  322. }
  323. break;
  324. case 'float':
  325. if (!validator.isValidFloat(value)) {
  326. this.set('errorMessage', 'Must be a valid number');
  327. isError = true;
  328. }
  329. break;
  330. case 'checkbox':
  331. break;
  332. case 'directories':
  333. if (!validator.isValidDir(value)) {
  334. this.set('errorMessage', 'Must be a slash at the start');
  335. isError = true;
  336. }
  337. break;
  338. case 'directory':
  339. if (!validator.isValidDir(value)) {
  340. this.set('errorMessage', 'Must be a slash at the start');
  341. isError = true;
  342. }
  343. break;
  344. case 'custom':
  345. break;
  346. case 'user':
  347. if (!validator.isValidUserName(value)) {
  348. this.set('errorMessage', Em.I18n.t('users.userName.validationFail'));
  349. }
  350. isError = true;
  351. break;
  352. case 'email':
  353. if (!validator.isValidEmail(value)) {
  354. this.set('errorMessage', 'Must be a valid email address');
  355. isError = true;
  356. }
  357. break;
  358. case 'password':
  359. // retypedPassword is set by the retypePasswordView child view of App.ServiceConfigPasswordField
  360. if (value !== this.get('retypedPassword')) {
  361. this.set('errorMessage', 'Passwords do not match');
  362. isError = true;
  363. }
  364. }
  365. }
  366. if (!isError) {
  367. this.set('errorMessage', '');
  368. }
  369. }.observes('value', 'retypedPassword')
  370. });