@@ -17,6 +17,7 @@ limitations under the License.
1717package openstack
1818
1919import (
20+ "errors"
2021 "fmt"
2122 "io/ioutil"
2223 "path"
@@ -25,7 +26,9 @@ import (
2526 "time"
2627
2728 "k8s.io/apimachinery/pkg/api/resource"
29+ "k8s.io/apimachinery/pkg/types"
2830 k8s_volume "k8s.io/kubernetes/pkg/volume"
31+ volumeutil "k8s.io/kubernetes/pkg/volume/util"
2932
3033 "github.com/gophercloud/gophercloud"
3134 volumeexpand "github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/volumeactions"
@@ -318,7 +321,17 @@ func (os *OpenStack) AttachDisk(instanceID, volumeID string) (string, error) {
318321 glog .V (4 ).Infof ("Disk %s is already attached to instance %s" , volumeID , instanceID )
319322 return volume .ID , nil
320323 }
321- return "" , fmt .Errorf ("disk %s is attached to a different instance (%s)" , volumeID , volume .AttachedServerId )
324+ nodeName , err := os .GetNodeNameByID (volume .AttachedServerId )
325+ attachErr := fmt .Sprintf ("disk %s path %s is attached to a different instance (%s)" , volumeID , volume .AttachedDevice , volume .AttachedServerId )
326+ if err != nil {
327+ glog .Error (attachErr )
328+ return "" , errors .New (attachErr )
329+ }
330+ // using volume.AttachedDevice may cause problems because cinder does not report device path correctly see issue #33128
331+ devicePath := volume .AttachedDevice
332+ danglingErr := volumeutil .NewDanglingError (attachErr , nodeName , devicePath )
333+ glog .V (2 ).Infof ("Found dangling volume %s attached to node %s" , volumeID , nodeName )
334+ return "" , danglingErr
322335 }
323336
324337 startTime := time .Now ()
@@ -578,6 +591,9 @@ func (os *OpenStack) GetAttachmentDiskPath(instanceID, volumeID string) (string,
578591
579592// DiskIsAttached queries if a volume is attached to a compute instance
580593func (os * OpenStack ) DiskIsAttached (instanceID , volumeID string ) (bool , error ) {
594+ if instanceID == "" {
595+ glog .Warningf ("calling DiskIsAttached with empty instanceid: %s %s" , instanceID , volumeID )
596+ }
581597 volume , err := os .getVolume (volumeID )
582598 if err != nil {
583599 return false , err
@@ -586,6 +602,29 @@ func (os *OpenStack) DiskIsAttached(instanceID, volumeID string) (bool, error) {
586602 return instanceID == volume .AttachedServerId , nil
587603}
588604
605+ // DiskIsAttachedByName queries if a volume is attached to a compute instance by name
606+ func (os * OpenStack ) DiskIsAttachedByName (nodeName types.NodeName , volumeID string ) (bool , string , error ) {
607+ cClient , err := os .NewComputeV2 ()
608+ if err != nil {
609+ return false , "" , err
610+ }
611+ srv , err := getServerByName (cClient , nodeName , false )
612+ if err != nil {
613+ if err == ErrNotFound {
614+ // instance not found anymore in cloudprovider, assume that cinder is detached
615+ return false , "" , nil
616+ } else {
617+ return false , "" , err
618+ }
619+ }
620+ instanceID := "/" + srv .ID
621+ if ind := strings .LastIndex (instanceID , "/" ); ind >= 0 {
622+ instanceID = instanceID [(ind + 1 ):]
623+ }
624+ attached , err := os .DiskIsAttached (instanceID , volumeID )
625+ return attached , instanceID , err
626+ }
627+
589628// DisksAreAttached queries if a list of volumes are attached to a compute instance
590629func (os * OpenStack ) DisksAreAttached (instanceID string , volumeIDs []string ) (map [string ]bool , error ) {
591630 attached := make (map [string ]bool )
@@ -600,6 +639,32 @@ func (os *OpenStack) DisksAreAttached(instanceID string, volumeIDs []string) (ma
600639 return attached , nil
601640}
602641
642+ // DisksAreAttachedByName queries if a list of volumes are attached to a compute instance by name
643+ func (os * OpenStack ) DisksAreAttachedByName (nodeName types.NodeName , volumeIDs []string ) (map [string ]bool , error ) {
644+ attached := make (map [string ]bool )
645+ cClient , err := os .NewComputeV2 ()
646+ if err != nil {
647+ return attached , err
648+ }
649+ srv , err := getServerByName (cClient , nodeName , false )
650+ if err != nil {
651+ if err == ErrNotFound {
652+ // instance not found anymore, mark all volumes as detached
653+ for _ , volumeID := range volumeIDs {
654+ attached [volumeID ] = false
655+ }
656+ return attached , nil
657+ } else {
658+ return attached , err
659+ }
660+ }
661+ instanceID := "/" + srv .ID
662+ if ind := strings .LastIndex (instanceID , "/" ); ind >= 0 {
663+ instanceID = instanceID [(ind + 1 ):]
664+ }
665+ return os .DisksAreAttached (instanceID , volumeIDs )
666+ }
667+
603668// diskIsUsed returns true a disk is attached to any node.
604669func (os * OpenStack ) diskIsUsed (volumeID string ) (bool , error ) {
605670 volume , err := os .getVolume (volumeID )
0 commit comments