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