Skip to content

Commit

Permalink
Added the ability to setup multiple NFS Shares
Browse files Browse the repository at this point in the history
By default (changeable with `xhyve-experimental-nfs-share-root`, see below) NFS shares are rooted at /xhyve-nfsshares to avoid the situation where a NFS Share `/usr` would be mounted at `/usr`

2 backward incompatible changes:
- renamed `xhyve-experimental-nfs-share` to `xhyve-experimental-nfs-share-enable`
- change `xhyve-experimental-nfs-share` from being a boolean to a string slice taking multiple path to be shared via NFS
- NFS Shares are now mounted under a default directory /xhyve-nfsshares (the old code was mounting everything under `/` causing, for example, `/usr` to be mounted at `/usr`)

Other change:
- add `xhyve-experimental-nfs-share-root` to allow specifying where in the guest the NFS Shares will be rooted at

Here's an example of how to use:

`docker-machine -D create -d xhyve --xhyve-disk-size 40000 --xhyve-memory-size 4000 --xhyve-cpu-count 2 --xhyve-experimental-nfs-share-enable --xhyve-experimental-nfs-share /Users --xhyve-experimental-nfs-share /usr/ --xhyve-experimental-nfs-share-root /nfsharesfromhost test`

This command will share the host folders /Users and /usr in the guest at /nfsharesfromhost/Users and /nfsharesfromhost/usr
  • Loading branch information
huguesalary committed Jul 13, 2017
1 parent e80dcd5 commit e6a8273
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 18 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,9 @@ Usage
| `--xhyve-boot-initrd` | `XHYVE_BOOT_INITRD` | string | `''` |
| `--xhyve-qcow2` | `XHYVE_QCOW2` | bool | `false` |
| `--xhyve-virtio-9p` | `XHYVE_VIRTIO_9P` | bool | `false` |
| `--xhyve-experimental-nfs-share` | `XHYVE_EXPERIMENTAL_NFS_SHARE` | bool | `false` |
| `--xhyve-experimental-nfs-share-enable` | `XHYVE_EXPERIMENTAL_NFS_SHARE_ENABLE` | bool | Enable `NFS` folder share (experimental) | `false` |
| `--xhyve-experimental-nfs-share` | `XHYVE_EXPERIMENTAL_NFS_SHARE` | string | Path to a host folder to be shared inside the guest | |
| `--xhyve-experimental-nfs-share-root` | `XHYVE_EXPERIMENTAL_NFS_SHARE_ROOT` | string | root path at which the NFS shares will be mounted| `/xhyve-nfsshares` |

#### `--xhyve-boot2docker-url`

Expand Down
65 changes: 48 additions & 17 deletions xhyve/xhyve.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"os"
"os/exec"
"os/user"
"path"
"path/filepath"
"regexp"
"runtime"
Expand Down Expand Up @@ -53,6 +54,7 @@ const (
defaultPrivateKeyPath = ""
defaultUUID = ""
defaultNFSShareEnable = false
defaultNFSSharesRoot = "/xhyve-nfsshares"
rootVolumeName = "root-volume"
defaultDiskNumber = -1
defaultVirtio9p = false
Expand All @@ -77,6 +79,8 @@ type Driver struct {
Qcow2 bool
RawDisk bool
NFSShareEnable bool
NFSShares []string
NFSSharesRoot string
DiskNumber int
Virtio9p bool
Virtio9pFolder string
Expand Down Expand Up @@ -116,6 +120,7 @@ func NewDriver(hostName, storePath string) *Driver {
PrivateKeyPath: defaultPrivateKeyPath,
UUID: defaultUUID,
NFSShareEnable: defaultNFSShareEnable,
NFSSharesRoot: defaultNFSSharesRoot,
DiskNumber: defaultDiskNumber,
Virtio9p: defaultVirtio9p,
Qcow2: defaultQcow2,
Expand Down Expand Up @@ -200,6 +205,16 @@ func (d *Driver) GetCreateFlags() []mcnflag.Flag {
Name: "xhyve-experimental-nfs-share-enable",
Usage: "Setup NFS shared folder (requires root)",
},
mcnflag.StringSliceFlag{
EnvVar: "XHYVE_EXPERIMENTAL_NFS_SHARE",
Name: "xhyve-experimental-nfs-share",
Usage: "Setup NFS shared folder (requires root)",
},
mcnflag.StringFlag{
EnvVar: "XHYVE_EXPERIMENTAL_NFS_SHARE_ROOT",
Name: "xhyve-experimental-nfs-share-root",
Usage: "root directory where the NFS shares will be mounted inside the machine",
},
}
}

Expand Down Expand Up @@ -258,6 +273,8 @@ func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error {
d.Virtio9p = flags.Bool("xhyve-virtio-9p")
d.Virtio9pFolder = "/Users"
d.NFSShareEnable = flags.Bool("xhyve-experimental-nfs-share-enable")
d.NFSShares = flags.StringSlice("xhyve-experimental-nfs-share")
d.NFSSharesRoot = flags.String("xhyve-experimental-nfs-share-root")

return nil
}
Expand Down Expand Up @@ -577,8 +594,10 @@ func (d *Driver) Remove() error {

if d.NFSShareEnable {
log.Infof("Remove NFS share folder must be root. Please insert root password.")
if _, err := nfsexports.Remove("", d.nfsExportIdentifier()); err != nil {
log.Errorf("failed removing nfs share: %s", err.Error())
for _, share := range d.NFSShares {
if _, err := nfsexports.Remove("", d.nfsExportIdentifier(share)); err != nil {
log.Errorf("failed removing nfs share (%s): %s", share, err.Error())
}
}

if err := nfsexports.ReloadDaemon(); err != nil {
Expand Down Expand Up @@ -1000,27 +1019,39 @@ func (d *Driver) setupNFSShare() error {
return err
}

nfsConfig := fmt.Sprintf("/Users %s -alldirs -mapall=%s", d.IPAddress, user.Username)

if _, err := nfsexports.Add("", d.nfsExportIdentifier(), nfsConfig); err != nil {
hostIP, err := vmnet.GetNetAddr()
if err != nil {
return err
}

if err := nfsexports.ReloadDaemon(); err != nil {
return err
bootScriptName := "/var/lib/boot2docker/bootlocal.sh"
bootScript := fmt.Sprintf("#/bin/bash\\n")

bootScript += "sudo /usr/local/etc/init.d/nfs-client start\\n"

for _, share := range d.NFSShares {
if !path.IsAbs(share) {
share = d.ResolveStorePath(share)
}
nfsConfig := fmt.Sprintf("%s %s -alldirs -mapall=%s", share, d.IPAddress, user.Username)

if _, err := nfsexports.Add("", d.nfsExportIdentifier(share), nfsConfig); err != nil {
if strings.Contains(err.Error(), "conflicts with existing export") {
log.Info("Conflicting NFS Share not setup and ignored:", err)
continue
}
return err
}

root := path.Clean(d.NFSSharesRoot)
bootScript += fmt.Sprintf("sudo mkdir -p %s/%s\\n", root, share)
bootScript += fmt.Sprintf("sudo mount -t nfs -o noacl,async %s:%s %s/%s\\n", hostIP, share, root, share)
}

hostIP, err := vmnet.GetNetAddr()
if err != nil {
if err := nfsexports.ReloadDaemon(); err != nil {
return err
}

bootScriptName := "/var/lib/boot2docker/bootlocal.sh"
bootScript := fmt.Sprintf("#/bin/bash\\n"+
"sudo mkdir -p /Users\\n"+
"sudo /usr/local/etc/init.d/nfs-client start\\n"+
"sudo mount -t nfs -o noacl,async %s:/Users /Users\\n", hostIP)

writeScriptCmd := fmt.Sprintf("echo -e \"%s\" | sudo tee %s && sudo chmod +x %s && %s",
bootScript, bootScriptName, bootScriptName, bootScriptName)

Expand All @@ -1031,8 +1062,8 @@ func (d *Driver) setupNFSShare() error {
return nil
}

func (d *Driver) nfsExportIdentifier() string {
return fmt.Sprintf("docker-machine-driver-xhyve %s", d.MachineName)
func (d *Driver) nfsExportIdentifier(path string) string {
return fmt.Sprintf("docker-machine-driver-xhyve %s-%s", d.MachineName, path)
}

func (d *Driver) GetPid() (int, error) {
Expand Down

0 comments on commit e6a8273

Please sign in to comment.