minikube/pkg/minikube/driver/driver.go

252 lines
6.5 KiB
Go

/*
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 driver
import (
"fmt"
"os"
"sort"
"strings"
"github.com/golang/glog"
"k8s.io/minikube/pkg/drivers/kic"
"k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/registry"
)
const (
// Podman is Kubernetes in container using podman driver
Podman = "podman"
// Docker is Kubernetes in container using docker driver
Docker = "docker"
// Mock driver
Mock = "mock"
// None driver
None = "none"
// KVM2 driver
KVM2 = "kvm2"
// VirtualBox driver
VirtualBox = "virtualbox"
// HyperKit driver
HyperKit = "hyperkit"
// VMware driver
VMware = "vmware"
// VMwareFusion driver
VMwareFusion = "vmwarefusion"
// HyperV driver
HyperV = "hyperv"
// Parallels driver
Parallels = "parallels"
)
var (
// systemdResolvConf is path to systemd's DNS configuration. https://github.com/kubernetes/minikube/issues/3511
systemdResolvConf = "/run/systemd/resolve/resolv.conf"
)
// SupportedDrivers returns a list of supported drivers
func SupportedDrivers() []string {
return supportedDrivers
}
// DisplaySupportedDrivers returns a string with a list of supported drivers
func DisplaySupportedDrivers() string {
var sd []string
for _, d := range supportedDrivers {
if registry.Driver(d).Priority == registry.Experimental {
sd = append(sd, d+" (experimental)")
continue
}
sd = append(sd, d)
}
return strings.Join(sd, ", ")
}
// Supported returns if the driver is supported on this host.
func Supported(name string) bool {
for _, d := range supportedDrivers {
if name == d {
return true
}
}
return false
}
// MachineType returns appropriate machine name for the driver
func MachineType(name string) string {
if IsKIC(name) {
return "container"
}
if IsVM(name) {
return "VM"
}
// none or mock
return "bare metal machine"
}
// IsKIC checks if the driver is a kubernetes in container
func IsKIC(name string) bool {
return name == Docker || name == Podman
}
// IsMock checks if the driver is a mock
func IsMock(name string) bool {
return name == Mock
}
// IsVM checks if the driver is a VM
func IsVM(name string) bool {
if IsKIC(name) || BareMetal(name) {
return false
}
return true
}
// BareMetal returns if this driver is unisolated
func BareMetal(name string) bool {
return name == None || name == Mock
}
// NeedsRoot returns true if driver needs to run with root privileges
func NeedsRoot(name string) bool {
return name == None || name == Podman
}
// HasResourceLimits returns true if driver can set resource limits such as memory size or CPU count.
func HasResourceLimits(name string) bool {
return !(name == None || name == Podman)
}
// FlagHints are hints for what default options should be used for this driver
type FlagHints struct {
ExtraOptions []string
CacheImages bool
ContainerRuntime string
Bootstrapper string
}
// FlagDefaults returns suggested defaults based on a driver
func FlagDefaults(name string) FlagHints {
fh := FlagHints{}
if name != None {
fh.CacheImages = true
// only for kic, till other run-times are available we auto-set containerd.
if name == Docker {
fh.ExtraOptions = append(fh.ExtraOptions, fmt.Sprintf("kubeadm.pod-network-cidr=%s", kic.DefaultPodCIDR))
}
return fh
}
fh.CacheImages = false
// if specifc linux add this option for systemd work on none driver
if _, err := os.Stat(systemdResolvConf); err == nil {
noneEO := fmt.Sprintf("kubelet.resolv-conf=%s", systemdResolvConf)
fh.ExtraOptions = append(fh.ExtraOptions, noneEO)
return fh
}
return fh
}
// Choices returns a list of drivers which are possible on this system
func Choices(vm bool) []registry.DriverState {
options := registry.Available(vm)
// Descending priority for predictability and appearance
sort.Slice(options, func(i, j int) bool {
return options[i].Priority > options[j].Priority
})
return options
}
// Suggest returns a suggested driver, alternate drivers, and rejected drivers
func Suggest(options []registry.DriverState) (registry.DriverState, []registry.DriverState, []registry.DriverState) {
pick := registry.DriverState{}
for _, ds := range options {
if !ds.State.Installed {
continue
}
if !ds.State.Healthy {
glog.Infof("not recommending %q due to health: %v", ds.Name, ds.State.Error)
continue
}
if ds.Priority <= registry.Discouraged {
glog.Infof("not recommending %q due to priority: %d", ds.Name, ds.Priority)
continue
}
if ds.Priority > pick.Priority {
glog.V(1).Infof("%q has a higher priority (%d) than %q (%d)", ds.Name, ds.Priority, pick.Name, pick.Priority)
pick = ds
}
}
alternates := []registry.DriverState{}
rejects := []registry.DriverState{}
for _, ds := range options {
if ds != pick {
glog.Errorf("%s: %s", ds.Name, ds.Rejection)
if !ds.State.Installed {
ds.Rejection = fmt.Sprintf("Not installed: %v", ds.State.Error)
rejects = append(rejects, ds)
continue
}
if !ds.State.Healthy {
ds.Rejection = fmt.Sprintf("Not healthy: %v", ds.State.Error)
rejects = append(rejects, ds)
continue
}
ds.Rejection = fmt.Sprintf("%s is preferred", pick.Name)
alternates = append(alternates, ds)
}
}
glog.Infof("Picked: %+v", pick)
glog.Infof("Alternatives: %+v", alternates)
glog.Infof("Rejects: %+v", rejects)
return pick, alternates, rejects
}
// Status returns the status of a driver
func Status(name string) registry.DriverState {
d := registry.Driver(name)
return registry.DriverState{
Name: d.Name,
Priority: d.Priority,
State: registry.Status(name),
}
}
// SetLibvirtURI sets the URI to perform libvirt health checks against
func SetLibvirtURI(v string) {
glog.Infof("Setting default libvirt URI to %s", v)
os.Setenv("LIBVIRT_DEFAULT_URI", v)
}
// MachineName returns the name of the machine, as seen by the hypervisor given the cluster and node names
func MachineName(cc config.ClusterConfig, n config.Node) string {
// For single node cluster, default to back to old naming
if len(cc.Nodes) == 1 || n.ControlPlane {
return cc.Name
}
return fmt.Sprintf("%s-%s", cc.Name, n.Name)
}