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