From 337856811ecb6d733f175fd67e63a83190cfd005 Mon Sep 17 00:00:00 2001 From: Arthur Burkart Date: Mon, 10 Oct 2016 22:16:25 -0400 Subject: [PATCH] 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. --- builder/virtualbox/ovf/builder.go | 10 ++- builder/virtualbox/ovf/config.go | 13 +++- builder/virtualbox/ovf/config_test.go | 78 ++++++++++++------- builder/virtualbox/ovf/step_import.go | 6 +- builder/virtualbox/ovf/step_import_test.go | 5 +- .../docs/builders/virtualbox-iso.html.md | 58 +++++++------- .../docs/builders/virtualbox-ovf.html.md | 67 ++++++++++------ 7 files changed, 142 insertions(+), 95 deletions(-) diff --git a/builder/virtualbox/ovf/builder.go b/builder/virtualbox/ovf/builder.go index a0f8811ee..bb992ab74 100644 --- a/builder/virtualbox/ovf/builder.go +++ b/builder/virtualbox/ovf/builder.go @@ -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{ diff --git a/builder/virtualbox/ovf/config.go b/builder/virtualbox/ovf/config.go index 0866a6205..5987118cd 100644 --- a/builder/virtualbox/ovf/config.go +++ b/builder/virtualbox/ovf/config.go @@ -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)) } } diff --git a/builder/virtualbox/ovf/config_test.go b/builder/virtualbox/ovf/config_test.go index 04c5c71d4..3de527acd 100644 --- a/builder/virtualbox/ovf/config_test.go +++ b/builder/virtualbox/ovf/config_test.go @@ -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) + } } diff --git a/builder/virtualbox/ovf/step_import.go b/builder/virtualbox/ovf/step_import.go index b9a74c9f8..2d8887444 100644 --- a/builder/virtualbox/ovf/step_import.go +++ b/builder/virtualbox/ovf/step_import.go @@ -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()) diff --git a/builder/virtualbox/ovf/step_import_test.go b/builder/virtualbox/ovf/step_import_test.go index e31d53791..7d535dc05 100644 --- a/builder/virtualbox/ovf/step_import_test.go +++ b/builder/virtualbox/ovf/step_import_test.go @@ -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 { diff --git a/website/source/docs/builders/virtualbox-iso.html.md b/website/source/docs/builders/virtualbox-iso.html.md index 641cc0158..78c6ceb71 100644 --- a/website/source/docs/builders/virtualbox-iso.html.md +++ b/website/source/docs/builders/virtualbox-iso.html.md @@ -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 @@ -349,19 +349,21 @@ by the proper key: - `` `` - Simulates pressing the page up and page down keys. -- `` `` - Simulates pressing the alt key. +- `` `` - Simulates pressing the alt key. - `` `` - Simulates pressing the ctrl key. - `` `` - Simulates pressing the shift key. -- `` `` - Simulates pressing and holding the alt key. +- `` `` - Simulates pressing and holding the alt key. -- `` `` - Simulates pressing and holding the ctrl key. +- `` `` - Simulates pressing and holding the + ctrl key. -- `` `` - Simulates pressing and holding the shift key. +- `` `` - Simulates pressing and holding the + shift key. -- `` `` - Simulates releasing a held alt key. +- `` `` - Simulates releasing a held alt key. - `` `` - Simulates releasing a held ctrl key. diff --git a/website/source/docs/builders/virtualbox-ovf.html.md b/website/source/docs/builders/virtualbox-ovf.html.md index 0d4f29619..6b0f73ee3 100644 --- a/website/source/docs/builders/virtualbox-ovf.html.md +++ b/website/source/docs/builders/virtualbox-ovf.html.md @@ -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 @@ -299,19 +314,21 @@ by the proper key: - `` `` - Simulates pressing the page up and page down keys. -- `` `` - Simulates pressing the alt key. +- `` `` - Simulates pressing the alt key. - `` `` - Simulates pressing the ctrl key. - `` `` - Simulates pressing the shift key. -- `` `` - Simulates pressing and holding the alt key. +- `` `` - Simulates pressing and holding the alt key. -- `` `` - Simulates pressing and holding the ctrl key. +- `` `` - Simulates pressing and holding the + ctrl key. -- `` `` - Simulates pressing and holding the shift key. +- `` `` - Simulates pressing and holding the + shift key. -- `` `` - Simulates releasing a held alt key. +- `` `` - Simulates releasing a held alt key. - `` `` - Simulates releasing a held ctrl key.