Update docker/machine dependencies to v0.10.0

pull/1329/head
Mike Grass 2017-04-07 12:38:07 -07:00
parent 09e8cce24d
commit 74014aed51
30 changed files with 615 additions and 295 deletions

164
Godeps/Godeps.json generated
View File

@ -862,158 +862,158 @@
},
{
"ImportPath": "github.com/docker/machine/commands/mcndirs",
"Comment": "docs-v0.8.2-2016-09-26-11-g91e368eb",
"Rev": "91e368eb7422665278b1d5665139ee0f9980b588"
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/drivers/errdriver",
"Comment": "docs-v0.8.2-2016-09-26-11-g91e368eb",
"Rev": "91e368eb7422665278b1d5665139ee0f9980b588"
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/drivers/hyperv",
"Comment": "docs-v0.8.2-2016-09-26-11-g91e368eb",
"Rev": "91e368eb7422665278b1d5665139ee0f9980b588"
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/drivers/none",
"Comment": "docs-v0.8.2-2016-09-26-11-g91e368eb",
"Rev": "91e368eb7422665278b1d5665139ee0f9980b588"
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/drivers/virtualbox",
"Comment": "docs-v0.8.2-2016-09-26-11-g91e368eb",
"Rev": "91e368eb7422665278b1d5665139ee0f9980b588"
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/drivers/vmwarefusion",
"Comment": "docs-v0.8.2-2016-09-26-11-g91e368eb",
"Rev": "91e368eb7422665278b1d5665139ee0f9980b588"
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/libmachine",
"Comment": "docs-v0.8.2-2016-09-26-11-g91e368eb",
"Rev": "91e368eb7422665278b1d5665139ee0f9980b588"
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/libmachine/auth",
"Comment": "docs-v0.8.2-2016-09-26-11-g91e368eb",
"Rev": "91e368eb7422665278b1d5665139ee0f9980b588"
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/libmachine/cert",
"Comment": "docs-v0.8.2-2016-09-26-11-g91e368eb",
"Rev": "91e368eb7422665278b1d5665139ee0f9980b588"
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/libmachine/check",
"Comment": "docs-v0.8.2-2016-09-26-11-g91e368eb",
"Rev": "91e368eb7422665278b1d5665139ee0f9980b588"
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/libmachine/drivers",
"Comment": "docs-v0.8.2-2016-09-26-11-g91e368eb",
"Rev": "91e368eb7422665278b1d5665139ee0f9980b588"
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/libmachine/drivers/plugin",
"Comment": "docs-v0.8.2-2016-09-26-11-g91e368eb",
"Rev": "91e368eb7422665278b1d5665139ee0f9980b588"
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/libmachine/drivers/plugin/localbinary",
"Comment": "docs-v0.8.2-2016-09-26-11-g91e368eb",
"Rev": "91e368eb7422665278b1d5665139ee0f9980b588"
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/libmachine/drivers/rpc",
"Comment": "docs-v0.8.2-2016-09-26-11-g91e368eb",
"Rev": "91e368eb7422665278b1d5665139ee0f9980b588"
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/libmachine/engine",
"Comment": "docs-v0.8.2-2016-09-26-11-g91e368eb",
"Rev": "91e368eb7422665278b1d5665139ee0f9980b588"
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/libmachine/host",
"Comment": "docs-v0.8.2-2016-09-26-11-g91e368eb",
"Rev": "91e368eb7422665278b1d5665139ee0f9980b588"
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/libmachine/log",
"Comment": "docs-v0.8.2-2016-09-26-11-g91e368eb",
"Rev": "91e368eb7422665278b1d5665139ee0f9980b588"
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/libmachine/mcndockerclient",
"Comment": "docs-v0.8.2-2016-09-26-11-g91e368eb",
"Rev": "91e368eb7422665278b1d5665139ee0f9980b588"
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/libmachine/mcnerror",
"Comment": "docs-v0.8.2-2016-09-26-11-g91e368eb",
"Rev": "91e368eb7422665278b1d5665139ee0f9980b588"
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/libmachine/mcnflag",
"Comment": "docs-v0.8.2-2016-09-26-11-g91e368eb",
"Rev": "91e368eb7422665278b1d5665139ee0f9980b588"
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/libmachine/mcnutils",
"Comment": "docs-v0.8.2-2016-09-26-11-g91e368eb",
"Rev": "91e368eb7422665278b1d5665139ee0f9980b588"
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/libmachine/persist",
"Comment": "docs-v0.8.2-2016-09-26-11-g91e368eb",
"Rev": "91e368eb7422665278b1d5665139ee0f9980b588"
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/libmachine/provision",
"Comment": "docs-v0.8.2-2016-09-26-11-g91e368eb",
"Rev": "91e368eb7422665278b1d5665139ee0f9980b588"
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/libmachine/provision/pkgaction",
"Comment": "docs-v0.8.2-2016-09-26-11-g91e368eb",
"Rev": "91e368eb7422665278b1d5665139ee0f9980b588"
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/libmachine/provision/serviceaction",
"Comment": "docs-v0.8.2-2016-09-26-11-g91e368eb",
"Rev": "91e368eb7422665278b1d5665139ee0f9980b588"
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/libmachine/shell",
"Comment": "docs-v0.8.2-2016-09-26-11-g91e368eb",
"Rev": "91e368eb7422665278b1d5665139ee0f9980b588"
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/libmachine/ssh",
"Comment": "docs-v0.8.2-2016-09-26-11-g91e368eb",
"Rev": "91e368eb7422665278b1d5665139ee0f9980b588"
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/libmachine/state",
"Comment": "docs-v0.8.2-2016-09-26-11-g91e368eb",
"Rev": "91e368eb7422665278b1d5665139ee0f9980b588"
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/libmachine/swarm",
"Comment": "docs-v0.8.2-2016-09-26-11-g91e368eb",
"Rev": "91e368eb7422665278b1d5665139ee0f9980b588"
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/libmachine/version",
"Comment": "docs-v0.8.2-2016-09-26-11-g91e368eb",
"Rev": "91e368eb7422665278b1d5665139ee0f9980b588"
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/version",
"Comment": "docs-v0.8.2-2016-09-26-11-g91e368eb",
"Rev": "91e368eb7422665278b1d5665139ee0f9980b588"
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/spdystream",
@ -6438,6 +6438,46 @@
{
"ImportPath": "k8s.io/metrics/pkg/client/custom_metrics",
"Rev": "fd2415bb9381a6731027b48a8c6b78f28e13f876"
},
{
"ImportPath": "github.com/docker/machine/vendor/github.com/docker/docker/pkg/term",
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/vendor/golang.org/x/crypto/ssh",
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/vendor/golang.org/x/crypto/ssh/terminal",
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/vendor/golang.org/x/crypto/curve25519",
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/vendor/golang.org/x/sys/windows/registry",
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/libmachine/versioncmp",
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/vendor/github.com/samalba/dockerclient",
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
},
{
"ImportPath": "github.com/docker/machine/vendor/github.com/docker/go-units",
"Comment": "docs-v0.8.2-2016-09-26-183-g07d63b6f",
"Rev": "07d63b6ff555ddec6f0458c5a4af3cc711aea75d"
}
]
}

View File

@ -428,7 +428,7 @@ func (d *Driver) generateDiskImage() (string, error) {
diskImage := d.ResolveStorePath("disk.vhd")
fixed := d.ResolveStorePath("fixed.vhd")
// Resizing vhds requires administrator priviledges
// Resizing vhds requires administrator privileges
// incase the user is only a hyper-v admin then create the disk at the target size to avoid resizing.
isWindowsAdmin, err := isWindowsAdministrator()
if err != nil {

View File

@ -140,13 +140,13 @@ func listHostOnlyAdapters(vbox VBoxManager) (map[string]*hostOnlyNetwork, error)
n.NetworkName = val
if _, present := byName[n.NetworkName]; present {
return fmt.Errorf("VirtualBox is configured with multiple host-only adapters with the same name %q. Please remove one.", n.NetworkName)
return fmt.Errorf("VirtualBox is configured with multiple host-only adapters with the same name %q. Please remove one", n.NetworkName)
}
byName[n.NetworkName] = n
if len(n.IPv4.IP) != 0 {
if _, present := byIP[n.IPv4.IP.String()]; present {
return fmt.Errorf("VirtualBox is configured with multiple host-only adapters with the same IP %q. Please remove one.", n.IPv4.IP)
return fmt.Errorf("VirtualBox is configured with multiple host-only adapters with the same IP %q. Please remove one", n.IPv4.IP)
}
byIP[n.IPv4.IP.String()] = n
}

View File

@ -69,6 +69,7 @@ type Driver struct {
NoShare bool
DNSProxy bool
NoVTXCheck bool
ShareFolder string
}
// NewDriver creates a new VirtualBox driver with default settings.
@ -190,6 +191,11 @@ func (d *Driver) GetCreateFlags() []mcnflag.Flag {
Usage: "Disable checking for the availability of hardware virtualization before the vm is started",
EnvVar: "VIRTUALBOX_NO_VTX_CHECK",
},
mcnflag.StringFlag{
EnvVar: "VIRTUALBOX_SHARE_FOLDER",
Name: "virtualbox-share-folder",
Usage: "Mount the specified directory instead of the default home location. Format: dir:name",
},
}
}
@ -242,6 +248,7 @@ func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error {
d.NoShare = flags.Bool("virtualbox-no-share")
d.DNSProxy = !flags.Bool("virtualbox-no-dns-proxy")
d.NoVTXCheck = flags.Bool("virtualbox-no-vtx-check")
d.ShareFolder = flags.String("virtualbox-share-folder")
return nil
}
@ -448,8 +455,12 @@ func (d *Driver) CreateVM() error {
shareName, shareDir := getShareDriveAndName()
if d.ShareFolder != "" {
shareDir, shareName = parseShareFolder(d.ShareFolder)
}
if shareDir != "" && !d.NoShare {
log.Debugf("setting up shareDir")
log.Debugf("setting up shareDir '%s' -> '%s'", shareDir, shareName)
if _, err := os.Stat(shareDir); err != nil && !os.IsNotExist(err) {
return err
} else if !os.IsNotExist(err) {
@ -475,6 +486,13 @@ func (d *Driver) CreateVM() error {
return nil
}
func parseShareFolder(shareFolder string) (string, string) {
split := strings.Split(shareFolder, ":")
shareDir := strings.Join(split[:len(split)-1], ":")
shareName := split[len(split)-1]
return shareDir, shareName
}
func (d *Driver) hostOnlyIPAvailable() bool {
ip, err := d.GetIP()
if err != nil {
@ -833,14 +851,15 @@ func (d *Driver) setupHostOnlyNetwork(machineName string) (*hostOnlyNetwork, err
return nil, err
}
log.Debugf("Adding/Modifying DHCP server %q...", dhcpAddr)
nAddr := network.IP.To4()
lowerIP, upperIP := getDHCPAddressRange(dhcpAddr, network)
log.Debugf("Adding/Modifying DHCP server %q with address range %q - %q...", dhcpAddr, lowerIP, upperIP)
dhcp := dhcpServer{}
dhcp.IPv4.IP = dhcpAddr
dhcp.IPv4.Mask = network.Mask
dhcp.LowerIP = net.IPv4(nAddr[0], nAddr[1], nAddr[2], byte(100))
dhcp.UpperIP = net.IPv4(nAddr[0], nAddr[1], nAddr[2], byte(254))
dhcp.LowerIP = lowerIP
dhcp.UpperIP = upperIP
dhcp.Enabled = !d.HostOnlyNoDHCP
if err := addHostOnlyDHCPServer(hostOnlyAdapter.Name, dhcp, d.VBoxManager); err != nil {
return nil, err
@ -858,6 +877,30 @@ func (d *Driver) setupHostOnlyNetwork(machineName string) (*hostOnlyNetwork, err
return hostOnlyAdapter, nil
}
func getDHCPAddressRange(dhcpAddr net.IP, network *net.IPNet) (lowerIP net.IP, upperIP net.IP) {
nAddr := network.IP.To4()
ones, bits := network.Mask.Size()
if ones <= 24 {
// For a /24 subnet, use the original behavior of allowing the address range
// between x.x.x.100 and x.x.x.254.
lowerIP = net.IPv4(nAddr[0], nAddr[1], nAddr[2], byte(100))
upperIP = net.IPv4(nAddr[0], nAddr[1], nAddr[2], byte(254))
return
}
// Start the lowerIP range one address above the selected DHCP address.
lowerIP = net.IPv4(nAddr[0], nAddr[1], nAddr[2], dhcpAddr.To4()[3]+1)
// The highest D-part of the address A.B.C.D in this subnet is at 2^n - 1,
// where n is the number of available bits in the subnet. Since the highest
// address is reserved for subnet broadcast, the highest *assignable* address
// is at (2^n - 1) - 1 == 2^n - 2.
maxAssignableSubnetAddress := (byte)((1 << (uint)(bits-ones)) - 2)
upperIP = net.IPv4(nAddr[0], nAddr[1], nAddr[2], maxAssignableSubnetAddress)
return
}
func parseAndValidateCIDR(hostOnlyCIDR string) (net.IP, *net.IPNet, error) {
ip, network, err := net.ParseCIDR(hostOnlyCIDR)
if err != nil {

View File

@ -0,0 +1,45 @@
package virtualbox
import (
"bytes"
"io/ioutil"
"github.com/docker/machine/libmachine/log"
)
// IsVTXDisabled checks if VT-X is disabled in the BIOS. If it is, the vm will fail to start.
// If we can't be sure it is disabled, we carry on and will check the vm logs after it's started.
// We want to check that either vmx or svm flags are present in /proc/cpuinfo.
func (d *Driver) IsVTXDisabled() bool {
cpuinfo, err := ioutil.ReadFile("/proc/cpuinfo")
if err != nil {
log.Debugf("Couldn't check that VT-X/AMD-v is enabled. Will check that the vm is properly created: %v", err)
return false
}
return isVTXDisabled(cpuinfo)
}
func isVTXDisabled(cpuinfo []byte) bool {
features := [2][]byte{
{'v', 'm', 'x'},
{'s', 'v', 'm'},
}
for _, v := range features {
if bytes.Contains(cpuinfo, v) {
return false
}
}
return true
}
func detectVBoxManageCmd() string {
return detectVBoxManageCmdInPath()
}
func getShareDriveAndName() (string, string) {
return "hosthome", "/home"
}
func isHyperVInstalled() bool {
return false
}

View File

@ -319,7 +319,7 @@ func (d *Driver) Create() error {
d.IPAddress = ip
// Do not execute the rest of boot2docker specific configuration
// The uplaod of the public ssh key uses a ssh connection,
// The upload of the public ssh key uses a ssh connection,
// this works without installed vmware client tools
if d.ConfigDriveURL != "" {
var keyfh *os.File
@ -564,7 +564,7 @@ func (d *Driver) getIPfromVmnetConfigurationFile(conffile, macaddr string) (stri
continue
}
// we are only in intressted in endings if we in a block. Otherwise we will count
// we are only in interested in endings if we in a block. Otherwise we will count
// ending of non host blocks as well
if matches := hostend.FindStringSubmatch(line); blockdepth > 0 && matches != nil {
blockdepth = blockdepth - 1

View File

@ -40,7 +40,7 @@ func BootstrapCertificates(authOptions *auth.Options) error {
// check if the key path exists; if so, error
if _, err := os.Stat(caPrivateKeyPath); err == nil {
return errors.New("The CA key already exists. Please remove it or specify a different key/cert.")
return errors.New("certificate authority key already exists")
}
if err := GenerateCACertificate(caCertPath, caPrivateKeyPath, caOrg, bits); err != nil {
@ -54,7 +54,7 @@ func BootstrapCertificates(authOptions *auth.Options) error {
if _, err := os.Stat(certDir); err != nil {
if os.IsNotExist(err) {
if err := os.Mkdir(certDir, 0700); err != nil {
return fmt.Errorf("Creating machine client cert dir failed: %s", err)
return fmt.Errorf("failure creating machine client cert dir: %s", err)
}
} else {
return err
@ -63,7 +63,7 @@ func BootstrapCertificates(authOptions *auth.Options) error {
// check if the key path exists; if so, error
if _, err := os.Stat(clientKeyPath); err == nil {
return errors.New("The client key already exists. Please remove it or specify a different key/cert.")
return errors.New("client key already exists")
}
// Used to generate the client certificate.
@ -79,7 +79,7 @@ func BootstrapCertificates(authOptions *auth.Options) error {
}
if err := GenerateCert(certOptions); err != nil {
return fmt.Errorf("Generating client certificate failed: %s", err)
return fmt.Errorf("failure generating client certificate: %s", err)
}
}

View File

@ -257,7 +257,7 @@ func (xcg *X509CertGenerator) ValidateCertificate(addr string, authOptions *auth
}
dialer := &net.Dialer{
Timeout: time.Second * 2,
Timeout: time.Second * 20,
}
_, err = tls.DialWithDialer(dialer, "tcp", addr, tlsConfig)

View File

@ -17,7 +17,7 @@ var (
// plugin server.
defaultTimeout = 10 * time.Second
CurrentBinaryIsDockerMachine = false
CoreDrivers = [...]string{"amazonec2", "azure", "digitalocean",
CoreDrivers = []string{"amazonec2", "azure", "digitalocean",
"exoscale", "generic", "google", "hyperv", "none", "openstack",
"rackspace", "softlayer", "virtualbox", "vmwarefusion",
"vmwarevcloudair", "vmwarevsphere"}
@ -85,10 +85,11 @@ type Executor struct {
type ErrPluginBinaryNotFound struct {
driverName string
driverPath string
}
func (e ErrPluginBinaryNotFound) Error() string {
return fmt.Sprintf("Driver %q not found. Do you have the plugin binary accessible in your PATH?", e.driverName)
return fmt.Sprintf("Driver %q not found. Do you have the plugin binary %q accessible in your PATH?", e.driverName, e.driverPath)
}
// driverPath finds the path of a driver binary by its name.
@ -114,7 +115,7 @@ func NewPlugin(driverName string) (*Plugin, error) {
driverPath := driverPath(driverName)
binaryPath, err := exec.LookPath(driverPath)
if err != nil {
return nil, ErrPluginBinaryNotFound{driverName}
return nil, ErrPluginBinaryNotFound{driverName, driverPath}
}
log.Debugf("Found binary path at %s", binaryPath)

View File

@ -213,10 +213,11 @@ func (c *RPCClientDriver) close() error {
log.Debug("Making call to close driver server")
if err := c.Client.Call(CloseMethod, struct{}{}, nil); err != nil {
return err
log.Debugf("Failed to make call to close driver server: %s", err)
} else {
log.Debug("Successfully made call to close driver server")
}
log.Debug("Successfully made call to close driver server")
log.Debug("Making call to close connection to plugin binary")
return c.plugin.Close()

View File

@ -44,11 +44,10 @@ func RunSSHCommandFromDriver(d Driver, command string) (string, error) {
output, err := client.Output(command)
log.Debugf("SSH cmd err, output: %v: %s", err, output)
if err != nil {
return "", fmt.Errorf(`Something went wrong running an SSH command!
return "", fmt.Errorf(`ssh command error:
command : %s
err : %v
output : %s
`, command, err, output)
output : %s`, command, err, output)
}
return output, nil

View File

@ -1,13 +1,13 @@
package host
import (
"errors"
"regexp"
"github.com/docker/machine/libmachine/auth"
"github.com/docker/machine/libmachine/drivers"
"github.com/docker/machine/libmachine/engine"
"github.com/docker/machine/libmachine/log"
"github.com/docker/machine/libmachine/mcndockerclient"
"github.com/docker/machine/libmachine/mcnerror"
"github.com/docker/machine/libmachine/mcnutils"
"github.com/docker/machine/libmachine/provision"
@ -16,12 +16,12 @@ import (
"github.com/docker/machine/libmachine/ssh"
"github.com/docker/machine/libmachine/state"
"github.com/docker/machine/libmachine/swarm"
"github.com/docker/machine/libmachine/versioncmp"
)
var (
validHostNamePattern = regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9\-\.]*$`)
errMachineMustBeRunningForUpgrade = errors.New("Error: machine must be running to upgrade.")
stdSSHClientCreator SSHClientCreator = &StandardSSHClientCreator{}
validHostNamePattern = regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9\-\.]*$`)
stdSSHClientCreator SSHClientCreator = &StandardSSHClientCreator{}
)
type SSHClientCreator interface {
@ -164,6 +164,24 @@ func (h *Host) Restart() error {
return h.WaitForDocker()
}
func (h *Host) DockerVersion() (string, error) {
url, err := h.Driver.GetURL()
if err != nil {
return "", err
}
dockerHost := &mcndockerclient.RemoteDocker{
HostURL: url,
AuthOption: h.AuthOptions(),
}
dockerVersion, err := mcndockerclient.DockerVersion(dockerHost)
if err != nil {
return "", err
}
return dockerVersion, nil
}
func (h *Host) Upgrade() error {
machineState, err := h.Driver.GetState()
if err != nil {
@ -171,7 +189,10 @@ func (h *Host) Upgrade() error {
}
if machineState != state.Running {
return errMachineMustBeRunningForUpgrade
log.Info("Starting machine so machine can be upgraded...")
if err := h.Start(); err != nil {
return err
}
}
provisioner, err := provision.DetectProvisioner(h.Driver)
@ -179,6 +200,39 @@ func (h *Host) Upgrade() error {
return err
}
dockerVersion, err := h.DockerVersion()
if err != nil {
return err
}
// If we're upgrading from a pre-CE (e.g., 1.13.1) release to a CE
// release (e.g., 17.03.0-ce), we should simply uninstall and
// re-install from scratch, since the official package names will
// change from 'docker-engine' to 'docker-ce'.
if versioncmp.LessThanOrEqualTo(dockerVersion, provision.LastReleaseBeforeCEVersioning) &&
// RancherOS and boot2docker, being 'static ISO builds', have
// an upgrade process which simply grabs the latest if it's
// different, and so do not need to jump through this hoop to
// upgrade safely.
provisioner.String() != "rancheros" &&
provisioner.String() != "boot2docker" {
// Name of pacakge 'docker-engine' will fall through in this
// case, so that we execute, e.g.,
//
// 'sudo apt-get purge -y docker-engine'
if err := provisioner.Package("docker-engine", pkgaction.Purge); err != nil {
return err
}
// Then we kick off the normal provisioning process which will
// go off and install Docker (get.docker.com script should work
// fine to install Docker from scratch after removing the old
// packages, and images/containers etc. should be preserved in
// /var/lib/docker)
return h.Provision()
}
log.Info("Upgrading docker...")
if err := provisioner.Package("docker", pkgaction.Upgrade); err != nil {
return err

View File

@ -12,7 +12,7 @@ import (
)
var (
errConfigFromFuture = errors.New("Config version is from the future, please upgrade your Docker Machine client.")
errConfigFromFuture = errors.New("config version is from the future -- you should upgrade your Docker Machine client")
)
type RawDataDriver struct {

View File

@ -33,8 +33,7 @@ var (
)
var (
errGitHubAPIResponse = errors.New(`Error getting a version tag from the Github API response.
You may be getting rate limited by Github.`)
errGitHubAPIResponse = errors.New(`failure getting a version tag from the Github API response (are you getting rate limited by Github?)`)
)
var (

View File

@ -43,16 +43,16 @@ func (provisioner *ArchProvisioner) Package(name string, action pkgaction.Packag
updateMetadata := true
switch action {
case pkgaction.Install:
case pkgaction.Install, pkgaction.Upgrade:
packageAction = "S"
case pkgaction.Remove:
packageAction = "R"
updateMetadata = false
case pkgaction.Upgrade:
packageAction = "U"
}
switch name {
case "docker-engine":
name = "docker"
case "docker":
name = "docker"
}

View File

@ -11,6 +11,7 @@ import (
"github.com/docker/machine/libmachine/log"
"github.com/docker/machine/libmachine/provision/pkgaction"
"github.com/docker/machine/libmachine/swarm"
"github.com/docker/machine/libmachine/versioncmp"
)
const (
@ -64,22 +65,21 @@ func (provisioner *CoreOSProvisioner) GenerateDockerOptions(dockerPort int) (*Do
driverNameLabel := fmt.Sprintf("provider=%s", provisioner.Driver.DriverName())
provisioner.EngineOptions.Labels = append(provisioner.EngineOptions.Labels, driverNameLabel)
engineConfigTmpl := `[Unit]
Description=Docker Socket for the API
After=docker.socket early-docker.target network.target
Requires=docker.socket early-docker.target
dockerVersion, err := DockerClientVersion(provisioner)
if err != nil {
return nil, err
}
[Service]
arg := "daemon"
if versioncmp.GreaterThanOrEqualTo(dockerVersion, "1.12.0") {
arg = ""
}
engineConfigTmpl := `[Service]
Environment=TMPDIR=/var/tmp
EnvironmentFile=-/run/flannel_docker_opts.env
MountFlags=slave
LimitNOFILE=1048576
LimitNPROC=1048576
ExecStart=/usr/lib/coreos/dockerd daemon --host=unix:///var/run/docker.sock --host=tcp://0.0.0.0:{{.DockerPort}} --tlsverify --tlscacert {{.AuthOptions.CaCertRemotePath}} --tlscert {{.AuthOptions.ServerCertRemotePath}} --tlskey {{.AuthOptions.ServerKeyRemotePath}}{{ range .EngineOptions.Labels }} --label {{.}}{{ end }}{{ range .EngineOptions.InsecureRegistry }} --insecure-registry {{.}}{{ end }}{{ range .EngineOptions.RegistryMirror }} --registry-mirror {{.}}{{ end }}{{ range .EngineOptions.ArbitraryFlags }} --{{.}}{{ end }} \$DOCKER_OPTS \$DOCKER_OPT_BIP \$DOCKER_OPT_MTU \$DOCKER_OPT_IPMASQ
ExecStart=
ExecStart=/usr/lib/coreos/dockerd ` + arg + ` --host=unix:///var/run/docker.sock --host=tcp://0.0.0.0:{{.DockerPort}} --tlsverify --tlscacert {{.AuthOptions.CaCertRemotePath}} --tlscert {{.AuthOptions.ServerCertRemotePath}} --tlskey {{.AuthOptions.ServerKeyRemotePath}}{{ range .EngineOptions.Labels }} --label {{.}}{{ end }}{{ range .EngineOptions.InsecureRegistry }} --insecure-registry {{.}}{{ end }}{{ range .EngineOptions.RegistryMirror }} --registry-mirror {{.}}{{ end }}{{ range .EngineOptions.ArbitraryFlags }} --{{.}}{{ end }} \$DOCKER_OPTS \$DOCKER_OPT_BIP \$DOCKER_OPT_MTU \$DOCKER_OPT_IPMASQ
Environment={{range .EngineOptions.Env}}{{ printf "%q" . }} {{end}}
[Install]
WantedBy=multi-user.target
`
t, err := template.New("engineConfig").Parse(engineConfigTmpl)

View File

@ -44,6 +44,9 @@ func (provisioner *DebianProvisioner) Package(name string, action pkgaction.Pack
case pkgaction.Remove:
packageAction = "remove"
updateMetadata = false
case pkgaction.Purge:
packageAction = "purge"
updateMetadata = false
}
switch name {
@ -52,7 +55,7 @@ func (provisioner *DebianProvisioner) Package(name string, action pkgaction.Pack
}
if updateMetadata {
if _, err := provisioner.SSHCommand("sudo apt-get update"); err != nil {
if err := waitForLockAptGetUpdate(provisioner); err != nil {
return err
}
}

View File

@ -6,12 +6,14 @@ const (
Install PackageAction = iota
Remove
Upgrade
Purge
)
var packageActions = []string{
"install",
"remove",
"upgrade",
"purge",
}
func (s PackageAction) String() string {

View File

@ -17,6 +17,10 @@ var (
detector Detector = &StandardDetector{}
)
const (
LastReleaseBeforeCEVersioning = "1.13.1"
)
type SSHCommander interface {
// Short-hand for accessing an SSH command from the driver.
SSHCommand(args string) (string, error)

View File

@ -19,35 +19,11 @@ import (
var (
ErrUnknownYumOsRelease = errors.New("unknown OS for Yum repository")
packageListTemplate = `[docker]
name=Docker Stable Repository
baseurl=https://yum.dockerproject.org/repo/main/{{.OsRelease}}/{{.OsReleaseVersion}}
priority=1
enabled=1
gpgkey=https://yum.dockerproject.org/gpg
`
engineConfigTemplate = `[Unit]
Description=Docker Application Container Engine
After=network.target
[Service]
Type=notify
ExecStart=/usr/bin/docker daemon -H tcp://0.0.0.0:{{.DockerPort}} -H unix:///var/run/docker.sock --storage-driver {{.EngineOptions.StorageDriver}} --tlsverify --tlscacert {{.AuthOptions.CaCertRemotePath}} --tlscert {{.AuthOptions.ServerCertRemotePath}} --tlskey {{.AuthOptions.ServerKeyRemotePath}} {{ range .EngineOptions.Labels }}--label {{.}} {{ end }}{{ range .EngineOptions.InsecureRegistry }}--insecure-registry {{.}} {{ end }}{{ range .EngineOptions.RegistryMirror }}--registry-mirror {{.}} {{ end }}{{ range .EngineOptions.ArbitraryFlags }}--{{.}} {{ end }}
ExecReload=/bin/kill -s HUP $MAINPID
MountFlags=slave
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TimeoutStartSec=0
Delegate=yes
KillMode=process
engineConfigTemplate = `[Service]
ExecStart=
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:{{.DockerPort}} -H unix:///var/run/docker.sock --storage-driver {{.EngineOptions.StorageDriver}} --tlsverify --tlscacert {{.AuthOptions.CaCertRemotePath}} --tlscert {{.AuthOptions.ServerCertRemotePath}} --tlskey {{.AuthOptions.ServerKeyRemotePath}} {{ range .EngineOptions.Labels }}--label {{.}} {{ end }}{{ range .EngineOptions.InsecureRegistry }}--insecure-registry {{.}} {{ end }}{{ range .EngineOptions.RegistryMirror }}--registry-mirror {{.}} {{ end }}{{ range .EngineOptions.ArbitraryFlags }}--{{.}} {{ end }}
Environment={{range .EngineOptions.Env}}{{ printf "%q" . }} {{end}}
[Install]
WantedBy=multi-user.target
`
majorVersionRE = regexp.MustCompile(`^(\d+)(\..*)?`)
)
@ -91,7 +67,6 @@ func (provisioner *RedHatProvisioner) SetHostname(hostname string) error {
return err
}
// ubuntu/debian use 127.0.1.1 for non "localhost" loopback hostnames: https://www.debian.org/doc/manuals/debian-reference/ch05.en.html#_the_hostname_resolution
if _, err := provisioner.SSHCommand(fmt.Sprintf(
"if grep -xq 127.0.1.1.* /etc/hosts; then sudo sed -i 's/^127.0.1.1.*/127.0.1.1 %s/g' /etc/hosts; else echo '127.0.1.1 %s' | sudo tee -a /etc/hosts; fi",
hostname,
@ -111,6 +86,8 @@ func (provisioner *RedHatProvisioner) Package(name string, action pkgaction.Pack
packageAction = "install"
case pkgaction.Remove:
packageAction = "remove"
case pkgaction.Purge:
packageAction = "remove"
case pkgaction.Upgrade:
packageAction = "upgrade"
}
@ -178,7 +155,7 @@ func (provisioner *RedHatProvisioner) Provision(swarmOptions swarm.Options, auth
}
// update OS -- this is needed for libdevicemapper and the docker install
if _, err := provisioner.SSHCommand("sudo -E yum -y update"); err != nil {
if _, err := provisioner.SSHCommand("sudo -E yum -y update -x docker-*"); err != nil {
return err
}

View File

@ -35,11 +35,10 @@ func (sshCmder RedHatSSHCommander) SSHCommand(args string) (string, error) {
log.Debugf("SSH cmd err, output: %v: %s", err, output)
if err != nil {
return "", fmt.Errorf(`Something went wrong running an SSH command!
return "", fmt.Errorf(`something went wrong running an SSH command
command : %s
err : %v
output : %s
`, args, err, output)
output : %s`, args, err, output)
}
return output, nil

View File

@ -1,9 +1,8 @@
package provision
import (
"bytes"
"fmt"
"text/template"
"strings"
"github.com/docker/machine/libmachine/auth"
"github.com/docker/machine/libmachine/drivers"
@ -27,82 +26,34 @@ func init() {
})
}
func NewOpenSUSEProvisioner(d drivers.Driver) Provisioner {
return &SUSEProvisioner{
GenericProvisioner{
SSHCommander: GenericSSHCommander{Driver: d},
DockerOptionsDir: "/etc/docker",
DaemonOptionsFile: "/etc/sysconfig/docker",
OsReleaseID: "opensuse",
Packages: []string{
"curl",
},
Driver: d,
},
}
}
func NewSLEDProvisioner(d drivers.Driver) Provisioner {
return &SUSEProvisioner{
GenericProvisioner{
SSHCommander: GenericSSHCommander{Driver: d},
DockerOptionsDir: "/etc/docker",
DaemonOptionsFile: "/etc/sysconfig/docker",
OsReleaseID: "sled",
Packages: []string{
"curl",
},
Driver: d,
},
NewSystemdProvisioner("sled", d),
}
}
func NewSLESProvisioner(d drivers.Driver) Provisioner {
return &SUSEProvisioner{
GenericProvisioner{
SSHCommander: GenericSSHCommander{Driver: d},
DockerOptionsDir: "/etc/docker",
DaemonOptionsFile: "/etc/sysconfig/docker",
OsReleaseID: "sles",
Packages: []string{
"curl",
},
Driver: d,
},
NewSystemdProvisioner("sles", d),
}
}
func NewOpenSUSEProvisioner(d drivers.Driver) Provisioner {
return &SUSEProvisioner{
NewSystemdProvisioner("openSUSE", d),
}
}
type SUSEProvisioner struct {
GenericProvisioner
SystemdProvisioner
}
func (provisioner *SUSEProvisioner) CompatibleWithHost() bool {
return strings.ToLower(provisioner.OsReleaseInfo.ID) == strings.ToLower(provisioner.OsReleaseID)
}
func (provisioner *SUSEProvisioner) String() string {
return "suse"
}
func (provisioner *SUSEProvisioner) Service(name string, action serviceaction.ServiceAction) error {
reloadDaemon := false
switch action {
case serviceaction.Start, serviceaction.Restart:
reloadDaemon = true
}
// systemd needs reloaded when config changes on disk; we cannot
// be sure exactly when it changes from the provisioner so
// we call a reload on every restart to be safe
if reloadDaemon {
if _, err := provisioner.SSHCommand("sudo systemctl daemon-reload"); err != nil {
return err
}
}
command := fmt.Sprintf("sudo systemctl %s %s", action.String(), name)
if _, err := provisioner.SSHCommand(command); err != nil {
return err
}
return nil
return "openSUSE"
}
func (provisioner *SUSEProvisioner) Package(name string, action pkgaction.PackageAction) error {
@ -110,15 +61,17 @@ func (provisioner *SUSEProvisioner) Package(name string, action pkgaction.Packag
switch action {
case pkgaction.Install:
packageAction = "install"
packageAction = "in"
case pkgaction.Remove:
packageAction = "remove"
packageAction = "rm"
case pkgaction.Upgrade:
packageAction = "upgrade"
packageAction = "up"
}
command := fmt.Sprintf("sudo -E zypper -n %s %s", packageAction, name)
log.Debugf("zypper: action=%s name=%s", action.String(), name)
if _, err := provisioner.SSHCommand(command); err != nil {
return err
}
@ -145,96 +98,97 @@ func (provisioner *SUSEProvisioner) Provision(swarmOptions swarm.Options, authOp
provisioner.EngineOptions = engineOptions
swarmOptions.Env = engineOptions.Env
// figure out the filesystem used by /var/lib
fs, err := provisioner.SSHCommand("stat -f -c %T /var/lib/")
if err != nil {
return err
}
graphDriver := "overlay"
if strings.Contains(fs, "btrfs") {
graphDriver = "btrfs"
}
storageDriver, err := decideStorageDriver(provisioner, graphDriver, engineOptions.StorageDriver)
if err != nil {
return err
}
provisioner.EngineOptions.StorageDriver = storageDriver
log.Debug("Setting hostname")
if err := provisioner.SetHostname(provisioner.Driver.GetMachineName()); err != nil {
return err
}
if strings.ToLower(provisioner.OsReleaseInfo.ID) != "opensuse" {
// This is a SLE machine, enable the containers module to have access
// to the docker packages
if _, err := provisioner.SSHCommand("sudo -E SUSEConnect -p sle-module-containers/12/$(uname -m) -r ''"); err != nil {
return fmt.Errorf(
"Error while adding the 'containers' module, make sure this machine is registered either against SUSE Customer Center (SCC) or to a local Subscription Management Tool (SMT): %v",
err)
}
}
log.Debug("Installing base packages")
for _, pkg := range provisioner.Packages {
if err := provisioner.Package(pkg, pkgaction.Install); err != nil {
return err
}
}
// update OS -- this is needed for libdevicemapper and the docker install
if _, err := provisioner.SSHCommand("sudo zypper ref"); err != nil {
return err
}
if _, err := provisioner.SSHCommand("sudo zypper -n update"); err != nil {
log.Debug("Installing docker")
if err := provisioner.Package("docker", pkgaction.Install); err != nil {
return err
}
if err := installDockerGeneric(provisioner, engineOptions.InstallURL); err != nil {
// create symlinks for containerd, containerd-shim and runc.
// We have to do that because machine overrides the openSUSE systemd
// unit of docker
if _, err := provisioner.SSHCommand("sudo -E ln -s /usr/sbin/runc /usr/sbin/docker-runc"); err != nil {
return err
}
if _, err := provisioner.SSHCommand("sudo -E ln -s /usr/sbin/containerd /usr/sbin/docker-containerd"); err != nil {
return err
}
if _, err := provisioner.SSHCommand("sudo -E ln -s /usr/sbin/containerd-shim /usr/sbin/docker-containerd-shim"); err != nil {
return err
}
if _, err := provisioner.SSHCommand("sudo systemctl start docker"); err != nil {
// Is yast2 firewall installed?
if _, installed := provisioner.SSHCommand("rpm -q yast2-firewall"); installed == nil {
// Open the firewall port required by docker
if _, err := provisioner.SSHCommand("sudo -E /sbin/yast2 firewall services add ipprotocol=tcp tcpport=2376 zone=EXT"); err != nil {
return err
}
}
log.Debug("Starting systemd docker service")
if err := provisioner.Service("docker", serviceaction.Start); err != nil {
return err
}
log.Debug("Waiting for docker daemon")
if err := mcnutils.WaitFor(provisioner.dockerDaemonResponding); err != nil {
return err
}
if _, err := provisioner.SSHCommand("sudo systemctl stop docker"); err != nil {
return err
}
// open firewall port required by docker
if _, err := provisioner.SSHCommand("sudo /sbin/yast2 firewall services add ipprotocol=tcp tcpport=2376 zone=EXT"); err != nil {
return err
}
if err := makeDockerOptionsDir(provisioner); err != nil {
return err
}
provisioner.AuthOptions = setRemoteAuthOptions(provisioner)
log.Debug("Configuring auth")
if err := ConfigureAuth(provisioner); err != nil {
return err
}
log.Debug("Configuring swarm")
if err := configureSwarm(provisioner, swarmOptions, provisioner.AuthOptions); err != nil {
return err
}
// enable in systemd
log.Debug("Enabling docker in systemd")
if err := provisioner.Service("docker", serviceaction.Enable); err != nil {
return err
}
return nil
}
func (provisioner *SUSEProvisioner) GenerateDockerOptions(dockerPort int) (*DockerOptions, error) {
var (
engineCfg bytes.Buffer
configPath = provisioner.DaemonOptionsFile
)
// remove existing
if _, err := provisioner.SSHCommand(fmt.Sprintf("sudo rm %s", configPath)); err != nil {
return nil, err
}
driverNameLabel := fmt.Sprintf("provider=%s", provisioner.Driver.DriverName())
provisioner.EngineOptions.Labels = append(provisioner.EngineOptions.Labels, driverNameLabel)
engineConfigTmpl := `# File automatically generated by docker-machine
DOCKER_OPTS=' -H tcp://0.0.0.0:{{.DockerPort}} {{ if .EngineOptions.StorageDriver }} --storage-driver {{.EngineOptions.StorageDriver}} {{ end }} --tlsverify --tlscacert {{.AuthOptions.CaCertRemotePath}} --tlscert {{.AuthOptions.ServerCertRemotePath}} --tlskey {{.AuthOptions.ServerKeyRemotePath}} {{ range .EngineOptions.Labels }}--label {{.}} {{ end }}{{ range .EngineOptions.InsecureRegistry }}--insecure-registry {{.}} {{ end }}{{ range .EngineOptions.RegistryMirror }}--registry-mirror {{.}} {{ end }}{{ range .EngineOptions.ArbitraryFlags }}--{{.}} {{ end }}'
`
t, err := template.New("engineConfig").Parse(engineConfigTmpl)
if err != nil {
return nil, err
}
engineConfigContext := EngineConfigContext{
DockerPort: dockerPort,
AuthOptions: provisioner.AuthOptions,
EngineOptions: provisioner.EngineOptions,
DockerOptionsDir: provisioner.DockerOptionsDir,
}
t.Execute(&engineCfg, engineConfigContext)
daemonOptsDir := configPath
return &DockerOptions{
EngineOptions: engineCfg.String(),
EngineOptionsPath: daemonOptsDir,
}, nil
}

View File

@ -7,6 +7,7 @@ import (
"github.com/docker/machine/libmachine/drivers"
"github.com/docker/machine/libmachine/provision/serviceaction"
"github.com/docker/machine/libmachine/versioncmp"
)
type SystemdProvisioner struct {
@ -22,7 +23,7 @@ func NewSystemdProvisioner(osReleaseID string, d drivers.Driver) SystemdProvisio
GenericProvisioner{
SSHCommander: GenericSSHCommander{Driver: d},
DockerOptionsDir: "/etc/docker",
DaemonOptionsFile: "/etc/systemd/system/docker.service",
DaemonOptionsFile: "/etc/systemd/system/docker.service.d/10-machine.conf",
OsReleaseID: osReleaseID,
Packages: []string{
"curl",
@ -40,16 +41,20 @@ func (p *SystemdProvisioner) GenerateDockerOptions(dockerPort int) (*DockerOptio
driverNameLabel := fmt.Sprintf("provider=%s", p.Driver.DriverName())
p.EngineOptions.Labels = append(p.EngineOptions.Labels, driverNameLabel)
engineConfigTmpl := `[Service]
ExecStart=/usr/bin/docker daemon -H tcp://0.0.0.0:{{.DockerPort}} -H unix:///var/run/docker.sock --storage-driver {{.EngineOptions.StorageDriver}} --tlsverify --tlscacert {{.AuthOptions.CaCertRemotePath}} --tlscert {{.AuthOptions.ServerCertRemotePath}} --tlskey {{.AuthOptions.ServerKeyRemotePath}} {{ range .EngineOptions.Labels }}--label {{.}} {{ end }}{{ range .EngineOptions.InsecureRegistry }}--insecure-registry {{.}} {{ end }}{{ range .EngineOptions.RegistryMirror }}--registry-mirror {{.}} {{ end }}{{ range .EngineOptions.ArbitraryFlags }}--{{.}} {{ end }}
MountFlags=slave
LimitNOFILE=1048576
LimitNPROC=1048576
LimitCORE=infinity
Environment={{range .EngineOptions.Env}}{{ printf "%q" . }} {{end}}
dockerVersion, err := DockerClientVersion(p)
if err != nil {
return nil, err
}
[Install]
WantedBy=multi-user.target
arg := "dockerd"
if versioncmp.LessThan(dockerVersion, "1.12.0") {
arg = "docker daemon"
}
engineConfigTmpl := `[Service]
ExecStart=
ExecStart=/usr/bin/` + arg + ` -H tcp://0.0.0.0:{{.DockerPort}} -H unix:///var/run/docker.sock --storage-driver {{.EngineOptions.StorageDriver}} --tlsverify --tlscacert {{.AuthOptions.CaCertRemotePath}} --tlscert {{.AuthOptions.ServerCertRemotePath}} --tlskey {{.AuthOptions.ServerKeyRemotePath}} {{ range .EngineOptions.Labels }}--label {{.}} {{ end }}{{ range .EngineOptions.InsecureRegistry }}--insecure-registry {{.}} {{ end }}{{ range .EngineOptions.RegistryMirror }}--registry-mirror {{.}} {{ end }}{{ range .EngineOptions.ArbitraryFlags }}--{{.}} {{ end }}
Environment={{range .EngineOptions.Env}}{{ printf "%q" . }} {{end}}
`
t, err := template.New("engineConfig").Parse(engineConfigTmpl)
if err != nil {

View File

@ -60,15 +60,18 @@ func (provisioner *UbuntuSystemdProvisioner) Package(name string, action pkgacti
case pkgaction.Remove:
packageAction = "remove"
updateMetadata = false
case pkgaction.Purge:
packageAction = "purge"
updateMetadata = false
}
switch name {
case "docker":
name = "docker-engine"
name = "docker-ce"
}
if updateMetadata {
if _, err := provisioner.SSHCommand("sudo apt-get update"); err != nil {
if err := waitForLockAptGetUpdate(provisioner); err != nil {
return err
}
}

View File

@ -87,7 +87,7 @@ func (provisioner *UbuntuProvisioner) Package(name string, action pkgaction.Pack
}
if updateMetadata {
if _, err := provisioner.SSHCommand("sudo apt-get update"); err != nil {
if err := waitForLockAptGetUpdate(provisioner); err != nil {
return err
}
}

View File

@ -28,7 +28,7 @@ func installDockerGeneric(p Provisioner, baseURL string) error {
// install docker - until cloudinit we use ubuntu everywhere so we
// just install it using the docker repos
if output, err := p.SSHCommand(fmt.Sprintf("if ! type docker; then curl -sSL %s | sh -; fi", baseURL)); err != nil {
return fmt.Errorf("error installing docker: %s\n", output)
return fmt.Errorf("error installing docker: %s", output)
}
return nil
@ -181,7 +181,7 @@ func ConfigureAuth(p Provisioner) error {
log.Info("Setting Docker configuration on the remote daemon...")
if _, err = p.SSHCommand(fmt.Sprintf("printf %%s \"%s\" | sudo tee %s", dkrcfg.EngineOptions, dkrcfg.EngineOptionsPath)); err != nil {
if _, err = p.SSHCommand(fmt.Sprintf("sudo mkdir -p %s && printf %%s \"%s\" | sudo tee %s", path.Dir(dkrcfg.EngineOptionsPath), dkrcfg.EngineOptions, dkrcfg.EngineOptionsPath)); err != nil {
return err
}
@ -272,3 +272,47 @@ func WaitForDocker(p Provisioner, dockerPort int) error {
return nil
}
// DockerClientVersion returns the version of the Docker client on the host
// that ssh is connected to, e.g. "1.12.1".
func DockerClientVersion(ssh SSHCommander) (string, error) {
// `docker version --format {{.Client.Version}}` would be preferable, but
// that fails if the server isn't running yet.
//
// output is expected to be something like
//
// Docker version 1.12.1, build 7a86f89
output, err := ssh.SSHCommand("docker --version")
if err != nil {
return "", err
}
words := strings.Fields(output)
if len(words) < 3 || words[0] != "Docker" || words[1] != "version" {
return "", fmt.Errorf("DockerClientVersion: cannot parse version string from %q", output)
}
return strings.TrimRight(words[2], ","), nil
}
func waitForLockAptGetUpdate(ssh SSHCommander) error {
var sshErr error
err := mcnutils.WaitFor(func() bool {
_, sshErr = ssh.SSHCommand("sudo apt-get update")
if sshErr != nil {
if strings.Contains(sshErr.Error(), "Could not get lock") {
sshErr = nil
return false
}
return true
}
return true
})
if sshErr != nil {
return fmt.Errorf("Error running apt-get update: %s", sshErr)
}
if err != nil {
return fmt.Errorf("Failed to obtain apt-get update lock: %s", err)
}
return nil
}

View File

@ -46,6 +46,7 @@ type NativeClient struct {
Hostname string
Port int
openSession *ssh.Session
openClient *ssh.Client
}
type Auth struct {
@ -156,43 +157,49 @@ func NewNativeConfig(user string, auth *Auth) (ssh.ClientConfig, error) {
}
func (client *NativeClient) dialSuccess() bool {
if _, err := ssh.Dial("tcp", net.JoinHostPort(client.Hostname, strconv.Itoa(client.Port)), &client.Config); err != nil {
conn, err := ssh.Dial("tcp", net.JoinHostPort(client.Hostname, strconv.Itoa(client.Port)), &client.Config)
if err != nil {
log.Debugf("Error dialing TCP: %s", err)
return false
}
closeConn(conn)
return true
}
func (client *NativeClient) session(command string) (*ssh.Session, error) {
func (client *NativeClient) session(command string) (*ssh.Client, *ssh.Session, error) {
if err := mcnutils.WaitFor(client.dialSuccess); err != nil {
return nil, fmt.Errorf("Error attempting SSH client dial: %s", err)
return nil, nil, fmt.Errorf("Error attempting SSH client dial: %s", err)
}
conn, err := ssh.Dial("tcp", net.JoinHostPort(client.Hostname, strconv.Itoa(client.Port)), &client.Config)
if err != nil {
return nil, fmt.Errorf("Mysterious error dialing TCP for SSH (we already succeeded at least once) : %s", err)
return nil, nil, fmt.Errorf("Mysterious error dialing TCP for SSH (we already succeeded at least once) : %s", err)
}
session, err := conn.NewSession()
return conn.NewSession()
return conn, session, err
}
func (client *NativeClient) Output(command string) (string, error) {
session, err := client.session(command)
conn, session, err := client.session(command)
if err != nil {
return "", nil
}
defer closeConn(conn)
defer session.Close()
output, err := session.CombinedOutput(command)
defer session.Close()
return string(output), err
}
func (client *NativeClient) OutputWithPty(command string) (string, error) {
session, err := client.session(command)
conn, session, err := client.session(command)
if err != nil {
return "", nil
}
defer closeConn(conn)
defer session.Close()
fd := int(os.Stdin.Fd())
@ -214,13 +221,12 @@ func (client *NativeClient) OutputWithPty(command string) (string, error) {
}
output, err := session.CombinedOutput(command)
defer session.Close()
return string(output), err
}
func (client *NativeClient) Start(command string) (io.ReadCloser, io.ReadCloser, error) {
session, err := client.session(command)
conn, session, err := client.session(command)
if err != nil {
return nil, nil, err
}
@ -237,15 +243,27 @@ func (client *NativeClient) Start(command string) (io.ReadCloser, io.ReadCloser,
return nil, nil, err
}
client.openClient = conn
client.openSession = session
return ioutil.NopCloser(stdout), ioutil.NopCloser(stderr), nil
}
func (client *NativeClient) Wait() error {
err := client.openSession.Wait()
if err != nil {
return err
}
_ = client.openSession.Close()
err = client.openClient.Close()
if err != nil {
return err
}
client.openSession = nil
return err
client.openClient = nil
return nil
}
func (client *NativeClient) Shell(args ...string) error {
@ -256,6 +274,7 @@ func (client *NativeClient) Shell(args ...string) error {
if err != nil {
return err
}
defer closeConn(conn)
session, err := conn.NewSession()
if err != nil {
@ -414,3 +433,10 @@ func (client *ExternalClient) Wait() error {
client.cmd = nil
return err
}
func closeConn(c io.Closer) {
err := c.Close()
if err != nil {
log.Debugf("Error closing SSH Client: %s", err)
}
}

View File

@ -82,7 +82,7 @@ func (kp *KeyPair) WriteToFile(privateKeyPath string, publicKeyPath string) erro
// windows does not support chmod
switch runtime.GOOS {
case "darwin", "linux":
case "darwin", "linux", "freebsd":
if err := f.Chmod(0600); err != nil {
return err
}

View File

@ -0,0 +1,121 @@
// Package versioncmp provides functions for comparing version strings.
//
// Version strings are dot-separated integers with an optional
// pre-release suffix. A pre-release suffix is an arbitrary string with a
// leading dash character. All functions ignore these suffixes, so "1.2" and
// "1.2-rc" are considered equivalent.
package versioncmp
import (
"strconv"
"strings"
)
const (
rcString = "-rc"
ceEdition = "-ce"
)
// compare compares two versions of Docker to decipher which came first.
//
// compare returns -1 if v1 < v2, 1 if v1 > v2, 0 otherwise.
func compare(v1, v2 string) int {
// Replace RC string with "." to make the RC number appear as simply
// another sub-version.
v1 = strings.Replace(v1, rcString, ".", -1)
v2 = strings.Replace(v2, rcString, ".", -1)
// All releases before the community edition (differentiated by
// presence of the "ce" string in the version string) are "less than"
// any community edition release (first occuring in March 2017).
if strings.Contains(v1, ceEdition) && !strings.Contains(v2, ceEdition) {
return -1
}
if !strings.Contains(v1, ceEdition) && strings.Contains(v2, ceEdition) {
return 1
}
// Without this tag, both are pre-CE versions.
if !strings.Contains(v1, ceEdition) && !strings.Contains(v2, ceEdition) {
return compareNumeric(v1, v2)
}
return compareCE(v1, v2)
}
// compareCE ("Community Edition") will differentiate between versions of
// Docker that use the versioning scheme
// {{release-year}}.{{release-month}}-{{ce|ee}}-{{rcnum|""}}
//
// This will be every release after 1.13.1.
func compareCE(v1, v2 string) int {
return compareNumeric(
strings.Replace(v1, ceEdition, "", -1),
strings.Replace(v2, ceEdition, "", -1),
)
}
// compareNumeric compares two version that use pre-17.03 Docker.
//
// Non-numeric segments in either argument are considered equal, so
// compare("1.a", "1.b") == 0, but compare("2.a", "1.b") == 1.
func compareNumeric(v1, v2 string) int {
if n := strings.IndexByte(v1, '-'); n != -1 {
v1 = v1[:n]
}
if n := strings.IndexByte(v2, '-'); n != -1 {
v2 = v2[:n]
}
var (
currTab = strings.Split(v1, ".")
otherTab = strings.Split(v2, ".")
)
max := len(currTab)
if len(otherTab) > max {
max = len(otherTab)
}
for i := 0; i < max; i++ {
var currInt, otherInt int
if len(currTab) > i {
currInt, _ = strconv.Atoi(currTab[i])
}
if len(otherTab) > i {
otherInt, _ = strconv.Atoi(otherTab[i])
}
if currInt > otherInt {
return 1
}
if otherInt > currInt {
return -1
}
}
return 0
}
// LessThan checks if a version is less than another.
func LessThan(v, other string) bool {
return compare(v, other) == -1
}
// LessThanOrEqualTo checks if a version is less than or equal to another.
func LessThanOrEqualTo(v, other string) bool {
return compare(v, other) <= 0
}
// GreaterThan checks if a version is greater than another.
func GreaterThan(v, other string) bool {
return compare(v, other) == 1
}
// GreaterThanOrEqualTo checks if a version is greater than or equal to
// another.
func GreaterThanOrEqualTo(v, other string) bool {
return compare(v, other) >= 0
}
// Equal checks if a version is equal to another.
func Equal(v, other string) bool {
return compare(v, other) == 0
}

View File

@ -7,7 +7,7 @@ import (
var (
// Version should be updated by hand at each release
Version = "0.8.2"
Version = "0.10.0"
// GitCommit will be overwritten automatically by the build system
GitCommit = "HEAD"