github.com/ttysteale/packer@v0.8.2-0.20150708160520-e5f8ea386ed8/post-processor/vsphere/post-processor.go (about)

     1  package vsphere
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"log"
     7  	"net/url"
     8  	"os/exec"
     9  	"strings"
    10  
    11  	"github.com/mitchellh/packer/common"
    12  	"github.com/mitchellh/packer/helper/config"
    13  	"github.com/mitchellh/packer/packer"
    14  	"github.com/mitchellh/packer/template/interpolate"
    15  )
    16  
    17  var builtins = map[string]string{
    18  	"mitchellh.vmware": "vmware",
    19  }
    20  
    21  type Config struct {
    22  	common.PackerConfig `mapstructure:",squash"`
    23  
    24  	Insecure     bool   `mapstructure:"insecure"`
    25  	Cluster      string `mapstructure:"cluster"`
    26  	Datacenter   string `mapstructure:"datacenter"`
    27  	Datastore    string `mapstructure:"datastore"`
    28  	DiskMode     string `mapstructure:"disk_mode"`
    29  	Host         string `mapstructure:"host"`
    30  	Password     string `mapstructure:"password"`
    31  	ResourcePool string `mapstructure:"resource_pool"`
    32  	Username     string `mapstructure:"username"`
    33  	VMFolder     string `mapstructure:"vm_folder"`
    34  	VMName       string `mapstructure:"vm_name"`
    35  	VMNetwork    string `mapstructure:"vm_network"`
    36  
    37  	ctx interpolate.Context
    38  }
    39  
    40  type PostProcessor struct {
    41  	config Config
    42  }
    43  
    44  func (p *PostProcessor) Configure(raws ...interface{}) error {
    45  	err := config.Decode(&p.config, &config.DecodeOpts{
    46  		Interpolate:        true,
    47  		InterpolateContext: &p.config.ctx,
    48  		InterpolateFilter: &interpolate.RenderFilter{
    49  			Exclude: []string{},
    50  		},
    51  	}, raws...)
    52  	if err != nil {
    53  		return err
    54  	}
    55  
    56  	// Defaults
    57  	if p.config.DiskMode == "" {
    58  		p.config.DiskMode = "thick"
    59  	}
    60  
    61  	// Accumulate any errors
    62  	errs := new(packer.MultiError)
    63  
    64  	if _, err := exec.LookPath("ovftool"); err != nil {
    65  		errs = packer.MultiErrorAppend(
    66  			errs, fmt.Errorf("ovftool not found: %s", err))
    67  	}
    68  
    69  	// First define all our templatable parameters that are _required_
    70  	templates := map[string]*string{
    71  		"cluster":    &p.config.Cluster,
    72  		"datacenter": &p.config.Datacenter,
    73  		"diskmode":   &p.config.DiskMode,
    74  		"host":       &p.config.Host,
    75  		"password":   &p.config.Password,
    76  		"username":   &p.config.Username,
    77  		"vm_name":    &p.config.VMName,
    78  	}
    79  	for key, ptr := range templates {
    80  		if *ptr == "" {
    81  			errs = packer.MultiErrorAppend(
    82  				errs, fmt.Errorf("%s must be set", key))
    83  		}
    84  	}
    85  
    86  	if len(errs.Errors) > 0 {
    87  		return errs
    88  	}
    89  
    90  	return nil
    91  }
    92  
    93  func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) {
    94  	if _, ok := builtins[artifact.BuilderId()]; !ok {
    95  		return nil, false, fmt.Errorf("Unknown artifact type, can't build box: %s", artifact.BuilderId())
    96  	}
    97  
    98  	vmx := ""
    99  	for _, path := range artifact.Files() {
   100  		if strings.HasSuffix(path, ".vmx") {
   101  			vmx = path
   102  			break
   103  		}
   104  	}
   105  
   106  	if vmx == "" {
   107  		return nil, false, fmt.Errorf("VMX file not found")
   108  	}
   109  
   110  	ovftool_uri := fmt.Sprintf("vi://%s:%s@%s/%s/host/%s",
   111  		url.QueryEscape(p.config.Username),
   112  		url.QueryEscape(p.config.Password),
   113  		p.config.Host,
   114  		p.config.Datacenter,
   115  		p.config.Cluster)
   116  
   117  	if p.config.ResourcePool != "" {
   118  		ovftool_uri += "/Resources/" + p.config.ResourcePool
   119  	}
   120  
   121  	args := []string{
   122  		fmt.Sprintf("--noSSLVerify=%t", p.config.Insecure),
   123  		"--acceptAllEulas",
   124  		fmt.Sprintf("--name=%s", p.config.VMName),
   125  		fmt.Sprintf("--datastore=%s", p.config.Datastore),
   126  		fmt.Sprintf("--diskMode=%s", p.config.DiskMode),
   127  		fmt.Sprintf("--network=%s", p.config.VMNetwork),
   128  		fmt.Sprintf("--vmFolder=%s", p.config.VMFolder),
   129  		fmt.Sprintf("%s", vmx),
   130  		fmt.Sprintf("%s", ovftool_uri),
   131  	}
   132  
   133  	ui.Message(fmt.Sprintf("Uploading %s to vSphere", vmx))
   134  	var out bytes.Buffer
   135  	log.Printf("Starting ovftool with parameters: %s", strings.Join(args, " "))
   136  	cmd := exec.Command("ovftool", args...)
   137  	cmd.Stdout = &out
   138  	if err := cmd.Run(); err != nil {
   139  		return nil, false, fmt.Errorf("Failed: %s\nStdout: %s", err, out.String())
   140  	}
   141  
   142  	ui.Message(fmt.Sprintf("%s", out.String()))
   143  
   144  	return artifact, false, nil
   145  }