github.com/skyscape-cloud-services/terraform@v0.9.2-0.20170609144644-7ece028a1747/builtin/providers/vcd/resource_vcd_vapp_vm.go (about) 1 package vcd 2 3 import ( 4 "fmt" 5 "github.com/hashicorp/terraform/helper/resource" 6 "github.com/hashicorp/terraform/helper/schema" 7 "log" 8 ) 9 10 func resourceVcdVAppVm() *schema.Resource { 11 return &schema.Resource{ 12 Create: resourceVcdVAppVmCreate, 13 Update: resourceVcdVAppVmUpdate, 14 Read: resourceVcdVAppVmRead, 15 Delete: resourceVcdVAppVmDelete, 16 17 Schema: map[string]*schema.Schema{ 18 "vapp_name": &schema.Schema{ 19 Type: schema.TypeString, 20 Required: true, 21 ForceNew: true, 22 }, 23 24 "name": &schema.Schema{ 25 Type: schema.TypeString, 26 Required: true, 27 ForceNew: true, 28 }, 29 30 "template_name": &schema.Schema{ 31 Type: schema.TypeString, 32 Required: true, 33 ForceNew: true, 34 }, 35 36 "catalog_name": &schema.Schema{ 37 Type: schema.TypeString, 38 Required: true, 39 ForceNew: true, 40 }, 41 42 "memory": &schema.Schema{ 43 Type: schema.TypeInt, 44 Optional: true, 45 }, 46 "cpus": &schema.Schema{ 47 Type: schema.TypeInt, 48 Optional: true, 49 }, 50 "ip": &schema.Schema{ 51 Type: schema.TypeString, 52 Optional: true, 53 Computed: true, 54 }, 55 "initscript": &schema.Schema{ 56 Type: schema.TypeString, 57 Optional: true, 58 ForceNew: true, 59 }, 60 61 "href": &schema.Schema{ 62 Type: schema.TypeString, 63 Optional: true, 64 Computed: true, 65 }, 66 "power_on": &schema.Schema{ 67 Type: schema.TypeBool, 68 Optional: true, 69 Default: true, 70 }, 71 }, 72 } 73 } 74 75 func resourceVcdVAppVmCreate(d *schema.ResourceData, meta interface{}) error { 76 vcdClient := meta.(*VCDClient) 77 78 catalog, err := vcdClient.Org.FindCatalog(d.Get("catalog_name").(string)) 79 if err != nil { 80 return fmt.Errorf("Error finding catalog: %#v", err) 81 } 82 83 catalogitem, err := catalog.FindCatalogItem(d.Get("template_name").(string)) 84 if err != nil { 85 return fmt.Errorf("Error finding catelog item: %#v", err) 86 } 87 88 vapptemplate, err := catalogitem.GetVAppTemplate() 89 if err != nil { 90 return fmt.Errorf("Error finding VAppTemplate: %#v", err) 91 } 92 93 vapp, err := vcdClient.OrgVdc.FindVAppByName(d.Get("vapp_name").(string)) 94 95 // get the network of the first child 96 97 if len(vapp.VApp.Children.VM) == 0 { 98 d.SetId("") 99 return fmt.Errorf("Current multi-VM support requires network to be determinted by initial VM. No VM's found so aborting.") 100 } 101 102 netname := vapp.VApp.Children.VM[0].NetworkConnectionSection.NetworkConnection.Network 103 104 log.Printf("[TRACE] Network name found: %s", netname) 105 106 net, err := vcdClient.OrgVdc.FindVDCNetwork(netname) 107 if err != nil { 108 return fmt.Errorf("Error finding OrgVCD Network: %#v", err) 109 } 110 111 err = retryCall(vcdClient.MaxRetryTimeout, func() *resource.RetryError { 112 log.Printf("[TRACE] Creating VM: %s", d.Get("name").(string)) 113 e := vapp.AddVM(net, vapptemplate, d.Get("name").(string)) 114 115 if e != nil { 116 return resource.RetryableError(fmt.Errorf("Error: %#v", e)) 117 } 118 119 e = vcdClient.OrgVdc.Refresh() 120 if e != nil { 121 return resource.RetryableError(fmt.Errorf("Error: %#v", e)) 122 } 123 return nil 124 }) 125 if err != nil { 126 return err 127 } 128 129 vm, err := vcdClient.OrgVdc.FindVMByName(vapp, d.Get("name").(string)) 130 131 if err != nil { 132 d.SetId("") 133 return fmt.Errorf("Error getting VM1 : %#v", err) 134 } 135 136 err = retryCall(vcdClient.MaxRetryTimeout, func() *resource.RetryError { 137 task, err := vm.ChangeNetworkConfig(netname, d.Get("ip").(string)) 138 if err != nil { 139 return resource.RetryableError(fmt.Errorf("Error with Networking change: %#v", err)) 140 } 141 return resource.RetryableError(task.WaitTaskCompletion()) 142 }) 143 if err != nil { 144 return fmt.Errorf("Error changing network: %#v", err) 145 } 146 147 if initscript, ok := d.GetOk("initscript"); ok { 148 err = retryCall(vcdClient.MaxRetryTimeout, func() *resource.RetryError { 149 task, err := vm.RunCustomizationScript(d.Get("name").(string), initscript.(string)) 150 if err != nil { 151 return resource.RetryableError(fmt.Errorf("Error with setting init script: %#v", err)) 152 } 153 return resource.RetryableError(task.WaitTaskCompletion()) 154 }) 155 if err != nil { 156 return fmt.Errorf("Error completing tasks: %#v", err) 157 } 158 } 159 160 d.SetId(d.Get("name").(string)) 161 162 return resourceVcdVAppVmUpdate(d, meta) 163 } 164 165 func resourceVcdVAppVmUpdate(d *schema.ResourceData, meta interface{}) error { 166 167 vcdClient := meta.(*VCDClient) 168 169 vapp, err := vcdClient.OrgVdc.FindVAppByName(d.Get("vapp_name").(string)) 170 171 if err != nil { 172 return fmt.Errorf("error finding vapp: %s", err) 173 } 174 175 vm, err := vcdClient.OrgVdc.FindVMByName(vapp, d.Get("name").(string)) 176 177 if err != nil { 178 d.SetId("") 179 return fmt.Errorf("Error getting VM2: %#v", err) 180 } 181 182 status, err := vm.GetStatus() 183 if err != nil { 184 return fmt.Errorf("Error getting VM status: %#v", err) 185 } 186 187 if d.HasChange("memory") || d.HasChange("cpus") || d.HasChange("power_on") { 188 if status != "POWERED_OFF" { 189 task, err := vm.PowerOff() 190 if err != nil { 191 return fmt.Errorf("Error Powering Off: %#v", err) 192 } 193 err = task.WaitTaskCompletion() 194 if err != nil { 195 return fmt.Errorf("Error completing tasks: %#v", err) 196 } 197 } 198 199 if d.HasChange("memory") { 200 err = retryCall(vcdClient.MaxRetryTimeout, func() *resource.RetryError { 201 task, err := vm.ChangeMemorySize(d.Get("memory").(int)) 202 if err != nil { 203 return resource.RetryableError(fmt.Errorf("Error changing memory size: %#v", err)) 204 } 205 206 return resource.RetryableError(task.WaitTaskCompletion()) 207 }) 208 if err != nil { 209 return err 210 } 211 } 212 213 if d.HasChange("cpus") { 214 err = retryCall(vcdClient.MaxRetryTimeout, func() *resource.RetryError { 215 task, err := vm.ChangeCPUcount(d.Get("cpus").(int)) 216 if err != nil { 217 return resource.RetryableError(fmt.Errorf("Error changing cpu count: %#v", err)) 218 } 219 220 return resource.RetryableError(task.WaitTaskCompletion()) 221 }) 222 if err != nil { 223 return fmt.Errorf("Error completing task: %#v", err) 224 } 225 } 226 227 if d.Get("power_on").(bool) { 228 task, err := vm.PowerOn() 229 if err != nil { 230 return fmt.Errorf("Error Powering Up: %#v", err) 231 } 232 err = task.WaitTaskCompletion() 233 if err != nil { 234 return fmt.Errorf("Error completing tasks: %#v", err) 235 } 236 } 237 238 } 239 240 return resourceVcdVAppVmRead(d, meta) 241 } 242 243 func resourceVcdVAppVmRead(d *schema.ResourceData, meta interface{}) error { 244 vcdClient := meta.(*VCDClient) 245 246 vapp, err := vcdClient.OrgVdc.FindVAppByName(d.Get("vapp_name").(string)) 247 248 if err != nil { 249 return fmt.Errorf("error finding vapp: %s", err) 250 } 251 252 vm, err := vcdClient.OrgVdc.FindVMByName(vapp, d.Get("name").(string)) 253 254 if err != nil { 255 d.SetId("") 256 return fmt.Errorf("Error getting VM3 : %#v", err) 257 } 258 259 d.Set("name", vm.VM.Name) 260 d.Set("ip", vm.VM.NetworkConnectionSection.NetworkConnection.IPAddress) 261 d.Set("href", vm.VM.HREF) 262 263 return nil 264 } 265 266 func resourceVcdVAppVmDelete(d *schema.ResourceData, meta interface{}) error { 267 vcdClient := meta.(*VCDClient) 268 269 vapp, err := vcdClient.OrgVdc.FindVAppByName(d.Get("vapp_name").(string)) 270 271 if err != nil { 272 return fmt.Errorf("error finding vapp: %s", err) 273 } 274 275 vm, err := vcdClient.OrgVdc.FindVMByName(vapp, d.Get("name").(string)) 276 277 if err != nil { 278 return fmt.Errorf("Error getting VM4 : %#v", err) 279 } 280 281 status, err := vapp.GetStatus() 282 if err != nil { 283 return fmt.Errorf("Error getting vApp status: %#v", err) 284 } 285 286 log.Printf("[TRACE] Vapp Status:: %s", status) 287 if status != "POWERED_OFF" { 288 log.Printf("[TRACE] Undeploying vApp: %s", vapp.VApp.Name) 289 task, err := vapp.Undeploy() 290 if err != nil { 291 return fmt.Errorf("Error Undeploying vApp: %#v", err) 292 } 293 err = task.WaitTaskCompletion() 294 if err != nil { 295 return fmt.Errorf("Error completing tasks: %#v", err) 296 } 297 } 298 299 err = retryCall(vcdClient.MaxRetryTimeout, func() *resource.RetryError { 300 log.Printf("[TRACE] Removing VM: %s", vm.VM.Name) 301 err := vapp.RemoveVM(vm) 302 if err != nil { 303 return resource.RetryableError(fmt.Errorf("Error deleting: %#v", err)) 304 } 305 306 return nil 307 }) 308 309 if status != "POWERED_OFF" { 310 log.Printf("[TRACE] Redeploying vApp: %s", vapp.VApp.Name) 311 task, err := vapp.Deploy() 312 if err != nil { 313 return fmt.Errorf("Error Deploying vApp: %#v", err) 314 } 315 err = task.WaitTaskCompletion() 316 if err != nil { 317 return fmt.Errorf("Error completing tasks: %#v", err) 318 } 319 320 log.Printf("[TRACE] Powering on vApp: %s", vapp.VApp.Name) 321 task, err = vapp.PowerOn() 322 if err != nil { 323 return fmt.Errorf("Error Powering on vApp: %#v", err) 324 } 325 err = task.WaitTaskCompletion() 326 if err != nil { 327 return fmt.Errorf("Error completing tasks: %#v", err) 328 } 329 } 330 331 return err 332 }