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  }