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