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