AMBARI-7231. Slider View: View UI should load data from Ambari API (alexantonenko)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/00be663b Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/00be663b Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/00be663b Branch: refs/heads/branch-alerts-dev Commit: 00be663b5835c3cc4e56b19f3e7521ff187a1926 Parents: 4f62444 Author: Alex Antonenko <hiv...@gmail.com> Authored: Wed Sep 10 02:11:02 2014 +0300 Committer: Alex Antonenko <hiv...@gmail.com> Committed: Wed Sep 10 02:14:18 2014 +0300 ---------------------------------------------------------------------- .../assets/data/resource/service_status.json | 107 +++++++++++++++ .../app/controllers/slider_apps_controller.js | 136 ++++++++++++++++++- .../src/main/resources/ui/app/helpers/ajax.js | 40 +++++- .../src/main/resources/ui/app/initialize.js | 4 +- .../ui/app/mappers/application_status.js | 79 +++++------ .../src/main/resources/ui/app/translations.js | 7 + 6 files changed, 325 insertions(+), 48 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/00be663b/contrib/views/slider/src/main/resources/ui/app/assets/data/resource/service_status.json ---------------------------------------------------------------------- diff --git a/contrib/views/slider/src/main/resources/ui/app/assets/data/resource/service_status.json b/contrib/views/slider/src/main/resources/ui/app/assets/data/resource/service_status.json new file mode 100644 index 0000000..59dd8db --- /dev/null +++ b/contrib/views/slider/src/main/resources/ui/app/assets/data/resource/service_status.json @@ -0,0 +1,107 @@ + +{ + "items" : [ + { + "ServiceInfo" : { + "service_name" : "FALCON", + "state" : "STARTED" + } + }, + { + "ServiceInfo" : { + "service_name" : "FLUME", + "state" : "STARTED" + } + }, + { + "ServiceInfo" : { + "service_name" : "GANGLIA", + "state" : "STARTED" + } + }, + { + "ServiceInfo" : { + "service_name" : "HBASE", + "state" : "STARTED" + } + }, + { + "ServiceInfo" : { + "service_name" : "HCATALOG", + "state" : "INSTALLED" + } + }, + { + "ServiceInfo" : { + "service_name" : "HDFS", + "state" : "STARTED" + } + }, + { + "ServiceInfo" : { + "service_name" : "HIVE", + "state" : "INSTALLED" + } + }, + { + "ServiceInfo" : { + "service_name" : "MAPREDUCE2", + "state" : "STARTED" + } + }, + { + "ServiceInfo" : { + "service_name" : "NAGIOS", + "state" : "STARTED" + } + }, + { + "ServiceInfo" : { + "service_name" : "OOZIE", + "state" : "STARTED" + } + }, + { + "ServiceInfo" : { + "service_name" : "PIG", + "state" : "INSTALLED" + } + }, + { + "ServiceInfo" : { + "service_name" : "SQOOP", + "state" : "INSTALLED" + } + }, + { + "ServiceInfo" : { + "service_name" : "STORM", + "state" : "STARTED" + } + }, + { + "ServiceInfo" : { + "service_name" : "TEZ", + "state" : "INSTALLED" + } + }, + { + "ServiceInfo" : { + "service_name" : "WEBHCAT", + "state" : "STARTED" + } + }, + { + "ServiceInfo" : { + "service_name" : "YARN", + "state" : "STARTED" + } + }, + { + "ServiceInfo" : { + "service_name" : "ZOOKEEPER", + "state" : "STARTED" + } + } + ] +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/00be663b/contrib/views/slider/src/main/resources/ui/app/controllers/slider_apps_controller.js ---------------------------------------------------------------------- diff --git a/contrib/views/slider/src/main/resources/ui/app/controllers/slider_apps_controller.js b/contrib/views/slider/src/main/resources/ui/app/controllers/slider_apps_controller.js index df06c2c..7199777 100644 --- a/contrib/views/slider/src/main/resources/ui/app/controllers/slider_apps_controller.js +++ b/contrib/views/slider/src/main/resources/ui/app/controllers/slider_apps_controller.js @@ -23,9 +23,141 @@ App.SliderAppsController = Ember.ArrayController.extend({ * @method initResources */ initResources:function () { + this.getClusterName(); + }, + + initialValuesToLoad: Em.Object.create({ + ambariAddress: null, + clusterName: null, + hdfsAddress: null, + yarnRMAddress: null, + yarnRMSchedulerAddress: null, + zookeeperQuorum: null + }), + + zookeeperHosts: [], + + /** + * Get cluster name from server + * @returns {$.ajax} + * @method getClusterName + */ + getClusterName: function() { + return App.ajax.send({ + name: 'cluster_name', + sender: this, + data: { + urlPrefix: '/api/v1/' + }, + success: 'getClusterNameSuccessCallback' + }); + }, + + /** + * Success callback for clusterName-request + * @param {object} data + * @method getClusterNameSuccessCallback + */ + getClusterNameSuccessCallback: function(data) { + var clusterName = Em.get(data.items[0], 'Clusters.cluster_name'); + App.set('clusterName', clusterName); + App.ApplicationStatusMapper.loop('load'); + this.loadConfigsTags(); this.loadComponentHost({componentName:"GANGLIA_SERVER",callback:"loadGangliaHostSuccessCallback"}); this.loadComponentHost({componentName:"NAGIOS_SERVER",callback:"loadNagiosHostSuccessCallback"}); - }.on('init'), + this.loadComponentHost({componentName:"ZOOKEEPER_SERVER",callback:"setZookeeperQuorum"}); + }, + + loadConfigsTags: function () { + App.ajax.send({ + name: 'config.tags', + sender: this, + data: { + urlPrefix: '/api/v1/' + }, + success: 'onLoadConfigsTags' + }); + }, + + onLoadConfigsTags: function (data) { + var urlParams = []; + if(data.Clusters.desired_configs['yarn-site'] && data.Clusters.desired_configs['zookeeper-env']){ + var coreSiteTag = data.Clusters.desired_configs['core-site'].tag; + var yarnSiteTag = data.Clusters.desired_configs['yarn-site'].tag; + var zookeeperTag = data.Clusters.desired_configs['zookeeper-env'].tag; + urlParams.push('(type=core-site&tag=' + coreSiteTag + ')'); + urlParams.push('(type=yarn-site&tag=' + yarnSiteTag + ')'); + urlParams.push('(type=zookeeper-env&tag=' + zookeeperTag + ')'); + + App.ajax.send({ + name: 'get_all_configurations', + sender: this, + data: { + urlParams: urlParams.join('|'), + urlPrefix: '/api/v1/' + }, + success: 'onLoadConfigs' + }); + } + }, + + onLoadConfigs: function (data) { + var hdfs = data.items.findProperty('type', 'core-site'), + yarn = data.items.findProperty('type', 'yarn-site'), + zookeeper = data.items.findProperty('type', 'zookeeper-env'), + initialValuesToLoad = this.get('initialValuesToLoad'); + initialValuesToLoad.set('ambariAddress', location.protocol+"//"+document.location.host); + initialValuesToLoad.set('clusterName', App.get('clusterName')); + initialValuesToLoad.set('hdfsAddress', hdfs.properties['fs.defaultFS']); + initialValuesToLoad.set('yarnRMAddress', yarn.properties['yarn.resourcemanager.address']); + initialValuesToLoad.set('yarnRMSchedulerAddress', yarn.properties['yarn.resourcemanager.scheduler.address']); + initialValuesToLoad.set('zookeeperQuorum', zookeeper.properties.clientPort); + this.setZookeeperQuorum(); + }, + + setZookeeperQuorum: function (data){ + var zookeeperHosts = this.get('zookeeperHosts'), + hosts = [], + initialValuesToLoad = this.get('initialValuesToLoad'); + + //done + if(initialValuesToLoad.zookeeperQuorum !== null){ + if(data){ + hosts = data.items.map(function(item) { + return item.Hosts.host_name + ":" + initialValuesToLoad.zookeeperQuorum; + }); + initialValuesToLoad.set('zookeeperQuorum', hosts.join(',')); + this.sendInitialValues(); + }else if(zookeeperHosts.length > 0){ + hosts = zookeeperHosts.map(function(host) { + return host + ":" + initialValuesToLoad.zookeeperQuorum; + }); + initialValuesToLoad.set('zookeeperQuorum', hosts.join(',')); + this.sendInitialValues(); + } + }else{ + this.set('zookeeperHosts', data.items.mapProperty('Hosts.host_name')); + } + }, + + /** + * Send request to server to save initialValues + * @return {$.ajax} + * @method sendInitialValues + */ + sendInitialValues: function () { + return App.ajax.send({ + name: 'saveInitialValues', + sender: this, + data: { + data: { + ViewInstanceInfo: { + properties: this.get('initialValuesToLoad') + } + } + } + }); + }, /** * Load ganglia server host @@ -66,5 +198,5 @@ App.SliderAppsController = Ember.ArrayController.extend({ if(data.items[0]){ App.set('nagiosHost', Em.get(data.items[0], 'Hosts.host_name')); } - }, + } }); http://git-wip-us.apache.org/repos/asf/ambari/blob/00be663b/contrib/views/slider/src/main/resources/ui/app/helpers/ajax.js ---------------------------------------------------------------------- diff --git a/contrib/views/slider/src/main/resources/ui/app/helpers/ajax.js b/contrib/views/slider/src/main/resources/ui/app/helpers/ajax.js index c3d6967..f19f4eb 100644 --- a/contrib/views/slider/src/main/resources/ui/app/helpers/ajax.js +++ b/contrib/views/slider/src/main/resources/ui/app/helpers/ajax.js @@ -53,6 +53,19 @@ var urls = { mock: '/data/resource/status_true.json' }, + 'saveInitialValues': { + real: '', + headers: { + "Content-Type": "text/plain; charset=utf-8" + }, + format: function(data) { + return { + type: 'PUT', + data: JSON.stringify(data.data) + } + } + }, + 'createNewApp': { real: 'apps', mock: '', @@ -104,6 +117,15 @@ var urls = { } }, + 'service_status': { + real: 'clusters/{clusterName}/services?fields=ServiceInfo/state&minimal_response=true', + mock:'/data/resource/service_status.json', + headers: { + Accept : "text/plain; charset=utf-8", + "Content-Type": "text/plain; charset=utf-8" + } + }, + 'components_hosts': { real: 'clusters/{clusterName}/hosts?host_components/HostRoles/component_name={componentName}&minimal_response=true', mock:'/data/resource/components_hosts.json', @@ -113,6 +135,22 @@ var urls = { } }, + 'config.tags': { + 'real': 'clusters/{clusterName}?fields=Clusters/desired_configs', + headers: { + Accept : "text/plain; charset=utf-8", + "Content-Type": "text/plain; charset=utf-8" + } + }, + + 'get_all_configurations': { + 'real': 'clusters/{clusterName}/configurations?{urlParams}', + headers: { + Accept : "text/plain; charset=utf-8", + "Content-Type": "text/plain; charset=utf-8" + } + }, + 'cluster_name': { real: 'clusters', mock:'/data/resource/cluster_name.json', @@ -190,7 +228,7 @@ var formatRequest = function (data) { if(Em.get(data, 'urlPrefix')){ var prefix = Em.get(data, 'urlPrefix'); } - opt.url = prefix + formatUrl(this.real, data); + opt.url = prefix + (formatUrl(this.real, data) ? formatUrl(this.real, data) : ""); } if (this.format) { http://git-wip-us.apache.org/repos/asf/ambari/blob/00be663b/contrib/views/slider/src/main/resources/ui/app/initialize.js ---------------------------------------------------------------------- diff --git a/contrib/views/slider/src/main/resources/ui/app/initialize.js b/contrib/views/slider/src/main/resources/ui/app/initialize.js index e93550f..a9df6ad 100755 --- a/contrib/views/slider/src/main/resources/ui/app/initialize.js +++ b/contrib/views/slider/src/main/resources/ui/app/initialize.js @@ -82,9 +82,7 @@ App.initializer({ viewErrors: [] }); - - application.ApplicationStatusMapper.getClusterName(); - application.ApplicationStatusMapper.loop('load'); + application.SliderAppsController.proto().initResources(); application.ApplicationTypeMapper.loop('load'); application.SliderAppsMapper.loop('load'); } http://git-wip-us.apache.org/repos/asf/ambari/blob/00be663b/contrib/views/slider/src/main/resources/ui/app/mappers/application_status.js ---------------------------------------------------------------------- diff --git a/contrib/views/slider/src/main/resources/ui/app/mappers/application_status.js b/contrib/views/slider/src/main/resources/ui/app/mappers/application_status.js index 93a3789..f3d3968 100644 --- a/contrib/views/slider/src/main/resources/ui/app/mappers/application_status.js +++ b/contrib/views/slider/src/main/resources/ui/app/mappers/application_status.js @@ -24,24 +24,14 @@ App.ApplicationStatusMapper = App.Mapper.createWithMixins(App.RunPeriodically, { /** - * Map for parsing JSON received from server - * Format: - * <code> - * { - * key1: 'path1', - * key2: 'path2', - * key3: 'path3' - * } - * </code> - * Keys - names for properties in App - * Values - pathes in JSON - * @type {object} + * List of services, we need to get status of them + * @type {Array} */ - map: { - viewEnabled: 'viewEnabled', - viewErrors: 'viewErrors', - resourcesVersion: 'version' - }, + servicesWeNeed: [ + 'HDFS', + 'YARN', + 'ZOOKEEPER' + ], /** * Load data from <code>App.urlPrefix + this.urlSuffix</code> one time @@ -49,50 +39,55 @@ App.ApplicationStatusMapper = App.Mapper.createWithMixins(App.RunPeriodically, { * @return {$.ajax} */ load: function() { - console.log('App.ApplicationStatusMapper loading data'); return App.ajax.send({ name: 'mapper.applicationStatus', sender: this, - success: 'parse' + success: 'setResourcesVersion' }); }, /** - * Parse loaded data according to <code>map</code> * Set <code>App</code> properties * @param {object} data received from server data - * @method parse + * @method setResourcesVersion */ - parse: function(data) { - var map = this.get('map'); - Ember.keys(map).forEach(function(key) { - App.set(key, Ember.getWithDefault(data, map[key], '')); - }); + setResourcesVersion: function(data) { + App.set('resourcesVersion', Em.get(data, "version") ? Em.get(data, "version") : "version" ); + if(App.get('clusterName')){ + this.loadServicesStatus(); + } }, - /** - * Get cluster name from server - * @returns {$.ajax} - * @method getClusterName - */ - getClusterName: function() { + loadServicesStatus: function () { return App.ajax.send({ - name: 'cluster_name', - sender: this, + name: 'service_status', data: { urlPrefix: '/api/v1/' }, - success: 'getClusterNameSuccessCallback' + sender: this, + success: 'setErrors' }); }, - /** - * Success callback for clusterName-request - * @param {object} data - * @method getClusterNameSuccessCallback - */ - getClusterNameSuccessCallback: function(data) { - App.set('clusterName', Em.get(data.items[0], 'Clusters.cluster_name')); + setErrors: function (data) { + var self = this, + errors = []; + this.get('servicesWeNeed').forEach( function (serviceName) { + self.findError(data.items.findProperty("ServiceInfo.service_name", serviceName), errors); + }); + + App.set('viewEnabled', (errors.length > 0 ? false : true)); + App.set('viewErrors', errors); + }, + + findError: function (data, errors){ + var name = Em.get(data, "ServiceInfo.service_name") + if(data){ + if(Em.get(data, "ServiceInfo.state") != "STARTED") + errors.push(Em.I18n.t('error.start'+name)); + }else{ + errors.push(Em.I18n.t('error.no'+name)); + } } }); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/00be663b/contrib/views/slider/src/main/resources/ui/app/translations.js ---------------------------------------------------------------------- diff --git a/contrib/views/slider/src/main/resources/ui/app/translations.js b/contrib/views/slider/src/main/resources/ui/app/translations.js index 108d1c7..4af412a 100644 --- a/contrib/views/slider/src/main/resources/ui/app/translations.js +++ b/contrib/views/slider/src/main/resources/ui/app/translations.js @@ -49,6 +49,13 @@ Em.I18n.translations = { 'description': 'Description' }, + 'error.noHDFS': 'Slider applications view requires HDFS service.', + 'error.startHDFS': 'Slider applications view requires HDFS service to be started.', + 'error.noYARN': 'Slider applications view requires YARN service.', + 'error.startYARN': 'Slider applications view requires YARN service to be started.', + 'error.noZooKeeper': 'Slider applications view requires ZooKeeper service.', + 'error.startZOOKEEPER': 'Slider applications view requires ZooKeeper service to be started.', + 'popup.confirmation.commonHeader': 'Confirmation', 'question.sure':'Are you sure?',