github.com/raghuse92/packer@v1.3.2/builder/openstack/builder.go (about)

     1  // The openstack package contains a packer.Builder implementation that
     2  // builds Images for openstack.
     3  
     4  package openstack
     5  
     6  import (
     7  	"fmt"
     8  	"log"
     9  
    10  	"github.com/hashicorp/packer/common"
    11  	"github.com/hashicorp/packer/helper/communicator"
    12  	"github.com/hashicorp/packer/helper/config"
    13  	"github.com/hashicorp/packer/helper/multistep"
    14  	"github.com/hashicorp/packer/packer"
    15  	"github.com/hashicorp/packer/template/interpolate"
    16  )
    17  
    18  // The unique ID for this builder
    19  const BuilderId = "mitchellh.openstack"
    20  
    21  type Config struct {
    22  	common.PackerConfig `mapstructure:",squash"`
    23  
    24  	AccessConfig `mapstructure:",squash"`
    25  	ImageConfig  `mapstructure:",squash"`
    26  	RunConfig    `mapstructure:",squash"`
    27  
    28  	ctx interpolate.Context
    29  }
    30  
    31  type Builder struct {
    32  	config Config
    33  	runner multistep.Runner
    34  }
    35  
    36  func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
    37  	err := config.Decode(&b.config, &config.DecodeOpts{
    38  		Interpolate:        true,
    39  		InterpolateContext: &b.config.ctx,
    40  	}, raws...)
    41  	if err != nil {
    42  		return nil, err
    43  	}
    44  
    45  	// Accumulate any errors
    46  	var errs *packer.MultiError
    47  	errs = packer.MultiErrorAppend(errs, b.config.AccessConfig.Prepare(&b.config.ctx)...)
    48  	errs = packer.MultiErrorAppend(errs, b.config.ImageConfig.Prepare(&b.config.ctx)...)
    49  	errs = packer.MultiErrorAppend(errs, b.config.RunConfig.Prepare(&b.config.ctx)...)
    50  
    51  	if errs != nil && len(errs.Errors) > 0 {
    52  		return nil, errs
    53  	}
    54  
    55  	if b.config.ImageConfig.ImageDiskFormat != "" && !b.config.RunConfig.UseBlockStorageVolume {
    56  		return nil, fmt.Errorf("use_blockstorage_volume must be true if image_disk_format is specified.")
    57  	}
    58  
    59  	// By default, instance name is same as image name
    60  	if b.config.InstanceName == "" {
    61  		b.config.InstanceName = b.config.ImageName
    62  	}
    63  
    64  	packer.LogSecretFilter.Set(b.config.Password)
    65  	return nil, nil
    66  }
    67  
    68  func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
    69  	computeClient, err := b.config.computeV2Client()
    70  	if err != nil {
    71  		return nil, fmt.Errorf("Error initializing compute client: %s", err)
    72  	}
    73  
    74  	// Setup the state bag and initial state for the steps
    75  	state := new(multistep.BasicStateBag)
    76  	state.Put("config", &b.config)
    77  	state.Put("hook", hook)
    78  	state.Put("ui", ui)
    79  
    80  	// Build the steps
    81  	steps := []multistep.Step{
    82  		&StepLoadFlavor{
    83  			Flavor: b.config.Flavor,
    84  		},
    85  		&StepKeyPair{
    86  			Debug:        b.config.PackerDebug,
    87  			Comm:         &b.config.Comm,
    88  			DebugKeyPath: fmt.Sprintf("os_%s.pem", b.config.PackerBuildName),
    89  		},
    90  		&StepSourceImageInfo{
    91  			SourceImage:      b.config.RunConfig.SourceImage,
    92  			SourceImageName:  b.config.RunConfig.SourceImageName,
    93  			SourceImageOpts:  b.config.RunConfig.sourceImageOpts,
    94  			SourceMostRecent: b.config.SourceImageFilters.MostRecent,
    95  		},
    96  		&StepCreateVolume{
    97  			UseBlockStorageVolume:  b.config.UseBlockStorageVolume,
    98  			VolumeName:             b.config.VolumeName,
    99  			VolumeType:             b.config.VolumeType,
   100  			VolumeAvailabilityZone: b.config.VolumeAvailabilityZone,
   101  		},
   102  		&StepRunSourceServer{
   103  			Name:                  b.config.InstanceName,
   104  			SecurityGroups:        b.config.SecurityGroups,
   105  			Networks:              b.config.Networks,
   106  			Ports:                 b.config.Ports,
   107  			AvailabilityZone:      b.config.AvailabilityZone,
   108  			UserData:              b.config.UserData,
   109  			UserDataFile:          b.config.UserDataFile,
   110  			ConfigDrive:           b.config.ConfigDrive,
   111  			InstanceMetadata:      b.config.InstanceMetadata,
   112  			UseBlockStorageVolume: b.config.UseBlockStorageVolume,
   113  		},
   114  		&StepGetPassword{
   115  			Debug: b.config.PackerDebug,
   116  			Comm:  &b.config.RunConfig.Comm,
   117  		},
   118  		&StepWaitForRackConnect{
   119  			Wait: b.config.RackconnectWait,
   120  		},
   121  		&StepAllocateIp{
   122  			FloatingIPNetwork: b.config.FloatingIPNetwork,
   123  			FloatingIP:        b.config.FloatingIP,
   124  			ReuseIPs:          b.config.ReuseIPs,
   125  		},
   126  		&communicator.StepConnect{
   127  			Config: &b.config.RunConfig.Comm,
   128  			Host: CommHost(
   129  				computeClient,
   130  				b.config.Comm.SSHInterface,
   131  				b.config.Comm.SSHIPVersion),
   132  			SSHConfig: b.config.RunConfig.Comm.SSHConfigFunc(),
   133  		},
   134  		&common.StepProvision{},
   135  		&common.StepCleanupTempKeys{
   136  			Comm: &b.config.RunConfig.Comm,
   137  		},
   138  		&StepStopServer{},
   139  		&StepDetachVolume{
   140  			UseBlockStorageVolume: b.config.UseBlockStorageVolume,
   141  		},
   142  		&stepCreateImage{
   143  			UseBlockStorageVolume: b.config.UseBlockStorageVolume,
   144  		},
   145  		&stepUpdateImageVisibility{},
   146  		&stepAddImageMembers{},
   147  	}
   148  
   149  	// Run!
   150  	b.runner = common.NewRunner(steps, b.config.PackerConfig, ui)
   151  	b.runner.Run(state)
   152  
   153  	// If there was an error, return that
   154  	if rawErr, ok := state.GetOk("error"); ok {
   155  		return nil, rawErr.(error)
   156  	}
   157  
   158  	// If there are no images, then just return
   159  	if _, ok := state.GetOk("image"); !ok {
   160  		return nil, nil
   161  	}
   162  
   163  	// Build the artifact and return it
   164  	artifact := &Artifact{
   165  		ImageId:        state.Get("image").(string),
   166  		BuilderIdValue: BuilderId,
   167  		Client:         computeClient,
   168  	}
   169  
   170  	return artifact, nil
   171  }
   172  
   173  func (b *Builder) Cancel() {
   174  	if b.runner != nil {
   175  		log.Println("Cancelling the step runner...")
   176  		b.runner.Cancel()
   177  	}
   178  }