| /* |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| */ |
| |
| /* Declarations of global data. */ |
| var fetchClusterServicesPoller; |
| var clusterServices; |
| |
| // Storing globally for the sake of multiple screens in reconfigure |
| var localReconfigureServiceData = {}; |
| var remoteReconfigureServiceData = {}; |
| var confirmationDataPanelBodyContent = ''; |
| |
| var confirmationDataPanel; |
| |
| var panelNoButton = { |
| value: 'Cancel', |
| action: function (e) { |
| e.preventDefault(); |
| hideAndDestroyPanel(); |
| }, |
| section: 'footer' |
| }; |
| |
| var panelYesButton; |
| |
| // Only one service can be reconfigured at a time. |
| var reconfigLevelOneYesButton; |
| var reconfigLevelTwoNoButton; |
| |
| function showPanel() { |
| showPanel(function() {}); |
| } |
| |
| function showPanel(postShowFn) { |
| confirmationDataPanel.set('y', 200); |
| confirmationDataPanel.set('x', (globalYui.one('body').get('region').width - confirmationDataPanel.get('width'))/2); |
| confirmationDataPanel.show(); |
| if (postShowFn != null) { |
| postShowFn.call(); |
| } |
| } |
| |
| function hidePanel(postHideFn) { |
| if (postHideFn != null) { |
| postHideFn.call(); |
| } |
| } |
| |
| function hideAndDestroyPanel() { |
| hidePanel(function() { |
| confirmationDataPanel.hide(); |
| destroyInformationalPanel(confirmationDataPanel); |
| }); |
| } |
| |
| function getTitleForReconfiguration(serviceName) { |
| return 'Make Configuration Changes for ' + serviceName; |
| } |
| |
| function setupReconfigureFirstScreen(serviceName) { |
| var panelTitle = getTitleForReconfiguration(serviceName); |
| confirmationDataPanel.set( 'headerContent', panelTitle); |
| confirmationDataPanel.set( 'bodyContent', confirmationDataPanelBodyContent); |
| // Remove buttons from previous stage |
| confirmationDataPanel.removeButton(0); |
| confirmationDataPanel.removeButton(0); |
| confirmationDataPanel.addButton( panelNoButton ); |
| confirmationDataPanel.addButton( reconfigLevelOneYesButton ); |
| } |
| |
| function setupReconfigureSecondScreen(serviceName) { |
| var affectedServices = clusterServices[serviceName].dependencies; |
| var dependents = clusterServices[serviceName].dependents; |
| for (dep in dependents) { |
| affectedServices.push(dependents[dep]); |
| } |
| var panelContent = 'Affected services:' + getAffectedDependenciesMarkup(affectedServices, serviceName, 'reconfigure'); |
| var panelTitle = 'Review changes to ' + serviceName + '\'s configuration'; |
| confirmationDataPanel.set( 'headerContent', panelTitle); |
| confirmationDataPanel.set( 'bodyContent', panelContent); |
| // Remove buttons from previous stage |
| confirmationDataPanel.removeButton(0); |
| confirmationDataPanel.removeButton(0); |
| confirmationDataPanel.addButton( reconfigLevelTwoNoButton ); |
| confirmationDataPanel.addButton( panelYesButton ); |
| } |
| |
| // Clean up the affected-services list to only include appropriate installed long-running services |
| function getAffectedDependenciesMarkup(affectedServices, serviceName, action) { |
| |
| var affectedDependenciesMarkup = ''; |
| |
| var serviceDisplayName = clusterServices[serviceName].displayName; |
| |
| var deps = affectedServices; |
| affectedServices = []; |
| for (dep in deps) { |
| var svc = deps[dep]; |
| if (clusterServices.hasOwnProperty(svc) && (clusterServices[svc].isEnabled == 1) && clusterServices[svc].attributes.runnable ) { |
| affectedServices.push(svc); |
| } |
| } |
| |
| var dependencyMarkup = ""; |
| for (affectedSrvc in affectedServices) { |
| if (clusterServices[affectedServices[affectedSrvc]].attributes.runnable) { |
| dependencyMarkup += '<tr><td>' + clusterServices[affectedServices[affectedSrvc]].displayName + '</td><td>' + titleCase(clusterServices[affectedServices[affectedSrvc]].state) + '</td></tr>'; |
| } |
| } |
| if (dependencyMarkup != '') { |
| // Add this service at the top of the list |
| dependencyMarkup = '<table><thead><th>Service name</th><th>Current state</th></thead><tr><td>' + serviceDisplayName + '</td><td>' + titleCase(clusterServices[serviceName].state) + '</td></tr>' + dependencyMarkup + '</table>'; |
| affectedDependenciesMarkup += 'Including this service and all its recursive dependencies, the following is the list of services that will be affected by ' + action + ' of ' + serviceName + ' :' + |
| '<br/>' + |
| '<div id="manageServicesDisplayDepsOnAction">' + |
| dependencyMarkup + |
| '</div>'; |
| } |
| return affectedDependenciesMarkup; |
| } |
| |
| function setupStartServiceScreen(serviceName) { |
| setupStartStopServiceScreen('start', serviceName); |
| } |
| |
| function setupStopServiceScreen(serviceName) { |
| setupStartStopServiceScreen('stop', serviceName); |
| } |
| |
| function setupStartStopServiceScreen(action, serviceName) { |
| |
| var serviceDisplayName = clusterServices[serviceName].displayName; |
| var affectedServices; |
| var confirmationDataPanelTitle; |
| |
| if ( action == 'start') { |
| confirmationDataPanelTitle = 'Starting ' + serviceDisplayName; |
| confirmationDataPanelBodyContent = "We are now going to start " + serviceDisplayName + "...<br/><br/>"; |
| affectedServices = clusterServices[serviceName].dependencies; |
| } else if (action == 'stop') { |
| confirmationDataPanelTitle = 'Stopping ' + serviceDisplayName; |
| confirmationDataPanelBodyContent = "We are now going to stop " + serviceDisplayName + "...<br/><br/>"; |
| affectedServices = clusterServices[serviceName].dependents; |
| } |
| |
| confirmationDataPanelBodyContent += getAffectedDependenciesMarkup(affectedServices, serviceName, action); |
| confirmationDataPanelBodyContent = '<div id="confirmationDataPanelBodyContent">' + confirmationDataPanelBodyContent + '</div>'; |
| |
| confirmationDataPanel.set( 'headerContent', confirmationDataPanelTitle); |
| confirmationDataPanel.set( 'bodyContent', confirmationDataPanelBodyContent); |
| confirmationDataPanel.set( 'height', 400); |
| confirmationDataPanel.set( 'width', 800); |
| |
| confirmationDataPanel.addButton( panelNoButton); |
| confirmationDataPanel.addButton( panelYesButton ); |
| |
| showPanel(); |
| } |
| |
| function setupStartAllServicesScreen() { |
| setupStartStopAllServicesScreen('startAll'); |
| } |
| |
| function setupStopAllServicesScreen() { |
| setupStartStopAllServicesScreen('stopAll'); |
| } |
| |
| function setupStartStopAllServicesScreen(action) { |
| var confirmationDataPanelTitle; |
| var confirmationDataPanelBodyContent; |
| |
| if ( action == 'startAll' ) { |
| confirmationDataPanelTitle = 'Start All Services'; |
| confirmationDataPanelBodyContent = "We are now going to start all services in the cluster"; |
| } else if ( action == 'stopAll' ) { |
| confirmationDataPanelTitle = 'Stop All Services'; |
| confirmationDataPanelBodyContent = "We are now going to stop all the services in the cluster"; |
| } |
| |
| confirmationDataPanel.set( 'headerContent', confirmationDataPanelTitle); |
| confirmationDataPanel.set( 'bodyContent', confirmationDataPanelBodyContent); |
| confirmationDataPanel.set( 'height', 400); |
| confirmationDataPanel.set( 'width', 800); |
| |
| confirmationDataPanel.addButton( panelNoButton); |
| confirmationDataPanel.addButton( panelYesButton ); |
| showPanel(); |
| } |
| |
| function setupReconfigureScreens(serviceName) { |
| // TODO: Needed for others too? |
| /* First, (temporarily) stop any further fetches. */ |
| fetchClusterServicesPoller.stop(); |
| |
| reconfigLevelOneYesButton = { |
| value: 'Apply Changes', |
| action: function (e) { |
| e.preventDefault(); |
| |
| localReconfigureServiceData = configureServicesUtil.generateUserOpts(); |
| var remoteProps = remoteReconfigureServiceData.services[serviceName].properties; |
| var localProps = localReconfigureServiceData[serviceName].properties; |
| var allEqual = true; |
| for (key in localProps) { |
| var remoteValue = remoteProps[key].value; |
| var localValue = localProps[key]["value"]; |
| if ( localValue != remoteValue) { |
| allEqual = false; |
| } |
| } |
| if (allEqual) { |
| alert("You haven't made any changes"); |
| return; |
| } |
| hidePanel(function() { |
| |
| // Store the requestData and the html |
| confirmationDataPanelBodyContent = confirmationDataPanel.get( 'bodyContent' ); |
| setupReconfigureSecondScreen(serviceName); |
| showPanel(); |
| }); |
| }, |
| classNames: 'okButton', |
| section: 'footer' |
| }; |
| |
| reconfigLevelTwoNoButton = { |
| value: 'Go back and re-edit', |
| action: function (e) { |
| e.preventDefault(); |
| |
| hidePanel(function() { |
| setupReconfigureFirstScreen(serviceName); |
| showPanel(); |
| }); |
| }, |
| section: 'footer' |
| }; |
| |
| // Render first with a loading image and then get config items |
| confirmationDataPanelBodyContent = |
| "<img id=errorInfoPanelLoadingImgId class=loadingImg src=../images/loading.gif />"; |
| var confirmationDataPanelTitle = getTitleForReconfiguration(serviceName); |
| confirmationDataPanel.set( 'height', 500); |
| confirmationDataPanel.set( 'width', 1000); |
| confirmationDataPanel.set( 'headerContent', confirmationDataPanelTitle); |
| confirmationDataPanel.set( 'bodyContent', confirmationDataPanelBodyContent ); |
| showPanel(); |
| |
| executeStage( '../php/frontend/fetchClusterServices.php?clusterName=' + clusterName + |
| '&getConfigs=true&serviceName=' + serviceName, function (serviceConfigurationData) { |
| |
| // Store the remote data |
| remoteReconfigureServiceData = serviceConfigurationData; |
| |
| var serviceConfigurationMarkup = configureServicesUtil.getOptionsSummaryMarkup(serviceConfigurationData, true); |
| |
| if( globalYui.Lang.trim( serviceConfigurationMarkup).length == 0 ) { |
| serviceConfigurationMarkup = '<p>There is nothing to reconfigure for this service.</p>'; |
| } |
| else { |
| /* Augment confirmationDataPanel with the relevant buttons only if there |
| * is something of value to show. |
| */ |
| confirmationDataPanel.addButton( panelNoButton ); |
| confirmationDataPanel.addButton( reconfigLevelOneYesButton ); |
| } |
| |
| /* XXX Note that this must be kept in-sync with the corresponding markup |
| * on the InstallationWizard page. |
| */ |
| confirmationDataPanelBodyContent = |
| '<div id=formStatusDivId class=formStatusBar style="display:none">'+ |
| 'Placeholder' + |
| '</div>' + |
| '<div id=configureClusterAdvancedCoreDivId>' + |
| '<form id=configureClusterAdvancedFormId>' + |
| '<fieldset id=configureClusterAdvancedFieldSetId>' + |
| '<div id=configureClusterAdvancedDynamicRenderDivId>' + |
| serviceConfigurationMarkup + |
| '</div>' + |
| '</fieldset>' + |
| '</form>' + |
| '</div>'; |
| |
| confirmationDataPanelBodyContent = '<div id="confirmationDataPanelBodyContent">' + confirmationDataPanelBodyContent + '</div>'; |
| |
| confirmationDataPanel.set( 'bodyContent', confirmationDataPanelBodyContent ); |
| }); |
| } |
| |
| function performServiceManagement( action, serviceName, confirmationDataPanel ) { |
| |
| /* First, (temporarily) stop any further fetches. */ |
| fetchClusterServicesPoller.stop(); |
| |
| var manageServicesRequestData = { |
| action: action, |
| services: {} |
| }; |
| |
| if( action == "reconfigure" ) { |
| manageServicesRequestData.services = localReconfigureServiceData; |
| } |
| else { |
| /* Need to explicitly set a key named for serviceName this way because it's |
| * a variable - in the future, the value will be a filled-out array (for |
| * now, we only support managing a single service at a time). |
| */ |
| manageServicesRequestData.services[serviceName] = {}; |
| } |
| |
| globalYui.io( "../php/frontend/manageServices.php?clusterName=" + clusterName, { |
| method: 'POST', |
| data: globalYui.JSON.stringify(manageServicesRequestData), |
| timeout: 10000, |
| on: { |
| success: function(x, o) { |
| |
| globalYui.log("RAW JSON DATA: " + o.responseText); |
| |
| var manageServicesResponseJson; |
| |
| try { |
| manageServicesResponseJson = globalYui.JSON.parse(o.responseText); |
| } |
| catch (e) { |
| alert("JSON Parse failed!"); |
| return; |
| } |
| |
| globalYui.log(globalYui.Lang.dump(manageServicesResponseJson)); |
| |
| /* Check that manageServicesResponseJson actually indicates success. */ |
| if( manageServicesResponseJson.result == 0 ) { |
| |
| /* Only on success should we destroy confirmationDataPanel - on |
| * failure, we depend on the fact that there'll be errors shown |
| * inside the panel that the user will want/need to interact with. |
| */ |
| hideAndDestroyPanel(); |
| |
| renderManageServicesProgress( manageServicesResponseJson.response ); |
| } |
| else { |
| /* No need to hide confirmationDataPanel here - there are errors |
| * that need to be handled. |
| */ |
| if (action == 'reconfigure') { |
| |
| hidePanel(function() { |
| setupReconfigureFirstScreen(serviceName); |
| showPanel( function() { |
| configureServicesUtil.handleConfigureServiceErrors( manageServicesResponseJson ); |
| }); |
| }); |
| } else { |
| // Can't do anything for others |
| alert('Got error during ' + action + ' : ' + globalYui.Lang.dump(manageServicesResponseJson)); |
| } |
| } |
| }, |
| failure: function(x, o) { |
| alert("Async call failed!"); |
| } |
| } |
| }); |
| } |
| |
| function getServiceConfigurationMarkup( serviceConfigurationData ) { |
| |
| return serviceConfigurationMarkup; |
| } |
| |
| function serviceManagementActionClickHandler( action, serviceName ) { |
| |
| // Reinit the global content |
| confirmationDataPanelBodyContent = ''; |
| |
| var confirmationDataPanelTitle = ''; // Set title later |
| |
| /* Create the panel that'll display our confirmation/data dialog. */ |
| confirmationDataPanel = |
| createInformationalPanel( '#informationalPanelContainerDivId', confirmationDataPanelTitle ); |
| |
| panelYesButton = { |
| value: 'OK', |
| action: function (e) { |
| e.preventDefault(); |
| performServiceManagement( action, serviceName, confirmationDataPanel ); |
| }, |
| classNames: 'okButton', |
| section: 'footer' |
| }; |
| |
| if ( action == 'start') { |
| setupStartServiceScreen(serviceName); |
| } else if ( action == 'stop') { |
| setupStopServiceScreen(serviceName); |
| } else if( action == 'startAll' ) { |
| setupStartAllServicesScreen(); |
| } else if( action == 'stopAll' ) { |
| setupStopAllServicesScreen(); |
| } else if( action == 'reconfigure' ) { |
| setupReconfigureScreens(serviceName); |
| } |
| } |
| |
| function deduceServiceManagementEntryCssClass( serviceInfo ) { |
| |
| var serviceManagementEntryCssClass = ''; |
| |
| var serviceState = serviceInfo.state; |
| |
| if( serviceState.match(/^stop/i) || serviceState.match(/^fail/i) ) { |
| serviceManagementEntryCssClass = "serviceManagementEntryStopped"; |
| } |
| else if( serviceState.match(/^start/i) ) { |
| serviceManagementEntryCssClass = "serviceManagementEntryStarted"; |
| } |
| else if( serviceState.match(/^install/i) ) { |
| serviceManagementEntryCssClass = "serviceManagementEntryInstalled"; |
| } |
| else if( serviceState.match(/^uninstall/i) ) { |
| serviceManagementEntryCssClass = "serviceManagementEntryUninstalled"; |
| } |
| |
| // globalYui.log( "Picking CSS class for" + serviceInfo.serviceName + ": " + serviceManagementEntryCssClass ); |
| |
| return serviceManagementEntryCssClass; |
| } |
| |
| function generateServiceManagementEntryMarkup( serviceName, serviceInfo ) { |
| |
| var generatedServiceManagementEntryMarkup = ''; |
| |
| var serviceAttributes = serviceInfo.attributes; |
| |
| /* Only generate a Service Management entry for services that are: |
| * |
| * a) enabled |
| * b) runnable |
| * c) meant to be displayed |
| */ |
| if( (serviceInfo.isEnabled == true) && !serviceAttributes.noDisplay ) { |
| |
| var serviceManagementEntryCssClass = deduceServiceManagementEntryCssClass( serviceInfo ); |
| |
| generatedServiceManagementEntryMarkup += |
| |
| '<li class="serviceManagementEntry '+ serviceManagementEntryCssClass + '">' + |
| '<div id="serviceManagementFor' + serviceName + '">' + |
| '<span class="serviceManagementEntryNameContainer">' + |
| '<a href="javascript:void(null)" name="' + serviceName + '" class="serviceManagementEntryName">' + |
| serviceInfo.displayName + |
| '</a>' + |
| '</span>' + |
| '<div class="serviceManagementEntryStateContainer">' + |
| titleCase(serviceInfo.state) + |
| '</div>' + |
| '<div class="serviceManagementEntryActionsContainer">'; |
| |
| if( serviceAttributes.runnable ) { |
| |
| var serviceManagementEntryAnchorName = ''; |
| var serviceManagementEntryAnchorTitle = ''; |
| var serviceManagementEntryAnchorCssClasses = 'serviceManagementEntryAction btn '; |
| var serviceManagementEntryIconCssClass = ''; |
| |
| /* Already-started/stopped services shouldn't allow a start/stop operation on them. */ |
| if( serviceInfo.state == 'STOPPED' || serviceInfo.state == 'FAILED') { |
| serviceManagementEntryAnchorName = 'start'; |
| serviceManagementEntryAnchorTitle = 'Start'; |
| serviceManagementEntryAnchorCssClasses += 'serviceManagementEntryActionStart'; |
| serviceManagementEntryIconCssClass = 'iconic-play'; |
| } |
| else if ( serviceInfo.state == 'STARTED' ) { |
| serviceManagementEntryAnchorName = 'stop'; |
| serviceManagementEntryAnchorTitle = 'Stop'; |
| serviceManagementEntryAnchorCssClasses += 'serviceManagementEntryActionStop'; |
| serviceManagementEntryIconCssClass = 'iconic-stop'; |
| } |
| else if ( serviceInfo.state == 'STOPPING') { |
| serviceManagementEntryAnchorName = 'start'; |
| serviceManagementEntryAnchorTitle = 'Start'; |
| serviceManagementEntryAnchorCssClasses += 'serviceManagementEntryActionStart disabled'; |
| serviceManagementEntryIconCssClass = 'iconic-start disabled'; |
| } |
| else if ( serviceInfo.state == 'STARTING') { |
| serviceManagementEntryAnchorName = 'stop'; |
| serviceManagementEntryAnchorTitle = 'Stop'; |
| serviceManagementEntryAnchorCssClasses += 'serviceManagementEntryActionStop disabled'; |
| serviceManagementEntryIconCssClass = 'iconic-stop disabled'; |
| } |
| |
| generatedServiceManagementEntryMarkup += |
| '<a href="javascript:void(null)" name="' + serviceManagementEntryAnchorName + '" ' + |
| 'title="' + serviceManagementEntryAnchorTitle + '" ' + |
| 'class="' + serviceManagementEntryAnchorCssClasses + '"><i class="' + serviceManagementEntryIconCssClass + '"></i></a> '; |
| } |
| |
| var notReconfigurable = [ 'PIG', 'SQOOP', 'OOZIE', 'TEMPLETON', 'GANGLIA', 'HIVE' ]; |
| var notReconfigurable = [ 'PIG', 'PIG2', 'SQOOP', 'OOZIE', 'TEMPLETON', 'GANGLIA', 'HIVE', 'HIVE2' ]; |
| var reconfigureClass; |
| if (globalYui.Array.indexOf(notReconfigurable, serviceName) >= 0) { |
| reconfigureClass = 'serviceManagementEntryActionReconfigure disabled'; |
| } else { |
| reconfigureClass = 'serviceManagementEntryActionReconfigure'; |
| } |
| |
| generatedServiceManagementEntryMarkup += '<a href="javascript:void(null)" name="reconfigure" title="Reconfigure" ' + |
| 'class="btn serviceManagementEntryAction ' + reconfigureClass + '"><i class="iconic-cog"></i></a>' + |
| '</div>' + |
| '</div>' + |
| '</li>'; |
| } |
| |
| return generatedServiceManagementEntryMarkup; |
| } |
| |
| // Do Not Remove --> We'll uncomment this section when the Service names link to something meaningful. |
| // |
| // /* Register click handlers for the service links themselves. */ |
| // globalYui.one('#serviceManagementListId').delegate('click', function (e) { |
| // alert(this.getAttribute('name')); |
| // }, 'li.serviceManagementEntry span.serviceManagementEntryNameContainer a.serviceManagementEntryName' ); |
| |
| /* Register click handlers for the global-action buttons. */ |
| globalYui.one('#serviceManagementGlobalActionsDivId').delegate('click', function (e) { |
| var action = this.getAttribute('name'); |
| |
| serviceManagementActionClickHandler( action ); |
| }, 'button' ); |
| |
| /* Register click handlers for the action links for each service. */ |
| globalYui.one('#serviceManagementListId').delegate('click', function (e) { |
| var action = this.getAttribute('name'); |
| var serviceName = this.ancestor('li.serviceManagementEntry'). |
| one('span.serviceManagementEntryNameContainer a.serviceManagementEntryName').getAttribute('name'); |
| |
| serviceManagementActionClickHandler( action, serviceName ); |
| }, 'li.serviceManagementEntry div.serviceManagementEntryActionsContainer a.serviceManagementEntryAction' ); |
| |
| /* Main() */ |
| |
| /* The clusterName variable is set in the Javascript scaffolding spit out by manageServices.php */ |
| var fetchClusterServicesPollerContext = { |
| source: '../php/frontend/fetchClusterServices.php', |
| schema: { |
| metaFields: { |
| services: 'response.services' |
| } |
| }, |
| request: '?clusterName=' + clusterName, |
| /* TODO XXX Change this from 5 seconds to 1 minute. */ |
| pollInterval: 5000, |
| maxFailedAttempts: 5 |
| }; |
| |
| var fetchClusterServicesPollerResponseHandler = { |
| success: function (e, pdp) { |
| /* Clear the screen of the loading image (in case it's currently showing). */ |
| hideLoadingImg(); |
| |
| /* The data from our backend. */ |
| clusterServices = e.response.meta.services; |
| |
| /* What we're here to render. */ |
| var serviceManagementMarkup = ''; |
| |
| // Separate block for client-only software |
| /* |
| var clientOnlySoftwareMarkup = ''; |
| for (var serviceName in clusterServices) { |
| var serviceInfo = clusterServices[serviceName]; |
| if (clusterServices.hasOwnProperty(serviceName) && !serviceInfo.attributes.runnable) { |
| clientOnlySoftwareMarkup += generateServiceManagementEntryMarkup( serviceName, serviceInfo ); |
| } |
| } |
| if (clientOnlySoftwareMarkup != '') { |
| serviceManagementMarkup += '<div class="serviceManagementGroup"><h2>Client-only software</h2><ul>'; |
| serviceManagementMarkup += clientOnlySoftwareMarkup; |
| serviceManagementMarkup += '</div>'; |
| } |
| */ |
| |
| // Real services with server side components |
| serviceManagementMarkup += '<div class="serviceManagementGroup" style="margin-top:30px"><ul>'; |
| for (var serviceName in clusterServices) { |
| var serviceInfo = clusterServices[serviceName]; |
| if (clusterServices.hasOwnProperty(serviceName) && serviceInfo.attributes.runnable) { |
| serviceManagementMarkup += generateServiceManagementEntryMarkup( serviceName, serviceInfo ); |
| } |
| } |
| serviceManagementMarkup += '</ul></div>'; |
| |
| /* Link the newly-generated serviceManagementMarkup into the DOM. */ |
| globalYui.one("#serviceManagementDynamicRenderDivId").setContent( serviceManagementMarkup ); |
| |
| /* If serviceManagementMarkup is non-empty, unveil the contents of |
| * #serviceManagementGlobalActionsDivId (which contains the StartAll |
| * and StopAll buttons) as well. |
| */ |
| if( globalYui.Lang.trim( serviceManagementMarkup ).length > 0 ) { |
| globalYui.one("#serviceManagementGlobalActionsDivId").setStyle( 'display', 'block' ); |
| } |
| }, |
| |
| failure: function (e, pdp) { |
| /* Clear the screen of the loading image (in case it's currently showing). */ |
| hideLoadingImg(); |
| |
| alert('Failed to fetch cluster services!'); |
| } |
| }; |
| |
| fetchClusterServicesPoller = new PeriodicDataPoller |
| ( fetchClusterServicesPollerContext, fetchClusterServicesPollerResponseHandler ); |
| |
| /* Kick the polling loop off. */ |
| fetchClusterServicesPoller.start(); |