All Downloads are FREE. Search and download functionalities are using the official Maven repository.

brooklyn.entity.group.DynamicCluster Maven / Gradle / Ivy

There is a newer version: 0.7.0-M1
Show newest version
package brooklyn.entity.group;

import groovy.lang.Closure;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;

import brooklyn.config.ConfigKey;
import brooklyn.entity.Entity;
import brooklyn.entity.Group;
import brooklyn.entity.annotation.Effector;
import brooklyn.entity.annotation.EffectorParam;
import brooklyn.entity.basic.AbstractGroup;
import brooklyn.entity.basic.Attributes;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.EntityFactory;
import brooklyn.entity.basic.Lifecycle;
import brooklyn.entity.basic.MethodEffector;
import brooklyn.entity.group.zoneaware.BalancingNodePlacementStrategy;
import brooklyn.entity.group.zoneaware.ProportionalZoneFailureDetector;
import brooklyn.entity.proxying.EntitySpec;
import brooklyn.entity.proxying.ImplementedBy;
import brooklyn.event.AttributeSensor;
import brooklyn.event.basic.BasicAttributeSensor;
import brooklyn.event.basic.BasicConfigKey;
import brooklyn.event.basic.BasicNotificationSensor;
import brooklyn.location.Location;
import brooklyn.util.GroovyJavaMethods;
import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.time.Duration;

import com.google.common.annotations.Beta;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Multimap;

/**
 * A cluster of entities that can dynamically increase or decrease the number of entities.
 */
@ImplementedBy(DynamicClusterImpl.class)
public interface DynamicCluster extends AbstractGroup, Cluster {

    @Beta
    public interface NodePlacementStrategy {
        List locationsForAdditions(Multimap currentMembers, Collection locs, int numToAdd);
        List entitiesToRemove(Multimap currentMembers, int numToRemove);
    }
    
    @Beta
    public interface ZoneFailureDetector {
        // TODO Would like to add entity-down reporting
        // TODO Should we push any of this into the AvailabilityZoneExtension, rather than on the dynamic cluster?
        void onStartupSuccess(Location loc, Entity entity);
        void onStartupFailure(Location loc, Entity entity, Throwable cause);
        boolean hasFailed(Location loc);
    }
    
    public static final MethodEffector REPLACE_MEMBER = new MethodEffector(DynamicCluster.class, "replaceMember");

    @SetFromFlag("quarantineFailedEntities")
    public static final ConfigKey QUARANTINE_FAILED_ENTITIES = new BasicConfigKey(
            Boolean.class, "dynamiccluster.quarantineFailedEntities", "Whether to guarantine entities that fail to start, or to try to clean them up", false);

    public static final AttributeSensor SERVICE_STATE = Attributes.SERVICE_STATE;

    public static final BasicNotificationSensor ENTITY_QUARANTINED = new BasicNotificationSensor(Entity.class, "dynamiccluster.entityQuarantined", "Entity failed to start, and has been quarantined");

    public static final AttributeSensor QUARANTINE_GROUP = new BasicAttributeSensor(Group.class, "dynamiccluster.quarantineGroup", "Group of quarantined entities that failed to start");
    
    @SetFromFlag("initialQuorumSize")
    ConfigKey INITIAL_QUORUM_SIZE = ConfigKeys.newIntegerConfigKey(
            "cluster.initial.quorumSize",
            "Initial cluster quorum size - number of initial nodes that must have been successfully started to report success (if < 0, then use value of INITIAL_SIZE)", 
            -1);

    @SetFromFlag("memberSpec")
    public static final ConfigKey> MEMBER_SPEC = new BasicConfigKey(
            EntitySpec.class, "dynamiccluster.memberspec", "entity spec for creating new cluster members", null);

    @SetFromFlag("factory")
    public static final ConfigKey FACTORY = new BasicConfigKey(
            EntityFactory.class, "dynamiccluster.factory", "factory for creating new cluster members", null);

    @SetFromFlag("removalStrategy")
    public static final ConfigKey, Entity>> REMOVAL_STRATEGY = new BasicConfigKey(
            Function.class, "dynamiccluster.removalstrategy", "strategy for deciding what to remove when down-sizing", null);
    
    @SetFromFlag("customChildFlags")
    public static final ConfigKey CUSTOM_CHILD_FLAGS = new BasicConfigKey(
            Map.class, "dynamiccluster.customChildFlags", "Additional flags to be passed to children when they are being created", ImmutableMap.of());

    @SetFromFlag("enableAvailabilityZones")
    ConfigKey ENABLE_AVAILABILITY_ZONES = ConfigKeys.newBooleanConfigKey(
            "dynamiccluster.zone.enable", "Whether to use availability zones, or just deploy everything into the generic location", false);
    
    @SetFromFlag("zoneFailureDetector")
    ConfigKey ZONE_FAILURE_DETECTOR = ConfigKeys.newConfigKey(
            ZoneFailureDetector.class, "dynamiccluster.zone.failureDetector", "Zone failure detector", new ProportionalZoneFailureDetector(2, Duration.ONE_HOUR, 0.9));
    
    @SetFromFlag("zonePlacementStrategy")
    ConfigKey ZONE_PLACEMENT_STRATEGY = ConfigKeys.newConfigKey(
            NodePlacementStrategy.class, "dynamiccluster.zone.placementStrategy", "Node placement strategy", new BalancingNodePlacementStrategy());
    
    @SetFromFlag("availabilityZoneNames")
    ConfigKey> AVAILABILITY_ZONE_NAMES = (ConfigKey) ConfigKeys.newConfigKey(
            Collection.class, "dynamiccluster.availabilityZones", "availability zones to use (if non-null, overrides other configuration)", null);
    
    @SetFromFlag("numAvailabilityZones")
    ConfigKey NUM_AVAILABILITY_ZONES = ConfigKeys.newIntegerConfigKey(
            "dynamiccluster.numAvailabilityZones", "number of availability zones to use (will attempt to auto-discover this number)", 3);

    AttributeSensor> SUB_LOCATIONS = new BasicAttributeSensor(List.class, "dynamiccluster.subLocations", "Locations for each availability zone to use");
    
    AttributeSensor> FAILED_SUB_LOCATIONS = new BasicAttributeSensor(Set.class, "dynamiccluster.failedSubLocations", "Sub locations that seem to have failed");
    
    /**
     * 
     * @param memberId
     * @throws NoSuchElementException If entity cannot be resolved, or it is not a member 
     */
    @Effector(description="Replaces the entity with the given ID, if it is a member; first adds a new member, then removes this one. "+
            "Returns id of the new entity; or throws exception if couldn't be replaced.")
    public String replaceMember(@EffectorParam(name="memberId", description="The entity id of a member to be replaced") String memberId);
    
    public void setRemovalStrategy(Function, Entity> val);

    /**
     * @deprecated since 0.6.0; use {@link #setRemovalStrategy(Function)}, along with {@link GroovyJavaMethods#functionFromClosure(Closure)}
     */
    public void setRemovalStrategy(Closure val);
    
    void setZonePlacementStrategy(NodePlacementStrategy val);
    
    public void setZoneFailureDetector(ZoneFailureDetector val);

    public void setMemberSpec(EntitySpec memberSpec);
    
    public void setFactory(EntityFactory factory);
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy