Example #1
0
// 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
}
Example #2
0
// 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
}
Example #3
0
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
}
Example #4
0
// 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
}