From 6e0bf07c7f326abb4cdf5a02e8edbf9aca7729b9 Mon Sep 17 00:00:00 2001 From: Travis Rhoden Date: Thu, 22 Jun 2017 10:06:48 -0700 Subject: [PATCH] Add dobs support for VolumeInspectByName This patch add the VolumeInspectByName function to the dobs driver, allowing a caller to more efficiently retrieve a single volume when doing a lookup by name instead of by ID. When looking up a volume by name instead of ID, the DO API requires a region, so the way a region was looked up was changed to have commonality between VolumeCreate() and VolumeInspectByName(). VolumeCreate() retains the additional capability to read a region from the AvailabilityZone create option. The order of precedence for region is: 1. az op (create only) 2. IID header field 3. driver config --- drivers/storage/dobs/storage/dobs_storage.go | 60 ++++++++++++++++++-- 1 file changed, 55 insertions(+), 5 deletions(-) diff --git a/drivers/storage/dobs/storage/dobs_storage.go b/drivers/storage/dobs/storage/dobs_storage.go index a0674526..517c0c84 100644 --- a/drivers/storage/dobs/storage/dobs_storage.go +++ b/drivers/storage/dobs/storage/dobs_storage.go @@ -31,6 +31,7 @@ type driver struct { maxAttempts int statusDelay int64 statusTimeout time.Duration + defaultRegion *string } func init() { @@ -71,7 +72,11 @@ func (d *driver) Init( "statusDelay": fmt.Sprintf( "%v", time.Duration(d.statusDelay)*time.Nanosecond), "statusTimeout": d.statusTimeout, - "region": d.config.GetString(do.ConfigRegion), + } + + if region := d.config.GetString(do.ConfigRegion); region != "" { + d.defaultRegion = ®ion + fields["region"] = region } if token == "" { @@ -155,6 +160,39 @@ func (d *driver) VolumeInspect( return volume, nil } +func (d *driver) VolumeInspectByName( + ctx types.Context, + volumeName string, + opts *types.VolumeInspectOpts) (*types.Volume, error) { + + region := d.mustRegion(ctx) + if region == nil || *region == "" { + return nil, goof.New("No region provided or configured") + } + doVolumes, _, err := d.client.Storage.ListVolumes( + ctx, + &godo.ListVolumeParams{ + Region: *region, + Name: volumeName, + }, + ) + if err != nil { + return nil, err + } + if len(doVolumes) == 0 { + return nil, apiUtils.NewNotFoundError(volumeName) + } + if len(doVolumes) > 1 { + return nil, goof.New("too many volumes returned") + } + + volume, err := d.toTypesVolume(ctx, &doVolumes[0], opts.Attachments) + if err != nil { + return nil, goof.New("error converting to types.Volume") + } + return volume, nil +} + func (d *driver) VolumeCreate( ctx types.Context, name string, @@ -165,12 +203,13 @@ func (d *driver) VolumeCreate( } if opts.AvailabilityZone == nil || *opts.AvailabilityZone == "" { - instance, err := d.InstanceInspect(ctx, nil) - if err != nil { - return nil, err + opts.AvailabilityZone = d.mustRegion(ctx) + if opts.AvailabilityZone == nil || *opts.AvailabilityZone == "" { + return nil, goof.WithFields(fields, + "No region for volume create") } - opts.AvailabilityZone = &instance.Region } + fields["region"] = *opts.AvailabilityZone if opts.Size == nil { size := int64(minSizeGiB) @@ -192,6 +231,8 @@ func (d *driver) VolumeCreate( volume, _, err := d.client.Storage.CreateVolume(ctx, volumeReq) if err != nil { + ctx.WithFields(fields).WithError(err).Error( + "error returned from create volume") return nil, err } @@ -473,3 +514,12 @@ func (d *driver) waitForAction( } return nil } + +func (d *driver) mustRegion(ctx types.Context) *string { + if iid, ok := context.InstanceID(ctx); ok { + if v, ok := iid.Fields[do.InstanceIDFieldRegion]; ok && v != "" { + return &v + } + } + return d.defaultRegion +}