diff --git a/README.md b/README.md index 9b2bae5967..a3b76bbb7e 100644 --- a/README.md +++ b/README.md @@ -302,12 +302,12 @@ spec: You can also achieve persistence by creating a PV in a mounted host folder. ## Mounting Host Folders -`minikube mount /path/to/dir/to/mount` is the recommended way to mount directories into minikube so that they can be used in your local kubernetes cluster. The command works on all supported platforms. Below is an example workflow for using `minikube mount`: +`minikube mount /path/to/dir/to/mount:/vm-mount-path` is the recommended way to mount directories into minikube so that they can be used in your local kubernetes cluster. The command works on all supported platforms. Below is an example workflow for using `minikube mount`: ``` # terminal 1 $ mkdir ~/mount-dir -$ minikube mount ~/mount-dir +$ minikube mount ~/mount-dir:/mount-9p Mounting /home/user/mount-dir/ into /mount-9p on the minikubeVM This daemon process needs to stay alive for the mount to still be accessible... ufs starting diff --git a/cmd/minikube/cmd/mount.go b/cmd/minikube/cmd/mount.go index 9de089b971..739ab02d3e 100644 --- a/cmd/minikube/cmd/mount.go +++ b/cmd/minikube/cmd/mount.go @@ -21,6 +21,8 @@ import ( "os" "sync" + "strings" + "github.com/golang/glog" "github.com/spf13/cobra" "k8s.io/minikube/pkg/minikube/cluster" @@ -36,26 +38,41 @@ var mountCmd = &cobra.Command{ Long: `Mounts the specified directory into minikube.`, Run: func(cmd *cobra.Command, args []string) { if len(args) != 1 { - errText := `Please specify a driver name and a directory to be mounted: -\tminikube mount MOUNT_DIRECTORY(ex:"/home") + errText := `Please specify the directory to be mounted: +\tminikube mount HOST_MOUNT_DIRECTORY:VM_MOUNT_DIRECTORY(ex:"/host-home:/vm-home") ` fmt.Fprintln(os.Stderr, errText) os.Exit(1) } - if _, err := os.Stat(args[0]); err != nil { + mountString := args[0] + idx := strings.LastIndex(mountString, ":") + if idx == -1 { // no ":" was present + errText := `Mount directory must be in the form: + \tHOST_MOUNT_DIRECTORY:VM_MOUNT_DIRECTORY` + fmt.Fprintln(os.Stderr, errText) + os.Exit(1) + } + hostPath := mountString[:idx] + vmPath := mountString[idx+1:] + if _, err := os.Stat(hostPath); err != nil { if os.IsNotExist(err) { - errText := fmt.Sprintf("Cannot find directory %s for mount", args[0]) + errText := fmt.Sprintf("Cannot find directory %s for mount", hostPath) fmt.Fprintln(os.Stderr, errText) } else { - errText := fmt.Sprintf("Error accesssing directory %s for mount", args[0]) + errText := fmt.Sprintf("Error accesssing directory %s for mount", hostPath) fmt.Fprintln(os.Stderr, errText) } + os.Exit(1) + } + if len(vmPath) == 0 || !strings.HasPrefix(vmPath, "/") { + errText := fmt.Sprintf("The :VM_MOUNT_DIRECTORY must be an absolute path") + fmt.Fprintln(os.Stderr, errText) + os.Exit(1) } var debugVal int if glog.V(1) { debugVal = 1 // ufs.StartServer takes int debug param } - mountDir := args[0] api, err := machine.NewAPIClient(clientType) if err != nil { fmt.Fprintf(os.Stderr, "Error getting client: %s\n", err) @@ -63,15 +80,15 @@ var mountCmd = &cobra.Command{ } defer api.Close() - fmt.Printf("Mounting %s into /mount-9p on the minikubeVM\n", mountDir) + fmt.Printf("Mounting %s into %s on the minikubeVM\n", hostPath, vmPath) fmt.Println("This daemon process needs to stay alive for the mount to still be accessible...") var wg sync.WaitGroup wg.Add(1) go func() { - ufs.StartServer(constants.DefaultUfsAddress, debugVal, mountDir) + ufs.StartServer(constants.DefaultUfsAddress, debugVal, hostPath) wg.Done() }() - err = cluster.Mount9pHost(api) + err = cluster.MountHost(api, vmPath) if err != nil { fmt.Println(err.Error()) os.Exit(1) diff --git a/pkg/minikube/cluster/cluster.go b/pkg/minikube/cluster/cluster.go index 988013276d..fcd4451375 100644 --- a/pkg/minikube/cluster/cluster.go +++ b/pkg/minikube/cluster/cluster.go @@ -398,8 +398,8 @@ func GetHostLogs(api libmachine.API, follow bool) (string, error) { return s, nil } -// Mount9pHost runs the mount command from the 9p client on the VM to the 9p server on the host -func Mount9pHost(api libmachine.API) error { +// MountHost runs the mount command from the 9p client on the VM to the 9p server on the host +func MountHost(api libmachine.API, path string) error { host, err := CheckIfApiExistsAndLoad(api) if err != nil { return errors.Wrap(err, "Error checking that api exists and loading it") @@ -408,8 +408,12 @@ func Mount9pHost(api libmachine.API) error { if err != nil { return errors.Wrap(err, "Error getting the host IP address to use from within the VM") } - host.RunSSHCommand(GetMount9pCleanupCommand()) - _, err = host.RunSSHCommand(GetMount9pCommand(ip)) + host.RunSSHCommand(GetMountCleanupCommand(path)) + mountCmd, err := GetMountCommand(ip, path) + if err != nil { + return errors.Wrap(err, "Error getting mount command") + } + _, err = host.RunSSHCommand(mountCmd) if err != nil { return err } diff --git a/pkg/minikube/cluster/commands.go b/pkg/minikube/cluster/commands.go index e2fe2ff773..69769b7348 100644 --- a/pkg/minikube/cluster/commands.go +++ b/pkg/minikube/cluster/commands.go @@ -175,16 +175,30 @@ func GetLogsCommand(follow bool) (string, error) { var localkubeStatusCommand = `sudo systemctl is-active localkube 2>&1 1>/dev/null && echo "Running" || echo "Stopped"` -func GetMount9pCleanupCommand() string { - return ` -sudo umount /mount-9p; -sudo rm -rf /mount-9p; -` +func GetMountCleanupCommand(path string) string { + return fmt.Sprintf(` +sudo umount %s; +sudo rm -rf %s; +`, path, path) } -func GetMount9pCommand(ip net.IP) string { - return fmt.Sprintf(` -sudo mkdir /mount-9p; -sudo mount -t 9p -o trans=tcp -o port=5640 -o uid=1001 -o gid=1001 %s /mount-9p; -sudo chmod 775 /mount-9p;`, ip) +var mountTemplate = ` +sudo mkdir -p {{.Path}}; +sudo mount -t 9p -o trans=tcp -o port=5640 -o uid=1001 -o gid=1001 {{.IP}} {{.Path}}; +sudo chmod 775 {{.Path}};` + +func GetMountCommand(ip net.IP, path string) (string, error) { + t := template.Must(template.New("mountCommand").Parse(mountTemplate)) + buf := bytes.Buffer{} + data := struct { + IP string + Path string + }{ + IP: ip.String(), + Path: path, + } + if err := t.Execute(&buf, data); err != nil { + return "", err + } + return buf.String(), nil } diff --git a/test/integration/mount_test.go b/test/integration/mount_test.go index e72bee3847..0ea2266f91 100644 --- a/test/integration/mount_test.go +++ b/test/integration/mount_test.go @@ -44,7 +44,7 @@ func testMounting(t *testing.T) { } defer os.RemoveAll(tempDir) - mountCmd := fmt.Sprintf("mount %s", tempDir) + mountCmd := fmt.Sprintf("mount %s:/mount-9p", tempDir) cmd := minikubeRunner.RunDaemon(mountCmd) defer cmd.Process.Kill()