/************************************************************************* * Copyright 2009-2013 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.instances; import static com.eucalyptus.autoscaling.common.AutoScalingMetadata.AutoScalingInstanceMetadata; import java.util.Date; import java.util.List; import java.util.concurrent.TimeUnit; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.EnumType; import javax.persistence.Enumerated; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.PersistenceContext; import javax.persistence.PrePersist; import javax.persistence.PreUpdate; import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.TemporalType; import org.apache.log4j.Logger; import com.eucalyptus.autoscaling.common.AutoScalingBackend; import com.eucalyptus.autoscaling.common.AutoScalingMetadatas; import com.eucalyptus.autoscaling.common.internal.groups.AutoScalingGroup; import com.eucalyptus.entities.AbstractOwnedPersistent; import com.eucalyptus.auth.principal.OwnerFullName; import com.eucalyptus.entities.Entities; import com.eucalyptus.entities.TransactionResource; import com.eucalyptus.upgrade.Upgrades; import com.eucalyptus.upgrade.Upgrades.EntityUpgrade; import com.eucalyptus.util.Exceptions; import com.google.common.base.Objects; import com.google.common.base.Predicate; /** * */ @Entity @PersistenceContext( name = "eucalyptus_autoscaling" ) @Table( name = "metadata_auto_scaling_instances" ) public class AutoScalingInstance extends AbstractOwnedPersistent implements AutoScalingInstanceMetadata { private static final long serialVersionUID = 1L; @Column( name = "metadata_availability_zone", nullable = false, updatable = false ) private String availabilityZone; @Column( name = "metadata_health_status", nullable = false ) @Enumerated( EnumType.STRING ) private HealthStatus healthStatus; @ManyToOne( optional = false ) @JoinColumn( name = "metadata_auto_scaling_group_id" ) private AutoScalingGroup autoScalingGroup; @Column( name = "metadata_auto_scaling_group_name", nullable = false, updatable = false ) private String autoScalingGroupName; @Column( name = "metadata_launch_configuration_name", nullable = false, updatable = false ) private String launchConfigurationName; @Column( name = "metadata_lifecycle_state", nullable = false ) @Enumerated( EnumType.STRING ) private LifecycleState lifecycleState; @Temporal( TemporalType.TIMESTAMP) @Column( name = "metadata_in_service_timestamp" ) private Date inServiceTimestamp; @Column( name = "metadata_configuration_state", nullable = false ) @Enumerated( EnumType.STRING ) private ConfigurationState configurationState; @Column( name = "metadata_registration_attempts", nullable = false ) private Integer registrationAttempts; @Column( name = "metadata_protected_from_scale_in" ) private Boolean protectedFromScaleIn; protected AutoScalingInstance() { } protected AutoScalingInstance( final OwnerFullName owner ) { super( owner ); } protected AutoScalingInstance( final OwnerFullName owner, final String displayName ) { super( owner, displayName ); } public String getInstanceId() { return getDisplayName(); } public String getAvailabilityZone() { return availabilityZone; } public void setAvailabilityZone( final String availabilityZone ) { this.availabilityZone = availabilityZone; } public HealthStatus getHealthStatus() { return healthStatus; } public void setHealthStatus( final HealthStatus healthStatus ) { this.healthStatus = healthStatus; } public AutoScalingGroup getAutoScalingGroup() { return autoScalingGroup; } public void setAutoScalingGroup( final AutoScalingGroup autoScalingGroup ) { this.autoScalingGroup = autoScalingGroup; } public String getAutoScalingGroupName() { return autoScalingGroupName; } public void setAutoScalingGroupName( final String autoScalingGroupName ) { this.autoScalingGroupName = autoScalingGroupName; } public String getLaunchConfigurationName() { return launchConfigurationName; } public void setLaunchConfigurationName( final String launchConfigurationName ) { this.launchConfigurationName = launchConfigurationName; } public LifecycleState getLifecycleState() { return lifecycleState; } public void setLifecycleState( final LifecycleState lifecycleState ) { this.lifecycleState = lifecycleState; } public Date getInServiceTimestamp() { return inServiceTimestamp; } public void setInServiceTimestamp( final Date inServiceTimestamp ) { this.inServiceTimestamp = inServiceTimestamp; } public ConfigurationState getConfigurationState() { return configurationState; } public void setConfigurationState( final ConfigurationState configurationState ) { this.configurationState = configurationState; } public Integer getRegistrationAttempts() { return registrationAttempts; } public void setRegistrationAttempts( final Integer registrationAttempts ) { this.registrationAttempts = registrationAttempts; } public Boolean getProtectedFromScaleIn() { return protectedFromScaleIn; } public void setProtectedFromScaleIn( final Boolean protectedFromScaleIn ) { this.protectedFromScaleIn = protectedFromScaleIn; } public boolean healthStatusGracePeriodExpired() { final long gracePeriodMillis = TimeUnit.SECONDS.toMillis( Objects.firstNonNull( getAutoScalingGroup( ).getHealthCheckGracePeriod(), 0 ) ); // last update timestamp will be when InService state entered return getInServiceTimestamp()!=null && System.currentTimeMillis() - getInServiceTimestamp().getTime() > gracePeriodMillis; } public int incrementRegistrationAttempts() { return ++this.registrationAttempts; } /** * Create an example AutoScalingInstance for the given owner. * * @param ownerFullName The owner * @return The example */ public static AutoScalingInstance withOwner( final OwnerFullName ownerFullName ) { return new AutoScalingInstance( ownerFullName ); } /** * Create an example AutoScalingInstance for the given owner. * * @param accountNumber The owning account number * @return The example */ public static AutoScalingInstance withOwner( final String accountNumber ) { final AutoScalingInstance example = new AutoScalingInstance( ); example.setOwnerAccountNumber( accountNumber ); return example; } /** * Create an example AutoScalingInstance for the given owner and name. * * @param ownerFullName The owner * @param name The name * @return The example */ public static AutoScalingInstance named( final OwnerFullName ownerFullName, final String name ) { return new AutoScalingInstance( ownerFullName, name ); } public static AutoScalingInstance withUuid( final String uuid ) { final AutoScalingInstance example = new AutoScalingInstance(); example.setNaturalId( uuid ); return example; } public static AutoScalingInstance withHealthStatus( final HealthStatus healthStatus ) { final AutoScalingInstance example = new AutoScalingInstance(); example.setHealthStatus( healthStatus ); return example; } public static AutoScalingInstance withStates( final LifecycleState lifecycleState, final ConfigurationState configurationState ) { final AutoScalingInstance example = new AutoScalingInstance(); example.setLifecycleState( lifecycleState ); example.setConfigurationState( configurationState ); return example; } public static AutoScalingInstance create( @Nonnull final OwnerFullName ownerFullName, @Nonnull final String instanceId, @Nonnull final String availabilityZone, @Nonnull final Boolean protectedFromScaleIn, @Nonnull final AutoScalingGroup group ) { final AutoScalingInstance autoScalingInstance = new AutoScalingInstance( ownerFullName, instanceId ); autoScalingInstance.setAvailabilityZone( availabilityZone ); autoScalingInstance.setProtectedFromScaleIn( protectedFromScaleIn ); autoScalingInstance.setAutoScalingGroup( group ); autoScalingInstance.setLaunchConfigurationName( AutoScalingMetadatas.toDisplayName().apply( group.getLaunchConfiguration() ) ); autoScalingInstance.setHealthStatus( HealthStatus.Healthy ); autoScalingInstance.setLifecycleState( LifecycleState.Pending ); autoScalingInstance.setConfigurationState( ConfigurationState.Instantiated ); autoScalingInstance.setRegistrationAttempts( 0 ); return autoScalingInstance; } @PrePersist @PreUpdate private void preUpdate() { autoScalingGroupName = AutoScalingMetadatas.toDisplayName().apply( autoScalingGroup ); if ( lifecycleState == LifecycleState.InService && getInServiceTimestamp() == null ) { setInServiceTimestamp( new Date() ); } } @EntityUpgrade( entities = AutoScalingInstance.class, since = Upgrades.Version.v5_0_0, value = AutoScalingBackend.class) public enum AutoScalingInstanceUpgrade500 implements Predicate<Class> { INSTANCE; private static Logger LOG = Logger.getLogger(AutoScalingInstanceUpgrade500.class); @Override public boolean apply(@Nullable Class aClass) { try ( final TransactionResource tran = Entities.transactionFor( AutoScalingInstance.class ) ) { final List<AutoScalingInstance> instances = Entities.criteriaQuery( Entities.restriction( AutoScalingInstance.class ) .isNull( AutoScalingInstance_.protectedFromScaleIn ) ).list( ); for ( final AutoScalingInstance instance : instances ) { if ( instance.getProtectedFromScaleIn( ) == null ) { instance.setProtectedFromScaleIn( false ); LOG.info( "Set default scale in protection for auto scaling instance : " + instance.getInstanceId( ) ); } } tran.commit( ); } catch (Exception ex) { LOG.error("Exception during upgrade while attempting to initialize scaling protection for instances"); throw Exceptions.toUndeclared(ex); } return true; } } }