From 032450eaf50691bd981a5abb3d7fc73a75c62881 Mon Sep 17 00:00:00 2001 From: Tom Clegg Date: Wed, 18 Jan 2023 09:58:49 -0500 Subject: [PATCH] 19320: Fix AWS InstanceStatus and SpotPrice API usage. Arvados-DCO-1.1-Signed-off-by: Tom Clegg --- lib/cloud/ec2/ec2.go | 15 +++++++++++---- lib/cloud/ec2/ec2_test.go | 14 +++++++++++++- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/lib/cloud/ec2/ec2.go b/lib/cloud/ec2/ec2.go index f80e9bd1a5..2a5eea4845 100644 --- a/lib/cloud/ec2/ec2.go +++ b/lib/cloud/ec2/ec2.go @@ -297,12 +297,17 @@ func (instanceSet *ec2InstanceSet) Instances(tags cloud.InstanceTags) (instances } if needAZs { az := map[string]string{} - instanceSet.client.DescribeInstanceStatusPages(&ec2.DescribeInstanceStatusInput{}, func(page *ec2.DescribeInstanceStatusOutput, lastPage bool) bool { + err := instanceSet.client.DescribeInstanceStatusPages(&ec2.DescribeInstanceStatusInput{ + IncludeAllInstances: aws.Bool(true), + }, func(page *ec2.DescribeInstanceStatusOutput, lastPage bool) bool { for _, ent := range page.InstanceStatuses { az[*ent.InstanceId] = *ent.AvailabilityZone } return true }) + if err != nil { + instanceSet.logger.Warnf("error getting instance statuses: %s", err) + } for _, inst := range instances { inst := inst.(*ec2Instance) inst.availabilityZone = az[*inst.instance.InstanceId] @@ -363,7 +368,8 @@ func (instanceSet *ec2InstanceSet) updateSpotPrices(instances []cloud.Instance) dsphi := &ec2.DescribeSpotPriceHistoryInput{ StartTime: aws.Time(updateTime.Add(-3 * instanceSet.ec2config.SpotPriceUpdateInterval.Duration())), Filters: []*ec2.Filter{ - &ec2.Filter{Name: aws.String("InstanceType"), Values: typeFilterValues}, + &ec2.Filter{Name: aws.String("instance-type"), Values: typeFilterValues}, + &ec2.Filter{Name: aws.String("product-description"), Values: []*string{aws.String("Linux/UNIX")}}, }, } err := instanceSet.client.DescribeSpotPriceHistoryPages(dsphi, func(page *ec2.DescribeSpotPriceHistoryOutput, lastPage bool) bool { @@ -503,11 +509,12 @@ func (inst *ec2Instance) VerifyHostKey(ssh.PublicKey, *ssh.Client) error { func (inst *ec2Instance) PriceHistory() []cloud.InstancePrice { inst.provider.pricesLock.Lock() defer inst.provider.pricesLock.Unlock() - return inst.provider.prices[priceKey{ + pk := priceKey{ instanceType: *inst.instance.InstanceType, spot: aws.StringValue(inst.instance.InstanceLifecycle) == "spot", availabilityZone: inst.availabilityZone, - }] + } + return inst.provider.prices[pk] } type rateLimitError struct { diff --git a/lib/cloud/ec2/ec2_test.go b/lib/cloud/ec2/ec2_test.go index 1036422582..e7534a7b69 100644 --- a/lib/cloud/ec2/ec2_test.go +++ b/lib/cloud/ec2/ec2_test.go @@ -287,6 +287,16 @@ func (*EC2InstanceSetSuite) TestInstancePriceHistory(c *check.C) { ap, img, cluster := GetInstanceSet(c) pk, _ := test.LoadTestKey(c, "../../dispatchcloud/test/sshkey_dispatch") tags := cloud.InstanceTags{"arvados-ec2-driver": "test"} + + defer func() { + instances, err := ap.Instances(tags) + c.Assert(err, check.IsNil) + for _, inst := range instances { + c.Logf("cleanup: destroy instance %s", inst) + c.Check(inst.Destroy(), check.IsNil) + } + }() + inst1, err := ap.Create(cluster.InstanceTypes["tiny-preemptible"], img, tags, "true", pk) c.Assert(err, check.IsNil) defer inst1.Destroy() @@ -305,13 +315,15 @@ func (*EC2InstanceSetSuite) TestInstancePriceHistory(c *check.C) { instances, err = ap.Instances(tags) running := 0 for _, inst := range instances { - if inst.Address() != "" { + if *inst.(*ec2Instance).instance.InstanceLifecycle == "spot" { running++ } } if running >= 2 { + c.Logf("instances are running, and identifiable as spot instances") break } + c.Logf("waiting for instances to be identifiable as spot instances...") time.Sleep(10 * time.Second) } -- 2.30.2