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