cluster_controller.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  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.ClusterController = Em.Controller.extend({
  20. name:'clusterController',
  21. cluster:null,
  22. isLoaded:false,
  23. clusterDataLoadedPercent: 'width:0', // 0 to 1
  24. /**
  25. * Whether we need to update statuses automatically or not
  26. */
  27. isWorking: false,
  28. updateLoadStatus:function (item) {
  29. var loadList = this.get('dataLoadList');
  30. var loaded = true;
  31. var numLoaded= 0;
  32. loadList.set(item, true);
  33. for (var i in loadList) {
  34. if (loadList.hasOwnProperty(i) && !loadList[i] && loaded) {
  35. loaded = false;
  36. }
  37. // calculate the number of true
  38. if (loadList.hasOwnProperty(i) && loadList[i]){
  39. numLoaded++;
  40. }
  41. }
  42. this.set('isLoaded', loaded);
  43. this.set('clusterDataLoadedPercent', 'width:' + (Math.floor(numLoaded/7*100)).toString() + '%');
  44. },
  45. dataLoadList:Em.Object.create({
  46. 'hosts':false,
  47. 'services':false,
  48. 'cluster':false,
  49. 'racks':false,
  50. 'alerts':false,
  51. 'users':false,
  52. 'datasets':false
  53. }),
  54. /**
  55. * load cluster name
  56. */
  57. loadClusterName:function (reload) {
  58. if (this.get('clusterName') && !reload) {
  59. return;
  60. }
  61. var self = this;
  62. var url = (App.testMode) ? '/data/clusters/info.json' : App.apiPrefix + '/clusters';
  63. $.ajax({
  64. async:false,
  65. type:"GET",
  66. url:url,
  67. dataType:'json',
  68. timeout:App.timeout,
  69. success:function (data) {
  70. self.set('cluster', data.items[0]);
  71. App.set('clusterName', data.items[0].Clusters.cluster_name);
  72. if(data.items[0].Clusters.version){
  73. App.set('currentStackVersion', data.items[0].Clusters.version);
  74. }
  75. },
  76. error:function (request, ajaxOptions, error) {
  77. console.log('failed on loading cluster name');
  78. self.set('isLoaded', true);
  79. },
  80. statusCode:require('data/statusCodes')
  81. });
  82. },
  83. getUrl:function (testUrl, url) {
  84. return (App.testMode) ? testUrl : App.apiPrefix + '/clusters/' + this.get('clusterName') + url;
  85. },
  86. /**
  87. * Provides the URL to use for Ganglia server. This URL
  88. * is helpful in populating links in UI.
  89. *
  90. * If null is returned, it means GANGLIA service is not installed.
  91. */
  92. gangliaUrl: function () {
  93. if (App.testMode) {
  94. return 'http://gangliaserver/ganglia/?t=yes';
  95. } else {
  96. // We want live data here
  97. var svcs = App.Service.find();
  98. var gangliaSvc = svcs.findProperty("serviceName", "GANGLIA");
  99. if (gangliaSvc) {
  100. var svcComponents = gangliaSvc.get('hostComponents');
  101. if (svcComponents) {
  102. var gangliaSvcComponent = svcComponents.findProperty("componentName", "GANGLIA_SERVER");
  103. if (gangliaSvcComponent) {
  104. var hostName = gangliaSvcComponent.get('host.hostName');
  105. if (hostName) {
  106. var host = App.Host.find(hostName);
  107. if (host) {
  108. hostName = host.get('publicHostName');
  109. }
  110. return "http://" + hostName + "/ganglia";
  111. }
  112. }
  113. }
  114. }
  115. return null;
  116. }
  117. }.property('App.router.updateController.isUpdated', 'dataLoadList.hosts'),
  118. /**
  119. * Provides the URL to use for NAGIOS server. This URL
  120. * is helpful in getting alerts data from server and also
  121. * in populating links in UI.
  122. *
  123. * If null is returned, it means NAGIOS service is not installed.
  124. */
  125. nagiosUrl:function () {
  126. if (App.testMode) {
  127. return 'http://nagiosserver/nagios';
  128. } else {
  129. // We want live data here
  130. var svcs = App.Service.find();
  131. var nagiosSvc = svcs.findProperty("serviceName", "NAGIOS");
  132. if (nagiosSvc) {
  133. var svcComponents = nagiosSvc.get('hostComponents');
  134. if (svcComponents) {
  135. var nagiosSvcComponent = svcComponents.findProperty("componentName", "NAGIOS_SERVER");
  136. if (nagiosSvcComponent) {
  137. var hostName = nagiosSvcComponent.get('host.hostName');
  138. if (hostName) {
  139. var host = App.Host.find(hostName);
  140. if (host) {
  141. hostName = host.get('publicHostName');
  142. }
  143. return "http://" + hostName + "/nagios";
  144. }
  145. }
  146. }
  147. }
  148. return null;
  149. }
  150. }.property('App.router.updateController.isUpdated', 'dataLoadList.services', 'dataLoadList.hosts'),
  151. isNagiosInstalled:function () {
  152. if (App.testMode) {
  153. return true;
  154. } else {
  155. var svcs = App.Service.find();
  156. var nagiosSvc = svcs.findProperty("serviceName", "NAGIOS");
  157. return nagiosSvc != null;
  158. }
  159. }.property('App.router.updateController.isUpdated', 'dataLoadList.services'),
  160. /**
  161. * Sorted list of alerts.
  162. * Changes whenever alerts are loaded.
  163. */
  164. alerts:[],
  165. updateAlerts: function(){
  166. var alerts = App.Alert.find();
  167. var alertsArray = alerts.toArray();
  168. var sortedArray = alertsArray.sort(function (left, right) {
  169. var statusDiff = right.get('status') - left.get('status');
  170. if (statusDiff == 0) { // same error severity - sort by time
  171. var rightTime = right.get('date');
  172. var leftTime = left.get('date');
  173. rightTime = rightTime ? rightTime.getTime() : 0;
  174. leftTime = leftTime ? leftTime.getTime() : 0;
  175. statusDiff = rightTime - leftTime;
  176. }
  177. return statusDiff;
  178. });
  179. this.set('alerts', sortedArray);
  180. },
  181. /**
  182. * Load alerts from server
  183. * @param callback Slave function, should be called to fire delayed update.
  184. * Look at <code>App.updater.run</code> for more information.
  185. * Also used to set <code>dataLoadList.alerts</code> status during app loading
  186. */
  187. loadAlerts:function (callback) {
  188. if (this.get('isNagiosInstalled')) {
  189. var dataUrl = this.getUrl('/data/alerts/alerts.json', '/host_components?fields=HostRoles/nagios_alerts&HostRoles/component_name=NAGIOS_SERVER');
  190. var self = this;
  191. var ajaxOptions = {
  192. dataType:"json",
  193. complete:function () {
  194. self.updateAlerts();
  195. callback();
  196. },
  197. error: function(jqXHR, testStatus, error) {
  198. console.log('Nagios $.ajax() response:', error);
  199. }
  200. };
  201. App.HttpClient.get(dataUrl, App.alertsMapper, ajaxOptions);
  202. } else {
  203. console.log("No Nagios URL provided.")
  204. callback();
  205. }
  206. },
  207. /**
  208. * Determination of Nagios presence is known only after App.Service is
  209. * loaded from server. When that is done, no one tells alerts to load,
  210. * due to which alerts are not loaded & shown till the next polling cycle.
  211. * This method immediately loads alerts once Nagios presence is known.
  212. */
  213. isNagiosInstalledListener: function () {
  214. var self = this;
  215. self.loadAlerts(function () {
  216. self.updateLoadStatus('alerts');
  217. });
  218. }.observes('isNagiosInstalled'),
  219. /**
  220. * Send request to server to load components updated statuses
  221. * @param callback Slave function, should be called to fire delayed update.
  222. * Look at <code>App.updater.run</code> for more information
  223. * @return {Boolean} Whether we have errors
  224. */
  225. loadUpdatedStatus: function(callback){
  226. if(!this.get('clusterName')){
  227. callback();
  228. return false;
  229. }
  230. var servicesUrl = this.getUrl('/data/dashboard/services.json', '/services?fields=ServiceInfo,components/host_components/HostRoles/desired_state,components/host_components/HostRoles/state');
  231. App.HttpClient.get(servicesUrl, App.statusMapper, {
  232. complete: callback
  233. });
  234. return true;
  235. },
  236. /**
  237. * Run <code>loadUpdatedStatus</code> with delay
  238. * @param delay
  239. */
  240. loadUpdatedStatusDelayed: function(delay){
  241. setTimeout(function(){
  242. App.updater.immediateRun('loadUpdatedStatus');
  243. }, delay);
  244. },
  245. /**
  246. * Start polling, when <code>isWorking</code> become true
  247. */
  248. startPolling: function(){
  249. if(!this.get('isWorking')){
  250. return false;
  251. }
  252. App.updater.run(this, 'loadUpdatedStatus', 'isWorking'); //update will not run it immediately
  253. App.updater.run(this, 'loadAlerts', 'isWorking'); //update will not run it immediately
  254. return true;
  255. }.observes('isWorking'),
  256. /**
  257. *
  258. * load all data and update load status
  259. */
  260. loadClusterData:function () {
  261. var self = this;
  262. if (!this.get('clusterName')) {
  263. return;
  264. }
  265. if(this.get('isLoaded')) { // do not load data repeatedly
  266. return;
  267. }
  268. var clusterUrl = this.getUrl('/data/clusters/cluster.json', '?fields=Clusters');
  269. var hostsUrl = this.getUrl('/data/hosts/hosts.json', '/hosts?fields=Hosts/host_name,Hosts/public_host_name,Hosts/disk_info,Hosts/cpu_count,Hosts/total_mem,Hosts/host_status,Hosts/last_heartbeat_time,Hosts/os_arch,Hosts/os_type,Hosts/ip,host_components,metrics/disk,metrics/load/load_one');
  270. var usersUrl = App.testMode ? '/data/users/users.json' : App.apiPrefix + '/users/?fields=*';
  271. var racksUrl = "/data/racks/racks.json";
  272. var dataSetUrl = "/data/mirroring/all_datasets.json";
  273. debugger;
  274. App.HttpClient.get(dataSetUrl, App.dataSetMapper, {
  275. complete:function (jqXHR, textStatus) {
  276. self.updateLoadStatus('datasets');
  277. }
  278. }, function (jqXHR, textStatus) {
  279. self.updateLoadStatus('datasets');
  280. });
  281. App.HttpClient.get(racksUrl, App.racksMapper, {
  282. complete:function (jqXHR, textStatus) {
  283. self.updateLoadStatus('racks');
  284. }
  285. }, function (jqXHR, textStatus) {
  286. self.updateLoadStatus('racks');
  287. });
  288. App.HttpClient.get(clusterUrl, App.clusterMapper, {
  289. complete:function (jqXHR, textStatus) {
  290. self.updateLoadStatus('cluster');
  291. }
  292. }, function (jqXHR, textStatus) {
  293. self.updateLoadStatus('cluster');
  294. });
  295. App.HttpClient.get(hostsUrl, App.hostsMapper, {
  296. complete:function (jqXHR, textStatus) {
  297. self.updateLoadStatus('hosts');
  298. }
  299. }, function (jqXHR, textStatus) {
  300. self.updateLoadStatus('hosts');
  301. });
  302. App.HttpClient.get(usersUrl, App.usersMapper, {
  303. complete:function (jqXHR, textStatus) {
  304. self.updateLoadStatus('users');
  305. }
  306. }, function (jqXHR, textStatus) {
  307. self.updateLoadStatus('users');
  308. });
  309. App.router.get('updateController').updateServiceMetric(function(){
  310. self.updateLoadStatus('services');
  311. }, true);
  312. this.loadAlerts(function(){
  313. self.updateLoadStatus('alerts');
  314. });
  315. },
  316. clusterName:function () {
  317. return (this.get('cluster')) ? this.get('cluster').Clusters.cluster_name : null;
  318. }.property('cluster')
  319. })