packer-cn/builder/openstack/step_run_source_server.go

102 lines
2.6 KiB
Go

package openstack
import (
"fmt"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
"github.com/rackspace/gophercloud"
"log"
)
type StepRunSourceServer struct {
Flavor string
Name string
SourceImage string
SecurityGroups []string
Networks []string
server *gophercloud.Server
}
func (s *StepRunSourceServer) Run(state multistep.StateBag) multistep.StepAction {
csp := state.Get("csp").(gophercloud.CloudServersProvider)
keyName := state.Get("keyPair").(string)
ui := state.Get("ui").(packer.Ui)
// XXX - validate image and flavor is available
securityGroups := make([]map[string]interface{}, len(s.SecurityGroups))
for i, groupName := range s.SecurityGroups {
securityGroups[i] = make(map[string]interface{})
securityGroups[i]["name"] = groupName
}
networks := make([]gophercloud.NetworkConfig, len(s.Networks))
for i, networkUuid := range s.Networks {
networks[i].Uuid = networkUuid
}
server := gophercloud.NewServer{
Name: s.Name,
ImageRef: s.SourceImage,
FlavorRef: s.Flavor,
KeyPairName: keyName,
SecurityGroup: securityGroups,
Networks: networks,
}
serverResp, err := csp.CreateServer(server)
if err != nil {
err := fmt.Errorf("Error launching source server: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
s.server, err = csp.ServerById(serverResp.Id)
log.Printf("server id: %s", s.server.Id)
ui.Say(fmt.Sprintf("Waiting for server (%s) to become ready...", s.server.Id))
stateChange := StateChangeConf{
Pending: []string{"BUILD"},
Target: "ACTIVE",
Refresh: ServerStateRefreshFunc(csp, s.server),
StepState: state,
}
latestServer, err := WaitForState(&stateChange)
if err != nil {
err := fmt.Errorf("Error waiting for server (%s) to become ready: %s", s.server.Id, err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
s.server = latestServer.(*gophercloud.Server)
state.Put("server", s.server)
return multistep.ActionContinue
}
func (s *StepRunSourceServer) Cleanup(state multistep.StateBag) {
if s.server == nil {
return
}
csp := state.Get("csp").(gophercloud.CloudServersProvider)
ui := state.Get("ui").(packer.Ui)
ui.Say("Terminating the source server...")
if err := csp.DeleteServerById(s.server.Id); err != nil {
ui.Error(fmt.Sprintf("Error terminating server, may still be around: %s", err))
return
}
stateChange := StateChangeConf{
Pending: []string{"ACTIVE", "BUILD", "REBUILD", "SUSPENDED"},
Refresh: ServerStateRefreshFunc(csp, s.server),
Target: "DELETED",
}
WaitForState(&stateChange)
}