github.com/amanya/packer@v0.12.1-0.20161117214323-902ac5ab2eb6/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  		&StepGetPassword{
    95  			Debug: b.config.PackerDebug,
    96  			Comm:  &b.config.RunConfig.Comm,
    97  		},
    98  		&StepWaitForRackConnect{
    99  			Wait: b.config.RackconnectWait,
   100  		},
   101  		&StepAllocateIp{
   102  			FloatingIpPool: b.config.FloatingIpPool,
   103  			FloatingIp:     b.config.FloatingIp,
   104  		},
   105  		&communicator.StepConnect{
   106  			Config: &b.config.RunConfig.Comm,
   107  			Host: CommHost(
   108  				computeClient,
   109  				b.config.SSHInterface,
   110  				b.config.SSHIPVersion),
   111  			SSHConfig: SSHConfig(b.config.RunConfig.Comm.SSHUsername,
   112  				b.config.RunConfig.Comm.SSHPassword),
   113  		},
   114  		&common.StepProvision{},
   115  		&StepStopServer{},
   116  		&stepCreateImage{},
   117  	}
   118  
   119  	// Run!
   120  	b.runner = common.NewRunner(steps, b.config.PackerConfig, ui)
   121  	b.runner.Run(state)
   122  
   123  	// If there was an error, return that
   124  	if rawErr, ok := state.GetOk("error"); ok {
   125  		return nil, rawErr.(error)
   126  	}
   127  
   128  	// If there are no images, then just return
   129  	if _, ok := state.GetOk("image"); !ok {
   130  		return nil, nil
   131  	}
   132  
   133  	// Build the artifact and return it
   134  	artifact := &Artifact{
   135  		ImageId:        state.Get("image").(string),
   136  		BuilderIdValue: BuilderId,
   137  		Client:         computeClient,
   138  	}
   139  
   140  	return artifact, nil
   141  }
   142  
   143  func (b *Builder) Cancel() {
   144  	if b.runner != nil {
   145  		log.Println("Cancelling the step runner...")
   146  		b.runner.Cancel()
   147  	}
   148  }