github.com/emate/packer@v0.8.1-0.20150625195101-fe0fde195dc6/builder/virtualbox/ovf/builder.go (about) 1 package ovf 2 3 import ( 4 "errors" 5 "fmt" 6 "log" 7 "math/rand" 8 "time" 9 10 "github.com/mitchellh/multistep" 11 vboxcommon "github.com/mitchellh/packer/builder/virtualbox/common" 12 "github.com/mitchellh/packer/common" 13 "github.com/mitchellh/packer/helper/communicator" 14 "github.com/mitchellh/packer/packer" 15 ) 16 17 // Builder implements packer.Builder and builds the actual VirtualBox 18 // images. 19 type Builder struct { 20 config *Config 21 runner multistep.Runner 22 } 23 24 // Prepare processes the build configuration parameters. 25 func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { 26 c, warnings, errs := NewConfig(raws...) 27 if errs != nil { 28 return warnings, errs 29 } 30 b.config = c 31 32 return warnings, nil 33 } 34 35 // Run executes a Packer build and returns a packer.Artifact representing 36 // a VirtualBox appliance. 37 func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) { 38 // Seed the random number generator 39 rand.Seed(time.Now().UTC().UnixNano()) 40 41 // Create the driver that we'll use to communicate with VirtualBox 42 driver, err := vboxcommon.NewDriver() 43 if err != nil { 44 return nil, fmt.Errorf("Failed creating VirtualBox driver: %s", err) 45 } 46 47 // Set up the state. 48 state := new(multistep.BasicStateBag) 49 state.Put("config", b.config) 50 state.Put("driver", driver) 51 state.Put("cache", cache) 52 state.Put("hook", hook) 53 state.Put("ui", ui) 54 55 // Build the steps. 56 steps := []multistep.Step{ 57 &vboxcommon.StepOutputDir{ 58 Force: b.config.PackerForce, 59 Path: b.config.OutputDir, 60 }, 61 new(vboxcommon.StepSuppressMessages), 62 &common.StepCreateFloppy{ 63 Files: b.config.FloppyFiles, 64 }, 65 &vboxcommon.StepHTTPServer{ 66 HTTPDir: b.config.HTTPDir, 67 HTTPPortMin: b.config.HTTPPortMin, 68 HTTPPortMax: b.config.HTTPPortMax, 69 }, 70 &vboxcommon.StepDownloadGuestAdditions{ 71 GuestAdditionsMode: b.config.GuestAdditionsMode, 72 GuestAdditionsURL: b.config.GuestAdditionsURL, 73 GuestAdditionsSHA256: b.config.GuestAdditionsSHA256, 74 Ctx: b.config.ctx, 75 }, 76 &StepImport{ 77 Name: b.config.VMName, 78 SourcePath: b.config.SourcePath, 79 ImportFlags: b.config.ImportFlags, 80 }, 81 &vboxcommon.StepAttachGuestAdditions{ 82 GuestAdditionsMode: b.config.GuestAdditionsMode, 83 }, 84 new(vboxcommon.StepAttachFloppy), 85 &vboxcommon.StepForwardSSH{ 86 CommConfig: &b.config.SSHConfig.Comm, 87 HostPortMin: b.config.SSHHostPortMin, 88 HostPortMax: b.config.SSHHostPortMax, 89 SkipNatMapping: b.config.SSHSkipNatMapping, 90 }, 91 &vboxcommon.StepVBoxManage{ 92 Commands: b.config.VBoxManage, 93 Ctx: b.config.ctx, 94 }, 95 &vboxcommon.StepRun{ 96 BootWait: b.config.BootWait, 97 Headless: b.config.Headless, 98 }, 99 &vboxcommon.StepTypeBootCommand{ 100 BootCommand: b.config.BootCommand, 101 VMName: b.config.VMName, 102 Ctx: b.config.ctx, 103 }, 104 &communicator.StepConnect{ 105 Config: &b.config.SSHConfig.Comm, 106 Host: vboxcommon.CommHost, 107 SSHConfig: vboxcommon.SSHConfigFunc(b.config.SSHConfig), 108 SSHPort: vboxcommon.SSHPort, 109 }, 110 &vboxcommon.StepUploadVersion{ 111 Path: b.config.VBoxVersionFile, 112 }, 113 &vboxcommon.StepUploadGuestAdditions{ 114 GuestAdditionsMode: b.config.GuestAdditionsMode, 115 GuestAdditionsPath: b.config.GuestAdditionsPath, 116 Ctx: b.config.ctx, 117 }, 118 new(common.StepProvision), 119 &vboxcommon.StepShutdown{ 120 Command: b.config.ShutdownCommand, 121 Timeout: b.config.ShutdownTimeout, 122 }, 123 new(vboxcommon.StepRemoveDevices), 124 &vboxcommon.StepVBoxManage{ 125 Commands: b.config.VBoxManagePost, 126 Ctx: b.config.ctx, 127 }, 128 &vboxcommon.StepExport{ 129 Format: b.config.Format, 130 OutputDir: b.config.OutputDir, 131 ExportOpts: b.config.ExportOpts.ExportOpts, 132 SkipNatMapping: b.config.SSHSkipNatMapping, 133 }, 134 } 135 136 // Run the steps. 137 if b.config.PackerDebug { 138 b.runner = &multistep.DebugRunner{ 139 Steps: steps, 140 PauseFn: common.MultistepDebugFn(ui), 141 } 142 } else { 143 b.runner = &multistep.BasicRunner{Steps: steps} 144 } 145 b.runner.Run(state) 146 147 // Report any errors. 148 if rawErr, ok := state.GetOk("error"); ok { 149 return nil, rawErr.(error) 150 } 151 152 // If we were interrupted or cancelled, then just exit. 153 if _, ok := state.GetOk(multistep.StateCancelled); ok { 154 return nil, errors.New("Build was cancelled.") 155 } 156 157 if _, ok := state.GetOk(multistep.StateHalted); ok { 158 return nil, errors.New("Build was halted.") 159 } 160 161 return vboxcommon.NewArtifact(b.config.OutputDir) 162 } 163 164 // Cancel. 165 func (b *Builder) Cancel() { 166 if b.runner != nil { 167 log.Println("Cancelling the step runner...") 168 b.runner.Cancel() 169 } 170 }