diff --git a/builder/hyperv/common/step_type_boot_command.go b/builder/hyperv/common/step_type_boot_command.go index 4af792eff..2955813d4 100644 --- a/builder/hyperv/common/step_type_boot_command.go +++ b/builder/hyperv/common/step_type_boot_command.go @@ -8,6 +8,7 @@ import ( "unicode/utf8" "github.com/mitchellh/multistep" + "github.com/mitchellh/packer/common" "github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/template/interpolate" ) @@ -42,6 +43,7 @@ func (s *StepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction ui.Say(fmt.Sprintf("Host IP for the HyperV machine: %s", hostIp)) + common.SetHTTPIP(hostIp) s.Ctx.Data = &bootCommandTemplateData{ hostIp, httpPort, diff --git a/builder/parallels/common/step_type_boot_command.go b/builder/parallels/common/step_type_boot_command.go index 5d116f077..01f9743cb 100644 --- a/builder/parallels/common/step_type_boot_command.go +++ b/builder/parallels/common/step_type_boot_command.go @@ -9,6 +9,7 @@ import ( "unicode/utf8" "github.com/mitchellh/multistep" + packer_common "github.com/mitchellh/packer/common" "github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/template/interpolate" ) @@ -67,6 +68,7 @@ func (s *StepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction ui.Say(fmt.Sprintf("Host IP for the Parallels machine: %s", hostIP)) + packer_common.SetHTTPIP(hostIP) s.Ctx.Data = &bootCommandTemplateData{ hostIP, httpPort, diff --git a/builder/qemu/step_type_boot_command.go b/builder/qemu/step_type_boot_command.go index af9334818..2ec581685 100644 --- a/builder/qemu/step_type_boot_command.go +++ b/builder/qemu/step_type_boot_command.go @@ -72,9 +72,11 @@ func (s *stepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction log.Printf("Connected to VNC desktop: %s", c.DesktopName) + hostIP := "10.0.2.2" + common.SetHTTPIP(hostIP) ctx := config.ctx ctx.Data = &bootCommandTemplateData{ - "10.0.2.2", + hostIP, httpPort, config.VMName, } diff --git a/builder/virtualbox/common/step_type_boot_command.go b/builder/virtualbox/common/step_type_boot_command.go index 7bccc70c6..26d5a9658 100644 --- a/builder/virtualbox/common/step_type_boot_command.go +++ b/builder/virtualbox/common/step_type_boot_command.go @@ -9,6 +9,7 @@ import ( "unicode/utf8" "github.com/mitchellh/multistep" + "github.com/mitchellh/packer/common" "github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/template/interpolate" ) @@ -49,8 +50,10 @@ func (s *StepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction pauseFn = state.Get("pauseFn").(multistep.DebugPauseFn) } + hostIP := "10.0.2.2" + common.SetHTTPIP(hostIP) s.Ctx.Data = &bootCommandTemplateData{ - "10.0.2.2", + hostIP, httpPort, s.VMName, } diff --git a/builder/vmware/common/step_type_boot_command.go b/builder/vmware/common/step_type_boot_command.go index b3cc02b79..f4d7367c8 100644 --- a/builder/vmware/common/step_type_boot_command.go +++ b/builder/vmware/common/step_type_boot_command.go @@ -95,7 +95,7 @@ func (s *StepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction ipFinder = &IfconfigIPFinder{Device: "vmnet8"} } - hostIp, err := ipFinder.HostIP() + hostIP, err := ipFinder.HostIP() if err != nil { err := fmt.Errorf("Error detecting host IP: %s", err) state.Put("error", err) @@ -103,10 +103,11 @@ func (s *StepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction return multistep.ActionHalt } - log.Printf("Host IP for the VMware machine: %s", hostIp) + log.Printf("Host IP for the VMware machine: %s", hostIP) + common.SetHTTPIP(hostIP) s.Ctx.Data = &bootCommandTemplateData{ - hostIp, + hostIP, httpPort, s.VMName, } diff --git a/common/step_http_server.go b/common/step_http_server.go index 55874992e..6dbef6011 100644 --- a/common/step_http_server.go +++ b/common/step_http_server.go @@ -2,12 +2,16 @@ package common import ( "fmt" - "github.com/mitchellh/multistep" - "github.com/mitchellh/packer/packer" + "io/ioutil" "log" "math/rand" "net" "net/http" + "os" + "path/filepath" + + "github.com/mitchellh/multistep" + "github.com/mitchellh/packer/packer" ) // This step creates and runs the HTTP server that is serving files from the @@ -66,13 +70,41 @@ func (s *StepHTTPServer) Run(state multistep.StateBag) multistep.StepAction { // Save the address into the state so it can be accessed in the future state.Put("http_port", httpPort) + SetHTTPPort(fmt.Sprintf("%d", httpPort)) return multistep.ActionContinue } +func httpAddrFilename(suffix string) string { + uuid := os.Getenv("PACKER_RUN_UUID") + return filepath.Join(os.TempDir(), fmt.Sprintf("packer-%s-%s", uuid, suffix)) +} + +func SetHTTPPort(port string) error { + return ioutil.WriteFile(httpAddrFilename("port"), []byte(port), 0644) +} + +func SetHTTPIP(ip string) error { + return ioutil.WriteFile(httpAddrFilename("ip"), []byte(ip), 0644) +} + +func GetHTTPAddr() string { + ip, err := ioutil.ReadFile(httpAddrFilename("ip")) + if err != nil { + return "" + } + port, err := ioutil.ReadFile(httpAddrFilename("port")) + if err != nil { + return "" + } + return fmt.Sprintf("%s:%s", ip, port) +} + func (s *StepHTTPServer) Cleanup(multistep.StateBag) { if s.l != nil { // Close the listener so that the HTTP server stops s.l.Close() } + os.Remove(httpAddrFilename("port")) + os.Remove(httpAddrFilename("ip")) } diff --git a/provisioner/powershell/provisioner.go b/provisioner/powershell/provisioner.go index 3f0f0b9dd..b62d35b91 100644 --- a/provisioner/powershell/provisioner.go +++ b/provisioner/powershell/provisioner.go @@ -234,12 +234,6 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error { scripts := make([]string, len(p.config.Scripts)) copy(scripts, p.config.Scripts) - // Build our variables up by adding in the build name and builder type - envVars := make([]string, len(p.config.Vars)+2) - envVars[0] = "PACKER_BUILD_NAME=" + p.config.PackerBuildName - envVars[1] = "PACKER_BUILDER_TYPE=" + p.config.PackerBuilderType - copy(envVars, p.config.Vars) - if p.config.Inline != nil { temp, err := extractScript(p) if err != nil { @@ -344,6 +338,10 @@ func (p *Provisioner) createFlattenedEnvVars(elevated bool) (flattened string, e // Always available Packer provided env vars envVars["PACKER_BUILD_NAME"] = p.config.PackerBuildName envVars["PACKER_BUILDER_TYPE"] = p.config.PackerBuilderType + httpAddr := common.GetHTTPAddr() + if httpAddr != "" { + envVars["PACKER_HTTP_ADDR"] = httpAddr + } // Split vars into key/value components for _, envVar := range p.config.Vars { diff --git a/provisioner/shell/provisioner.go b/provisioner/shell/provisioner.go index 00a81bf30..c37f8df6b 100644 --- a/provisioner/shell/provisioner.go +++ b/provisioner/shell/provisioner.go @@ -232,7 +232,12 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error { envVars := make([]string, len(p.config.Vars)+2) envVars[0] = fmt.Sprintf("PACKER_BUILD_NAME='%s'", p.config.PackerBuildName) envVars[1] = fmt.Sprintf("PACKER_BUILDER_TYPE='%s'", p.config.PackerBuilderType) + copy(envVars[2:], p.config.Vars) + httpAddr := common.GetHTTPAddr() + if httpAddr != "" { + envVars = append(envVars, fmt.Sprintf("PACKER_HTTP_ADDR=%s", common.GetHTTPAddr())) + } for _, path := range scripts { ui.Say(fmt.Sprintf("Provisioning with shell script: %s", path)) diff --git a/provisioner/windows-shell/provisioner.go b/provisioner/windows-shell/provisioner.go index 6f58bcb9e..60d085008 100644 --- a/provisioner/windows-shell/provisioner.go +++ b/provisioner/windows-shell/provisioner.go @@ -188,13 +188,6 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error { scripts := make([]string, len(p.config.Scripts)) copy(scripts, p.config.Scripts) - // Build our variables up by adding in the build name and builder type - envVars := make([]string, len(p.config.Vars)+2) - envVars[0] = "PACKER_BUILD_NAME=" + p.config.PackerBuildName - envVars[1] = "PACKER_BUILDER_TYPE=" + p.config.PackerBuilderType - - copy(envVars, p.config.Vars) - if p.config.Inline != nil { temp, err := extractScript(p) if err != nil { @@ -301,6 +294,10 @@ func (p *Provisioner) createFlattenedEnvVars() (flattened string, err error) { // Always available Packer provided env vars envVars["PACKER_BUILD_NAME"] = p.config.PackerBuildName envVars["PACKER_BUILDER_TYPE"] = p.config.PackerBuilderType + httpAddr := common.GetHTTPAddr() + if httpAddr != "" { + envVars["PACKER_HTTP_ADDR"] = httpAddr + } // Split vars into key/value components for _, envVar := range p.config.Vars { diff --git a/website/source/docs/provisioners/powershell.html.md b/website/source/docs/provisioners/powershell.html.md index 245b78e76..95f63b9de 100644 --- a/website/source/docs/provisioners/powershell.html.md +++ b/website/source/docs/provisioners/powershell.html.md @@ -82,3 +82,25 @@ Optional parameters: - `valid_exit_codes` (list of ints) - Valid exit codes for the script. By default this is just 0. + + +## Default Environmental Variables + +In addition to being able to specify custom environmental variables using the +`environment_vars` configuration, the provisioner automatically defines certain +commonly useful environmental variables: + +- `PACKER_BUILD_NAME` is set to the name of the build that Packer is running. + This is most useful when Packer is making multiple builds and you want to + distinguish them slightly from a common provisioning script. + +- `PACKER_BUILDER_TYPE` is the type of the builder that was used to create the + machine that the script is running on. This is useful if you want to run + only certain parts of the script on systems built with certain builders. + +- `PACKER_HTTP_ADDR` If using a builder that provides an http server for file + transfer (such as hyperv, parallels, qemu, virtualbox, and vmware), this + will be set to the address. You can use this address in your provisioner to + download large files over http. This may be useful if you're experiencing + slower speeds using the default file provisioner. A file provisioner using + the `winrm` communicator may experience these types of difficulties. diff --git a/website/source/docs/provisioners/shell.html.md b/website/source/docs/provisioners/shell.html.md index 4d1699342..8012e62fb 100644 --- a/website/source/docs/provisioners/shell.html.md +++ b/website/source/docs/provisioners/shell.html.md @@ -149,6 +149,13 @@ commonly useful environmental variables: machine that the script is running on. This is useful if you want to run only certain parts of the script on systems built with certain builders. +- `PACKER_HTTP_ADDR` If using a builder that provides an http server for file + transfer (such as hyperv, parallels, qemu, virtualbox, and vmware), this + will be set to the address. You can use this address in your provisioner to + download large files over http. This may be useful if you're experiencing + slower speeds using the default file provisioner. A file provisioner using + the `winrm` communicator may experience these types of difficulties. + ## Handling Reboots Provisioning sometimes involves restarts, usually when updating the operating diff --git a/website/source/docs/provisioners/windows-shell.html.md b/website/source/docs/provisioners/windows-shell.html.md index a3d80a63a..295fcfba0 100644 --- a/website/source/docs/provisioners/windows-shell.html.md +++ b/website/source/docs/provisioners/windows-shell.html.md @@ -73,3 +73,25 @@ Optional parameters: exists in order to deal with times when SSH may restart, such as a system reboot. Set this to a higher value if reboots take a longer amount of time. + + +## Default Environmental Variables + +In addition to being able to specify custom environmental variables using the +`environment_vars` configuration, the provisioner automatically defines certain +commonly useful environmental variables: + +- `PACKER_BUILD_NAME` is set to the name of the build that Packer is running. + This is most useful when Packer is making multiple builds and you want to + distinguish them slightly from a common provisioning script. + +- `PACKER_BUILDER_TYPE` is the type of the builder that was used to create the + machine that the script is running on. This is useful if you want to run + only certain parts of the script on systems built with certain builders. + +- `PACKER_HTTP_ADDR` If using a builder that provides an http server for file + transfer (such as hyperv, parallels, qemu, virtualbox, and vmware), this + will be set to the address. You can use this address in your provisioner to + download large files over http. This may be useful if you're experiencing + slower speeds using the default file provisioner. A file provisioner using + the `winrm` communicator may experience these types of difficulties.