Skip to content

Commit a7bd9e0

Browse files
committed
Update B2D cache in PreCreateCheck phase
Signed-off-by: David Gageot <david@gageot.net>
1 parent 0a74068 commit a7bd9e0

File tree

6 files changed

+90
-65
lines changed

6 files changed

+90
-65
lines changed

drivers/hyperv/hyperv.go

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import (
1919

2020
type Driver struct {
2121
*drivers.BaseDriver
22-
boot2DockerURL string
22+
Boot2DockerURL string
2323
boot2DockerLoc string
2424
vSwitch string
2525
diskImage string
@@ -73,7 +73,7 @@ func (d *Driver) GetCreateFlags() []mcnflag.Flag {
7373
}
7474

7575
func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error {
76-
d.boot2DockerURL = flags.String("hyperv-boot2docker-url")
76+
d.Boot2DockerURL = flags.String("hyperv-boot2docker-url")
7777
d.boot2DockerLoc = flags.String("hyperv-boot2docker-location")
7878
d.vSwitch = flags.String("hyperv-virtual-switch")
7979
d.DiskSize = flags.Int("hyperv-disk-size")
@@ -139,16 +139,27 @@ func (d *Driver) GetState() (state.State, error) {
139139
return state.None, nil
140140
}
141141

142-
func (d *Driver) Create() error {
143-
err := hypervAvailable()
144-
if err != nil {
142+
// PreCreateCheck checks that the machine creation process can be started safely.
143+
func (d *Driver) PreCreateCheck() error {
144+
if err := hypervAvailable(); err != nil {
145+
return err
146+
}
147+
148+
// Downloading boot2docker to cache should be done here to make sure
149+
// that a download failure will not leave a machine half created.
150+
b2dutils := mcnutils.NewB2dUtils(d.StorePath)
151+
if err := b2dutils.UpdateISOCache(d.Boot2DockerURL); err != nil {
145152
return err
146153
}
147154

155+
return nil
156+
}
157+
158+
func (d *Driver) Create() error {
148159
d.setMachineNameIfNotSet()
149160

150161
b2dutils := mcnutils.NewB2dUtils(d.StorePath)
151-
if err := b2dutils.CopyIsoToMachineDir(d.boot2DockerURL, d.MachineName); err != nil {
162+
if err := b2dutils.CopyIsoToMachineDir(d.Boot2DockerURL, d.MachineName); err != nil {
152163
return err
153164
}
154165

drivers/virtualbox/virtualbox.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,13 @@ func (d *Driver) PreCreateCheck() error {
216216
log.Warn("This computer doesn't have VT-X/AMD-v enabled. Enabling it in the BIOS is mandatory.")
217217
}
218218

219+
// Downloading boot2docker to cache should be done here to make sure
220+
// that a download failure will not leave a machine half created.
221+
b2dutils := mcnutils.NewB2dUtils(d.StorePath)
222+
if err := b2dutils.UpdateISOCache(d.Boot2DockerURL); err != nil {
223+
return err
224+
}
225+
219226
return nil
220227
}
221228

drivers/vmwarefusion/fusion_darwin.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,18 @@ func (d *Driver) GetState() (state.State, error) {
206206
return state.Stopped, nil
207207
}
208208

209+
// PreCreateCheck checks that the machine creation process can be started safely.
210+
func (d *Driver) PreCreateCheck() error {
211+
// Downloading boot2docker to cache should be done here to make sure
212+
// that a download failure will not leave a machine half created.
213+
b2dutils := mcnutils.NewB2dUtils(d.StorePath)
214+
if err := b2dutils.UpdateISOCache(d.Boot2DockerURL); err != nil {
215+
return err
216+
}
217+
218+
return nil
219+
}
220+
209221
func (d *Driver) Create() error {
210222
b2dutils := mcnutils.NewB2dUtils(d.StorePath)
211223
if err := b2dutils.CopyIsoToMachineDir(d.Boot2DockerURL, d.MachineName); err != nil {
@@ -214,7 +226,6 @@ func (d *Driver) Create() error {
214226

215227
// download cloud-init config drive
216228
if d.ConfigDriveURL != "" {
217-
log.Infof("Downloading %s from %s", isoConfigDrive, d.ConfigDriveURL)
218229
if err := b2dutils.DownloadISO(d.ResolveStorePath("."), isoConfigDrive, d.ConfigDriveURL); err != nil {
219230
return err
220231
}

drivers/vmwarevsphere/vsphere.go

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -212,16 +212,28 @@ func (d *Driver) GetState() (state.State, error) {
212212
return state.None, nil
213213
}
214214

215+
// PreCreateCheck checks that the machine creation process can be started safely.
216+
func (d *Driver) PreCreateCheck() error {
217+
if err := d.checkVsphereConfig(); err != nil {
218+
return err
219+
}
220+
221+
// Downloading boot2docker to cache should be done here to make sure
222+
// that a download failure will not leave a machine half created.
223+
b2dutils := mcnutils.NewB2dUtils(d.StorePath)
224+
if err := b2dutils.UpdateISOCache(d.Boot2DockerURL); err != nil {
225+
return err
226+
}
227+
228+
return nil
229+
}
230+
215231
// Create has the following implementation:
216232
// 1. check whether the docker directory contains the boot2docker ISO
217233
// 2. generate an SSH keypair and bundle it in a tar.
218234
// 3. create a virtual machine with the boot2docker ISO mounted;
219235
// 4. reconfigure the virtual machine network and disk size;
220236
func (d *Driver) Create() error {
221-
if err := d.checkVsphereConfig(); err != nil {
222-
return err
223-
}
224-
225237
b2dutils := mcnutils.NewB2dUtils(d.StorePath)
226238
if err := b2dutils.CopyIsoToMachineDir(d.Boot2DockerURL, d.MachineName); err != nil {
227239
return err

libmachine/mcnutils/b2d.go

Lines changed: 34 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,9 @@ func getClient() *http.Client {
4343
Dial: defaultTimeout,
4444
}
4545

46-
client := http.Client{
46+
return &http.Client{
4747
Transport: &transport,
4848
}
49-
50-
return &client
5149
}
5250

5351
func getRequest(apiURL string) (*http.Request, error) {
@@ -204,11 +202,7 @@ func (*b2dReleaseGetter) download(dir, file, isoURL string) error {
204202
return err
205203
}
206204

207-
if err := os.Rename(f.Name(), dest); err != nil {
208-
return err
209-
}
210-
211-
return nil
205+
return os.Rename(f.Name(), dest)
212206
}
213207

214208
// iso is an ISO volume.
@@ -305,6 +299,7 @@ func NewB2dUtils(storePath string) *B2dUtils {
305299

306300
// DownloadISO downloads boot2docker ISO image for the given tag and save it at dest.
307301
func (b *B2dUtils) DownloadISO(dir, file, isoURL string) error {
302+
log.Infof("Downloading %s from %s...", b.path(), isoURL)
308303
return b.download(dir, file, isoURL)
309304
}
310305

@@ -351,72 +346,60 @@ func (b *B2dUtils) DownloadLatestBoot2Docker(apiURL string) error {
351346
}
352347

353348
func (b *B2dUtils) DownloadISOFromURL(latestReleaseURL string) error {
354-
log.Infof("Downloading %s to %s...", latestReleaseURL, b.path())
355-
if err := b.DownloadISO(b.imgCachePath, b.filename(), latestReleaseURL); err != nil {
356-
return err
357-
}
358-
359-
return nil
349+
return b.DownloadISO(b.imgCachePath, b.filename(), latestReleaseURL)
360350
}
361351

362-
func (b *B2dUtils) CopyIsoToMachineDir(isoURL, machineName string) error {
363-
// TODO: This is a bit off-color.
364-
machineDir := filepath.Join(b.storePath, "machines", machineName)
365-
machineIsoPath := filepath.Join(machineDir, b.filename())
366-
367-
// just in case the cache dir has been manually deleted,
368-
// check for it and recreate it if it's gone
352+
func (b *B2dUtils) UpdateISOCache(isoURL string) error {
353+
// recreate the cache dir if it has been manually deleted
369354
if _, err := os.Stat(b.imgCachePath); os.IsNotExist(err) {
370-
log.Infof("Image cache does not exist, creating it at %s...", b.imgCachePath)
355+
log.Infof("Image cache directory does not exist, creating it at %s...", b.imgCachePath)
371356
if err := os.Mkdir(b.imgCachePath, 0700); err != nil {
372357
return err
373358
}
374359
}
375360

376-
// By default just copy the existing "cached" iso to the machine's directory...
377-
if isoURL == "" {
378-
return b.copyDefaultISOToMachine(machineIsoPath)
361+
if isoURL != "" {
362+
// Non-default B2D are not cached
363+
return nil
379364
}
380365

381-
// if ISO is specified, check if it matches a github releases url or fallback to a direct download
382-
downloadURL, err := b.getReleaseURL(isoURL)
383-
if err != nil {
384-
return err
366+
exists := b.exists()
367+
if !exists {
368+
log.Info("No default Boot2Docker ISO found locally, downloading the latest release...")
369+
return b.DownloadLatestBoot2Docker("")
385370
}
386371

387-
log.Infof("Downloading %s from %s...", b.filename(), downloadURL)
388-
return b.DownloadISO(machineDir, b.filename(), downloadURL)
372+
latest := b.isLatest()
373+
if !latest {
374+
log.Info("Default Boot2Docker ISO is out-of-date, downloading the latest release...")
375+
return b.DownloadLatestBoot2Docker("")
376+
}
377+
378+
return nil
389379
}
390380

391-
func (b *B2dUtils) copyDefaultISOToMachine(machineIsoPath string) error {
392-
// just in case the cache dir has been manually deleted,
393-
// check for it and recreate it if it's gone
394-
if _, err := os.Stat(b.imgCachePath); os.IsNotExist(err) {
395-
log.Infof("Image cache directory does not exist, creating it at %s...", b.imgCachePath)
396-
if err := os.Mkdir(b.imgCachePath, 0700); err != nil {
397-
return err
398-
}
381+
func (b *B2dUtils) CopyIsoToMachineDir(isoURL, machineName string) error {
382+
if err := b.UpdateISOCache(isoURL); err != nil {
383+
return err
399384
}
400385

401-
exists := b.exists()
402-
latest := b.isLatest()
386+
// TODO: This is a bit off-color.
387+
machineDir := filepath.Join(b.storePath, "machines", machineName)
388+
machineIsoPath := filepath.Join(machineDir, b.filename())
403389

404-
if exists && latest {
405-
log.Infof("Latest Boot2Docker ISO found locally, copying it to %s...", machineIsoPath)
390+
// By default just copy the existing "cached" iso to the machine's directory...
391+
if isoURL == "" {
392+
log.Infof("Copying %s to %s...", b.path(), machineIsoPath)
406393
return CopyFile(b.path(), machineIsoPath)
407394
}
408395

409-
if !exists {
410-
log.Info("No default Boot2Docker ISO found locally, downloading the latest release...")
411-
} else if !latest {
412-
log.Info("Default Boot2Docker ISO is out-of-date, downloading the latest release...")
413-
}
414-
if err := b.DownloadLatestBoot2Docker(""); err != nil {
396+
// if ISO is specified, check if it matches a github releases url or fallback to a direct download
397+
downloadURL, err := b.getReleaseURL(isoURL)
398+
if err != nil {
415399
return err
416400
}
417401

418-
log.Infof("Copying %s to %s...", b.path(), machineIsoPath)
419-
return CopyFile(b.path(), machineIsoPath)
402+
return b.DownloadISO(machineDir, b.filename(), downloadURL)
420403
}
421404

422405
// isLatest checks the latest release tag and

libmachine/mcnutils/b2d_test.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -261,13 +261,14 @@ func TestCopyDefaultISOToMachine(t *testing.T) {
261261
imgCachePath: imgCachePath,
262262
}
263263

264-
dir := filepath.Join(storePath, tt.machineName)
264+
dir := filepath.Join(storePath, "machines", tt.machineName)
265265
err = os.MkdirAll(dir, 0700)
266-
267266
assert.NoError(t, err, "machine: %s", tt.machineName)
268267

268+
err = b.CopyIsoToMachineDir("", tt.machineName)
269+
assert.NoError(t, err)
270+
269271
dest := filepath.Join(dir, b.filename())
270-
err = b.copyDefaultISOToMachine(dest)
271272
_, pathErr := os.Stat(dest)
272273

273274
assert.NoError(t, err, "machine: %s", tt.machineName)

0 commit comments

Comments
 (0)