github.phpd.cn/hashicorp/packer@v1.3.2/builder/cloudstack/builder.go (about) 1 package cloudstack 2 3 import ( 4 "fmt" 5 6 "github.com/hashicorp/packer/common" 7 "github.com/hashicorp/packer/helper/communicator" 8 "github.com/hashicorp/packer/helper/multistep" 9 "github.com/hashicorp/packer/packer" 10 "github.com/xanzy/go-cloudstack/cloudstack" 11 ) 12 13 const BuilderId = "packer.cloudstack" 14 15 // Builder represents the CloudStack builder. 16 type Builder struct { 17 config *Config 18 runner multistep.Runner 19 ui packer.Ui 20 } 21 22 // Prepare implements the packer.Builder interface. 23 func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { 24 config, errs := NewConfig(raws...) 25 if errs != nil { 26 return nil, errs 27 } 28 b.config = config 29 30 return nil, nil 31 } 32 33 // Run implements the packer.Builder interface. 34 func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) { 35 b.ui = ui 36 37 // Create a CloudStack API client. 38 client := cloudstack.NewAsyncClient( 39 b.config.APIURL, 40 b.config.APIKey, 41 b.config.SecretKey, 42 !b.config.SSLNoVerify, 43 ) 44 45 // Set the time to wait before timing out 46 client.AsyncTimeout(int64(b.config.AsyncTimeout.Seconds())) 47 48 // Some CloudStack service providers only allow HTTP GET calls. 49 client.HTTPGETOnly = b.config.HTTPGetOnly 50 51 // Set up the state. 52 state := new(multistep.BasicStateBag) 53 state.Put("client", client) 54 state.Put("config", b.config) 55 state.Put("hook", hook) 56 state.Put("ui", ui) 57 58 // Build the steps. 59 steps := []multistep.Step{ 60 &stepPrepareConfig{}, 61 &common.StepHTTPServer{ 62 HTTPDir: b.config.HTTPDir, 63 HTTPPortMin: b.config.HTTPPortMin, 64 HTTPPortMax: b.config.HTTPPortMax, 65 }, 66 &stepKeypair{ 67 Debug: b.config.PackerDebug, 68 Comm: &b.config.Comm, 69 DebugKeyPath: fmt.Sprintf("cs_%s.pem", b.config.PackerBuildName), 70 }, 71 &stepCreateSecurityGroup{}, 72 &stepCreateInstance{ 73 Ctx: b.config.ctx, 74 Debug: b.config.PackerDebug, 75 }, 76 &stepSetupNetworking{}, 77 &communicator.StepConnect{ 78 Config: &b.config.Comm, 79 Host: commHost, 80 SSHConfig: b.config.Comm.SSHConfigFunc(), 81 SSHPort: commPort, 82 WinRMPort: commPort, 83 }, 84 &common.StepProvision{}, 85 &common.StepCleanupTempKeys{ 86 Comm: &b.config.Comm, 87 }, 88 &stepShutdownInstance{}, 89 &stepCreateTemplate{}, 90 } 91 92 // Configure the runner and run the steps. 93 b.runner = common.NewRunner(steps, b.config.PackerConfig, ui) 94 b.runner.Run(state) 95 96 // If there was an error, return that 97 if rawErr, ok := state.GetOk("error"); ok { 98 ui.Error(rawErr.(error).Error()) 99 return nil, rawErr.(error) 100 } 101 102 // If there was no template created, just return 103 if _, ok := state.GetOk("template"); !ok { 104 return nil, nil 105 } 106 107 // Build the artifact and return it 108 artifact := &Artifact{ 109 client: client, 110 config: b.config, 111 template: state.Get("template").(*cloudstack.CreateTemplateResponse), 112 } 113 114 return artifact, nil 115 } 116 117 // Cancel the step runner. 118 func (b *Builder) Cancel() { 119 if b.runner != nil { 120 b.ui.Say("Cancelling the step runner...") 121 b.runner.Cancel() 122 } 123 }