github.com/jmbataller/terraform@v0.6.8-0.20151125192640-b7a12e3a580c/builtin/providers/openstack/resource_openstack_lb_vip_v1.go (about) 1 package openstack 2 3 import ( 4 "fmt" 5 "log" 6 7 "github.com/hashicorp/terraform/helper/schema" 8 "github.com/rackspace/gophercloud" 9 "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/floatingips" 10 "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/vips" 11 ) 12 13 func resourceLBVipV1() *schema.Resource { 14 return &schema.Resource{ 15 Create: resourceLBVipV1Create, 16 Read: resourceLBVipV1Read, 17 Update: resourceLBVipV1Update, 18 Delete: resourceLBVipV1Delete, 19 20 Schema: map[string]*schema.Schema{ 21 "region": &schema.Schema{ 22 Type: schema.TypeString, 23 Required: true, 24 ForceNew: true, 25 DefaultFunc: envDefaultFuncAllowMissing("OS_REGION_NAME"), 26 }, 27 "name": &schema.Schema{ 28 Type: schema.TypeString, 29 Required: true, 30 ForceNew: false, 31 }, 32 "subnet_id": &schema.Schema{ 33 Type: schema.TypeString, 34 Required: true, 35 ForceNew: true, 36 }, 37 "protocol": &schema.Schema{ 38 Type: schema.TypeString, 39 Required: true, 40 ForceNew: true, 41 }, 42 "port": &schema.Schema{ 43 Type: schema.TypeInt, 44 Required: true, 45 ForceNew: true, 46 }, 47 "pool_id": &schema.Schema{ 48 Type: schema.TypeString, 49 Required: true, 50 ForceNew: false, 51 }, 52 "tenant_id": &schema.Schema{ 53 Type: schema.TypeString, 54 Optional: true, 55 Computed: true, 56 ForceNew: true, 57 }, 58 "address": &schema.Schema{ 59 Type: schema.TypeString, 60 Optional: true, 61 Computed: true, 62 ForceNew: true, 63 }, 64 "description": &schema.Schema{ 65 Type: schema.TypeString, 66 Optional: true, 67 Computed: true, 68 ForceNew: false, 69 }, 70 "persistence": &schema.Schema{ 71 Type: schema.TypeMap, 72 Optional: true, 73 ForceNew: false, 74 }, 75 "conn_limit": &schema.Schema{ 76 Type: schema.TypeInt, 77 Optional: true, 78 Computed: true, 79 ForceNew: false, 80 }, 81 "port_id": &schema.Schema{ 82 Type: schema.TypeString, 83 Computed: true, 84 ForceNew: false, 85 }, 86 "floating_ip": &schema.Schema{ 87 Type: schema.TypeString, 88 Optional: true, 89 ForceNew: false, 90 }, 91 "admin_state_up": &schema.Schema{ 92 Type: schema.TypeBool, 93 Optional: true, 94 Computed: true, 95 ForceNew: false, 96 }, 97 }, 98 } 99 } 100 101 func resourceLBVipV1Create(d *schema.ResourceData, meta interface{}) error { 102 config := meta.(*Config) 103 networkingClient, err := config.networkingV2Client(d.Get("region").(string)) 104 if err != nil { 105 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 106 } 107 108 createOpts := vips.CreateOpts{ 109 Name: d.Get("name").(string), 110 SubnetID: d.Get("subnet_id").(string), 111 Protocol: d.Get("protocol").(string), 112 ProtocolPort: d.Get("port").(int), 113 PoolID: d.Get("pool_id").(string), 114 TenantID: d.Get("tenant_id").(string), 115 Address: d.Get("address").(string), 116 Description: d.Get("description").(string), 117 Persistence: resourceVipPersistenceV1(d), 118 ConnLimit: gophercloud.MaybeInt(d.Get("conn_limit").(int)), 119 } 120 121 asu := d.Get("admin_state_up").(bool) 122 createOpts.AdminStateUp = &asu 123 124 log.Printf("[DEBUG] Create Options: %#v", createOpts) 125 p, err := vips.Create(networkingClient, createOpts).Extract() 126 if err != nil { 127 return fmt.Errorf("Error creating OpenStack LB VIP: %s", err) 128 } 129 log.Printf("[INFO] LB VIP ID: %s", p.ID) 130 131 floatingIP := d.Get("floating_ip").(string) 132 if floatingIP != "" { 133 lbVipV1AssignFloatingIP(floatingIP, p.PortID, networkingClient) 134 } 135 136 d.SetId(p.ID) 137 138 return resourceLBVipV1Read(d, meta) 139 } 140 141 func resourceLBVipV1Read(d *schema.ResourceData, meta interface{}) error { 142 config := meta.(*Config) 143 networkingClient, err := config.networkingV2Client(d.Get("region").(string)) 144 if err != nil { 145 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 146 } 147 148 p, err := vips.Get(networkingClient, d.Id()).Extract() 149 if err != nil { 150 return CheckDeleted(d, err, "LB VIP") 151 } 152 153 log.Printf("[DEBUG] Retreived OpenStack LB VIP %s: %+v", d.Id(), p) 154 155 d.Set("name", p.Name) 156 d.Set("subnet_id", p.SubnetID) 157 d.Set("protocol", p.Protocol) 158 d.Set("port", p.ProtocolPort) 159 d.Set("pool_id", p.PoolID) 160 d.Set("port_id", p.PortID) 161 d.Set("tenant_id", p.TenantID) 162 d.Set("address", p.Address) 163 d.Set("description", p.Description) 164 d.Set("conn_limit", p.ConnLimit) 165 d.Set("admin_state_up", p.AdminStateUp) 166 167 return nil 168 } 169 170 func resourceLBVipV1Update(d *schema.ResourceData, meta interface{}) error { 171 config := meta.(*Config) 172 networkingClient, err := config.networkingV2Client(d.Get("region").(string)) 173 if err != nil { 174 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 175 } 176 177 var updateOpts vips.UpdateOpts 178 if d.HasChange("name") { 179 updateOpts.Name = d.Get("name").(string) 180 } 181 if d.HasChange("pool_id") { 182 updateOpts.PoolID = d.Get("pool_id").(string) 183 } 184 if d.HasChange("description") { 185 updateOpts.Description = d.Get("description").(string) 186 } 187 if d.HasChange("persistence") { 188 updateOpts.Persistence = resourceVipPersistenceV1(d) 189 } 190 if d.HasChange("conn_limit") { 191 updateOpts.ConnLimit = gophercloud.MaybeInt(d.Get("conn_limit").(int)) 192 } 193 if d.HasChange("floating_ip") { 194 portID := d.Get("port_id").(string) 195 196 // Searching for a floating IP assigned to the VIP 197 listOpts := floatingips.ListOpts{ 198 PortID: portID, 199 } 200 page, err := floatingips.List(networkingClient, listOpts).AllPages() 201 if err != nil { 202 return err 203 } 204 205 fips, err := floatingips.ExtractFloatingIPs(page) 206 if err != nil { 207 return err 208 } 209 210 // If a floating IP is found we unassign it 211 if len(fips) == 1 { 212 updateOpts := floatingips.UpdateOpts{ 213 PortID: "", 214 } 215 if err = floatingips.Update(networkingClient, fips[0].ID, updateOpts).Err; err != nil { 216 return err 217 } 218 } 219 220 // Assign the updated floating IP 221 floatingIP := d.Get("floating_ip").(string) 222 if floatingIP != "" { 223 lbVipV1AssignFloatingIP(floatingIP, portID, networkingClient) 224 } 225 } 226 if d.HasChange("admin_state_up") { 227 asu := d.Get("admin_state_up").(bool) 228 updateOpts.AdminStateUp = &asu 229 } 230 231 log.Printf("[DEBUG] Updating OpenStack LB VIP %s with options: %+v", d.Id(), updateOpts) 232 233 _, err = vips.Update(networkingClient, d.Id(), updateOpts).Extract() 234 if err != nil { 235 return fmt.Errorf("Error updating OpenStack LB VIP: %s", err) 236 } 237 238 return resourceLBVipV1Read(d, meta) 239 } 240 241 func resourceLBVipV1Delete(d *schema.ResourceData, meta interface{}) error { 242 config := meta.(*Config) 243 networkingClient, err := config.networkingV2Client(d.Get("region").(string)) 244 if err != nil { 245 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 246 } 247 248 err = vips.Delete(networkingClient, d.Id()).ExtractErr() 249 if err != nil { 250 return fmt.Errorf("Error deleting OpenStack LB VIP: %s", err) 251 } 252 253 d.SetId("") 254 return nil 255 } 256 257 func resourceVipPersistenceV1(d *schema.ResourceData) *vips.SessionPersistence { 258 rawP := d.Get("persistence").(interface{}) 259 rawMap := rawP.(map[string]interface{}) 260 if len(rawMap) != 0 { 261 p := vips.SessionPersistence{} 262 if t, ok := rawMap["type"]; ok { 263 p.Type = t.(string) 264 } 265 if c, ok := rawMap["cookie_name"]; ok { 266 p.CookieName = c.(string) 267 } 268 return &p 269 } 270 return nil 271 } 272 273 func lbVipV1AssignFloatingIP(floatingIP, portID string, networkingClient *gophercloud.ServiceClient) error { 274 log.Printf("[DEBUG] Assigning floating IP %s to VIP %s", floatingIP, portID) 275 276 listOpts := floatingips.ListOpts{ 277 FloatingIP: floatingIP, 278 } 279 page, err := floatingips.List(networkingClient, listOpts).AllPages() 280 if err != nil { 281 return err 282 } 283 284 fips, err := floatingips.ExtractFloatingIPs(page) 285 if err != nil { 286 return err 287 } 288 if len(fips) != 1 { 289 return fmt.Errorf("Unable to retrieve floating IP '%s'", floatingIP) 290 } 291 292 updateOpts := floatingips.UpdateOpts{ 293 PortID: portID, 294 } 295 if err = floatingips.Update(networkingClient, fips[0].ID, updateOpts).Err; err != nil { 296 return err 297 } 298 299 return nil 300 }