Implements OVA downloads w/local checksum support

Presumably, it is convention to store a manifest file with checksums
inside the OVA, so remote checksum support was not implemented.
This commit is contained in:
Arthur Burkart 2016-10-10 22:16:25 -04:00
parent 541a209f93
commit 337856811e
7 changed files with 142 additions and 95 deletions

View File

@ -70,9 +70,17 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
GuestAdditionsSHA256: b.config.GuestAdditionsSHA256,
Ctx: b.config.ctx,
},
&common.StepDownload{
Checksum: b.config.Checksum,
ChecksumType: b.config.ChecksumType,
Description: "OVF/OVA",
Extension: "ova",
ResultKey: "vm_path",
TargetPath: b.config.TargetPath,
Url: []string{b.config.SourcePath},
},
&StepImport{
Name: b.config.VMName,
SourcePath: b.config.SourcePath,
ImportFlags: b.config.ImportFlags,
},
&vboxcommon.StepAttachGuestAdditions{

View File

@ -2,7 +2,6 @@ package ovf
import (
"fmt"
"os"
"strings"
vboxcommon "github.com/mitchellh/packer/builder/virtualbox/common"
@ -29,6 +28,9 @@ type Config struct {
BootCommand []string `mapstructure:"boot_command"`
SourcePath string `mapstructure:"source_path"`
Checksum string `mapstructure:"checksum"`
ChecksumType string `mapstructure:"checksum_type"`
TargetPath string `mapstructure:"target_path"`
GuestAdditionsMode string `mapstructure:"guest_additions_mode"`
GuestAdditionsPath string `mapstructure:"guest_additions_path"`
GuestAdditionsURL string `mapstructure:"guest_additions_url"`
@ -87,12 +89,15 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
errs = packer.MultiErrorAppend(errs, c.VBoxManagePostConfig.Prepare(&c.ctx)...)
errs = packer.MultiErrorAppend(errs, c.VBoxVersionConfig.Prepare(&c.ctx)...)
c.ChecksumType = strings.ToLower(c.ChecksumType)
c.Checksum = strings.ToLower(c.Checksum)
if c.SourcePath == "" {
errs = packer.MultiErrorAppend(errs, fmt.Errorf("source_path is required"))
} else {
if _, err := os.Stat(c.SourcePath); err != nil {
errs = packer.MultiErrorAppend(errs,
fmt.Errorf("source_path is invalid: %s", err))
c.SourcePath, err = common.DownloadableURL(c.SourcePath)
if err != nil {
errs = packer.MultiErrorAppend(errs, fmt.Errorf("source_path is invalid: %s", err))
}
}

View File

@ -30,24 +30,6 @@ func getTempFile(t *testing.T) *os.File {
return tf
}
func testConfigErr(t *testing.T, warns []string, err error) {
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should error")
}
}
func testConfigOk(t *testing.T, warns []string, err error) {
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("bad: %s", err)
}
}
func TestNewConfig_FloppyFiles(t *testing.T) {
c := testConfig(t)
floppies_path := "../../../common/test-fixtures/floppies"
@ -72,17 +54,38 @@ func TestNewConfig_InvalidFloppies(t *testing.T) {
}
func TestNewConfig_sourcePath(t *testing.T) {
// Bad
// Okay, because it gets caught during download
c := testConfig(t)
delete(c, "source_path")
_, warns, errs := NewConfig(c)
testConfigErr(t, warns, errs)
_, warns, err := NewConfig(c)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatalf("should error with empty `source_path`")
}
// Okay, because it gets caught during download
c = testConfig(t)
c["source_path"] = "/i/dont/exist"
_, warns, err = NewConfig(c)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("bad: %s", err)
}
// Bad
c = testConfig(t)
c["source_path"] = "/i/dont/exist"
_, warns, errs = NewConfig(c)
testConfigErr(t, warns, errs)
c["source_path"] = "ftp://i/dont/exist"
_, warns, err = NewConfig(c)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should error")
}
// Good
tf := getTempFile(t)
@ -90,8 +93,13 @@ func TestNewConfig_sourcePath(t *testing.T) {
c = testConfig(t)
c["source_path"] = tf.Name()
_, warns, errs = NewConfig(c)
testConfigOk(t, warns, errs)
_, warns, err = NewConfig(c)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("bad: %s", err)
}
}
func TestNewConfig_shutdown_timeout(t *testing.T) {
@ -102,11 +110,21 @@ func TestNewConfig_shutdown_timeout(t *testing.T) {
// Expect this to fail
c["source_path"] = tf.Name()
c["shutdown_timeout"] = "NaN"
_, warns, errs := NewConfig(c)
testConfigErr(t, warns, errs)
_, warns, err := NewConfig(c)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should error")
}
// Passes when given a valid time duration
c["shutdown_timeout"] = "10s"
_, warns, errs = NewConfig(c)
testConfigOk(t, warns, errs)
_, warns, err = NewConfig(c)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("bad: %s", err)
}
}

View File

@ -10,7 +10,6 @@ import (
// This step imports an OVF VM into VirtualBox.
type StepImport struct {
Name string
SourcePath string
ImportFlags []string
vmName string
@ -19,9 +18,10 @@ type StepImport struct {
func (s *StepImport) Run(state multistep.StateBag) multistep.StepAction {
driver := state.Get("driver").(vboxcommon.Driver)
ui := state.Get("ui").(packer.Ui)
vmPath := state.Get("vm_path").(string)
ui.Say(fmt.Sprintf("Importing VM: %s", s.SourcePath))
if err := driver.Import(s.Name, s.SourcePath, s.ImportFlags); err != nil {
ui.Say(fmt.Sprintf("Importing VM: %s", vmPath))
if err := driver.Import(s.Name, vmPath, s.ImportFlags); err != nil {
err := fmt.Errorf("Error importing VM: %s", err)
state.Put("error", err)
ui.Error(err.Error())

View File

@ -12,9 +12,9 @@ func TestStepImport_impl(t *testing.T) {
func TestStepImport(t *testing.T) {
state := testState(t)
state.Put("vm_path", "foo")
step := new(StepImport)
step.Name = "bar"
step.SourcePath = "foo"
driver := state.Get("driver").(*vboxcommon.DriverMock)
@ -33,9 +33,6 @@ func TestStepImport(t *testing.T) {
if driver.ImportName != step.Name {
t.Fatalf("bad: %#v", driver.ImportName)
}
if driver.ImportPath != step.SourcePath {
t.Fatalf("bad: %#v", driver.ImportPath)
}
// Test output state
if name, ok := state.GetOk("vmName"); !ok {

View File

@ -55,11 +55,10 @@ builder.
### Required:
- `iso_checksum` (string) - The checksum for the OS ISO file. Because ISO
files are so large, this is required and Packer will verify it prior to
booting a virtual machine with the ISO attached. The type of the checksum is
specified with `iso_checksum_type`, documented below. At least one of
`iso_checksum` and `iso_checksum_url` must be defined. This has precedence
over `iso_checksum_url` type.
files are so large, this is required and Packer will verify it prior to booting
a virtual machine with the ISO attached. The type of the checksum is specified
with `iso_checksum_type`, documented below. The `iso_checksum` has precedence
over the `iso_checksum_url`.
- `iso_checksum_type` (string) - The type of the checksum specified in
`iso_checksum`. Valid values are "none", "md5", "sha1", "sha256", or
@ -101,9 +100,10 @@ builder.
for the VM. By default, this is 40000 (about 40 GB).
- `export_opts` (array of strings) - Additional options to pass to the
[VBoxManage export](https://www.virtualbox.org/manual/ch08.html#vboxmanage-export).
This can be useful for passing product information to include in the
resulting appliance file. Packer JSON configuration file example:
[VBoxManage
export](https://www.virtualbox.org/manual/ch08.html#vboxmanage-export). This
can be useful for passing product information to include in the resulting
appliance file. Packer JSON configuration file example:
``` {.json}
{
@ -119,12 +119,13 @@ builder.
}
```
A VirtualBox [VM description](https://www.virtualbox.org/manual/ch08.html#idm3756)
may contain arbitrary strings; the GUI interprets HTML formatting.
However, the JSON format does not allow arbitrary newlines within a
value. Add a multi-line description by preparing the string in the
shell before the packer call like this (shell `>` continuation
character snipped for easier copy & paste):
A VirtualBox [VM
description](https://www.virtualbox.org/manual/ch08.html#idm3756) may
contain arbitrary strings; the GUI interprets HTML formatting. However, the
JSON format does not allow arbitrary newlines within a value. Add a
multi-line description by preparing the string in the shell before the
packer call like this (shell `>` continuation character snipped for easier
copy & paste):
``` {.shell}
@ -228,8 +229,8 @@ builder.
to, defaults to "ide". When set to "sata", the drive is attached to an AHCI
SATA controller.
- `iso_target_path` (string) - The path where the iso should be saved after
download. By default will go in the packer cache, with a hash of the
- `iso_target_path` (string) - The path where the iso should be saved
after download. By default will go in the packer cache, with a hash of the
original filename as its name.
- `iso_urls` (array of strings) - Multiple URLs for the ISO to download.
@ -249,9 +250,9 @@ builder.
name of the build.
- `post_shutdown_delay` (string) - The amount of time to wait after shutting
down the virtual machine. If you get the error `Error removing floppy
controller`, you might need to set this to `5m` or so. By default, the
delay is `0s`, or disabled.
down the virtual machine. If you get the error
`Error removing floppy controller`, you might need to set this to `5m`
or so. By default, the delay is `0s`, or disabled.
- `shutdown_command` (string) - The command to use to gracefully shut down the
machine once all the provisioning is done. By default this is an empty
@ -301,16 +302,15 @@ builder.
machine, without the file extension. By default this is "packer-BUILDNAME",
where "BUILDNAME" is the name of the build.
- `vrdp_bind_address` (string / IP address) - The IP address that should be binded
to for VRDP. By default packer will use 127.0.0.1 for this. If you wish to bind
to all interfaces use 0.0.0.0
- `vrdp_bind_address` (string / IP address) - The IP address that should be
binded to for VRDP. By default packer will use 127.0.0.1 for this. If you
wish to bind to all interfaces use 0.0.0.0
- `vrdp_port_min` and `vrdp_port_max` (integer) - The minimum and maximum port
to use for VRDP access to the virtual machine. Packer uses a randomly chosen
port in this range that appears available. By default this is 5900 to 6000.
The minimum and maximum ports are inclusive.
## Boot Command
The `boot_command` configuration is very important: it specifies the keys to
@ -357,9 +357,11 @@ by the proper key:
- `<leftAltOn>` `<rightAltOn>` - Simulates pressing and holding the alt key.
- `<leftCtrlOn>` `<rightCtrlOn>` - Simulates pressing and holding the ctrl key.
- `<leftCtrlOn>` `<rightCtrlOn>` - Simulates pressing and holding the
ctrl key.
- `<leftShiftOn>` `<rightShiftOn>` - Simulates pressing and holding the shift key.
- `<leftShiftOn>` `<rightShiftOn>` - Simulates pressing and holding the
shift key.
- `<leftAltOff>` `<rightAltOff>` - Simulates releasing a held alt key.

View File

@ -62,7 +62,7 @@ builder.
### Required:
- `source_path` (string) - The path to an OVF or OVA file that acts as the
source of this build.
source of this build. It can also be a URL.
- `ssh_username` (string) - The username to use to SSH into the machine once
the OS is installed.
@ -82,10 +82,20 @@ builder.
five seconds and one minute 30 seconds, respectively. If this isn't
specified, the default is 10 seconds.
- `checksum` (string) - The checksum for the OVA file. The type of the
checksum is specified with `checksum_type`, documented below.
- `checksum_type` (string) - The type of the checksum specified in `checksum`.
Valid values are "none", "md5", "sha1", "sha256", or "sha512". Although the
checksum will not be verified when `checksum_type` is set to "none", this is
not recommended since OVA files can be very large and corruption does happen
from time to time.
- `export_opts` (array of strings) - Additional options to pass to the
[VBoxManage export](https://www.virtualbox.org/manual/ch08.html#vboxmanage-export).
This can be useful for passing product information to include in the
resulting appliance file. Packer JSON configuration file example:
[VBoxManage
export](https://www.virtualbox.org/manual/ch08.html#vboxmanage-export). This
can be useful for passing product information to include in the resulting
appliance file. Packer JSON configuration file example:
``` {.json}
{
@ -101,12 +111,13 @@ builder.
}
```
A VirtualBox [VM description](https://www.virtualbox.org/manual/ch08.html#idm3756)
may contain arbitrary strings; the GUI interprets HTML formatting.
However, the JSON format does not allow arbitrary newlines within a
value. Add a multi-line description by preparing the string in the
shell before the packer call like this (shell `>` continuation
character snipped for easier copy & paste):
A VirtualBox [VM
description](https://www.virtualbox.org/manual/ch08.html#idm3756) may
contain arbitrary strings; the GUI interprets HTML formatting. However, the
JSON format does not allow arbitrary newlines within a value. Add a
multi-line description by preparing the string in the shell before the
packer call like this (shell `>` continuation character snipped for easier
copy & paste):
``` {.shell}
@ -132,11 +143,11 @@ builder.
and \[\]) are allowed. Directory names are also allowed, which will add all
the files found in the directory to the floppy.
- `floppy_dirs` (array of strings) - A list of directories to place onto
the floppy disk recursively. This is similar to the `floppy_files` option
except that the directory structure is preserved. This is useful for when
your floppy disk includes drivers or if you just want to organize it's
contents as a hierarchy. Wildcard characters (\*, ?, and \[\]) are allowed.
- `floppy_dirs` (array of strings) - A list of directories to place onto the
floppy disk recursively. This is similar to the `floppy_files` option except
that the directory structure is preserved. This is useful for when your
floppy disk includes drivers or if you just want to organize it's contents
as a hierarchy. Wildcard characters (\*, ?, and \[\]) are allowed.
- `format` (string) - Either "ovf" or "ova", this specifies the output format
of the exported virtual machine. This defaults to "ovf".
@ -201,9 +212,9 @@ builder.
name of the build.
- `post_shutdown_delay` (string) - The amount of time to wait after shutting
down the virtual machine. If you get the error `Error removing floppy
controller`, you might need to set this to `5m` or so. By default, the
delay is `0s`, or disabled.
down the virtual machine. If you get the error
`Error removing floppy controller`, you might need to set this to `5m`
or so. By default, the delay is `0s`, or disabled.
- `shutdown_command` (string) - The command to use to gracefully shut down the
machine once all the provisioning is done. By default this is an empty
@ -228,6 +239,10 @@ builder.
does not setup forwarded port mapping for SSH requests and uses `ssh_port`
on the host to communicate to the virtual machine
- `target_path` (string) - The path where the OVA should be saved
after download. By default, it will go in the packer cache, with a hash of
the original filename as its name.
- `vboxmanage` (array of array of strings) - Custom `VBoxManage` commands to
execute in order to further customize the virtual machine being created. The
value of this is an array of commands to execute. The commands are executed
@ -254,8 +269,8 @@ builder.
is exported. By default this is "packer-BUILDNAME", where "BUILDNAME" is the
name of the build.
- `vrdp_bind_address` (string / IP address) - The IP address that should be binded
to for VRDP. By default packer will use 127.0.0.1 for this.
- `vrdp_bind_address` (string / IP address) - The IP address that should be
binded to for VRDP. By default packer will use 127.0.0.1 for this.
- `vrdp_port_min` and `vrdp_port_max` (integer) - The minimum and maximum port
to use for VRDP access to the virtual machine. Packer uses a randomly chosen
@ -307,9 +322,11 @@ by the proper key:
- `<leftAltOn>` `<rightAltOn>` - Simulates pressing and holding the alt key.
- `<leftCtrlOn>` `<rightCtrlOn>` - Simulates pressing and holding the ctrl key.
- `<leftCtrlOn>` `<rightCtrlOn>` - Simulates pressing and holding the
ctrl key.
- `<leftShiftOn>` `<rightShiftOn>` - Simulates pressing and holding the shift key.
- `<leftShiftOn>` `<rightShiftOn>` - Simulates pressing and holding the
shift key.
- `<leftAltOff>` `<rightAltOff>` - Simulates releasing a held alt key.