Download kvm2 driver

pull/5085/head
josedonizetti 2019-08-14 20:28:38 -04:00
parent f36c5d8ed1
commit 30e75c3c39
6 changed files with 155 additions and 30 deletions

View File

@ -21,6 +21,7 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"runtime"
"strings" "strings"
"github.com/docker/machine/libmachine" "github.com/docker/machine/libmachine"
@ -108,6 +109,12 @@ func Execute() {
flag.Usage = translate.T(flag.Usage) flag.Usage = translate.T(flag.Usage)
}) })
if runtime.GOOS == "linux" {
// add minikube binaries to the path
targetDir := constants.MakeMiniPath("bin")
addToPath(targetDir)
}
if err := RootCmd.Execute(); err != nil { if err := RootCmd.Execute(); err != nil {
// Cobra already outputs the error, typically because the user provided an unknown command. // Cobra already outputs the error, typically because the user provided an unknown command.
os.Exit(exit.BadUsage) os.Exit(exit.BadUsage)
@ -281,3 +288,8 @@ func getClusterBootstrapper(api libmachine.API, bootstrapperName string) (bootst
return b, nil return b, nil
} }
func addToPath(dir string) {
path := os.Getenv("PATH")
os.Setenv("PATH", fmt.Sprintf("%s:%s", dir, path))
}

View File

@ -24,7 +24,6 @@ import (
"os/exec" "os/exec"
"os/user" "os/user"
"path/filepath" "path/filepath"
"regexp"
"runtime" "runtime"
"strconv" "strconv"
"strings" "strings"
@ -46,6 +45,7 @@ import (
"github.com/spf13/viper" "github.com/spf13/viper"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
cmdcfg "k8s.io/minikube/cmd/minikube/cmd/config" cmdcfg "k8s.io/minikube/cmd/minikube/cmd/config"
"k8s.io/minikube/pkg/drivers"
"k8s.io/minikube/pkg/minikube/bootstrapper" "k8s.io/minikube/pkg/minikube/bootstrapper"
"k8s.io/minikube/pkg/minikube/bootstrapper/kubeadm" "k8s.io/minikube/pkg/minikube/bootstrapper/kubeadm"
"k8s.io/minikube/pkg/minikube/cluster" "k8s.io/minikube/pkg/minikube/cluster"
@ -278,7 +278,8 @@ func runStart(cmd *cobra.Command, args []string) {
registryMirror = viper.GetStringSlice("registry_mirror") registryMirror = viper.GetStringSlice("registry_mirror")
} }
if err := cmdcfg.IsValidDriver(runtime.GOOS, viper.GetString(vmDriver)); err != nil { driver := viper.GetString(vmDriver)
if err := cmdcfg.IsValidDriver(runtime.GOOS, driver); err != nil {
exit.WithCodeT( exit.WithCodeT(
exit.Failure, exit.Failure,
"The driver '{{.driver}}' is not supported on {{.os}}", "The driver '{{.driver}}' is not supported on {{.os}}",
@ -288,7 +289,7 @@ func runStart(cmd *cobra.Command, args []string) {
validateConfig() validateConfig()
validateUser() validateUser()
validateDriverVersion(viper.GetString(vmDriver)) validateDriverVersion(driver)
k8sVersion, isUpgrade := getKubernetesVersion() k8sVersion, isUpgrade := getKubernetesVersion()
config, err := generateCfgFromFlags(cmd, k8sVersion) config, err := generateCfgFromFlags(cmd, k8sVersion)
@ -1027,9 +1028,21 @@ func validateDriverVersion(vmDriver string) {
var driverExecutable string var driverExecutable string
driverDocumentation := fmt.Sprintf("%s%s#driver-installation", constants.DriverDocumentation, vmDriver) driverDocumentation := fmt.Sprintf("%s%s#driver-installation", constants.DriverDocumentation, vmDriver)
minikubeVersion, err := version.GetSemverVersion()
if err != nil {
out.WarningT("Error parsing minukube version: {{.error}}", out.V{"error": err})
return
}
switch vmDriver { switch vmDriver {
case constants.DriverKvm2: case constants.DriverKvm2:
driverExecutable = fmt.Sprintf("docker-machine-driver-%s", constants.DriverKvm2) driverExecutable = fmt.Sprintf("docker-machine-driver-%s", constants.DriverKvm2)
targetDir := constants.MakeMiniPath("bin")
err := drivers.Download(driverExecutable, targetDir, minikubeVersion)
if err != nil {
out.WarningT("Error downloading driver: {{.error}}", out.V{"error": err})
}
return
case constants.DriverHyperkit: case constants.DriverHyperkit:
driverExecutable = fmt.Sprintf("docker-machine-driver-%s", constants.DriverHyperkit) driverExecutable = fmt.Sprintf("docker-machine-driver-%s", constants.DriverHyperkit)
default: // driver doesn't support version default: // driver doesn't support version
@ -1046,7 +1059,7 @@ func validateDriverVersion(vmDriver string) {
return return
} }
v := extractVMDriverVersion(string(output)) v := drivers.ExtractVMDriverVersion(string(output))
// if the driver doesn't have return any version, it is really old, we force a upgrade. // if the driver doesn't have return any version, it is really old, we force a upgrade.
if len(v) == 0 && !viper.GetBool(force) { if len(v) == 0 && !viper.GetBool(force) {
@ -1063,12 +1076,6 @@ func validateDriverVersion(vmDriver string) {
return return
} }
minikubeVersion, err := version.GetSemverVersion()
if err != nil {
out.WarningT("Error parsing minikube version: {{.error}}", out.V{"error": err})
return
}
if vmDriverVersion.LT(minikubeVersion) { if vmDriverVersion.LT(minikubeVersion) {
out.WarningT( out.WarningT(
"The installed version of '{{.driver_executable}}' ({{.driver_version}}) is no longer current. Upgrade: {{.documentation_url}}", "The installed version of '{{.driver_executable}}' ({{.driver_version}}) is no longer current. Upgrade: {{.documentation_url}}",
@ -1076,20 +1083,3 @@ func validateDriverVersion(vmDriver string) {
) )
} }
} }
// extractVMDriverVersion extracts the driver version.
// KVM and Hyperkit drivers support the 'version' command, that display the information as:
// version: vX.X.X
// commit: XXXX
// This method returns the version 'vX.X.X' or empty if the version isn't found.
func extractVMDriverVersion(s string) string {
versionRegex := regexp.MustCompile(`version:(.*)`)
matches := versionRegex.FindStringSubmatch(s)
if len(matches) != 2 {
return ""
}
v := strings.TrimSpace(matches[1])
return strings.TrimPrefix(v, version.VersionPrefix)
}

View File

@ -20,15 +20,29 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"os" "os"
"os/exec"
"path"
"path/filepath" "path/filepath"
"regexp"
"strings"
"syscall" "syscall"
"github.com/blang/semver"
"github.com/docker/machine/libmachine/drivers" "github.com/docker/machine/libmachine/drivers"
"github.com/docker/machine/libmachine/mcnflag" "github.com/docker/machine/libmachine/mcnflag"
"github.com/docker/machine/libmachine/mcnutils" "github.com/docker/machine/libmachine/mcnutils"
"github.com/docker/machine/libmachine/ssh" "github.com/docker/machine/libmachine/ssh"
"github.com/golang/glog" "github.com/golang/glog"
"github.com/hashicorp/go-getter"
"github.com/pkg/errors" "github.com/pkg/errors"
"k8s.io/minikube/pkg/version"
"k8s.io/minikube/pkg/minikube/out"
"k8s.io/minikube/pkg/util"
)
const (
driverKVMDownloadURL = "https://storage.googleapis.com/minikube/releases/latest/docker-machine-driver-kvm2"
) )
// GetDiskPath returns the path of the machine disk image // GetDiskPath returns the path of the machine disk image
@ -136,3 +150,88 @@ func fixPermissions(path string) error {
} }
return nil return nil
} }
// Download downloads driver if it is not present, or if the version is old
func Download(driver, destination string, minikubeVersion semver.Version) error {
_, err := exec.LookPath(driver)
// if file driver doesn't exist, download it
if err != nil {
return download(driver, destination)
}
cmd := exec.Command(driver, "version")
output, err := cmd.Output()
// if driver doesnt support 'version', it is old, download it
if err != nil {
return download(driver, destination)
}
v := ExtractVMDriverVersion(string(output))
// if the driver doesn't return any version, download it
if len(v) == 0 {
return download(driver, destination)
}
vmDriverVersion, err := semver.Make(v)
if err != nil {
return errors.Wrap(err, "can't parse driver version")
}
// if the current driver version is older, download newer
if vmDriverVersion.LT(minikubeVersion) {
return download(driver, destination)
}
return nil
}
func download(driver, destination string) error {
// only support kvm2 for now
if driver != "docker-machine-driver-kvm2" {
return nil
}
out.T(out.Happy, "Downloading driver {{.driver}}:", out.V{"driver": driver})
targetFilepath := path.Join(destination, "docker-machine-driver-kvm2")
os.Remove(targetFilepath)
url := driverKVMDownloadURL
opts := []getter.ClientOption{getter.WithProgress(util.DefaultProgressBar)}
client := &getter.Client{
Src: url,
Dst: targetFilepath,
Mode: getter.ClientModeFile,
Options: opts,
}
if err := client.Get(); err != nil {
return errors.Wrapf(err, "can't download driver %s from: %s", driver, url)
}
err := os.Chmod(targetFilepath, 0777)
if err != nil {
return errors.Wrap(err, "chmod error")
}
return nil
}
// ExtractVMDriverVersion extracts the driver version.
// KVM and Hyperkit drivers support the 'version' command, that display the information as:
// version: vX.X.X
// commit: XXXX
// This method returns the version 'vX.X.X' or empty if the version isn't found.
func ExtractVMDriverVersion(s string) string {
versionRegex := regexp.MustCompile(`version:(.*)`)
matches := versionRegex.FindStringSubmatch(s)
if len(matches) != 2 {
return ""
}
v := strings.TrimSpace(matches[1])
return strings.TrimPrefix(v, version.VersionPrefix)
}

View File

@ -48,3 +48,27 @@ func Test_createDiskImage(t *testing.T) {
t.Errorf("Disk size is %v, want %v", fi.Size(), sizeInBytes) t.Errorf("Disk size is %v, want %v", fi.Size(), sizeInBytes)
} }
} }
func TestExtractVMDriverVersion(t *testing.T) {
v := ExtractVMDriverVersion("")
if len(v) != 0 {
t.Error("Expected empty string")
}
v = ExtractVMDriverVersion("random text")
if len(v) != 0 {
t.Error("Expected empty string")
}
expectedVersion := "1.2.3"
v = ExtractVMDriverVersion("version: v1.2.3")
if expectedVersion != v {
t.Errorf("Expected version: %s, got: %s", expectedVersion, v)
}
v = ExtractVMDriverVersion("version: 1.2.3")
if expectedVersion != v {
t.Errorf("Expected version: %s, got: %s", expectedVersion, v)
}
}

View File

@ -69,7 +69,7 @@ func (f DefaultDownloader) CacheMinikubeISOFromURL(url string) error {
// Predictable temp destination so that resume can function // Predictable temp destination so that resume can function
tmpDst := dst + ".download" tmpDst := dst + ".download"
opts := []getter.ClientOption{getter.WithProgress(defaultProgressBar)} opts := []getter.ClientOption{getter.WithProgress(DefaultProgressBar)}
client := &getter.Client{ client := &getter.Client{
Src: urlWithChecksum, Src: urlWithChecksum,
Dst: tmpDst, Dst: tmpDst,

View File

@ -15,9 +15,9 @@ limitations under the License.
*/ */
// This file implements a go-getter wrapper for cheggaaa progress bar // This file implements a go-getter wrapper for cheggaaa progress bar
// based on: // based on:
// https://github.com/hashicorp/go-getter/blob/master/cmd/go-getter/progress_tracking.go // https://github.com/hashicorp/go-getter/blob/master/cmd/go-getter/progress_tracking.go
package util package util
import ( import (
@ -29,7 +29,7 @@ import (
"github.com/hashicorp/go-getter" "github.com/hashicorp/go-getter"
) )
var defaultProgressBar getter.ProgressTracker = &progressBar{} var DefaultProgressBar getter.ProgressTracker = &progressBar{}
type progressBar struct { type progressBar struct {
lock sync.Mutex lock sync.Mutex