mirror of https://github.com/docker/docs.git
Merge pull request #1292 from ehazlett/vbox-recreate-hostonlyif
virtualbox: more flexibility with networking
This commit is contained in:
commit
3387f988b8
|
@ -1464,6 +1464,7 @@ Options:
|
|||
- `--virtualbox-disk-size`: Size of disk for the host in MB.
|
||||
- `--virtualbox-boot2docker-url`: The URL of the boot2docker image. Defaults to the latest available version.
|
||||
- `--virtualbox-import-boot2docker-vm`: The name of a Boot2Docker VM to import.
|
||||
- `--virtualbox-hostonly-cidr`: The CIDR of the host only adapter.
|
||||
|
||||
The `--virtualbox-boot2docker-url` flag takes a few different forms. By
|
||||
default, if no value is specified for this flag, Machine will check locally for
|
||||
|
@ -1482,6 +1483,15 @@ file://$HOME/Downloads/rc.iso` to test out a release candidate ISO that you have
|
|||
downloaded already. You could also just get an ISO straight from the Internet
|
||||
using the `http://` form.
|
||||
|
||||
To customize the host only adapter, you can use the `--virtualbox-hostonly-cidr`
|
||||
flag. This will specify the host IP and Machine will calculate the VirtualBox
|
||||
DHCP server address (a random IP on the subnet between `.1` and `.25`) so
|
||||
it does not clash with the specified host IP.
|
||||
Machine will also specify the DHCP lower bound to `.100` and the upper bound
|
||||
to `.254`. For example, a specified CIDR of `192.168.24.1/24` would have a
|
||||
DHCP server between `192.168.24.2-25`, a lower bound of `192.168.24.100` and
|
||||
upper bound of `192.168.24.254`.
|
||||
|
||||
Environment variables and default values:
|
||||
|
||||
| CLI option | Environment variable | Default |
|
||||
|
@ -1491,6 +1501,7 @@ Environment variables and default values:
|
|||
| `--virtualbox-disk-size` | `VIRTUALBOX_DISK_SIZE` | `20000` |
|
||||
| `--virtualbox-boot2docker-url` | `VIRTUALBOX_BOOT2DOCKER_URL` | *Latest boot2docker url* |
|
||||
| `--virtualbox-import-boot2docker-vm` | - | `boot2docker-vm` |
|
||||
| `--virtualbox-hostonly-cidr` | `VIRTUALBOX_HOSTONLY_CIDR` | `192.168.99.1/24` |
|
||||
|
||||
#### VMware Fusion
|
||||
Creates machines locally on [VMware Fusion](http://www.vmware.com/products/fusion). Requires VMware Fusion to be installed.
|
||||
|
|
|
@ -3,9 +3,11 @@ package virtualbox
|
|||
import (
|
||||
"archive/tar"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
@ -28,6 +30,10 @@ const (
|
|||
isoFilename = "boot2docker.iso"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrUnableToGenerateRandomIP = errors.New("unable to generate random IP")
|
||||
)
|
||||
|
||||
type Driver struct {
|
||||
IPAddress string
|
||||
CPU int
|
||||
|
@ -44,6 +50,7 @@ type Driver struct {
|
|||
SwarmDiscovery string
|
||||
storePath string
|
||||
Boot2DockerImportVM string
|
||||
HostOnlyCIDR string
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
@ -86,6 +93,12 @@ func GetCreateFlags() []cli.Flag {
|
|||
Usage: "The name of a Boot2Docker VM to import",
|
||||
Value: "",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "virtualbox-hostonly-cidr",
|
||||
Usage: "Specify the Host Only CIDR",
|
||||
Value: "192.168.99.1/24",
|
||||
EnvVar: "VIRTUALBOX_HOSTONLY_CIDR",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,6 +163,7 @@ func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error {
|
|||
d.SwarmDiscovery = flags.String("swarm-discovery")
|
||||
d.SSHUser = "docker"
|
||||
d.Boot2DockerImportVM = flags.String("virtualbox-import-boot2docker-vm")
|
||||
d.HostOnlyCIDR = flags.String("virtualbox-hostonly-cidr")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -273,20 +287,7 @@ func (d *Driver) Create() error {
|
|||
return err
|
||||
}
|
||||
|
||||
hostOnlyNetwork, err := getOrCreateHostOnlyNetwork(
|
||||
net.ParseIP("192.168.99.1"),
|
||||
net.IPv4Mask(255, 255, 255, 0),
|
||||
net.ParseIP("192.168.99.2"),
|
||||
net.ParseIP("192.168.99.100"),
|
||||
net.ParseIP("192.168.99.254"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := vbm("modifyvm", d.MachineName,
|
||||
"--nic2", "hostonly",
|
||||
"--nictype2", "82540EM",
|
||||
"--hostonlyadapter2", hostOnlyNetwork.Name,
|
||||
"--cableconnected2", "on"); err != nil {
|
||||
if err := d.setupHostOnlyNetwork(d.MachineName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -372,6 +373,11 @@ func (d *Driver) Start() error {
|
|||
return err
|
||||
}
|
||||
|
||||
// check network to re-create if needed
|
||||
if err := d.setupHostOnlyNetwork(d.MachineName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch s {
|
||||
case state.Stopped, state.Saved:
|
||||
d.SSHPort, err = setPortForwarding(d.MachineName, 1, "ssh", "tcp", 22, d.SSHPort)
|
||||
|
@ -572,6 +578,43 @@ func (d *Driver) generateDiskImage(size int) error {
|
|||
return createDiskImage(d.diskPath(), size, raw)
|
||||
}
|
||||
|
||||
func (d *Driver) setupHostOnlyNetwork(machineName string) error {
|
||||
ip, network, err := net.ParseCIDR(d.HostOnlyCIDR)
|
||||
nAddr := network.IP.To4()
|
||||
|
||||
dhcpAddr, err := getRandomIPinSubnet(network.IP)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
lowerDHCPIP := net.IPv4(nAddr[0], nAddr[1], nAddr[2], byte(100))
|
||||
upperDHCPIP := net.IPv4(nAddr[0], nAddr[1], nAddr[2], byte(254))
|
||||
|
||||
log.Debugf("using %s for dhcp address", dhcpAddr)
|
||||
|
||||
hostOnlyNetwork, err := getOrCreateHostOnlyNetwork(
|
||||
ip,
|
||||
network.Mask,
|
||||
dhcpAddr,
|
||||
lowerDHCPIP,
|
||||
upperDHCPIP,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := vbm("modifyvm", machineName,
|
||||
"--nic2", "hostonly",
|
||||
"--nictype2", "82540EM",
|
||||
"--hostonlyadapter2", hostOnlyNetwork.Name,
|
||||
"--cableconnected2", "on"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// createDiskImage makes a disk image at dest with the given size in MB. If r is
|
||||
// not nil, it will be read as a raw disk image to convert from.
|
||||
func createDiskImage(dest string, size int, r io.Reader) error {
|
||||
|
@ -678,3 +721,26 @@ func setPortForwarding(machine string, interfaceNum int, mapName, protocol strin
|
|||
}
|
||||
return actualHostPort, nil
|
||||
}
|
||||
|
||||
// getRandomIPinSubnet returns a pseudo-random net.IP in the same
|
||||
// subnet as the IP passed
|
||||
func getRandomIPinSubnet(baseIP net.IP) (net.IP, error) {
|
||||
var dhcpAddr net.IP
|
||||
|
||||
nAddr := baseIP.To4()
|
||||
// select pseudo-random DHCP addr; make sure not to clash with the host
|
||||
// only try 5 times and bail if no random received
|
||||
for i := 0; i < 5; i++ {
|
||||
n := rand.Intn(25)
|
||||
if byte(n) != nAddr[3] {
|
||||
dhcpAddr = net.IPv4(nAddr[0], nAddr[1], nAddr[2], byte(1))
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if dhcpAddr == nil {
|
||||
return nil, ErrUnableToGenerateRandomIP
|
||||
}
|
||||
|
||||
return dhcpAddr, nil
|
||||
}
|
||||
|
|
|
@ -1 +1,31 @@
|
|||
package virtualbox
|
||||
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGetRandomIPinSubnet(t *testing.T) {
|
||||
// test IP 1.2.3.4
|
||||
testIP := net.IPv4(byte(1), byte(2), byte(3), byte(4))
|
||||
newIP, err := getRandomIPinSubnet(testIP)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if testIP.Equal(newIP) {
|
||||
t.Fatalf("expected different IP (source %s); received %s", testIP.String(), newIP.String())
|
||||
}
|
||||
|
||||
if newIP[0] != testIP[0] {
|
||||
t.Fatalf("expected first octet of %d; received %d", testIP[0], newIP[0])
|
||||
}
|
||||
|
||||
if newIP[1] != testIP[1] {
|
||||
t.Fatalf("expected second octet of %d; received %d", testIP[1], newIP[1])
|
||||
}
|
||||
|
||||
if newIP[2] != testIP[2] {
|
||||
t.Fatalf("expected third octet of %d; received %d", testIP[2], newIP[2])
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue