From 090e3328c8d45a394105f65a8095e39451f797fb Mon Sep 17 00:00:00 2001 From: Evan Hazlett Date: Thu, 15 Jan 2015 13:44:59 -0500 Subject: [PATCH] refactor b2d retrieval for fusion/vbox Signed-off-by: Evan Hazlett --- commands.go | 2 +- drivers/google/compute_util.go | 2 +- drivers/virtualbox/virtualbox.go | 68 ++++---------------------------- drivers/vmwarefusion/fusion.go | 46 ++++++++++++++++++--- drivers/vmwarevsphere/vsphere.go | 46 ++++++++++++++++++--- utils/b2d.go | 62 +++++++++++++++++++++++++++++ 6 files changed, 151 insertions(+), 75 deletions(-) create mode 100644 utils/b2d.go diff --git a/commands.go b/commands.go index a8e1ae866b..c09f674fda 100644 --- a/commands.go +++ b/commands.go @@ -210,7 +210,7 @@ func cmdCreate(c *cli.Context) { log.Infof("%q has been created and is now the active machine", name) // TODO @ehazlett: this will likely change but at least show how to connect for now - log.Infof("To connect, use docker $(machine config %s)", name) + log.Infof("To connect: docker $(machine config %s) ps", name) } func cmdConfig(c *cli.Context) { diff --git a/drivers/google/compute_util.go b/drivers/google/compute_util.go index 16a312c4d2..0cdcdb6f32 100644 --- a/drivers/google/compute_util.go +++ b/drivers/google/compute_util.go @@ -41,7 +41,7 @@ var ( `sudo mkdir -p /.docker/authorized-keys.d/ sudo chown -R {{ .UserName }} /.docker while [ -e /var/run/docker.pid ]; do sleep 1; done -sudo curl -L -o /usr/bin/docker https://get.docker.com/builds/Linux/x86_64/docker-latest +sudo curl -s -L -o /usr/bin/docker https://get.docker.com/builds/Linux/x86_64/docker-latest `)) ) diff --git a/drivers/virtualbox/virtualbox.go b/drivers/virtualbox/virtualbox.go index ccc84feef0..7a4cdb8b41 100644 --- a/drivers/virtualbox/virtualbox.go +++ b/drivers/virtualbox/virtualbox.go @@ -3,12 +3,10 @@ package virtualbox import ( "archive/tar" "bytes" - "encoding/json" "fmt" "io" "io/ioutil" "net" - "net/http" "os" "os/exec" "path/filepath" @@ -20,10 +18,10 @@ import ( log "github.com/Sirupsen/logrus" "github.com/codegangsta/cli" - "github.com/docker/docker/utils" "github.com/docker/machine/drivers" "github.com/docker/machine/ssh" "github.com/docker/machine/state" + "github.com/docker/machine/utils" ) const ( @@ -133,14 +131,13 @@ func (d *Driver) Create() error { if d.Boot2DockerURL != "" { isoURL = d.Boot2DockerURL log.Infof("Downloading boot2docker.iso from %s...", isoURL) - if err := downloadISO(d.storePath, "boot2docker.iso", isoURL); err != nil { + if err := utils.DownloadISO(d.storePath, "boot2docker.iso", isoURL); err != nil { return err } } else { // todo: check latest release URL, download if it's new // until then always use "latest" - - isoURL, err = getLatestReleaseURL() + isoURL, err = utils.GetLatestBoot2DockerReleaseURL() if err != nil { return err } @@ -159,7 +156,7 @@ func (d *Driver) Create() error { } } - if err := downloadISO(imgPath, "boot2docker.iso", isoURL); err != nil { + if err := utils.DownloadISO(imgPath, "boot2docker.iso", isoURL); err != nil { return err } } @@ -398,13 +395,13 @@ func (d *Driver) Upgrade() error { return err } - isoURL, err := getLatestReleaseURL() + isoURL, err := utils.GetLatestBoot2DockerReleaseURL() if err != nil { return err } log.Infof("Downloading boot2docker...") - if err := downloadISO(d.storePath, "boot2docker.iso", isoURL); err != nil { + if err := utils.DownloadISO(d.storePath, "boot2docker.iso", isoURL); err != nil { return err } @@ -445,7 +442,7 @@ func (d *Driver) GetState() (state.State, error) { func (d *Driver) setMachineNameIfNotSet() { if d.MachineName == "" { - d.MachineName = fmt.Sprintf("docker-host-%s", utils.GenerateRandomID()) + d.MachineName = fmt.Sprintf("docker-machine-unknown") } } @@ -534,57 +531,6 @@ func (d *Driver) diskPath() string { return filepath.Join(d.storePath, "disk.vmdk") } -// Get the latest boot2docker release tag name (e.g. "v0.6.0"). -// FIXME: find or create some other way to get the "latest release" of boot2docker since the GitHub API has a pretty low rate limit on API requests -func getLatestReleaseURL() (string, error) { - rsp, err := http.Get("https://api.github.com/repos/boot2docker/boot2docker/releases") - if err != nil { - return "", err - } - defer rsp.Body.Close() - - var t []struct { - TagName string `json:"tag_name"` - } - if err := json.NewDecoder(rsp.Body).Decode(&t); err != nil { - return "", err - } - if len(t) == 0 { - return "", fmt.Errorf("no releases found") - } - - tag := t[0].TagName - url := fmt.Sprintf("https://github.com/boot2docker/boot2docker/releases/download/%s/boot2docker.iso", tag) - return url, nil -} - -// Download boot2docker ISO image for the given tag and save it at dest. -func downloadISO(dir, file, url string) error { - rsp, err := http.Get(url) - if err != nil { - return err - } - defer rsp.Body.Close() - - // Download to a temp file first then rename it to avoid partial download. - f, err := ioutil.TempFile(dir, file+".tmp") - if err != nil { - return err - } - defer os.Remove(f.Name()) - if _, err := io.Copy(f, rsp.Body); err != nil { - // TODO: display download progress? - return err - } - if err := f.Close(); err != nil { - return err - } - if err := os.Rename(f.Name(), filepath.Join(dir, file)); err != nil { - return err - } - return nil -} - // Make a boot2docker VM disk image. func (d *Driver) generateDiskImage(size int) error { log.Debugf("Creating %d MB hard disk image...", size) diff --git a/drivers/vmwarefusion/fusion.go b/drivers/vmwarefusion/fusion.go index b0b14fd9f3..4a85cc3bc9 100644 --- a/drivers/vmwarefusion/fusion.go +++ b/drivers/vmwarefusion/fusion.go @@ -23,6 +23,7 @@ import ( "github.com/docker/machine/drivers" "github.com/docker/machine/ssh" "github.com/docker/machine/state" + "github.com/docker/machine/utils" cssh "golang.org/x/crypto/ssh" ) @@ -129,15 +130,48 @@ func (d *Driver) GetState() (state.State, error) { func (d *Driver) Create() error { - var isoURL string + var ( + isoURL string + err error + ) + if d.Boot2DockerURL != "" { isoURL = d.Boot2DockerURL + log.Infof("Downloading boot2docker.iso from %s...", isoURL) + if err := utils.DownloadISO(d.storePath, "boot2docker.iso", isoURL); err != nil { + return err + } } else { - isoURL = "https://github.com/boot2docker/boot2docker/releases/download/v1.4.1/boot2docker.iso" - } - log.Infof("Downloading boot2docker...") - if err := downloadISO(d.storePath, "boot2docker.iso", isoURL); err != nil { - return err + // todo: check latest release URL, download if it's new + // until then always use "latest" + isoURL, err = utils.GetLatestBoot2DockerReleaseURL() + if err != nil { + return err + } + + // todo: use real constant for .docker + rootPath := filepath.Join(drivers.GetHomeDir(), ".docker") + imgPath := filepath.Join(rootPath, "images") + commonIsoPath := filepath.Join(imgPath, "boot2docker.iso") + if _, err := os.Stat(commonIsoPath); os.IsNotExist(err) { + log.Infof("Downloading boot2docker.iso to %s...", commonIsoPath) + + // just in case boot2docker.iso has been manually deleted + if _, err := os.Stat(imgPath); os.IsNotExist(err) { + if err := os.Mkdir(imgPath, 0700); err != nil { + return err + } + } + + if err := utils.DownloadISO(imgPath, "boot2docker.iso", isoURL); err != nil { + return err + } + } + + isoDest := filepath.Join(d.storePath, "boot2docker.iso") + if err := utils.CopyFile(commonIsoPath, isoDest); err != nil { + return err + } } log.Infof("Creating SSH key...") diff --git a/drivers/vmwarevsphere/vsphere.go b/drivers/vmwarevsphere/vsphere.go index 2d6495f07b..5b003d8dda 100644 --- a/drivers/vmwarevsphere/vsphere.go +++ b/drivers/vmwarevsphere/vsphere.go @@ -22,6 +22,7 @@ import ( "github.com/docker/machine/drivers/vmwarevsphere/errors" "github.com/docker/machine/ssh" "github.com/docker/machine/state" + "github.com/docker/machine/utils" cssh "golang.org/x/crypto/ssh" ) @@ -224,15 +225,48 @@ func (d *Driver) Create() error { return err } - var isoURL string + var ( + isoURL string + err error + ) + if d.Boot2DockerURL != "" { isoURL = d.Boot2DockerURL + log.Infof("Downloading boot2docker.iso from %s...", isoURL) + if err := utils.DownloadISO(d.storePath, "boot2docker.iso", isoURL); err != nil { + return err + } } else { - isoURL = "https://github.com/boot2docker/boot2docker/releases/download/v1.4.1/boot2docker.iso" - } - log.Infof("Downloading boot2docker...") - if err := downloadISO(d.storePath, "boot2docker.iso", isoURL); err != nil { - return err + // todo: check latest release URL, download if it's new + // until then always use "latest" + isoURL, err = utils.GetLatestBoot2DockerReleaseURL() + if err != nil { + return err + } + + // todo: use real constant for .docker + rootPath := filepath.Join(drivers.GetHomeDir(), ".docker") + imgPath := filepath.Join(rootPath, "images") + commonIsoPath := filepath.Join(imgPath, "boot2docker.iso") + if _, err := os.Stat(commonIsoPath); os.IsNotExist(err) { + log.Infof("Downloading boot2docker.iso to %s...", commonIsoPath) + + // just in case boot2docker.iso has been manually deleted + if _, err := os.Stat(imgPath); os.IsNotExist(err) { + if err := os.Mkdir(imgPath, 0700); err != nil { + return err + } + } + + if err := utils.DownloadISO(imgPath, "boot2docker.iso", isoURL); err != nil { + return err + } + } + + isoDest := filepath.Join(d.storePath, "boot2docker.iso") + if err := utils.CopyFile(commonIsoPath, isoDest); err != nil { + return err + } } log.Infof("Generating SSH Keypair...") diff --git a/utils/b2d.go b/utils/b2d.go new file mode 100644 index 0000000000..4b200db0ca --- /dev/null +++ b/utils/b2d.go @@ -0,0 +1,62 @@ +package utils + +import ( + "encoding/json" + "fmt" + "io" + "io/ioutil" + "net/http" + "os" + "path/filepath" +) + +// Get the latest boot2docker release tag name (e.g. "v0.6.0"). +// FIXME: find or create some other way to get the "latest release" of boot2docker since the GitHub API has a pretty low rate limit on API requests +func GetLatestBoot2DockerReleaseURL() (string, error) { + rsp, err := http.Get("https://api.github.com/repos/boot2docker/boot2docker/releases") + if err != nil { + return "", err + } + defer rsp.Body.Close() + + var t []struct { + TagName string `json:"tag_name"` + } + if err := json.NewDecoder(rsp.Body).Decode(&t); err != nil { + return "", err + } + if len(t) == 0 { + return "", fmt.Errorf("no releases found") + } + + tag := t[0].TagName + url := fmt.Sprintf("https://github.com/boot2docker/boot2docker/releases/download/%s/boot2docker.iso", tag) + return url, nil +} + +// Download boot2docker ISO image for the given tag and save it at dest. +func DownloadISO(dir, file, url string) error { + rsp, err := http.Get(url) + if err != nil { + return err + } + defer rsp.Body.Close() + + // Download to a temp file first then rename it to avoid partial download. + f, err := ioutil.TempFile(dir, file+".tmp") + if err != nil { + return err + } + defer os.Remove(f.Name()) + if _, err := io.Copy(f, rsp.Body); err != nil { + // TODO: display download progress? + return err + } + if err := f.Close(); err != nil { + return err + } + if err := os.Rename(f.Name(), filepath.Join(dir, file)); err != nil { + return err + } + return nil +}