/
snapshot_from_volume_driver.go
86 lines (73 loc) · 3.28 KB
/
snapshot_from_volume_driver.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package driver
import (
"fmt"
"io"
"github.com/jevyzhu/light-stemcell-builder/config"
"github.com/jevyzhu/light-stemcell-builder/resources"
"log"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ec2"
)
var _ resources.SnapshotDriver = &SDKSnapshotFromVolumeDriver{}
// SDKSnapshotFromVolumeDriver creates an AMI from a previously created EBS volume
type SDKSnapshotFromVolumeDriver struct {
ec2Client *ec2.EC2
logger *log.Logger
}
// NewSnapshotFromVolumeDriver creates a NewSnapshotFromVolumeDriver for creating snapshots in EC2
func NewSnapshotFromVolumeDriver(logDest io.Writer, creds config.Credentials) *SDKSnapshotFromVolumeDriver {
logger := log.New(logDest, "SDKSnapshotFromVolumeDriver ", log.LstdFlags)
awsConfig := aws.NewConfig().
WithCredentials(awsCreds(creds)).
WithRegion(creds.Region).
WithLogger(newDriverLogger(logger))
ec2Client := ec2.New(session.New(), awsConfig)
return &SDKSnapshotFromVolumeDriver{ec2Client: ec2Client, logger: logger}
}
// Create produces a snapshot in EC2 from a previoulsy created EBS volume
func (d *SDKSnapshotFromVolumeDriver) Create(driverConfig resources.SnapshotDriverConfig) (resources.Snapshot, error) {
createStartTime := time.Now()
defer func(startTime time.Time) {
d.logger.Printf("completed Create() in %f minutes\n", time.Since(startTime).Minutes())
}(createStartTime)
d.logger.Printf("initiating CreateSnapshot task from volume: %s\n", driverConfig.VolumeID)
reqOutput, err := d.ec2Client.CreateSnapshot(&ec2.CreateSnapshotInput{
VolumeId: aws.String(driverConfig.VolumeID),
Description: aws.String(fmt.Sprintf("bosh-light-stemcell-builder-%d", time.Now().UnixNano())),
})
if err != nil {
return resources.Snapshot{}, fmt.Errorf("creating snapshot from EBS volume: %s: %s", driverConfig.VolumeID, err)
}
modifySnapshotAttributeInput := &ec2.ModifySnapshotAttributeInput{
SnapshotId: reqOutput.SnapshotId,
Attribute: aws.String("createVolumePermission"),
OperationType: aws.String("add"),
GroupNames: []*string{aws.String("all")},
}
_, err = d.ec2Client.ModifySnapshotAttribute(modifySnapshotAttributeInput)
if err != nil {
return resources.Snapshot{}, fmt.Errorf("making snapshot with id %s public: %s", *reqOutput.SnapshotId, err)
}
d.logger.Printf("waiting on snapshot %s to be completed\n", *reqOutput.SnapshotId)
waitStartTime := time.Now()
err = d.waitUntilSnapshotCompleted(&ec2.DescribeSnapshotsInput{
SnapshotIds: []*string{reqOutput.SnapshotId},
}, d.ec2Client)
if err != nil {
return resources.Snapshot{}, fmt.Errorf("waiting for snapshot to complete: %s", err)
}
d.logger.Printf("waited for snapshot %s completion for %f minutes\n", *reqOutput.SnapshotId, time.Since(waitStartTime).Minutes())
d.logger.Printf("created snapshot %s\n", *reqOutput.SnapshotId)
return resources.Snapshot{ID: *reqOutput.SnapshotId}, nil
}
func (d *SDKSnapshotFromVolumeDriver) waitUntilSnapshotCompleted(input *ec2.DescribeSnapshotsInput, c *ec2.EC2) error {
ctx := aws.BackgroundContext()
opts := []request.WaiterOption{
request.WithWaiterDelay(request.ConstantWaiterDelay(15 * time.Second)),
request.WithWaiterMaxAttempts(60),
}
return c.WaitUntilSnapshotCompletedWithContext(ctx, input, opts...)
}