github.com/emc-cmd/terraform@v0.7.8-0.20161101145618-f16309630e7c/builtin/providers/openstack/resource_openstack_lb_loadbalancer_v2.go (about) 1 package openstack 2 3 import ( 4 "fmt" 5 "log" 6 "time" 7 8 "github.com/hashicorp/terraform/helper/resource" 9 "github.com/hashicorp/terraform/helper/schema" 10 11 "github.com/gophercloud/gophercloud" 12 "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/loadbalancers" 13 ) 14 15 func resourceLoadBalancerV2() *schema.Resource { 16 return &schema.Resource{ 17 Create: resourceLoadBalancerV2Create, 18 Read: resourceLoadBalancerV2Read, 19 Update: resourceLoadBalancerV2Update, 20 Delete: resourceLoadBalancerV2Delete, 21 22 Schema: map[string]*schema.Schema{ 23 "region": &schema.Schema{ 24 Type: schema.TypeString, 25 Required: true, 26 ForceNew: true, 27 DefaultFunc: schema.EnvDefaultFunc("OS_REGION_NAME", ""), 28 }, 29 30 "name": &schema.Schema{ 31 Type: schema.TypeString, 32 Optional: true, 33 }, 34 35 "description": &schema.Schema{ 36 Type: schema.TypeString, 37 Optional: true, 38 }, 39 40 "vip_subnet_id": &schema.Schema{ 41 Type: schema.TypeString, 42 Required: true, 43 ForceNew: true, 44 }, 45 46 "tenant_id": &schema.Schema{ 47 Type: schema.TypeString, 48 Optional: true, 49 Computed: true, 50 ForceNew: true, 51 }, 52 53 "vip_address": &schema.Schema{ 54 Type: schema.TypeString, 55 Optional: true, 56 Computed: true, 57 ForceNew: true, 58 }, 59 60 "vip_port_id": &schema.Schema{ 61 Type: schema.TypeString, 62 Computed: true, 63 }, 64 65 "admin_state_up": &schema.Schema{ 66 Type: schema.TypeBool, 67 Default: true, 68 Optional: true, 69 }, 70 71 "flavor": &schema.Schema{ 72 Type: schema.TypeString, 73 Optional: true, 74 ForceNew: true, 75 }, 76 77 "provider": &schema.Schema{ 78 Type: schema.TypeString, 79 Optional: true, 80 Computed: true, 81 ForceNew: true, 82 }, 83 }, 84 } 85 } 86 87 func resourceLoadBalancerV2Create(d *schema.ResourceData, meta interface{}) error { 88 config := meta.(*Config) 89 networkingClient, err := config.networkingV2Client(d.Get("region").(string)) 90 if err != nil { 91 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 92 } 93 94 adminStateUp := d.Get("admin_state_up").(bool) 95 createOpts := loadbalancers.CreateOpts{ 96 Name: d.Get("name").(string), 97 Description: d.Get("description").(string), 98 VipSubnetID: d.Get("vip_subnet_id").(string), 99 TenantID: d.Get("tenant_id").(string), 100 VipAddress: d.Get("vip_address").(string), 101 AdminStateUp: &adminStateUp, 102 Flavor: d.Get("flavor").(string), 103 Provider: d.Get("provider").(string), 104 } 105 106 log.Printf("[DEBUG] Create Options: %#v", createOpts) 107 lb, err := loadbalancers.Create(networkingClient, createOpts).Extract() 108 if err != nil { 109 return fmt.Errorf("Error creating OpenStack LoadBalancer: %s", err) 110 } 111 log.Printf("[INFO] LoadBalancer ID: %s", lb.ID) 112 113 log.Printf("[DEBUG] Waiting for Openstack LoadBalancer (%s) to become available.", lb.ID) 114 115 stateConf := &resource.StateChangeConf{ 116 Pending: []string{"PENDING_CREATE"}, 117 Target: []string{"ACTIVE"}, 118 Refresh: waitForLoadBalancerActive(networkingClient, lb.ID), 119 Timeout: 20 * time.Minute, 120 Delay: 5 * time.Second, 121 MinTimeout: 3 * time.Second, 122 } 123 124 _, err = stateConf.WaitForState() 125 if err != nil { 126 return err 127 } 128 129 d.SetId(lb.ID) 130 131 return resourceLoadBalancerV2Read(d, meta) 132 } 133 134 func resourceLoadBalancerV2Read(d *schema.ResourceData, meta interface{}) error { 135 config := meta.(*Config) 136 networkingClient, err := config.networkingV2Client(d.Get("region").(string)) 137 if err != nil { 138 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 139 } 140 141 lb, err := loadbalancers.Get(networkingClient, d.Id()).Extract() 142 if err != nil { 143 return CheckDeleted(d, err, "LoadBalancerV2") 144 } 145 146 log.Printf("[DEBUG] Retrieved OpenStack LBaaSV2 LoadBalancer %s: %+v", d.Id(), lb) 147 148 d.Set("name", lb.Name) 149 d.Set("description", lb.Description) 150 d.Set("vip_subnet_id", lb.VipSubnetID) 151 d.Set("tenant_id", lb.TenantID) 152 d.Set("vip_address", lb.VipAddress) 153 d.Set("vip_port_id", lb.VipPortID) 154 d.Set("admin_state_up", lb.AdminStateUp) 155 d.Set("flavor", lb.Flavor) 156 d.Set("provider", lb.Provider) 157 158 return nil 159 } 160 161 func resourceLoadBalancerV2Update(d *schema.ResourceData, meta interface{}) error { 162 config := meta.(*Config) 163 networkingClient, err := config.networkingV2Client(d.Get("region").(string)) 164 if err != nil { 165 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 166 } 167 168 var updateOpts loadbalancers.UpdateOpts 169 if d.HasChange("name") { 170 updateOpts.Name = d.Get("name").(string) 171 } 172 if d.HasChange("description") { 173 updateOpts.Description = d.Get("description").(string) 174 } 175 if d.HasChange("admin_state_up") { 176 asu := d.Get("admin_state_up").(bool) 177 updateOpts.AdminStateUp = &asu 178 } 179 180 log.Printf("[DEBUG] Updating OpenStack LBaaSV2 LoadBalancer %s with options: %+v", d.Id(), updateOpts) 181 182 _, err = loadbalancers.Update(networkingClient, d.Id(), updateOpts).Extract() 183 if err != nil { 184 return fmt.Errorf("Error updating OpenStack LBaaSV2 LoadBalancer: %s", err) 185 } 186 187 return resourceLoadBalancerV2Read(d, meta) 188 } 189 190 func resourceLoadBalancerV2Delete(d *schema.ResourceData, meta interface{}) error { 191 config := meta.(*Config) 192 networkingClient, err := config.networkingV2Client(d.Get("region").(string)) 193 if err != nil { 194 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 195 } 196 197 stateConf := &resource.StateChangeConf{ 198 Pending: []string{"ACTIVE", "PENDING_DELETE"}, 199 Target: []string{"DELETED"}, 200 Refresh: waitForLoadBalancerDelete(networkingClient, d.Id()), 201 Timeout: 2 * time.Minute, 202 Delay: 5 * time.Second, 203 MinTimeout: 3 * time.Second, 204 } 205 206 _, err = stateConf.WaitForState() 207 if err != nil { 208 return fmt.Errorf("Error deleting OpenStack LBaaSV2 LoadBalancer: %s", err) 209 } 210 211 d.SetId("") 212 return nil 213 } 214 215 func waitForLoadBalancerActive(networkingClient *gophercloud.ServiceClient, lbID string) resource.StateRefreshFunc { 216 return func() (interface{}, string, error) { 217 lb, err := loadbalancers.Get(networkingClient, lbID).Extract() 218 if err != nil { 219 return nil, "", err 220 } 221 222 log.Printf("[DEBUG] OpenStack LBaaSV2 LoadBalancer: %+v", lb) 223 if lb.ProvisioningStatus == "ACTIVE" { 224 return lb, "ACTIVE", nil 225 } 226 227 return lb, lb.ProvisioningStatus, nil 228 } 229 } 230 231 func waitForLoadBalancerDelete(networkingClient *gophercloud.ServiceClient, lbID string) resource.StateRefreshFunc { 232 return func() (interface{}, string, error) { 233 log.Printf("[DEBUG] Attempting to delete OpenStack LBaaSV2 LoadBalancer %s", lbID) 234 235 lb, err := loadbalancers.Get(networkingClient, lbID).Extract() 236 if err != nil { 237 if _, ok := err.(gophercloud.ErrDefault404); ok { 238 log.Printf("[DEBUG] Successfully deleted OpenStack LBaaSV2 LoadBalancer %s", lbID) 239 return lb, "DELETED", nil 240 } 241 return lb, "ACTIVE", err 242 } 243 244 log.Printf("[DEBUG] Openstack LoadBalancerV2: %+v", lb) 245 err = loadbalancers.Delete(networkingClient, lbID).ExtractErr() 246 if err != nil { 247 if _, ok := err.(gophercloud.ErrDefault404); ok { 248 log.Printf("[DEBUG] Successfully deleted OpenStack LBaaSV2 LoadBalancer %s", lbID) 249 return lb, "DELETED", nil 250 } 251 252 if errCode, ok := err.(gophercloud.ErrUnexpectedResponseCode); ok { 253 if errCode.Actual == 409 { 254 log.Printf("[DEBUG] OpenStack LBaaSV2 LoadBalancer (%s) is still in use.", lbID) 255 return lb, "ACTIVE", nil 256 } 257 } 258 259 return lb, "ACTIVE", err 260 } 261 262 log.Printf("[DEBUG] OpenStack LBaaSV2 LoadBalancer (%s) still active.", lbID) 263 return lb, "ACTIVE", nil 264 } 265 }