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  }