From 4180bbb4a6a1a1b7ac9e1eac33e36c0cc2b3c141 Mon Sep 17 00:00:00 2001 From: chris grzegorczyk Date: Sat, 20 Apr 2013 19:51:31 -0700 Subject: [PATCH 01/14] Working patch set against Eucalyptus 3.3.0m5 --- grails-app/conf/Config.groovy | 54 ++++++++--- .../asgard/InstanceTypeController.groovy | 1 + .../asgard/AwsAutoScalingService.groovy | 30 +++--- .../netflix/asgard/AwsClientService.groovy | 15 +-- .../asgard/AwsCloudWatchService.groovy | 2 +- .../com/netflix/asgard/AwsEc2Service.groovy | 12 +-- .../asgard/AwsLoadBalancerService.groovy | 2 +- .../com/netflix/asgard/AwsS3Service.groovy | 3 +- .../com/netflix/asgard/AwsSqsService.groovy | 6 +- .../services/com/netflix/asgard/Caches.groovy | 22 ++--- .../com/netflix/asgard/InitService.groovy | 3 +- .../netflix/asgard/InstanceTypeService.groovy | 34 +++++-- grails-app/views/image/prelaunch.gsp | 2 +- src/groovy/com/netflix/asgard/Region.groovy | 91 +++++++++--------- web-app/images/worldmap/eucalyptus.png | Bin 0 -> 6937 bytes 15 files changed, 167 insertions(+), 110 deletions(-) create mode 100644 web-app/images/worldmap/eucalyptus.png diff --git a/grails-app/conf/Config.groovy b/grails-app/conf/Config.groovy index 9792dcc8..bc97d583 100644 --- a/grails-app/conf/Config.groovy +++ b/grails-app/conf/Config.groovy @@ -32,7 +32,7 @@ log4j = { } root { - info 'asgardrolling' + debug 'asgardrolling' } // Set level for all application artifacts @@ -68,7 +68,7 @@ log4j = { development { console name: 'stdout', layout: pattern(conversionPattern: '[%d{ISO8601}] %c{4} %m%n') root { - info 'stdout' + debug 'stdout' } } } @@ -134,20 +134,44 @@ cloud { // TODO: Delete these instance type hacks as soon as m3.xlarge, m3.2xlarge are in the AWS Java SDK enum instead customInstanceTypes = [ - new InstanceTypeData(linuxOnDemandPrice: 0.580, hardwareProfile: - new HardwareProfile(instanceType: 'm3.xlarge', architecture: '64-bit', - cpu: '13 EC2 Compute Units (4 virtual cores with 3.25 EC2 Compute Units each)', - description: 'M3 Extra Large Instance', - ioPerformance: 'Moderate', memory: '15 GiB', - storage: 'EBS storage only')), - new InstanceTypeData(linuxOnDemandPrice: 1.160, hardwareProfile: - new HardwareProfile(instanceType: 'm3.2xlarge', architecture: '64-bit', - cpu: '26 EC2 Compute Units (8 virtual cores with 3.25 EC2 Compute Units each)', - description: 'M3 Double Extra Large Instance', - ioPerformance: 'High', memory: '30 GiB', - storage: 'EBS storage only')), + new InstanceTypeData(linuxOnDemandPrice: 0.1, hardwareProfile: + new HardwareProfile(instanceType: 'm1.small', architecture: '64-bit', + cpu: '1 EC2 Compute Units (1 virtual cores with 1 EC2 Compute Units each)', + description: 'M1 Small Instance', + ioPerformance: 'Poor', memory: '0.25 GiB', + storage: '5 GB of instance storage')), + new InstanceTypeData(linuxOnDemandPrice: 0.2, hardwareProfile: + new HardwareProfile(instanceType: 'm1.medium', architecture: '64-bit', + cpu: '1 EC2 Compute Units (1 virtual cores with 1 EC2 Compute Units each)', + description: 'M1 Medium Instance', + ioPerformance: 'Poor', memory: '0.5 GiB', + storage: '10 GB of instance storage')), + new InstanceTypeData(linuxOnDemandPrice: 0.3, hardwareProfile: + new HardwareProfile(instanceType: 'm1.large', architecture: '64-bit', + cpu: '2 EC2 Compute Units (2 virtual cores with 1 EC2 Compute Units each)', + description: 'M1 Large Instance', + ioPerformance: 'Poor', memory: '0.5 GiB', + storage: '10 GB of instance storage')), + new InstanceTypeData(linuxOnDemandPrice: 0.5, hardwareProfile: + new HardwareProfile(instanceType: 'm1.xlarge', architecture: '64-bit', + cpu: '2 EC2 Compute Units (2 virtual cores with 1 EC2 Compute Units each)', + description: 'M1 Xtra-Large Instance', + ioPerformance: 'Poor', memory: '1 GiB', + storage: '10 GB of instance storage')), +// new InstanceTypeData(linuxOnDemandPrice: 0.580, hardwareProfile: +// new HardwareProfile(instanceType: 'm3.xlarge', architecture: '64-bit', +// cpu: '13 EC2 Compute Units (4 virtual cores with 3.25 EC2 Compute Units each)', +// description: 'M3 Extra Large Instance', +// ioPerformance: 'Moderate', memory: '15 GiB', +// storage: 'EBS storage only')), +// new InstanceTypeData(linuxOnDemandPrice: 1.160, hardwareProfile: +// new HardwareProfile(instanceType: 'm3.2xlarge', architecture: '64-bit', +// cpu: '26 EC2 Compute Units (8 virtual cores with 3.25 EC2 Compute Units each)', +// description: 'M3 Double Extra Large Instance', +// ioPerformance: 'High', memory: '30 GiB', +// storage: 'EBS storage only')), ] - spot.infoUrl = 'http://aws.amazon.com/ec2/spot-instances/' +// spot.infoUrl = 'http://aws.amazon.com/ec2/spot-instances/' } healthCheck { diff --git a/grails-app/controllers/com/netflix/asgard/InstanceTypeController.groovy b/grails-app/controllers/com/netflix/asgard/InstanceTypeController.groovy index 492ea221..af6eba68 100644 --- a/grails-app/controllers/com/netflix/asgard/InstanceTypeController.groovy +++ b/grails-app/controllers/com/netflix/asgard/InstanceTypeController.groovy @@ -30,6 +30,7 @@ class InstanceTypeController { def list = { UserContext userContext = UserContext.of(request) List instanceTypes = instanceTypeService.getInstanceTypes(userContext) + println instanceTypes Map details = [instanceTypes: instanceTypes] withFormat { html { details } diff --git a/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy b/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy index 28b75669..d8e390f9 100644 --- a/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy +++ b/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy @@ -121,7 +121,7 @@ class AwsAutoScalingService implements CacheInitializer, InitializingBean { void afterPropertiesSet() { awsClient = new MultiRegionAwsClient({ Region region -> AmazonAutoScaling client = awsClientService.create(AmazonAutoScaling) - client.setEndpoint("autoscaling.${region}.amazonaws.com") + client.setEndpoint("http://10.111.1.67:8773/services/AutoScaling") client }) } @@ -130,26 +130,26 @@ class AwsAutoScalingService implements CacheInitializer, InitializingBean { // Cluster cache has no timer. It gets triggered by the Auto Scaling Group cache callback closure. caches.allClusters.ensureSetUp( { Region region -> buildClusters(region, caches.allAutoScalingGroups.by(region).list()) }, {}, - { Region region -> - boolean awaitingLoadBalancers = caches.allLoadBalancers.by(region).isDoingFirstFill() - boolean awaitingAppInstances = caches.allApplicationInstances.by(region).isDoingFirstFill() - boolean awaitingImages = caches.allImages.by(region).isDoingFirstFill() - boolean awaitingEc2Instances = caches.allInstances.by(region).isDoingFirstFill() - !awaitingLoadBalancers && !awaitingAppInstances && !awaitingImages && !awaitingEc2Instances - } +// { Region region -> +// boolean awaitingLoadBalancers = caches.allLoadBalancers.by(region).isDoingFirstFill() +// boolean awaitingAppInstances = caches.allApplicationInstances.by(region).isDoingFirstFill() +// boolean awaitingImages = caches.allImages.by(region).isDoingFirstFill() +// boolean awaitingEc2Instances = caches.allInstances.by(region).isDoingFirstFill() +// !awaitingLoadBalancers && !awaitingAppInstances && !awaitingImages && !awaitingEc2Instances +// } ) caches.allAutoScalingGroups.ensureSetUp({ Region region -> retrieveAutoScalingGroups(region) }, { Region region -> caches.allClusters.by(region).fill() }) caches.allLaunchConfigurations.ensureSetUp({ Region region -> retrieveLaunchConfigurations(region) }) caches.allScalingPolicies.ensureSetUp({ Region region -> retrieveScalingPolicies(region) }) caches.allTerminationPolicyTypes.ensureSetUp({ Region region -> retrieveTerminationPolicyTypes() }) - caches.allScheduledActions.ensureSetUp({ Region region -> retrieveScheduledActions(region) }) - caches.allSignificantStackInstanceHealthChecks.ensureSetUp( - { Region region -> retrieveInstanceHealthChecks(region) }, {}, - { Region region -> - caches.allApplicationInstances.by(region).filled && caches.allAutoScalingGroups.by(region).filled - } - ) +// caches.allScheduledActions.ensureSetUp({ Region region -> retrieveScheduledActions(region) }) +// caches.allSignificantStackInstanceHealthChecks.ensureSetUp( +// { Region region -> retrieveInstanceHealthChecks(region) }, {}, +// { Region region -> +// caches.allApplicationInstances.by(region).filled && caches.allAutoScalingGroups.by(region).filled +// } +// ) } // Clusters diff --git a/grails-app/services/com/netflix/asgard/AwsClientService.groovy b/grails-app/services/com/netflix/asgard/AwsClientService.groovy index a125e0df..6a528b66 100644 --- a/grails-app/services/com/netflix/asgard/AwsClientService.groovy +++ b/grails-app/services/com/netflix/asgard/AwsClientService.groovy @@ -57,16 +57,19 @@ class AwsClientService implements InitializingBean { void afterPropertiesSet() { interfaceSimpleNamesToAwsClientClasses = [ +// AmazonAutoScaling: concrete(/*AmazonAutoScalingClient*/MockAmazonAutoScalingClient, MockAmazonAutoScalingClient), AmazonAutoScaling: concrete(AmazonAutoScalingClient, MockAmazonAutoScalingClient), +// AmazonCloudWatch: concrete(/*AmazonCloudWatchClient*/MockAmazonCloudWatchClient, MockAmazonCloudWatchClient), AmazonCloudWatch: concrete(AmazonCloudWatchClient, MockAmazonCloudWatchClient), AmazonEC2: concrete(AmazonEC2Client, MockAmazonEC2Client), - AmazonElasticLoadBalancing: concrete(AmazonElasticLoadBalancingClient, - MockAmazonElasticLoadBalancingClient), - AmazonRDS: concrete(AmazonRDSClient, MockAmazonRDSClient), + AmazonElasticLoadBalancing: concrete(/*AmazonElasticLoadBalancingClient*/MockAmazonElasticLoadBalancingClient,MockAmazonElasticLoadBalancingClient), +// AmazonElasticLoadBalancing: concrete(AmazonElasticLoadBalancingClient,MockAmazonElasticLoadBalancingClient), + AmazonRDS: concrete(/*AmazonRDSClient*/MockAmazonRDSClient, MockAmazonRDSClient), +// AmazonS3: concrete(/*AmazonS3Client*/MockAmazonS3Client, MockAmazonS3Client), AmazonS3: concrete(AmazonS3Client, MockAmazonS3Client), - AmazonSimpleDB: concrete(AmazonSimpleDBClient, MockAmazonSimpleDBClient), - AmazonSNS: concrete(AmazonSNSClient, MockAmazonSnsClient), - AmazonSQS: concrete(AmazonSQSClient, MockAmazonSqsClient) + AmazonSimpleDB: concrete(/*AmazonSimpleDBClient*/MockAmazonSimpleDBClient, MockAmazonSimpleDBClient), + AmazonSNS: concrete(/*AmazonSNSClient*/MockAmazonSnsClient, MockAmazonSnsClient), + AmazonSQS: concrete(/*AmazonSQSClient*/MockAmazonSqsClient, MockAmazonSqsClient) ] clientConfiguration = new ClientConfiguration() clientConfiguration.proxyHost = configService.proxyHost diff --git a/grails-app/services/com/netflix/asgard/AwsCloudWatchService.groovy b/grails-app/services/com/netflix/asgard/AwsCloudWatchService.groovy index 24a09bee..019446c1 100644 --- a/grails-app/services/com/netflix/asgard/AwsCloudWatchService.groovy +++ b/grails-app/services/com/netflix/asgard/AwsCloudWatchService.groovy @@ -54,7 +54,7 @@ class AwsCloudWatchService implements CacheInitializer, InitializingBean { void afterPropertiesSet() { awsClient = new MultiRegionAwsClient( { Region region -> AmazonCloudWatch client = awsClientService.create(AmazonCloudWatch) - client.setEndpoint("monitoring.${region}.amazonaws.com") + client.setEndpoint("http://10.111.1.67:8773/services/CloudWatch") client }) } diff --git a/grails-app/services/com/netflix/asgard/AwsEc2Service.groovy b/grails-app/services/com/netflix/asgard/AwsEc2Service.groovy index 6199271d..1c8e7e88 100644 --- a/grails-app/services/com/netflix/asgard/AwsEc2Service.groovy +++ b/grails-app/services/com/netflix/asgard/AwsEc2Service.groovy @@ -121,7 +121,7 @@ class AwsEc2Service implements CacheInitializer, InitializingBean { void afterPropertiesSet() { awsClient = awsClient ?: new MultiRegionAwsClient({ Region region -> AmazonEC2 client = awsClientService.create(AmazonEC2) - client.setEndpoint("ec2.${region}.amazonaws.com") + client.setEndpoint("http://10.111.1.67:8773/services/Eucalyptus/") client }) accounts = configService.awsAccounts @@ -187,7 +187,7 @@ class AwsEc2Service implements CacheInitializer, InitializingBean { } private Collection retrieveSubnets(Region region) { - awsClient.by(region).describeSubnets().subnets +// awsClient.by(region).describeSubnets().subnets } /** @@ -201,7 +201,7 @@ class AwsEc2Service implements CacheInitializer, InitializingBean { } private Collection retrieveVpcs(Region region) { - awsClient.by(region).describeVpcs().vpcs +// awsClient.by(region).describeVpcs().vpcs } /** @@ -638,13 +638,13 @@ class AwsEc2Service implements CacheInitializer, InitializingBean { // TODO: Delete this method after rewriting AwsResultsRetrieverSpec unit test to use some other use case DescribeSpotPriceHistoryResult describeSpotPriceHistory(Region region, DescribeSpotPriceHistoryRequest describeSpotPriceHistoryRequest) { - awsClient.by(region).describeSpotPriceHistory(describeSpotPriceHistoryRequest) +// awsClient.by(region).describeSpotPriceHistory(describeSpotPriceHistoryRequest) } // Spot Instance Requests List retrieveSpotInstanceRequests(Region region) { - awsClient.by(region).describeSpotInstanceRequests().spotInstanceRequests +// awsClient.by(region).describeSpotInstanceRequests().spotInstanceRequests } DescribeSpotInstanceRequestsResult describeSpotInstanceRequests(UserContext userContext, @@ -873,7 +873,7 @@ class AwsEc2Service implements CacheInitializer, InitializingBean { // Reservations private List retrieveReservations(Region region) { - awsClient.by(region).describeReservedInstances().reservedInstances +// awsClient.by(region).describeReservedInstances().reservedInstances } /** diff --git a/grails-app/services/com/netflix/asgard/AwsLoadBalancerService.groovy b/grails-app/services/com/netflix/asgard/AwsLoadBalancerService.groovy index b9a88245..44775940 100644 --- a/grails-app/services/com/netflix/asgard/AwsLoadBalancerService.groovy +++ b/grails-app/services/com/netflix/asgard/AwsLoadBalancerService.groovy @@ -59,7 +59,7 @@ class AwsLoadBalancerService implements CacheInitializer, InitializingBean { void afterPropertiesSet() { awsClient = awsClient ?: new MultiRegionAwsClient( { Region region -> AmazonElasticLoadBalancing client = awsClientService.create(AmazonElasticLoadBalancing) - client.setEndpoint("elasticloadbalancing.${region}.amazonaws.com") + client.setEndpoint("http://10.111.1.67:8773/services/LoadBalancing") client }) } diff --git a/grails-app/services/com/netflix/asgard/AwsS3Service.groovy b/grails-app/services/com/netflix/asgard/AwsS3Service.groovy index 6f165644..6e2dd3d0 100644 --- a/grails-app/services/com/netflix/asgard/AwsS3Service.groovy +++ b/grails-app/services/com/netflix/asgard/AwsS3Service.groovy @@ -36,7 +36,8 @@ class AwsS3Service implements InitializingBean { awsClient = new MultiRegionAwsClient( { Region region -> AmazonS3 client = awsClientService.create(AmazonS3) // Unconventional S3 endpoints. http://docs.amazonwebservices.com/general/latest/gr/index.html?rande.html - if (region != Region.US_EAST_1) { client.setEndpoint("s3-${region}.amazonaws.com") } +// if (region != Region.US_EAST_1) { client.setEndpoint("s3-${region}.amazonaws.com") } + client.setEndpoint( "http://10.111.1.67:8773/services/Walrus" ) client }) } diff --git a/grails-app/services/com/netflix/asgard/AwsSqsService.groovy b/grails-app/services/com/netflix/asgard/AwsSqsService.groovy index 582ffe93..6527b2b3 100644 --- a/grails-app/services/com/netflix/asgard/AwsSqsService.groovy +++ b/grails-app/services/com/netflix/asgard/AwsSqsService.groovy @@ -58,9 +58,9 @@ class AwsSqsService implements CacheInitializer, InitializingBean { try { return awsClient.by(region).listQueues(new ListQueuesRequest()).queueUrls.collect { new SimpleQueue(it) } } catch (AmazonServiceException ase) { - if (ase.errorCode != 'OptInRequired') { // Ignore if SQS is disabled for this account - throw ase - } +// if (ase.errorCode != 'OptInRequired') { // Ignore if SQS is disabled for this account +// throw ase +// } return [] } } diff --git a/grails-app/services/com/netflix/asgard/Caches.groovy b/grails-app/services/com/netflix/asgard/Caches.groovy index 5d4b39e2..7d8a88d1 100644 --- a/grails-app/services/com/netflix/asgard/Caches.groovy +++ b/grails-app/services/com/netflix/asgard/Caches.groovy @@ -94,22 +94,22 @@ class Caches { Caches(CachedMapBuilder cachedMapBuilder, ConfigService configService = null) { allClusters = cachedMapBuilder.of(EntityType.cluster).buildMultiRegionCachedMap() - allAutoScalingGroups = cachedMapBuilder.of(EntityType.autoScaling, 120).buildMultiRegionCachedMap() - allLaunchConfigurations = cachedMapBuilder.of(EntityType.launchConfiguration, 180).buildMultiRegionCachedMap() - allLoadBalancers = cachedMapBuilder.of(EntityType.loadBalancer, 120).buildMultiRegionCachedMap() + allAutoScalingGroups = cachedMapBuilder.of(EntityType.autoScaling, 10).buildMultiRegionCachedMap() + allLaunchConfigurations = cachedMapBuilder.of(EntityType.launchConfiguration, 10).buildMultiRegionCachedMap() + allLoadBalancers = cachedMapBuilder.of(EntityType.loadBalancer, 10).buildMultiRegionCachedMap() allSourceSecurityGroups = cachedMapBuilder.of(EntityType.sourceSecurityGroup).buildMultiRegionCachedMap() allAvailabilityZones = cachedMapBuilder.of(EntityType.availabilityZone, 3600).buildMultiRegionCachedMap() allSubnets = cachedMapBuilder.of(EntityType.subnet, 3600).buildMultiRegionCachedMap() allVpcs = cachedMapBuilder.of(EntityType.vpc, 3600).buildMultiRegionCachedMap() - allKeyPairs = cachedMapBuilder.of(EntityType.keyPair).buildMultiRegionCachedMap() - allImages = cachedMapBuilder.of(EntityType.image, 120).buildMultiRegionCachedMap() - allInstances = cachedMapBuilder.of(EntityType.instance, 120).buildMultiRegionCachedMap() + allKeyPairs = cachedMapBuilder.of(EntityType.keyPair, 10).buildMultiRegionCachedMap() + allImages = cachedMapBuilder.of(EntityType.image, 10).buildMultiRegionCachedMap() + allInstances = cachedMapBuilder.of(EntityType.instance, 10).buildMultiRegionCachedMap() allSpotInstanceRequests = cachedMapBuilder.of(EntityType.spotInstanceRequest, 120).buildMultiRegionCachedMap() - allApplicationInstances = cachedMapBuilder.of(EntityType.applicationInstance, 60).buildMultiRegionCachedMap() + allApplicationInstances = cachedMapBuilder.of(EntityType.applicationInstance, 10).buildMultiRegionCachedMap() allReservedInstancesGroups = cachedMapBuilder.of(EntityType.reservation, 3600).buildMultiRegionCachedMap() - allSecurityGroups = cachedMapBuilder.of(EntityType.security, 120).buildMultiRegionCachedMap() - allSnapshots = cachedMapBuilder.of(EntityType.snapshot, 300).buildMultiRegionCachedMap() - allVolumes = cachedMapBuilder.of(EntityType.volume, 300).buildMultiRegionCachedMap() + allSecurityGroups = cachedMapBuilder.of(EntityType.security, 10).buildMultiRegionCachedMap() + allSnapshots = cachedMapBuilder.of(EntityType.snapshot, 10).buildMultiRegionCachedMap() + allVolumes = cachedMapBuilder.of(EntityType.volume, 10).buildMultiRegionCachedMap() allDomains = cachedMapBuilder.of(EntityType.domain, 120).buildMultiRegionCachedMap() allTopics = cachedMapBuilder.of(EntityType.topic, 120).buildMultiRegionCachedMap() allQueues = cachedMapBuilder.of(EntityType.queue, 120).buildMultiRegionCachedMap() @@ -119,7 +119,7 @@ class Caches { allDBSnapshots = cachedMapBuilder.of(EntityType.dbSnapshot, 120).buildMultiRegionCachedMap() allFastProperties = cachedMapBuilder.of(EntityType.fastProperty, 180).buildMultiRegionCachedMap(configService?. platformServiceRegions) - allScalingPolicies = cachedMapBuilder.of(EntityType.scalingPolicy, 120).buildMultiRegionCachedMap() + allScalingPolicies = cachedMapBuilder.of(EntityType.scalingPolicy, 10).buildMultiRegionCachedMap() allScheduledActions = cachedMapBuilder.of(EntityType.scheduledAction, 120).buildMultiRegionCachedMap() allSignificantStackInstanceHealthChecks = cachedMapBuilder.of(EntityType.instanceHealth, 300). buildMultiRegionCachedMap() diff --git a/grails-app/services/com/netflix/asgard/InitService.groovy b/grails-app/services/com/netflix/asgard/InitService.groovy index 97bc26c2..1077d8af 100644 --- a/grails-app/services/com/netflix/asgard/InitService.groovy +++ b/grails-app/services/com/netflix/asgard/InitService.groovy @@ -78,6 +78,7 @@ class InitService implements ApplicationContextAware { */ boolean cachesFilled() { Collection fillableCaches = caches.properties*.value.findAll { it instanceof Fillable } - !fillableCaches.find { !it.filled } + !fillableCaches.findAll { !it.filled; }.each{ println it.name } + !fillableCaches.find { !it.filled; } } } diff --git a/grails-app/services/com/netflix/asgard/InstanceTypeService.groovy b/grails-app/services/com/netflix/asgard/InstanceTypeService.groovy index 30f94c0c..a7a644de 100644 --- a/grails-app/services/com/netflix/asgard/InstanceTypeService.groovy +++ b/grails-app/services/com/netflix/asgard/InstanceTypeService.groovy @@ -93,7 +93,7 @@ class InstanceTypeService implements CacheInitializer { } Collection getInstanceTypes(UserContext userContext) { - caches.allInstanceTypes.by(userContext.region).list().sort { it.linuxOnDemandPrice } + caches.allInstanceTypes.by(userContext.region).list() as List//.sort { it.linuxOnDemandPrice } } private Document fetchInstanceTypesDocument() { @@ -133,7 +133,8 @@ class InstanceTypeService implements CacheInitializer { RegionalInstancePrices reservedPrices = getReservedPrices(region) RegionalInstancePrices spotPrices = getSpotPrices(region) - Set awsInstanceTypes = InstanceType.values() as Set + Set awsInstanceTypes = InstanceType.values().findAll{ it.name().startsWith("m") } as Set + awsInstanceTypes.each{ println it } List instanceTypes = awsInstanceTypes.findResults { InstanceType instanceType -> HardwareProfile hardwareProfile = hardwareProfiles.find { it.instanceType == instanceType.toString() } if (!hardwareProfile) { @@ -142,12 +143,12 @@ class InstanceTypeService implements CacheInitializer { } new InstanceTypeData( hardwareProfile: hardwareProfile, - linuxOnDemandPrice: onDemandPrices.get(instanceType, InstanceProductType.LINUX_UNIX), + linuxOnDemandPrice: onDemandPrices?.get(instanceType, InstanceProductType.LINUX_UNIX), linuxReservedPrice: reservedPrices?.get(instanceType, InstanceProductType.LINUX_UNIX), - linuxSpotPrice: spotPrices.get(instanceType, InstanceProductType.LINUX_UNIX), - windowsOnDemandPrice: onDemandPrices.get(instanceType, InstanceProductType.WINDOWS), + linuxSpotPrice: spotPrices?.get(instanceType, InstanceProductType.LINUX_UNIX), + windowsOnDemandPrice: onDemandPrices?.get(instanceType, InstanceProductType.WINDOWS), windowsReservedPrice: reservedPrices?.get(instanceType, InstanceProductType.WINDOWS), - windowsSpotPrice: spotPrices.get(instanceType, InstanceProductType.WINDOWS) + windowsSpotPrice: spotPrices?.get(instanceType, InstanceProductType.WINDOWS) ) } instanceTypes.sort { a, b -> a.instanceType <=> b.instanceType } @@ -234,6 +235,27 @@ class InstanceTypeService implements CacheInitializer { hardwareProfiles << hardwareProfile } } + hardwareProfiles << new HardwareProfile(instanceType: 'm1.small', architecture: '64-bit', + cpu: '1 EC2 Compute Units (1 virtual cores with 1 EC2 Compute Units each)', + description: 'M1 Small Instance', + ioPerformance: 'Poor', memory: '0.25 GiB', + storage: '5 GB of instance storage') + hardwareProfiles << new HardwareProfile(instanceType: 'm1.medium', architecture: '64-bit', + cpu: '1 EC2 Compute Units (1 virtual cores with 1 EC2 Compute Units each)', + description: 'M1 Medium Instance', + ioPerformance: 'Poor', memory: '0.5 GiB', + storage: '10 GB of instance storage') + hardwareProfiles << new HardwareProfile(instanceType: 'm1.large', architecture: '64-bit', + cpu: '2 EC2 Compute Units (2 virtual cores with 1 EC2 Compute Units each)', + description: 'M1 Large Instance', + ioPerformance: 'Poor', memory: '0.5 GiB', + storage: '10 GB of instance storage') + hardwareProfiles << new HardwareProfile(instanceType: 'm1.xlarge', architecture: '64-bit', + cpu: '2 EC2 Compute Units (2 virtual cores with 1 EC2 Compute Units each)', + description: 'M1 Xtra-Large Instance', + ioPerformance: 'Poor', memory: '1 GiB', + storage: '10 GB of instance storage') + } else { throw new Exception("Unexpected format of HTML on ${instanceTypesUrl}") } diff --git a/grails-app/views/image/prelaunch.gsp b/grails-app/views/image/prelaunch.gsp index 2e65533e..6af8d608 100644 --- a/grails-app/views/image/prelaunch.gsp +++ b/grails-app/views/image/prelaunch.gsp @@ -51,7 +51,7 @@ diff --git a/src/groovy/com/netflix/asgard/Region.groovy b/src/groovy/com/netflix/asgard/Region.groovy index a3d1b327..7230d0dc 100644 --- a/src/groovy/com/netflix/asgard/Region.groovy +++ b/src/groovy/com/netflix/asgard/Region.groovy @@ -20,53 +20,58 @@ package com.netflix.asgard */ enum Region { + EUCALYPTUS('PARTI', + 'eucalyptus', + 'eucalyptus.png', + 'Santa Barbara' + ), US_EAST_1('us-east-1', 'us-east', 'us-east-1.png', 'Virginia' ), - - US_WEST_1('us-west-1', - 'us-west', - 'us-west-1.png', - 'California' - ), - - US_WEST_2('us-west-2', - 'us-west-2', - 'us-west-2.png', - 'Oregon' - ), - - EU_WEST_1('eu-west-1', - 'eu-ireland', - 'eu-west-1.png', - 'Ireland' - ), - - AP_NORTHEAST_1('ap-northeast-1', - 'apac-tokyo', - 'ap-northeast-1.png', - 'Tokyo' - ), - - AP_SOUTHEAST_1('ap-southeast-1', - 'apac-sin', - 'ap-southeast-1.png', - 'Singapore' - ), - - AP_SOUTHEAST_2('ap-southeast-2', - 'apac-syd', - 'ap-southeast-2.png', - 'Sydney' - ), - - SA_EAST_1('sa-east-1', - 'sa-east-1', - 'sa-east-1.png', - 'Sao Paulo' - ) +// +// US_WEST_1('us-west-1', +// 'us-west', +// 'us-west-1.png', +// 'California' +// ), +// +// US_WEST_2('us-west-2', +// 'us-west-2', +// 'us-west-2.png', +// 'Oregon' +// ), +// +// EU_WEST_1('eu-west-1', +// 'eu-ireland', +// 'eu-west-1.png', +// 'Ireland' +// ), +// +// AP_NORTHEAST_1('ap-northeast-1', +// 'apac-tokyo', +// 'ap-northeast-1.png', +// 'Tokyo' +// ), +// +// AP_SOUTHEAST_1('ap-southeast-1', +// 'apac-sin', +// 'ap-southeast-1.png', +// 'Singapore' +// ), +// +// AP_SOUTHEAST_2('ap-southeast-2', +// 'apac-syd', +// 'ap-southeast-2.png', +// 'Sydney' +// ), +// +// SA_EAST_1('sa-east-1', +// 'sa-east-1', +// 'sa-east-1.png', +// 'Sao Paulo' +// ) String code String pricingJsonCode @@ -116,7 +121,7 @@ enum Region { } [] } - static Region defaultRegion() { Region.US_EAST_1 } + static Region defaultRegion() { Region.EUCALYPTUS } String getDescription() { "$code ($location)" } diff --git a/web-app/images/worldmap/eucalyptus.png b/web-app/images/worldmap/eucalyptus.png new file mode 100644 index 0000000000000000000000000000000000000000..674ec78b5929627b5900559dd8eaa8df6de96ae7 GIT binary patch literal 6937 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 Date: Sun, 21 Apr 2013 00:40:55 -0700 Subject: [PATCH 02/14] Demo patch #2 --- grails-app/conf/BuildConfig.groovy | 2 +- grails-app/conf/Config.groovy | 54 ++++++++--- .../asgard/InstanceTypeController.groovy | 1 + .../asgard/AwsAutoScalingService.groovy | 30 +++--- .../netflix/asgard/AwsClientService.groovy | 11 +-- .../asgard/AwsCloudWatchService.groovy | 4 +- .../com/netflix/asgard/AwsEc2Service.groovy | 12 +-- .../asgard/AwsLoadBalancerService.groovy | 2 +- .../com/netflix/asgard/AwsS3Service.groovy | 3 +- .../com/netflix/asgard/AwsSqsService.groovy | 6 +- .../services/com/netflix/asgard/Caches.groovy | 22 ++--- .../com/netflix/asgard/InitService.groovy | 3 +- .../netflix/asgard/InstanceTypeService.groovy | 36 +++++-- grails-app/views/image/prelaunch.gsp | 2 +- src/groovy/com/netflix/asgard/Region.groovy | 91 +++++++++--------- web-app/images/worldmap/eucalyptus.png | Bin 0 -> 1215 bytes 16 files changed, 166 insertions(+), 113 deletions(-) create mode 100644 web-app/images/worldmap/eucalyptus.png diff --git a/grails-app/conf/BuildConfig.groovy b/grails-app/conf/BuildConfig.groovy index 3a34be8b..2f2908e7 100644 --- a/grails-app/conf/BuildConfig.groovy +++ b/grails-app/conf/BuildConfig.groovy @@ -80,7 +80,7 @@ grails.project.dependency.resolution = { compile( // Amazon Web Services programmatic interface - 'com.amazonaws:aws-java-sdk:1.3.23', + 'com.amazonaws:aws-java-sdk:1.4.0', ) { // AWS defines their dependencies as open-ended, which causes problems when resolving. // See http://stackoverflow.com/a/7990573/869 diff --git a/grails-app/conf/Config.groovy b/grails-app/conf/Config.groovy index 9792dcc8..bc97d583 100644 --- a/grails-app/conf/Config.groovy +++ b/grails-app/conf/Config.groovy @@ -32,7 +32,7 @@ log4j = { } root { - info 'asgardrolling' + debug 'asgardrolling' } // Set level for all application artifacts @@ -68,7 +68,7 @@ log4j = { development { console name: 'stdout', layout: pattern(conversionPattern: '[%d{ISO8601}] %c{4} %m%n') root { - info 'stdout' + debug 'stdout' } } } @@ -134,20 +134,44 @@ cloud { // TODO: Delete these instance type hacks as soon as m3.xlarge, m3.2xlarge are in the AWS Java SDK enum instead customInstanceTypes = [ - new InstanceTypeData(linuxOnDemandPrice: 0.580, hardwareProfile: - new HardwareProfile(instanceType: 'm3.xlarge', architecture: '64-bit', - cpu: '13 EC2 Compute Units (4 virtual cores with 3.25 EC2 Compute Units each)', - description: 'M3 Extra Large Instance', - ioPerformance: 'Moderate', memory: '15 GiB', - storage: 'EBS storage only')), - new InstanceTypeData(linuxOnDemandPrice: 1.160, hardwareProfile: - new HardwareProfile(instanceType: 'm3.2xlarge', architecture: '64-bit', - cpu: '26 EC2 Compute Units (8 virtual cores with 3.25 EC2 Compute Units each)', - description: 'M3 Double Extra Large Instance', - ioPerformance: 'High', memory: '30 GiB', - storage: 'EBS storage only')), + new InstanceTypeData(linuxOnDemandPrice: 0.1, hardwareProfile: + new HardwareProfile(instanceType: 'm1.small', architecture: '64-bit', + cpu: '1 EC2 Compute Units (1 virtual cores with 1 EC2 Compute Units each)', + description: 'M1 Small Instance', + ioPerformance: 'Poor', memory: '0.25 GiB', + storage: '5 GB of instance storage')), + new InstanceTypeData(linuxOnDemandPrice: 0.2, hardwareProfile: + new HardwareProfile(instanceType: 'm1.medium', architecture: '64-bit', + cpu: '1 EC2 Compute Units (1 virtual cores with 1 EC2 Compute Units each)', + description: 'M1 Medium Instance', + ioPerformance: 'Poor', memory: '0.5 GiB', + storage: '10 GB of instance storage')), + new InstanceTypeData(linuxOnDemandPrice: 0.3, hardwareProfile: + new HardwareProfile(instanceType: 'm1.large', architecture: '64-bit', + cpu: '2 EC2 Compute Units (2 virtual cores with 1 EC2 Compute Units each)', + description: 'M1 Large Instance', + ioPerformance: 'Poor', memory: '0.5 GiB', + storage: '10 GB of instance storage')), + new InstanceTypeData(linuxOnDemandPrice: 0.5, hardwareProfile: + new HardwareProfile(instanceType: 'm1.xlarge', architecture: '64-bit', + cpu: '2 EC2 Compute Units (2 virtual cores with 1 EC2 Compute Units each)', + description: 'M1 Xtra-Large Instance', + ioPerformance: 'Poor', memory: '1 GiB', + storage: '10 GB of instance storage')), +// new InstanceTypeData(linuxOnDemandPrice: 0.580, hardwareProfile: +// new HardwareProfile(instanceType: 'm3.xlarge', architecture: '64-bit', +// cpu: '13 EC2 Compute Units (4 virtual cores with 3.25 EC2 Compute Units each)', +// description: 'M3 Extra Large Instance', +// ioPerformance: 'Moderate', memory: '15 GiB', +// storage: 'EBS storage only')), +// new InstanceTypeData(linuxOnDemandPrice: 1.160, hardwareProfile: +// new HardwareProfile(instanceType: 'm3.2xlarge', architecture: '64-bit', +// cpu: '26 EC2 Compute Units (8 virtual cores with 3.25 EC2 Compute Units each)', +// description: 'M3 Double Extra Large Instance', +// ioPerformance: 'High', memory: '30 GiB', +// storage: 'EBS storage only')), ] - spot.infoUrl = 'http://aws.amazon.com/ec2/spot-instances/' +// spot.infoUrl = 'http://aws.amazon.com/ec2/spot-instances/' } healthCheck { diff --git a/grails-app/controllers/com/netflix/asgard/InstanceTypeController.groovy b/grails-app/controllers/com/netflix/asgard/InstanceTypeController.groovy index 492ea221..af6eba68 100644 --- a/grails-app/controllers/com/netflix/asgard/InstanceTypeController.groovy +++ b/grails-app/controllers/com/netflix/asgard/InstanceTypeController.groovy @@ -30,6 +30,7 @@ class InstanceTypeController { def list = { UserContext userContext = UserContext.of(request) List instanceTypes = instanceTypeService.getInstanceTypes(userContext) + println instanceTypes Map details = [instanceTypes: instanceTypes] withFormat { html { details } diff --git a/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy b/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy index 28b75669..7ed3e275 100644 --- a/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy +++ b/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy @@ -121,7 +121,7 @@ class AwsAutoScalingService implements CacheInitializer, InitializingBean { void afterPropertiesSet() { awsClient = new MultiRegionAwsClient({ Region region -> AmazonAutoScaling client = awsClientService.create(AmazonAutoScaling) - client.setEndpoint("autoscaling.${region}.amazonaws.com") + client.setEndpoint("http://eucalyptus:8773/services/AutoScaling") client }) } @@ -130,26 +130,26 @@ class AwsAutoScalingService implements CacheInitializer, InitializingBean { // Cluster cache has no timer. It gets triggered by the Auto Scaling Group cache callback closure. caches.allClusters.ensureSetUp( { Region region -> buildClusters(region, caches.allAutoScalingGroups.by(region).list()) }, {}, - { Region region -> - boolean awaitingLoadBalancers = caches.allLoadBalancers.by(region).isDoingFirstFill() - boolean awaitingAppInstances = caches.allApplicationInstances.by(region).isDoingFirstFill() - boolean awaitingImages = caches.allImages.by(region).isDoingFirstFill() - boolean awaitingEc2Instances = caches.allInstances.by(region).isDoingFirstFill() - !awaitingLoadBalancers && !awaitingAppInstances && !awaitingImages && !awaitingEc2Instances - } +// { Region region -> +// boolean awaitingLoadBalancers = caches.allLoadBalancers.by(region).isDoingFirstFill() +// boolean awaitingAppInstances = caches.allApplicationInstances.by(region).isDoingFirstFill() +// boolean awaitingImages = caches.allImages.by(region).isDoingFirstFill() +// boolean awaitingEc2Instances = caches.allInstances.by(region).isDoingFirstFill() +// !awaitingLoadBalancers && !awaitingAppInstances && !awaitingImages && !awaitingEc2Instances +// } ) caches.allAutoScalingGroups.ensureSetUp({ Region region -> retrieveAutoScalingGroups(region) }, { Region region -> caches.allClusters.by(region).fill() }) caches.allLaunchConfigurations.ensureSetUp({ Region region -> retrieveLaunchConfigurations(region) }) caches.allScalingPolicies.ensureSetUp({ Region region -> retrieveScalingPolicies(region) }) caches.allTerminationPolicyTypes.ensureSetUp({ Region region -> retrieveTerminationPolicyTypes() }) - caches.allScheduledActions.ensureSetUp({ Region region -> retrieveScheduledActions(region) }) - caches.allSignificantStackInstanceHealthChecks.ensureSetUp( - { Region region -> retrieveInstanceHealthChecks(region) }, {}, - { Region region -> - caches.allApplicationInstances.by(region).filled && caches.allAutoScalingGroups.by(region).filled - } - ) +// caches.allScheduledActions.ensureSetUp({ Region region -> retrieveScheduledActions(region) }) +// caches.allSignificantStackInstanceHealthChecks.ensureSetUp( +// { Region region -> retrieveInstanceHealthChecks(region) }, {}, +// { Region region -> +// caches.allApplicationInstances.by(region).filled && caches.allAutoScalingGroups.by(region).filled +// } +// ) } // Clusters diff --git a/grails-app/services/com/netflix/asgard/AwsClientService.groovy b/grails-app/services/com/netflix/asgard/AwsClientService.groovy index a125e0df..86b63eb5 100644 --- a/grails-app/services/com/netflix/asgard/AwsClientService.groovy +++ b/grails-app/services/com/netflix/asgard/AwsClientService.groovy @@ -60,13 +60,12 @@ class AwsClientService implements InitializingBean { AmazonAutoScaling: concrete(AmazonAutoScalingClient, MockAmazonAutoScalingClient), AmazonCloudWatch: concrete(AmazonCloudWatchClient, MockAmazonCloudWatchClient), AmazonEC2: concrete(AmazonEC2Client, MockAmazonEC2Client), - AmazonElasticLoadBalancing: concrete(AmazonElasticLoadBalancingClient, - MockAmazonElasticLoadBalancingClient), - AmazonRDS: concrete(AmazonRDSClient, MockAmazonRDSClient), + AmazonElasticLoadBalancing: concrete(AmazonElasticLoadBalancingClient,MockAmazonElasticLoadBalancingClient), + AmazonRDS: concrete(/*AmazonRDSClient*/MockAmazonRDSClient, MockAmazonRDSClient), AmazonS3: concrete(AmazonS3Client, MockAmazonS3Client), - AmazonSimpleDB: concrete(AmazonSimpleDBClient, MockAmazonSimpleDBClient), - AmazonSNS: concrete(AmazonSNSClient, MockAmazonSnsClient), - AmazonSQS: concrete(AmazonSQSClient, MockAmazonSqsClient) + AmazonSimpleDB: concrete(/*AmazonSimpleDBClient*/MockAmazonSimpleDBClient, MockAmazonSimpleDBClient), + AmazonSNS: concrete(/*AmazonSNSClient*/MockAmazonSnsClient, MockAmazonSnsClient), + AmazonSQS: concrete(/*AmazonSQSClient*/MockAmazonSqsClient, MockAmazonSqsClient) ] clientConfiguration = new ClientConfiguration() clientConfiguration.proxyHost = configService.proxyHost diff --git a/grails-app/services/com/netflix/asgard/AwsCloudWatchService.groovy b/grails-app/services/com/netflix/asgard/AwsCloudWatchService.groovy index 24a09bee..7f5a31b4 100644 --- a/grails-app/services/com/netflix/asgard/AwsCloudWatchService.groovy +++ b/grails-app/services/com/netflix/asgard/AwsCloudWatchService.groovy @@ -54,7 +54,7 @@ class AwsCloudWatchService implements CacheInitializer, InitializingBean { void afterPropertiesSet() { awsClient = new MultiRegionAwsClient( { Region region -> AmazonCloudWatch client = awsClientService.create(AmazonCloudWatch) - client.setEndpoint("monitoring.${region}.amazonaws.com") + client.setEndpoint("http://eucalyptus:8773/services/CloudWatch") client }) } @@ -100,7 +100,7 @@ class AwsCloudWatchService implements CacheInitializer, InitializingBean { final List alarms = result.metricAlarms // Fix cache to update found alarms and remove missing alarms - caches.allAlarms.by(userContext.region).putAllAndRemoveMissing(alarmNames, alarms) + //caches.allAlarms.by(userContext.region).putAllAndRemoveMissing(alarmNames, alarms) alarms } diff --git a/grails-app/services/com/netflix/asgard/AwsEc2Service.groovy b/grails-app/services/com/netflix/asgard/AwsEc2Service.groovy index 6199271d..c3662d6c 100644 --- a/grails-app/services/com/netflix/asgard/AwsEc2Service.groovy +++ b/grails-app/services/com/netflix/asgard/AwsEc2Service.groovy @@ -121,7 +121,7 @@ class AwsEc2Service implements CacheInitializer, InitializingBean { void afterPropertiesSet() { awsClient = awsClient ?: new MultiRegionAwsClient({ Region region -> AmazonEC2 client = awsClientService.create(AmazonEC2) - client.setEndpoint("ec2.${region}.amazonaws.com") + client.setEndpoint("http://eucalyptus:8773/services/Eucalyptus/") client }) accounts = configService.awsAccounts @@ -187,7 +187,7 @@ class AwsEc2Service implements CacheInitializer, InitializingBean { } private Collection retrieveSubnets(Region region) { - awsClient.by(region).describeSubnets().subnets +// awsClient.by(region).describeSubnets().subnets } /** @@ -201,7 +201,7 @@ class AwsEc2Service implements CacheInitializer, InitializingBean { } private Collection retrieveVpcs(Region region) { - awsClient.by(region).describeVpcs().vpcs +// awsClient.by(region).describeVpcs().vpcs } /** @@ -638,13 +638,13 @@ class AwsEc2Service implements CacheInitializer, InitializingBean { // TODO: Delete this method after rewriting AwsResultsRetrieverSpec unit test to use some other use case DescribeSpotPriceHistoryResult describeSpotPriceHistory(Region region, DescribeSpotPriceHistoryRequest describeSpotPriceHistoryRequest) { - awsClient.by(region).describeSpotPriceHistory(describeSpotPriceHistoryRequest) +// awsClient.by(region).describeSpotPriceHistory(describeSpotPriceHistoryRequest) } // Spot Instance Requests List retrieveSpotInstanceRequests(Region region) { - awsClient.by(region).describeSpotInstanceRequests().spotInstanceRequests +// awsClient.by(region).describeSpotInstanceRequests().spotInstanceRequests } DescribeSpotInstanceRequestsResult describeSpotInstanceRequests(UserContext userContext, @@ -873,7 +873,7 @@ class AwsEc2Service implements CacheInitializer, InitializingBean { // Reservations private List retrieveReservations(Region region) { - awsClient.by(region).describeReservedInstances().reservedInstances +// awsClient.by(region).describeReservedInstances().reservedInstances } /** diff --git a/grails-app/services/com/netflix/asgard/AwsLoadBalancerService.groovy b/grails-app/services/com/netflix/asgard/AwsLoadBalancerService.groovy index b9a88245..2b262529 100644 --- a/grails-app/services/com/netflix/asgard/AwsLoadBalancerService.groovy +++ b/grails-app/services/com/netflix/asgard/AwsLoadBalancerService.groovy @@ -59,7 +59,7 @@ class AwsLoadBalancerService implements CacheInitializer, InitializingBean { void afterPropertiesSet() { awsClient = awsClient ?: new MultiRegionAwsClient( { Region region -> AmazonElasticLoadBalancing client = awsClientService.create(AmazonElasticLoadBalancing) - client.setEndpoint("elasticloadbalancing.${region}.amazonaws.com") + client.setEndpoint("http://eucalyptus:8773/services/LoadBalancing") client }) } diff --git a/grails-app/services/com/netflix/asgard/AwsS3Service.groovy b/grails-app/services/com/netflix/asgard/AwsS3Service.groovy index 6f165644..9f6ccbf8 100644 --- a/grails-app/services/com/netflix/asgard/AwsS3Service.groovy +++ b/grails-app/services/com/netflix/asgard/AwsS3Service.groovy @@ -36,7 +36,8 @@ class AwsS3Service implements InitializingBean { awsClient = new MultiRegionAwsClient( { Region region -> AmazonS3 client = awsClientService.create(AmazonS3) // Unconventional S3 endpoints. http://docs.amazonwebservices.com/general/latest/gr/index.html?rande.html - if (region != Region.US_EAST_1) { client.setEndpoint("s3-${region}.amazonaws.com") } +// if (region != Region.US_EAST_1) { client.setEndpoint("s3-${region}.amazonaws.com") } + client.setEndpoint( "http://eucalyptus:8773/services/Walrus" ) client }) } diff --git a/grails-app/services/com/netflix/asgard/AwsSqsService.groovy b/grails-app/services/com/netflix/asgard/AwsSqsService.groovy index 582ffe93..6527b2b3 100644 --- a/grails-app/services/com/netflix/asgard/AwsSqsService.groovy +++ b/grails-app/services/com/netflix/asgard/AwsSqsService.groovy @@ -58,9 +58,9 @@ class AwsSqsService implements CacheInitializer, InitializingBean { try { return awsClient.by(region).listQueues(new ListQueuesRequest()).queueUrls.collect { new SimpleQueue(it) } } catch (AmazonServiceException ase) { - if (ase.errorCode != 'OptInRequired') { // Ignore if SQS is disabled for this account - throw ase - } +// if (ase.errorCode != 'OptInRequired') { // Ignore if SQS is disabled for this account +// throw ase +// } return [] } } diff --git a/grails-app/services/com/netflix/asgard/Caches.groovy b/grails-app/services/com/netflix/asgard/Caches.groovy index 5d4b39e2..7d8a88d1 100644 --- a/grails-app/services/com/netflix/asgard/Caches.groovy +++ b/grails-app/services/com/netflix/asgard/Caches.groovy @@ -94,22 +94,22 @@ class Caches { Caches(CachedMapBuilder cachedMapBuilder, ConfigService configService = null) { allClusters = cachedMapBuilder.of(EntityType.cluster).buildMultiRegionCachedMap() - allAutoScalingGroups = cachedMapBuilder.of(EntityType.autoScaling, 120).buildMultiRegionCachedMap() - allLaunchConfigurations = cachedMapBuilder.of(EntityType.launchConfiguration, 180).buildMultiRegionCachedMap() - allLoadBalancers = cachedMapBuilder.of(EntityType.loadBalancer, 120).buildMultiRegionCachedMap() + allAutoScalingGroups = cachedMapBuilder.of(EntityType.autoScaling, 10).buildMultiRegionCachedMap() + allLaunchConfigurations = cachedMapBuilder.of(EntityType.launchConfiguration, 10).buildMultiRegionCachedMap() + allLoadBalancers = cachedMapBuilder.of(EntityType.loadBalancer, 10).buildMultiRegionCachedMap() allSourceSecurityGroups = cachedMapBuilder.of(EntityType.sourceSecurityGroup).buildMultiRegionCachedMap() allAvailabilityZones = cachedMapBuilder.of(EntityType.availabilityZone, 3600).buildMultiRegionCachedMap() allSubnets = cachedMapBuilder.of(EntityType.subnet, 3600).buildMultiRegionCachedMap() allVpcs = cachedMapBuilder.of(EntityType.vpc, 3600).buildMultiRegionCachedMap() - allKeyPairs = cachedMapBuilder.of(EntityType.keyPair).buildMultiRegionCachedMap() - allImages = cachedMapBuilder.of(EntityType.image, 120).buildMultiRegionCachedMap() - allInstances = cachedMapBuilder.of(EntityType.instance, 120).buildMultiRegionCachedMap() + allKeyPairs = cachedMapBuilder.of(EntityType.keyPair, 10).buildMultiRegionCachedMap() + allImages = cachedMapBuilder.of(EntityType.image, 10).buildMultiRegionCachedMap() + allInstances = cachedMapBuilder.of(EntityType.instance, 10).buildMultiRegionCachedMap() allSpotInstanceRequests = cachedMapBuilder.of(EntityType.spotInstanceRequest, 120).buildMultiRegionCachedMap() - allApplicationInstances = cachedMapBuilder.of(EntityType.applicationInstance, 60).buildMultiRegionCachedMap() + allApplicationInstances = cachedMapBuilder.of(EntityType.applicationInstance, 10).buildMultiRegionCachedMap() allReservedInstancesGroups = cachedMapBuilder.of(EntityType.reservation, 3600).buildMultiRegionCachedMap() - allSecurityGroups = cachedMapBuilder.of(EntityType.security, 120).buildMultiRegionCachedMap() - allSnapshots = cachedMapBuilder.of(EntityType.snapshot, 300).buildMultiRegionCachedMap() - allVolumes = cachedMapBuilder.of(EntityType.volume, 300).buildMultiRegionCachedMap() + allSecurityGroups = cachedMapBuilder.of(EntityType.security, 10).buildMultiRegionCachedMap() + allSnapshots = cachedMapBuilder.of(EntityType.snapshot, 10).buildMultiRegionCachedMap() + allVolumes = cachedMapBuilder.of(EntityType.volume, 10).buildMultiRegionCachedMap() allDomains = cachedMapBuilder.of(EntityType.domain, 120).buildMultiRegionCachedMap() allTopics = cachedMapBuilder.of(EntityType.topic, 120).buildMultiRegionCachedMap() allQueues = cachedMapBuilder.of(EntityType.queue, 120).buildMultiRegionCachedMap() @@ -119,7 +119,7 @@ class Caches { allDBSnapshots = cachedMapBuilder.of(EntityType.dbSnapshot, 120).buildMultiRegionCachedMap() allFastProperties = cachedMapBuilder.of(EntityType.fastProperty, 180).buildMultiRegionCachedMap(configService?. platformServiceRegions) - allScalingPolicies = cachedMapBuilder.of(EntityType.scalingPolicy, 120).buildMultiRegionCachedMap() + allScalingPolicies = cachedMapBuilder.of(EntityType.scalingPolicy, 10).buildMultiRegionCachedMap() allScheduledActions = cachedMapBuilder.of(EntityType.scheduledAction, 120).buildMultiRegionCachedMap() allSignificantStackInstanceHealthChecks = cachedMapBuilder.of(EntityType.instanceHealth, 300). buildMultiRegionCachedMap() diff --git a/grails-app/services/com/netflix/asgard/InitService.groovy b/grails-app/services/com/netflix/asgard/InitService.groovy index 97bc26c2..1077d8af 100644 --- a/grails-app/services/com/netflix/asgard/InitService.groovy +++ b/grails-app/services/com/netflix/asgard/InitService.groovy @@ -78,6 +78,7 @@ class InitService implements ApplicationContextAware { */ boolean cachesFilled() { Collection fillableCaches = caches.properties*.value.findAll { it instanceof Fillable } - !fillableCaches.find { !it.filled } + !fillableCaches.findAll { !it.filled; }.each{ println it.name } + !fillableCaches.find { !it.filled; } } } diff --git a/grails-app/services/com/netflix/asgard/InstanceTypeService.groovy b/grails-app/services/com/netflix/asgard/InstanceTypeService.groovy index 30f94c0c..9b3198e9 100644 --- a/grails-app/services/com/netflix/asgard/InstanceTypeService.groovy +++ b/grails-app/services/com/netflix/asgard/InstanceTypeService.groovy @@ -93,7 +93,7 @@ class InstanceTypeService implements CacheInitializer { } Collection getInstanceTypes(UserContext userContext) { - caches.allInstanceTypes.by(userContext.region).list().sort { it.linuxOnDemandPrice } + caches.allInstanceTypes.by(userContext.region).list() as List//.sort { it.linuxOnDemandPrice } } private Document fetchInstanceTypesDocument() { @@ -133,7 +133,8 @@ class InstanceTypeService implements CacheInitializer { RegionalInstancePrices reservedPrices = getReservedPrices(region) RegionalInstancePrices spotPrices = getSpotPrices(region) - Set awsInstanceTypes = InstanceType.values() as Set + Set awsInstanceTypes = InstanceType.values().findAll{ it.name().startsWith("m") } as Set + awsInstanceTypes.each{ println it } List instanceTypes = awsInstanceTypes.findResults { InstanceType instanceType -> HardwareProfile hardwareProfile = hardwareProfiles.find { it.instanceType == instanceType.toString() } if (!hardwareProfile) { @@ -142,12 +143,12 @@ class InstanceTypeService implements CacheInitializer { } new InstanceTypeData( hardwareProfile: hardwareProfile, - linuxOnDemandPrice: onDemandPrices.get(instanceType, InstanceProductType.LINUX_UNIX), + linuxOnDemandPrice: onDemandPrices?.get(instanceType, InstanceProductType.LINUX_UNIX), linuxReservedPrice: reservedPrices?.get(instanceType, InstanceProductType.LINUX_UNIX), - linuxSpotPrice: spotPrices.get(instanceType, InstanceProductType.LINUX_UNIX), - windowsOnDemandPrice: onDemandPrices.get(instanceType, InstanceProductType.WINDOWS), + linuxSpotPrice: spotPrices?.get(instanceType, InstanceProductType.LINUX_UNIX), + windowsOnDemandPrice: onDemandPrices?.get(instanceType, InstanceProductType.WINDOWS), windowsReservedPrice: reservedPrices?.get(instanceType, InstanceProductType.WINDOWS), - windowsSpotPrice: spotPrices.get(instanceType, InstanceProductType.WINDOWS) + windowsSpotPrice: spotPrices?.get(instanceType, InstanceProductType.WINDOWS) ) } instanceTypes.sort { a, b -> a.instanceType <=> b.instanceType } @@ -234,8 +235,29 @@ class InstanceTypeService implements CacheInitializer { hardwareProfiles << hardwareProfile } } + hardwareProfiles << new HardwareProfile(instanceType: 'm1.small', architecture: '64-bit', + cpu: '1 EC2 Compute Units (1 virtual cores with 1 EC2 Compute Units each)', + description: 'M1 Small Instance', + ioPerformance: 'Poor', memory: '0.25 GiB', + storage: '5 GB of instance storage') + hardwareProfiles << new HardwareProfile(instanceType: 'm1.medium', architecture: '64-bit', + cpu: '1 EC2 Compute Units (1 virtual cores with 1 EC2 Compute Units each)', + description: 'M1 Medium Instance', + ioPerformance: 'Poor', memory: '0.5 GiB', + storage: '10 GB of instance storage') + hardwareProfiles << new HardwareProfile(instanceType: 'm1.large', architecture: '64-bit', + cpu: '2 EC2 Compute Units (2 virtual cores with 1 EC2 Compute Units each)', + description: 'M1 Large Instance', + ioPerformance: 'Poor', memory: '0.5 GiB', + storage: '10 GB of instance storage') + hardwareProfiles << new HardwareProfile(instanceType: 'm1.xlarge', architecture: '64-bit', + cpu: '2 EC2 Compute Units (2 virtual cores with 1 EC2 Compute Units each)', + description: 'M1 Xtra-Large Instance', + ioPerformance: 'Poor', memory: '1 GiB', + storage: '10 GB of instance storage') + } else { - throw new Exception("Unexpected format of HTML on ${instanceTypesUrl}") +// throw new Exception("Unexpected format of HTML on ${instanceTypesUrl}") } hardwareProfiles } diff --git a/grails-app/views/image/prelaunch.gsp b/grails-app/views/image/prelaunch.gsp index 2e65533e..6af8d608 100644 --- a/grails-app/views/image/prelaunch.gsp +++ b/grails-app/views/image/prelaunch.gsp @@ -51,7 +51,7 @@ diff --git a/src/groovy/com/netflix/asgard/Region.groovy b/src/groovy/com/netflix/asgard/Region.groovy index a3d1b327..7230d0dc 100644 --- a/src/groovy/com/netflix/asgard/Region.groovy +++ b/src/groovy/com/netflix/asgard/Region.groovy @@ -20,53 +20,58 @@ package com.netflix.asgard */ enum Region { + EUCALYPTUS('PARTI', + 'eucalyptus', + 'eucalyptus.png', + 'Santa Barbara' + ), US_EAST_1('us-east-1', 'us-east', 'us-east-1.png', 'Virginia' ), - - US_WEST_1('us-west-1', - 'us-west', - 'us-west-1.png', - 'California' - ), - - US_WEST_2('us-west-2', - 'us-west-2', - 'us-west-2.png', - 'Oregon' - ), - - EU_WEST_1('eu-west-1', - 'eu-ireland', - 'eu-west-1.png', - 'Ireland' - ), - - AP_NORTHEAST_1('ap-northeast-1', - 'apac-tokyo', - 'ap-northeast-1.png', - 'Tokyo' - ), - - AP_SOUTHEAST_1('ap-southeast-1', - 'apac-sin', - 'ap-southeast-1.png', - 'Singapore' - ), - - AP_SOUTHEAST_2('ap-southeast-2', - 'apac-syd', - 'ap-southeast-2.png', - 'Sydney' - ), - - SA_EAST_1('sa-east-1', - 'sa-east-1', - 'sa-east-1.png', - 'Sao Paulo' - ) +// +// US_WEST_1('us-west-1', +// 'us-west', +// 'us-west-1.png', +// 'California' +// ), +// +// US_WEST_2('us-west-2', +// 'us-west-2', +// 'us-west-2.png', +// 'Oregon' +// ), +// +// EU_WEST_1('eu-west-1', +// 'eu-ireland', +// 'eu-west-1.png', +// 'Ireland' +// ), +// +// AP_NORTHEAST_1('ap-northeast-1', +// 'apac-tokyo', +// 'ap-northeast-1.png', +// 'Tokyo' +// ), +// +// AP_SOUTHEAST_1('ap-southeast-1', +// 'apac-sin', +// 'ap-southeast-1.png', +// 'Singapore' +// ), +// +// AP_SOUTHEAST_2('ap-southeast-2', +// 'apac-syd', +// 'ap-southeast-2.png', +// 'Sydney' +// ), +// +// SA_EAST_1('sa-east-1', +// 'sa-east-1', +// 'sa-east-1.png', +// 'Sao Paulo' +// ) String code String pricingJsonCode @@ -116,7 +121,7 @@ enum Region { } [] } - static Region defaultRegion() { Region.US_EAST_1 } + static Region defaultRegion() { Region.EUCALYPTUS } String getDescription() { "$code ($location)" } diff --git a/web-app/images/worldmap/eucalyptus.png b/web-app/images/worldmap/eucalyptus.png new file mode 100644 index 0000000000000000000000000000000000000000..6d97fb0f6adc491c889e5939141fb949342a7f8e GIT binary patch literal 1215 zcmV;w1VHPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01sgR01sgSs6VG^00007bV*G`2i*e> z03jd5oUo(-00citL_t(&-ql)5iycK2{!Tr590oIiU^JqOAQD^#{Q(Z{Ob`SYA}HA? zWFbB_LYBG{5p?BR@ehPV1O*|4pn?bnG!T&xLu6v+74O{c+g(-1#mvA=cXd9_sGKWZVFt^~eFpu>(+Q>;RIW2dzsM^zr2-$8%kuApEoO zpS29Cl~4c!%%`7v;@b;v2%`C}AIpmiPrv)w?SD5xRL4Mo2ONKT?#v@cmZ)ZyL5I`} zP&x_#5heQYtfC~OhKONc55_@R@y-LdZ7jn$chJKoP-2H=~fKHcz~di zvV?Rr1N{SNh*4Exz=~)StG*@FP{?G}#9aU|^X`Ue5C-ZbB%~*Wn15L>Y@02P1fD&X z?31PLJB6A&P);GzctEVm`*u>OMKhPrf&h4D zv<`U|y&qt9`(C(nC^EQk1~yiM9yCXQir8jTtgn`vIfj;PmJcLK0DBE=o?(3z91dV> zEeya(&&52$)>;`rn&%(B*gb`c0uR>Pn0T@oR0OQ`TrP48}d8hQ>o5bdrY_*8D!G|0Qea&$hOO!c9zC% z$t-45*q#9pTnz(hT9Hs30B4bkS_6m{rNkKmIn&X7$Ic5gS@&e*5JY&cC!WoE4OmCtv&E*4=yc z2i+mRO>|(_cW@7-q!`wyyDQ}G0N5U?S-C0f6kLFY9DnrX#jh^Bsid6q;+K~eEi)K( z>m)pXE@-C0EFXRN#Id8p`L(7s5;yOx7RJ{9;VC!{wzku)?euU|L`^Y@Q4a;?kprM{ dGaxYX@jot}v^R#A@YetU002ovPDHLkV1j9O9Z3KH literal 0 HcmV?d00001 From d2deb74226585524014b5a7c87f70a56de48ebca Mon Sep 17 00:00:00 2001 From: chris grzegorczyk Date: Sun, 21 Apr 2013 01:52:18 -0700 Subject: [PATCH 03/14] elb --- .../services/com/netflix/asgard/AwsClientService.groovy | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/grails-app/services/com/netflix/asgard/AwsClientService.groovy b/grails-app/services/com/netflix/asgard/AwsClientService.groovy index f3ac50c4..fe9d788d 100644 --- a/grails-app/services/com/netflix/asgard/AwsClientService.groovy +++ b/grails-app/services/com/netflix/asgard/AwsClientService.groovy @@ -63,10 +63,9 @@ class AwsClientService implements InitializingBean { // AmazonCloudWatch: concrete(/*AmazonCloudWatchClient*/MockAmazonCloudWatchClient, MockAmazonCloudWatchClient), AmazonCloudWatch: concrete(AmazonCloudWatchClient, MockAmazonCloudWatchClient), AmazonEC2: concrete(AmazonEC2Client, MockAmazonEC2Client), - AmazonElasticLoadBalancing: concrete(/*AmazonElasticLoadBalancingClient*/MockAmazonElasticLoadBalancingClient,MockAmazonElasticLoadBalancingClient), -// AmazonElasticLoadBalancing: concrete(AmazonElasticLoadBalancingClient,MockAmazonElasticLoadBalancingClient), +// AmazonElasticLoadBalancing: concrete(/*AmazonElasticLoadBalancingClient*/MockAmazonElasticLoadBalancingClient,MockAmazonElasticLoadBalancingClient), + AmazonElasticLoadBalancing: concrete(AmazonElasticLoadBalancingClient,MockAmazonElasticLoadBalancingClient), AmazonRDS: concrete(/*AmazonRDSClient*/MockAmazonRDSClient, MockAmazonRDSClient), -// AmazonS3: concrete(/*AmazonS3Client*/MockAmazonS3Client, MockAmazonS3Client), AmazonS3: concrete(AmazonS3Client, MockAmazonS3Client), AmazonSimpleDB: concrete(/*AmazonSimpleDBClient*/MockAmazonSimpleDBClient, MockAmazonSimpleDBClient), AmazonSNS: concrete(/*AmazonSNSClient*/MockAmazonSnsClient, MockAmazonSnsClient), From c95a720e5086502dcc52d69e8bae612284a2fefb Mon Sep 17 00:00:00 2001 From: chris grzegorczyk Date: Sun, 21 Apr 2013 02:10:42 -0700 Subject: [PATCH 04/14] restore regions --- src/groovy/com/netflix/asgard/Region.groovy | 86 ++++++++++----------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/src/groovy/com/netflix/asgard/Region.groovy b/src/groovy/com/netflix/asgard/Region.groovy index 7230d0dc..d8a2f7dd 100644 --- a/src/groovy/com/netflix/asgard/Region.groovy +++ b/src/groovy/com/netflix/asgard/Region.groovy @@ -20,7 +20,7 @@ package com.netflix.asgard */ enum Region { - EUCALYPTUS('PARTI', + EUCALYPTUS('qa', 'eucalyptus', 'eucalyptus.png', 'Santa Barbara' @@ -30,48 +30,48 @@ enum Region { 'us-east-1.png', 'Virginia' ), -// -// US_WEST_1('us-west-1', -// 'us-west', -// 'us-west-1.png', -// 'California' -// ), -// -// US_WEST_2('us-west-2', -// 'us-west-2', -// 'us-west-2.png', -// 'Oregon' -// ), -// -// EU_WEST_1('eu-west-1', -// 'eu-ireland', -// 'eu-west-1.png', -// 'Ireland' -// ), -// -// AP_NORTHEAST_1('ap-northeast-1', -// 'apac-tokyo', -// 'ap-northeast-1.png', -// 'Tokyo' -// ), -// -// AP_SOUTHEAST_1('ap-southeast-1', -// 'apac-sin', -// 'ap-southeast-1.png', -// 'Singapore' -// ), -// -// AP_SOUTHEAST_2('ap-southeast-2', -// 'apac-syd', -// 'ap-southeast-2.png', -// 'Sydney' -// ), -// -// SA_EAST_1('sa-east-1', -// 'sa-east-1', -// 'sa-east-1.png', -// 'Sao Paulo' -// ) + + US_WEST_1('us-west-1', + 'us-west', + 'us-west-1.png', + 'California' + ), + + US_WEST_2('us-west-2', + 'us-west-2', + 'us-west-2.png', + 'Oregon' + ), + + EU_WEST_1('eu-west-1', + 'eu-ireland', + 'eu-west-1.png', + 'Ireland' + ), + + AP_NORTHEAST_1('ap-northeast-1', + 'apac-tokyo', + 'ap-northeast-1.png', + 'Tokyo' + ), + + AP_SOUTHEAST_1('ap-southeast-1', + 'apac-sin', + 'ap-southeast-1.png', + 'Singapore' + ), + + AP_SOUTHEAST_2('ap-southeast-2', + 'apac-syd', + 'ap-southeast-2.png', + 'Sydney' + ), + + SA_EAST_1('sa-east-1', + 'sa-east-1', + 'sa-east-1.png', + 'Sao Paulo' + ) String code String pricingJsonCode From 4def2ce1202e26e70ffe20be735f2dbe9b8b19b7 Mon Sep 17 00:00:00 2001 From: chris grzegorczyk Date: Sun, 21 Apr 2013 02:19:31 -0700 Subject: [PATCH 05/14] restore regions --- grails-app/services/com/netflix/asgard/AwsClientService.groovy | 2 -- .../services/com/netflix/asgard/AwsCloudWatchService.groovy | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/grails-app/services/com/netflix/asgard/AwsClientService.groovy b/grails-app/services/com/netflix/asgard/AwsClientService.groovy index fe9d788d..4a494270 100644 --- a/grails-app/services/com/netflix/asgard/AwsClientService.groovy +++ b/grails-app/services/com/netflix/asgard/AwsClientService.groovy @@ -58,9 +58,7 @@ class AwsClientService implements InitializingBean { void afterPropertiesSet() { interfaceSimpleNamesToAwsClientClasses = [ -// AmazonAutoScaling: concrete(/*AmazonAutoScalingClient*/MockAmazonAutoScalingClient, MockAmazonAutoScalingClient), AmazonAutoScaling: concrete(AmazonAutoScalingClient, MockAmazonAutoScalingClient), -// AmazonCloudWatch: concrete(/*AmazonCloudWatchClient*/MockAmazonCloudWatchClient, MockAmazonCloudWatchClient), AmazonCloudWatch: concrete(AmazonCloudWatchClient, MockAmazonCloudWatchClient), AmazonEC2: concrete(AmazonEC2Client, MockAmazonEC2Client), // AmazonElasticLoadBalancing: concrete(/*AmazonElasticLoadBalancingClient*/MockAmazonElasticLoadBalancingClient,MockAmazonElasticLoadBalancingClient), diff --git a/grails-app/services/com/netflix/asgard/AwsCloudWatchService.groovy b/grails-app/services/com/netflix/asgard/AwsCloudWatchService.groovy index 37720b92..8f71f417 100644 --- a/grails-app/services/com/netflix/asgard/AwsCloudWatchService.groovy +++ b/grails-app/services/com/netflix/asgard/AwsCloudWatchService.groovy @@ -120,7 +120,7 @@ class AwsCloudWatchService implements CacheInitializer, InitializingBean { final List alarms = result.metricAlarms // Fix cache to update found alarms and remove missing alarms - //caches.allAlarms.by(userContext.region).putAllAndRemoveMissing(alarmNames, alarms) + caches.allAlarms.by(userContext.region).putAllAndRemoveMissing(alarmNames, alarms) alarms } From 21f699c6f93a859e8b89f8855b3a8718dcd1a883 Mon Sep 17 00:00:00 2001 From: chris grzegorczyk Date: Sun, 21 Apr 2013 02:25:09 -0700 Subject: [PATCH 06/14] scheduled policies --- .../com/netflix/asgard/AwsAutoScalingService.groovy | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy b/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy index 05f4da98..a2eb1140 100644 --- a/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy +++ b/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy @@ -131,20 +131,21 @@ class AwsAutoScalingService implements CacheInitializer, InitializingBean { // Cluster cache has no timer. It gets triggered by the Auto Scaling Group cache callback closure. caches.allClusters.ensureSetUp( { Region region -> buildClusters(region, caches.allAutoScalingGroups.by(region).list()) }, {}, -// { Region region -> + { Region region -> // boolean awaitingLoadBalancers = caches.allLoadBalancers.by(region).isDoingFirstFill() // boolean awaitingAppInstances = caches.allApplicationInstances.by(region).isDoingFirstFill() -// boolean awaitingImages = caches.allImages.by(region).isDoingFirstFill() -// boolean awaitingEc2Instances = caches.allInstances.by(region).isDoingFirstFill() + boolean awaitingImages = caches.allImages.by(region).isDoingFirstFill() + boolean awaitingEc2Instances = caches.allInstances.by(region).isDoingFirstFill() + !awaitingImages && !awaitingEc2Instances // !awaitingLoadBalancers && !awaitingAppInstances && !awaitingImages && !awaitingEc2Instances -// } + } ) caches.allAutoScalingGroups.ensureSetUp({ Region region -> retrieveAutoScalingGroups(region) }, { Region region -> caches.allClusters.by(region).fill() }) caches.allLaunchConfigurations.ensureSetUp({ Region region -> retrieveLaunchConfigurations(region) }) caches.allScalingPolicies.ensureSetUp({ Region region -> retrieveScalingPolicies(region) }) caches.allTerminationPolicyTypes.ensureSetUp({ Region region -> retrieveTerminationPolicyTypes() }) -// caches.allScheduledActions.ensureSetUp({ Region region -> retrieveScheduledActions(region) }) + caches.allScheduledActions.ensureSetUp({ Region region -> retrieveScheduledActions(region) }) // caches.allSignificantStackInstanceHealthChecks.ensureSetUp( // { Region region -> retrieveInstanceHealthChecks(region) }, {}, // { Region region -> From c3776e8ff7a629cd1c9bd5c1e0d6f25082228209 Mon Sep 17 00:00:00 2001 From: chris grzegorczyk Date: Sun, 21 Apr 2013 02:28:06 -0700 Subject: [PATCH 07/14] app instances --- .../services/com/netflix/asgard/AwsAutoScalingService.groovy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy b/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy index a2eb1140..f3aac32f 100644 --- a/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy +++ b/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy @@ -133,10 +133,10 @@ class AwsAutoScalingService implements CacheInitializer, InitializingBean { { Region region -> buildClusters(region, caches.allAutoScalingGroups.by(region).list()) }, {}, { Region region -> // boolean awaitingLoadBalancers = caches.allLoadBalancers.by(region).isDoingFirstFill() -// boolean awaitingAppInstances = caches.allApplicationInstances.by(region).isDoingFirstFill() + boolean awaitingAppInstances = caches.allApplicationInstances.by(region).isDoingFirstFill() boolean awaitingImages = caches.allImages.by(region).isDoingFirstFill() boolean awaitingEc2Instances = caches.allInstances.by(region).isDoingFirstFill() - !awaitingImages && !awaitingEc2Instances + !awaitingAppInstances && !awaitingImages && !awaitingEc2Instances // !awaitingLoadBalancers && !awaitingAppInstances && !awaitingImages && !awaitingEc2Instances } ) From 1bf94b8cf8d0ae4d63cf4c7cf94462747d08bf05 Mon Sep 17 00:00:00 2001 From: chris grzegorczyk Date: Sun, 21 Apr 2013 02:29:56 -0700 Subject: [PATCH 08/14] elb & app instances --- .../netflix/asgard/AwsAutoScalingService.groovy | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy b/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy index f3aac32f..e95fcf85 100644 --- a/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy +++ b/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy @@ -132,12 +132,11 @@ class AwsAutoScalingService implements CacheInitializer, InitializingBean { caches.allClusters.ensureSetUp( { Region region -> buildClusters(region, caches.allAutoScalingGroups.by(region).list()) }, {}, { Region region -> -// boolean awaitingLoadBalancers = caches.allLoadBalancers.by(region).isDoingFirstFill() + boolean awaitingLoadBalancers = caches.allLoadBalancers.by(region).isDoingFirstFill() boolean awaitingAppInstances = caches.allApplicationInstances.by(region).isDoingFirstFill() boolean awaitingImages = caches.allImages.by(region).isDoingFirstFill() boolean awaitingEc2Instances = caches.allInstances.by(region).isDoingFirstFill() - !awaitingAppInstances && !awaitingImages && !awaitingEc2Instances -// !awaitingLoadBalancers && !awaitingAppInstances && !awaitingImages && !awaitingEc2Instances + !awaitingLoadBalancers && !awaitingAppInstances && !awaitingImages && !awaitingEc2Instances } ) caches.allAutoScalingGroups.ensureSetUp({ Region region -> retrieveAutoScalingGroups(region) }, @@ -146,12 +145,12 @@ class AwsAutoScalingService implements CacheInitializer, InitializingBean { caches.allScalingPolicies.ensureSetUp({ Region region -> retrieveScalingPolicies(region) }) caches.allTerminationPolicyTypes.ensureSetUp({ Region region -> retrieveTerminationPolicyTypes() }) caches.allScheduledActions.ensureSetUp({ Region region -> retrieveScheduledActions(region) }) -// caches.allSignificantStackInstanceHealthChecks.ensureSetUp( -// { Region region -> retrieveInstanceHealthChecks(region) }, {}, -// { Region region -> -// caches.allApplicationInstances.by(region).filled && caches.allAutoScalingGroups.by(region).filled -// } -// ) + caches.allSignificantStackInstanceHealthChecks.ensureSetUp( + { Region region -> retrieveInstanceHealthChecks(region) }, {}, + { Region region -> + caches.allApplicationInstances.by(region).filled && caches.allAutoScalingGroups.by(region).filled + } + ) } // Clusters From 7e96215bd59a6411696204a466afcc25bb4be93c Mon Sep 17 00:00:00 2001 From: chris grzegorczyk Date: Sun, 21 Apr 2013 02:32:13 -0700 Subject: [PATCH 09/14] unrestore regions --- src/groovy/com/netflix/asgard/Region.groovy | 91 +++++++++++---------- 1 file changed, 46 insertions(+), 45 deletions(-) diff --git a/src/groovy/com/netflix/asgard/Region.groovy b/src/groovy/com/netflix/asgard/Region.groovy index d8a2f7dd..46b672be 100644 --- a/src/groovy/com/netflix/asgard/Region.groovy +++ b/src/groovy/com/netflix/asgard/Region.groovy @@ -20,64 +20,65 @@ package com.netflix.asgard */ enum Region { - EUCALYPTUS('qa', + EUCALYPTUS('euca-qa', 'eucalyptus', 'eucalyptus.png', - 'Santa Barbara' + 'Santa Barbara' ), + US_EAST_1('us-east-1', 'us-east', 'us-east-1.png', 'Virginia' ), - - US_WEST_1('us-west-1', - 'us-west', - 'us-west-1.png', - 'California' - ), - - US_WEST_2('us-west-2', - 'us-west-2', - 'us-west-2.png', - 'Oregon' - ), - - EU_WEST_1('eu-west-1', - 'eu-ireland', - 'eu-west-1.png', - 'Ireland' - ), - - AP_NORTHEAST_1('ap-northeast-1', - 'apac-tokyo', - 'ap-northeast-1.png', - 'Tokyo' - ), - - AP_SOUTHEAST_1('ap-southeast-1', - 'apac-sin', - 'ap-southeast-1.png', - 'Singapore' - ), - - AP_SOUTHEAST_2('ap-southeast-2', - 'apac-syd', - 'ap-southeast-2.png', - 'Sydney' - ), - - SA_EAST_1('sa-east-1', - 'sa-east-1', - 'sa-east-1.png', - 'Sao Paulo' - ) +// +// US_WEST_1('us-west-1', +// 'us-west', +// 'us-west-1.png', +// 'California' +// ), +// +// US_WEST_2('us-west-2', +// 'us-west-2', +// 'us-west-2.png', +// 'Oregon' +// ), +// +// EU_WEST_1('eu-west-1', +// 'eu-ireland', +// 'eu-west-1.png', +// 'Ireland' +// ), +// +// AP_NORTHEAST_1('ap-northeast-1', +// 'apac-tokyo', +// 'ap-northeast-1.png', +// 'Tokyo' +// ), +// +// AP_SOUTHEAST_1('ap-southeast-1', +// 'apac-sin', +// 'ap-southeast-1.png', +// 'Singapore' +// ), +// +// AP_SOUTHEAST_2('ap-southeast-2', +// 'apac-syd', +// 'ap-southeast-2.png', +// 'Sydney' +// ), +// +// SA_EAST_1('sa-east-1', +// 'sa-east-1', +// 'sa-east-1.png', +// 'Sao Paulo' +// ) String code String pricingJsonCode String mapImageFileName String location - + Region(String code, String pricingJsonCode, mapImageFileName, location) { this.code = code this.pricingJsonCode = pricingJsonCode From 7a0ff25461084a001010ae288073d07706088deb Mon Sep 17 00:00:00 2001 From: chris grzegorczyk Date: Sun, 21 Apr 2013 02:36:41 -0700 Subject: [PATCH 10/14] remove app instances atm --- .../services/com/netflix/asgard/AwsAutoScalingService.groovy | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy b/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy index e95fcf85..3c23090e 100644 --- a/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy +++ b/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy @@ -146,7 +146,8 @@ class AwsAutoScalingService implements CacheInitializer, InitializingBean { caches.allTerminationPolicyTypes.ensureSetUp({ Region region -> retrieveTerminationPolicyTypes() }) caches.allScheduledActions.ensureSetUp({ Region region -> retrieveScheduledActions(region) }) caches.allSignificantStackInstanceHealthChecks.ensureSetUp( - { Region region -> retrieveInstanceHealthChecks(region) }, {}, +//GRZE: this depends on meaningful add definitions... +// { Region region -> retrieveInstanceHealthChecks(region) }, {}, { Region region -> caches.allApplicationInstances.by(region).filled && caches.allAutoScalingGroups.by(region).filled } From b8be5f6b5f8a0c61c7904130fe1cce60f9562e4e Mon Sep 17 00:00:00 2001 From: chris grzegorczyk Date: Sun, 21 Apr 2013 02:38:19 -0700 Subject: [PATCH 11/14] remove app instances atm --- .../com/netflix/asgard/AwsAutoScalingService.groovy | 10 +++++----- src/groovy/com/netflix/asgard/Region.groovy | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy b/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy index 3c23090e..b1d30d77 100644 --- a/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy +++ b/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy @@ -145,13 +145,13 @@ class AwsAutoScalingService implements CacheInitializer, InitializingBean { caches.allScalingPolicies.ensureSetUp({ Region region -> retrieveScalingPolicies(region) }) caches.allTerminationPolicyTypes.ensureSetUp({ Region region -> retrieveTerminationPolicyTypes() }) caches.allScheduledActions.ensureSetUp({ Region region -> retrieveScheduledActions(region) }) - caches.allSignificantStackInstanceHealthChecks.ensureSetUp( //GRZE: this depends on meaningful add definitions... +// caches.allSignificantStackInstanceHealthChecks.ensureSetUp( // { Region region -> retrieveInstanceHealthChecks(region) }, {}, - { Region region -> - caches.allApplicationInstances.by(region).filled && caches.allAutoScalingGroups.by(region).filled - } - ) +// { Region region -> +// caches.allApplicationInstances.by(region).filled && caches.allAutoScalingGroups.by(region).filled +// } +// ) } // Clusters diff --git a/src/groovy/com/netflix/asgard/Region.groovy b/src/groovy/com/netflix/asgard/Region.groovy index 46b672be..2212cb0f 100644 --- a/src/groovy/com/netflix/asgard/Region.groovy +++ b/src/groovy/com/netflix/asgard/Region.groovy @@ -30,7 +30,7 @@ enum Region { 'us-east', 'us-east-1.png', 'Virginia' - ), + ) // // US_WEST_1('us-west-1', // 'us-west', From 264c27a19250f6e40fffda40085f2e371f26571f Mon Sep 17 00:00:00 2001 From: chris grzegorczyk Date: Mon, 22 Apr 2013 02:25:45 -0700 Subject: [PATCH 12/14] add endpoint service --- .../com/netflix/asgard/EndpointService.groovy | 8 ++++++++ .../netflix/asgard/EndpointServiceSpec.groovy | 20 +++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 grails-app/services/com/netflix/asgard/EndpointService.groovy create mode 100644 test/unit/com/netflix/asgard/EndpointServiceSpec.groovy diff --git a/grails-app/services/com/netflix/asgard/EndpointService.groovy b/grails-app/services/com/netflix/asgard/EndpointService.groovy new file mode 100644 index 00000000..89182557 --- /dev/null +++ b/grails-app/services/com/netflix/asgard/EndpointService.groovy @@ -0,0 +1,8 @@ +package com.netflix.asgard + +class EndpointService { + + def serviceMethod() { + + } +} diff --git a/test/unit/com/netflix/asgard/EndpointServiceSpec.groovy b/test/unit/com/netflix/asgard/EndpointServiceSpec.groovy new file mode 100644 index 00000000..bee7e485 --- /dev/null +++ b/test/unit/com/netflix/asgard/EndpointServiceSpec.groovy @@ -0,0 +1,20 @@ +package com.netflix.asgard + +import grails.test.mixin.TestFor +import spock.lang.Specification + +/** + * See the API for {@link grails.test.mixin.services.ServiceUnitTestMixin} for usage instructions + */ +@TestFor(EndpointService) +class EndpointServiceSpec extends Specification { + + def setup() { + } + + def cleanup() { + } + + void "test something"() { + } +} From 372b1b35ed0f363e9539d41b7f8f856dc153b198 Mon Sep 17 00:00:00 2001 From: chris grzegorczyk Date: Mon, 22 Apr 2013 02:41:40 -0700 Subject: [PATCH 13/14] add endpoint service --- grails-app/conf/Config.groovy | 56 +++------ .../asgard/InstanceTypeController.groovy | 1 - .../asgard/AwsAutoScalingService.groovy | 17 ++- .../netflix/asgard/AwsClientService.groovy | 50 ++++---- .../asgard/AwsCloudWatchService.groovy | 4 +- .../com/netflix/asgard/AwsEc2Service.groovy | 18 ++- .../asgard/AwsLoadBalancerService.groovy | 4 +- .../com/netflix/asgard/AwsRdsService.groovy | 4 +- .../com/netflix/asgard/AwsS3Service.groovy | 6 +- .../netflix/asgard/AwsSimpleDbService.groovy | 5 +- .../com/netflix/asgard/AwsSnsService.groovy | 9 +- .../com/netflix/asgard/AwsSqsService.groovy | 4 +- .../services/com/netflix/asgard/Caches.groovy | 24 ++-- .../com/netflix/asgard/ConfigService.groovy | 28 ++--- .../com/netflix/asgard/EndpointService.groovy | 51 +++++++- .../com/netflix/asgard/InitService.groovy | 3 +- .../netflix/asgard/InstanceTypeService.groovy | 23 +--- .../com/netflix/asgard/SecretService.groovy | 10 +- src/groovy/com/netflix/asgard/Region.groovy | 112 ++++++++++-------- web-app/images/worldmap/eucalyptus.png | Bin 6937 -> 1215 bytes 20 files changed, 219 insertions(+), 210 deletions(-) diff --git a/grails-app/conf/Config.groovy b/grails-app/conf/Config.groovy index ebcd481f..bcf766dd 100644 --- a/grails-app/conf/Config.groovy +++ b/grails-app/conf/Config.groovy @@ -134,44 +134,26 @@ cloud { // TODO: Delete these instance type hacks when they are in the AWS Java SDK enum instead customInstanceTypes = [ - new InstanceTypeData(linuxOnDemandPrice: 0.1, hardwareProfile: - new HardwareProfile(instanceType: 'm1.small', architecture: '64-bit', - cpu: '1 EC2 Compute Units (1 virtual cores with 1 EC2 Compute Units each)', - description: 'M1 Small Instance', - ioPerformance: 'Poor', memory: '0.25 GiB', - storage: '5 GB of instance storage')), - new InstanceTypeData(linuxOnDemandPrice: 0.2, hardwareProfile: - new HardwareProfile(instanceType: 'm1.medium', architecture: '64-bit', - cpu: '1 EC2 Compute Units (1 virtual cores with 1 EC2 Compute Units each)', - description: 'M1 Medium Instance', - ioPerformance: 'Poor', memory: '0.5 GiB', - storage: '10 GB of instance storage')), - new InstanceTypeData(linuxOnDemandPrice: 0.3, hardwareProfile: - new HardwareProfile(instanceType: 'm1.large', architecture: '64-bit', - cpu: '2 EC2 Compute Units (2 virtual cores with 1 EC2 Compute Units each)', - description: 'M1 Large Instance', - ioPerformance: 'Poor', memory: '0.5 GiB', - storage: '10 GB of instance storage')), - new InstanceTypeData(linuxOnDemandPrice: 0.5, hardwareProfile: - new HardwareProfile(instanceType: 'm1.xlarge', architecture: '64-bit', - cpu: '2 EC2 Compute Units (2 virtual cores with 1 EC2 Compute Units each)', - description: 'M1 Xtra-Large Instance', - ioPerformance: 'Poor', memory: '1 GiB', - storage: '10 GB of instance storage')), -// new InstanceTypeData(linuxOnDemandPrice: 0.580, hardwareProfile: -// new HardwareProfile(instanceType: 'm3.xlarge', architecture: '64-bit', -// cpu: '13 EC2 Compute Units (4 virtual cores with 3.25 EC2 Compute Units each)', -// description: 'M3 Extra Large Instance', -// ioPerformance: 'Moderate', memory: '15 GiB', -// storage: 'EBS storage only')), -// new InstanceTypeData(linuxOnDemandPrice: 1.160, hardwareProfile: -// new HardwareProfile(instanceType: 'm3.2xlarge', architecture: '64-bit', -// cpu: '26 EC2 Compute Units (8 virtual cores with 3.25 EC2 Compute Units each)', -// description: 'M3 Double Extra Large Instance', -// ioPerformance: 'High', memory: '30 GiB', -// storage: 'EBS storage only')), + new InstanceTypeData(linuxOnDemandPrice: 0.580, hardwareProfile: + new HardwareProfile(instanceType: 'm3.xlarge', architecture: '64-bit', + cpu: '13 EC2 Compute Units (4 virtual cores with 3.25 EC2 Compute Units each)', + description: 'M3 Extra Large Instance', + ioPerformance: 'Moderate', memory: '15 GiB', + storage: 'EBS storage only')), + new InstanceTypeData(linuxOnDemandPrice: 1.160, hardwareProfile: + new HardwareProfile(instanceType: 'm3.2xlarge', architecture: '64-bit', + cpu: '26 EC2 Compute Units (8 virtual cores with 3.25 EC2 Compute Units each)', + description: 'M3 Double Extra Large Instance', + ioPerformance: 'High', memory: '30 GiB', + storage: 'EBS storage only')), + new InstanceTypeData(linuxOnDemandPrice: 3.50, hardwareProfile: + new HardwareProfile(instanceType: 'cr1.8xlarge', architecture: '64-bit', + cpu: '88 EC2 Compute Units (2 x Intel Xeon E5-2670, eight-core)', + description: 'Cluster High Memory', + ioPerformance: '10 Gbps Ethernet', memory: '244 GiB', + storage: '240 GiB instance 64-bit storage (2 x 120 GiB SSD)')), ] -// spot.infoUrl = 'http://aws.amazon.com/ec2/spot-instances/' + spot.infoUrl = 'http://aws.amazon.com/ec2/spot-instances/' } healthCheck { diff --git a/grails-app/controllers/com/netflix/asgard/InstanceTypeController.groovy b/grails-app/controllers/com/netflix/asgard/InstanceTypeController.groovy index af6eba68..492ea221 100644 --- a/grails-app/controllers/com/netflix/asgard/InstanceTypeController.groovy +++ b/grails-app/controllers/com/netflix/asgard/InstanceTypeController.groovy @@ -30,7 +30,6 @@ class InstanceTypeController { def list = { UserContext userContext = UserContext.of(request) List instanceTypes = instanceTypeService.getInstanceTypes(userContext) - println instanceTypes Map details = [instanceTypes: instanceTypes] withFormat { html { details } diff --git a/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy b/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy index b1d30d77..43c21bde 100644 --- a/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy +++ b/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy @@ -121,9 +121,7 @@ class AwsAutoScalingService implements CacheInitializer, InitializingBean { void afterPropertiesSet() { awsClient = new MultiRegionAwsClient({ Region region -> - AmazonAutoScaling client = awsClientService.create(AmazonAutoScaling) - client.setEndpoint("http://eucalyptus:8773/services/AutoScaling") - client + awsClientService.create(AmazonAutoScaling,region) }) } @@ -145,13 +143,12 @@ class AwsAutoScalingService implements CacheInitializer, InitializingBean { caches.allScalingPolicies.ensureSetUp({ Region region -> retrieveScalingPolicies(region) }) caches.allTerminationPolicyTypes.ensureSetUp({ Region region -> retrieveTerminationPolicyTypes() }) caches.allScheduledActions.ensureSetUp({ Region region -> retrieveScheduledActions(region) }) -//GRZE: this depends on meaningful add definitions... -// caches.allSignificantStackInstanceHealthChecks.ensureSetUp( -// { Region region -> retrieveInstanceHealthChecks(region) }, {}, -// { Region region -> -// caches.allApplicationInstances.by(region).filled && caches.allAutoScalingGroups.by(region).filled -// } -// ) + caches.allSignificantStackInstanceHealthChecks.ensureSetUp( + { Region region -> retrieveInstanceHealthChecks(region) }, {}, + { Region region -> + caches.allApplicationInstances.by(region).filled && caches.allAutoScalingGroups.by(region).filled + } + ) } // Clusters diff --git a/grails-app/services/com/netflix/asgard/AwsClientService.groovy b/grails-app/services/com/netflix/asgard/AwsClientService.groovy index 4a494270..95b524f1 100644 --- a/grails-app/services/com/netflix/asgard/AwsClientService.groovy +++ b/grails-app/services/com/netflix/asgard/AwsClientService.groovy @@ -16,6 +16,7 @@ package com.netflix.asgard import com.amazonaws.ClientConfiguration +import com.amazonaws.regions.Regions import com.amazonaws.services.autoscaling.AmazonAutoScalingClient import com.amazonaws.services.cloudwatch.AmazonCloudWatchClient import com.amazonaws.services.ec2.AmazonEC2Client @@ -45,6 +46,7 @@ class AwsClientService implements InitializingBean { def grailsApplication def secretService + def endpointService def serverService def configService @@ -52,39 +54,47 @@ class AwsClientService implements InitializingBean { * Interface names mapped to ClientTypes wrapper objects. For each interface name, a real and fake concrete class * type should be provided. */ - private Map interfaceSimpleNamesToAwsClientClasses + private Map> interfaceSimpleNamesToAwsClientClasses = [:] private ClientConfiguration clientConfiguration void afterPropertiesSet() { - interfaceSimpleNamesToAwsClientClasses = [ - AmazonAutoScaling: concrete(AmazonAutoScalingClient, MockAmazonAutoScalingClient), - AmazonCloudWatch: concrete(AmazonCloudWatchClient, MockAmazonCloudWatchClient), - AmazonEC2: concrete(AmazonEC2Client, MockAmazonEC2Client), -// AmazonElasticLoadBalancing: concrete(/*AmazonElasticLoadBalancingClient*/MockAmazonElasticLoadBalancingClient,MockAmazonElasticLoadBalancingClient), - AmazonElasticLoadBalancing: concrete(AmazonElasticLoadBalancingClient,MockAmazonElasticLoadBalancingClient), - AmazonRDS: concrete(/*AmazonRDSClient*/MockAmazonRDSClient, MockAmazonRDSClient), - AmazonS3: concrete(AmazonS3Client, MockAmazonS3Client), - AmazonSimpleDB: concrete(/*AmazonSimpleDBClient*/MockAmazonSimpleDBClient, MockAmazonSimpleDBClient), - AmazonSNS: concrete(/*AmazonSNSClient*/MockAmazonSnsClient, MockAmazonSnsClient), - AmazonSQS: concrete(/*AmazonSQSClient*/MockAmazonSqsClient, MockAmazonSqsClient) - ] + Set providers = Region.values().collect { it.provider } as Set + Region.values().findAll { providers.remove(it.provider) }.each { Region region -> + interfaceSimpleNamesToAwsClientClasses[region.provider] = [ + AmazonAutoScaling: concrete(region, AmazonAutoScalingClient, MockAmazonAutoScalingClient), + AmazonCloudWatch: concrete(region, AmazonCloudWatchClient, MockAmazonCloudWatchClient), + AmazonEC2: concrete(region, AmazonEC2Client, MockAmazonEC2Client), + AmazonElasticLoadBalancing: concrete(region, AmazonElasticLoadBalancingClient, MockAmazonElasticLoadBalancingClient), + AmazonRDS: concrete(region, AmazonRDSClient, MockAmazonRDSClient), + AmazonS3: concrete(region, AmazonS3Client, MockAmazonS3Client), + AmazonSimpleDB: concrete(region, AmazonSimpleDBClient, MockAmazonSimpleDBClient), + AmazonSNS: concrete(region, AmazonSNSClient, MockAmazonSnsClient), + AmazonSQS: concrete(region, AmazonSQSClient, MockAmazonSqsClient) + ] + } clientConfiguration = new ClientConfiguration() clientConfiguration.proxyHost = configService.proxyHost clientConfiguration.proxyPort = configService.proxyPort clientConfiguration.userAgent = 'asgard-' + serverService.version } - public T create(Class interfaceType) { - Class implementationType = interfaceSimpleNamesToAwsClientClasses[interfaceType.simpleName] - createImpl(implementationType) + public T create(Class interfaceType, Region region = Region.US_EAST_1) { + Class implementationType = interfaceSimpleNamesToAwsClientClasses[region.provider][interfaceType.simpleName] + createImpl(implementationType, interfaceType, region) } - public T createImpl(Class implementationType) { - implementationType.newInstance(secretService.awsCredentials, clientConfiguration) as T + public T createImpl(Class implementationType, Class interfaceType = null, Region region = Region.US_EAST_1) { + //GRZE:NOTE: just default to Region.US_EAST_1 if there is no endpoint, need to make sure and use right credentials then. + region = endpointService.getEndpoint(region, interfaceType) != null ? region : Region.US_EAST_1 + T client = implementationType.newInstance(secretService.awsCredentials[region], clientConfiguration) as T + client.setEndpoint(endpointService.getEndpoint(region, interfaceType)) + client } - Class concrete(Class real, Class fake) { - grailsApplication.config.server.online ? real : fake + Class concrete(Region region, Class real, Class fake) { + Class interfaceType = real.class.interfaces[0] + Set mocks = grailsApplication.config.grails?."${region.provider}"?.mockServices ?: [] + !mocks.contains(interfaceType.simpleName) && grailsApplication.config.server.online ? real : fake } } diff --git a/grails-app/services/com/netflix/asgard/AwsCloudWatchService.groovy b/grails-app/services/com/netflix/asgard/AwsCloudWatchService.groovy index 8f71f417..06c3831a 100644 --- a/grails-app/services/com/netflix/asgard/AwsCloudWatchService.groovy +++ b/grails-app/services/com/netflix/asgard/AwsCloudWatchService.groovy @@ -53,9 +53,7 @@ class AwsCloudWatchService implements CacheInitializer, InitializingBean { void afterPropertiesSet() { awsClient = new MultiRegionAwsClient( { Region region -> - AmazonCloudWatch client = awsClientService.create(AmazonCloudWatch) - client.setEndpoint("http://eucalyptus:8773/services/CloudWatch") - client + awsClientService.create(AmazonCloudWatch,region) }) } diff --git a/grails-app/services/com/netflix/asgard/AwsEc2Service.groovy b/grails-app/services/com/netflix/asgard/AwsEc2Service.groovy index c3662d6c..14763acd 100644 --- a/grails-app/services/com/netflix/asgard/AwsEc2Service.groovy +++ b/grails-app/services/com/netflix/asgard/AwsEc2Service.groovy @@ -119,10 +119,8 @@ class AwsEc2Service implements CacheInitializer, InitializingBean { private static final int TAG_IMAGE_CHUNK_SIZE = 250 void afterPropertiesSet() { - awsClient = awsClient ?: new MultiRegionAwsClient({ Region region -> - AmazonEC2 client = awsClientService.create(AmazonEC2) - client.setEndpoint("http://eucalyptus:8773/services/Eucalyptus/") - client + awsClient = new MultiRegionAwsClient({ Region region -> + awsClientService.create(AmazonEC2,region) }) accounts = configService.awsAccounts } @@ -161,7 +159,7 @@ class AwsEc2Service implements CacheInitializer, InitializingBean { // Images private List retrieveImages(Region region) { - List owners = configService.publicResourceAccounts + configService.awsAccounts + List owners = configService.publicResourceAccounts + configService.getAwsAccounts(region) DescribeImagesRequest request = new DescribeImagesRequest().withOwners(owners) AmazonEC2 awsClientForRegion = awsClient.by(region) List images = awsClientForRegion.describeImages(request).getImages() @@ -187,7 +185,7 @@ class AwsEc2Service implements CacheInitializer, InitializingBean { } private Collection retrieveSubnets(Region region) { -// awsClient.by(region).describeSubnets().subnets + awsClient.by(region).describeSubnets().subnets } /** @@ -201,7 +199,7 @@ class AwsEc2Service implements CacheInitializer, InitializingBean { } private Collection retrieveVpcs(Region region) { -// awsClient.by(region).describeVpcs().vpcs + awsClient.by(region).describeVpcs().vpcs } /** @@ -638,13 +636,13 @@ class AwsEc2Service implements CacheInitializer, InitializingBean { // TODO: Delete this method after rewriting AwsResultsRetrieverSpec unit test to use some other use case DescribeSpotPriceHistoryResult describeSpotPriceHistory(Region region, DescribeSpotPriceHistoryRequest describeSpotPriceHistoryRequest) { -// awsClient.by(region).describeSpotPriceHistory(describeSpotPriceHistoryRequest) + awsClient.by(region).describeSpotPriceHistory(describeSpotPriceHistoryRequest) } // Spot Instance Requests List retrieveSpotInstanceRequests(Region region) { -// awsClient.by(region).describeSpotInstanceRequests().spotInstanceRequests + awsClient.by(region).describeSpotInstanceRequests().spotInstanceRequests } DescribeSpotInstanceRequestsResult describeSpotInstanceRequests(UserContext userContext, @@ -873,7 +871,7 @@ class AwsEc2Service implements CacheInitializer, InitializingBean { // Reservations private List retrieveReservations(Region region) { -// awsClient.by(region).describeReservedInstances().reservedInstances + awsClient.by(region).describeReservedInstances().reservedInstances } /** diff --git a/grails-app/services/com/netflix/asgard/AwsLoadBalancerService.groovy b/grails-app/services/com/netflix/asgard/AwsLoadBalancerService.groovy index 2b262529..24cd9ae5 100644 --- a/grails-app/services/com/netflix/asgard/AwsLoadBalancerService.groovy +++ b/grails-app/services/com/netflix/asgard/AwsLoadBalancerService.groovy @@ -58,9 +58,7 @@ class AwsLoadBalancerService implements CacheInitializer, InitializingBean { void afterPropertiesSet() { awsClient = awsClient ?: new MultiRegionAwsClient( { Region region -> - AmazonElasticLoadBalancing client = awsClientService.create(AmazonElasticLoadBalancing) - client.setEndpoint("http://eucalyptus:8773/services/LoadBalancing") - client + awsClientService.create(AmazonElasticLoadBalancing,region) }) } diff --git a/grails-app/services/com/netflix/asgard/AwsRdsService.groovy b/grails-app/services/com/netflix/asgard/AwsRdsService.groovy index e8f0eee7..be72dc01 100644 --- a/grails-app/services/com/netflix/asgard/AwsRdsService.groovy +++ b/grails-app/services/com/netflix/asgard/AwsRdsService.groovy @@ -70,9 +70,7 @@ class AwsRdsService implements CacheInitializer, InitializingBean { void afterPropertiesSet() { awsClient = new MultiRegionAwsClient( { Region region -> - AmazonRDS client = awsClientService.create(AmazonRDS) - client.setEndpoint("rds.${region}.amazonaws.com") - client + awsClientService.create(AmazonRDS,region) }) accounts = configService.awsAccounts } diff --git a/grails-app/services/com/netflix/asgard/AwsS3Service.groovy b/grails-app/services/com/netflix/asgard/AwsS3Service.groovy index 9f6ccbf8..db6758c8 100644 --- a/grails-app/services/com/netflix/asgard/AwsS3Service.groovy +++ b/grails-app/services/com/netflix/asgard/AwsS3Service.groovy @@ -34,11 +34,7 @@ class AwsS3Service implements InitializingBean { void afterPropertiesSet() { awsClient = new MultiRegionAwsClient( { Region region -> - AmazonS3 client = awsClientService.create(AmazonS3) - // Unconventional S3 endpoints. http://docs.amazonwebservices.com/general/latest/gr/index.html?rande.html -// if (region != Region.US_EAST_1) { client.setEndpoint("s3-${region}.amazonaws.com") } - client.setEndpoint( "http://eucalyptus:8773/services/Walrus" ) - client + awsClientService.create(AmazonS3,region) }) } diff --git a/grails-app/services/com/netflix/asgard/AwsSimpleDbService.groovy b/grails-app/services/com/netflix/asgard/AwsSimpleDbService.groovy index 859592a6..d7a6a23a 100644 --- a/grails-app/services/com/netflix/asgard/AwsSimpleDbService.groovy +++ b/grails-app/services/com/netflix/asgard/AwsSimpleDbService.groovy @@ -43,10 +43,7 @@ class AwsSimpleDbService implements InitializingBean { void afterPropertiesSet() { awsClient = new MultiRegionAwsClient( { Region region -> - AmazonSimpleDB client = awsClientService.create(AmazonSimpleDB) - // Unconventional SDB endpoints. http://docs.amazonwebservices.com/general/latest/gr/index.html?rande.html - if (region != Region.US_EAST_1) { client.setEndpoint("sdb.${region}.amazonaws.com") } - client + awsClientService.create(AmazonSimpleDB,region) }) } diff --git a/grails-app/services/com/netflix/asgard/AwsSnsService.groovy b/grails-app/services/com/netflix/asgard/AwsSnsService.groovy index c0e693ea..72762dd6 100644 --- a/grails-app/services/com/netflix/asgard/AwsSnsService.groovy +++ b/grails-app/services/com/netflix/asgard/AwsSnsService.groovy @@ -39,7 +39,6 @@ class AwsSnsService implements CacheInitializer, InitializingBean { static transactional = false - private String accountNumber MultiRegionAwsClient awsClient def grailsApplication def awsClientService @@ -67,12 +66,8 @@ class AwsSnsService implements CacheInitializer, InitializingBean { } void afterPropertiesSet() { - accountNumber = configService.awsAccountNumber - awsClient = awsClient ?: new MultiRegionAwsClient( { Region region -> - AmazonSNS client = awsClientService.create(AmazonSNS) - client.setEndpoint("sns.${region}.amazonaws.com") - client + awsClientService.create(AmazonSNS,region) }) } @@ -98,7 +93,7 @@ class AwsSnsService implements CacheInitializer, InitializingBean { return caches.allTopics.by(region).get(topicName) } TopicData existingTopic = caches.allTopics.by(region).get(topicName) - TopicData topic = existingTopic ?: new TopicData(region, accountNumber, topicName) + TopicData topic = existingTopic ?: new TopicData(region, configService.awsAccountNumber, topicName) String arn = topic.arn try { GetTopicAttributesRequest attributesRequest = new GetTopicAttributesRequest(arn) diff --git a/grails-app/services/com/netflix/asgard/AwsSqsService.groovy b/grails-app/services/com/netflix/asgard/AwsSqsService.groovy index 6527b2b3..8dd15ad4 100644 --- a/grails-app/services/com/netflix/asgard/AwsSqsService.groovy +++ b/grails-app/services/com/netflix/asgard/AwsSqsService.groovy @@ -42,9 +42,7 @@ class AwsSqsService implements CacheInitializer, InitializingBean { accountNumber = grailsApplication.config.grails.awsAccounts[0] awsClient = new MultiRegionAwsClient( { Region region -> - AmazonSQS client = awsClientService.create(AmazonSQS) - client.setEndpoint("sqs.${region}.amazonaws.com") - client + awsClientService.create(AmazonSQS,region) }) } diff --git a/grails-app/services/com/netflix/asgard/Caches.groovy b/grails-app/services/com/netflix/asgard/Caches.groovy index c69aec15..ad14aaf4 100644 --- a/grails-app/services/com/netflix/asgard/Caches.groovy +++ b/grails-app/services/com/netflix/asgard/Caches.groovy @@ -94,22 +94,22 @@ class Caches { Caches(CachedMapBuilder cachedMapBuilder, ConfigService configService = null) { allClusters = cachedMapBuilder.of(EntityType.cluster).buildMultiRegionCachedMap() - allAutoScalingGroups = cachedMapBuilder.of(EntityType.autoScaling, 10).buildMultiRegionCachedMap() - allLaunchConfigurations = cachedMapBuilder.of(EntityType.launchConfiguration, 10).buildMultiRegionCachedMap() - allLoadBalancers = cachedMapBuilder.of(EntityType.loadBalancer, 10).buildMultiRegionCachedMap() + allAutoScalingGroups = cachedMapBuilder.of(EntityType.autoScaling, 15).buildMultiRegionCachedMap() + allLaunchConfigurations = cachedMapBuilder.of(EntityType.launchConfiguration, 180).buildMultiRegionCachedMap() + allLoadBalancers = cachedMapBuilder.of(EntityType.loadBalancer, 15).buildMultiRegionCachedMap() allSourceSecurityGroups = cachedMapBuilder.of(EntityType.sourceSecurityGroup).buildMultiRegionCachedMap() allAvailabilityZones = cachedMapBuilder.of(EntityType.availabilityZone, 3600).buildMultiRegionCachedMap() allSubnets = cachedMapBuilder.of(EntityType.subnet, 3600).buildMultiRegionCachedMap() allVpcs = cachedMapBuilder.of(EntityType.vpc, 3600).buildMultiRegionCachedMap() - allKeyPairs = cachedMapBuilder.of(EntityType.keyPair, 10).buildMultiRegionCachedMap() - allImages = cachedMapBuilder.of(EntityType.image, 10).buildMultiRegionCachedMap() - allInstances = cachedMapBuilder.of(EntityType.instance, 10).buildMultiRegionCachedMap() + allKeyPairs = cachedMapBuilder.of(EntityType.keyPair, 120).buildMultiRegionCachedMap() + allImages = cachedMapBuilder.of(EntityType.image, 120).buildMultiRegionCachedMap() + allInstances = cachedMapBuilder.of(EntityType.instance, 15).buildMultiRegionCachedMap() allSpotInstanceRequests = cachedMapBuilder.of(EntityType.spotInstanceRequest, 120).buildMultiRegionCachedMap() - allApplicationInstances = cachedMapBuilder.of(EntityType.applicationInstance, 10).buildMultiRegionCachedMap() + allApplicationInstances = cachedMapBuilder.of(EntityType.applicationInstance, 60).buildMultiRegionCachedMap() allReservedInstancesGroups = cachedMapBuilder.of(EntityType.reservation, 3600).buildMultiRegionCachedMap() - allSecurityGroups = cachedMapBuilder.of(EntityType.security, 10).buildMultiRegionCachedMap() - allSnapshots = cachedMapBuilder.of(EntityType.snapshot, 10).buildMultiRegionCachedMap() - allVolumes = cachedMapBuilder.of(EntityType.volume, 10).buildMultiRegionCachedMap() + allSecurityGroups = cachedMapBuilder.of(EntityType.security, 120).buildMultiRegionCachedMap() + allSnapshots = cachedMapBuilder.of(EntityType.snapshot, 300).buildMultiRegionCachedMap() + allVolumes = cachedMapBuilder.of(EntityType.volume, 300).buildMultiRegionCachedMap() allDomains = cachedMapBuilder.of(EntityType.domain, 120).buildMultiRegionCachedMap() allTopics = cachedMapBuilder.of(EntityType.topic, 120).buildMultiRegionCachedMap() allQueues = cachedMapBuilder.of(EntityType.queue, 120).buildMultiRegionCachedMap() @@ -119,9 +119,9 @@ class Caches { allDBSnapshots = cachedMapBuilder.of(EntityType.dbSnapshot, 120).buildMultiRegionCachedMap() allFastProperties = cachedMapBuilder.of(EntityType.fastProperty, 180).buildMultiRegionCachedMap(configService?. platformServiceRegions) - allScalingPolicies = cachedMapBuilder.of(EntityType.scalingPolicy, 10).buildMultiRegionCachedMap() + allScalingPolicies = cachedMapBuilder.of(EntityType.scalingPolicy, 120).buildMultiRegionCachedMap() allScheduledActions = cachedMapBuilder.of(EntityType.scheduledAction, 120).buildMultiRegionCachedMap() - allSignificantStackInstanceHealthChecks = cachedMapBuilder.of(EntityType.instanceHealth, 300). + allSignificantStackInstanceHealthChecks = cachedMapBuilder.of(EntityType.instanceHealth, 60). buildMultiRegionCachedMap() allApplications = cachedMapBuilder.of(EntityType.application, 120).buildCachedMap() allCustomMetrics = cachedMapBuilder.of(EntityType.metric, 120).buildCachedMap() diff --git a/grails-app/services/com/netflix/asgard/ConfigService.groovy b/grails-app/services/com/netflix/asgard/ConfigService.groovy index 3a929098..e672975c 100644 --- a/grails-app/services/com/netflix/asgard/ConfigService.groovy +++ b/grails-app/services/com/netflix/asgard/ConfigService.groovy @@ -51,8 +51,8 @@ class ConfigService { * * @return the AWS account number for the current environment */ - String getAwsAccountNumber() { - grailsApplication.config.grails?.awsAccounts[0] + String getAwsAccountNumber(Region region=Region.US_EAST_1) { + grailsApplication.config.grails?."${region.provider()}"?.awsAccounts[0] } /** @@ -60,8 +60,8 @@ class ConfigService { * * @return Map account numbers to account names */ - Map getAwsAccountNames() { - grailsApplication.config.grails?.awsAccountNames ?: [:] + Map getAwsAccountNames(Region region=Region.US_EAST_1) { + grailsApplication.config.grails?."${region.provider()}"?.awsAccountNames ?: [:] } /** @@ -193,8 +193,8 @@ class ConfigService { * * @return list of relevant AWS account numbers, starting with the current account of the current environment */ - List getAwsAccounts() { - grailsApplication.config.grails?.awsAccounts ?: [] + List getAwsAccounts(Region region=Region.US_EAST_1) { + grailsApplication.config.grails?."${region.provider}"?.awsAccounts ?: [] } /** @@ -239,20 +239,20 @@ class ConfigService { grailsApplication.config.server.online } - String getAccessId() { - grailsApplication.config.secret?.accessId ?: null + String getAccessId(Region region=Region.US_EAST_1) { + grailsApplication.config.secret?."${region.provider}"?.accessId ?: null } - String getSecretKey() { - grailsApplication.config.secret?.secretKey ?: null + String getSecretKey(Region region=Region.US_EAST_1) { + grailsApplication.config.secret?."${region.provider}"?.secretKey ?: null } - String getAccessIdFileName() { - grailsApplication.config.secret?.accessIdFileName ?: null + String getAccessIdFileName(Region region=Region.US_EAST_1) { + grailsApplication.config.secret?."${region.provider}"?.accessIdFileName ?: null } - String getSecretKeyFileName() { - grailsApplication.config.secret?.secretKeyFileName ?: null + String getSecretKeyFileName(Region region=Region.US_EAST_1) { + grailsApplication.config.secret?."${region.provider}"?.secretKeyFileName ?: null } String getLoadBalancerUsernameFile() { diff --git a/grails-app/services/com/netflix/asgard/EndpointService.groovy b/grails-app/services/com/netflix/asgard/EndpointService.groovy index 89182557..9a4d3471 100644 --- a/grails-app/services/com/netflix/asgard/EndpointService.groovy +++ b/grails-app/services/com/netflix/asgard/EndpointService.groovy @@ -1,8 +1,53 @@ package com.netflix.asgard -class EndpointService { +import org.springframework.beans.factory.InitializingBean - def serviceMethod() { +class EndpointService implements InitializingBean { + static transactional = false + + def grailsApplication + + private def providers + void afterPropertiesSet() { + providers = [ + 'aws': [ + AmazonAutoScaling: { Region region -> "autoscaling.${region}.amazonaws.com" }, + AmazonCloudWatch: { Region region -> "monitoring.${region}.amazonaws.com" }, + AmazonEC2: { Region region -> "ec2.${region}.amazonaws.com" }, + AmazonElasticLoadBalancing: { Region region -> "elasticloadbalancing.${region}.amazonaws.com" }, + AmazonRDS: { Region region -> "rds.${region}.amazonaws.com" }, + // Unconventional S3 endpoints. http://docs.amazonwebservices.com/general/latest/gr/index.html?rande.html + AmazonS3: { Region region -> region != Region.US_EAST_1 ? "s3-${region}.amazonaws.com" : "s3.amazonaws.com" }, + // Unconventional SDB endpoints. http://docs.amazonwebservices.com/general/latest/gr/index.html?rande.html + AmazonSimpleDB: { Region region -> region != Region.US_EAST_1 ? "sdb.${region}.amazonaws.com" : "sdb.amazonaws.com" }, + AmazonSNS: { Region region -> "sns.${region}.amazonaws.com" }, + AmazonSQS: { Region region -> "sqs.${region}.amazonaws.com" } + ] as Map, + 'eucauser': createEucalyptusEndpoints(),//GRZE:HACK: temporary! + 'eucalyptus': createEucalyptusEndpoints() + ] + } + + String getEndpoint(Region region, Class serviceInterfaceClass) { + Set useAws = grailsApplication.config.grails?."${region.provider}"?.useAwsServices ?: [] + if(useAws.contains(serviceInterfaceClass.simpleName)){ + return null; + } else { + def endpointSupplier = providers[region.provider]?.get(serviceInterfaceClass.simpleName) ?: null + endpointSupplier?.call(region) + } + } + + private Map createEucalyptusEndpoints() { + //GRZE:NOTE: this is a temporary hack related to the region enum fwiw. + def configHostName = grailsApplication.config.grails?.eucalyptus?.hostName + [ + AmazonAutoScaling: { Region region, String hostName -> "http://${hostName}:8773/services/AutoScaling" }.rcurry(configHostName), + AmazonCloudWatch: { Region region, String hostName -> "http://${hostName}:8773/services/CloudWatch" }.rcurry(configHostName), + AmazonEC2: { Region region, String hostName -> "http://${hostName}:8773/services/Eucalyptus/" }.rcurry(configHostName), + AmazonElasticLoadBalancing: { Region region, String hostName -> "http://${hostName}:8773/services/LoadBalancing" }.rcurry(configHostName), + AmazonS3: { Region region, String hostName -> "http://${hostName}:8773/services/Walrus" }.rcurry(configHostName), + ] as Map + } - } } diff --git a/grails-app/services/com/netflix/asgard/InitService.groovy b/grails-app/services/com/netflix/asgard/InitService.groovy index 1077d8af..f13462f6 100644 --- a/grails-app/services/com/netflix/asgard/InitService.groovy +++ b/grails-app/services/com/netflix/asgard/InitService.groovy @@ -7,7 +7,7 @@ * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software + * Unless required by applicable law or agrleed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and @@ -78,7 +78,6 @@ class InitService implements ApplicationContextAware { */ boolean cachesFilled() { Collection fillableCaches = caches.properties*.value.findAll { it instanceof Fillable } - !fillableCaches.findAll { !it.filled; }.each{ println it.name } !fillableCaches.find { !it.filled; } } } diff --git a/grails-app/services/com/netflix/asgard/InstanceTypeService.groovy b/grails-app/services/com/netflix/asgard/InstanceTypeService.groovy index d0de3151..058c5b4a 100644 --- a/grails-app/services/com/netflix/asgard/InstanceTypeService.groovy +++ b/grails-app/services/com/netflix/asgard/InstanceTypeService.groovy @@ -84,7 +84,7 @@ class InstanceTypeService implements CacheInitializer { } Collection getInstanceTypes(UserContext userContext) { - caches.allInstanceTypes.by(userContext.region).list() as List//.sort { it.linuxOnDemandPrice } + caches.allInstanceTypes.by(userContext.region).list().sort { it.linuxOnDemandPrice } } private Document fetchInstanceTypesDocument() { @@ -240,27 +240,6 @@ class InstanceTypeService implements CacheInitializer { hardwareProfiles << hardwareProfile } } - hardwareProfiles << new HardwareProfile(instanceType: 'm1.small', architecture: '64-bit', - cpu: '1 EC2 Compute Units (1 virtual cores with 1 EC2 Compute Units each)', - description: 'M1 Small Instance', - ioPerformance: 'Poor', memory: '0.25 GiB', - storage: '5 GB of instance storage') - hardwareProfiles << new HardwareProfile(instanceType: 'm1.medium', architecture: '64-bit', - cpu: '1 EC2 Compute Units (1 virtual cores with 1 EC2 Compute Units each)', - description: 'M1 Medium Instance', - ioPerformance: 'Poor', memory: '0.5 GiB', - storage: '10 GB of instance storage') - hardwareProfiles << new HardwareProfile(instanceType: 'm1.large', architecture: '64-bit', - cpu: '2 EC2 Compute Units (2 virtual cores with 1 EC2 Compute Units each)', - description: 'M1 Large Instance', - ioPerformance: 'Poor', memory: '0.5 GiB', - storage: '10 GB of instance storage') - hardwareProfiles << new HardwareProfile(instanceType: 'm1.xlarge', architecture: '64-bit', - cpu: '2 EC2 Compute Units (2 virtual cores with 1 EC2 Compute Units each)', - description: 'M1 Xtra-Large Instance', - ioPerformance: 'Poor', memory: '1 GiB', - storage: '10 GB of instance storage') - } else { // throw new Exception("Unexpected format of HTML on ${instanceTypesUrl}") } diff --git a/grails-app/services/com/netflix/asgard/SecretService.groovy b/grails-app/services/com/netflix/asgard/SecretService.groovy index 7d14a753..0b8242c4 100644 --- a/grails-app/services/com/netflix/asgard/SecretService.groovy +++ b/grails-app/services/com/netflix/asgard/SecretService.groovy @@ -24,7 +24,7 @@ class SecretService implements InitializingBean { def configService def sshService - BasicAWSCredentials awsCredentials + Map awsCredentials = [:] String loadBalancerUserName String loadBalancerPassword @@ -37,9 +37,11 @@ class SecretService implements InitializingBean { void afterPropertiesSet() { if (configService.online) { - String awsAccessId = configService.accessId ?: fetch(configService.accessIdFileName) - String awsSecretKey = configService.secretKey ?: fetch(configService.secretKeyFileName) - awsCredentials = new BasicAWSCredentials(awsAccessId, awsSecretKey) + Region.values().each { Region region -> + String awsAccessId = configService.getAccessId(region) ?: fetch(configService.getAccessIdFileName(region)) + String awsSecretKey = configService.getSecretKey(region) ?: fetch(configService.getSecretKeyFileName(region)) + awsCredentials[region] = new BasicAWSCredentials(awsAccessId, awsSecretKey) + } if (configService.loadBalancerUsernameFile && configService.loadBalancerPasswordFile) { loadBalancerUserName = fetchRemote(configService.loadBalancerUsernameFile) loadBalancerPassword = fetchRemote(configService.loadBalancerPasswordFile) diff --git a/src/groovy/com/netflix/asgard/Region.groovy b/src/groovy/com/netflix/asgard/Region.groovy index 2212cb0f..b2872ae1 100644 --- a/src/groovy/com/netflix/asgard/Region.groovy +++ b/src/groovy/com/netflix/asgard/Region.groovy @@ -20,70 +20,85 @@ package com.netflix.asgard */ enum Region { - EUCALYPTUS('euca-qa', + EUCALYPTUS('euca-admin', 'eucalyptus', 'eucalyptus.png', - 'Santa Barbara' + 'Santa Barbara', + 'Eucalyptus' ), - + + EUCALYPTUS_USER('euca-user', + 'eucauser', + 'eucalyptus.png', + 'Santa Barbara', + 'Eucauser' + ), + US_EAST_1('us-east-1', 'us-east', 'us-east-1.png', 'Virginia' + ), + + US_WEST_1('us-west-1', + 'us-west', + 'us-west-1.png', + 'California' + ), + + US_WEST_2('us-west-2', + 'us-west-2', + 'us-west-2.png', + 'Oregon' + ), + + EU_WEST_1('eu-west-1', + 'eu-ireland', + 'eu-west-1.png', + 'Ireland' + ), + + AP_NORTHEAST_1('ap-northeast-1', + 'apac-tokyo', + 'ap-northeast-1.png', + 'Tokyo' + ), + + AP_SOUTHEAST_1('ap-southeast-1', + 'apac-sin', + 'ap-southeast-1.png', + 'Singapore' + ), + + AP_SOUTHEAST_2('ap-southeast-2', + 'apac-syd', + 'ap-southeast-2.png', + 'Sydney' + ), + + SA_EAST_1('sa-east-1', + 'sa-east-1', + 'sa-east-1.png', + 'Sao Paulo' ) -// -// US_WEST_1('us-west-1', -// 'us-west', -// 'us-west-1.png', -// 'California' -// ), -// -// US_WEST_2('us-west-2', -// 'us-west-2', -// 'us-west-2.png', -// 'Oregon' -// ), -// -// EU_WEST_1('eu-west-1', -// 'eu-ireland', -// 'eu-west-1.png', -// 'Ireland' -// ), -// -// AP_NORTHEAST_1('ap-northeast-1', -// 'apac-tokyo', -// 'ap-northeast-1.png', -// 'Tokyo' -// ), -// -// AP_SOUTHEAST_1('ap-southeast-1', -// 'apac-sin', -// 'ap-southeast-1.png', -// 'Singapore' -// ), -// -// AP_SOUTHEAST_2('ap-southeast-2', -// 'apac-syd', -// 'ap-southeast-2.png', -// 'Sydney' -// ), -// -// SA_EAST_1('sa-east-1', -// 'sa-east-1', -// 'sa-east-1.png', -// 'Sao Paulo' -// ) String code String pricingJsonCode String mapImageFileName String location - + String provider + + Region(String code, String pricingJsonCode, String mapImageFileName, String location, String provider) { + this(code, pricingJsonCode, mapImageFileName, location) + this.provider = provider + } + Region(String code, String pricingJsonCode, mapImageFileName, location) { this.code = code this.pricingJsonCode = pricingJsonCode this.mapImageFileName = mapImageFileName this.location = location + this.provider = 'AWS' } /** @@ -122,9 +137,12 @@ enum Region { } [] } - static Region defaultRegion() { Region.EUCALYPTUS } + + static Region defaultRegion() { Region.US_EAST_1 } String getDescription() { "$code ($location)" } String toString() { code } + + String getProvider() { provider.toLowerCase() } } diff --git a/web-app/images/worldmap/eucalyptus.png b/web-app/images/worldmap/eucalyptus.png index 674ec78b5929627b5900559dd8eaa8df6de96ae7..6d97fb0f6adc491c889e5939141fb949342a7f8e 100644 GIT binary patch delta 1205 zcmV;m1WNmvHopljiBL{Q4GJ0x0000DNk~Le0000$0000y2m$~A09orRGXMYp0drDE zLIAGL9O;vK3LJkAVE_ORVF9Q=r)dBH00(qQO+^RY0}cQoAHh8v5+yJ2U$N|W)15j%00Fs~wtxFd4@#Q7Qb6uYx{Il_&wG672PyhqWr=NP_+Y4_9 zqWP{L%Zm$7zx&zke>Xu?$3TDw9DjQ5%p*sZsAiTyhtvyDItl<0CHnBJq9mk-h+$w4 z#z9%}&P9Lg9P@CC7c3N11AveiC4ht%(ic~*fA{;}!y(X8+)E9#1}MVBL{$kA(f2p* zod5bt-Mi`62a%PSyf5I-`wyV?JOIR2Vjlwlgj5arFtO^M(EQr)CxNrc0&73!e zg@8=T48)ae%YaNEcrFqW0$P=CskoxHGpFlWLiHYy6$z=hP$GiVpne%3^0pEXJ03uf z650)h{yh+GVkKe$NR8k*!g`?w56FrKWSoQqLFrZu#CU+9lCp$!Gz0wuXoyi&VZe%L z6RUr|CDc&JWYxr705J3JhG`H6>LetjCxw`QSubpxEsg}9J(lc~rS3b0nmkZWA<}s6 zoBJ(WO5#@^>zYDAb)Y_lDhx1y#dhmo+F$#2Qm92Um(PL#cxSW@c^17NV0QanxN|5n zxNrtGR)ZciM}UghW>c)MmYX?-mTi^~Buak(dkt)!VSN=G4q$6748Tdx#XQ5-S{Xo^ z=O4bO#O9c6wgHfa9dI}w09zoPR2Y~= zIl@?^lQsadX_$$9wz3AZY1zbS76rf=WYYlv_!%(Bw#%J%md0(#EM`;Ko&gYC4Fi8^ zT9Hs30B4bA zefY$&qr>^NrZo~b@2nQa*8kxtI1aY9)2;3Fa8yK1F^W+S1?G_hpm8%GF!J#~E}pbE ThL`Zy00000NkvXXu0mjf;wl_h literal 6937 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 Date: Wed, 18 Dec 2013 09:45:27 -0800 Subject: [PATCH 14/14] Fix handling of null userData --- .../services/com/netflix/asgard/AwsAutoScalingService.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy b/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy index 43c21bde..d72b4372 100644 --- a/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy +++ b/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy @@ -936,7 +936,7 @@ class AwsAutoScalingService implements CacheInitializer, InitializingBean { private void ensureUserDataIsDecodedAndTruncated(LaunchConfiguration launchConfiguration) { ensureUserDataIsDecoded(launchConfiguration) - String userData = launchConfiguration.userData + String userData = userData!=null?launchConfiguration.userData:"" int maxLength = configService.cachedUserDataMaxLength if (userData.length() > maxLength) { launchConfiguration.userData = userData.substring(0, maxLength)