@@ -249,6 +249,10 @@ func (v *volumeSource) DestroyVolumes(volNames []string) ([]error, error) {
249249 return v .foreachVolume (volNames , v .destroyOneVolume ), nil
250250}
251251
252+ func (v * volumeSource ) ReleaseVolumes (volNames []string ) ([]error , error ) {
253+ return v .foreachVolume (volNames , v .releaseOneVolume ), nil
254+ }
255+
252256func (v * volumeSource ) foreachVolume (volNames []string , f func (string ) error ) []error {
253257 var wg sync.WaitGroup
254258 wg .Add (len (volNames ))
@@ -263,10 +267,6 @@ func (v *volumeSource) foreachVolume(volNames []string, f func(string) error) []
263267 return results
264268}
265269
266- func (v * volumeSource ) ReleaseVolumes (volNames []string ) ([]error , error ) {
267- return nil , errors .NotImplementedf ("ReleaseVolumes" )
268- }
269-
270270func parseVolumeId (volName string ) (string , string , error ) {
271271 idRest := strings .SplitN (volName , "--" , 2 )
272272 if len (idRest ) != 2 {
@@ -293,6 +293,37 @@ func (v *volumeSource) destroyOneVolume(volName string) error {
293293 return nil
294294}
295295
296+ func (v * volumeSource ) releaseOneVolume (volName string ) error {
297+ zone , _ , err := parseVolumeId (volName )
298+ if err != nil {
299+ return errors .Annotatef (err , "invalid volume id %q" , volName )
300+ }
301+ disk , err := v .gce .Disk (zone , volName )
302+ if err != nil {
303+ return errors .Trace (err )
304+ }
305+ switch disk .Status {
306+ case google .StatusReady , google .StatusFailed :
307+ default :
308+ return errors .Errorf (
309+ "cannot release volume %q with status %q" ,
310+ volName , disk .Status ,
311+ )
312+ }
313+ if len (disk .AttachedInstances ) > 0 {
314+ return errors .Errorf (
315+ "cannot release volume %q, attached to instances %q" ,
316+ volName , disk .AttachedInstances ,
317+ )
318+ }
319+ delete (disk .Labels , tags .JujuController )
320+ delete (disk .Labels , tags .JujuModel )
321+ if err := v .gce .SetDiskLabels (zone , volName , disk .LabelFingerprint , disk .Labels ); err != nil {
322+ return errors .Annotatef (err , "cannot remove labels from volume %q" , volName )
323+ }
324+ return nil
325+ }
326+
296327func (v * volumeSource ) ListVolumes () ([]string , error ) {
297328 var volumes []string
298329 disks , err := v .gce .Disks ()
@@ -311,6 +342,38 @@ func (v *volumeSource) ListVolumes() ([]string, error) {
311342 return volumes , nil
312343}
313344
345+ // ImportVolume is specified on the storage.VolumeImporter interface.
346+ func (v * volumeSource ) ImportVolume (volName string , tags map [string ]string ) (storage.VolumeInfo , error ) {
347+ zone , _ , err := parseVolumeId (volName )
348+ if err != nil {
349+ return storage.VolumeInfo {}, errors .Annotatef (err , "cannot get volume %q" , volName )
350+ }
351+ disk , err := v .gce .Disk (zone , volName )
352+ if err != nil {
353+ return storage.VolumeInfo {}, errors .Annotatef (err , "cannot get volume %q" , volName )
354+ }
355+ if disk .Status != google .StatusReady {
356+ return storage.VolumeInfo {}, errors .Errorf (
357+ "cannot import volume %q with status %q" ,
358+ volName , disk .Status ,
359+ )
360+ }
361+ if disk .Labels == nil {
362+ disk .Labels = make (map [string ]string )
363+ }
364+ for k , v := range resourceTagsToDiskLabels (tags ) {
365+ disk .Labels [k ] = v
366+ }
367+ if err := v .gce .SetDiskLabels (zone , volName , disk .LabelFingerprint , disk .Labels ); err != nil {
368+ return storage.VolumeInfo {}, errors .Annotatef (err , "cannot update labels on volume %q" , volName )
369+ }
370+ return storage.VolumeInfo {
371+ VolumeId : disk .Name ,
372+ Size : disk .Size ,
373+ Persistent : true ,
374+ }, nil
375+ }
376+
314377func (v * volumeSource ) DescribeVolumes (volNames []string ) ([]storage.DescribeVolumesResult , error ) {
315378 results := make ([]storage.DescribeVolumesResult , len (volNames ))
316379 for i , vol := range volNames {
0 commit comments