Merge pull request #1459 from aaron-prindle/add-mount-daemon

Added mount daemon process that is starts/stops w/ minikube start/stop
pull/1120/merge
Aaron Prindle 2017-05-17 13:34:22 -07:00 committed by GitHub
commit d4b5b62b2e
14 changed files with 135 additions and 15 deletions

View File

@ -21,6 +21,7 @@ import (
"os" "os"
"github.com/spf13/cobra" "github.com/spf13/cobra"
cmdUtil "k8s.io/minikube/cmd/util"
"k8s.io/minikube/pkg/minikube/cluster" "k8s.io/minikube/pkg/minikube/cluster"
"k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/pkg/minikube/machine"
) )
@ -45,6 +46,10 @@ associated files.`,
os.Exit(1) os.Exit(1)
} }
fmt.Println("Machine deleted.") fmt.Println("Machine deleted.")
if err := cmdUtil.KillMountProcess(); err != nil {
fmt.Println("Errors occurred deleting mount process: ", err)
}
}, },
} }

View File

@ -26,14 +26,15 @@ import (
"github.com/golang/glog" "github.com/golang/glog"
"github.com/spf13/cobra" "github.com/spf13/cobra"
cmdUtil "k8s.io/minikube/cmd/util"
"k8s.io/minikube/pkg/minikube/cluster" "k8s.io/minikube/pkg/minikube/cluster"
"k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/pkg/minikube/machine"
"k8s.io/minikube/third_party/go9p/ufs" "k8s.io/minikube/third_party/go9p/ufs"
) )
var mountIP string var mountIP string
var isKill bool
// mountCmd represents the mount command // mountCmd represents the mount command
var mountCmd = &cobra.Command{ var mountCmd = &cobra.Command{
@ -41,6 +42,14 @@ var mountCmd = &cobra.Command{
Short: "Mounts the specified directory into minikube", Short: "Mounts the specified directory into minikube",
Long: `Mounts the specified directory into minikube.`, Long: `Mounts the specified directory into minikube.`,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
if isKill {
if err := cmdUtil.KillMountProcess(); err != nil {
fmt.Println("Errors occurred deleting mount process: ", err)
os.Exit(1)
}
os.Exit(0)
}
if len(args) != 1 { if len(args) != 1 {
errText := `Please specify the directory to be mounted: errText := `Please specify the directory to be mounted:
\tminikube mount HOST_MOUNT_DIRECTORY:VM_MOUNT_DIRECTORY(ex:"/host-home:/vm-home") \tminikube mount HOST_MOUNT_DIRECTORY:VM_MOUNT_DIRECTORY(ex:"/host-home:/vm-home")
@ -104,13 +113,18 @@ var mountCmd = &cobra.Command{
} }
fmt.Printf("Mounting %s into %s on the minikubeVM\n", hostPath, vmPath) 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...") fmt.Println("This daemon process needs to stay alive for the mount to still be accessible...")
port, err := cmdUtil.GetPort()
if err != nil {
glog.Errorln("Error finding port for mount: ", err)
os.Exit(1)
}
var wg sync.WaitGroup var wg sync.WaitGroup
wg.Add(1) wg.Add(1)
go func() { go func() {
ufs.StartServer(net.JoinHostPort(ip.String(), constants.DefaultUfsPort), debugVal, hostPath) ufs.StartServer(net.JoinHostPort(ip.String(), port), debugVal, hostPath)
wg.Done() wg.Done()
}() }()
err = cluster.MountHost(api, vmPath, ip) err = cluster.MountHost(api, vmPath, ip, port)
if err != nil { if err != nil {
fmt.Println(err.Error()) fmt.Println(err.Error())
os.Exit(1) os.Exit(1)
@ -121,5 +135,6 @@ var mountCmd = &cobra.Command{
func init() { func init() {
mountCmd.Flags().StringVar(&mountIP, "ip", "", "Specify the ip that the mount should be setup on") mountCmd.Flags().StringVar(&mountIP, "ip", "", "Specify the ip that the mount should be setup on")
mountCmd.Flags().BoolVar(&isKill, "kill", false, "Kill the mount process spawned by minikube start")
RootCmd.AddCommand(mountCmd) RootCmd.AddCommand(mountCmd)
} }

View File

@ -19,6 +19,7 @@ package cmd
import ( import (
"fmt" "fmt"
"os" "os"
"os/exec"
"path/filepath" "path/filepath"
"strconv" "strconv"
"strings" "strings"
@ -30,6 +31,8 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
"io/ioutil"
cmdUtil "k8s.io/minikube/cmd/util" cmdUtil "k8s.io/minikube/cmd/util"
"k8s.io/minikube/pkg/minikube/cluster" "k8s.io/minikube/pkg/minikube/cluster"
cfg "k8s.io/minikube/pkg/minikube/config" cfg "k8s.io/minikube/pkg/minikube/config"
@ -55,9 +58,11 @@ const (
hypervVirtualSwitch = "hyperv-virtual-switch" hypervVirtualSwitch = "hyperv-virtual-switch"
kvmNetwork = "kvm-network" kvmNetwork = "kvm-network"
keepContext = "keep-context" keepContext = "keep-context"
noMount = "no-mount"
featureGates = "feature-gates" featureGates = "feature-gates"
apiServerName = "apiserver-name" apiServerName = "apiserver-name"
dnsDomain = "dns-domain" dnsDomain = "dns-domain"
mountString = "mount-string"
) )
var ( var (
@ -197,8 +202,35 @@ func runStart(cmd *cobra.Command, args []string) {
cmdUtil.MaybeReportErrorAndExit(err) cmdUtil.MaybeReportErrorAndExit(err)
} }
fmt.Printf("Setting up hostmount on %s...\n", viper.GetString(mountString))
// start 9p server mount
if !viper.GetBool(noMount) || cfg.GetMachineName() != constants.DefaultMachineName {
path := os.Args[0]
mountDebugVal := 0
if glog.V(8) {
mountDebugVal = 1
}
mountCmd := exec.Command(path, "mount", fmt.Sprintf("--v=%d", mountDebugVal), viper.GetString(mountString))
mountCmd.Env = append(os.Environ(), constants.IsMinikubeChildProcess+"=true")
if glog.V(8) {
mountCmd.Stdout = os.Stdout
mountCmd.Stderr = os.Stderr
}
err = mountCmd.Start()
if err != nil {
glog.Errorf("Error running command minikube mount %s", err)
cmdUtil.MaybeReportErrorAndExit(err)
}
err = ioutil.WriteFile(filepath.Join(constants.GetMinipath(), constants.MountProcessFileName), []byte(strconv.Itoa(mountCmd.Process.Pid)), 0644)
if err != nil {
glog.Errorf("Error writing mount process pid to file: %s", err)
cmdUtil.MaybeReportErrorAndExit(err)
}
}
if kubeCfgSetup.KeepContext { if kubeCfgSetup.KeepContext {
fmt.Printf("The local Kubernetes cluster has started. The kubectl context has not been altered, kubectl will require \"--context=%s\" to use the local Kubernetes cluster.\n", kubeCfgSetup.ClusterName) fmt.Printf("The local Kubernetes cluster has started. The kubectl context has not been altered, kubectl will require \"--context=%s\" to use the local Kubernetes cluster.\n",
kubeCfgSetup.ClusterName)
} else { } else {
fmt.Println("Kubectl is now configured to use the cluster.") fmt.Println("Kubectl is now configured to use the cluster.")
} }
@ -227,6 +259,8 @@ func calculateDiskSizeInMB(humanReadableDiskSize string) int {
func init() { func init() {
startCmd.Flags().Bool(keepContext, constants.DefaultKeepContext, "This will keep the existing kubectl context and will create a minikube context.") startCmd.Flags().Bool(keepContext, constants.DefaultKeepContext, "This will keep the existing kubectl context and will create a minikube context.")
startCmd.Flags().Bool(noMount, constants.DefaultNoMount, "This will not start the mount daemon and automatically mount files into minikube")
startCmd.Flags().String(mountString, constants.DefaultMountDir+":"+constants.DefaultMountEndpoint, "The argument to pass the minikube mount command on start")
startCmd.Flags().String(isoURL, constants.DefaultIsoUrl, "Location of the minikube iso") startCmd.Flags().String(isoURL, constants.DefaultIsoUrl, "Location of the minikube iso")
startCmd.Flags().String(vmDriver, constants.DefaultVMDriver, fmt.Sprintf("VM driver is one of: %v", constants.SupportedVMDrivers)) startCmd.Flags().String(vmDriver, constants.DefaultVMDriver, fmt.Sprintf("VM driver is one of: %v", constants.SupportedVMDrivers))
startCmd.Flags().Int(memory, constants.DefaultMemory, "Amount of RAM allocated to the minikube VM") startCmd.Flags().Int(memory, constants.DefaultMemory, "Amount of RAM allocated to the minikube VM")

View File

@ -46,6 +46,10 @@ itself, leaving all files intact. The cluster can be started again with the "sta
cmdUtil.MaybeReportErrorAndExit(err) cmdUtil.MaybeReportErrorAndExit(err)
} }
fmt.Println("Machine stopped.") fmt.Println("Machine stopped.")
if err := cmdUtil.KillMountProcess(); err != nil {
fmt.Println("Errors occurred deleting mount process: ", err)
}
}, },
} }

View File

@ -17,12 +17,12 @@ limitations under the License.
package main package main
import ( import (
"github.com/pkg/profile"
"k8s.io/minikube/cmd/minikube/cmd"
"k8s.io/minikube/pkg/minikube/machine"
"os" "os"
"github.com/pkg/profile"
"k8s.io/minikube/cmd/minikube/cmd"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/machine"
_ "k8s.io/minikube/pkg/provision" _ "k8s.io/minikube/pkg/provision"
) )
@ -32,6 +32,8 @@ func main() {
if os.Getenv(minikubeEnvPrefix) == "1" { if os.Getenv(minikubeEnvPrefix) == "1" {
defer profile.Start(profile.TraceProfile).Stop() defer profile.Start(profile.TraceProfile).Stop()
} }
machine.StartDriver() if os.Getenv(constants.IsMinikubeChildProcess) == "" {
machine.StartDriver()
}
cmd.Execute() cmd.Execute()
} }

View File

@ -22,13 +22,18 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"net"
"net/http" "net/http"
"os" "os"
"os/exec" "os/exec"
"path/filepath"
"runtime" "runtime"
"strings" "strings"
"time" "time"
"strconv"
"github.com/golang/glog" "github.com/golang/glog"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/spf13/viper" "github.com/spf13/viper"
@ -210,3 +215,34 @@ minikube config set WantKubectlDownloadMsg false
verb, fmt.Sprintf(installInstructions, constants.DefaultKubernetesVersion, goos, runtime.GOARCH)) verb, fmt.Sprintf(installInstructions, constants.DefaultKubernetesVersion, goos, runtime.GOARCH))
} }
} }
// Ask the kernel for a free open port that is ready to use
func GetPort() (string, error) {
addr, err := net.ResolveTCPAddr("tcp", "localhost:0")
if err != nil {
panic(err)
}
l, err := net.ListenTCP("tcp", addr)
if err != nil {
return "", errors.Errorf("Error accessing port %d", addr.Port)
}
defer l.Close()
return strconv.Itoa(l.Addr().(*net.TCPAddr).Port), nil
}
func KillMountProcess() error {
out, err := ioutil.ReadFile(filepath.Join(constants.GetMinipath(), constants.MountProcessFileName))
if err != nil {
return errors.Wrap(err, "error reading mount process from file")
}
pid, err := strconv.Atoi(string(out))
if err != nil {
return errors.Wrap(err, "error converting mount string to pid")
}
mountProc, err := os.FindProcess(pid)
if err != nil {
return errors.Wrap(err, "error converting mount string to pid")
}
return mountProc.Kill()
}

View File

@ -46,7 +46,7 @@ sudo rm -rf $HOME/.minikube || true
# Allow this to fail, we'll switch on the return code below. # Allow this to fail, we'll switch on the return code below.
set +e set +e
out/e2e-${OS_ARCH} -minikube-args="--vm-driver=${VM_DRIVER} --v=10" -test.v -test.timeout=30m -binary=out/minikube-${OS_ARCH} out/e2e-${OS_ARCH} -minikube-args="--vm-driver=${VM_DRIVER} --v=10 --no-mount" -test.v -test.timeout=30m -binary=out/minikube-${OS_ARCH}
result=$? result=$?
set -e set -e

View File

@ -21,7 +21,7 @@ gsutil.cmd cp -r gs://minikube-builds/$env:MINIKUBE_LOCATION/testdata .
./out/minikube-windows-amd64.exe delete ./out/minikube-windows-amd64.exe delete
Remove-Item -Recurse -Force C:\Users\jenkins\.minikube Remove-Item -Recurse -Force C:\Users\jenkins\.minikube
out/e2e-windows-amd64.exe --% -minikube-args="--vm-driver=hyperv --hyperv-virtual-switch=Minikube --cpus=4 $env:EXTRA_BUILD_ARGS" -test.v -test.timeout=30m -binary=out/minikube-windows-amd64.exe out/e2e-windows-amd64.exe --% -minikube-args="--vm-driver=hyperv --hyperv-virtual-switch=Minikube --cpus=4 $env:EXTRA_BUILD_ARGS --no-mount" -test.v -test.timeout=30m -binary=out/minikube-windows-amd64.exe
$env:result=$lastexitcode $env:result=$lastexitcode
# If the last exit code was 0->success, x>0->error # If the last exit code was 0->success, x>0->error

View File

@ -402,7 +402,7 @@ func GetHostLogs(api libmachine.API, follow bool) (string, error) {
} }
// MountHost runs the mount command from the 9p client on the VM to the 9p server on the host // 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, ip net.IP) error { func MountHost(api libmachine.API, path string, ip net.IP, port string) error {
host, err := CheckIfApiExistsAndLoad(api) host, err := CheckIfApiExistsAndLoad(api)
if err != nil { if err != nil {
return errors.Wrap(err, "Error checking that api exists and loading it") return errors.Wrap(err, "Error checking that api exists and loading it")
@ -414,7 +414,7 @@ func MountHost(api libmachine.API, path string, ip net.IP) error {
} }
} }
host.RunSSHCommand(GetMountCleanupCommand(path)) host.RunSSHCommand(GetMountCleanupCommand(path))
mountCmd, err := GetMountCommand(ip, path) mountCmd, err := GetMountCommand(ip, path, port)
if err != nil { if err != nil {
return errors.Wrap(err, "Error getting mount command") return errors.Wrap(err, "Error getting mount command")
} }

View File

@ -184,18 +184,20 @@ sudo rm -rf %s;
var mountTemplate = ` var mountTemplate = `
sudo mkdir -p {{.Path}}; sudo mkdir -p {{.Path}};
sudo mount -t 9p -o trans=tcp -o port=5640 -o uid=1001 -o gid=1001 {{.IP}} {{.Path}}; sudo mount -t 9p -o trans=tcp -o port={{.Port}} -o uid=1001 -o gid=1001 {{.IP}} {{.Path}};
sudo chmod 775 {{.Path}};` sudo chmod 775 {{.Path}};`
func GetMountCommand(ip net.IP, path string) (string, error) { func GetMountCommand(ip net.IP, path string, port string) (string, error) {
t := template.Must(template.New("mountCommand").Parse(mountTemplate)) t := template.Must(template.New("mountCommand").Parse(mountTemplate))
buf := bytes.Buffer{} buf := bytes.Buffer{}
data := struct { data := struct {
IP string IP string
Path string Path string
Port string
}{ }{
IP: ip.String(), IP: ip.String(),
Path: path, Path: path,
Port: port,
} }
if err := t.Execute(&buf, data); err != nil { if err := t.Execute(&buf, data); err != nil {
return "", err return "", err

View File

@ -73,6 +73,8 @@ func MakeMiniPath(fileName ...string) string {
return filepath.Join(args...) return filepath.Join(args...)
} }
var MountProcessFileName = ".mount-process"
// Only pass along these flags to localkube. // Only pass along these flags to localkube.
var LogFlags = [...]string{ var LogFlags = [...]string{
"v", "v",
@ -127,4 +129,7 @@ const (
const ( const (
DefaultUfsPort = "5640" DefaultUfsPort = "5640"
DefaultUfsDebugLvl = 0 DefaultUfsDebugLvl = 0
DefaultNoMount = false
) )
const IsMinikubeChildProcess = "IS_MINIKUBE_CHILD_PROCESS"

View File

@ -23,3 +23,6 @@ var SupportedVMDrivers = [...]string{
"xhyve", "xhyve",
"vmwarefusion", "vmwarefusion",
} }
var DefaultMountDir = "/Users"
var DefaultMountEndpoint = "/Users"

View File

@ -18,7 +18,14 @@ limitations under the License.
package constants package constants
import (
"k8s.io/client-go/util/homedir"
)
var SupportedVMDrivers = [...]string{ var SupportedVMDrivers = [...]string{
"virtualbox", "virtualbox",
"kvm", "kvm",
} }
var DefaultMountDir = homedir.HomeDir()
var DefaultMountEndpoint = "/hosthome"

View File

@ -18,7 +18,14 @@ limitations under the License.
package constants package constants
import (
"k8s.io/client-go/util/homedir"
)
var SupportedVMDrivers = [...]string{ var SupportedVMDrivers = [...]string{
"virtualbox", "virtualbox",
"hyperv", "hyperv",
} }
var DefaultMountDir = homedir.HomeDir()
var DefaultMountEndpoint = "/hostmount"