blob: 0e210a58b77f8795ba3b274fb0de4acfbe0ebb5f [file] [log] [blame]
/**
* 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.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.DuplicateResourceException;
import org.apache.ambari.server.ObjectNotFoundException;
import org.apache.ambari.server.ParentObjectNotFoundException;
import org.apache.ambari.server.controller.AmbariManagementController;
import org.apache.ambari.server.controller.RequestStatusResponse;
import org.apache.ambari.server.controller.predicate.BasePredicate;
import org.apache.ambari.server.controller.spi.*;
import org.apache.ambari.server.controller.utilities.PredicateHelper;
import org.apache.ambari.server.controller.utilities.PropertyHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Basic resource provider implementation that maps to a management controller.
*/
public abstract class ResourceProviderImpl implements ResourceProvider, ObservableResourceProvider {
/**
* The set of property ids supported by this resource provider.
*/
private final Set<String> propertyIds;
/**
* The management controller to delegate to.
*/
private final AmbariManagementController managementController;
/**
* Key property mapping by resource type.
*/
private final Map<Resource.Type, String> keyPropertyIds;
/**
* Observers of this observable resource provider.
*/
private final Set<ResourceProviderObserver> observers = new HashSet<ResourceProviderObserver>();
protected final static Logger LOG =
LoggerFactory.getLogger(ResourceProviderImpl.class);
// ----- Constructors ------------------------------------------------------
/**
* Create a new resource provider for the given management controller.
*
* @param propertyIds the property ids
* @param keyPropertyIds the key property ids
* @param managementController the management controller
*/
protected ResourceProviderImpl(Set<String> propertyIds,
Map<Resource.Type, String> keyPropertyIds,
AmbariManagementController managementController) {
this.propertyIds = propertyIds;
this.keyPropertyIds = keyPropertyIds;
this.managementController = managementController;
}
// ----- ResourceProvider --------------------------------------------------
@Override
public Set<String> getPropertyIdsForSchema() {
return propertyIds;
}
@Override
public Map<Resource.Type, String> getKeyPropertyIds() {
return keyPropertyIds;
}
@Override
public Set<String> checkPropertyIds(Set<String> propertyIds) {
if (!this.propertyIds.containsAll(propertyIds)) {
Set<String> unsupportedPropertyIds = new HashSet<String>(propertyIds);
unsupportedPropertyIds.removeAll(this.propertyIds);
return unsupportedPropertyIds;
}
return Collections.emptySet();
}
// ----- ObservableResourceProvider ----------------------------------------
@Override
public void updateObservers(ResourceProviderEvent event) {
for (ResourceProviderObserver observer : observers) {
observer.update(event);
}
}
@Override
public void addObserver(ResourceProviderObserver observer) {
observers.add(observer);
}
// ----- accessors ---------------------------------------------------------
/**
* Get the associated property ids.
*
* @return the property ids
*/
protected Set<String> getPropertyIds() {
return propertyIds;
}
/**
* Get the associated management controller.
*
* @return the associated management controller
*/
protected AmbariManagementController getManagementController() {
return managementController;
}
// ----- utility methods ---------------------------------------------------
/**
* Get the set of property ids that uniquely identify the resources
* of this provider.
*
* @return the set of primary key properties
*/
protected abstract Set<String> getPKPropertyIds();
/**
* Notify all listeners of a creation event.
*
* @param type the type of the resources being created
* @param request the request used to create the resources
*/
protected void notifyCreate(Resource.Type type, Request request) {
updateObservers(new ResourceProviderEvent(type, ResourceProviderEvent.Type.Create, request, null));
}
/**
* Notify all listeners of a update event.
*
* @param type the type of the resources being updated
* @param request the request used to update the resources
* @param predicate the predicate used to update the resources
*/
protected void notifyUpdate(Resource.Type type, Request request, Predicate predicate) {
updateObservers(new ResourceProviderEvent(type, ResourceProviderEvent.Type.Update, request, predicate));
}
/**
* Notify all listeners of a delete event.
*
* @param type the type of the resources being deleted
* @param predicate the predicate used to delete the resources
*/
protected void notifyDelete(Resource.Type type, Predicate predicate) {
updateObservers(new ResourceProviderEvent(type, ResourceProviderEvent.Type.Delete, null, predicate));
}
/**
* Get a set of properties from the given property map and predicate.
*
* @param givenPredicate the predicate
*
* @return the set of properties used to build request objects
*/
protected Set<Map<String, Object>> getPropertyMaps(Predicate givenPredicate)
throws UnsupportedPropertyException, SystemException, NoSuchResourceException, NoSuchParentResourceException {
SimplifyingPredicateVisitor visitor = new SimplifyingPredicateVisitor(propertyIds);
PredicateHelper.visit(givenPredicate, visitor);
List<BasePredicate> predicates = visitor.getSimplifiedPredicates();
Set<Map<String, Object>> propertyMaps = new HashSet<Map<String, Object>>();
for (BasePredicate predicate : predicates) {
propertyMaps.add(PredicateHelper.getProperties(predicate));
}
return propertyMaps;
}
/**
* Get a set of properties from the given property map and predicate.
*
* @param requestPropertyMap the request properties (for update)
* @param givenPredicate the predicate
*
* @return the set of properties used to build request objects
*/
protected Set<Map<String, Object>> getPropertyMaps(Map<String, Object> requestPropertyMap,
Predicate givenPredicate)
throws UnsupportedPropertyException, SystemException, NoSuchResourceException, NoSuchParentResourceException {
Set<Map<String, Object>> propertyMaps = new HashSet<Map<String, Object>>();
Set<String> pkPropertyIds = getPKPropertyIds();
if (requestPropertyMap != null && !pkPropertyIds.equals(PredicateHelper.getPropertyIds(givenPredicate))) {
for (Resource resource : getResources(PropertyHelper.getReadRequest(pkPropertyIds), givenPredicate)) {
Map<String, Object> propertyMap = new HashMap<String, Object>(PropertyHelper.getProperties(resource));
propertyMap.putAll(requestPropertyMap);
propertyMaps.add(propertyMap);
}
}
else {
Map<String, Object> propertyMap = new HashMap<String, Object>(PredicateHelper.getProperties(givenPredicate));
propertyMap.putAll(requestPropertyMap);
propertyMaps.add(propertyMap);
}
return propertyMaps;
}
/**
* Get a request status
*
* @return the request status
*/
protected RequestStatus getRequestStatus(RequestStatusResponse response) {
if (response != null){
Resource requestResource = new ResourceImpl(Resource.Type.Request);
requestResource.setProperty(PropertyHelper.getPropertyId("Requests", "id"), response.getRequestId());
// TODO : how do we tell what a request status is?
// for now make everything InProgress
requestResource.setProperty(PropertyHelper.getPropertyId("Requests", "status"), "InProgress");
return new RequestStatusImpl(requestResource);
}
return new RequestStatusImpl(null);
}
/**
* Set a property value on the given resource for the given id and value.
* Make sure that the id is in the given set of requested ids.
*
* @param resource the resource
* @param propertyId the property id
* @param value the value to set
* @param requestedIds the requested set of property ids
*/
protected static void setResourceProperty(Resource resource, String propertyId, Object value, Set<String> requestedIds) {
if (requestedIds.contains(propertyId)) {
if (LOG.isDebugEnabled()) {
LOG.debug("Setting property for resource"
+ ", resourceType=" + resource.getType()
+ ", propertyId=" + propertyId
+ ", value=" + value);
}
resource.setProperty(propertyId, value);
}
else {
if (LOG.isDebugEnabled()) {
LOG.debug("Skipping property for resource as not in requestedIds"
+ ", resourceType=" + resource.getType()
+ ", propertyId=" + propertyId
+ ", value=" + value);
}
}
}
/**
* Factory method for obtaining a resource provider based on a given type and management controller.
*
*
* @param type the resource type
* @param propertyIds the property ids
* @param managementController the management controller
*
* @return a new resource provider
*/
public static ResourceProvider getResourceProvider(Resource.Type type,
Set<String> propertyIds,
Map<Resource.Type, String> keyPropertyIds,
AmbariManagementController managementController) {
switch (type) {
case Cluster:
return new ClusterResourceProvider(propertyIds, keyPropertyIds, managementController);
case Service:
return new ServiceResourceProvider(propertyIds, keyPropertyIds, managementController);
case Component:
return new ComponentResourceProvider(propertyIds, keyPropertyIds, managementController);
case Host:
return new HostResourceProvider(propertyIds, keyPropertyIds, managementController);
case HostComponent:
return new HostComponentResourceProvider(propertyIds, keyPropertyIds, managementController);
case Configuration:
return new ConfigurationResourceProvider(propertyIds, keyPropertyIds, managementController);
case Action:
return new ActionResourceProvider(propertyIds, keyPropertyIds, managementController);
case Request:
return new RequestResourceProvider(propertyIds, keyPropertyIds, managementController);
case Task:
return new TaskResourceProvider(propertyIds, keyPropertyIds, managementController);
case User:
return new UserResourceProvider(propertyIds, keyPropertyIds, managementController);
default:
throw new IllegalArgumentException("Unknown type " + type);
}
}
protected <T> T createResources(Command<T> command)
throws SystemException, ResourceAlreadyExistsException, NoSuchParentResourceException {
try {
return command.invoke();
} catch (ParentObjectNotFoundException e) {
throw new NoSuchParentResourceException(e.getMessage(), e);
} catch (DuplicateResourceException e) {
throw new ResourceAlreadyExistsException(e.getMessage());
} catch (AmbariException e) {
if (LOG.isErrorEnabled()) {
LOG.error("Caught AmbariException when creating a resource", e);
}
throw new SystemException("An internal system exception occurred: " + e.getMessage(), e);
}
}
protected <T> T getResources (Command<T> command)
throws SystemException, NoSuchResourceException, NoSuchParentResourceException {
try {
return command.invoke();
} catch (ObjectNotFoundException e) {
throw new NoSuchResourceException("The requested resource doesn't exist: " + e.getMessage(), e);
} catch (ParentObjectNotFoundException e) {
throw new NoSuchParentResourceException(e.getMessage(), e);
} catch (AmbariException e) {
if (LOG.isErrorEnabled()) {
LOG.error("Caught AmbariException when getting a resource", e);
}
throw new SystemException("An internal system exception occurred: " + e.getMessage(), e);
}
}
protected <T> T modifyResources (Command<T> command)
throws SystemException, NoSuchResourceException, NoSuchParentResourceException {
try {
return command.invoke();
} catch (ObjectNotFoundException e) {
throw new NoSuchResourceException("The specified resource doesn't exist: " + e.getMessage(), e);
} catch (ParentObjectNotFoundException e) {
throw new NoSuchParentResourceException(e.getMessage(), e);
} catch (AmbariException e) {
if (LOG.isErrorEnabled()) {
LOG.error("Caught AmbariException when modifying a resource", e);
}
throw new SystemException("An internal system exception occurred: " + e.getMessage(), e);
}
}
protected interface Command<T> {
public T invoke() throws AmbariException;
}
}