github.com/amanya/packer@v0.12.1-0.20161117214323-902ac5ab2eb6/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 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 57 serverOpts := servers.CreateOpts{ 58 Name: s.Name, 59 ImageRef: s.SourceImage, 60 ImageName: s.SourceImageName, 61 FlavorRef: flavor, 62 SecurityGroups: s.SecurityGroups, 63 Networks: networks, 64 AvailabilityZone: s.AvailabilityZone, 65 UserData: userData, 66 ConfigDrive: s.ConfigDrive, 67 } 68 69 var serverOptsExt servers.CreateOptsBuilder 70 keyName, hasKey := state.GetOk("keyPair") 71 if hasKey { 72 serverOptsExt = keypairs.CreateOptsExt{ 73 CreateOptsBuilder: serverOpts, 74 KeyName: keyName.(string), 75 } 76 } else { 77 serverOptsExt = serverOpts 78 } 79 80 s.server, err = servers.Create(computeClient, serverOptsExt).Extract() 81 if err != nil { 82 err := fmt.Errorf("Error launching source server: %s", err) 83 state.Put("error", err) 84 ui.Error(err.Error()) 85 return multistep.ActionHalt 86 } 87 88 ui.Message(fmt.Sprintf("Server ID: %s", s.server.ID)) 89 log.Printf("server id: %s", s.server.ID) 90 91 ui.Say("Waiting for server to become ready...") 92 stateChange := StateChangeConf{ 93 Pending: []string{"BUILD"}, 94 Target: []string{"ACTIVE"}, 95 Refresh: ServerStateRefreshFunc(computeClient, s.server), 96 StepState: state, 97 } 98 latestServer, err := WaitForState(&stateChange) 99 if err != nil { 100 err := fmt.Errorf("Error waiting for server (%s) to become ready: %s", s.server.ID, err) 101 state.Put("error", err) 102 ui.Error(err.Error()) 103 return multistep.ActionHalt 104 } 105 106 s.server = latestServer.(*servers.Server) 107 state.Put("server", s.server) 108 109 return multistep.ActionContinue 110 } 111 112 func (s *StepRunSourceServer) Cleanup(state multistep.StateBag) { 113 if s.server == nil { 114 return 115 } 116 117 config := state.Get("config").(Config) 118 ui := state.Get("ui").(packer.Ui) 119 120 // We need the v2 compute client 121 computeClient, err := config.computeV2Client() 122 if err != nil { 123 ui.Error(fmt.Sprintf("Error terminating server, may still be around: %s", err)) 124 return 125 } 126 127 ui.Say(fmt.Sprintf("Terminating the source server: %s ...", s.server.ID)) 128 if err := servers.Delete(computeClient, s.server.ID).ExtractErr(); err != nil { 129 ui.Error(fmt.Sprintf("Error terminating server, may still be around: %s", err)) 130 return 131 } 132 133 stateChange := StateChangeConf{ 134 Pending: []string{"ACTIVE", "BUILD", "REBUILD", "SUSPENDED", "SHUTOFF", "STOPPED"}, 135 Refresh: ServerStateRefreshFunc(computeClient, s.server), 136 Target: []string{"DELETED"}, 137 } 138 139 WaitForState(&stateChange) 140 }