github.com/arvindram03/terraform@v0.3.7-0.20150212015210-408f838db36d/builtin/providers/azure/resource_virtual_machine.go (about)

     1  package azure
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"log"
     7  
     8  	"github.com/MSOpenTech/azure-sdk-for-go/clients/hostedServiceClient"
     9  	"github.com/MSOpenTech/azure-sdk-for-go/clients/vmClient"
    10  	"github.com/hashicorp/terraform/helper/hashcode"
    11  	"github.com/hashicorp/terraform/helper/schema"
    12  )
    13  
    14  func resourceVirtualMachine() *schema.Resource {
    15  	return &schema.Resource{
    16  		Create: resourceVirtualMachineCreate,
    17  		Read:   resourceVirtualMachineRead,
    18  		Delete: resourceVirtualMachineDelete,
    19  
    20  		Schema: map[string]*schema.Schema{
    21  			"name": &schema.Schema{
    22  				Type:     schema.TypeString,
    23  				Required: true,
    24  				ForceNew: true,
    25  			},
    26  
    27  			"location": &schema.Schema{
    28  				Type:     schema.TypeString,
    29  				Required: true,
    30  				ForceNew: true,
    31  			},
    32  
    33  			"image": &schema.Schema{
    34  				Type:     schema.TypeString,
    35  				Required: true,
    36  				ForceNew: true,
    37  			},
    38  
    39  			"size": &schema.Schema{
    40  				Type:     schema.TypeString,
    41  				Required: true,
    42  				ForceNew: true,
    43  			},
    44  
    45  			"username": &schema.Schema{
    46  				Type:     schema.TypeString,
    47  				Required: true,
    48  				ForceNew: true,
    49  			},
    50  
    51  			"password": &schema.Schema{
    52  				Type:     schema.TypeString,
    53  				Optional: true,
    54  				Default:  "",
    55  				ForceNew: true,
    56  			},
    57  
    58  			"ssh_public_key_file": &schema.Schema{
    59  				Type:     schema.TypeString,
    60  				Optional: true,
    61  				Default:  "",
    62  				ForceNew: true,
    63  			},
    64  
    65  			"ssh_port": &schema.Schema{
    66  				Type:     schema.TypeInt,
    67  				Optional: true,
    68  				Default:  22,
    69  				ForceNew: true,
    70  			},
    71  
    72  			"endpoint": &schema.Schema{
    73  				Type:     schema.TypeSet,
    74  				Optional: true,
    75  				Computed: true,
    76  				ForceNew: true, // This can be updatable once we support updates on the resource
    77  				Elem: &schema.Resource{
    78  					Schema: map[string]*schema.Schema{
    79  						"name": &schema.Schema{
    80  							Type:     schema.TypeString,
    81  							Required: true,
    82  						},
    83  
    84  						"protocol": &schema.Schema{
    85  							Type:     schema.TypeString,
    86  							Required: true,
    87  						},
    88  
    89  						"port": &schema.Schema{
    90  							Type:     schema.TypeInt,
    91  							Required: true,
    92  						},
    93  
    94  						"local_port": &schema.Schema{
    95  							Type:     schema.TypeInt,
    96  							Required: true,
    97  						},
    98  					},
    99  				},
   100  				Set: resourceVirtualMachineEndpointHash,
   101  			},
   102  
   103  			"url": &schema.Schema{
   104  				Type:     schema.TypeString,
   105  				Computed: true,
   106  			},
   107  
   108  			"ip_address": &schema.Schema{
   109  				Type:     schema.TypeString,
   110  				Computed: true,
   111  			},
   112  
   113  			"vip_address": &schema.Schema{
   114  				Type:     schema.TypeString,
   115  				Computed: true,
   116  			},
   117  		},
   118  	}
   119  }
   120  
   121  func resourceVirtualMachineCreate(d *schema.ResourceData, meta interface{}) error {
   122  	log.Printf("[DEBUG] Creating Azure Virtual Machine Configuration...")
   123  	vmConfig, err := vmClient.CreateAzureVMConfiguration(
   124  		d.Get("name").(string),
   125  		d.Get("size").(string),
   126  		d.Get("image").(string),
   127  		d.Get("location").(string))
   128  	if err != nil {
   129  		return fmt.Errorf("Error creating Azure virtual machine configuration: %s", err)
   130  	}
   131  
   132  	// Only Linux VMs are supported. If we want to support other VM types, we need to
   133  	// grab the image details and based on the OS add the corresponding configuration.
   134  	log.Printf("[DEBUG] Adding Azure Linux Provisioning Configuration...")
   135  	vmConfig, err = vmClient.AddAzureLinuxProvisioningConfig(
   136  		vmConfig,
   137  		d.Get("username").(string),
   138  		d.Get("password").(string),
   139  		d.Get("ssh_public_key_file").(string),
   140  		d.Get("ssh_port").(int))
   141  	if err != nil {
   142  		return fmt.Errorf("Error adding Azure linux provisioning configuration: %s", err)
   143  	}
   144  
   145  	if v := d.Get("endpoint").(*schema.Set); v.Len() > 0 {
   146  		log.Printf("[DEBUG] Adding Endpoints to the Azure Virtual Machine...")
   147  		endpoints := make([]vmClient.InputEndpoint, v.Len())
   148  		for i, v := range v.List() {
   149  			m := v.(map[string]interface{})
   150  			endpoint := vmClient.InputEndpoint{}
   151  			endpoint.Name = m["name"].(string)
   152  			endpoint.Protocol = m["protocol"].(string)
   153  			endpoint.Port = m["port"].(int)
   154  			endpoint.LocalPort = m["local_port"].(int)
   155  			endpoints[i] = endpoint
   156  		}
   157  
   158  		configSets := vmConfig.ConfigurationSets.ConfigurationSet
   159  		if len(configSets) == 0 {
   160  			return fmt.Errorf("Azure virtual machine does not have configuration sets")
   161  		}
   162  		for i := 0; i < len(configSets); i++ {
   163  			if configSets[i].ConfigurationSetType != "NetworkConfiguration" {
   164  				continue
   165  			}
   166  			configSets[i].InputEndpoints.InputEndpoint =
   167  				append(configSets[i].InputEndpoints.InputEndpoint, endpoints...)
   168  		}
   169  	}
   170  
   171  	log.Printf("[DEBUG] Creating Azure Virtual Machine...")
   172  	err = vmClient.CreateAzureVM(
   173  		vmConfig,
   174  		d.Get("name").(string),
   175  		d.Get("location").(string))
   176  	if err != nil {
   177  		return fmt.Errorf("Error creating Azure virtual machine: %s", err)
   178  	}
   179  
   180  	d.SetId(d.Get("name").(string))
   181  
   182  	return resourceVirtualMachineRead(d, meta)
   183  }
   184  
   185  func resourceVirtualMachineRead(d *schema.ResourceData, meta interface{}) error {
   186  	log.Printf("[DEBUG] Getting Azure Virtual Machine Deployment: %s", d.Id())
   187  	VMDeployment, err := vmClient.GetVMDeployment(d.Id(), d.Id())
   188  	if err != nil {
   189  		return fmt.Errorf("Error getting Azure virtual machine deployment: %s", err)
   190  	}
   191  
   192  	d.Set("url", VMDeployment.Url)
   193  
   194  	roleInstances := VMDeployment.RoleInstanceList.RoleInstance
   195  	if len(roleInstances) == 0 {
   196  		return fmt.Errorf("Virtual Machine does not have IP addresses")
   197  	}
   198  	ipAddress := roleInstances[0].IpAddress
   199  	d.Set("ip_address", ipAddress)
   200  
   201  	vips := VMDeployment.VirtualIPs.VirtualIP
   202  	if len(vips) == 0 {
   203  		return fmt.Errorf("Virtual Machine does not have VIP addresses")
   204  	}
   205  	vip := vips[0].Address
   206  	d.Set("vip_address", vip)
   207  
   208  	d.SetConnInfo(map[string]string{
   209  		"type": "ssh",
   210  		"host": vip,
   211  		"user": d.Get("username").(string),
   212  	})
   213  
   214  	return nil
   215  }
   216  
   217  func resourceVirtualMachineDelete(d *schema.ResourceData, meta interface{}) error {
   218  	log.Printf("[DEBUG] Deleting Azure Virtual Machine Deployment: %s", d.Id())
   219  	if err := vmClient.DeleteVMDeployment(d.Id(), d.Id()); err != nil {
   220  		return fmt.Errorf("Error deleting Azure virtual machine deployment: %s", err)
   221  	}
   222  
   223  	log.Printf("[DEBUG] Deleting Azure Hosted Service: %s", d.Id())
   224  	if err := hostedServiceClient.DeleteHostedService(d.Id()); err != nil {
   225  		return fmt.Errorf("Error deleting Azure hosted service: %s", err)
   226  	}
   227  
   228  	d.SetId("")
   229  
   230  	return nil
   231  }
   232  
   233  func resourceVirtualMachineEndpointHash(v interface{}) int {
   234  	var buf bytes.Buffer
   235  	m := v.(map[string]interface{})
   236  	buf.WriteString(fmt.Sprintf("%s-", m["name"].(string)))
   237  	buf.WriteString(fmt.Sprintf("%s-", m["protocol"].(string)))
   238  	buf.WriteString(fmt.Sprintf("%d-", m["port"].(int)))
   239  	buf.WriteString(fmt.Sprintf("%d-", m["local_port"].(int)))
   240  
   241  	return hashcode.String(buf.String())
   242  }