2013-06-11 23:00:30 -04:00
|
|
|
package virtualbox
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/hex"
|
|
|
|
"fmt"
|
|
|
|
"github.com/mitchellh/multistep"
|
2013-06-12 20:42:18 -04:00
|
|
|
"github.com/mitchellh/packer/builder/common"
|
2013-06-11 23:00:30 -04:00
|
|
|
"github.com/mitchellh/packer/packer"
|
2013-06-24 00:47:56 -04:00
|
|
|
"io"
|
|
|
|
"io/ioutil"
|
2013-06-11 23:00:30 -04:00
|
|
|
"log"
|
2013-06-24 00:47:56 -04:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
2013-06-11 23:00:30 -04:00
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
// This step downloads the ISO specified.
|
|
|
|
//
|
|
|
|
// Uses:
|
|
|
|
// cache packer.Cache
|
|
|
|
// config *config
|
|
|
|
// ui packer.Ui
|
|
|
|
//
|
|
|
|
// Produces:
|
|
|
|
// iso_path string
|
2013-06-24 00:47:56 -04:00
|
|
|
type stepDownloadISO struct {
|
|
|
|
isoCopyDir string
|
|
|
|
}
|
2013-06-11 23:00:30 -04:00
|
|
|
|
2013-06-24 00:47:56 -04:00
|
|
|
func (s *stepDownloadISO) Run(state map[string]interface{}) multistep.StepAction {
|
2013-06-11 23:00:30 -04:00
|
|
|
cache := state["cache"].(packer.Cache)
|
|
|
|
config := state["config"].(*config)
|
|
|
|
ui := state["ui"].(packer.Ui)
|
|
|
|
|
2013-07-14 02:50:34 -04:00
|
|
|
checksum, err := hex.DecodeString(config.ISOChecksum)
|
2013-06-12 20:42:18 -04:00
|
|
|
if err != nil {
|
2013-06-28 22:34:43 -04:00
|
|
|
state["error"] = fmt.Errorf("Error parsing checksum: %s", err)
|
2013-06-12 20:42:18 -04:00
|
|
|
return multistep.ActionHalt
|
|
|
|
}
|
|
|
|
|
2013-06-11 23:00:30 -04:00
|
|
|
log.Printf("Acquiring lock to download the ISO.")
|
|
|
|
cachePath := cache.Lock(config.ISOUrl)
|
|
|
|
defer cache.Unlock(config.ISOUrl)
|
|
|
|
|
2013-06-12 20:42:18 -04:00
|
|
|
downloadConfig := &common.DownloadConfig{
|
|
|
|
Url: config.ISOUrl,
|
|
|
|
TargetPath: cachePath,
|
|
|
|
CopyFile: false,
|
2013-07-14 02:50:34 -04:00
|
|
|
Hash: common.HashForType(config.ISOChecksumType),
|
2013-06-12 20:42:18 -04:00
|
|
|
Checksum: checksum,
|
2013-06-11 23:00:30 -04:00
|
|
|
}
|
|
|
|
|
2013-06-12 20:42:18 -04:00
|
|
|
download := common.NewDownloadClient(downloadConfig)
|
2013-06-11 23:00:30 -04:00
|
|
|
|
2013-06-12 20:42:18 -04:00
|
|
|
downloadCompleteCh := make(chan error, 1)
|
|
|
|
go func() {
|
|
|
|
ui.Say("Copying or downloading ISO. Progress will be reported periodically.")
|
|
|
|
cachePath, err = download.Get()
|
|
|
|
downloadCompleteCh <- err
|
|
|
|
}()
|
2013-06-11 23:00:30 -04:00
|
|
|
|
2013-06-12 20:42:18 -04:00
|
|
|
progressTicker := time.NewTicker(5 * time.Second)
|
|
|
|
defer progressTicker.Stop()
|
2013-06-11 23:00:30 -04:00
|
|
|
|
2013-06-20 00:20:54 -04:00
|
|
|
DownloadWaitLoop:
|
2013-06-12 20:42:18 -04:00
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case err := <-downloadCompleteCh:
|
|
|
|
if err != nil {
|
2013-06-20 00:07:53 -04:00
|
|
|
err := fmt.Errorf("Error downloading ISO: %s", err)
|
|
|
|
state["error"] = err
|
|
|
|
ui.Error(err.Error())
|
2013-06-23 21:23:00 -04:00
|
|
|
return multistep.ActionHalt
|
2013-06-11 23:00:30 -04:00
|
|
|
}
|
|
|
|
|
2013-06-12 20:42:18 -04:00
|
|
|
break DownloadWaitLoop
|
|
|
|
case <-progressTicker.C:
|
2013-06-24 02:05:32 -04:00
|
|
|
ui.Message(fmt.Sprintf("Download progress: %d%%", download.PercentProgress()))
|
2013-06-12 20:42:18 -04:00
|
|
|
case <-time.After(1 * time.Second):
|
|
|
|
if _, ok := state[multistep.StateCancelled]; ok {
|
|
|
|
ui.Say("Interrupt received. Cancelling download...")
|
|
|
|
return multistep.ActionHalt
|
|
|
|
}
|
2013-06-11 23:00:30 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-24 00:47:56 -04:00
|
|
|
// VirtualBox is really dumb and can't figure out that the file is an
|
|
|
|
// ISO unless it has a ".iso" extension. We can't modify the cache
|
|
|
|
// filenames so we just do a copy.
|
|
|
|
tempdir, err := ioutil.TempDir("", "packer")
|
|
|
|
if err != nil {
|
|
|
|
state["error"] = fmt.Errorf("Error copying ISO: %s", err)
|
|
|
|
return multistep.ActionHalt
|
|
|
|
}
|
|
|
|
s.isoCopyDir = tempdir
|
|
|
|
|
|
|
|
f, err := os.Create(filepath.Join(tempdir, "image.iso"))
|
|
|
|
if err != nil {
|
|
|
|
state["error"] = fmt.Errorf("Error copying ISO: %s", err)
|
|
|
|
return multistep.ActionHalt
|
|
|
|
}
|
|
|
|
defer f.Close()
|
|
|
|
|
|
|
|
sourceF, err := os.Open(cachePath)
|
|
|
|
if err != nil {
|
|
|
|
state["error"] = fmt.Errorf("Error copying ISO: %s", err)
|
|
|
|
return multistep.ActionHalt
|
|
|
|
}
|
2013-06-28 10:30:33 -04:00
|
|
|
defer sourceF.Close()
|
2013-06-24 00:47:56 -04:00
|
|
|
|
2013-06-28 22:34:43 -04:00
|
|
|
log.Printf("Copying ISO to temp location: %s", tempdir)
|
2013-06-24 00:47:56 -04:00
|
|
|
if _, err := io.Copy(f, sourceF); err != nil {
|
|
|
|
state["error"] = fmt.Errorf("Error copying ISO: %s", err)
|
|
|
|
return multistep.ActionHalt
|
|
|
|
}
|
|
|
|
|
2013-06-11 23:00:30 -04:00
|
|
|
log.Printf("Path to ISO on disk: %s", cachePath)
|
2013-06-24 00:47:56 -04:00
|
|
|
state["iso_path"] = f.Name()
|
2013-06-11 23:00:30 -04:00
|
|
|
|
|
|
|
return multistep.ActionContinue
|
|
|
|
}
|
|
|
|
|
2013-06-24 00:47:56 -04:00
|
|
|
func (s *stepDownloadISO) Cleanup(map[string]interface{}) {
|
|
|
|
if s.isoCopyDir != "" {
|
|
|
|
os.RemoveAll(s.isoCopyDir)
|
|
|
|
}
|
|
|
|
}
|