Repository: ambari Updated Branches: refs/heads/branch-feature-AMBARI-14714 16913b201 -> adc7060a6
AMBARI-22198. Implement read only API for getting stack level settings. Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/adc7060a Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/adc7060a Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/adc7060a Branch: refs/heads/branch-feature-AMBARI-14714 Commit: adc7060a6cf6b0e318e6d94ac973dfdc27eeb45f Parents: 16913b2 Author: Swapan Shridhar <[email protected]> Authored: Mon Oct 23 16:40:45 2017 -0700 Committer: Swapan Shridhar <[email protected]> Committed: Thu Nov 2 12:24:39 2017 -0700 ---------------------------------------------------------------------- .../resources/ResourceInstanceFactoryImpl.java | 4 + .../RootStackSettingsResourceDefinition.java | 51 ++++++ .../server/api/services/AmbariMetaInfo.java | 60 +++++-- .../api/services/RootClusterSettingService.java | 2 +- .../server/api/services/StacksService.java | 89 ++++++++++ .../controller/AmbariManagementController.java | 8 + .../AmbariManagementControllerImpl.java | 44 ++++- .../server/controller/ControllerModule.java | 4 +- .../AbstractControllerResourceProvider.java | 6 +- .../RootStackSettingsResourceProvider.java | 177 +++++++++++++++++++ .../ambari/server/controller/spi/Resource.java | 2 + .../ResourceLevelClusterSettingManager.java | 168 ------------------ ...sourceLevelClusterSettingManagerFactory.java | 34 ---- .../resources/RootLevelSettingsManager.java | 174 ++++++++++++++++++ .../RootLevelSettingsManagerFactory.java | 36 ++++ .../apache/ambari/server/stack/StackModule.java | 20 ++- .../apache/ambari/server/state/StackInfo.java | 37 ++++ .../stacks/HDP/3.0/configuration/settings.xml | 91 ++++++++++ 18 files changed, 784 insertions(+), 223 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/adc7060a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java index c009cbb..6096fa5 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java @@ -205,6 +205,10 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory { resourceDefinition = new StackLevelConfigurationResourceDefinition(); break; + case RootStackSetting: + resourceDefinition = new RootStackSettingsResourceDefinition(); + break; + case StackService: resourceDefinition = new StackServiceResourceDefinition(); break; http://git-wip-us.apache.org/repos/asf/ambari/blob/adc7060a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/RootStackSettingsResourceDefinition.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/RootStackSettingsResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/RootStackSettingsResourceDefinition.java new file mode 100644 index 0000000..0991ace --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/RootStackSettingsResourceDefinition.java @@ -0,0 +1,51 @@ +/* + * 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. + */ + +package org.apache.ambari.server.api.resources; + +import java.util.HashSet; +import java.util.Set; + +import org.apache.ambari.server.controller.spi.Resource.Type; + +public class RootStackSettingsResourceDefinition extends BaseResourceDefinition { + + public RootStackSettingsResourceDefinition(Type resourceType) { + super(resourceType); + } + + public RootStackSettingsResourceDefinition() { + super(Type.RootStackSetting); + } + + @Override + public String getPluralName() { + return "rootStackSettings"; + } + + @Override + public String getSingularName() { + return "rootStackSetting"; + } + + @Override + public Set<SubResourceDefinition> getSubResourceDefinitions() { + Set<SubResourceDefinition> subs = new HashSet<>(); + return subs; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/adc7060a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java index 1c0a555..c410ce4 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java @@ -63,8 +63,8 @@ import org.apache.ambari.server.orm.dao.MetainfoDAO; import org.apache.ambari.server.orm.entities.AlertDefinitionEntity; import org.apache.ambari.server.orm.entities.MpackEntity; import org.apache.ambari.server.orm.entities.StackEntity; -import org.apache.ambari.server.resources.ResourceLevelClusterSettingManager; -import org.apache.ambari.server.resources.ResourceLevelClusterSettingManagerFactory; +import org.apache.ambari.server.resources.RootLevelSettingsManager; +import org.apache.ambari.server.resources.RootLevelSettingsManagerFactory; import org.apache.ambari.server.stack.StackManager; import org.apache.ambari.server.stack.StackManagerFactory; import org.apache.ambari.server.state.Cluster; @@ -143,8 +143,8 @@ public class AmbariMetaInfo { private final ActionDefinitionManager adManager = new ActionDefinitionManager(); private String serverVersion = "undefined"; - private String clusterSettingFileName = "cluster-settings.xml"; - + private final String clusterSettingsTypeName = "cluster-settings"; + private final String clusterSettingFileName = clusterSettingsTypeName + ".xml"; private File resourcesRoot; private File stackRoot; private File commonServicesRoot; @@ -226,16 +226,15 @@ public class AmbariMetaInfo { private MpackManager mpackManager; /** - * Factory for injecting {@link ResourceLevelClusterSettingManager} instances. + * Factory for injecting {@link RootLevelSettingsManager} instances. */ @Inject - private ResourceLevelClusterSettingManagerFactory resourceLevelClusterSettingManagerFactory; + private RootLevelSettingsManagerFactory rootLevelSettingsManagerFactory; /** * Singleton instance of Resource Level 'Cluster Setting' Manager */ - private ResourceLevelClusterSettingManager resourceLevelClusterSettingManager; - + private RootLevelSettingsManager rootLevelClusterSettingManager; private Configuration conf; @@ -298,7 +297,9 @@ public class AmbariMetaInfo { mpackManager = mpackManagerFactory.create(mpacksV2Staging, stackRoot); - resourceLevelClusterSettingManager = resourceLevelClusterSettingManagerFactory.create(conf.getResourceDirPath()); + // Manager for cluster's read-only default settings + rootLevelClusterSettingManager = rootLevelSettingsManagerFactory.create(conf.getResourceDirPath(), + clusterSettingFileName, clusterSettingsTypeName); getCustomActionDefinitions(customActionRoot); } @@ -813,14 +814,14 @@ public class AmbariMetaInfo { Returns Resource Level read only 'Cluster Properties'. */ public Set<PropertyInfo> getClusterProperties() { - return new HashSet<>(resourceLevelClusterSettingManager.getClusterSettingsMap()); + return new HashSet<>(rootLevelClusterSettingManager.getClusterSettingsMap()); } /* Returns specific Resource Level read only 'Cluster Property'. */ public Set<PropertyInfo> getClusterPropertiesByName(String propertyName) throws AmbariException { - HashSet<PropertyInfo> properties = new HashSet<>(resourceLevelClusterSettingManager.getClusterSettingsMap()); + HashSet<PropertyInfo> properties = new HashSet<>(rootLevelClusterSettingManager.getClusterSettingsMap()); if (properties.size() == 0) { throw new PropertyNotFoundException("'" + propertyName + "', in " + clusterSettingFileName); } @@ -838,6 +839,43 @@ public class AmbariMetaInfo { return propertyResult; } + /* + Returns read only 'Stack Settings'. + */ + public Set<PropertyInfo> getStackSettings(String stackName, String version) + throws AmbariException { + return new HashSet<>(getStack(stackName, version).getStackSettings()); + } + + /* + Returns specific read only 'Stack Setting'. + */ + public Set<PropertyInfo> getStackSettingsByName(String stackName, String version, String settingName) + throws AmbariException { + Set<PropertyInfo> settings = getStackSettings(stackName, version); + if (settings.size() == 0) { + throw new StackAccessException("stackName=" + stackName + + ", stackVersion=" + version + + ", settingName=" + settingName); + } + + Set<PropertyInfo> settingResult = new HashSet<>(); + + for (PropertyInfo setting : settings) { + if (setting.getName().equals(settingName)) { + settingResult.add(setting); + } + } + + if (settingResult.isEmpty()) { + throw new StackAccessException("stackName=" + stackName + + ", stackVersion=" + version + + ", settingName=" + settingName); + } + + return settingResult; + } + public Set<PropertyInfo> getStackPropertiesByName(String stackName, String version, String propertyName) throws AmbariException { Set<PropertyInfo> properties = getStackProperties(stackName, version); http://git-wip-us.apache.org/repos/asf/ambari/blob/adc7060a/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootClusterSettingService.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootClusterSettingService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootClusterSettingService.java index d77b347..bd2fb91 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootClusterSettingService.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootClusterSettingService.java @@ -46,7 +46,7 @@ import io.swagger.annotations.ApiResponse; import io.swagger.annotations.ApiResponses; /** - * Service responsible for services resource requests. + * Service responsible for 'root cluster settings' resource requests. */ @Path("/cluster_settings/") @Api(value = "ClusterSettings", description = "Endpoint for fetching read only 'cluster settings'") http://git-wip-us.apache.org/repos/asf/ambari/blob/adc7060a/ambari-server/src/main/java/org/apache/ambari/server/api/services/StacksService.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/StacksService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/StacksService.java index aef7fc1..4b0208f 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/StacksService.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/StacksService.java @@ -46,6 +46,7 @@ import org.apache.ambari.server.controller.StackServiceComponentResponse; import org.apache.ambari.server.controller.StackServiceResponse; import org.apache.ambari.server.controller.StackVersionResponse; import org.apache.ambari.server.controller.ThemeResponse; +import org.apache.ambari.server.controller.internal.RootClusterSettingsResourceProvider; import org.apache.ambari.server.controller.spi.Resource; import org.apache.http.HttpStatus; @@ -1051,5 +1052,93 @@ public class StacksService extends BaseService { Collections.singletonMap(Resource.Type.Stack, stackName)); } + + /** + * Handles: GET /stack_settings + * Get all stack-settings for a given stack. + * + * @param headers http headers + * @param ui uri info + * @return stack settings collection resource representation + */ + @GET + @Path("{stackName}/versions/{stackVersion}/settings") + @Produces(MediaType.TEXT_PLAIN) + @ApiOperation(value = "Get all stack-settings for a given stack", + nickname = "StacksService#getClusterSettings", + notes = "Returns all stack-settings for a given stack.", + response = ReadOnlyConfigurationResponse.ReadOnlyConfigurationResponseSwagger.class, + responseContainer = RESPONSE_CONTAINER_LIST) + @ApiImplicitParams({ + @ApiImplicitParam(name = QUERY_FIELDS, value = "Filter returned attributes", + defaultValue = "StackSettingsInfo/property_name,", + dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY), + @ApiImplicitParam(name = QUERY_SORT, value = "Sort stack settings (asc | desc)", + defaultValue = "StackSettingsInfo/property_name.asc,", + dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY), + @ApiImplicitParam(name = QUERY_PAGE_SIZE, value = QUERY_PAGE_SIZE_DESCRIPTION, defaultValue = DEFAULT_PAGE_SIZE, dataType = DATA_TYPE_INT, paramType = PARAM_TYPE_QUERY), + @ApiImplicitParam(name = QUERY_FROM, value = QUERY_FROM_DESCRIPTION, defaultValue = DEFAULT_FROM, dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY), + @ApiImplicitParam(name = QUERY_TO, value = QUERY_TO_DESCRIPTION, dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY) + }) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION), + @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR) + }) + public Response getStackSettings(String body, + @Context HttpHeaders headers, + @Context UriInfo ui, + @ApiParam @PathParam("stackName") String stackName, + @ApiParam @PathParam("stackVersion") String stackVersion) { + return handleRequest(headers, body, ui, Request.Type.GET, createStackSettingsResource(stackName, stackVersion, null)); + } + + /** + * Handles GET /stack_settings/{settingName} + * Get specific read-only default stack setting. + * + * @param headers http headers + * @param ui uri info + * @return stack settings collection resource representation + */ + @GET + @Path("{stackName}/versions/{stackVersion}/settings/{settingName}") + @Produces("text/plain") + @ApiOperation(value = "Returns information about specific read only 'stack setting'", + response = ReadOnlyConfigurationResponse.ReadOnlyConfigurationResponseSwagger.class) + @ApiImplicitParams({ + @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION, dataType = DATA_TYPE_STRING, + paramType = PARAM_TYPE_QUERY, defaultValue = RootClusterSettingsResourceProvider.ALL_PROPERTIES), + }) + @ApiResponses({ + @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION), + @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND), + @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = MSG_NOT_AUTHENTICATED), + @ApiResponse(code = HttpStatus.SC_FORBIDDEN, message = MSG_PERMISSION_DENIED), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR), + }) + public Response getStackSetting(String body, + @Context HttpHeaders headers, + @Context UriInfo ui, + @ApiParam @PathParam("stackName") String stackName, + @ApiParam @PathParam("stackVersion") String stackVersion, + @PathParam("settingName") String settingName) { + return handleRequest(headers, body, ui, Request.Type.GET, createStackSettingsResource(stackName, stackVersion, settingName)); + } + + /** + * Create a 'stack setting' resource instance. + * + * @return 'stack setting' resource instance + */ + ResourceInstance createStackSettingsResource(String stackName, + String stackVersion, String settingName) { + Map<Resource.Type, String> mapIds = new HashMap<>(); + mapIds.put(Resource.Type.Stack, stackName); + mapIds.put(Resource.Type.StackVersion, stackVersion); + mapIds.put(Resource.Type.RootStackSetting, settingName); + + return createResource(Resource.Type.RootStackSetting, mapIds); + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/adc7060a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java index 0a75595..358b1bf 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java @@ -846,6 +846,14 @@ public interface AmbariManagementController { Set<ReadOnlyConfigurationResponse> getStackLevelConfigurations(Set<StackLevelConfigurationRequest> requests) throws AmbariException; /** + * Get initial settings for a given stack (!not a service). + * @param requests + * @return + * @throws AmbariException + */ + Set<ReadOnlyConfigurationResponse> getReadOnlyStackSettings(Set<StackConfigurationRequest> requests) throws AmbariException; + + /** * Get initial settings for a cluster (!not a service). * @param requests * @return http://git-wip-us.apache.org/repos/asf/ambari/blob/adc7060a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java index 5eb18c3..370f735 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java @@ -156,7 +156,6 @@ import org.apache.ambari.server.stack.ExtensionHelper; import org.apache.ambari.server.stack.RepoUtil; import org.apache.ambari.server.stageplanner.RoleGraph; import org.apache.ambari.server.stageplanner.RoleGraphFactory; - import org.apache.ambari.server.state.Cluster; import org.apache.ambari.server.state.Clusters; import org.apache.ambari.server.state.CommandScriptDefinition; @@ -4872,8 +4871,8 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle Set<RootClusterSettingRequest> requests) throws AmbariException { Set<ReadOnlyConfigurationResponse> response = new HashSet<>(); for (RootClusterSettingRequest request : requests) { - Set<ReadOnlyConfigurationResponse> stackConfigurations = getResourceLevelClusterSettings(request); - response.addAll(stackConfigurations); + Set<ReadOnlyConfigurationResponse> clusterSettings = getResourceLevelClusterSettings(request); + response.addAll(clusterSettings); } return response; @@ -4896,6 +4895,45 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle return response; } + @Override + public Set<ReadOnlyConfigurationResponse> getReadOnlyStackSettings( + Set<StackConfigurationRequest> requests) throws AmbariException { + Set<ReadOnlyConfigurationResponse> response = new HashSet<>(); + for (StackConfigurationRequest request : requests) { + String stackName = request.getStackName(); + String stackVersion = request.getStackVersion(); + Set<ReadOnlyConfigurationResponse> stackSettings = getReadOnlyStackSettings(request); + + for (ReadOnlyConfigurationResponse stackSetting : stackSettings) { + stackSetting.setStackName(stackName); + stackSetting.setStackVersion(stackVersion); + } + response.addAll(stackSettings); + } + + return response; + } + + private Set<ReadOnlyConfigurationResponse> getReadOnlyStackSettings( + StackConfigurationRequest request) throws AmbariException { + Set<ReadOnlyConfigurationResponse> response = new HashSet<>(); + + String stackName = request.getStackName(); + String stackVersion = request.getStackVersion(); + String settingName = request.getPropertyName(); + + Set<PropertyInfo> settings; + if (settingName != null) { + settings = ambariMetaInfo.getStackSettingsByName(stackName, stackVersion, settingName); + } else { + settings = ambariMetaInfo.getStackSettings(stackName, stackVersion); + } + + for (PropertyInfo setting : settings) { + response.add(setting.convertToResponse()); + } + return response; + } @Override public Set<ReadOnlyConfigurationResponse> getStackConfigurations( http://git-wip-us.apache.org/repos/asf/ambari/blob/adc7060a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java index cb19099..3db55d4 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java @@ -111,7 +111,7 @@ import org.apache.ambari.server.registry.RegistryFactory; import org.apache.ambari.server.registry.RegistryFactoryImpl; import org.apache.ambari.server.registry.RegistryManager; import org.apache.ambari.server.registry.RegistryManagerImpl; -import org.apache.ambari.server.resources.ResourceLevelClusterSettingManagerFactory; +import org.apache.ambari.server.resources.RootLevelSettingsManagerFactory; import org.apache.ambari.server.scheduler.ExecutionScheduler; import org.apache.ambari.server.scheduler.ExecutionSchedulerImpl; import org.apache.ambari.server.security.SecurityHelper; @@ -516,7 +516,7 @@ public class ControllerModule extends AbstractModule { install(new FactoryModuleBuilder().build(MetricPropertyProviderFactory.class)); install(new FactoryModuleBuilder().build(UpgradeContextFactory.class)); install(new FactoryModuleBuilder().build(MpackManagerFactory.class)); - install(new FactoryModuleBuilder().build(ResourceLevelClusterSettingManagerFactory.class)); + install(new FactoryModuleBuilder().build(RootLevelSettingsManagerFactory.class)); bind(RegistryFactory.class).to(RegistryFactoryImpl.class); bind(HostRoleCommandFactory.class).to(HostRoleCommandFactoryImpl.class); http://git-wip-us.apache.org/repos/asf/ambari/blob/adc7060a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java index 123f2fe..9050e3d 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java @@ -152,6 +152,8 @@ public abstract class AbstractControllerResourceProvider extends AbstractAuthori switch (type.getInternalType()) { case Cluster: return new ClusterResourceProvider(managementController); + case RootClusterSetting: + return new RootClusterSettingsResourceProvider(managementController); case Service: return resourceProviderFactory.getServiceResourceProvider(managementController); case ServiceGroup: @@ -198,8 +200,6 @@ public abstract class AbstractControllerResourceProvider extends AbstractAuthori return new RegistryMpackVersionResourceProvider(managementController); case Mpack: return new MpackResourceProvider(managementController); - case RootClusterSetting: - return new RootClusterSettingsResourceProvider(managementController); case StackVersion: return new StackVersionResourceProvider(managementController); case ClusterStackVersion: @@ -212,6 +212,8 @@ public abstract class AbstractControllerResourceProvider extends AbstractAuthori return new StackServiceComponentResourceProvider(propertyIds, keyPropertyIds, managementController); case StackConfiguration: return new StackConfigurationResourceProvider(propertyIds, keyPropertyIds, managementController); + case RootStackSetting: + return new RootStackSettingsResourceProvider(managementController); case StackConfigurationDependency: return new StackConfigurationDependencyResourceProvider(propertyIds, keyPropertyIds, managementController); case StackLevelConfiguration: http://git-wip-us.apache.org/repos/asf/ambari/blob/adc7060a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootStackSettingsResourceProvider.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootStackSettingsResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootStackSettingsResourceProvider.java new file mode 100644 index 0000000..81baec6 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootStackSettingsResourceProvider.java @@ -0,0 +1,177 @@ +/* + * 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. + */ + + +package org.apache.ambari.server.controller.internal; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.apache.ambari.server.AmbariException; +import org.apache.ambari.server.controller.AmbariManagementController; +import org.apache.ambari.server.controller.ReadOnlyConfigurationResponse; +import org.apache.ambari.server.controller.StackConfigurationRequest; +import org.apache.ambari.server.controller.spi.NoSuchParentResourceException; +import org.apache.ambari.server.controller.spi.NoSuchResourceException; +import org.apache.ambari.server.controller.spi.Predicate; +import org.apache.ambari.server.controller.spi.Request; +import org.apache.ambari.server.controller.spi.Resource; +import org.apache.ambari.server.controller.spi.Resource.Type; +import org.apache.ambari.server.controller.spi.SystemException; +import org.apache.ambari.server.controller.spi.UnsupportedPropertyException; +import org.apache.ambari.server.controller.utilities.PropertyHelper; +import org.apache.commons.lang.StringUtils; + +import com.google.inject.assistedinject.Assisted; + +public class RootStackSettingsResourceProvider extends ReadOnlyResourceProvider { + + public static final String RESPONSE_KEY = "StackSettingsInfo"; + public static final String ALL_PROPERTIES = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "*"; + public static final String STACK_NAME_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "stack_name"; + public static final String STACK_VERSION_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "stack_version"; + public static final String PROPERTY_NAME_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "property_name"; + public static final String PROPERTY_DISPLAY_NAME_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "property_display_name"; + public static final String PROPERTY_VALUE_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "property_value"; + public static final String PROPERTY_VALUE_ATTRIBUTES_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "property_value_attributes"; + public static final String DEPENDS_ON_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "property_depends_on"; + public static final String PROPERTY_DESCRIPTION_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "property_description"; + public static final String PROPERTY_PROPERTY_TYPE_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "property_type"; + public static final String PROPERTY_TYPE_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "type"; + public static final String PROPERTY_FINAL_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "final"; + + private static Set<String> pkPropertyIds = new HashSet<>(Arrays.asList(new String[]{PROPERTY_NAME_PROPERTY_ID})); + + /** + * The key property ids for stack's 'settings' resource. + */ + private static final Map<Resource.Type, String> KEY_PROPERTY_IDS = new HashMap<>(); + + /** + * The property ids for an stack's 'settings' resource. + */ + private static final Set<String> PROPERTY_IDS = new HashSet<>(); + + static { + // properties + PROPERTY_IDS.add(STACK_NAME_PROPERTY_ID); + PROPERTY_IDS.add(STACK_VERSION_PROPERTY_ID); + PROPERTY_IDS.add(PROPERTY_NAME_PROPERTY_ID); + PROPERTY_IDS.add(PROPERTY_DISPLAY_NAME_PROPERTY_ID); + PROPERTY_IDS.add(PROPERTY_VALUE_PROPERTY_ID); + PROPERTY_IDS.add(PROPERTY_VALUE_ATTRIBUTES_PROPERTY_ID); + PROPERTY_IDS.add(DEPENDS_ON_PROPERTY_ID); + PROPERTY_IDS.add(PROPERTY_DESCRIPTION_PROPERTY_ID); + PROPERTY_IDS.add(PROPERTY_PROPERTY_TYPE_PROPERTY_ID); + PROPERTY_IDS.add(PROPERTY_TYPE_PROPERTY_ID); + PROPERTY_IDS.add(PROPERTY_FINAL_PROPERTY_ID); + + // keys + KEY_PROPERTY_IDS.put(Type.Stack, STACK_NAME_PROPERTY_ID); + KEY_PROPERTY_IDS.put(Type.StackVersion, STACK_VERSION_PROPERTY_ID); + KEY_PROPERTY_IDS.put(Type.RootStackSetting, PROPERTY_NAME_PROPERTY_ID); + } + + protected RootStackSettingsResourceProvider(@Assisted AmbariManagementController managementController) { + super(Resource.Type.RootStackSetting, PROPERTY_IDS, KEY_PROPERTY_IDS, managementController); + } + + + @Override + public Set<Resource> getResources(Request request, Predicate predicate) + throws SystemException, UnsupportedPropertyException, + NoSuchResourceException, NoSuchParentResourceException { + + final Set<StackConfigurationRequest> requests = new HashSet<>(); + + if (predicate == null) { + requests.add(getRequest(Collections.emptyMap())); + } else { + for (Map<String, Object> propertyMap : getPropertyMaps(predicate)) { + requests.add(getRequest(propertyMap)); + } + } + + Set<String> requestedIds = getRequestPropertyIds(request, predicate); + + Set<ReadOnlyConfigurationResponse> responses = getResources(new Command<Set<ReadOnlyConfigurationResponse>>() { + @Override + public Set<ReadOnlyConfigurationResponse> invoke() throws AmbariException { + return getManagementController().getReadOnlyStackSettings(requests); + } + }); + + Set<Resource> resources = new HashSet<>(); + + for (ReadOnlyConfigurationResponse response : responses) { + Resource resource = new ResourceImpl(Type.RootStackSetting); + + setResourceProperty(resource, STACK_NAME_PROPERTY_ID, response.getStackName(), requestedIds); + setResourceProperty(resource, STACK_VERSION_PROPERTY_ID, response.getStackVersion(), requestedIds); + setResourceProperty(resource, PROPERTY_NAME_PROPERTY_ID, response.getPropertyName(), requestedIds); + setResourceProperty(resource, PROPERTY_VALUE_PROPERTY_ID, response.getPropertyValue(), requestedIds); + setResourceProperty(resource, PROPERTY_VALUE_ATTRIBUTES_PROPERTY_ID, response.getPropertyValueAttributes(), requestedIds); + setResourceProperty(resource, DEPENDS_ON_PROPERTY_ID, response.getDependsOnProperties(), requestedIds); + setResourceProperty(resource, PROPERTY_DESCRIPTION_PROPERTY_ID, response.getPropertyDescription(), requestedIds); + + //should not be returned if empty + if (StringUtils.isNotEmpty(response.getPropertyDisplayName())) { + setResourceProperty(resource, PROPERTY_DISPLAY_NAME_PROPERTY_ID, response.getPropertyDisplayName(), requestedIds); + } + + setResourceProperty(resource, PROPERTY_PROPERTY_TYPE_PROPERTY_ID, response.getPropertyType(), requestedIds); + + setResourceProperty(resource, PROPERTY_TYPE_PROPERTY_ID, response.getType(), requestedIds); + + setDefaultPropertiesAttributes(resource, requestedIds); + + for (Map.Entry<String, String> attribute : response.getPropertyAttributes().entrySet()) { + setResourceProperty(resource, PropertyHelper.getPropertyId(RESPONSE_KEY, attribute.getKey()), + attribute.getValue(), requestedIds); + } + resources.add(resource); + } + return resources; + } + + /** + * Set default values for properties attributes before applying original ones + * to prevent absence in case of empty attributes map + */ + private void setDefaultPropertiesAttributes(Resource resource, Set<String> requestedIds) { + setResourceProperty(resource, PROPERTY_FINAL_PROPERTY_ID, "false", requestedIds); + } + + private StackConfigurationRequest getRequest(Map<String, Object> properties) { + return new StackConfigurationRequest( + (String) properties.get(STACK_NAME_PROPERTY_ID), + (String) properties.get(STACK_VERSION_PROPERTY_ID), + null, // Call is at stack version level (and not service level). + (String) properties.get(PROPERTY_NAME_PROPERTY_ID)); + } + + @Override + protected Set<String> getPKPropertyIds() { + return pkPropertyIds; + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/adc7060a/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java index 3699cd0..bd6d7bb 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java @@ -101,6 +101,7 @@ public interface Resource { RegistryMpackVersion, Mpack, Stack, + RootStackSetting, StackVersion, ExtensionLink, Extension, @@ -233,6 +234,7 @@ public interface Resource { public static final Type RegistryMpackVersion = InternalType.RegistryMpackVersion.getType(); public static final Type Mpack = InternalType.Mpack.getType(); public static final Type Stack = InternalType.Stack.getType(); + public static final Type RootStackSetting = InternalType.RootStackSetting.getType(); public static final Type StackVersion = InternalType.StackVersion.getType(); public static final Type ExtensionLink = InternalType.ExtensionLink.getType(); public static final Type Extension = InternalType.Extension.getType(); http://git-wip-us.apache.org/repos/asf/ambari/blob/adc7060a/ambari-server/src/main/java/org/apache/ambari/server/resources/ResourceLevelClusterSettingManager.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/resources/ResourceLevelClusterSettingManager.java b/ambari-server/src/main/java/org/apache/ambari/server/resources/ResourceLevelClusterSettingManager.java deleted file mode 100644 index 4cb6cd9..0000000 --- a/ambari-server/src/main/java/org/apache/ambari/server/resources/ResourceLevelClusterSettingManager.java +++ /dev/null @@ -1,168 +0,0 @@ -/** - * 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 - * <p> - * http://www.apache.org/licenses/LICENSE-2.0 - * <p> - * 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. - */ -package org.apache.ambari.server.resources; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import javax.xml.namespace.QName; - -import org.apache.ambari.server.AmbariException; -import org.apache.ambari.server.stack.ConfigurationInfo; -import org.apache.ambari.server.stack.ConfigurationModule; -import org.apache.ambari.server.stack.ModuleFileUnmarshaller; -import org.apache.ambari.server.state.PropertyInfo; -import org.apache.ambari.server.state.stack.ConfigurationXml; -import org.apache.ambari.server.utils.XmlUtils; -import org.apache.commons.io.FileUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.inject.assistedinject.Assisted; -import com.google.inject.assistedinject.AssistedInject; - -public class ResourceLevelClusterSettingManager { - /** - * Used to unmarshal a configuration file to an object representation - */ - private static ModuleFileUnmarshaller unmarshaller = new ModuleFileUnmarshaller(); - - private String clusterSettingsPath; - private static final String CLUSTER_SETTINGS_FILE_NAME = "cluster-settings.xml"; - private static final String clusterSettingsConfigType = "cluster-settings"; - private static File clusterSettingsFile; - private final static Logger LOG = LoggerFactory.getLogger(ResourceLevelClusterSettingManager.class); - private Map<String, Map<String, PropertyInfo>> clusterSettingsMap = new ConcurrentHashMap<>(); - private Map<String, ConfigurationModule> configurationModules = new HashMap<>(); - - @AssistedInject - public ResourceLevelClusterSettingManager(@Assisted("resourcesDirPath") String resourcesDirPath) { - clusterSettingsPath = resourcesDirPath; - clusterSettingsFile = new File(clusterSettingsPath + File.separator + CLUSTER_SETTINGS_FILE_NAME); - populateClusterSettingsXml(); - } - - public Collection<PropertyInfo> getClusterSettingsMap() { - return configurationModules.get("cluster-settings").getModuleInfo().getProperties(); - } - - /** - * Obtain a collection of of configuration modules representing each configuration - * file contained in this configuration directory. - * - * @return collection of configuration modules - */ - public Collection<ConfigurationModule> getConfigurationModules() { - return configurationModules.values(); - } - - /** - * Parses 'cluster-settings.xml' during ambari-server boostrap and (re)start - * Reads from /var/lib/ambari-server/resources - * - * @throws java.io.IOException - */ - private void populateClusterSettingsXml() { - ConfigurationXml config = null; - try { - config = unmarshaller.unmarshal(ConfigurationXml.class, clusterSettingsFile); - ConfigurationInfo configInfo = new ConfigurationInfo(parseProperties(config, clusterSettingsFile.getName()), - parseAttributes(config)); - ConfigurationModule module = new ConfigurationModule(clusterSettingsConfigType, configInfo); - configurationModules.put(clusterSettingsConfigType, module); - } catch (Exception e) { - e.printStackTrace(); - } - - } - - /** - * Parse a configurations type attributes. - * - * @param configuration object representation of a configuration file - * @return collection of attributes for the configuration type - */ - private Map<String, String> parseAttributes(ConfigurationXml configuration) { - Map<String, String> attributes = new HashMap<>(); - for (Map.Entry<QName, String> attribute : configuration.getAttributes().entrySet()) { - attributes.put(attribute.getKey().getLocalPart(), attribute.getValue()); - } - return attributes; - } - - /** - * Parse a configurations properties. - * - * @param configuration object representation of a configuration file - * @param fileName configuration file name - * @return collection of properties - */ - private Collection<PropertyInfo> parseProperties(ConfigurationXml configuration, String fileName) - throws FileNotFoundException, RuntimeException { - List<PropertyInfo> props = new ArrayList<>(); - for (PropertyInfo pi : configuration.getProperties()) { - pi.setFilename(fileName); - if (pi.getPropertyTypes().contains(PropertyInfo.PropertyType.VALUE_FROM_PROPERTY_FILE)) { - if (clusterSettingsPath != null || clusterSettingsPath.isEmpty()) { - String propertyFileType = pi.getPropertyValueAttributes().getPropertyFileType(); - if (clusterSettingsFile.exists() && clusterSettingsFile.isFile()) { - try { - String propertyValue = FileUtils.readFileToString(clusterSettingsFile); - boolean valid = true; - switch (propertyFileType.toLowerCase()) { - case "xml": - if (!XmlUtils.isValidXml(propertyValue)) { - valid = false; - LOG.error("Failed to load value from property file. Property file {} is not a valid XML file", - clusterSettingsFile); - } - break; - case "json": // Not supporting JSON as of now. - case "text": // fallthrough - default: - throw new AmbariException("'" + propertyFileType + "' type file not supported for '" - + clusterSettingsConfigType + "'. File Path : " + clusterSettingsFile.getAbsolutePath()); - } - if (valid) { - pi.setValue(propertyValue); - } - } catch (IOException e) { - LOG.error("Failed to load value from property file {}. Error Message {}", - clusterSettingsFile.getAbsolutePath(), e.getMessage()); - } - } else { - throw new FileNotFoundException("Failed to find '" + CLUSTER_SETTINGS_FILE_NAME + "' file with path : " - + clusterSettingsFile); - } - } else { - throw new RuntimeException("Failed to load value from property file. Properties directory {} does not exist" - + clusterSettingsFile.getAbsolutePath()); - } - } - props.add(pi); - } - return props; - } -} http://git-wip-us.apache.org/repos/asf/ambari/blob/adc7060a/ambari-server/src/main/java/org/apache/ambari/server/resources/ResourceLevelClusterSettingManagerFactory.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/resources/ResourceLevelClusterSettingManagerFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/resources/ResourceLevelClusterSettingManagerFactory.java deleted file mode 100644 index fcda654..0000000 --- a/ambari-server/src/main/java/org/apache/ambari/server/resources/ResourceLevelClusterSettingManagerFactory.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * 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 - * <p> - * http://www.apache.org/licenses/LICENSE-2.0 - * <p> - * 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. - */ -package org.apache.ambari.server.resources; - -import com.google.inject.assistedinject.Assisted; -import com.google.inject.assistedinject.AssistedInject; - -/** - * The {@link ResourceLevelClusterSettingManagerFactory} is used along with {@link AssistedInject} to - * build instances of {@link ResourceLevelClusterSettingManager}. - */ -public interface ResourceLevelClusterSettingManagerFactory { - - /** - * @return a ResourceLevelClusterSetting manager instance. - */ - ResourceLevelClusterSettingManager create(@Assisted("resourcesDirPath") String resourcesDirPath); -} - http://git-wip-us.apache.org/repos/asf/ambari/blob/adc7060a/ambari-server/src/main/java/org/apache/ambari/server/resources/RootLevelSettingsManager.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/resources/RootLevelSettingsManager.java b/ambari-server/src/main/java/org/apache/ambari/server/resources/RootLevelSettingsManager.java new file mode 100644 index 0000000..3b74e69 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/resources/RootLevelSettingsManager.java @@ -0,0 +1,174 @@ +/** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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. + */ +package org.apache.ambari.server.resources; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import javax.xml.namespace.QName; + +import org.apache.ambari.server.AmbariException; +import org.apache.ambari.server.stack.ConfigurationInfo; +import org.apache.ambari.server.stack.ConfigurationModule; +import org.apache.ambari.server.stack.ModuleFileUnmarshaller; +import org.apache.ambari.server.state.PropertyInfo; +import org.apache.ambari.server.state.stack.ConfigurationXml; +import org.apache.ambari.server.utils.XmlUtils; +import org.apache.commons.io.FileUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.inject.assistedinject.Assisted; +import com.google.inject.assistedinject.AssistedInject; + +public class RootLevelSettingsManager { + /** + * Used to unmarshal a configuration file to an object representation + */ + private static ModuleFileUnmarshaller unmarshaller = new ModuleFileUnmarshaller(); + + private String clusterSettingsPath; + private String clusterSettingsFileName; + private String clusterSettingsConfigType; + private static File clusterSettingsFile; + private final static Logger LOG = LoggerFactory.getLogger(RootLevelSettingsManager.class); + private Map<String, Map<String, PropertyInfo>> clusterSettingsMap = new ConcurrentHashMap<>(); + private Map<String, ConfigurationModule> configurationModules = new HashMap<>(); + + @AssistedInject + public RootLevelSettingsManager(@Assisted("directoryPath") String directoryPath, + @Assisted("settingsFileName") String settingsFileName, + @Assisted("settingsTypeName") String settingsTypeName) { + clusterSettingsPath = directoryPath; + clusterSettingsFileName = settingsFileName; + clusterSettingsConfigType = settingsTypeName; + clusterSettingsFile = new File(clusterSettingsPath + File.separator + clusterSettingsFileName); + LOG.info("\n\n\n\n SWAP - clusterSettingsPath = "+clusterSettingsPath+" - clusterSettingsFileName = "+clusterSettingsFileName + +" - clusterSettingsConfigType = "+clusterSettingsFile + "clusterSettingsFile = "+clusterSettingsFile); + populateClusterSettingsXml(); + } + + public Collection<PropertyInfo> getClusterSettingsMap() { + return configurationModules.get(clusterSettingsConfigType).getModuleInfo().getProperties(); + } + + /** + * Obtain a collection of of configuration modules representing each configuration + * file contained in this configuration directory. + * + * @return collection of configuration modules + */ + public Collection<ConfigurationModule> getConfigurationModules() { + return configurationModules.values(); + } + + /** + * Parses 'cluster-settings.xml' during ambari-server boostrap and (re)start + * Reads from /var/lib/ambari-server/resources + * + * @throws java.io.IOException + */ + private void populateClusterSettingsXml() { + ConfigurationXml config = null; + try { + config = unmarshaller.unmarshal(ConfigurationXml.class, clusterSettingsFile); + ConfigurationInfo configInfo = new ConfigurationInfo(parseProperties(config, clusterSettingsFile.getName()), + parseAttributes(config)); + ConfigurationModule module = new ConfigurationModule(clusterSettingsConfigType, configInfo); + configurationModules.put(clusterSettingsConfigType, module); + } catch (Exception e) { + e.printStackTrace(); + } + + } + + /** + * Parse a configurations type attributes. + * + * @param configuration object representation of a configuration file + * @return collection of attributes for the configuration type + */ + private Map<String, String> parseAttributes(ConfigurationXml configuration) { + Map<String, String> attributes = new HashMap<>(); + for (Map.Entry<QName, String> attribute : configuration.getAttributes().entrySet()) { + attributes.put(attribute.getKey().getLocalPart(), attribute.getValue()); + } + return attributes; + } + + /** + * Parse a configurations properties. + * + * @param configuration object representation of a configuration file + * @param fileName configuration file name + * @return collection of properties + */ + private Collection<PropertyInfo> parseProperties(ConfigurationXml configuration, String fileName) + throws FileNotFoundException, RuntimeException { + List<PropertyInfo> props = new ArrayList<>(); + for (PropertyInfo pi : configuration.getProperties()) { + pi.setFilename(fileName); + if (pi.getPropertyTypes().contains(PropertyInfo.PropertyType.VALUE_FROM_PROPERTY_FILE)) { + if (clusterSettingsPath != null || clusterSettingsPath.isEmpty()) { + String propertyFileType = pi.getPropertyValueAttributes().getPropertyFileType(); + if (clusterSettingsFile.exists() && clusterSettingsFile.isFile()) { + try { + String propertyValue = FileUtils.readFileToString(clusterSettingsFile); + boolean valid = true; + switch (propertyFileType.toLowerCase()) { + case "xml": + if (!XmlUtils.isValidXml(propertyValue)) { + valid = false; + LOG.error("Failed to load value from property file. Property file {} is not a valid XML file", + clusterSettingsFile); + } + break; + case "json": // Not supporting JSON as of now. + case "text": // fallthrough + default: + throw new AmbariException("'" + propertyFileType + "' type file not supported for '" + + clusterSettingsConfigType + "'. File Path : " + clusterSettingsFile.getAbsolutePath()); + } + if (valid) { + pi.setValue(propertyValue); + } + } catch (IOException e) { + LOG.error("Failed to load value from property file {}. Error Message {}", + clusterSettingsFile.getAbsolutePath(), e.getMessage()); + } + } else { + throw new FileNotFoundException("Failed to find '" + clusterSettingsFileName + "' file with path : " + + clusterSettingsFile); + } + } else { + throw new RuntimeException("Failed to load value from property file. Properties directory {} does not exist" + + clusterSettingsFile.getAbsolutePath()); + } + } + props.add(pi); + } + return props; + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/adc7060a/ambari-server/src/main/java/org/apache/ambari/server/resources/RootLevelSettingsManagerFactory.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/resources/RootLevelSettingsManagerFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/resources/RootLevelSettingsManagerFactory.java new file mode 100644 index 0000000..5a94b12 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/resources/RootLevelSettingsManagerFactory.java @@ -0,0 +1,36 @@ +/** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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. + */ +package org.apache.ambari.server.resources; + +import com.google.inject.assistedinject.Assisted; +import com.google.inject.assistedinject.AssistedInject; + +/** + * The {@link RootLevelSettingsManagerFactory} is used along with {@link AssistedInject} to + * build instances of {@link RootLevelSettingsManager}. + */ +public interface RootLevelSettingsManagerFactory { + + /** + * @return a ResourceLevelClusterSetting manager instance. + */ + RootLevelSettingsManager create(@Assisted("directoryPath") String directoryPath, + @Assisted("settingsFileName") String settingsFileName, + @Assisted("settingsTypeName") String settingsTypeName); +} + http://git-wip-us.apache.org/repos/asf/ambari/blob/adc7060a/ambari-server/src/main/java/org/apache/ambari/server/stack/StackModule.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/stack/StackModule.java b/ambari-server/src/main/java/org/apache/ambari/server/stack/StackModule.java index 878415b..dc16ae2 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/stack/StackModule.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/stack/StackModule.java @@ -650,6 +650,10 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V */ private void populateConfigurationModules() { //todo: can't exclude types in stack config + // TODO : Correct naming for 'SERVICE_CONFIG_FOLDER_NAME' and 'SERVICE_PROPERTIES_FOLDER_NAME', + // as we are currently in stack version folder (not in services). It's reuse of macros, + // which is misleading given that both stack's version and services dirs can have 'configurations' and 'properties' + // folder. ConfigurationDirectory configDirectory = stackDirectory.getConfigurationDirectory( StackDirectory.SERVICE_CONFIG_FOLDER_NAME, StackDirectory.SERVICE_PROPERTIES_FOLDER_NAME); @@ -659,8 +663,20 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V stackInfo.setValid(config.isValid()); stackInfo.addErrors(config.getErrors()); } - stackInfo.getProperties().addAll(config.getModuleInfo().getProperties()); - stackInfo.setConfigTypeAttributes(config.getConfigType(), config.getModuleInfo().getAttributes()); + // TODO : Remove this switch case as part of removing case "cluster-env" as part of AMBARI-22197, where we are + // phasing out cluster-env entirely. + switch(config.getConfigType()) { + case "settings": + stackInfo.setStackSettings((List<PropertyInfo>) config.getModuleInfo().getProperties()); + stackInfo.setStackSettingsConfigTypeAttributes(config.getConfigType(), config.getModuleInfo().getAttributes()); + break; + case "cluster-env": + stackInfo.getProperties().addAll(config.getModuleInfo().getProperties()); + stackInfo.setConfigTypeAttributes(config.getConfigType(), config.getModuleInfo().getAttributes()); + break; + default: + break; + } configurationModules.put(config.getConfigType(), config); } } http://git-wip-us.apache.org/repos/asf/ambari/blob/adc7060a/ambari-server/src/main/java/org/apache/ambari/server/state/StackInfo.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/StackInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/state/StackInfo.java index 07d28ce..df0d2dc 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/StackInfo.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/StackInfo.java @@ -60,6 +60,11 @@ public class StackInfo implements Comparable<StackInfo>, Validable { // stack-level properties private List<PropertyInfo> properties; private Map<String, Map<String, Map<String, String>>> configTypes; + + // Gets information from stacks/<stack-name>/<version>/settings.xml + private List<PropertyInfo> stackSettings; + private Map<String, Map<String, Map<String, String>>> stackSettingsConfigTypes; + private Map<String, UpgradePack> upgradePacks; private ConfigUpgradePack configUpgradePack; private StackRoleCommandOrder roleCommandOrder; @@ -245,6 +250,12 @@ public class StackInfo implements Comparable<StackInfo>, Validable { this.properties = properties; } + public List<PropertyInfo> getStackSettings() { return stackSettings; } + + public void setStackSettings(List<PropertyInfo> stackSettings) { + this.stackSettings = stackSettings; + } + /** * Obtain the config types associated with this stack. * The returned map is an unmodifiable view. @@ -272,6 +283,32 @@ public class StackInfo implements Comparable<StackInfo>, Validable { } /** + * Obtain the config types associated with this stack's settings. + * The returned map is an unmodifiable view. + * @return copy of the map of config types associated with this stack's settings + */ + public synchronized Map<String, Map<String, Map<String, String>>> getStackSettingsConfigTypeAttributes() { + return stackSettingsConfigTypes == null ? + Collections.emptyMap() : + Collections.unmodifiableMap(stackSettingsConfigTypes); + } + + + /** + * Add the given type and set it's attributes. + * + * @param type configuration type + * @param typeAttributes attributes associated with the type + */ + public synchronized void setStackSettingsConfigTypeAttributes(String type, Map<String, Map<String, String>> typeAttributes) { + if (this.stackSettingsConfigTypes == null) { + stackSettingsConfigTypes = new HashMap<>(); + } + // todo: no exclusion mechanism for stack config types + stackSettingsConfigTypes.put(type, typeAttributes); + } + + /** * Set all types and associated attributes. Any previously existing types and * attributes are removed prior to setting the new values. * http://git-wip-us.apache.org/repos/asf/ambari/blob/adc7060a/ambari-server/src/main/resources/stacks/HDP/3.0/configuration/settings.xml ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/stacks/HDP/3.0/configuration/settings.xml b/ambari-server/src/main/resources/stacks/HDP/3.0/configuration/settings.xml new file mode 100644 index 0000000..97e4063 --- /dev/null +++ b/ambari-server/src/main/resources/stacks/HDP/3.0/configuration/settings.xml @@ -0,0 +1,91 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/xsl" href="configuration.xsl"?> +<!-- +/** + * 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. + */ +--> +<configuration> + <!-- Define stack_name property in the base stack. DO NOT override this property for each stack version --> + <property> + <name>stack_name</name> + <value>HDP</value> + <description>The name of the stack.</description> + <value-attributes> + <read-only>true</read-only> + <overridable>false</overridable> + <visible>false</visible> + </value-attributes> + <on-ambari-upgrade add="true"/> + </property> + <!-- Define stack_tools property in the base stack. DO NOT override this property for each stack version --> + <property> + <name>stack_tools</name> + <value/> + <description>Stack specific tools</description> + <property-type>VALUE_FROM_PROPERTY_FILE</property-type> + <value-attributes> + <property-file-name>stack_tools.json</property-file-name> + <property-file-type>json</property-file-type> + <read-only>true</read-only> + <overridable>false</overridable> + <visible>false</visible> + </value-attributes> + <on-ambari-upgrade add="true"/> + </property> + <!-- Define stack_features property in the base stack. DO NOT override this property for each stack version --> + <property> + <name>stack_features</name> + <value/> + <description>List of features supported by the stack</description> + <property-type>VALUE_FROM_PROPERTY_FILE</property-type> + <value-attributes> + <property-file-name>stack_features.json</property-file-name> + <property-file-type>json</property-file-type> + <read-only>true</read-only> + <overridable>false</overridable> + <visible>false</visible> + </value-attributes> + <on-ambari-upgrade add="true"/> + </property> + <!-- Define stack_packages property in the base stack. DO NOT override this property for each stack version --> + <property> + <name>stack_packages</name> + <value/> + <description>Associations between component and stack-select tools.</description> + <property-type>VALUE_FROM_PROPERTY_FILE</property-type> + <value-attributes> + <property-file-name>stack_packages.json</property-file-name> + <property-file-type>json</property-file-type> + <read-only>true</read-only> + <overridable>false</overridable> + <visible>false</visible> + </value-attributes> + <on-ambari-upgrade add="true"/> + </property> + <property> + <name>stack_root</name> + <value>{"HDP":"/usr/hdp"}</value> + <description>JSON which defines the stack root by stack name</description> + <value-attributes> + <read-only>true</read-only> + <overridable>false</overridable> + <visible>false</visible> + </value-attributes> + <on-ambari-upgrade add="true"/> + </property> +</configuration> \ No newline at end of file
