github.com/turtlemonvh/terraform@v0.6.9-0.20151204001754-8e40b6b855e8/builtin/providers/vcd/resource_vcd_vapp.go (about)

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