github.com/daniellockard/packer@v0.7.6-0.20141210173435-5a9390934716/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  	"log"
    12  
    13  	"github.com/mitchellh/gophercloud-fork-40444fb"
    14  )
    15  
    16  // The unique ID for this builder
    17  const BuilderId = "mitchellh.openstack"
    18  
    19  type config struct {
    20  	common.PackerConfig `mapstructure:",squash"`
    21  	AccessConfig        `mapstructure:",squash"`
    22  	ImageConfig         `mapstructure:",squash"`
    23  	RunConfig           `mapstructure:",squash"`
    24  
    25  	tpl *packer.ConfigTemplate
    26  }
    27  
    28  type Builder struct {
    29  	config config
    30  	runner multistep.Runner
    31  }
    32  
    33  func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
    34  	md, err := common.DecodeConfig(&b.config, raws...)
    35  	if err != nil {
    36  		return nil, err
    37  	}
    38  
    39  	b.config.tpl, err = packer.NewConfigTemplate()
    40  	if err != nil {
    41  		return nil, err
    42  	}
    43  	b.config.tpl.UserVars = b.config.PackerUserVars
    44  
    45  	// Accumulate any errors
    46  	errs := common.CheckUnusedConfig(md)
    47  	errs = packer.MultiErrorAppend(errs, b.config.AccessConfig.Prepare(b.config.tpl)...)
    48  	errs = packer.MultiErrorAppend(errs, b.config.ImageConfig.Prepare(b.config.tpl)...)
    49  	errs = packer.MultiErrorAppend(errs, b.config.RunConfig.Prepare(b.config.tpl)...)
    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  	auth, err := b.config.AccessConfig.Auth()
    61  	if err != nil {
    62  		return nil, err
    63  	}
    64  	//fetches the api requisites from gophercloud for the appropriate
    65  	//openstack variant
    66  	api, err := gophercloud.PopulateApi(b.config.RunConfig.OpenstackProvider)
    67  	if err != nil {
    68  		return nil, err
    69  	}
    70  	api.Region = b.config.AccessConfig.Region()
    71  
    72  	csp, err := gophercloud.ServersApi(auth, api)
    73  	if err != nil {
    74  		log.Printf("Region: %s", b.config.AccessConfig.Region())
    75  		return nil, err
    76  	}
    77  
    78  	// Setup the state bag and initial state for the steps
    79  	state := new(multistep.BasicStateBag)
    80  	state.Put("config", b.config)
    81  	state.Put("csp", csp)
    82  	state.Put("hook", hook)
    83  	state.Put("ui", ui)
    84  
    85  	// Build the steps
    86  	steps := []multistep.Step{
    87  		&StepKeyPair{
    88  			Debug:        b.config.PackerDebug,
    89  			DebugKeyPath: fmt.Sprintf("os_%s.pem", b.config.PackerBuildName),
    90  		},
    91  		&StepRunSourceServer{
    92  			Name:           b.config.ImageName,
    93  			Flavor:         b.config.Flavor,
    94  			SourceImage:    b.config.SourceImage,
    95  			SecurityGroups: b.config.SecurityGroups,
    96  			Networks:       b.config.Networks,
    97  		},
    98  		&StepAllocateIp{
    99  			FloatingIpPool: b.config.FloatingIpPool,
   100  			FloatingIp:     b.config.FloatingIp,
   101  		},
   102  		&common.StepConnectSSH{
   103  			SSHAddress:     SSHAddress(csp, b.config.SSHPort),
   104  			SSHConfig:      SSHConfig(b.config.SSHUsername),
   105  			SSHWaitTimeout: b.config.SSHTimeout(),
   106  		},
   107  		&common.StepProvision{},
   108  		&stepCreateImage{},
   109  	}
   110  
   111  	// Run!
   112  	if b.config.PackerDebug {
   113  		b.runner = &multistep.DebugRunner{
   114  			Steps:   steps,
   115  			PauseFn: common.MultistepDebugFn(ui),
   116  		}
   117  	} else {
   118  		b.runner = &multistep.BasicRunner{Steps: steps}
   119  	}
   120  
   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  		Conn:           csp,
   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  }