github.com/mmcquillan/packer@v1.1.1-0.20171009221028-c85cf0483a5d/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/gophercloud/gophercloud/openstack/compute/v2/extensions/keypairs"
     9  	"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
    10  	"github.com/hashicorp/packer/packer"
    11  	"github.com/mitchellh/multistep"
    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  	InstanceMetadata map[string]string
    25  	server           *servers.Server
    26  }
    27  
    28  func (s *StepRunSourceServer) Run(state multistep.StateBag) multistep.StepAction {
    29  	config := state.Get("config").(Config)
    30  	flavor := state.Get("flavor_id").(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  
    58  	serverOpts := 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  		ServiceClient:    computeClient,
    69  		Metadata:         s.InstanceMetadata,
    70  	}
    71  
    72  	var serverOptsExt servers.CreateOptsBuilder
    73  	keyName, hasKey := state.GetOk("keyPair")
    74  	if hasKey {
    75  		serverOptsExt = keypairs.CreateOptsExt{
    76  			CreateOptsBuilder: serverOpts,
    77  			KeyName:           keyName.(string),
    78  		}
    79  	} else {
    80  		serverOptsExt = serverOpts
    81  	}
    82  
    83  	s.server, err = servers.Create(computeClient, serverOptsExt).Extract()
    84  	if err != nil {
    85  		err := fmt.Errorf("Error launching source server: %s", err)
    86  		state.Put("error", err)
    87  		ui.Error(err.Error())
    88  		return multistep.ActionHalt
    89  	}
    90  
    91  	ui.Message(fmt.Sprintf("Server ID: %s", s.server.ID))
    92  	log.Printf("server id: %s", s.server.ID)
    93  
    94  	ui.Say("Waiting for server to become ready...")
    95  	stateChange := StateChangeConf{
    96  		Pending:   []string{"BUILD"},
    97  		Target:    []string{"ACTIVE"},
    98  		Refresh:   ServerStateRefreshFunc(computeClient, s.server),
    99  		StepState: state,
   100  	}
   101  	latestServer, err := WaitForState(&stateChange)
   102  	if err != nil {
   103  		err := fmt.Errorf("Error waiting for server (%s) to become ready: %s", s.server.ID, err)
   104  		state.Put("error", err)
   105  		ui.Error(err.Error())
   106  		return multistep.ActionHalt
   107  	}
   108  
   109  	s.server = latestServer.(*servers.Server)
   110  	state.Put("server", s.server)
   111  
   112  	return multistep.ActionContinue
   113  }
   114  
   115  func (s *StepRunSourceServer) Cleanup(state multistep.StateBag) {
   116  	if s.server == nil {
   117  		return
   118  	}
   119  
   120  	config := state.Get("config").(Config)
   121  	ui := state.Get("ui").(packer.Ui)
   122  
   123  	// We need the v2 compute client
   124  	computeClient, err := config.computeV2Client()
   125  	if err != nil {
   126  		ui.Error(fmt.Sprintf("Error terminating server, may still be around: %s", err))
   127  		return
   128  	}
   129  
   130  	ui.Say(fmt.Sprintf("Terminating the source server: %s ...", s.server.ID))
   131  	if err := servers.Delete(computeClient, s.server.ID).ExtractErr(); err != nil {
   132  		ui.Error(fmt.Sprintf("Error terminating server, may still be around: %s", err))
   133  		return
   134  	}
   135  
   136  	stateChange := StateChangeConf{
   137  		Pending: []string{"ACTIVE", "BUILD", "REBUILD", "SUSPENDED", "SHUTOFF", "STOPPED"},
   138  		Refresh: ServerStateRefreshFunc(computeClient, s.server),
   139  		Target:  []string{"DELETED"},
   140  	}
   141  
   142  	WaitForState(&stateChange)
   143  }