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  }