github.com/minamijoyo/terraform@v0.7.8-0.20161029001309-18b3736ba44b/builtin/providers/vcd/resource_vcd_vapp.go (about) 1 package vcd 2 3 import ( 4 "fmt" 5 "log" 6 7 "github.com/hashicorp/terraform/helper/resource" 8 "github.com/hashicorp/terraform/helper/schema" 9 types "github.com/hmrc/vmware-govcd/types/v56" 10 ) 11 12 func resourceVcdVApp() *schema.Resource { 13 return &schema.Resource{ 14 Create: resourceVcdVAppCreate, 15 Update: resourceVcdVAppUpdate, 16 Read: resourceVcdVAppRead, 17 Delete: resourceVcdVAppDelete, 18 19 Schema: map[string]*schema.Schema{ 20 "name": &schema.Schema{ 21 Type: schema.TypeString, 22 Required: true, 23 ForceNew: true, 24 }, 25 26 "template_name": &schema.Schema{ 27 Type: schema.TypeString, 28 Required: true, 29 ForceNew: true, 30 }, 31 32 "catalog_name": &schema.Schema{ 33 Type: schema.TypeString, 34 Required: true, 35 }, 36 37 "network_href": &schema.Schema{ 38 Type: schema.TypeString, 39 Optional: true, 40 }, 41 42 "network_name": &schema.Schema{ 43 Type: schema.TypeString, 44 Required: true, 45 ForceNew: true, 46 }, 47 "memory": &schema.Schema{ 48 Type: schema.TypeInt, 49 Optional: true, 50 }, 51 "cpus": &schema.Schema{ 52 Type: schema.TypeInt, 53 Optional: true, 54 }, 55 "ip": &schema.Schema{ 56 Type: schema.TypeString, 57 Optional: true, 58 Computed: true, 59 }, 60 "initscript": &schema.Schema{ 61 Type: schema.TypeString, 62 Optional: true, 63 ForceNew: true, 64 }, 65 "metadata": &schema.Schema{ 66 Type: schema.TypeMap, 67 Optional: true, 68 }, 69 "href": &schema.Schema{ 70 Type: schema.TypeString, 71 Optional: true, 72 Computed: true, 73 }, 74 "power_on": &schema.Schema{ 75 Type: schema.TypeBool, 76 Optional: true, 77 Default: true, 78 }, 79 }, 80 } 81 } 82 83 func resourceVcdVAppCreate(d *schema.ResourceData, meta interface{}) error { 84 vcdClient := meta.(*VCDClient) 85 86 catalog, err := vcdClient.Org.FindCatalog(d.Get("catalog_name").(string)) 87 if err != nil { 88 return fmt.Errorf("Error finding catalog: %#v", err) 89 } 90 91 catalogitem, err := catalog.FindCatalogItem(d.Get("template_name").(string)) 92 if err != nil { 93 return fmt.Errorf("Error finding catelog item: %#v", err) 94 } 95 96 vapptemplate, err := catalogitem.GetVAppTemplate() 97 if err != nil { 98 return fmt.Errorf("Error finding VAppTemplate: %#v", err) 99 } 100 101 log.Printf("[DEBUG] VAppTemplate: %#v", vapptemplate) 102 var networkHref string 103 net, err := vcdClient.OrgVdc.FindVDCNetwork(d.Get("network_name").(string)) 104 if err != nil { 105 return fmt.Errorf("Error finding OrgVCD Network: %#v", err) 106 } 107 if attr, ok := d.GetOk("network_href"); ok { 108 networkHref = attr.(string) 109 } else { 110 networkHref = net.OrgVDCNetwork.HREF 111 } 112 // vapptemplate := govcd.NewVAppTemplate(&vcdClient.Client) 113 // 114 createvapp := &types.InstantiateVAppTemplateParams{ 115 Ovf: "http://schemas.dmtf.org/ovf/envelope/1", 116 Xmlns: "http://www.vmware.com/vcloud/v1.5", 117 Name: d.Get("name").(string), 118 InstantiationParams: &types.InstantiationParams{ 119 NetworkConfigSection: &types.NetworkConfigSection{ 120 Info: "Configuration parameters for logical networks", 121 NetworkConfig: &types.VAppNetworkConfiguration{ 122 NetworkName: d.Get("network_name").(string), 123 Configuration: &types.NetworkConfiguration{ 124 ParentNetwork: &types.Reference{ 125 HREF: networkHref, 126 }, 127 FenceMode: "bridged", 128 }, 129 }, 130 }, 131 }, 132 Source: &types.Reference{ 133 HREF: vapptemplate.VAppTemplate.HREF, 134 }, 135 } 136 137 err = retryCall(vcdClient.MaxRetryTimeout, func() *resource.RetryError { 138 e := vcdClient.OrgVdc.InstantiateVAppTemplate(createvapp) 139 140 if e != nil { 141 return resource.RetryableError(fmt.Errorf("Error: %#v", e)) 142 } 143 144 e = vcdClient.OrgVdc.Refresh() 145 if e != nil { 146 return resource.RetryableError(fmt.Errorf("Error: %#v", e)) 147 } 148 return nil 149 }) 150 if err != nil { 151 return err 152 } 153 154 vapp, err := vcdClient.OrgVdc.FindVAppByName(d.Get("name").(string)) 155 156 err = retryCall(vcdClient.MaxRetryTimeout, func() *resource.RetryError { 157 task, err := vapp.ChangeVMName(d.Get("name").(string)) 158 if err != nil { 159 return resource.RetryableError(fmt.Errorf("Error with vm name change: %#v", err)) 160 } 161 162 return resource.RetryableError(task.WaitTaskCompletion()) 163 }) 164 if err != nil { 165 return fmt.Errorf("Error changing vmname: %#v", err) 166 } 167 168 err = retryCall(vcdClient.MaxRetryTimeout, func() *resource.RetryError { 169 task, err := vapp.ChangeNetworkConfig(d.Get("network_name").(string), d.Get("ip").(string)) 170 if err != nil { 171 return resource.RetryableError(fmt.Errorf("Error with Networking change: %#v", err)) 172 } 173 return resource.RetryableError(task.WaitTaskCompletion()) 174 }) 175 if err != nil { 176 return fmt.Errorf("Error changing network: %#v", err) 177 } 178 179 if initscript, ok := d.GetOk("initscript"); ok { 180 err = retryCall(vcdClient.MaxRetryTimeout, func() *resource.RetryError { 181 task, err := vapp.RunCustomizationScript(d.Get("name").(string), initscript.(string)) 182 if err != nil { 183 return resource.RetryableError(fmt.Errorf("Error with setting init script: %#v", err)) 184 } 185 return resource.RetryableError(task.WaitTaskCompletion()) 186 }) 187 if err != nil { 188 return fmt.Errorf("Error completing tasks: %#v", err) 189 } 190 } 191 192 d.SetId(d.Get("name").(string)) 193 194 return resourceVcdVAppUpdate(d, meta) 195 } 196 197 func resourceVcdVAppUpdate(d *schema.ResourceData, meta interface{}) error { 198 vcdClient := meta.(*VCDClient) 199 vapp, err := vcdClient.OrgVdc.FindVAppByName(d.Id()) 200 201 if err != nil { 202 return fmt.Errorf("Error finding VApp: %#v", err) 203 } 204 205 status, err := vapp.GetStatus() 206 if err != nil { 207 return fmt.Errorf("Error getting VApp status: %#v", err) 208 } 209 210 if d.HasChange("metadata") { 211 oraw, nraw := d.GetChange("metadata") 212 metadata := oraw.(map[string]interface{}) 213 for k := range metadata { 214 task, err := vapp.DeleteMetadata(k) 215 if err != nil { 216 return fmt.Errorf("Error deleting metadata: %#v", err) 217 } 218 err = task.WaitTaskCompletion() 219 if err != nil { 220 return fmt.Errorf("Error completing tasks: %#v", err) 221 } 222 } 223 metadata = nraw.(map[string]interface{}) 224 for k, v := range metadata { 225 task, err := vapp.AddMetadata(k, v.(string)) 226 if err != nil { 227 return fmt.Errorf("Error adding metadata: %#v", err) 228 } 229 err = task.WaitTaskCompletion() 230 if err != nil { 231 return fmt.Errorf("Error completing tasks: %#v", err) 232 } 233 } 234 235 } 236 237 if d.HasChange("memory") || d.HasChange("cpus") || d.HasChange("power_on") { 238 if status != "POWERED_OFF" { 239 task, err := vapp.PowerOff() 240 if err != nil { 241 return fmt.Errorf("Error Powering Off: %#v", err) 242 } 243 err = task.WaitTaskCompletion() 244 if err != nil { 245 return fmt.Errorf("Error completing tasks: %#v", err) 246 } 247 } 248 249 if d.HasChange("memory") { 250 err = retryCall(vcdClient.MaxRetryTimeout, func() *resource.RetryError { 251 task, err := vapp.ChangeMemorySize(d.Get("memory").(int)) 252 if err != nil { 253 return resource.RetryableError(fmt.Errorf("Error changing memory size: %#v", err)) 254 } 255 256 return resource.RetryableError(task.WaitTaskCompletion()) 257 }) 258 if err != nil { 259 return err 260 } 261 } 262 263 if d.HasChange("cpus") { 264 err = retryCall(vcdClient.MaxRetryTimeout, func() *resource.RetryError { 265 task, err := vapp.ChangeCPUcount(d.Get("cpus").(int)) 266 if err != nil { 267 return resource.RetryableError(fmt.Errorf("Error changing cpu count: %#v", err)) 268 } 269 270 return resource.RetryableError(task.WaitTaskCompletion()) 271 }) 272 if err != nil { 273 return fmt.Errorf("Error completing task: %#v", err) 274 } 275 } 276 277 if d.Get("power_on").(bool) { 278 task, err := vapp.PowerOn() 279 if err != nil { 280 return fmt.Errorf("Error Powering Up: %#v", err) 281 } 282 err = task.WaitTaskCompletion() 283 if err != nil { 284 return fmt.Errorf("Error completing tasks: %#v", err) 285 } 286 } 287 288 } 289 290 return resourceVcdVAppRead(d, meta) 291 } 292 293 func resourceVcdVAppRead(d *schema.ResourceData, meta interface{}) error { 294 vcdClient := meta.(*VCDClient) 295 296 err := vcdClient.OrgVdc.Refresh() 297 if err != nil { 298 return fmt.Errorf("Error refreshing vdc: %#v", err) 299 } 300 301 _, err = vcdClient.OrgVdc.FindVAppByName(d.Id()) 302 if err != nil { 303 log.Printf("[DEBUG] Unable to find vapp. Removing from tfstate") 304 d.SetId("") 305 return nil 306 } 307 308 ip, err := getVAppIPAddress(d, meta) 309 if err != nil { 310 return err 311 } 312 d.Set("ip", ip) 313 314 return nil 315 } 316 317 func getVAppIPAddress(d *schema.ResourceData, meta interface{}) (string, error) { 318 vcdClient := meta.(*VCDClient) 319 var ip string 320 321 err := retryCall(vcdClient.MaxRetryTimeout, func() *resource.RetryError { 322 err := vcdClient.OrgVdc.Refresh() 323 if err != nil { 324 return resource.RetryableError(fmt.Errorf("Error refreshing vdc: %#v", err)) 325 } 326 vapp, err := vcdClient.OrgVdc.FindVAppByName(d.Id()) 327 if err != nil { 328 return resource.RetryableError(fmt.Errorf("Unable to find vapp.")) 329 } 330 ip = vapp.VApp.Children.VM[0].NetworkConnectionSection.NetworkConnection.IPAddress 331 if ip == "" { 332 return resource.RetryableError(fmt.Errorf("Timeout: VM did not aquire IP address")) 333 } 334 return nil 335 }) 336 337 return ip, err 338 } 339 340 func resourceVcdVAppDelete(d *schema.ResourceData, meta interface{}) error { 341 vcdClient := meta.(*VCDClient) 342 vapp, err := vcdClient.OrgVdc.FindVAppByName(d.Id()) 343 344 if err != nil { 345 return fmt.Errorf("error finding vapp: %s", err) 346 } 347 348 if err != nil { 349 return fmt.Errorf("Error getting VApp status: %#v", err) 350 } 351 352 _ = retryCall(vcdClient.MaxRetryTimeout, func() *resource.RetryError { 353 task, err := vapp.Undeploy() 354 if err != nil { 355 return resource.RetryableError(fmt.Errorf("Error undeploying: %#v", err)) 356 } 357 358 return resource.RetryableError(task.WaitTaskCompletion()) 359 }) 360 361 err = retryCall(vcdClient.MaxRetryTimeout, func() *resource.RetryError { 362 task, err := vapp.Delete() 363 if err != nil { 364 return resource.RetryableError(fmt.Errorf("Error deleting: %#v", err)) 365 } 366 367 return resource.RetryableError(task.WaitTaskCompletion()) 368 }) 369 370 return err 371 }