github.com/askholme/packer@v0.7.2-0.20140924152349-70d9566a6852/post-processor/vsphere/post-processor.go (about)

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