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 }