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 }