// Attaches a disk specified by a volume.GCEPersistentDisk to the current kubelet. // Mounts the disk to it's global path. func (util *GCEDiskUtil) AttachAndMountDisk(pd *gcePersistentDisk, globalPDPath string) error { gce, err := cloudprovider.GetCloudProvider("gce", nil) if err != nil { return err } flags := uintptr(0) if pd.readOnly { flags = mount.FlagReadOnly } if err := gce.(*gce_cloud.GCECloud).AttachDisk(pd.pdName, pd.readOnly); err != nil { return err } devicePath := path.Join("/dev/disk/by-id/", "google-"+pd.pdName) if pd.partition != "" { devicePath = devicePath + "-part" + pd.partition } //TODO(jonesdl) There should probably be better method than busy-waiting here. numTries := 0 for { _, err := os.Stat(devicePath) if err == nil { break } if err != nil && !os.IsNotExist(err) { return err } numTries++ if numTries == 10 { return errors.New("Could not attach disk: Timeout after 10s") } time.Sleep(time.Second) } // Only mount the PD globally once. mountpoint, err := mount.IsMountPoint(globalPDPath) if err != nil { if os.IsNotExist(err) { if err := os.MkdirAll(globalPDPath, 0750); err != nil { return err } mountpoint = false } else { return err } } if !mountpoint { err = pd.diskMounter.Mount(devicePath, globalPDPath, pd.fsType, flags, "") if err != nil { os.Remove(globalPDPath) return err } } return nil }
// Unmounts the bind mount, and detaches the disk only if the PD // resource was the last reference to that disk on the kubelet. func (pd *gcePersistentDisk) TearDownAt(dir string) error { mountpoint, err := mount.IsMountPoint(dir) if err != nil { return err } if !mountpoint { return os.Remove(dir) } refs, err := mount.GetMountRefs(pd.mounter, dir) if err != nil { return err } // Unmount the bind-mount inside this pod if err := pd.mounter.Unmount(dir, 0); err != nil { return err } // If len(refs) is 1, then all bind mounts have been removed, and the // remaining reference is the global mount. It is safe to detach. if len(refs) == 1 { // pd.pdName is not initially set for volume-cleaners, so set it here. pd.pdName = path.Base(refs[0]) if err := pd.manager.DetachDisk(pd); err != nil { return err } } mountpoint, mntErr := mount.IsMountPoint(dir) if mntErr != nil { glog.Errorf("isMountpoint check failed: %v", mntErr) return err } if !mountpoint { if err := os.Remove(dir); err != nil { return err } } return nil }
func (m *realMountDetector) GetMountMedium(path string) (storageMedium, bool, error) { isMnt, err := mount.IsMountPoint(path) if err != nil { return 0, false, fmt.Errorf("IsMountPoint(%q): %v", path, err) } buf := syscall.Statfs_t{} if err := syscall.Statfs(path, &buf); err != nil { return 0, false, fmt.Errorf("statfs(%q): %v", path, err) } if buf.Type == linuxTmpfsMagic { return mediumMemory, isMnt, nil } return mediumUnknown, isMnt, nil }
// SetUpAt attaches the disk and bind mounts to the volume path. func (pd *gcePersistentDisk) SetUpAt(dir string) error { if pd.legacyMode { return fmt.Errorf("legacy mode: can not create new instances") } // TODO: handle failed mounts here. mountpoint, err := mount.IsMountPoint(dir) glog.V(4).Infof("PersistentDisk set up: %s %v %v", dir, mountpoint, err) if err != nil && !os.IsNotExist(err) { return err } if mountpoint { return nil } globalPDPath := makeGlobalPDName(pd.plugin.host, pd.pdName) if err := pd.manager.AttachAndMountDisk(pd, globalPDPath); err != nil { return err } flags := uintptr(0) if pd.readOnly { flags = mount.FlagReadOnly } if err := os.MkdirAll(dir, 0750); err != nil { // TODO: we should really eject the attach/detach out into its own control loop. detachDiskLogError(pd) return err } // Perform a bind mount to the full path to allow duplicate mounts of the same PD. err = pd.mounter.Mount(globalPDPath, dir, "", mount.FlagBind|flags, "") if err != nil { mountpoint, mntErr := mount.IsMountPoint(dir) if mntErr != nil { glog.Errorf("isMountpoint check failed: %v", mntErr) return err } if mountpoint { if mntErr = pd.mounter.Unmount(dir, 0); mntErr != nil { glog.Errorf("Failed to unmount: %v", mntErr) return err } mountpoint, mntErr := mount.IsMountPoint(dir) if mntErr != nil { glog.Errorf("isMountpoint check failed: %v", mntErr) return err } if mountpoint { // This is very odd, we don't expect it. We'll try again next sync loop. glog.Errorf("%s is still mounted, despite call to unmount(). Will try again next sync loop.", dir) return err } } os.Remove(dir) // TODO: we should really eject the attach/detach out into its own control loop. detachDiskLogError(pd) return err } return nil }