Skip to content
Browse files

Merge remote-tracking branch 'origin/testing' into dev/juphoff/evac-t…

…esting

Conflicts:
	cluster/handlers.c
	cluster/server-marshal.c
	node/handlers.c
  • Loading branch information...
2 parents d0a51bb + af0f578 commit d81eb82ab2a613b0b9c12aad868a8d7d6f00a795 @juphoff juphoff committed Apr 8, 2013
Showing with 4,635 additions and 1,755 deletions.
  1. +29 −36 clc/.classpath
  2. +1 −0 clc/modules/autoscaling-common/build.xml
  3. +1 −1 ...oscaling-common/src/main/java/com/eucalyptus/autoscaling/common/AutoScalingMessageValidation.java
  4. +20 −5 ...les/autoscaling-common/src/main/java/com/eucalyptus/autoscaling/common/AutoScalingMessages.groovy
  5. +7 −1 ...dules/autoscaling-common/src/main/java/com/eucalyptus/autoscaling/common/AutoScalingMetadata.java
  6. +2 −39 ...ules/autoscaling-common/src/main/java/com/eucalyptus/autoscaling/common/AutoScalingMetadatas.java
  7. +4 −0 clc/modules/autoscaling-common/src/main/resources/autoscaling-binding.xml
  8. +1 −0 clc/modules/autoscaling/build.xml
  9. +5 −4 clc/modules/autoscaling/ivy.xml
  10. +173 −39 clc/modules/autoscaling/src/main/java/com/eucalyptus/autoscaling/AutoScalingService.java
  11. +74 −0 clc/modules/autoscaling/src/main/java/com/eucalyptus/autoscaling/activities/ActivityCause.java
  12. +541 −205 clc/modules/autoscaling/src/main/java/com/eucalyptus/autoscaling/activities/ActivityManager.java
  13. +0 −27 clc/modules/autoscaling/src/main/java/com/eucalyptus/autoscaling/activities/BackoffRunner.java
  14. +1 −1 clc/modules/autoscaling/src/main/java/com/eucalyptus/autoscaling/activities/CloudWatchClient.java
  15. +64 −4 ...autoscaling/src/main/java/com/eucalyptus/autoscaling/activities/PersistenceScalingActivities.java
  16. +42 −6 clc/modules/autoscaling/src/main/java/com/eucalyptus/autoscaling/activities/ScalingActivities.java
  17. +65 −24 clc/modules/autoscaling/src/main/java/com/eucalyptus/autoscaling/activities/ScalingActivity.java
  18. +182 −0 ...modules/autoscaling/src/main/java/com/eucalyptus/autoscaling/config/AutoScalingConfiguration.java
  19. +1 −0 ...les/autoscaling/src/main/java/com/eucalyptus/autoscaling/configurations/LaunchConfigurations.java
  20. +46 −14 clc/modules/autoscaling/src/main/java/com/eucalyptus/autoscaling/groups/AutoScalingGroup.java
  21. +5 −2 clc/modules/autoscaling/src/main/java/com/eucalyptus/autoscaling/groups/AutoScalingGroups.java
  22. +64 −0 clc/modules/autoscaling/src/main/java/com/eucalyptus/autoscaling/groups/GroupScalingCause.java
  23. +110 −0 clc/modules/autoscaling/src/main/java/com/eucalyptus/autoscaling/groups/MetricCollectionType.java
  24. +1 −1 clc/modules/autoscaling/src/main/java/com/eucalyptus/autoscaling/groups/ScalingProcessType.java
  25. +2 −2 clc/modules/autoscaling/src/main/java/com/eucalyptus/autoscaling/groups/TerminationPolicyType.java
  26. +2 −1 ...odules/autoscaling/src/main/java/com/eucalyptus/autoscaling/metadata/AbstractOwnedPersistent.java
  27. +20 −4 ...dules/autoscaling/src/main/java/com/eucalyptus/autoscaling/metadata/AbstractOwnedPersistents.java
  28. +27 −5 ...ain/java/com/eucalyptus/autoscaling/metadata/AbstractOwnedPersistentsWithResourceNameSupport.java
  29. +107 −9 clc/modules/autoscaling/src/test/java/com/eucalyptus/autoscaling/AutoScalingServiceTest.groovy
  30. +47 −22 ...odules/autoscaling/src/test/java/com/eucalyptus/autoscaling/activities/ActivityManagerTest.groovy
  31. +26 −2 clc/modules/autoscaling/src/test/java/com/eucalyptus/autoscaling/activities/TestClients.java
  32. +29 −0 ...s/autoscaling/src/test/java/com/eucalyptus/autoscaling/config/AutoScalingConfigurationTest.groovy
  33. +1 −4 clc/modules/cloud/src/main/java/com/eucalyptus/cloud/CloudMetadata.java
  34. +6 −108 clc/modules/cloud/src/main/java/com/eucalyptus/cloud/CloudMetadatas.java
  35. +1 −0 clc/modules/cloudwatch-common/build.xml
  36. +8 −1 clc/modules/cloudwatch-common/src/main/java/com/eucalyptus/cloudwatch/CloudWatchMessages.groovy
  37. +1 −0 clc/modules/cloudwatch/build.xml
  38. +3 −2 clc/modules/cloudwatch/ivy.xml
  39. +18 −0 clc/modules/cloudwatch/src/main/java/com/eucalyptus/cloudwatch/BadRequestException.java
  40. +1 −0 clc/modules/cloudwatch/src/main/java/com/eucalyptus/cloudwatch/CloudWatchException.java
  41. +958 −384 clc/modules/cloudwatch/src/main/java/com/eucalyptus/cloudwatch/CloudWatchService.java
  42. +18 −0 clc/modules/cloudwatch/src/main/java/com/eucalyptus/cloudwatch/InternalFailureException.java
  43. +18 −0 clc/modules/cloudwatch/src/main/java/com/eucalyptus/cloudwatch/InvalidFormatException.java
  44. +18 −0 clc/modules/cloudwatch/src/main/java/com/eucalyptus/cloudwatch/InvalidNextTokenException.java
  45. +18 −0 ...ules/cloudwatch/src/main/java/com/eucalyptus/cloudwatch/InvalidParameterCombinationException.java
  46. +18 −0 clc/modules/cloudwatch/src/main/java/com/eucalyptus/cloudwatch/InvalidParameterValueException.java
  47. +18 −0 clc/modules/cloudwatch/src/main/java/com/eucalyptus/cloudwatch/LimitExceededException.java
  48. +18 −0 clc/modules/cloudwatch/src/main/java/com/eucalyptus/cloudwatch/MissingParameterException.java
  49. +18 −0 clc/modules/cloudwatch/src/main/java/com/eucalyptus/cloudwatch/ResourceNotFoundException.java
  50. +177 −0 clc/modules/cloudwatch/src/main/java/com/eucalyptus/cloudwatch/TransformationFunctions.java
  51. +1 −1 ...c/main/java/com/eucalyptus/cloudwatch/domain/{dimension → }/AbstractPersistentWithDimensions.java
  52. +1 −1 ...les/cloudwatch/src/main/java/com/eucalyptus/cloudwatch/domain/{dimension → }/DimensionEntity.java
  53. +62 −0 clc/modules/cloudwatch/src/main/java/com/eucalyptus/cloudwatch/domain/NextTokenUtils.java
  54. +89 −0 ...ules/cloudwatch/src/main/java/com/eucalyptus/cloudwatch/domain/absolute/AbsoluteMetricHelper.java
  55. +42 −16 ...ucalyptus/cloudwatch/domain/{cpu/CPUUtilizationEntity.java → absolute/AbsoluteMetricHistory.java}
  56. +1 −1 clc/modules/cloudwatch/src/main/java/com/eucalyptus/cloudwatch/domain/alarms/AlarmEntity.java
  57. +201 −60 clc/modules/cloudwatch/src/main/java/com/eucalyptus/cloudwatch/domain/alarms/AlarmManager.java
  58. +11 −6 .../cloudwatch/src/main/java/com/eucalyptus/cloudwatch/domain/alarms/AlarmStateEvaluationWorker.java
  59. +0 −72 ...dwatch/src/main/java/com/eucalyptus/cloudwatch/domain/cpu/CPUUtilizationPercentageCalculator.java
  60. +18 −4 clc/modules/cloudwatch/src/main/java/com/eucalyptus/cloudwatch/domain/listmetrics/ListMetric.java
  61. +58 −31 ...ules/cloudwatch/src/main/java/com/eucalyptus/cloudwatch/domain/listmetrics/ListMetricManager.java
  62. +13 −12 ...odules/cloudwatch/src/main/java/com/eucalyptus/cloudwatch/domain/listmetrics/ListMetricsTest.java
  63. +111 −21 ...modules/cloudwatch/src/main/java/com/eucalyptus/cloudwatch/domain/metricdata/MetricDataQueue.java
  64. +31 −16 clc/modules/cloudwatch/src/main/java/com/eucalyptus/cloudwatch/domain/metricdata/MetricEntity.java
  65. +9 −6 clc/modules/cloudwatch/src/main/java/com/eucalyptus/cloudwatch/domain/metricdata/MetricManager.java
  66. +1 −11 ...modules/cloudwatch/src/main/java/com/eucalyptus/cloudwatch/domain/metricdata/MetricQueueItem.java
  67. +1 −13 ...odules/cloudwatch/src/main/java/com/eucalyptus/cloudwatch/domain/metricdata/MetricStatistics.java
  68. +5 −5 clc/modules/cloudwatch/src/main/java/com/eucalyptus/cloudwatch/domain/metricdata/MetricTest.java
  69. +0 −8 ...dwatch/src/main/java/com/eucalyptus/cloudwatch/domain/metricdata/PutMetricDataAggregationKey.java
  70. +75 −1 clc/modules/cloudwatch/src/main/java/com/eucalyptus/cloudwatch/ws/CloudWatchQueryBinding.java
  71. +42 −0 clc/modules/cloudwatch/src/main/java/com/eucalyptus/cloudwatch/ws/WrappedBindingException.java
  72. +0 −92 clc/modules/cloudwatch/src/test/java/com/eucalyptus/cloudwatch/TestAggregationQueue.java
  73. +2 −1 clc/modules/cluster-manager/ivy.xml
  74. +24 −2 clc/modules/cluster-manager/src/main/java/com/eucalyptus/blockstorage/SnapshotManager.java
  75. +2 −1 clc/modules/cluster-manager/src/main/java/com/eucalyptus/blockstorage/SnapshotTag.java
  76. +12 −46 clc/modules/cluster-manager/src/main/java/com/eucalyptus/blockstorage/VolumeManager.java
  77. +2 −1 clc/modules/cluster-manager/src/main/java/com/eucalyptus/blockstorage/VolumeTag.java
  78. +0 −1 clc/modules/cluster-manager/src/main/java/com/eucalyptus/cloud/AccountMetadata.java
  79. +28 −3 clc/modules/cluster-manager/src/main/java/com/eucalyptus/cloud/run/Allocations.java
  80. +113 −71 clc/modules/cluster-manager/src/main/java/com/eucalyptus/cloud/run/ClusterAllocator.java
  81. +107 −2 clc/modules/cluster-manager/src/main/java/com/eucalyptus/cloud/run/VerifyMetadata.java
  82. +237 −196 ...modules/cluster-manager/src/main/java/com/eucalyptus/cluster/callback/DescribeSensorCallback.java
  83. +11 −2 clc/modules/cluster-manager/src/main/java/com/eucalyptus/images/BlockStorageImageInfo.java
  84. +2 −0 clc/modules/cluster-manager/src/main/java/com/eucalyptus/images/DeviceMapping.java
  85. +2 −1 clc/modules/cluster-manager/src/main/java/com/eucalyptus/images/ImageInfoTag.java
  86. +47 −3 clc/modules/cluster-manager/src/main/java/com/eucalyptus/images/ImageManager.java
  87. +175 −34 clc/modules/cluster-manager/src/main/java/com/eucalyptus/images/Images.java
  88. +2 −1 clc/modules/cluster-manager/src/main/java/com/eucalyptus/network/NetworkGroupTag.java
  89. +1 −1 clc/modules/cluster-manager/src/main/java/com/eucalyptus/node/Nodes.java
  90. +36 −2 clc/modules/cluster-manager/src/main/java/com/eucalyptus/tags/Tag.java
  91. +8 −11 clc/modules/cluster-manager/src/main/java/com/eucalyptus/tags/TagManager.java
  92. +2 −16 clc/modules/cluster-manager/src/main/java/com/eucalyptus/tags/TagSupport.java
  93. +18 −20 clc/modules/cluster-manager/src/main/java/com/eucalyptus/tags/Tags.java
  94. +15 −10 clc/modules/cluster-manager/src/main/java/com/eucalyptus/vm/VmBootRecord.java
Sorry, we could not display the entire diff because it was too big.
View
65 clc/.classpath
@@ -1,47 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
- <classpathentry kind="src" output="modules/authentication/build" path="modules/authentication/src/main/java"/>
- <classpathentry kind="src" output="modules/autoscaling/build" path="modules/autoscaling/src/main/java"/>
- <classpathentry kind="src" output="modules/autoscaling-common/build" path="modules/autoscaling-common/src/main/java"/>
- <classpathentry kind="src" output="modules/cloud/build" path="modules/cloud/src/main/java"/>
- <classpathentry kind="src" output="modules/cloudwatch/build" path="modules/cloudwatch/src/main/java"/>
- <classpathentry kind="src" output="modules/cloudwatch-common/build" path="modules/cloudwatch-common/src/main/java"/>
- <classpathentry kind="src" output="modules/cluster-manager/build" path="modules/cluster-manager/src/main/java"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="src" path="modules/authentication/src/main/java"/>
+ <classpathentry kind="src" path="modules/cloud/src/main/java"/>
+ <classpathentry kind="src" path="modules/cluster-manager/src/main/java"/>
<classpathentry kind="src" path="modules/cluster-manager/conf/scripts"/>
- <classpathentry kind="src" output="modules/component/build" path="modules/component/src/main/java"/>
- <classpathentry kind="src" output="modules/configuration/build" path="modules/configuration/src/main/java"/>
+ <classpathentry kind="src" path="modules/component/src/main/java"/>
+ <classpathentry kind="src" path="modules/configuration/src/main/java"/>
<classpathentry kind="src" path="modules/configuration/conf/scripts"/>
- <classpathentry kind="src" output="modules/core/build" path="modules/core/src/main/java"/>
+ <classpathentry kind="src" path="modules/core/src/main/java"/>
+ <classpathentry kind="src" path="modules/core/src/test/java"/>
<classpathentry kind="src" path="modules/core/conf/scripts"/>
- <classpathentry kind="src" output="modules/dns/build" path="modules/dns/src/main/java"/>
- <classpathentry kind="src" output="modules/euare/build" path="modules/euare/src/main/java"/>
- <classpathentry kind="src" output="modules/euare-common/build" path="modules/euare-common/src/main/java"/>
- <classpathentry kind="src" output="modules/loadbalancing/build" path="modules/loadbalancing/src/main/java"/>
- <classpathentry kind="src" output="modules/loadbalancing-common/build" path="modules/loadbalancing-common/src/main/java"/>
- <classpathentry kind="src" output="modules/msgs/build" path="modules/msgs/src/main/java"/>
+ <classpathentry kind="src" path="modules/dns/src/main/java"/>
+ <classpathentry kind="src" path="modules/euare/src/main/java"/>
+ <classpathentry kind="src" path="modules/euare-common/src/main/java"/>
+ <classpathentry kind="src" path="modules/msgs/src/main/java"/>
+ <classpathentry kind="src" path="modules/msgs/src/test/java"/>
<classpathentry kind="src" path="modules/msgs/conf/jmx"/>
<classpathentry kind="src" path="modules/msgs/conf/scripts"/>
- <classpathentry kind="src" output="modules/notifications/build" path="modules/notifications/src/main/java"/>
- <classpathentry kind="src" output="modules/postgresql/build" path="modules/postgresql/src/main/java"/>
- <classpathentry kind="src" path="modules/postgresql/conf/init.d"/>
+ <classpathentry kind="src" path="modules/notifications/src/main/java"/>
+ <classpathentry kind="src" path="modules/postgresql/src/main/java"/>
<classpathentry kind="src" path="modules/postgresql/conf/scripts"/>
- <classpathentry kind="src" output="modules/reporting/build" path="modules/reporting/src/main/java"/>
- <classpathentry kind="src" output="modules/storage-common/build" path="modules/storage-common/src/main/java"/>
- <classpathentry kind="src" output="modules/storage-controller/build" path="modules/storage-controller/src/main/java"/>
- <classpathentry kind="src" output="modules/tokens/build" path="modules/tokens/src/main/java"/>
- <classpathentry kind="src" output="modules/troubleshooting/build" path="modules/troubleshooting/src/main/java"/>
- <classpathentry kind="src" output="modules/walrus/build" path="modules/walrus/src/main/java"/>
+ <classpathentry kind="src" path="modules/reporting/src/main/java"/>
+ <classpathentry kind="src" path="modules/reporting/src/test/java"/>
+ <classpathentry kind="src" path="modules/storage-common/src/main/java"/>
+ <classpathentry kind="src" path="modules/storage-controller/src/main/java"/>
+ <classpathentry kind="src" path="modules/walrus/src/main/java"/>
<classpathentry kind="src" path="modules/walrus/conf/drbd"/>
- <classpathentry kind="src" output="modules/wsstack/build" path="modules/wsstack/src/main/java"/>
+ <classpathentry kind="src" path="modules/walrus/src/test/java"/>
+ <classpathentry kind="src" path="modules/wsstack/src/main/java"/>
<classpathentry kind="src" path="modules/wsstack/conf/scripts"/>
- <classpathentry kind="src" output="modules/www/build" path="modules/www/src/main/java"/>
+ <classpathentry kind="src" path="modules/www/src/main/java"/>
<classpathentry kind="src" path="modules/www/conf/www"/>
<classpathentry kind="src" path="modules/troubleshooting/src/main/java"/>
<classpathentry kind="src" path="modules/loadbalancing/src/main/java"/>
<classpathentry kind="src" path="modules/loadbalancing-common/src/main/java"/>
<classpathentry kind="src" path="modules/tokens/src/main/java"/>
+ <classpathentry kind="src" path="modules/tokens-common/src/main/java"/>
<classpathentry kind="con" path="GROOVY_SUPPORT"/>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="lib/activemq-core-5.4.1.jar"/>
<classpathentry kind="lib" path="lib/ant-1.7.jar"/>
<classpathentry kind="lib" path="lib/antlr-3.0.1.jar"/>
@@ -65,7 +61,7 @@
<classpathentry kind="lib" path="lib/batik-svggen.jar"/>
<classpathentry kind="lib" path="lib/batik-util.jar"/>
<classpathentry kind="lib" path="lib/batik-xml.jar"/>
- <classpathentry kind="lib" path="lib/bcel-5.2.jar"/>
+ <classpathentry kind="lib" path="lib/bcel-5.2.jar" sourcepath="/git/third-party/bcel-5.2"/>
<classpathentry kind="lib" path="lib/bcprov.jar"/>
<classpathentry kind="lib" path="lib/bsf-2.4.0.jar"/>
<classpathentry kind="lib" path="lib/btm-2.1.0.jar"/>
@@ -104,18 +100,16 @@
<classpathentry kind="lib" path="lib/geronimo-stax-1.0-spec-1.0.1.jar"/>
<classpathentry kind="lib" path="lib/groovy-all-1.7.2.jar"/>
<classpathentry kind="lib" path="lib/guava-r09-gwt.jar"/>
- <classpathentry kind="lib" path="lib/guava-r09.jar"/>
+ <classpathentry kind="lib" path="lib/guava-r09.jar" sourcepath="/bzr/third-party/guava-r08"/>
<classpathentry kind="lib" path="lib/gwt-api-checker-2.2.jar"/>
<classpathentry kind="lib" path="lib/gwt-dev-2.2.jar"/>
<classpathentry kind="lib" path="lib/gwt-servlet-2.2.jar"/>
<classpathentry kind="lib" path="lib/gwt-servlet-deps-2.2.jar"/>
<classpathentry kind="lib" path="lib/gwt-soyc-vis-2.2.jar"/>
<classpathentry kind="lib" path="lib/gwt-user-2.2.jar"/>
- <classpathentry kind="lib" path="lib/ha-jdbc-2.0.16-rc-1-jdk1.6.jar"/>
+ <classpathentry kind="lib" path="lib/ha-jdbc-2.0.16-rc-1-jdk1.6.jar" sourcepath="//git/third-party/ha-jdbc-2.0.16-rc-1"/>
<classpathentry kind="lib" path="lib/hamcrest-all-1.2.jar"/>
<classpathentry kind="lib" path="lib/hibernate-3.5.6-Final.jar"/>
- <classpathentry kind="lib" path="lib/hsqldb-1.8.0.10.jar"/>
- <classpathentry kind="lib" path="lib/hsqldbutil-1.8.0.10.jar"/>
<classpathentry kind="lib" path="lib/infinispan-core-4.2.1.CR4.jar"/>
<classpathentry kind="lib" path="lib/iText-2.1.7.jar"/>
<classpathentry kind="lib" path="lib/janino-2.5.15-1.jar"/>
@@ -143,9 +137,9 @@
<classpathentry kind="lib" path="lib/jetty6-sslengine-6.1.19.jar"/>
<classpathentry kind="lib" path="lib/jetty6-util-6.1.19.jar"/>
<classpathentry kind="lib" path="lib/jgroups-2.11.1.Final.jar"/>
- <classpathentry kind="lib" path="lib/jibx-bind-1.2.3.jar"/>
+ <classpathentry kind="lib" path="lib/jibx-bind-1.2.3.jar" sourcepath="/git/third-party/jibx-1.2.3"/>
<classpathentry kind="lib" path="lib/jibx-extras-1.2.3.jar"/>
- <classpathentry kind="lib" path="lib/jibx-run-1.2.3.jar"/>
+ <classpathentry kind="lib" path="lib/jibx-run-1.2.3.jar" sourcepath="/bzr/third-party/jibx-1.2.3"/>
<classpathentry kind="lib" path="lib/jibx-schema-1.2.3.jar"/>
<classpathentry kind="lib" path="lib/jibx-tools-1.2.3.jar"/>
<classpathentry kind="lib" path="lib/jminix-0.9.jar"/>
@@ -201,6 +195,5 @@
<classpathentry kind="lib" path="lib/commons-codec-1.4.jar"/>
<classpathentry kind="lib" path="lib/commons-io-2.0.1.jar"/>
<classpathentry kind="lib" path="lib/commons-lang-2.6.jar"/>
- <classpathentry exported="true" kind="con" path="GROOVY_SUPPORT"/>
<classpathentry kind="output" path="bin"/>
</classpath>
View
1 clc/modules/autoscaling-common/build.xml
@@ -24,5 +24,6 @@
<srcfiles dir="${src.dir}" includes="**/*" />
</uptodate>
<import file="../module-inc.xml"/>
+ <target name="indent-module" />
</project>
View
2 ...-common/src/main/java/com/eucalyptus/autoscaling/common/AutoScalingMessageValidation.java
@@ -51,7 +51,7 @@
// Generic
STRING_128( "(?s).{1,128}" ),
STRING_256( "(?s).{1,256}" ),
- UUID( "[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}" ),
+ UUID_VERBOSE( "[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|verbose" ),
// Auto scaling
ADJUSTMENT( "ChangeInCapacity|ExactCapacity|PercentChangeInCapacity" ),
View
25 ...scaling-common/src/main/java/com/eucalyptus/autoscaling/common/AutoScalingMessages.groovy
@@ -40,7 +40,7 @@ public class Alarm extends EucalyptusData {
}
public class MetricGranularityTypes extends EucalyptusData {
public MetricGranularityTypes() { }
- ArrayList<MetricGranularityType> member = new ArrayList<MetricGranularityType>()
+ ArrayList<MetricGranularityType> member = [ new MetricGranularityType(granularity: "1Minute") ]
}
public class DescribeAutoScalingNotificationTypesResponseType extends AutoScalingMessage {
public DescribeAutoScalingNotificationTypesResponseType() { }
@@ -290,6 +290,9 @@ public class PutNotificationConfigurationType extends AutoScalingMessage {
}
public class MetricCollectionTypes extends EucalyptusData {
public MetricCollectionTypes() { }
+ public MetricCollectionTypes( Collection<String> types ) {
+ member.addAll( types.collect{ type -> new MetricCollectionType( metric: type ) } )
+ }
ArrayList<MetricCollectionType> member = new ArrayList<MetricCollectionType>()
}
public class CreateAutoScalingGroupResponseType extends AutoScalingMessage {
@@ -488,6 +491,9 @@ public class CreateAutoScalingGroupType extends AutoScalingMessage {
if ( maxSize && desiredCapacity && desiredCapacity > maxSize ) {
errors.put( "DesiredCapacity", "DesiredCapacity must not be greater than MaxSize" )
}
+ if ( availabilityZones && availabilityZones.member.isEmpty() ) {
+ errors.put( "AvailabilityZones.member.1", "AvailabilityZones.member.1 is required" )
+ }
errors
}
}
@@ -537,7 +543,6 @@ public class AvailabilityZones extends EucalyptusData {
if ( zones != null ) member.addAll( zones )
}
@AutoScalingMessageValidation.FieldRegex(AutoScalingMessageValidation.FieldRegexValue.EC2_NAME)
- @AutoScalingMessageValidation.FieldRange(min=1L)
@HttpParameterMapping(parameter="member")
ArrayList<String> member = new ArrayList<String>()
}
@@ -690,7 +695,7 @@ public class UpdateAutoScalingGroupResponseType extends AutoScalingMessage {
}
public class EnabledMetric extends EucalyptusData {
String metric
- String granularity
+ String granularity = "1Minute"
public EnabledMetric() { }
}
public class DescribePoliciesResponseType extends AutoScalingMessage {
@@ -737,7 +742,7 @@ public class ExecutePolicyResponseType extends AutoScalingMessage {
}
public class ActivityIds extends EucalyptusData {
public ActivityIds() { }
- @AutoScalingMessageValidation.FieldRegex(AutoScalingMessageValidation.FieldRegexValue.UUID)
+ @AutoScalingMessageValidation.FieldRegex(AutoScalingMessageValidation.FieldRegexValue.UUID_VERBOSE)
@HttpParameterMapping(parameter="member")
ArrayList<String> member = new ArrayList<String>()
}
@@ -772,6 +777,13 @@ public class DescribeScalingActivitiesType extends AutoScalingMessage {
Integer maxRecords
String nextToken
public DescribeScalingActivitiesType() { }
+ public List<String> activityIds() {
+ List<String> ids = Lists.newArrayList()
+ if ( activityIds != null ) {
+ ids = activityIds.getMember()
+ }
+ return ids
+ }
}
public class LaunchConfigurationType extends EucalyptusData {
String launchConfigurationName
@@ -860,7 +872,7 @@ public class UpdateAutoScalingGroupType extends AutoScalingMessage {
}
public class DescribeMetricCollectionTypesResult extends EucalyptusData {
MetricCollectionTypes metrics
- MetricGranularityTypes granularities
+ MetricGranularityTypes granularities = new MetricGranularityTypes()
public DescribeMetricCollectionTypesResult() { }
}
public class BlockDeviceMappingType extends EucalyptusData {
@@ -908,6 +920,9 @@ public class AutoScalingGroupsType extends EucalyptusData {
}
public class EnabledMetrics extends EucalyptusData {
public EnabledMetrics() { }
+ public EnabledMetrics( Collection<String> enabledMetrics ) {
+ if ( enabledMetrics != null ) member.addAll( enabledMetrics.collect{ metric -> new EnabledMetric(metric: metric) } )
+ }
ArrayList<EnabledMetric> member = new ArrayList<EnabledMetric>()
}
public class SetDesiredCapacityType extends AutoScalingMessage {
View
8 ...toscaling-common/src/main/java/com/eucalyptus/autoscaling/common/AutoScalingMetadata.java
@@ -1,5 +1,5 @@
/*************************************************************************
- * Copyright 2009-2012 Eucalyptus Systems, Inc.
+ * 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
@@ -58,4 +58,10 @@
@PolicyResourceType( "scalingprocesstype" )
public interface ScalingProcessTypeMetadata extends AutoScalingMetadata {}
+ @PolicyResourceType( "scalingactivity" )
+ public interface ScalingActivityMetadata extends AutoScalingMetadata {}
+
+ @PolicyResourceType( "metriccollectiontype" )
+ public interface MetricCollectionTypeMetadata extends AutoScalingMetadata {}
+
}
View
41 ...oscaling-common/src/main/java/com/eucalyptus/autoscaling/common/AutoScalingMetadatas.java
@@ -1,5 +1,5 @@
/*************************************************************************
- * Copyright 2009-2012 Eucalyptus Systems, Inc.
+ * 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
@@ -21,7 +21,6 @@
import static com.eucalyptus.autoscaling.common.AutoScalingMetadata.AutoScalingMetadataWithResourceName;
import java.util.Collection;
-import com.eucalyptus.util.CollectionUtils;
import com.eucalyptus.util.RestrictedTypes;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
@@ -30,16 +29,7 @@
/**
*
*/
-public class AutoScalingMetadatas {
-
- public static <T extends AutoScalingMetadata> Function<T, String> toDisplayName( ) {
- return new Function<T, String>( ) {
- @Override
- public String apply( T metadata ) {
- return metadata == null ? null : metadata.getDisplayName( );
- }
- };
- }
+public class AutoScalingMetadatas extends RestrictedTypes {
public static <T extends AutoScalingMetadataWithResourceName> Function<T, String> toArn( ) {
return new Function<T, String>( ) {
@@ -50,33 +40,10 @@ public String apply( T metadata ) {
};
}
- public static <T extends AutoScalingMetadata> Predicate<T> filterById( final Collection<String> requestedIdentifiers ) {
- return filterByProperty( requestedIdentifiers, toDisplayName() );
- }
-
public static <T extends AutoScalingMetadataWithResourceName> Predicate<T> filterByArn( final Collection<String> requestedArns ) {
return filterByProperty( requestedArns, toArn() );
}
- public static <T extends AutoScalingMetadata> Predicate<T> filterByProperty( final String requestedValue,
- final Function<? super T,String> extractor ) {
- return filterByProperty( CollectionUtils.<String>listUnit().apply( requestedValue ), extractor );
- }
-
- public static <T extends AutoScalingMetadata> Predicate<T> filterByProperty( final Collection<String> requestedValues,
- final Function<? super T,String> extractor ) {
- return new Predicate<T>( ) {
- @Override
- public boolean apply( T input ) {
- return requestedValues == null || requestedValues.isEmpty( ) || requestedValues.contains( extractor.apply( input ) );
- }
- };
- }
-
- public static <T extends AutoScalingMetadata> Predicate<T> filterPrivilegesById( final Collection<String> requestedIdentifiers ) {
- return Predicates.and( filterById( requestedIdentifiers ), filterPrivileged() );
- }
-
public static <T extends AutoScalingMetadataWithResourceName> Predicate<T> filterPrivilegesByIdOrArn( final Collection<String> requestedItems ) {
final Collection<String> names = AutoScalingResourceName.simpleNames( requestedItems );
final Collection<String> arns = AutoScalingResourceName.arns( requestedItems );
@@ -90,9 +57,5 @@ public boolean apply( T input ) {
AutoScalingMetadatas.<T>filterById( names ),
filterPrivileged() );
}
-
- public static <T extends AutoScalingMetadata> Predicate<T> filterPrivileged() {
- return RestrictedTypes.filterPrivileged();
- }
}
View
4 clc/modules/autoscaling-common/src/main/resources/autoscaling-binding.xml
@@ -20,6 +20,10 @@
-->
<binding name="autoscaling_amazonaws_com_doc_2011_01_01" force-classes="true" add-constructors="true">
<namespace uri="http://autoscaling.amazonaws.com/doc/2011-01-01/" default="elements"/>
+ <format
+ type="java.util.Date"
+ deserializer="org.jibx.runtime.Utility.deserializeDateTime"
+ serializer="com.eucalyptus.ws.util.SerializationUtils.serializeDateTime"/>
<mapping class="com.eucalyptus.autoscaling.common.ResponseMetadata" abstract="true">
<value name="RequestId" field="requestId" usage="required"/>
</mapping>
View
1 clc/modules/autoscaling/build.xml
@@ -25,5 +25,6 @@
<srcfiles dir="${src.dir}" includes="**/*" />
</uptodate>
<import file="../module-inc.xml"/>
+ <target name="indent-module" />
</project>
View
9 clc/modules/autoscaling/ivy.xml
@@ -1,10 +1,11 @@
<ivy-module version="2.0">
<info organisation="com.eucalyptus" module="eucalyptus-autoscaling"/>
<dependencies>
- <dependency org="com.eucalyptus" name="eucalyptus-autoscaling-common" rev="latest.integration"/>
- <dependency org="com.eucalyptus" name="eucalyptus-loadbalancing-common" rev="latest.integration"/>
- <dependency org="com.eucalyptus" name="eucalyptus-ws" rev="latest.integration"/>
- <dependency org="com.eucalyptus" name="eucalyptus-cluster-manager" rev="latest.integration"/>
+ <dependency name="eucalyptus-autoscaling-common" rev="latest.integration"/>
+ <dependency name="eucalyptus-cloudwatch-common" rev="latest.integration"/>
+ <dependency name="eucalyptus-loadbalancing-common" rev="latest.integration"/>
+ <dependency name="eucalyptus-ws" rev="latest.integration"/>
+ <dependency name="eucalyptus-cluster-manager" rev="latest.integration"/>
</dependencies>
</ivy-module>
View
212 clc/modules/autoscaling/src/main/java/com/eucalyptus/autoscaling/AutoScalingService.java
@@ -40,8 +40,11 @@
import com.eucalyptus.auth.Permissions;
import com.eucalyptus.auth.policy.PolicySpec;
import com.eucalyptus.auth.principal.AccountFullName;
+import com.eucalyptus.auth.principal.Principals;
import com.eucalyptus.auth.principal.UserFullName;
import com.eucalyptus.autoscaling.activities.ActivityManager;
+import com.eucalyptus.autoscaling.activities.PersistenceScalingActivities;
+import com.eucalyptus.autoscaling.activities.ScalingActivities;
import com.eucalyptus.autoscaling.activities.ScalingActivity;
import com.eucalyptus.autoscaling.common.Activity;
import com.eucalyptus.autoscaling.common.Alarms;
@@ -105,6 +108,7 @@
import com.eucalyptus.autoscaling.common.Instance;
import com.eucalyptus.autoscaling.common.Instances;
import com.eucalyptus.autoscaling.common.LaunchConfigurationType;
+import com.eucalyptus.autoscaling.common.MetricCollectionTypes;
import com.eucalyptus.autoscaling.common.ProcessType;
import com.eucalyptus.autoscaling.common.PutNotificationConfigurationResponseType;
import com.eucalyptus.autoscaling.common.PutNotificationConfigurationType;
@@ -128,11 +132,13 @@
import com.eucalyptus.autoscaling.common.TerminateInstanceInAutoScalingGroupType;
import com.eucalyptus.autoscaling.common.UpdateAutoScalingGroupResponseType;
import com.eucalyptus.autoscaling.common.UpdateAutoScalingGroupType;
+import com.eucalyptus.autoscaling.config.AutoScalingConfiguration;
import com.eucalyptus.autoscaling.configurations.LaunchConfiguration;
import com.eucalyptus.autoscaling.configurations.LaunchConfigurations;
import com.eucalyptus.autoscaling.configurations.PersistenceLaunchConfigurations;
import com.eucalyptus.autoscaling.groups.AutoScalingGroup;
import com.eucalyptus.autoscaling.groups.AutoScalingGroups;
+import com.eucalyptus.autoscaling.groups.MetricCollectionType;
import com.eucalyptus.autoscaling.groups.HealthCheckType;
import com.eucalyptus.autoscaling.groups.PersistenceAutoScalingGroups;
import com.eucalyptus.autoscaling.groups.ScalingProcessType;
@@ -142,6 +148,7 @@
import com.eucalyptus.autoscaling.instances.AutoScalingInstances;
import com.eucalyptus.autoscaling.instances.HealthStatus;
import com.eucalyptus.autoscaling.instances.PersistenceAutoScalingInstances;
+import com.eucalyptus.autoscaling.metadata.AbstractOwnedPersistents;
import com.eucalyptus.autoscaling.metadata.AutoScalingMetadataException;
import com.eucalyptus.autoscaling.metadata.AutoScalingMetadataNotFoundException;
import com.eucalyptus.autoscaling.policies.AdjustmentType;
@@ -166,6 +173,7 @@
import com.eucalyptus.util.RestrictedTypes;
import com.eucalyptus.util.Strings;
import com.eucalyptus.util.TypeMappers;
+import com.eucalyptus.util.Wrappers;
import com.google.common.base.Enums;
import com.google.common.base.Function;
import com.google.common.base.Functions;
@@ -207,32 +215,36 @@
private final AutoScalingInstances autoScalingInstances;
private final ScalingPolicies scalingPolicies;
private final ActivityManager activityManager;
+ private final ScalingActivities scalingActivities;
public AutoScalingService() {
this(
new PersistenceLaunchConfigurations( ),
new PersistenceAutoScalingGroups( ),
new PersistenceAutoScalingInstances( ),
new PersistenceScalingPolicies( ),
- new ActivityManager() );
+ new ActivityManager( ),
+ new PersistenceScalingActivities( ) );
}
protected AutoScalingService( final LaunchConfigurations launchConfigurations,
final AutoScalingGroups autoScalingGroups,
final AutoScalingInstances autoScalingInstances,
final ScalingPolicies scalingPolicies,
- final ActivityManager activityManager ) {
+ final ActivityManager activityManager,
+ final ScalingActivities scalingActivities ) {
this.launchConfigurations = launchConfigurations;
this.autoScalingGroups = autoScalingGroups;
this.autoScalingInstances = autoScalingInstances;
this.scalingPolicies = scalingPolicies;
this.activityManager = activityManager;
+ this.scalingActivities = scalingActivities;
}
public DescribeAutoScalingGroupsResponseType describeAutoScalingGroups( final DescribeAutoScalingGroupsType request ) throws EucalyptusCloudException {
final DescribeAutoScalingGroupsResponseType reply = request.getReply( );
- //TODO:STEVE: MaxRecords / NextToken support for DescribeAutoScalingGroups
+ //TODO: MaxRecords / NextToken support for DescribeAutoScalingGroups
final Context ctx = Contexts.lookup( );
final boolean showAll = request.autoScalingGroupNames().remove( "verbose" );
@@ -274,8 +286,38 @@ public DescribeAutoScalingGroupsResponseType describeAutoScalingGroups( final De
return reply;
}
- public EnableMetricsCollectionResponseType enableMetricsCollection(EnableMetricsCollectionType request) throws EucalyptusCloudException {
- EnableMetricsCollectionResponseType reply = request.getReply( );
+ public EnableMetricsCollectionResponseType enableMetricsCollection( final EnableMetricsCollectionType request ) throws EucalyptusCloudException {
+ final EnableMetricsCollectionResponseType reply = request.getReply( );
+
+ final Context ctx = Contexts.lookup( );
+ try {
+ final AccountFullName accountFullName = ctx.getUserFullName().asAccountFullName();
+ final Callback<AutoScalingGroup> groupCallback = new Callback<AutoScalingGroup>() {
+ @Override
+ public void fire( final AutoScalingGroup autoScalingGroup ) {
+ if ( RestrictedTypes.filterPrivileged().apply( autoScalingGroup ) ) {
+ final Set<MetricCollectionType> metricsToEnable = EnumSet.allOf( MetricCollectionType.class );
+ if ( request.getMetrics() != null && !request.getMetrics().getMember().isEmpty() ) {
+ metricsToEnable.clear();
+ Iterables.addAll( metricsToEnable, Iterables.transform(
+ request.getMetrics().getMember(),
+ Enums.valueOfFunction(MetricCollectionType.class) ) );
+ }
+ autoScalingGroup.getEnabledMetrics().addAll( metricsToEnable );
+ }
+ }
+ };
+
+ autoScalingGroups.update(
+ accountFullName,
+ request.getAutoScalingGroupName(),
+ groupCallback );
+ } catch ( AutoScalingMetadataNotFoundException e ) {
+ throw new ValidationErrorException( "Auto scaling group not found: " + request.getAutoScalingGroupName() );
+ } catch ( Exception e ) {
+ handleException( e );
+ }
+
return reply;
}
@@ -338,7 +380,7 @@ public DeleteLaunchConfigurationResponseType deleteLaunchConfiguration( final De
public DescribePoliciesResponseType describePolicies(final DescribePoliciesType request) throws EucalyptusCloudException {
final DescribePoliciesResponseType reply = request.getReply( );
- //TODO:STEVE: MaxRecords / NextToken support for DescribePolicies
+ //TODO: MaxRecords / NextToken support for DescribePolicies
final Context ctx = Contexts.lookup( );
final boolean showAll = request.policyNames().remove( "verbose" );
@@ -481,8 +523,33 @@ public AutoScalingGroup get( ) {
return reply;
}
- public DescribeScalingActivitiesResponseType describeScalingActivities(DescribeScalingActivitiesType request) throws EucalyptusCloudException {
- DescribeScalingActivitiesResponseType reply = request.getReply( );
+ public DescribeScalingActivitiesResponseType describeScalingActivities( final DescribeScalingActivitiesType request ) throws EucalyptusCloudException {
+ final DescribeScalingActivitiesResponseType reply = request.getReply( );
+
+ final Context ctx = Contexts.lookup( );
+ final boolean showAll = request.activityIds().remove( "verbose" );
+ final OwnerFullName ownerFullName = ctx.hasAdministrativePrivileges( ) && showAll ?
+ null :
+ ctx.getUserFullName( ).asAccountFullName( );
+
+ try {
+ final AutoScalingGroup group = com.google.common.base.Strings.isNullOrEmpty( request.getAutoScalingGroupName() ) ?
+ null :
+ autoScalingGroups.lookup( ownerFullName, request.getAutoScalingGroupName() );
+
+ final List<ScalingActivity> scalingActivities =
+ this.scalingActivities.list( ownerFullName, group, request.activityIds(), AutoScalingMetadatas.filterPrivileged() );
+ Collections.sort( scalingActivities, Ordering.natural().reverse().onResultOf( AbstractOwnedPersistents.createdDate() ) );
+
+ Iterables.addAll(
+ reply.getDescribeScalingActivitiesResult().getActivities().getMember(),
+ Iterables.transform( scalingActivities, TypeMappers.lookup( ScalingActivity.class, Activity.class ) ) );
+ } catch ( AutoScalingMetadataNotFoundException e ) {
+ throw new ValidationErrorException( "Auto scaling group not found: " + request.getAutoScalingGroupName() );
+ } catch ( AutoScalingMetadataException e ) {
+ handleException( e );
+ }
+
return reply;
}
@@ -505,7 +572,7 @@ public DescribeTerminationPolicyTypesResponseType describeTerminationPolicyTypes
public DescribeTagsResponseType describeTags( final DescribeTagsType request ) throws EucalyptusCloudException {
final DescribeTagsResponseType reply = request.getReply( );
- //TODO:STEVE: MaxRecords / NextToken support for DescribeTags
+ //TODO: MaxRecords / NextToken support for DescribeTags
final Collection<Predicate<Tag>> tagFilters = Lists.newArrayList();
for ( final Filter filter : request.filters() ) {
@@ -569,21 +636,35 @@ public ExecutePolicyResponseType executePolicy(final ExecutePolicyType request)
throw new ValidationErrorException( "Scaling policy not found: " + request.getPolicyName() );
}
- autoScalingGroups.update( accountFullName, request.getAutoScalingGroupName(), new Callback<AutoScalingGroup>(){
+ autoScalingGroups.update( accountFullName, scalingPolicy.getAutoScalingGroupName(), new Callback<AutoScalingGroup>(){
@Override
public void fire( final AutoScalingGroup autoScalingGroup ) {
+ final boolean isCloudWatch = Principals.isSameUser(
+ Principals.systemUser(),
+ Wrappers.unwrap( Context.class, Contexts.lookup() ).getUser() );
+ if ( isCloudWatch && !scalingProcessEnabled( ScalingProcessType.AlarmNotification, autoScalingGroup ) ) {
+ logger.debug( "Ignoring policy execution due to alarm notification suspension" );
+ return;
+ }
failIfScaling( activityManager, autoScalingGroup );
+ final Integer desiredCapacity = scalingPolicy.getAdjustmentType().adjustCapacity(
+ autoScalingGroup.getDesiredCapacity( ),
+ scalingPolicy.getScalingAdjustment( ),
+ Objects.firstNonNull( scalingPolicy.getMinAdjustmentStep( ), 0 ),
+ Objects.firstNonNull( autoScalingGroup.getMinSize( ), 0 ),
+ Objects.firstNonNull( autoScalingGroup.getMaxSize( ), Integer.MAX_VALUE )
+ );
setDesiredCapacityWithCooldown(
autoScalingGroup,
request.getHonorCooldown(),
scalingPolicy.getCooldown(),
- scalingPolicy.getAdjustmentType().adjustCapacity(
+ desiredCapacity,
+ String.format( isCloudWatch ?
+ "a CloudWatch alarm triggered policy %1$s changing the desired capacity from %2$d to %3$d" :
+ "a user request executed policy %1$s changing the desired capacity from %2$d to %3$d",
+ scalingPolicy.getDisplayName(),
autoScalingGroup.getDesiredCapacity(),
- scalingPolicy.getScalingAdjustment(),
- Objects.firstNonNull( scalingPolicy.getMinAdjustmentStep(), 0 ),
- Objects.firstNonNull( autoScalingGroup.getMinSize(), 0 ),
- Objects.firstNonNull( autoScalingGroup.getMaxSize(), Integer.MAX_VALUE )
- ) );
+ desiredCapacity ) );
}
} );
} catch( Exception e ) {
@@ -919,7 +1000,7 @@ public void fire( final AutoScalingGroup autoScalingGroup ) {
public DescribeAutoScalingInstancesResponseType describeAutoScalingInstances( final DescribeAutoScalingInstancesType request ) throws EucalyptusCloudException {
final DescribeAutoScalingInstancesResponseType reply = request.getReply( );
- //TODO:STEVE: MaxRecords / NextToken support for DescribeAutoScalingInstances
+ //TODO: MaxRecords / NextToken support for DescribeAutoScalingInstances
final Context ctx = Contexts.lookup( );
final boolean showAll = request.instanceIds().remove( "verbose" );
@@ -1036,8 +1117,38 @@ public DeleteAutoScalingGroupResponseType deleteAutoScalingGroup( final DeleteAu
return reply;
}
- public DisableMetricsCollectionResponseType disableMetricsCollection(DisableMetricsCollectionType request) throws EucalyptusCloudException {
- DisableMetricsCollectionResponseType reply = request.getReply( );
+ public DisableMetricsCollectionResponseType disableMetricsCollection( final DisableMetricsCollectionType request ) throws EucalyptusCloudException {
+ final DisableMetricsCollectionResponseType reply = request.getReply( );
+
+ final Context ctx = Contexts.lookup( );
+ try {
+ final AccountFullName accountFullName = ctx.getUserFullName().asAccountFullName();
+ final Callback<AutoScalingGroup> groupCallback = new Callback<AutoScalingGroup>() {
+ @Override
+ public void fire( final AutoScalingGroup autoScalingGroup ) {
+ if ( RestrictedTypes.filterPrivileged().apply( autoScalingGroup ) ) {
+ final Set<MetricCollectionType> metricsToDisable = EnumSet.allOf( MetricCollectionType.class );
+ if ( request.getMetrics() != null && !request.getMetrics().getMember().isEmpty() ) {
+ metricsToDisable.clear();
+ Iterables.addAll( metricsToDisable, Iterables.transform(
+ request.getMetrics().getMember(),
+ Enums.valueOfFunction(MetricCollectionType.class) ) );
+ }
+ autoScalingGroup.getEnabledMetrics().removeAll( metricsToDisable );
+ }
+ }
+ };
+
+ autoScalingGroups.update(
+ accountFullName,
+ request.getAutoScalingGroupName(),
+ groupCallback );
+ } catch ( AutoScalingMetadataNotFoundException e ) {
+ throw new ValidationErrorException( "Auto scaling group not found: " + request.getAutoScalingGroupName() );
+ } catch ( Exception e ) {
+ handleException( e );
+ }
+
return reply;
}
@@ -1054,30 +1165,38 @@ public void fire( final AutoScalingGroup autoScalingGroup ) {
if ( request.availabilityZones() != null && !request.availabilityZones().isEmpty() )
autoScalingGroup.updateAvailabilityZones( Lists.newArrayList( Sets.newLinkedHashSet( request.availabilityZones() ) ) );
if ( request.getDefaultCooldown() != null )
- autoScalingGroup.setDefaultCooldown( Numbers.intValue( request.getDefaultCooldown() ) );
- if ( request.getDesiredCapacity() != null )
- autoScalingGroup.updateDesiredCapacity( Numbers.intValue( request.getDesiredCapacity() ) );
- if ( request.getHealthCheckGracePeriod() != null )
- autoScalingGroup.setHealthCheckGracePeriod( Numbers.intValue( request.getHealthCheckGracePeriod() ) );
- if ( request.getHealthCheckType() != null )
- autoScalingGroup.setHealthCheckType( Enums.valueOfFunction( HealthCheckType.class ).apply( request.getHealthCheckType() ) );
- if ( request.getLaunchConfigurationName() != null )
+ autoScalingGroup.setDefaultCooldown( Numbers.intValue( request.getDefaultCooldown( ) ) );
+ if ( request.getHealthCheckGracePeriod( ) != null )
+ autoScalingGroup.setHealthCheckGracePeriod( Numbers.intValue( request.getHealthCheckGracePeriod( ) ) );
+ if ( request.getHealthCheckType( ) != null )
+ autoScalingGroup.setHealthCheckType( Enums.valueOfFunction( HealthCheckType.class ).apply( request.getHealthCheckType( ) ) );
+ if ( request.getLaunchConfigurationName( ) != null )
try {
autoScalingGroup.setLaunchConfiguration( launchConfigurations.lookup( accountFullName, request.getLaunchConfigurationName() ) );
} catch ( AutoScalingMetadataNotFoundException e ) {
throw Exceptions.toUndeclared( new ValidationErrorException( "Launch configuration not found: " + request.getLaunchConfigurationName() ) );
} catch ( AutoScalingMetadataException e ) {
throw Exceptions.toUndeclared( e );
}
- if ( request.getMaxSize() != null )
+ if ( request.getMaxSize( ) != null )
autoScalingGroup.setMaxSize( Numbers.intValue( request.getMaxSize() ) );
- if ( request.getMinSize() != null )
- autoScalingGroup.setMinSize( Numbers.intValue( request.getMinSize() ) );
+ if ( request.getMinSize( ) != null )
+ autoScalingGroup.setMinSize( Numbers.intValue( request.getMinSize( ) ) );
if ( request.terminationPolicies() != null && !request.terminationPolicies().isEmpty() )
autoScalingGroup.setTerminationPolicies( Lists.newArrayList(
Sets.newLinkedHashSet( Iterables.filter(
- Iterables.transform( request.terminationPolicies(), Enums.valueOfFunction( TerminationPolicyType.class ) ),
- Predicates.not( Predicates.isNull() ) ) ) ) );
+ Iterables.transform( request.terminationPolicies( ), Enums.valueOfFunction( TerminationPolicyType.class ) ),
+ Predicates.not( Predicates.isNull( ) ) ) ) ) );
+ if ( request.getDesiredCapacity() != null ) {
+ Integer updatedDesiredCapacity = Numbers.intValue( request.getDesiredCapacity( ) );
+ autoScalingGroup.updateDesiredCapacity(
+ updatedDesiredCapacity,
+ String.format("a user request update of AutoScalingGroup constraints to min: %1$d, max: %2$d, desired: %4$d changing the desired capacity from %3$d to %4$d",
+ autoScalingGroup.getMinSize(),
+ autoScalingGroup.getMaxSize(),
+ autoScalingGroup.getDesiredCapacity(),
+ updatedDesiredCapacity ) );
+ }
if ( autoScalingGroup.getDesiredCapacity() < autoScalingGroup.getMinSize() ) {
throw Exceptions.toUndeclared( new ValidationErrorException( "DesiredCapacity must not be less than MinSize" ) );
@@ -1119,7 +1238,7 @@ public void fire( final AutoScalingGroup autoScalingGroup ) {
public DescribeLaunchConfigurationsResponseType describeLaunchConfigurations(DescribeLaunchConfigurationsType request) throws EucalyptusCloudException {
final DescribeLaunchConfigurationsResponseType reply = request.getReply( );
- //TODO:STEVE: MaxRecords / NextToken support for DescribeLaunchConfigurations
+ //TODO: MaxRecords / NextToken support for DescribeLaunchConfigurations
final Context ctx = Contexts.lookup( );
final boolean showAll = request.launchConfigurationNames().remove( "verbose" );
@@ -1163,8 +1282,14 @@ public PutScheduledUpdateGroupActionResponseType putScheduledUpdateGroupAction(P
return reply;
}
- public DescribeMetricCollectionTypesResponseType describeMetricCollectionTypes(DescribeMetricCollectionTypesType request) throws EucalyptusCloudException {
- DescribeMetricCollectionTypesResponseType reply = request.getReply( );
+ public DescribeMetricCollectionTypesResponseType describeMetricCollectionTypes( final DescribeMetricCollectionTypesType request ) throws EucalyptusCloudException {
+ final DescribeMetricCollectionTypesResponseType reply = request.getReply( );
+
+ reply.getDescribeMetricCollectionTypesResult().setMetrics( new MetricCollectionTypes(
+ Collections2.transform(
+ Collections2.filter( EnumSet.allOf( MetricCollectionType.class ), RestrictedTypes.filterPrivilegedWithoutOwner() ),
+ Strings.toStringFunction() ) ) );
+
return reply;
}
@@ -1178,11 +1303,15 @@ public SetDesiredCapacityResponseType setDesiredCapacity( final SetDesiredCapaci
public void fire( final AutoScalingGroup autoScalingGroup ) {
if ( RestrictedTypes.filterPrivileged().apply( autoScalingGroup ) ) {
failIfScaling( activityManager, autoScalingGroup );
+ final Integer desiredCapacity = Numbers.intValue( request.getDesiredCapacity( ) );
setDesiredCapacityWithCooldown(
autoScalingGroup,
request.getHonorCooldown(),
- null,
- Numbers.intValue( request.getDesiredCapacity() ) );
+ null,
+ desiredCapacity,
+ String.format( "a user request explicitly set group desired capacity changing the desired capacity from %1$d to %2$d",
+ autoScalingGroup.getDesiredCapacity(),
+ desiredCapacity ) );
}
}
};
@@ -1256,14 +1385,19 @@ private static void failIfScaling( final ActivityManager activityManager,
}
}
+ private static boolean scalingProcessEnabled( final ScalingProcessType type, final AutoScalingGroup group ) {
+ return !AutoScalingConfiguration.getSuspendedProcesses().contains( type ) && type.apply( group );
+ }
+
private static void setDesiredCapacityWithCooldown( final AutoScalingGroup autoScalingGroup,
final Boolean honorCooldown,
final Integer cooldown,
- final int capacity ) {
+ final int capacity,
+ final String reason ) {
final long cooldownMs = TimeUnit.SECONDS.toMillis( Objects.firstNonNull( cooldown, autoScalingGroup.getDefaultCooldown() ) );
if ( !Objects.firstNonNull( honorCooldown, Boolean.FALSE ) ||
( System.currentTimeMillis() - autoScalingGroup.getCapacityTimestamp().getTime() ) > cooldownMs ) {
- autoScalingGroup.updateDesiredCapacity( capacity );
+ autoScalingGroup.updateDesiredCapacity( capacity, reason );
autoScalingGroup.setCapacityTimestamp( new Date() );
} else {
throw Exceptions.toUndeclared( new InternalFailureException("Group is in cooldown") );
View
74 ...odules/autoscaling/src/main/java/com/eucalyptus/autoscaling/activities/ActivityCause.java
@@ -0,0 +1,74 @@
+/*************************************************************************
+ * 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.activities;
+
+import java.util.Date;
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+import com.eucalyptus.crypto.util.Timestamps;
+
+/**
+ *
+ */
+@Embeddable
+public class ActivityCause {
+
+ @Temporal( TemporalType.TIMESTAMP)
+ @Column(name = "metadata_timestamp", nullable = false, updatable = false)
+ private Date timestamp;
+
+ @Column(name = "metadata_cause", nullable = false, updatable = false)
+ private String cause;
+
+ public ActivityCause() {
+ }
+
+ public ActivityCause( final String cause ) {
+ this( new Date(), cause );
+ }
+
+ public ActivityCause( final Date timestamp,
+ final String cause ) {
+ this.timestamp = timestamp;
+ this.cause = cause;
+ }
+
+ public Date getTimestamp() {
+ return timestamp;
+ }
+
+ public void setTimestamp( final Date timestamp ) {
+ this.timestamp = timestamp;
+ }
+
+ public String getCause() {
+ return cause;
+ }
+
+ public void setCause( final String cause ) {
+ this.cause = cause;
+ }
+
+ public String toString() {
+ return "At " + Timestamps.formatIso8601Timestamp( getTimestamp() ) + " " + getCause() + ".";
+ }
+}
View
746 ...ules/autoscaling/src/main/java/com/eucalyptus/autoscaling/activities/ActivityManager.java
@@ -36,8 +36,8 @@
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
+import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.apache.log4j.Logger;
import com.eucalyptus.auth.Accounts;
@@ -47,10 +47,13 @@
import com.eucalyptus.auth.policy.ern.EuareResourceName;
import com.eucalyptus.auth.principal.AccountFullName;
import com.eucalyptus.autoscaling.common.AutoScaling;
+import com.eucalyptus.autoscaling.config.AutoScalingConfiguration;
import com.eucalyptus.autoscaling.configurations.LaunchConfiguration;
import com.eucalyptus.autoscaling.groups.AutoScalingGroup;
import com.eucalyptus.autoscaling.groups.AutoScalingGroups;
+import com.eucalyptus.autoscaling.groups.GroupScalingCause;
import com.eucalyptus.autoscaling.groups.HealthCheckType;
+import com.eucalyptus.autoscaling.groups.MetricCollectionType;
import com.eucalyptus.autoscaling.groups.PersistenceAutoScalingGroups;
import com.eucalyptus.autoscaling.groups.ScalingProcessType;
import com.eucalyptus.autoscaling.groups.SuspendedProcess;
@@ -68,21 +71,27 @@
import com.eucalyptus.bootstrap.Bootstrap;
import com.eucalyptus.cloudwatch.DescribeAlarmsResponseType;
import com.eucalyptus.cloudwatch.DescribeAlarmsType;
+import com.eucalyptus.cloudwatch.Dimension;
+import com.eucalyptus.cloudwatch.Dimensions;
import com.eucalyptus.cloudwatch.MetricAlarm;
+import com.eucalyptus.cloudwatch.MetricData;
+import com.eucalyptus.cloudwatch.MetricDatum;
+import com.eucalyptus.cloudwatch.PutMetricDataResponseType;
+import com.eucalyptus.cloudwatch.PutMetricDataType;
import com.eucalyptus.cloudwatch.ResourceList;
import com.eucalyptus.component.Topology;
import com.eucalyptus.component.id.Eucalyptus;
import com.eucalyptus.event.ClockTick;
import com.eucalyptus.event.EventListener;
import com.eucalyptus.event.Listeners;
+import com.eucalyptus.event.SystemClock;
import com.eucalyptus.loadbalancing.DeregisterInstancesFromLoadBalancerResponseType;
import com.eucalyptus.loadbalancing.DeregisterInstancesFromLoadBalancerType;
import com.eucalyptus.loadbalancing.DescribeInstanceHealthResponseType;
import com.eucalyptus.loadbalancing.DescribeInstanceHealthType;
import com.eucalyptus.loadbalancing.DescribeLoadBalancersResponseType;
import com.eucalyptus.loadbalancing.DescribeLoadBalancersType;
import com.eucalyptus.loadbalancing.Instance;
-import com.eucalyptus.loadbalancing.InstanceState;
import com.eucalyptus.loadbalancing.LoadBalancerDescription;
import com.eucalyptus.loadbalancing.LoadBalancerNames;
import com.eucalyptus.loadbalancing.RegisterInstancesWithLoadBalancerResponseType;
@@ -97,9 +106,12 @@
import com.eucalyptus.util.async.Futures;
import com.eucalyptus.vmtypes.DescribeVmTypesResponseType;
import com.eucalyptus.vmtypes.DescribeVmTypesType;
+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.base.Predicates;
+import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.HashMultimap;
@@ -151,24 +163,72 @@
ActivityStatusCode.Failed,
ActivityStatusCode.Successful );
+ private static final Set<MetricCollectionType> instanceMetrics = EnumSet.of(
+ MetricCollectionType.GroupInServiceInstances,
+ MetricCollectionType.GroupPendingInstances,
+ MetricCollectionType.GroupTerminatingInstances,
+ MetricCollectionType.GroupTotalInstances );
+
private static final String INSTANCE_PROFILE_RESOURCE =
PolicySpec.qualifiedName( PolicySpec.VENDOR_IAM, PolicySpec.IAM_RESOURCE_INSTANCE_PROFILE );
- //TODO:STEVE: What do we want to expose as configuration settings?
- private static final long activityTimeout = TimeUnit.MINUTES.toMillis( 5 );
- private static final int maxLaunchIncrement = 20;
- private static final int maxRegistrationRetries = 5;
- private static final long zoneFailureThreshold = TimeUnit.MINUTES.toMillis( 5 );
- private static final long suspensionTimeout = TimeUnit.DAYS.toMillis( 1 );
- private static final int suspensionLaunchAttemptsThreshold = 15;
-
private final ScalingActivities scalingActivities;
private final AutoScalingGroups autoScalingGroups;
private final AutoScalingInstances autoScalingInstances;
private final ZoneUnavailabilityMarkers zoneAvailabilityMarkers;
private final ZoneMonitor zoneMonitor;
private final BackoffRunner runner = BackoffRunner.getInstance( );
- private final ConcurrentMap<String,Integer> launchFailureCounters = Maps.newConcurrentMap();
+ private final ConcurrentMap<String,Integer> launchFailureCounters = Maps.newConcurrentMap(); // TODO:STEVE:expire entries (also below)
+ private final ConcurrentMap<String,Long> untrackedInstanceTimestamps = Maps.newConcurrentMap();
+ private final List<UnstableInstanceState> unstableInstanceStates = ImmutableList.<UnstableInstanceState>builder()
+ .add( state( LifecycleState.Terminating, ConfigurationState.Instantiated, terminateInstancesTask() ) )
+ .add( state( LifecycleState.Terminating, ConfigurationState.Registered, removeFromLoadBalancerOrTerminate() ) )
+ .add( state( LifecycleState.InService, ConfigurationState.Instantiated, addToLoadBalancer() ) )
+ .build();
+ private final List<ScalingTask> scalingTasks = ImmutableList.<ScalingTask>builder()
+ .add( new ScalingTask( 30, ActivityTask.Timeout ) { @Override void doWork( ) throws Exception { timeoutScalingActivities( ); } } )
+ .add( new ScalingTask( 3600, ActivityTask.Expiry ) { @Override void doWork( ) throws Exception { deleteExpiredActivities( ); } } )
+ .add( new ScalingTask( 10, ActivityTask.ZoneHealth ) { @Override void doWork( ) throws Exception { updateUnavailableZones( ); } } )
+ .add( new ScalingTask( 10, ActivityTask.Recovery ) { @Override void doWork( ) throws Exception { progressUnstableStates( ); } } )
+ .add( new ScalingTask( 10, ActivityTask.Scaling ) { @Override void doWork( ) throws Exception { scalingActivities( ); } } )
+ .add( new ScalingTask( 10, ActivityTask.Scaling ) { @Override void doWork( ) throws Exception { replaceUnhealthy( ); } } )
+ .add( new ScalingTask( 10, ActivityTask.InstanceCleanup ) { @Override void doWork( ) throws Exception { runningInstanceChecks( ); } } )
+ .add( new ScalingTask( 10, ActivityTask.MetricsSubmission ) { @Override void doWork( ) throws Exception { submitMetrics( ); } } )
+ .build( );
+
+ private static UnstableInstanceState state( final LifecycleState lifecycleState,
+ final ConfigurationState configurationState,
+ final Function<Iterable<AutoScalingInstance>,? extends ScalingProcessTask<?>> stateProgressFunction ) {
+ return new UnstableInstanceState( lifecycleState, configurationState, stateProgressFunction );
+ }
+
+ private static final class UnstableInstanceState {
+ private final LifecycleState lifecycleState;
+ private final ConfigurationState configurationState;
+ private final Function<Iterable<AutoScalingInstance>,? extends ScalingProcessTask<?>> stateProgressFunction;
+
+ private UnstableInstanceState( final LifecycleState lifecycleState,
+ final ConfigurationState configurationState,
+ final Function<Iterable<AutoScalingInstance>,? extends ScalingProcessTask<?>> stateProgressFunction ) {
+ this.lifecycleState = lifecycleState;
+ this.configurationState = configurationState;
+ this.stateProgressFunction = stateProgressFunction;
+ }
+
+ public LifecycleState getLifecycleState() {
+ return lifecycleState;
+ }
+
+ public ConfigurationState getConfigurationState() {
+ return configurationState;
+ }
+
+ public Function<Iterable<AutoScalingInstance>, ? extends ScalingProcessTask<?>> getStateProgressFunction() {
+ return stateProgressFunction;
+ }
+ }
+
+ public enum ActivityTask { Timeout, Expiry, ZoneHealth, Recovery, Scaling, InstanceCleanup, MetricsSubmission }
public ActivityManager() {
this(
@@ -192,109 +252,13 @@ protected ActivityManager( final ScalingActivities scalingActivities,
}
public void doScaling() {
- timeoutScalingActivities( );
-
- // Check for zone failures
- final Set<String> unavailableZones = zoneMonitor.getUnavailableZones( zoneFailureThreshold );
- try {
- zoneAvailabilityMarkers.updateUnavailableZones( unavailableZones, new ZoneCallback(){
- @Override
- public void notifyChangedZones( final Set<String> zones ) throws AutoScalingMetadataException {
- autoScalingGroups.markScalingRequiredForZones( zones );
- }
- } );
- } catch ( Exception e ) {
- logger.error( e, e );
- }
-
- // Restore old termination attempts
- try {
- final List<AutoScalingInstance> instancesToTerminate =
- autoScalingInstances.listByState( LifecycleState.Terminating, ConfigurationState.Instantiated );
- final Set<String> groupArns = Sets.newHashSet( Iterables.transform( instancesToTerminate, AutoScalingInstances.groupArn() ) );
- for ( final String groupArn : groupArns ) {
- final Iterable<AutoScalingInstance> groupInstances =
- Iterables.filter( instancesToTerminate, CollectionUtils.propertyPredicate( groupArn, AutoScalingInstances.groupArn() ) );
- runTask( terminateInstancesTask( groupInstances ) );
- }
- } catch ( Exception e ) {
- logger.error( e, e );
- }
-
- // Progress instances through termination
- try {
- final List<AutoScalingInstance> instancesToDeregister =
- autoScalingInstances.listByState( LifecycleState.Terminating, ConfigurationState.Registered );
- final Set<String> groupArns = Sets.newHashSet( Iterables.transform( instancesToDeregister, AutoScalingInstances.groupArn() ) );
- for ( final String groupArn : groupArns ) {
- final Iterable<AutoScalingInstance> groupInstances =
- Iterables.filter( instancesToDeregister, CollectionUtils.propertyPredicate( groupArn, AutoScalingInstances.groupArn() ) );
- runTask( removeFromLoadBalancerOrTerminate(
- Iterables.get( groupInstances, 0 ).getAutoScalingGroup(),
- Lists.newArrayList( Iterables.transform( groupInstances, AutoScalingInstances.instanceId() ) ) ) );
- }
- } catch ( Exception e ) {
- logger.error( e, e );
- }
-
- // Progress instances through launch
- try {
- final List<AutoScalingInstance> unregisteredInstances =
- autoScalingInstances.listByState( LifecycleState.InService, ConfigurationState.Instantiated );
- final Set<String> groupArns = Sets.newHashSet( Iterables.transform( unregisteredInstances, AutoScalingInstances.groupArn() ) );
- for ( final String groupArn : groupArns ) {
- final Iterable<AutoScalingInstance> groupInstances =
- Iterables.filter( unregisteredInstances, CollectionUtils.propertyPredicate( groupArn, AutoScalingInstances.groupArn() ) );
- runTask( addToLoadBalancer( groupInstances ) );
- }
- } catch ( Exception e ) {
- logger.error( e, e );
- }
-
- // Launch and terminate
- try {
- for ( final AutoScalingGroup group : autoScalingGroups.listRequiringScaling() ) {
- runTask( perhapsScale( group ) );
- }
- } catch ( Exception e ) {
- logger.error( e, e );
- }
-
- // Replace unhealthy
- try {
- for ( final AutoScalingGroup group : autoScalingGroups.listRequiringInstanceReplacement() ) {
- runTask( perhapsReplaceInstances( group ) ) ;
- }
- } catch ( Exception e ) {
- logger.error( e, e );
- }
-
- // Monitor instances
- final Map<String,AutoScalingGroup> autoScalingAccounts = Maps.newHashMap();
- try {
- for ( final AutoScalingGroup group : autoScalingGroups.listRequiringMonitoring( 10000L ) ) {
- autoScalingAccounts.put( group.getOwnerAccountNumber(), group );
- final List<AutoScalingInstance> groupInstances = autoScalingInstances.listByGroup( group );
- if ( !groupInstances.isEmpty() ) runTask( new MonitoringScalingProcessTask(
- group,
- Lists.newArrayList( Iterables.transform( Iterables.filter( groupInstances, LifecycleState.Pending ), instanceId() ) ),
- Lists.newArrayList( Iterables.transform( Iterables.filter( groupInstances, LifecycleState.InService ), instanceId() ) )
- ) );
- }
- } catch ( Exception e ) {
- logger.error( e, e );
- }
-
- // Terminate rogue instances
- try {
- for ( final AutoScalingGroup group : autoScalingAccounts.values() ) {
- runTask( new UntrackedInstanceTerminationScalingProcessTask( group ) );
+ for ( final ScalingTask scalingTask : scalingTasks ) {
+ try {
+ scalingTask.perhapsWork( );
+ } catch ( Exception e ) {
+ logger.error( e, e );
}
- } catch ( Exception e ) {
- logger.error( e, e );
}
-
- //TODO:STEVE: When do we delete old scaling activities? (retain 6 weeks of activities by default as per AWS)
}
public boolean scalingInProgress( final AutoScalingGroup group ) {
@@ -380,6 +344,138 @@ protected long timestamp() {
return System.currentTimeMillis();
}
+ /**
+ * Periodically executed scaling work.
+ *
+ * If scaling activities are not updated for some time we will fail them.
+ *
+ * Activities should not require this cleanup, this is an error case.
+ */
+ private void timeoutScalingActivities( ) throws AutoScalingMetadataException {
+ for ( final ScalingActivity activity : scalingActivities.listByActivityStatusCode( null, completedActivityStates ) ) {
+ if ( !completedActivityStates.contains( activity.getStatusCode( ) ) &&
+ isTimedOut( activity.getLastUpdateTimestamp() ) ) {
+ scalingActivities.update( activity.getOwner(),
+ activity.getActivityId(),
+ new Callback<ScalingActivity>(){
+ @Override
+ public void fire( final ScalingActivity scalingActivity ) {
+ scalingActivity.setStatusCode( ActivityStatusCode.Cancelled );
+ scalingActivity.setEndTime( new Date() );
+ }
+ } );
+ }
+ }
+ }
+
+ /**
+ * Periodically executed scaling work.
+ */
+ private void deleteExpiredActivities() throws AutoScalingMetadataException {
+ logger.debug( "Deleting expired scaling activities" );
+ scalingActivities.deleteByCreatedAge( null, System.currentTimeMillis() - AutoScalingConfiguration.getActivityExpiryMillis() );
+ }
+
+ /**
+ * Periodically executed scaling work.
+ */
+ private void runningInstanceChecks() {
+ final Map<String,AutoScalingGroup> autoScalingAccounts = Maps.newHashMap( );
+ try {
+ for ( final AutoScalingGroup group : autoScalingGroups.listRequiringMonitoring( 10000L ) ) {
+ autoScalingAccounts.put( group.getOwnerAccountNumber(), group );
+ final List<AutoScalingInstance> groupInstances = autoScalingInstances.listByGroup( group );
+ if ( !groupInstances.isEmpty() ) runTask( new MonitoringScalingProcessTask(
+ group,
+ Lists.newArrayList( Iterables.transform( Iterables.filter( groupInstances, LifecycleState.Pending ), instanceId( ) ) ),
+ Lists.newArrayList( Iterables.transform( Iterables.filter( groupInstances, LifecycleState.InService ), instanceId() ) )
+ ) );
+ }
+ } catch ( Exception e ) {
+ logger.error( e, e );
+ }
+
+ // Terminate rogue instances
+ try {
+ for ( final AutoScalingGroup group : autoScalingAccounts.values() ) {
+ runTask( new UntrackedInstanceTerminationScalingProcessTask( group ) );
+ }
+ } catch ( Exception e ) {
+ logger.error( e, e );
+ }
+ }
+
+ /**
+ * Periodically executed scaling work.
+ */
+ private void submitMetrics() {
+ try {
+ for ( final AutoScalingGroup group : autoScalingGroups.listRequiringMonitoring( 10000L ) ) {
+ if ( !group.getEnabledMetrics().isEmpty() ) {
+ final List<AutoScalingInstance> groupInstances = Sets.intersection( group.getEnabledMetrics(), instanceMetrics ).isEmpty() ?
+ Collections.<AutoScalingInstance>emptyList() :
+ autoScalingInstances.listByGroup( group );
+ runTask( new MetricsSubmissionScalingProcessTask(
+ group,
+ groupInstances ) );
+ }
+ }
+ } catch ( Exception e ) {
+ logger.error( e, e );
+ }
+ }
+
+ /**
+ * Periodically executed scaling work.
+ */
+ private void replaceUnhealthy() throws AutoScalingMetadataException {
+ for ( final AutoScalingGroup group : autoScalingGroups.listRequiringInstanceReplacement() ) {
+ runTask( perhapsReplaceInstances( group ) ) ;
+ }
+ }
+
+ /**
+ * Periodically executed scaling work.
+ */
+ private void scalingActivities() throws AutoScalingMetadataException {
+ for ( final AutoScalingGroup group : autoScalingGroups.listRequiringScaling() ) {
+ runTask( perhapsScale( group ) );
+ }
+ }
+
+ /**
+ * Periodically executed scaling work.
+ */
+ private void progressUnstableStates() {
+ for ( final UnstableInstanceState state : unstableInstanceStates ) {
+ try {
+ final List<AutoScalingInstance> instanceInState =
+ autoScalingInstances.listByState( state.getLifecycleState(), state.getConfigurationState() );
+ final Set<String> groupArns = Sets.newHashSet( Iterables.transform( instanceInState, AutoScalingInstances.groupArn() ) );
+ for ( final String groupArn : groupArns ) {
+ final Iterable<AutoScalingInstance> groupInstances =
+ Iterables.filter( instanceInState, CollectionUtils.propertyPredicate( groupArn, AutoScalingInstances.groupArn() ) );
+ runTask( state.getStateProgressFunction().apply( groupInstances ) );
+ }
+ } catch ( Exception e ) {
+ logger.error( e, e );
+ }
+ }
+ }
+
+ /**
+ * Periodically executed scaling work.
+ */
+ private void updateUnavailableZones() throws AutoScalingMetadataException {
+ final Set<String> unavailableZones = zoneMonitor.getUnavailableZones( AutoScalingConfiguration.getZoneFailureThresholdMillis() );
+ zoneAvailabilityMarkers.updateUnavailableZones( unavailableZones, new ZoneCallback(){
+ @Override
+ public void notifyChangedZones( final Set<String> zones ) throws AutoScalingMetadataException {
+ autoScalingGroups.markScalingRequiredForZones( zones );
+ }
+ } );
+ }
+
private List<String> validateReferences( final OwnerFullName owner,
final Iterable<String> availabilityZones,
final Iterable<String> loadBalancerNames,
@@ -450,6 +546,10 @@ private void validateIamInstanceProfile( final OwnerFullName owner,
}
}
+ private boolean scalingProcessEnabled( final ScalingProcessType type, final AutoScalingGroup group ) {
+ return !AutoScalingConfiguration.getSuspendedProcesses().contains( type ) && type.apply( group );
+ }
+
private void setScalingNotRequired( final AutoScalingGroup group ) {
try {
updateScalingRequiredFlag( group, false );
@@ -466,17 +566,31 @@ private void updateScalingRequiredFlag( final AutoScalingGroup group,
new Callback<AutoScalingGroup>(){
@Override
public void fire( final AutoScalingGroup autoScalingGroup ) {
- if ( scalingRequired || group.getVersion().equals( autoScalingGroup.getVersion() ) )
+ if ( scalingRequired || group.getVersion().equals( autoScalingGroup.getVersion() ) ) {
autoScalingGroup.setScalingRequired( scalingRequired );
+ if ( !scalingRequired ) {
+ autoScalingGroup.setScalingCauses( Lists.<GroupScalingCause>newArrayList() );
+ }
+ }
}
} );
}
+ private Function<Iterable<AutoScalingInstance>,TerminateInstancesScalingProcessTask> terminateInstancesTask() {
+ return new Function<Iterable<AutoScalingInstance>,TerminateInstancesScalingProcessTask>(){
+ @Override
+ public TerminateInstancesScalingProcessTask apply( final Iterable<AutoScalingInstance> groupInstances ) {
+ return terminateInstancesTask( groupInstances );
+ }
+ };
+ }
+
private TerminateInstancesScalingProcessTask terminateInstancesTask( final Iterable<AutoScalingInstance> groupInstances ) {
return new TerminateInstancesScalingProcessTask(
Iterables.get( groupInstances, 0 ).getAutoScalingGroup(),
Iterables.get( groupInstances, 0 ).getAutoScalingGroup().getCapacity(),
Lists.newArrayList( Iterables.transform( groupInstances, AutoScalingInstances.instanceId() ) ),
+ Collections.<ActivityCause>emptyList(),
false,
true,
true );
@@ -497,7 +611,7 @@ private TerminateInstancesScalingProcessTask terminateInstancesTask( final Itera
} else {
// First terminate instances in zones that are no longer in use
final Set<String> groupZones = Sets.newLinkedHashSet( group.getAvailabilityZones() );
- groupZones.removeAll( zoneMonitor.getUnavailableZones( zoneFailureThreshold ) ) ;
+ groupZones.removeAll( zoneMonitor.getUnavailableZones( AutoScalingConfiguration.getZoneFailureThresholdMillis() ) ) ;
final Set<String> unwantedZones = Sets.newHashSet( Iterables.transform( currentInstances, availabilityZone() ) );
unwantedZones.removeAll( groupZones );
@@ -535,23 +649,32 @@ private TerminateInstancesScalingProcessTask terminateInstancesTask( final Itera
} catch ( final Exception e ) {
logger.error( e, e );
}
- return removeFromLoadBalancerOrTerminate( group, currentCapacity, instancesToTerminate, false );
+
+ final List<ActivityCause> causes = Lists.newArrayList();
+ causes.add( new ActivityCause( String.format( "an instance was taken out of service in response to a difference between desired and actual capacity, shrinking the capacity from %1$d to %2$d",
+ group.getCapacity(),
+ group.getCapacity() - instancesToTerminate.size() ) ) );
+ for ( final String instanceId : instancesToTerminate ) {
+ causes.add( new ActivityCause( String.format( "instance %1$s was selected for termination", instanceId ) ) );
+ }
+
+ return removeFromLoadBalancerOrTerminate( group, currentCapacity, instancesToTerminate, causes, false );
}
private ScalingProcessTask<?> perhapsReplaceInstances( final AutoScalingGroup group ) {
final List<String> instancesToTerminate = Lists.newArrayList();
- if ( ScalingProcessType.ReplaceUnhealthy.apply( group ) ) try {
+ if ( scalingProcessEnabled( ScalingProcessType.ReplaceUnhealthy, group ) ) try {
final List<AutoScalingInstance> currentInstances =
autoScalingInstances.listUnhealthyByGroup( group );
Iterables.addAll(
instancesToTerminate,
Iterables.limit(
Iterables.transform( currentInstances, AutoScalingInstances.instanceId()),
- Math.min( maxLaunchIncrement, currentInstances.size() ) ) );
+ Math.min( AutoScalingConfiguration.getMaxLaunchIncrement(), currentInstances.size() ) ) );
} catch ( final Exception e ) {
logger.error( e, e );
}
- return removeFromLoadBalancerOrTerminate( group, group.getCapacity(), instancesToTerminate, true );
+ return removeFromLoadBalancerOrTerminate( group, group.getCapacity(), instancesToTerminate, Collections.singletonList( new ActivityCause( "an instance was taken out of service in response to a health-check" ) ), true );
}
private ScalingProcessTask<?> perhapsScale( final AutoScalingGroup group ) {
@@ -560,20 +683,21 @@ private TerminateInstancesScalingProcessTask terminateInstancesTask( final Itera
currentInstances = autoScalingInstances.listByGroup( group );
} catch ( final Exception e ) {
logger.error( e, e );
- return new LaunchInstancesScalingProcessTask( group, 0 );
+ return new LaunchInstancesScalingProcessTask( group, 0, "" );
}
if ( group.getCapacity() > group.getDesiredCapacity() ) {
if ( !Iterables.all( currentInstances, Predicates.and( LifecycleState.InService, ConfigurationState.Registered, HealthStatus.Healthy ) ) ) {
// Wait for terminations / launches to complete before further scaling.
- return new LaunchInstancesScalingProcessTask( group, 0 );
+ return new LaunchInstancesScalingProcessTask( group, 0, "" );
}
return perhapsTerminateInstances( group, group.getCapacity() - group.getDesiredCapacity() );
} else {
final List<String> zones =
Lists.transform( currentInstances, AutoScalingInstances.availabilityZone() );
final Set<String> groupZones = Sets.newLinkedHashSet( group.getAvailabilityZones() );
- groupZones.removeAll( zoneMonitor.getUnavailableZones( zoneFailureThreshold ) );
+ final Set<String> unavailableZones = zoneMonitor.getUnavailableZones( AutoScalingConfiguration.getZoneFailureThresholdMillis() );
+ groupZones.removeAll( unavailableZones );
final int expectedInstancesPerZone = group.getCapacity() / Math.max( 1, groupZones.size() );
int requiredInstances = 0;
for ( final String zone : groupZones ) {
@@ -592,19 +716,49 @@ private TerminateInstancesScalingProcessTask terminateInstancesTask( final Itera
if ( requiredInstances == 0 ) {
setScalingNotRequired( group );
- } else if ( !ScalingProcessType.AZRebalance.apply( group ) &&
+ } else if ( !scalingProcessEnabled( ScalingProcessType.AZRebalance, group ) &&
group.getCapacity().equals( group.getDesiredCapacity() ) ) {
requiredInstances = 0; // rebalancing disabled
}
- return new LaunchInstancesScalingProcessTask( group, requiredInstances );
+ String cause;
+ if ( group.getCapacity() < group.getDesiredCapacity() ) {
+ cause = String.format( "an instance was started in response to a difference between desired and actual capacity, increasing the capacity from %1$d to %2$d",
+ group.getCapacity( ),
+ group.getCapacity( ) + requiredInstances );
+ } else {
+ final Set<String> groupZoneSet = Sets.newHashSet( group.getAvailabilityZones() );
+ final Set<String> invalidZoneSet = Sets.newTreeSet();
+ Iterables.addAll( invalidZoneSet, Sets.intersection( groupZoneSet, unavailableZones ) );
+ Iterables.addAll( invalidZoneSet, Sets.difference( Sets.newHashSet( zones ), groupZoneSet ) );
+ final List<Integer> invalidZoneCounts = Lists.newArrayList();
+ for ( final String zone : invalidZoneSet ) {
+ invalidZoneCounts.add( CollectionUtils.reduce( zones, 0, CollectionUtils.count( Predicates.equalTo( zone ) ) ) );
+ }
+ final String invalidZones = Joiner.on( ", " ).join( invalidZoneSet );
+ final String invalidZoneInstanceCounts = Joiner.on( ", " ).join( invalidZoneCounts );
+ cause = String.format( "invalid availability zones %1$s had %2$s instances respectively. An instance was launched to aid in migrating instances from these zones to valid ones",
+ invalidZones,
+ invalidZoneInstanceCounts );
+ }
+
+ return new LaunchInstancesScalingProcessTask( group, requiredInstances, cause );
}
}
+ private Function<Iterable<AutoScalingInstance>,AddToLoadBalancerScalingProcessTask> addToLoadBalancer() {
+ return new Function<Iterable<AutoScalingInstance>,AddToLoadBalancerScalingProcessTask>(){
+ @Override
+ public AddToLoadBalancerScalingProcessTask apply( final Iterable<AutoScalingInstance> groupInstances ) {
+ return addToLoadBalancer( groupInstances );
+ }
+ };
+ }
+
private AddToLoadBalancerScalingProcessTask addToLoadBalancer( final Iterable<AutoScalingInstance> unregisteredInstances ) {
final AutoScalingGroup group = Iterables.get( unregisteredInstances, 0 ).getAutoScalingGroup();
final List<String> instancesToRegister = Lists.newArrayList();
- if ( group.getLoadBalancerNames().isEmpty() || !ScalingProcessType.AddToLoadBalancer.apply( group ) ) {
+ if ( group.getLoadBalancerNames().isEmpty() || !scalingProcessEnabled( ScalingProcessType.AddToLoadBalancer, group ) ) {
// nothing to do, mark instances as registered
transitionToRegistered(
group,
@@ -618,33 +772,46 @@ private AddToLoadBalancerScalingProcessTask addToLoadBalancer( final Iterable<Au
return new AddToLoadBalancerScalingProcessTask( group, instancesToRegister );
}
+ private Function<Iterable<AutoScalingInstance>,ScalingProcessTask<?>> removeFromLoadBalancerOrTerminate() {
+ return new Function<Iterable<AutoScalingInstance>,ScalingProcessTask<?>>(){
+ @Override
+ public ScalingProcessTask<?> apply( final Iterable<AutoScalingInstance> groupInstances ) {
+ return removeFromLoadBalancerOrTerminate( Iterables.get( groupInstances, 0 ).getAutoScalingGroup(),
+ Lists.newArrayList( Iterables.transform( groupInstances, AutoScalingInstances.instanceId() ) ) );
+ }
+ };
+ }
+
private ScalingProcessTask<?> removeFromLoadBalancerOrTerminate( final AutoScalingGroup group,
final List<String> registeredInstances ) {
- return removeFromLoadBalancerOrTerminate( group, group.getCapacity(), registeredInstances, false );
+ return removeFromLoadBalancerOrTerminate( group, group.getCapacity(), registeredInstances, Collections.<ActivityCause>emptyList(), false );
}
private ScalingProcessTask<?> removeFromLoadBalancerOrTerminate( final AutoScalingGroup group,
final int currentCapacity,
final List<String> registeredInstances,
+ final List<ActivityCause> causes,
final boolean replace ) {
final ScalingProcessTask<?> task;
if ( group.getLoadBalancerNames().isEmpty() ) {
// deregistration not required, mark instances
transitionToDeregistered( group, registeredInstances );
- task = new TerminateInstancesScalingProcessTask( group, currentCapacity, registeredInstances, replace, true, true );
+ task = new TerminateInstancesScalingProcessTask( group, currentCapacity, registeredInstances, causes, replace, true, true );
} else {
- task = new RemoveFromLoadBalancerScalingProcessTask( group, currentCapacity, registeredInstances, replace );
+ task = new RemoveFromLoadBalancerScalingProcessTask( group, currentCapacity, registeredInstances, causes, replace );
}
return task;
}
private RunInstancesType runInstances( final AutoScalingGroup group,
final String availabilityZone,
+ final String clientToken,
final int attemptToLaunch ) {
final LaunchConfiguration launchConfiguration = group.getLaunchConfiguration();
final RunInstancesType runInstances = TypeMappers.transform( launchConfiguration, RunInstancesType.class );
runInstances.setAvailabilityZone( availabilityZone );
+ runInstances.setClientToken( clientToken );
runInstances.setMaxCount( attemptToLaunch );
return runInstances;
}
@@ -710,32 +877,6 @@ private Filter filter( final String name, final Collection<String> values ) {
return filter;
}
- /**
- * If scaling activities are not updated for some time we will fail them.
- *
- * Activities should not require this cleanup, this is an error case.
- */
- private void timeoutScalingActivities( ) {
- try {
- for ( final ScalingActivity activity : scalingActivities.list( null ) ) { //TODO:STEVE: don't list all activities
- if ( !completedActivityStates.contains( activity.getActivityStatusCode() ) &&
- isTimedOut( activity.getLastUpdateTimestamp() ) ) {
- scalingActivities.update( activity.getOwner(),
- activity.getActivityId(),
- new Callback<ScalingActivity>(){
- @Override
- public void fire( final ScalingActivity scalingActivity ) {
- scalingActivity.setActivityStatusCode( ActivityStatusCode.Cancelled );
- scalingActivity.setEndTime( new Date() );
- }
- } );
- }
- }
- } catch ( Exception e ) {
- logger.error( e, e );
- }
- }
-
private void transitionToRegistered( final AutoScalingGroup group, final List<String> instanceIds ) {
try {
autoScalingInstances.transitionConfigurationState(
@@ -761,7 +902,7 @@ private void transitionToDeregistered( final AutoScalingGroup group, final List<
}
private boolean isTimedOut( final Date timestamp ) {
- return ( timestamp() - timestamp.getTime() ) > activityTimeout;
+ return ( timestamp() - timestamp.getTime() ) > AutoScalingConfiguration.getActivityTimeoutMillis();
}
private Map<String,Integer> buildAvailabilityZoneInstanceCounts( final Collection<AutoScalingInstance> instances,
@@ -823,7 +964,7 @@ ElbClient createElbClientForUser( final String userId ) {
}
}
- CloudWatchClient createCloudWatchClientForUser( final String userId ) {
+ public CloudWatchClient createCloudWatchClientForUser( final String userId ) {
try {
final CloudWatchClient client = new CloudWatchClient( userId );
client.init();
@@ -877,7 +1018,7 @@ private boolean shouldSuspendDueToLaunchFailure( final AutoScalingGroup group )
final Integer newCount = Objects.firstNonNull( count, 0 ) + 1;
if ( ( count == null && launchFailureCounters.putIfAbsent( group.getArn(), newCount ) == null ) ||
( count != null && launchFailureCounters.replace( group.getArn(), count, newCount ) ) ) {
- return newCount >= suspensionLaunchAttemptsThreshold;
+ return newCount >= AutoScalingConfiguration.getSuspensionLaunchAttemptsThreshold();
}
}
}
@@ -886,6 +1027,30 @@ private void clearLaunchFailures( final AutoScalingGroup group ) {
launchFailureCounters.remove( group.getArn() );
}
+ private boolean shouldTerminateUntrackedInstance( final String instanceId ) {
+ while ( true ) {
+ final Long timestamp = untrackedInstanceTimestamps.get( instanceId );
+ final Long newTimestamp = Objects.firstNonNull( timestamp, timestamp() );
+ if ( ( timestamp == null && untrackedInstanceTimestamps.putIfAbsent( instanceId, newTimestamp ) == null ) ||
+ timestamp != null ) {
+ return (timestamp() - newTimestamp) >= AutoScalingConfiguration.getUntrackedInstanceTimeoutMillis();
+ }
+ }
+ }
+
+ private Predicate<String> shouldTerminateUntrackedInstance( ) {
+ return new Predicate<String>( ) {
+ @Override
+ public boolean apply( final String instanceId ) {
+ return shouldTerminateUntrackedInstance( instanceId );
+ }
+ };
+ }
+
+ private void clearUntrackedInstances( final Collection<String> instanceIds ) {
+ untrackedInstanceTimestamps.keySet().removeAll( instanceIds );
+ }
+
private interface ActivityContext {
String getUserId();
EucalyptusClient getEucalyptusClient();
@@ -955,26 +1120,50 @@ public void fire( final RES response ) {
void dispatchFailure( ActivityContext context, Throwable throwable ) {
// error, assume no instances run for now
- logger.error( "Activity error", throwable ); //TODO:STEVE: Remove failure logging and record in scaling activity details/description
- setActivityFinalStatus( ActivityStatusCode.Failed );
+ Logs.extreme().error( "Activity error", throwable );
+ setActivityFinalStatus( ActivityStatusCode.Failed, throwable.getMessage(), null );
}
abstract void dispatchSuccess( ActivityContext context, RES response );
+ void setActivityStatus( final ActivityStatusCode activityStatusCode,
+ final int progress ) {
+ updateActivity( new Callback<ScalingActivity>( ) {
+ @Override
+ public void fire( final ScalingActivity input ) {
+ input.setStatusCode( activityStatusCode );
+ input.setProgress( progress );
+ }
+ } );
+ }
+
void setActivityFinalStatus( final ActivityStatusCode activityStatusCode ) {
+ setActivityFinalStatus( activityStatusCode, null, null );
+ }
+
+ void setActivityFinalStatus( @Nonnull final ActivityStatusCode activityStatusCode,
+ @Nullable final String message,
+ @Nullable final String description ) {
+ updateActivity( new Callback<ScalingActivity>( ) {
+ @Override
+ public void fire( final ScalingActivity input ) {
+ input.setStatusCode( activityStatusCode );
+ input.setStatusMessage( message );
+ if ( description != null ) input.setDescription( description );
+ input.setProgress( 100 );
+ input.setEndTime( new Date() );
+ }
+ } );
+ }
+
+ void updateActivity( @Nonnull final Callback<ScalingActivity> callback ) {
final ScalingActivity activity = getActivity();
if ( activity.getCreationTimestamp() != null ) { // only update if persistent
try {
scalingActivities.update(
activity.getOwner(),
activity.getActivityId(),
- new Callback<ScalingActivity>(){
- @Override
- public void fire( final ScalingActivity input ) {
- input.setActivityStatusCode( activityStatusCode );
- input.setEndTime( new Date() );
- }
- } );
+ callback );
} catch ( AutoScalingMetadataNotFoundException e ) {
// this is expected when terminating instances and deleting the group
Logs.exhaust().debug( e, e );
@@ -987,19 +1176,16 @@ public void fire( final ScalingActivity input ) {
abstract class ScalingProcessTask<AT extends ScalingActivityTask> extends TaskWithBackOff implements ActivityContext {
private final AutoScalingGroup group;
- private final String activity;
private final Supplier<String> userIdSupplier;
private final AtomicReference<List<ScalingActivity>> activities =
new AtomicReference<List<ScalingActivity>>( Collections.<ScalingActivity>emptyList() );
- private volatile CheckedListenableFuture<List<Boolean>> dispatchFuture;
private volatile CheckedListenableFuture<Boolean> taskFuture;
ScalingProcessTask( final String uniqueKey,
final AutoScalingGroup group,
final String activity ) {
super( uniqueKey, activity );
this.group = group;
- this.activity = activity;
this.userIdSupplier = Suppliers.memoize( userIdSupplier( group.getOwnerAccountNumber() ) );
}
@@ -1045,8 +1231,31 @@ public VmTypesClient getVmTypesClient() {
return createVmTypesClientForUser( getUserId() );
}
+ final ActivityCause cause( final String cause ) {
+ return new ActivityCause( new Date(timestamp()), cause );
+ }
+
ScalingActivity newActivity() {
- return ScalingActivity.create( group, activity );
+ return newActivity( null, 0, null, Collections.<ActivityCause>emptyList(), null );
+ }
+
+ ScalingActivity newActivity( @Nullable final String description,
+ final int progress,
+ @Nullable final String clientToken,
+ @Nonnull final List<ActivityCause> activityCauses,
+ @Nullable final ActivityStatusCode activityStatusCode ) {
+ final List<ActivityCause> causes = Lists.newArrayList();
+ Iterables.addAll( causes, Iterables.transform( group.getScalingCauses(), CauseTransform.INSTANCE ) );
+ Iterables.addAll( causes, activityCauses );
+ final ScalingActivity scalingActivity = ScalingActivity.create( group, clientToken, causes );
+ if ( description != null ) {
+ scalingActivity.setDescription( description );
+ }
+ scalingActivity.setProgress( progress );
+ if ( activityStatusCode != null ) {
+ scalingActivity.setStatusCode( activityStatusCode );
+ }
+ return scalingActivity;
}
abstract boolean shouldRun();
@@ -1095,7 +1304,7 @@ void runTask() {
failure();
} else {
taskFuture = Futures.newGenericeFuture();
- final CheckedListenableFuture<List<Boolean>> resultFuture = dispatchFuture = Futures.allAsList( dispatchFutures );
+ final CheckedListenableFuture<List<Boolean>> resultFuture = Futures.allAsList( dispatchFutures );
resultFuture.addListener( new Runnable() {
@Override
public void run() {
@@ -1123,21 +1332,25 @@ public void run() {
private class LaunchInstanceScalingActivityTask extends ScalingActivityTask<RunInstancesResponseType> {
private final String availabilityZone;
+ private final String clientToken;
private final AtomicReference<List<String>> instanceIds = new AtomicReference<List<String>>(
Collections.<String>emptyList()
);
private LaunchInstanceScalingActivityTask( final ScalingActivity activity,
- final String availabilityZone ) {
+ final String availabilityZone,
+ final String clientToken ) {
super( activity );
this.availabilityZone = availabilityZone;
+ this.clientToken = clientToken;
}
@Override
void dispatchInternal( final ActivityContext context,
final Callback.Checked<RunInstancesResponseType> callback ) {
+ setActivityStatus( ActivityStatusCode.InProgress, 50 );
final EucalyptusClient client = context.getEucalyptusClient();
- client.dispatch( runInstances( getGroup(), availabilityZone, 1 ), callback );
+ client.dispatch( runInstances( getGroup(), availabilityZone, clientToken, 1 ), callback );
}
@Override
@@ -1160,7 +1373,7 @@ void dispatchSuccess( final ActivityContext context,
this.instanceIds.set( ImmutableList.copyOf( instanceIds ) );
- setActivityFinalStatus( ActivityStatusCode.Successful );
+ setActivityFinalStatus( ActivityStatusCode.Successful, null, String.format( "Launching a new EC2 instance: %1$s", Joiner.on(", ").join(instanceIds) ) );
}
List<String> getInstanceIds() {
@@ -1170,32 +1383,39 @@ void dispatchSuccess( final ActivityContext context,
private class LaunchInstancesScalingProcessTask extends ScalingProcessTask<LaunchInstanceScalingActivityTask> {
private final int launchCount;