github.com/rothwerx/packer@v0.9.0/builder/openstack/builder.go (about)

     1  // The openstack package contains a packer.Builder implementation that
     2  // builds Images for openstack.
     3  
     4  package openstack
     5  
     6  import (
     7  	"fmt"
     8  	"log"
     9  
    10  	"github.com/mitchellh/multistep"
    11  	"github.com/mitchellh/packer/common"
    12  	"github.com/mitchellh/packer/helper/communicator"
    13  	"github.com/mitchellh/packer/helper/config"
    14  	"github.com/mitchellh/packer/packer"
    15  	"github.com/mitchellh/packer/template/interpolate"
    16  )
    17  
    18  // The unique ID for this builder
    19  const BuilderId = "mitchellh.openstack"
    20  
    21  type Config struct {
    22  	common.PackerConfig `mapstructure:",squash"`
    23  
    24  	AccessConfig `mapstructure:",squash"`
    25  	ImageConfig  `mapstructure:",squash"`
    26  	RunConfig    `mapstructure:",squash"`
    27  
    28  	ctx interpolate.Context
    29  }
    30  
    31  type Builder struct {
    32  	config Config
    33  	runner multistep.Runner
    34  }
    35  
    36  func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
    37  	err := config.Decode(&b.config, &config.DecodeOpts{
    38  		Interpolate:        true,
    39  		InterpolateContext: &b.config.ctx,
    40  	}, raws...)
    41  	if err != nil {
    42  		return nil, err
    43  	}
    44  
    45  	// Accumulate any errors
    46  	var errs *packer.MultiError
    47  	errs = packer.MultiErrorAppend(errs, b.config.AccessConfig.Prepare(&b.config.ctx)...)
    48  	errs = packer.MultiErrorAppend(errs, b.config.ImageConfig.Prepare(&b.config.ctx)...)
    49  	errs = packer.MultiErrorAppend(errs, b.config.RunConfig.Prepare(&b.config.ctx)...)
    50  
    51  	if errs != nil && len(errs.Errors) > 0 {
    52  		return nil, errs
    53  	}
    54  
    55  	log.Println(common.ScrubConfig(b.config, b.config.Password))
    56  	return nil, nil
    57  }
    58  
    59  func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
    60  	computeClient, err := b.config.computeV2Client()
    61  	if err != nil {
    62  		return nil, fmt.Errorf("Error initializing compute client: %s", err)
    63  	}
    64  
    65  	// Setup the state bag and initial state for the steps
    66  	state := new(multistep.BasicStateBag)
    67  	state.Put("config", b.config)
    68  	state.Put("hook", hook)
    69  	state.Put("ui", ui)
    70  
    71  	// Build the steps
    72  	steps := []multistep.Step{
    73  		&StepLoadExtensions{},
    74  		&StepLoadFlavor{
    75  			Flavor: b.config.Flavor,
    76  		},
    77  		&StepKeyPair{
    78  			Debug:          b.config.PackerDebug,
    79  			DebugKeyPath:   fmt.Sprintf("os_%s.pem", b.config.PackerBuildName),
    80  			KeyPairName:    b.config.SSHKeyPairName,
    81  			PrivateKeyFile: b.config.RunConfig.Comm.SSHPrivateKey,
    82  		},
    83  		&StepRunSourceServer{
    84  			Name:             b.config.ImageName,
    85  			SourceImage:      b.config.SourceImage,
    86  			SourceImageName:  b.config.SourceImageName,
    87  			SecurityGroups:   b.config.SecurityGroups,
    88  			Networks:         b.config.Networks,
    89  			AvailabilityZone: b.config.AvailabilityZone,
    90  			UserData:         b.config.UserData,
    91  			UserDataFile:     b.config.UserDataFile,
    92  			ConfigDrive:      b.config.ConfigDrive,
    93  		},
    94  		&StepWaitForRackConnect{
    95  			Wait: b.config.RackconnectWait,
    96  		},
    97  		&StepAllocateIp{
    98  			FloatingIpPool: b.config.FloatingIpPool,
    99  			FloatingIp:     b.config.FloatingIp,
   100  		},
   101  		&communicator.StepConnect{
   102  			Config: &b.config.RunConfig.Comm,
   103  			Host: CommHost(
   104  				computeClient,
   105  				b.config.SSHInterface,
   106  				b.config.SSHIPVersion),
   107  			SSHConfig: SSHConfig(b.config.RunConfig.Comm.SSHUsername),
   108  		},
   109  		&common.StepProvision{},
   110  		&StepStopServer{},
   111  		&stepCreateImage{},
   112  	}
   113  
   114  	// Run!
   115  	if b.config.PackerDebug {
   116  		b.runner = &multistep.DebugRunner{
   117  			Steps:   steps,
   118  			PauseFn: common.MultistepDebugFn(ui),
   119  		}
   120  	} else {
   121  		b.runner = &multistep.BasicRunner{Steps: steps}
   122  	}
   123  
   124  	b.runner.Run(state)
   125  
   126  	// If there was an error, return that
   127  	if rawErr, ok := state.GetOk("error"); ok {
   128  		return nil, rawErr.(error)
   129  	}
   130  
   131  	// If there are no images, then just return
   132  	if _, ok := state.GetOk("image"); !ok {
   133  		return nil, nil
   134  	}
   135  
   136  	// Build the artifact and return it
   137  	artifact := &Artifact{
   138  		ImageId:        state.Get("image").(string),
   139  		BuilderIdValue: BuilderId,
   140  		Client:         computeClient,
   141  	}
   142  
   143  	return artifact, nil
   144  }
   145  
   146  func (b *Builder) Cancel() {
   147  	if b.runner != nil {
   148  		log.Println("Cancelling the step runner...")
   149  		b.runner.Cancel()
   150  	}
   151  }