예제 #1
0
func Init(params volume.DriverParams) (volume.VolumeDriver, error) {
	inst := &driver{
		IoNotSupported:    &volume.IoNotSupported{},
		DefaultEnumerator: volume.NewDefaultEnumerator(Name, kvdb.Instance()),
	}
	inst.buseDevices = make(map[string]*buseDev)
	if err := os.MkdirAll(BuseMountPath, 0744); err != nil {
		return nil, err
	}
	volumeInfo, err := inst.DefaultEnumerator.Enumerate(
		&api.VolumeLocator{},
		nil,
	)
	if err == nil {
		for _, info := range volumeInfo {
			if info.Status == api.VolumeStatus_VOLUME_STATUS_NONE {
				info.Status = api.VolumeStatus_VOLUME_STATUS_UP
				inst.UpdateVol(info)
			}
		}
	} else {
		dlog.Println("Could not enumerate Volumes, ", err)
	}

	c, err := cluster.Inst()
	if err != nil {
		dlog.Println("BUSE initializing in single node mode")
	} else {
		dlog.Println("BUSE initializing in clustered mode")
		c.AddEventListener(inst)
	}

	dlog.Println("BUSE initialized and driver mounted at: ", BuseMountPath)
	return inst, nil
}
예제 #2
0
func (d *driver) Delete(volumeID string) error {
	v, err := d.GetVol(volumeID)
	if err != nil {
		dlog.Println(err)
		return err
	}

	bd, ok := d.buseDevices[v.DevicePath]
	if !ok {
		err = fmt.Errorf("Cannot locate a BUSE device for %s", v.DevicePath)
		dlog.Println(err)
		return err
	}

	// Clean up buse block file and close the NBD connection.
	os.Remove(bd.file)
	bd.f.Close()
	bd.nbd.Disconnect()

	dlog.Infof("BUSE deleted volume %v at NBD device %s", volumeID, v.DevicePath)

	if err := d.DeleteVol(volumeID); err != nil {
		dlog.Println(err)
		return err
	}

	return nil
}
예제 #3
0
func (d *driver) Create(
	locator *api.VolumeLocator,
	source *api.Source,
	spec *api.VolumeSpec) (string, error) {

	volumeID := uuid.New()
	volumeID = strings.TrimSuffix(volumeID, "\n")

	// Create a directory on the NFS server with this UUID.
	volPath := path.Join(nfsMountPath, volumeID)
	err := os.MkdirAll(volPath, 0744)
	if err != nil {
		dlog.Println(err)
		return "", err
	}
	if source != nil {
		if len(source.Seed) != 0 {
			seed, err := seed.New(source.Seed, spec.VolumeLabels)
			if err != nil {
				dlog.Warnf("Failed to initailize seed from %q : %v",
					source.Seed, err)
				return "", err
			}
			err = seed.Load(path.Join(volPath, config.DataDir))
			if err != nil {
				dlog.Warnf("Failed to  seed from %q to %q: %v",
					source.Seed, nfsMountPath, err)
				return "", err
			}
		}
	}

	f, err := os.Create(path.Join(nfsMountPath, volumeID+nfsBlockFile))
	if err != nil {
		dlog.Println(err)
		return "", err
	}
	defer f.Close()

	if err := f.Truncate(int64(spec.Size)); err != nil {
		dlog.Println(err)
		return "", err
	}

	v := common.NewVolume(
		volumeID,
		api.FSType_FS_TYPE_NFS,
		locator,
		source,
		spec,
	)
	v.DevicePath = path.Join(nfsMountPath, volumeID+nfsBlockFile)

	if err := d.CreateVol(v); err != nil {
		return "", err
	}
	return v.Id, err
}
예제 #4
0
func (d *driver) Delete(volumeID string) error {
	v, err := d.GetVol(volumeID)
	if err != nil {
		dlog.Println(err)
		return err
	}

	// Delete the simulated block volume
	os.Remove(v.DevicePath)

	// Delete the directory on the nfs server.
	os.RemoveAll(path.Join(nfsMountPath, volumeID))

	err = d.DeleteVol(volumeID)
	if err != nil {
		dlog.Println(err)
		return err
	}

	return nil
}
예제 #5
0
func (d *driver) Delete(volumeID string) error {

	// Check if volume exists
	_, err := d.GetVol(volumeID)
	if err != nil {
		dlog.Println("Volume not found ", err)
		return err
	}

	// Delete the directory
	os.RemoveAll(filepath.Join(config.VolumeBase, string(volumeID)))

	err = d.DeleteVol(volumeID)
	if err != nil {
		dlog.Println(err)
		return err
	}

	return nil

}
예제 #6
0
// Mount volume at specified path
// Errors ErrEnoEnt, ErrVolDetached may be returned.
func (d *driver) Mount(volumeID string, mountpath string) error {
	v, err := d.GetVol(volumeID)
	if err != nil {
		dlog.Println(err)
		return err
	}
	syscall.Unmount(mountpath, 0)
	if err := syscall.Mount(filepath.Join(config.VolumeBase, string(volumeID)), mountpath, string(v.Spec.Format), syscall.MS_BIND, ""); err != nil {
		dlog.Printf("Cannot mount %s at %s because %+v", filepath.Join(config.VolumeBase, string(volumeID)), mountpath, err)
		return err
	}
	v.AttachPath = mountpath
	// TODO(pedge): why ignoring error?
	err = d.UpdateVol(v)
	return nil
}
예제 #7
0
func (d *driver) Mount(volumeID string, mountpath string) error {
	v, err := d.GetVol(volumeID)
	if err != nil {
		dlog.Println(err)
		return err
	}

	srcPath := path.Join(":", d.nfsPath, volumeID)
	mountExists, err := d.mounter.Exists(srcPath, mountpath)
	if !mountExists {
		d.mounter.Unmount(path.Join(nfsMountPath, volumeID), mountpath)
		if err := d.mounter.Mount(0, path.Join(nfsMountPath, volumeID), mountpath, string(v.Spec.Format), syscall.MS_BIND, ""); err != nil {
			dlog.Printf("Cannot mount %s at %s because %+v", path.Join(nfsMountPath, volumeID), mountpath, err)
			return err
		}
	}
	v.AttachPath = mountpath
	return d.UpdateVol(v)
}
예제 #8
0
func (d *driver) Create(locator *api.VolumeLocator, source *api.Source, spec *api.VolumeSpec) (string, error) {
	volumeID := uuid.New()
	volumeID = strings.TrimSuffix(volumeID, "\n")
	// Create a directory on the Local machine with this UUID.
	if err := os.MkdirAll(filepath.Join(config.VolumeBase, string(volumeID)), 0744); err != nil {
		dlog.Println(err)
		return "", err
	}

	v := common.NewVolume(
		volumeID,
		api.FSType_FS_TYPE_VFS,
		locator,
		source,
		spec,
	)
	v.DevicePath = filepath.Join(config.VolumeBase, volumeID)

	if err := d.CreateVol(v); err != nil {
		return "", err
	}
	return v.Id, d.UpdateVol(v)
}
예제 #9
0
func (d *driver) Create(locator *api.VolumeLocator, source *api.Source, spec *api.VolumeSpec) (string, error) {
	volumeID := uuid.New()
	volumeID = strings.TrimSuffix(volumeID, "\n")
	if spec.Size == 0 {
		return "", fmt.Errorf("Volume size cannot be zero", "buse")
	}
	if spec.Format == api.FSType_FS_TYPE_NONE {
		return "", fmt.Errorf("Missing volume format", "buse")
	}
	// Create a file on the local buse path with this UUID.
	buseFile := path.Join(BuseMountPath, volumeID)
	f, err := os.Create(buseFile)
	if err != nil {
		dlog.Println(err)
		return "", err
	}

	if err := f.Truncate(int64(spec.Size)); err != nil {
		dlog.Println(err)
		return "", err
	}

	bd := &buseDev{
		file: buseFile,
		f:    f,
	}
	nbd := Create(bd, int64(spec.Size))
	bd.nbd = nbd

	dlog.Infof("Connecting to NBD...")
	dev, err := bd.nbd.Connect()
	if err != nil {
		dlog.Println(err)
		return "", err
	}

	dlog.Infof("Formatting %s with %v", dev, spec.Format)
	cmd := "/sbin/mkfs." + spec.Format.SimpleString()
	o, err := exec.Command(cmd, dev).Output()
	if err != nil {
		dlog.Warnf("Failed to run command %v %v: %v", cmd, dev, o)
		return "", err
	}

	dlog.Infof("BUSE mapped NBD device %s (size=%v) to block file %s", dev, spec.Size, buseFile)

	v := common.NewVolume(
		volumeID,
		spec.Format,
		locator,
		source,
		spec,
	)
	v.DevicePath = dev

	d.buseDevices[dev] = bd

	err = d.CreateVol(v)
	if err != nil {
		return "", err
	}
	return v.Id, err
}
예제 #10
0
func Init(params volume.DriverParams) (volume.VolumeDriver, error) {
	path, ok := params["path"]
	if !ok {
		return nil, errors.New("No NFS path provided")
	}
	server, ok := params["server"]
	if !ok {
		dlog.Printf("No NFS server provided, will attempt to bind mount %s", path)
	} else {
		dlog.Printf("NFS driver initializing with %s:%s ", server, path)
	}
	// Create a mount manager for this NFS server. Blank sever is OK.
	mounter, err := mount.New(mount.NFSMount, server)
	if err != nil {
		dlog.Warnf("Failed to create mount manager for server: %v (%v)", server, err)
		return nil, err
	}
	inst := &driver{
		IoNotSupported:    &volume.IoNotSupported{},
		DefaultEnumerator: volume.NewDefaultEnumerator(Name, kvdb.Instance()),
		nfsServer:         server,
		nfsPath:           path,
		mounter:           mounter,
	}
	if err := os.MkdirAll(nfsMountPath, 0744); err != nil {
		return nil, err
	}
	src := inst.nfsPath
	if server != "" {
		src = ":" + inst.nfsPath
	}
	// If src is already mounted at dest, leave it be.
	mountExists, err := mounter.Exists(src, nfsMountPath)
	if !mountExists {
		// Mount the nfs server locally on a unique path.
		syscall.Unmount(nfsMountPath, 0)
		if server != "" {
			err = syscall.Mount(src, nfsMountPath, "nfs", 0, "nolock,addr="+inst.nfsServer)
		} else {
			err = syscall.Mount(src, nfsMountPath, "", syscall.MS_BIND, "")
		}
		if err != nil {
			dlog.Printf("Unable to mount %s:%s at %s (%+v)", inst.nfsServer, inst.nfsPath, nfsMountPath, err)
			return nil, err
		}
	}
	volumeInfo, err := inst.DefaultEnumerator.Enumerate(&api.VolumeLocator{}, nil)
	if err == nil {
		for _, info := range volumeInfo {
			if info.Status == api.VolumeStatus_VOLUME_STATUS_NONE {
				info.Status = api.VolumeStatus_VOLUME_STATUS_UP
				inst.UpdateVol(info)
			}
		}
	} else {
		dlog.Println("Could not enumerate Volumes, ", err)
	}

	dlog.Println("NFS initialized and driver mounted at: ", nfsMountPath)
	return inst, nil
}