github.com/StackPointCloud/packer@v0.10.2-0.20180716202532-b28098e0f79b/builder/openstack/step_run_source_server.go (about)

     1  package openstack
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"log"
     8  
     9  	"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/keypairs"
    10  	"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
    11  	"github.com/hashicorp/packer/helper/multistep"
    12  	"github.com/hashicorp/packer/packer"
    13  )
    14  
    15  type StepRunSourceServer struct {
    16  	Name             string
    17  	SourceImage      string
    18  	SourceImageName  string
    19  	SecurityGroups   []string
    20  	Networks         []string
    21  	AvailabilityZone string
    22  	UserData         string
    23  	UserDataFile     string
    24  	ConfigDrive      bool
    25  	InstanceMetadata map[string]string
    26  	server           *servers.Server
    27  }
    28  
    29  func (s *StepRunSourceServer) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
    30  	config := state.Get("config").(Config)
    31  	flavor := state.Get("flavor_id").(string)
    32  	ui := state.Get("ui").(packer.Ui)
    33  
    34  	// We need the v2 compute client
    35  	computeClient, err := config.computeV2Client()
    36  	if err != nil {
    37  		err = fmt.Errorf("Error initializing compute client: %s", err)
    38  		state.Put("error", err)
    39  		return multistep.ActionHalt
    40  	}
    41  
    42  	networks := make([]servers.Network, len(s.Networks))
    43  	for i, networkUuid := range s.Networks {
    44  		networks[i].UUID = networkUuid
    45  	}
    46  
    47  	userData := []byte(s.UserData)
    48  	if s.UserDataFile != "" {
    49  		userData, err = ioutil.ReadFile(s.UserDataFile)
    50  		if err != nil {
    51  			err = fmt.Errorf("Error reading user data file: %s", err)
    52  			state.Put("error", err)
    53  			return multistep.ActionHalt
    54  		}
    55  	}
    56  
    57  	ui.Say("Launching server...")
    58  
    59  	serverOpts := servers.CreateOpts{
    60  		Name:             s.Name,
    61  		ImageRef:         s.SourceImage,
    62  		ImageName:        s.SourceImageName,
    63  		FlavorRef:        flavor,
    64  		SecurityGroups:   s.SecurityGroups,
    65  		Networks:         networks,
    66  		AvailabilityZone: s.AvailabilityZone,
    67  		UserData:         userData,
    68  		ConfigDrive:      &s.ConfigDrive,
    69  		ServiceClient:    computeClient,
    70  		Metadata:         s.InstanceMetadata,
    71  	}
    72  
    73  	var serverOptsExt servers.CreateOptsBuilder
    74  	keyName, hasKey := state.GetOk("keyPair")
    75  	if hasKey {
    76  		serverOptsExt = keypairs.CreateOptsExt{
    77  			CreateOptsBuilder: serverOpts,
    78  			KeyName:           keyName.(string),
    79  		}
    80  	} else {
    81  		serverOptsExt = serverOpts
    82  	}
    83  
    84  	s.server, err = servers.Create(computeClient, serverOptsExt).Extract()
    85  	if err != nil {
    86  		err := fmt.Errorf("Error launching source server: %s", err)
    87  		state.Put("error", err)
    88  		ui.Error(err.Error())
    89  		return multistep.ActionHalt
    90  	}
    91  
    92  	ui.Message(fmt.Sprintf("Server ID: %s", s.server.ID))
    93  	log.Printf("server id: %s", s.server.ID)
    94  
    95  	ui.Say("Waiting for server to become ready...")
    96  	stateChange := StateChangeConf{
    97  		Pending:   []string{"BUILD"},
    98  		Target:    []string{"ACTIVE"},
    99  		Refresh:   ServerStateRefreshFunc(computeClient, s.server),
   100  		StepState: state,
   101  	}
   102  	latestServer, err := WaitForState(&stateChange)
   103  	if err != nil {
   104  		err := fmt.Errorf("Error waiting for server (%s) to become ready: %s", s.server.ID, err)
   105  		state.Put("error", err)
   106  		ui.Error(err.Error())
   107  		return multistep.ActionHalt
   108  	}
   109  
   110  	s.server = latestServer.(*servers.Server)
   111  	state.Put("server", s.server)
   112  
   113  	return multistep.ActionContinue
   114  }
   115  
   116  func (s *StepRunSourceServer) Cleanup(state multistep.StateBag) {
   117  	if s.server == nil {
   118  		return
   119  	}
   120  
   121  	config := state.Get("config").(Config)
   122  	ui := state.Get("ui").(packer.Ui)
   123  
   124  	// We need the v2 compute client
   125  	computeClient, err := config.computeV2Client()
   126  	if err != nil {
   127  		ui.Error(fmt.Sprintf("Error terminating server, may still be around: %s", err))
   128  		return
   129  	}
   130  
   131  	ui.Say(fmt.Sprintf("Terminating the source server: %s ...", s.server.ID))
   132  	if err := servers.Delete(computeClient, s.server.ID).ExtractErr(); err != nil {
   133  		ui.Error(fmt.Sprintf("Error terminating server, may still be around: %s", err))
   134  		return
   135  	}
   136  
   137  	stateChange := StateChangeConf{
   138  		Pending: []string{"ACTIVE", "BUILD", "REBUILD", "SUSPENDED", "SHUTOFF", "STOPPED"},
   139  		Refresh: ServerStateRefreshFunc(computeClient, s.server),
   140  		Target:  []string{"DELETED"},
   141  	}
   142  
   143  	WaitForState(&stateChange)
   144  }