github.com/StackPointCloud/packer@v0.10.2-0.20180716202532-b28098e0f79b/builder/openstack/step_run_source_server.go (about) 1 package openstack 2 3 import ( 4 "context" 5 "fmt" 6 "io/ioutil" 7 "log" 8 9 "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/keypairs" 10 "github.com/gophercloud/gophercloud/openstack/compute/v2/servers" 11 "github.com/hashicorp/packer/helper/multistep" 12 "github.com/hashicorp/packer/packer" 13 ) 14 15 type StepRunSourceServer struct { 16 Name string 17 SourceImage string 18 SourceImageName string 19 SecurityGroups []string 20 Networks []string 21 AvailabilityZone string 22 UserData string 23 UserDataFile string 24 ConfigDrive bool 25 InstanceMetadata map[string]string 26 server *servers.Server 27 } 28 29 func (s *StepRunSourceServer) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { 30 config := state.Get("config").(Config) 31 flavor := state.Get("flavor_id").(string) 32 ui := state.Get("ui").(packer.Ui) 33 34 // We need the v2 compute client 35 computeClient, err := config.computeV2Client() 36 if err != nil { 37 err = fmt.Errorf("Error initializing compute client: %s", err) 38 state.Put("error", err) 39 return multistep.ActionHalt 40 } 41 42 networks := make([]servers.Network, len(s.Networks)) 43 for i, networkUuid := range s.Networks { 44 networks[i].UUID = networkUuid 45 } 46 47 userData := []byte(s.UserData) 48 if s.UserDataFile != "" { 49 userData, err = ioutil.ReadFile(s.UserDataFile) 50 if err != nil { 51 err = fmt.Errorf("Error reading user data file: %s", err) 52 state.Put("error", err) 53 return multistep.ActionHalt 54 } 55 } 56 57 ui.Say("Launching server...") 58 59 serverOpts := servers.CreateOpts{ 60 Name: s.Name, 61 ImageRef: s.SourceImage, 62 ImageName: s.SourceImageName, 63 FlavorRef: flavor, 64 SecurityGroups: s.SecurityGroups, 65 Networks: networks, 66 AvailabilityZone: s.AvailabilityZone, 67 UserData: userData, 68 ConfigDrive: &s.ConfigDrive, 69 ServiceClient: computeClient, 70 Metadata: s.InstanceMetadata, 71 } 72 73 var serverOptsExt servers.CreateOptsBuilder 74 keyName, hasKey := state.GetOk("keyPair") 75 if hasKey { 76 serverOptsExt = keypairs.CreateOptsExt{ 77 CreateOptsBuilder: serverOpts, 78 KeyName: keyName.(string), 79 } 80 } else { 81 serverOptsExt = serverOpts 82 } 83 84 s.server, err = servers.Create(computeClient, serverOptsExt).Extract() 85 if err != nil { 86 err := fmt.Errorf("Error launching source server: %s", err) 87 state.Put("error", err) 88 ui.Error(err.Error()) 89 return multistep.ActionHalt 90 } 91 92 ui.Message(fmt.Sprintf("Server ID: %s", s.server.ID)) 93 log.Printf("server id: %s", s.server.ID) 94 95 ui.Say("Waiting for server to become ready...") 96 stateChange := StateChangeConf{ 97 Pending: []string{"BUILD"}, 98 Target: []string{"ACTIVE"}, 99 Refresh: ServerStateRefreshFunc(computeClient, s.server), 100 StepState: state, 101 } 102 latestServer, err := WaitForState(&stateChange) 103 if err != nil { 104 err := fmt.Errorf("Error waiting for server (%s) to become ready: %s", s.server.ID, err) 105 state.Put("error", err) 106 ui.Error(err.Error()) 107 return multistep.ActionHalt 108 } 109 110 s.server = latestServer.(*servers.Server) 111 state.Put("server", s.server) 112 113 return multistep.ActionContinue 114 } 115 116 func (s *StepRunSourceServer) Cleanup(state multistep.StateBag) { 117 if s.server == nil { 118 return 119 } 120 121 config := state.Get("config").(Config) 122 ui := state.Get("ui").(packer.Ui) 123 124 // We need the v2 compute client 125 computeClient, err := config.computeV2Client() 126 if err != nil { 127 ui.Error(fmt.Sprintf("Error terminating server, may still be around: %s", err)) 128 return 129 } 130 131 ui.Say(fmt.Sprintf("Terminating the source server: %s ...", s.server.ID)) 132 if err := servers.Delete(computeClient, s.server.ID).ExtractErr(); err != nil { 133 ui.Error(fmt.Sprintf("Error terminating server, may still be around: %s", err)) 134 return 135 } 136 137 stateChange := StateChangeConf{ 138 Pending: []string{"ACTIVE", "BUILD", "REBUILD", "SUSPENDED", "SHUTOFF", "STOPPED"}, 139 Refresh: ServerStateRefreshFunc(computeClient, s.server), 140 Target: []string{"DELETED"}, 141 } 142 143 WaitForState(&stateChange) 144 }