github.com/phobos182/packer@v0.2.3-0.20130819023704-c84d2aeffc68/builder/amazon/common/step_run_source_instance.go (about)

     1  package common
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/mitchellh/goamz/ec2"
     6  	"github.com/mitchellh/multistep"
     7  	"github.com/mitchellh/packer/packer"
     8  	"io/ioutil"
     9  	"log"
    10  )
    11  
    12  type StepRunSourceInstance struct {
    13  	ExpectedRootDevice string
    14  	InstanceType       string
    15  	UserData           string
    16  	UserDataFile       string
    17  	SourceAMI          string
    18  	IamInstanceProfile string
    19  	SubnetId           string
    20  	BlockDevices       BlockDevices
    21  
    22  	instance *ec2.Instance
    23  }
    24  
    25  func (s *StepRunSourceInstance) Run(state map[string]interface{}) multistep.StepAction {
    26  	ec2conn := state["ec2"].(*ec2.EC2)
    27  	keyName := state["keyPair"].(string)
    28  	securityGroupId := state["securityGroupId"].(string)
    29  	ui := state["ui"].(packer.Ui)
    30  
    31  	userData := s.UserData
    32  	if s.UserDataFile != "" {
    33  		contents, err := ioutil.ReadFile(s.UserDataFile)
    34  		if err != nil {
    35  			state["error"] = fmt.Errorf("Problem reading user data file: %s", err)
    36  			return multistep.ActionHalt
    37  		}
    38  
    39  		userData = string(contents)
    40  	}
    41  
    42  	runOpts := &ec2.RunInstances{
    43  		KeyName:            keyName,
    44  		ImageId:            s.SourceAMI,
    45  		InstanceType:       s.InstanceType,
    46  		UserData:           []byte(userData),
    47  		MinCount:           0,
    48  		MaxCount:           0,
    49  		SecurityGroups:     []ec2.SecurityGroup{ec2.SecurityGroup{Id: securityGroupId}},
    50  		IamInstanceProfile: s.IamInstanceProfile,
    51  		SubnetId:           s.SubnetId,
    52  		BlockDevices:       s.BlockDevices.BuildLaunchDevices(),
    53  	}
    54  
    55  	ui.Say("Launching a source AWS instance...")
    56  	imageResp, err := ec2conn.Images([]string{s.SourceAMI}, ec2.NewFilter())
    57  	if err != nil {
    58  		state["error"] = fmt.Errorf("There was a problem with the source AMI: %s", err)
    59  		return multistep.ActionHalt
    60  	}
    61  
    62  	if len(imageResp.Images) != 1 {
    63  		state["error"] = fmt.Errorf("The source AMI '%s' could not be found.", s.SourceAMI)
    64  		return multistep.ActionHalt
    65  	}
    66  
    67  	if s.ExpectedRootDevice != "" && imageResp.Images[0].RootDeviceType != s.ExpectedRootDevice {
    68  		state["error"] = fmt.Errorf(
    69  			"The provided source AMI has an invalid root device type.\n"+
    70  				"Expected '%s', got '%s'.",
    71  			s.ExpectedRootDevice, imageResp.Images[0].RootDeviceType)
    72  		return multistep.ActionHalt
    73  	}
    74  
    75  	runResp, err := ec2conn.RunInstances(runOpts)
    76  	if err != nil {
    77  		err := fmt.Errorf("Error launching source instance: %s", err)
    78  		state["error"] = err
    79  		ui.Error(err.Error())
    80  		return multistep.ActionHalt
    81  	}
    82  
    83  	s.instance = &runResp.Instances[0]
    84  	log.Printf("instance id: %s", s.instance.InstanceId)
    85  
    86  	ui.Say(fmt.Sprintf("Waiting for instance (%s) to become ready...", s.instance.InstanceId))
    87  	stateChange := StateChangeConf{
    88  		Conn:      ec2conn,
    89  		Pending:   []string{"pending"},
    90  		Target:    "running",
    91  		Refresh:   InstanceStateRefreshFunc(ec2conn, s.instance),
    92  		StepState: state,
    93  	}
    94  	latestInstance, err := WaitForState(&stateChange)
    95  	if err != nil {
    96  		err := fmt.Errorf("Error waiting for instance (%s) to become ready: %s", s.instance.InstanceId, err)
    97  		state["error"] = err
    98  		ui.Error(err.Error())
    99  		return multistep.ActionHalt
   100  	}
   101  
   102  	s.instance = latestInstance.(*ec2.Instance)
   103  	state["instance"] = s.instance
   104  
   105  	return multistep.ActionContinue
   106  }
   107  
   108  func (s *StepRunSourceInstance) Cleanup(state map[string]interface{}) {
   109  	if s.instance == nil {
   110  		return
   111  	}
   112  
   113  	ec2conn := state["ec2"].(*ec2.EC2)
   114  	ui := state["ui"].(packer.Ui)
   115  
   116  	ui.Say("Terminating the source AWS instance...")
   117  	if _, err := ec2conn.TerminateInstances([]string{s.instance.InstanceId}); err != nil {
   118  		ui.Error(fmt.Sprintf("Error terminating instance, may still be around: %s", err))
   119  		return
   120  	}
   121  
   122  	stateChange := StateChangeConf{
   123  		Conn:    ec2conn,
   124  		Pending: []string{"pending", "running", "shutting-down", "stopped", "stopping"},
   125  		Refresh: InstanceStateRefreshFunc(ec2conn, s.instance),
   126  		Target:  "terminated",
   127  	}
   128  
   129  	WaitForState(&stateChange)
   130  }