github.com/jerryclinesmith/packer@v0.3.7/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  	"github.com/mitchellh/multistep"
     9  	"github.com/mitchellh/packer/common"
    10  	"github.com/mitchellh/packer/packer"
    11  	"github.com/rackspace/gophercloud"
    12  	"log"
    13  )
    14  
    15  // The unique ID for this builder
    16  const BuilderId = "mitchellh.openstack"
    17  
    18  type config struct {
    19  	common.PackerConfig `mapstructure:",squash"`
    20  	AccessConfig        `mapstructure:",squash"`
    21  	ImageConfig         `mapstructure:",squash"`
    22  	RunConfig           `mapstructure:",squash"`
    23  
    24  	tpl *packer.ConfigTemplate
    25  }
    26  
    27  type Builder struct {
    28  	config config
    29  	runner multistep.Runner
    30  }
    31  
    32  func (b *Builder) Prepare(raws ...interface{}) error {
    33  	md, err := common.DecodeConfig(&b.config, raws...)
    34  	if err != nil {
    35  		return err
    36  	}
    37  
    38  	b.config.tpl, err = packer.NewConfigTemplate()
    39  	if err != nil {
    40  		return err
    41  	}
    42  	b.config.tpl.UserVars = b.config.PackerUserVars
    43  
    44  	// Accumulate any errors
    45  	errs := common.CheckUnusedConfig(md)
    46  	errs = packer.MultiErrorAppend(errs, b.config.AccessConfig.Prepare(b.config.tpl)...)
    47  	errs = packer.MultiErrorAppend(errs, b.config.ImageConfig.Prepare(b.config.tpl)...)
    48  	errs = packer.MultiErrorAppend(errs, b.config.RunConfig.Prepare(b.config.tpl)...)
    49  
    50  	if errs != nil && len(errs.Errors) > 0 {
    51  		return errs
    52  	}
    53  
    54  	log.Printf("Config: %+v", b.config)
    55  	return nil
    56  }
    57  
    58  func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
    59  	auth, err := b.config.AccessConfig.Auth()
    60  	if err != nil {
    61  		return nil, err
    62  	}
    63  	api := &gophercloud.ApiCriteria{
    64  		Name:      "cloudServersOpenStack",
    65  		Region:    b.config.AccessConfig.Region(),
    66  		VersionId: "2",
    67  		UrlChoice: gophercloud.PublicURL,
    68  	}
    69  	csp, err := gophercloud.ServersApi(auth, *api)
    70  	if err != nil {
    71  		log.Printf("Region: %s", b.config.AccessConfig.Region())
    72  		return nil, err
    73  	}
    74  
    75  	// Setup the state bag and initial state for the steps
    76  	state := new(multistep.BasicStateBag)
    77  	state.Put("config", b.config)
    78  	state.Put("csp", csp)
    79  	state.Put("hook", hook)
    80  	state.Put("ui", ui)
    81  
    82  	// Build the steps
    83  	steps := []multistep.Step{
    84  		&StepKeyPair{},
    85  		&StepRunSourceServer{
    86  			Name:        b.config.ImageName,
    87  			Flavor:      b.config.Flavor,
    88  			SourceImage: b.config.SourceImage,
    89  		},
    90  		&common.StepConnectSSH{
    91  			SSHAddress:     SSHAddress(csp, b.config.SSHPort),
    92  			SSHConfig:      SSHConfig(b.config.SSHUsername),
    93  			SSHWaitTimeout: b.config.SSHTimeout(),
    94  		},
    95  		&common.StepProvision{},
    96  		&stepCreateImage{},
    97  	}
    98  
    99  	// Run!
   100  	if b.config.PackerDebug {
   101  		b.runner = &multistep.DebugRunner{
   102  			Steps:   steps,
   103  			PauseFn: common.MultistepDebugFn(ui),
   104  		}
   105  	} else {
   106  		b.runner = &multistep.BasicRunner{Steps: steps}
   107  	}
   108  
   109  	b.runner.Run(state)
   110  
   111  	// If there was an error, return that
   112  	if rawErr, ok := state.GetOk("error"); ok {
   113  		return nil, rawErr.(error)
   114  	}
   115  
   116  	// If there are no images, then just return
   117  	if _, ok := state.GetOk("image"); !ok {
   118  		return nil, nil
   119  	}
   120  
   121  	// Build the artifact and return it
   122  	artifact := &Artifact{
   123  		ImageId:        state.Get("image").(string),
   124  		BuilderIdValue: BuilderId,
   125  		Conn:           csp,
   126  	}
   127  
   128  	return artifact, nil
   129  }
   130  
   131  func (b *Builder) Cancel() {
   132  	if b.runner != nil {
   133  		log.Println("Cancelling the step runner...")
   134  		b.runner.Cancel()
   135  	}
   136  }