/*************************************************************************
* Copyright 2009-2016 Eucalyptus Systems, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*
* Please contact Eucalyptus Systems, Inc., 6755 Hollister Ave., Goleta
* CA 93117, USA or visit http://www.eucalyptus.com/licenses/ if you need
* additional information or have any questions.
************************************************************************/
package com.eucalyptus.autoscaling.common.internal.groups;
import static com.eucalyptus.autoscaling.common.AutoScalingMetadata.AutoScalingGroupMetadata;
import static com.google.common.base.Strings.emptyToNull;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import javax.persistence.EntityTransaction;
import com.eucalyptus.autoscaling.common.AutoScalingMetadatas;
import com.eucalyptus.autoscaling.common.msgs.AutoScalingGroupType;
import com.eucalyptus.autoscaling.common.msgs.AvailabilityZones;
import com.eucalyptus.autoscaling.common.msgs.EnabledMetrics;
import com.eucalyptus.autoscaling.common.msgs.Instance;
import com.eucalyptus.autoscaling.common.msgs.Instances;
import com.eucalyptus.autoscaling.common.msgs.LoadBalancerNames;
import com.eucalyptus.autoscaling.common.msgs.ProcessType;
import com.eucalyptus.autoscaling.common.msgs.SuspendedProcessType;
import com.eucalyptus.autoscaling.common.msgs.SuspendedProcesses;
import com.eucalyptus.autoscaling.common.msgs.TagType;
import com.eucalyptus.autoscaling.common.msgs.TerminationPolicies;
import com.eucalyptus.autoscaling.common.internal.configurations.LaunchConfiguration;
import com.eucalyptus.autoscaling.common.internal.instances.AutoScalingInstance;
import com.eucalyptus.autoscaling.common.internal.metadata.AutoScalingMetadataException;
import com.eucalyptus.autoscaling.common.internal.tags.AutoScalingGroupTag;
import com.eucalyptus.entities.Entities;
import com.eucalyptus.util.Callback;
import com.eucalyptus.auth.principal.OwnerFullName;
import com.eucalyptus.util.RestrictedTypes;
import com.eucalyptus.util.Strings;
import com.eucalyptus.util.TypeMapper;
import com.eucalyptus.util.TypeMappers;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Objects;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Ordering;
/**
*
*/
public abstract class AutoScalingGroups {
public enum MonitoringSelector {
Set1( "0", "1", "2" ),
Set2( "3", "4", "5" ),
Set3( "6", "7", "8" ),
Set4( "9", "a", "b" ),
Set5( "c", "d" ),
Set6( "e", "f" ),
;
private final ImmutableSet<String> suffixes;
MonitoringSelector( String... idSuffixes ) {
this.suffixes = ImmutableSet.copyOf( idSuffixes );
}
Set<String> suffixes( ) {
return suffixes;
}
}
public abstract <T> List<T> list( OwnerFullName ownerFullName,
Predicate<? super AutoScalingGroup> filter,
Function<? super AutoScalingGroup,T> transform ) throws AutoScalingMetadataException;
public abstract <T> List<T> listRequiringScaling( Function<? super AutoScalingGroup,T> transform ) throws AutoScalingMetadataException;
public abstract <T> List<T> listRequiringInstanceReplacement( Function<? super AutoScalingGroup,T> transform ) throws AutoScalingMetadataException;
public abstract <T> List<T> listRequiringMonitoring( Set<MonitoringSelector> selectors,
Function<? super AutoScalingGroup,T> transform ) throws AutoScalingMetadataException;
public abstract <T> T lookup( OwnerFullName ownerFullName,
String autoScalingGroupName,
Function<? super AutoScalingGroup,T> transform ) throws AutoScalingMetadataException;
public abstract void update( OwnerFullName ownerFullName,
String autoScalingGroupName,
Callback<AutoScalingGroup> groupUpdateCallback ) throws AutoScalingMetadataException;
public abstract void markScalingRequiredForZones( Set<String> availabilityZones ) throws AutoScalingMetadataException;
public abstract boolean delete( AutoScalingGroupMetadata autoScalingGroup ) throws AutoScalingMetadataException;
public abstract AutoScalingGroup save( AutoScalingGroup autoScalingGroup ) throws AutoScalingMetadataException;
public final PersistingBuilder create( final OwnerFullName ownerFullName,
final String autoScalingGroupName,
final LaunchConfiguration launchConfiguration,
final Integer minSize,
final Integer maxSize ) {
return new PersistingBuilder( this, ownerFullName, autoScalingGroupName, launchConfiguration, minSize, maxSize );
}
public static class PersistingBuilder extends AutoScalingGroup.BaseBuilder<PersistingBuilder> {
private final AutoScalingGroups autoScalingGroups;
PersistingBuilder( final AutoScalingGroups autoScalingGroups,
final OwnerFullName ownerFullName,
final String name,
final LaunchConfiguration launchConfiguration,
final Integer minSize,
final Integer maxSize ) {
super( ownerFullName, name, launchConfiguration, minSize, maxSize );
this.autoScalingGroups = autoScalingGroups;
}
@Override
protected PersistingBuilder builder() {
return this;
}
public AutoScalingGroup persist() throws AutoScalingMetadataException {
return autoScalingGroups.save( build() );
}
}
@TypeMapper
public enum AutoScalingGroupTransform implements Function<AutoScalingGroup, AutoScalingGroupType> {
INSTANCE;
@Override
public AutoScalingGroupType apply( final AutoScalingGroup group ) {
final AutoScalingGroupType type = new AutoScalingGroupType();
type.setAutoScalingGroupARN( group.getArn() );
type.setAutoScalingGroupName( group.getAutoScalingGroupName() );
type.setAvailabilityZones( new AvailabilityZones( group.getAvailabilityZones() ) );
type.setVpcZoneIdentifier( emptyToNull( Joiner.on( ',' ).join( group.getSubnetIdByZone().values( ) ) ) );
type.setCreatedTime( group.getCreationTimestamp() );
type.setDefaultCooldown( group.getDefaultCooldown() );
type.setDesiredCapacity( group.getDesiredCapacity() );
type.setEnabledMetrics( new EnabledMetrics( group.getEnabledMetrics() == null ?
null :
Ordering.natural().sortedCopy( Iterables.transform( group.getEnabledMetrics(), Strings.toStringFunction() ) ) ) );
type.setHealthCheckGracePeriod( group.getHealthCheckGracePeriod() );
type.setHealthCheckType( Strings.toString( group.getHealthCheckType() ) );
type.setLaunchConfigurationName( AutoScalingMetadatas.toDisplayName().apply( group.getLaunchConfiguration() ) );
type.setLoadBalancerNames( new LoadBalancerNames( group.getLoadBalancerNames() ) );
type.setMaxSize( group.getMaxSize() );
type.setMinSize( group.getMinSize() );
type.setNewInstancesProtectedFromScaleIn( group.getNewInstancesProtectedFromScaleIn( ) );
final Collection<SuspendedProcess> suspendedProcesses = group.getSuspendedProcesses();
if ( suspendedProcesses != null && !suspendedProcesses.isEmpty() ) {
type.setSuspendedProcesses( new SuspendedProcesses() );
Iterables.addAll(
type.getSuspendedProcesses().getMember(),
Iterables.transform(
suspendedProcesses,
TypeMappers.lookup(SuspendedProcess.class, SuspendedProcessType.class ) ) );
}
type.setTerminationPolicies( new TerminationPolicies( group.getTerminationPolicies() == null ?
null :
Collections2.transform( group.getTerminationPolicies(), Strings.toStringFunction() ) ) );
if ( group.getAutoScalingInstances() != null && !group.getAutoScalingInstances().isEmpty() ) {
type.setInstances( new Instances() );
Iterables.addAll( type.getInstances().getMember(),
Iterables.transform(
group.getAutoScalingInstances(),
TypeMappers.lookup( AutoScalingInstance.class, Instance.class ) ) );
}
return type;
}
}
@TypeMapper
public enum AutoScalingGroupMinimumViewTransform implements Function<AutoScalingGroup, AutoScalingGroupMinimumView> {
INSTANCE;
@Override
public AutoScalingGroupMinimumView apply( final AutoScalingGroup group ) {
return new AutoScalingGroupMinimumView( group );
}
}
@TypeMapper
public enum AutoScalingGroupCoreViewTransform implements Function<AutoScalingGroup, AutoScalingGroupCoreView> {
INSTANCE;
@Override
public AutoScalingGroupCoreView apply( final AutoScalingGroup group ) {
return new AutoScalingGroupCoreView( group );
}
}
@TypeMapper
public enum AutoScalingGroupScalingViewTransform implements Function<AutoScalingGroup, AutoScalingGroupScalingView> {
INSTANCE;
@Override
public AutoScalingGroupScalingView apply( final AutoScalingGroup group ) {
return new AutoScalingGroupScalingView( group );
}
}
@TypeMapper
public enum AutoScalingGroupMetricsViewTransform implements Function<AutoScalingGroup, AutoScalingGroupMetricsView> {
INSTANCE;
@Override
public AutoScalingGroupMetricsView apply( final AutoScalingGroup group ) {
return new AutoScalingGroupMetricsView( group );
}
}
@TypeMapper
public enum SuspendedProcessTransform implements Function<SuspendedProcess, SuspendedProcessType> {
INSTANCE;
@Override
public SuspendedProcessType apply( final SuspendedProcess suspendedProcess ) {
final SuspendedProcessType suspendedProcessType = new SuspendedProcessType();
suspendedProcessType.setProcessName( suspendedProcess.getScalingProcessType().toString() );
suspendedProcessType.setSuspensionReason( suspendedProcess.getReason() );
return suspendedProcessType;
}
}
@TypeMapper
public enum ScalingProcessTypeTransform implements Function<ScalingProcessType, ProcessType> {
INSTANCE;
@Override
public ProcessType apply( final ScalingProcessType scalingProcessType ) {
final ProcessType processType = new ProcessType();
processType.setProcessName( scalingProcessType.toString() );
return processType;
}
}
@TypeMapper
public enum AutoScalingTagTransform implements Function<TagType, AutoScalingGroupTag> {
INSTANCE;
@Override
public AutoScalingGroupTag apply( final TagType tagType ) {
final AutoScalingGroupTag groupTag = AutoScalingGroupTag.createUnassigned();
groupTag.setKey( tagType.getKey() );
groupTag.setValue( Objects.firstNonNull( tagType.getValue(), "" ) );
groupTag.setPropagateAtLaunch( Objects.firstNonNull( tagType.getPropagateAtLaunch(), Boolean.FALSE ) );
return groupTag;
}
}
@RestrictedTypes.QuantityMetricFunction( AutoScalingGroupMetadata.class )
public enum CountAutoScalingGroups implements Function<OwnerFullName, Long> {
INSTANCE;
@Override
public Long apply( final OwnerFullName input ) {
final EntityTransaction db = Entities.get( AutoScalingGroup.class );
try {
return Entities.count( AutoScalingGroup.withOwner( input ) );
} finally {
db.rollback( );
}
}
}
}