github.com/mmcquillan/packer@v1.1.1-0.20171009221028-c85cf0483a5d/post-processor/vsphere/post-processor.go (about) 1 package vsphere 2 3 import ( 4 "fmt" 5 "log" 6 "net/url" 7 "os" 8 "os/exec" 9 "strings" 10 11 "github.com/hashicorp/packer/common" 12 "github.com/hashicorp/packer/helper/config" 13 "github.com/hashicorp/packer/packer" 14 "github.com/hashicorp/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 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 Insecure bool `mapstructure:"insecure"` 31 Options []string `mapstructure:"options"` 32 Overwrite bool `mapstructure:"overwrite"` 33 Password string `mapstructure:"password"` 34 ResourcePool string `mapstructure:"resource_pool"` 35 Username string `mapstructure:"username"` 36 VMFolder string `mapstructure:"vm_folder"` 37 VMName string `mapstructure:"vm_name"` 38 VMNetwork string `mapstructure:"vm_network"` 39 40 ctx interpolate.Context 41 } 42 43 type PostProcessor struct { 44 config Config 45 } 46 47 func (p *PostProcessor) Configure(raws ...interface{}) error { 48 err := config.Decode(&p.config, &config.DecodeOpts{ 49 Interpolate: true, 50 InterpolateContext: &p.config.ctx, 51 InterpolateFilter: &interpolate.RenderFilter{ 52 Exclude: []string{}, 53 }, 54 }, raws...) 55 if err != nil { 56 return err 57 } 58 59 // Defaults 60 if p.config.DiskMode == "" { 61 p.config.DiskMode = "thick" 62 } 63 64 // Accumulate any errors 65 errs := new(packer.MultiError) 66 67 if _, err := exec.LookPath("ovftool"); err != nil { 68 errs = packer.MultiErrorAppend( 69 errs, fmt.Errorf("ovftool not found: %s", err)) 70 } 71 72 // First define all our templatable parameters that are _required_ 73 templates := map[string]*string{ 74 "cluster": &p.config.Cluster, 75 "datacenter": &p.config.Datacenter, 76 "diskmode": &p.config.DiskMode, 77 "host": &p.config.Host, 78 "password": &p.config.Password, 79 "username": &p.config.Username, 80 "vm_name": &p.config.VMName, 81 } 82 for key, ptr := range templates { 83 if *ptr == "" { 84 errs = packer.MultiErrorAppend( 85 errs, fmt.Errorf("%s must be set", key)) 86 } 87 } 88 89 if len(errs.Errors) > 0 { 90 return errs 91 } 92 93 return nil 94 } 95 96 func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) { 97 if _, ok := builtins[artifact.BuilderId()]; !ok { 98 return nil, false, fmt.Errorf("Unknown artifact type, can't build box: %s", artifact.BuilderId()) 99 } 100 101 source := "" 102 for _, path := range artifact.Files() { 103 if strings.HasSuffix(path, ".vmx") || strings.HasSuffix(path, ".ovf") || strings.HasSuffix(path, ".ova") { 104 source = path 105 break 106 } 107 } 108 109 if source == "" { 110 return nil, false, fmt.Errorf("VMX, OVF or OVA file not found") 111 } 112 113 password := url.QueryEscape(p.config.Password) 114 ovftool_uri := fmt.Sprintf("vi://%s:%s@%s/%s/host/%s", 115 url.QueryEscape(p.config.Username), 116 password, 117 p.config.Host, 118 p.config.Datacenter, 119 p.config.Cluster) 120 121 if p.config.ResourcePool != "" { 122 ovftool_uri += "/Resources/" + p.config.ResourcePool 123 } 124 125 args, err := p.BuildArgs(source, ovftool_uri) 126 if err != nil { 127 ui.Message(fmt.Sprintf("Failed: %s\n", err)) 128 } 129 130 ui.Message(fmt.Sprintf("Uploading %s to vSphere", source)) 131 132 log.Printf("Starting ovftool with parameters: %s", 133 strings.Replace( 134 strings.Join(args, " "), 135 password, 136 "<password>", 137 -1)) 138 cmd := exec.Command("ovftool", args...) 139 cmd.Stdout = os.Stdout 140 cmd.Stderr = os.Stderr 141 if err := cmd.Run(); err != nil { 142 return nil, false, fmt.Errorf("Failed: %s\n", err) 143 } 144 145 return artifact, false, nil 146 } 147 148 func (p *PostProcessor) BuildArgs(source, ovftool_uri string) ([]string, error) { 149 args := []string{ 150 "--acceptAllEulas", 151 fmt.Sprintf(`--name=%s`, p.config.VMName), 152 fmt.Sprintf(`--datastore=%s`, p.config.Datastore), 153 } 154 155 if p.config.Insecure { 156 args = append(args, fmt.Sprintf(`--noSSLVerify=%t`, p.config.Insecure)) 157 } 158 159 if p.config.DiskMode != "" { 160 args = append(args, fmt.Sprintf(`--diskMode=%s`, p.config.DiskMode)) 161 } 162 163 if p.config.VMFolder != "" { 164 args = append(args, fmt.Sprintf(`--vmFolder=%s`, p.config.VMFolder)) 165 } 166 167 if p.config.VMNetwork != "" { 168 args = append(args, fmt.Sprintf(`--network=%s`, p.config.VMNetwork)) 169 } 170 171 if p.config.Overwrite == true { 172 args = append(args, "--overwrite") 173 } 174 175 if len(p.config.Options) > 0 { 176 args = append(args, p.config.Options...) 177 } 178 179 args = append(args, fmt.Sprintf(`%s`, source)) 180 args = append(args, fmt.Sprintf(`%s`, ovftool_uri)) 181 182 return args, nil 183 }