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 }