Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Add minikube support for the "generic" VM driver #9545

Closed
wants to merge 29 commits into from
Closed
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
264072b
Add minikube support for the "generic" VM driver
afbjorklund Jul 10, 2019
63e6c66
Don't download ISO for the generic VM driver
afbjorklund Jul 14, 2019
d8712cd
Generic driver does not add user to docker group
afbjorklund Jul 14, 2019
19918ca
Try to uninstall kubernetes on delete, for generic
afbjorklund Jul 14, 2019
d53a0d3
Don't try to start/stop drivers without VMs
afbjorklund Jul 15, 2019
71e9dc1
Flip the driver logic to make code easier to read
afbjorklund Oct 28, 2020
d35d00c
Allow actually using the generic driver
afbjorklund Oct 28, 2020
55e8e33
Call DetectProvisioner for the generic driver
afbjorklund Oct 28, 2020
4197935
Show remote host info and proper progress
afbjorklund Oct 29, 2020
dc08bd8
Fix failing unit test for MachineType
afbjorklund Oct 29, 2020
9e7739e
Log the os-release also for the generic driver
afbjorklund Oct 29, 2020
3b594c3
Need to set up docker group in start - not in fix
afbjorklund Oct 29, 2020
be770af
Also parse the available, in addition to the total
afbjorklund Oct 30, 2020
e1effd3
Add some error checking on the parsed data fields
afbjorklund Oct 30, 2020
b17ecbd
Convert the return values to use uint64 instead
afbjorklund Oct 30, 2020
88df534
Supply the disk mountpoint as a parameter instead
afbjorklund Oct 30, 2020
2394e33
Merge branch 'master' into generic
afbjorklund Nov 7, 2020
251ee84
Merge branch 'master' into generic
afbjorklund Nov 14, 2020
6104fb9
fixup: out.T was renamed to out.Step
afbjorklund Nov 14, 2020
3bb75da
Revert "Supply the disk mountpoint as a parameter instead"
afbjorklund Nov 14, 2020
bb53864
Revert "Convert the return values to use uint64 instead"
afbjorklund Nov 14, 2020
612606c
Revert "Add some error checking on the parsed data fields"
afbjorklund Nov 14, 2020
08e1a65
Revert "Also parse the available, in addition to the total"
afbjorklund Nov 14, 2020
4428b3b
Revert "Show remote host info and proper progress"
afbjorklund Nov 14, 2020
70d1a31
Add helper for checking the generic driver name
afbjorklund Nov 14, 2020
1dc8769
Merge branch 'master' into generic
afbjorklund Nov 18, 2020
306d08d
Merge branch 'master' into generic
afbjorklund Nov 29, 2020
31ccaa6
Merge branch 'master' into generic
afbjorklund Dec 5, 2020
1369b08
Merge branch 'master' into generic
afbjorklund Dec 9, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/minikube/cmd/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ func deleteProfile(profile *config.Profile) error {
return DeletionError{Err: delErr, Errtype: MissingProfile}
}

if err == nil && driver.BareMetal(cc.Driver) {
if err == nil && (driver.BareMetal(cc.Driver) || cc.Driver == driver.Generic) {
if err := uninstallKubernetes(api, *cc, cc.Nodes[0], viper.GetString(cmdcfg.Bootstrapper)); err != nil {
deletionError, ok := err.(DeletionError)
if ok {
Expand Down
4 changes: 2 additions & 2 deletions cmd/minikube/cmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ func provisionWithDriver(cmd *cobra.Command, ds registry.DriverState, existing *
os.Exit(0)
}

if driver.IsVM(driverName) {
if driver.IsVM(driverName) && driverName != driver.Generic {
url, err := download.ISO(viper.GetStringSlice(isoURL), cmd.Flags().Changed(isoURL))
if err != nil {
return node.Starter{}, errors.Wrap(err, "Failed to cache ISO")
Expand Down Expand Up @@ -812,7 +812,7 @@ func validateUser(drvName string) {

// memoryLimits returns the amount of memory allocated to the system and hypervisor, the return value is in MiB
func memoryLimits(drvName string) (int, int, error) {
info, cpuErr, memErr, diskErr := machine.CachedHostInfo()
info, cpuErr, memErr, diskErr := machine.LocalHostInfo()
if cpuErr != nil {
klog.Warningf("could not get system cpu info while verifying memory limits, which might be okay: %v", cpuErr)
}
Expand Down
15 changes: 15 additions & 0 deletions cmd/minikube/cmd/start_flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"time"

"github.com/blang/semver"
"github.com/docker/machine/libmachine/drivers"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/spf13/viper"
Expand Down Expand Up @@ -108,6 +109,10 @@ const (
kicBaseImage = "base-image"
ports = "ports"
startNamespace = "namespace"
genericIPAddress = "generic-ip-address"
genericSSHUser = "generic-ssh-user"
genericSSHKey = "generic-ssh-key"
genericSSHPort = "generic-ssh-port"
)

var (
Expand Down Expand Up @@ -217,6 +222,12 @@ func initNetworkingFlags() {
startCmd.Flags().String(serviceCIDR, constants.DefaultServiceCIDR, "The CIDR to be used for service cluster IPs.")
startCmd.Flags().StringArrayVar(&config.DockerEnv, "docker-env", nil, "Environment variables to pass to the Docker daemon. (format: key=value)")
startCmd.Flags().StringArrayVar(&config.DockerOpt, "docker-opt", nil, "Specify arbitrary flags to pass to the Docker daemon. (format: key=value)")

// generic
startCmd.Flags().String(genericIPAddress, "", "IP address (generic)")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should validate that all of these flags are set and exit with a helpful error message if the user has forgotten anything

Copy link
Collaborator Author

@afbjorklund afbjorklund Oct 28, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did that, but it was lost during the rebase. It should at least give an error if forgetting to provide an IP address ?

The other parameters are optional, by default it will connect as root on port 22 and assume keys are in ssh-agent

startCmd.Flags().String(genericSSHUser, drivers.DefaultSSHUser, "SSH user (generic)")
startCmd.Flags().String(genericSSHKey, "", "SSH key (generic)")
startCmd.Flags().Int(genericSSHPort, drivers.DefaultSSHPort, "SSH port (generic)")
}

// ClusterFlagValue returns the current cluster name based on flags
Expand Down Expand Up @@ -326,6 +337,10 @@ func generateClusterConfig(cmd *cobra.Command, existing *config.ClusterConfig, k
NatNicType: viper.GetString(natNicType),
StartHostTimeout: viper.GetDuration(waitTimeout),
ExposedPorts: viper.GetStringSlice(ports),
GenericIPAddress: viper.GetString(genericIPAddress),
GenericSSHUser: viper.GetString(genericSSHUser),
GenericSSHKey: viper.GetString(genericSSHKey),
GenericSSHPort: viper.GetInt(genericSSHPort),
KubernetesConfig: config.KubernetesConfig{
KubernetesVersion: k8sVersion,
ClusterName: ClusterFlagValue(),
Expand Down
6 changes: 6 additions & 0 deletions pkg/minikube/cluster/ip.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ func HostIP(host *host.Host, clusterName string) (net.IP, error) {
return oci.RoutableHostIPFromInside(oci.Docker, clusterName, host.Name)
case driver.Podman:
return oci.RoutableHostIPFromInside(oci.Podman, clusterName, host.Name)
case driver.Generic:
ip, err := host.Driver.GetIP()
if err != nil {
return []byte{}, errors.Wrap(err, "Error getting VM/Host IP address")
}
return net.ParseIP(ip), nil
case driver.KVM2:
return net.ParseIP("192.168.39.1"), nil
case driver.HyperV:
Expand Down
4 changes: 4 additions & 0 deletions pkg/minikube/config/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ type ClusterConfig struct {
HostDNSResolver bool // Only used by virtualbox
HostOnlyNicType string // Only used by virtualbox
NatNicType string // Only used by virtualbox
GenericIPAddress string // Only used by generic
GenericSSHUser string // Only used by generic
GenericSSHKey string // Only used by generic
GenericSSHPort int // Only used by generic
KubernetesConfig KubernetesConfig
Nodes []Node
Addons map[string]bool
Expand Down
6 changes: 6 additions & 0 deletions pkg/minikube/driver/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ const (
Mock = "mock"
// None driver
None = "none"
// Generic driver
Generic = "generic"
// KVM2 driver
KVM2 = "kvm2"
// VirtualBox driver
Expand Down Expand Up @@ -94,6 +96,10 @@ func MachineType(name string) string {
return "container"
}

if name == Generic {
return "bare metal machine"
}

if IsVM(name) {
return "VM"
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/minikube/driver/driver_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ var supportedDrivers = []string{
HyperKit,
VMware,
Docker,
Podman,
Generic,
}

func VBoxManagePath() string {
Expand Down
1 change: 1 addition & 0 deletions pkg/minikube/driver/driver_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ var supportedDrivers = []string{
None,
Docker,
Podman,
Generic,
}

// VBoxManagePath returns the path to the VBoxManage command
Expand Down
1 change: 1 addition & 0 deletions pkg/minikube/driver/driver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ func TestMachineType(t *testing.T) {
Docker: "container",
Mock: "bare metal machine",
None: "bare metal machine",
Generic: "bare metal machine",
KVM2: "VM",
VirtualBox: "VM",
HyperKit: "VM",
Expand Down
1 change: 1 addition & 0 deletions pkg/minikube/driver/driver_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ var supportedDrivers = []string{
HyperV,
VMware,
Docker,
Generic,
}

// TODO: medyagh add same check for kic docker
Expand Down
9 changes: 9 additions & 0 deletions pkg/minikube/machine/fix.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,15 @@ func recreateIfNeeded(api libmachine.API, cc *config.ClusterConfig, n *config.No
}
}

if h.Driver.DriverName() == driver.Generic {
if s == state.Running {
out.T(style.Running, `Using the {{.driver_name}} "{{.cluster}}" {{.machine_type}} ...`, out.V{"driver_name": cc.Driver, "cluster": cc.Name, "machine_type": machineType})
} else {
return h, errors.Errorf("not running")
}
return h, nil
}

if serr != constants.ErrMachineMissing {
klog.Warningf("unexpected machine state, will restart: %v", serr)
}
Expand Down
43 changes: 41 additions & 2 deletions pkg/minikube/machine/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ package machine
import (
"io/ioutil"
"os/exec"
"strconv"
"strings"

"github.com/docker/machine/libmachine/provision"
"github.com/shirou/gopsutil/cpu"
Expand All @@ -39,8 +41,8 @@ type HostInfo struct {
DiskSize int64
}

// CachedHostInfo returns system information such as memory,CPU, DiskSize
func CachedHostInfo() (*HostInfo, error, error, error) {
// LocalHostInfo returns system information such as memory,CPU, DiskSize
func LocalHostInfo() (*HostInfo, error, error, error) {
var cpuErr, memErr, diskErr error
i, cpuErr := cachedCPUInfo()
if cpuErr != nil {
Expand All @@ -63,6 +65,43 @@ func CachedHostInfo() (*HostInfo, error, error, error) {
return &info, cpuErr, memErr, diskErr
}

// RemoteHostInfo returns system information such as memory,CPU, DiskSize
func RemoteHostInfo(r command.Runner) (*HostInfo, error, error, error) {
rr, cpuErr := r.RunCmd(exec.Command("nproc"))
if cpuErr != nil {
klog.Warningf("Unable to get CPU info: %v", cpuErr)
}
nproc := rr.Stdout.String()
ncpus, err := strconv.Atoi(strings.TrimSpace(nproc))
if err != nil {
klog.Warningf("Failed to parse CPU info: %v", err)
}
rr, memErr := r.RunCmd(exec.Command("free", "-m"))
if memErr != nil {
klog.Warningf("Unable to get mem info: %v", memErr)
}
free := rr.Stdout.String()
memory, _, err := util.ParseMemFree(free)
if err != nil {
klog.Warningf("Unable to parse mem info: %v", err)
}
rr, diskErr := r.RunCmd(exec.Command("df", "-m"))
if diskErr != nil {
klog.Warningf("Unable to get disk info: %v", diskErr)
}
df := rr.Stdout.String()
disksize, _, err := util.ParseDiskFree(df, "/")
if err != nil {
klog.Warningf("Unable to parse disk info: %v", err)
}

var info HostInfo
info.CPUs = ncpus
info.Memory = int64(memory)
info.DiskSize = int64(disksize)
return &info, cpuErr, memErr, diskErr
}

// showLocalOsRelease shows systemd information about the current linux distribution, on the local host
func showLocalOsRelease() {
osReleaseOut, err := ioutil.ReadFile("/etc/os-release")
Expand Down
2 changes: 1 addition & 1 deletion pkg/minikube/machine/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func fastDetectProvisioner(h *host.Host) (libprovision.Provisioner, error) {
switch {
case driver.IsKIC(d):
return provision.NewUbuntuProvisioner(h.Driver), nil
case driver.BareMetal(d):
case driver.BareMetal(d), d == driver.Generic:
return libprovision.DetectProvisioner(h.Driver)
default:
return provision.NewBuildrootProvisioner(h.Driver), nil
Expand Down
32 changes: 28 additions & 4 deletions pkg/minikube/machine/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,9 @@ func createHost(api libmachine.API, cfg *config.ClusterConfig, n *config.Node) (
See https://minikube.sigs.k8s.io/docs/reference/drivers/vmware/ for more information.
To disable this message, run [minikube config set ShowDriverDeprecationNotification false]`)
}
showHostInfo(*cfg)
if cfg.Driver != driver.Generic {
showHostInfo(nil, *cfg)
}
def := registry.Driver(cfg.Driver)
if def.Empty() {
return nil, fmt.Errorf("unsupported/missing driver: %s", cfg.Driver)
Expand Down Expand Up @@ -170,11 +172,20 @@ func createHost(api libmachine.API, cfg *config.ClusterConfig, n *config.Node) (
return nil, errors.Wrap(err, "creating host")
}
klog.Infof("duration metric: libmachine.API.Create for %q took %s", cfg.Name, time.Since(cstart))
if cfg.Driver == driver.Generic {
showHostInfo(h, *cfg)
}

if err := postStartSetup(h, *cfg); err != nil {
return h, errors.Wrap(err, "post-start")
}

if h.Driver.DriverName() == driver.Generic {
if _, err := h.RunSSHCommand(fmt.Sprintf("sudo usermod -aG docker %s", h.Driver.GetSSHUsername())); err != nil {
return h, errors.Wrap(err, "usermod")
}
}

if err := saveHost(api, h, cfg, n); err != nil {
return h, err
}
Expand Down Expand Up @@ -290,7 +301,7 @@ func postStartSetup(h *host.Host, mc config.ClusterConfig) error {
if driver.BareMetal(mc.Driver) {
showLocalOsRelease()
}
if driver.IsVM(mc.Driver) || driver.IsKIC(mc.Driver) {
if driver.IsVM(mc.Driver) || driver.IsKIC(mc.Driver) || mc.Driver == driver.Generic {
logRemoteOsRelease(r)
}
return syncLocalAssets(r)
Expand Down Expand Up @@ -321,16 +332,29 @@ func acquireMachinesLock(name string, drv string) (mutex.Releaser, error) {
}

// showHostInfo shows host information
func showHostInfo(cfg config.ClusterConfig) {
func showHostInfo(h *host.Host, cfg config.ClusterConfig) {
machineType := driver.MachineType(cfg.Driver)
if driver.BareMetal(cfg.Driver) {
info, cpuErr, memErr, DiskErr := CachedHostInfo()
info, cpuErr, memErr, DiskErr := LocalHostInfo()
if cpuErr == nil && memErr == nil && DiskErr == nil {
register.Reg.SetStep(register.RunningLocalhost)
out.T(style.StartingNone, "Running on localhost (CPUs={{.number_of_cpus}}, Memory={{.memory_size}}MB, Disk={{.disk_size}}MB) ...", out.V{"number_of_cpus": info.CPUs, "memory_size": info.Memory, "disk_size": info.DiskSize})
}
return
}
if cfg.Driver == driver.Generic {
r, err := CommandRunner(h)
if err != nil {
klog.Warningf("error getting command runner: %v", err)
return
}
info, cpuErr, memErr, DiskErr := RemoteHostInfo(r)
if cpuErr == nil && memErr == nil && DiskErr == nil {
register.Reg.SetStep(register.RunningRemotely)
out.T(style.StartingGeneric, "Running remotely (CPUs={{.number_of_cpus}}, Memory={{.memory_size}}MB, Disk={{.disk_size}}MB) ...", out.V{"number_of_cpus": info.CPUs, "memory_size": info.Memory, "disk_size": info.DiskSize})
}
return
}
if driver.IsKIC(cfg.Driver) { // TODO:medyagh add free disk space on docker machine
register.Reg.SetStep(register.CreatingContainer)
out.T(style.StartingVM, "Creating {{.driver_name}} {{.machine_type}} (CPUs={{.number_of_cpus}}, Memory={{.memory_size}}MB) ...", out.V{"driver_name": cfg.Driver, "number_of_cpus": cfg.CPUs, "memory_size": cfg.Memory, "machine_type": machineType})
Expand Down
4 changes: 4 additions & 0 deletions pkg/minikube/machine/stop.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ func stop(h *host.Host) error {
}
}

if h.DriverName == driver.Generic {
return nil
}

if err := h.Stop(); err != nil {
klog.Infof("stop err: %v", err)
st, ok := err.(mcnerror.ErrHostAlreadyInState)
Expand Down
2 changes: 2 additions & 0 deletions pkg/minikube/out/register/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const (
DownloadingArtifacts RegStep = "Downloading Artifacts"
StartingNode RegStep = "Starting Node"
RunningLocalhost RegStep = "Running on Localhost"
RunningRemotely RegStep = "Running Remotely"
LocalOSRelease RegStep = "Local OS Release"
CreatingContainer RegStep = "Creating Container"
CreatingVM RegStep = "Creating VM"
Expand Down Expand Up @@ -72,6 +73,7 @@ func init() {
LocalOSRelease,
CreatingContainer,
CreatingVM,
RunningRemotely,
PreparingKubernetes,
ConfiguringLHEnv,
VerifyingKubernetes,
Expand Down
62 changes: 62 additions & 0 deletions pkg/minikube/registry/drvs/generic/generic.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
Copyright 2019 The Kubernetes Authors All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package generic

import (
"fmt"

"github.com/docker/machine/drivers/generic"
"github.com/docker/machine/libmachine/drivers"
"github.com/pkg/errors"

"k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/driver"
"k8s.io/minikube/pkg/minikube/localpath"
"k8s.io/minikube/pkg/minikube/registry"
)

func init() {
err := registry.Register(registry.DriverDef{
Name: driver.Generic,
Config: configure,
Status: status,
Priority: registry.Fallback,
Init: func() drivers.Driver { return generic.NewDriver("", "") },
})
if err != nil {
panic(fmt.Sprintf("unable to register: %v", err))
}
}

func configure(cc config.ClusterConfig, n config.Node) (interface{}, error) {
d := generic.NewDriver(driver.MachineName(cc, n), localpath.MiniPath())

if cc.GenericIPAddress == "" {
return nil, errors.Errorf("please provide an IP address")
}

d.(*generic.Driver).IPAddress = cc.GenericIPAddress
d.(*generic.Driver).SSHUser = cc.GenericSSHUser
d.(*generic.Driver).SSHKey = cc.GenericSSHKey
d.(*generic.Driver).SSHPort = cc.GenericSSHPort

return d, nil
}

func status() registry.State {
return registry.State{Installed: true, Healthy: true}
}
Loading