github.com/minamijoyo/terraform@v0.7.8-0.20161029001309-18b3736ba44b/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 "admin_state_up": &schema.Schema{ 61 Type: schema.TypeBool, 62 Default: true, 63 Optional: true, 64 }, 65 66 "flavor": &schema.Schema{ 67 Type: schema.TypeString, 68 Optional: true, 69 ForceNew: true, 70 }, 71 72 "provider": &schema.Schema{ 73 Type: schema.TypeString, 74 Optional: true, 75 Computed: true, 76 ForceNew: true, 77 }, 78 }, 79 } 80 } 81 82 func resourceLoadBalancerV2Create(d *schema.ResourceData, meta interface{}) error { 83 config := meta.(*Config) 84 networkingClient, err := config.networkingV2Client(d.Get("region").(string)) 85 if err != nil { 86 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 87 } 88 89 adminStateUp := d.Get("admin_state_up").(bool) 90 createOpts := loadbalancers.CreateOpts{ 91 Name: d.Get("name").(string), 92 Description: d.Get("description").(string), 93 VipSubnetID: d.Get("vip_subnet_id").(string), 94 TenantID: d.Get("tenant_id").(string), 95 VipAddress: d.Get("vip_address").(string), 96 AdminStateUp: &adminStateUp, 97 Flavor: d.Get("flavor").(string), 98 Provider: d.Get("provider").(string), 99 } 100 101 log.Printf("[DEBUG] Create Options: %#v", createOpts) 102 lb, err := loadbalancers.Create(networkingClient, createOpts).Extract() 103 if err != nil { 104 return fmt.Errorf("Error creating OpenStack LoadBalancer: %s", err) 105 } 106 log.Printf("[INFO] LoadBalancer ID: %s", lb.ID) 107 108 log.Printf("[DEBUG] Waiting for Openstack LoadBalancer (%s) to become available.", lb.ID) 109 110 stateConf := &resource.StateChangeConf{ 111 Pending: []string{"PENDING_CREATE"}, 112 Target: []string{"ACTIVE"}, 113 Refresh: waitForLoadBalancerActive(networkingClient, lb.ID), 114 Timeout: 20 * time.Minute, 115 Delay: 5 * time.Second, 116 MinTimeout: 3 * time.Second, 117 } 118 119 _, err = stateConf.WaitForState() 120 if err != nil { 121 return err 122 } 123 124 d.SetId(lb.ID) 125 126 return resourceLoadBalancerV2Read(d, meta) 127 } 128 129 func resourceLoadBalancerV2Read(d *schema.ResourceData, meta interface{}) error { 130 config := meta.(*Config) 131 networkingClient, err := config.networkingV2Client(d.Get("region").(string)) 132 if err != nil { 133 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 134 } 135 136 lb, err := loadbalancers.Get(networkingClient, d.Id()).Extract() 137 if err != nil { 138 return CheckDeleted(d, err, "LoadBalancerV2") 139 } 140 141 log.Printf("[DEBUG] Retrieved OpenStack LBaaSV2 LoadBalancer %s: %+v", d.Id(), lb) 142 143 d.Set("name", lb.Name) 144 d.Set("description", lb.Description) 145 d.Set("vip_subnet_id", lb.VipSubnetID) 146 d.Set("tenant_id", lb.TenantID) 147 d.Set("vip_address", lb.VipAddress) 148 d.Set("admin_state_up", lb.AdminStateUp) 149 d.Set("flavor", lb.Flavor) 150 d.Set("provider", lb.Provider) 151 152 return nil 153 } 154 155 func resourceLoadBalancerV2Update(d *schema.ResourceData, meta interface{}) error { 156 config := meta.(*Config) 157 networkingClient, err := config.networkingV2Client(d.Get("region").(string)) 158 if err != nil { 159 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 160 } 161 162 var updateOpts loadbalancers.UpdateOpts 163 if d.HasChange("name") { 164 updateOpts.Name = d.Get("name").(string) 165 } 166 if d.HasChange("description") { 167 updateOpts.Description = d.Get("description").(string) 168 } 169 if d.HasChange("admin_state_up") { 170 asu := d.Get("admin_state_up").(bool) 171 updateOpts.AdminStateUp = &asu 172 } 173 174 log.Printf("[DEBUG] Updating OpenStack LBaaSV2 LoadBalancer %s with options: %+v", d.Id(), updateOpts) 175 176 _, err = loadbalancers.Update(networkingClient, d.Id(), updateOpts).Extract() 177 if err != nil { 178 return fmt.Errorf("Error updating OpenStack LBaaSV2 LoadBalancer: %s", err) 179 } 180 181 return resourceLoadBalancerV2Read(d, meta) 182 } 183 184 func resourceLoadBalancerV2Delete(d *schema.ResourceData, meta interface{}) error { 185 config := meta.(*Config) 186 networkingClient, err := config.networkingV2Client(d.Get("region").(string)) 187 if err != nil { 188 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 189 } 190 191 stateConf := &resource.StateChangeConf{ 192 Pending: []string{"ACTIVE", "PENDING_DELETE"}, 193 Target: []string{"DELETED"}, 194 Refresh: waitForLoadBalancerDelete(networkingClient, d.Id()), 195 Timeout: 2 * time.Minute, 196 Delay: 5 * time.Second, 197 MinTimeout: 3 * time.Second, 198 } 199 200 _, err = stateConf.WaitForState() 201 if err != nil { 202 return fmt.Errorf("Error deleting OpenStack LBaaSV2 LoadBalancer: %s", err) 203 } 204 205 d.SetId("") 206 return nil 207 } 208 209 func waitForLoadBalancerActive(networkingClient *gophercloud.ServiceClient, lbID string) resource.StateRefreshFunc { 210 return func() (interface{}, string, error) { 211 lb, err := loadbalancers.Get(networkingClient, lbID).Extract() 212 if err != nil { 213 return nil, "", err 214 } 215 216 log.Printf("[DEBUG] OpenStack LBaaSV2 LoadBalancer: %+v", lb) 217 if lb.ProvisioningStatus == "ACTIVE" { 218 return lb, "ACTIVE", nil 219 } 220 221 return lb, lb.ProvisioningStatus, nil 222 } 223 } 224 225 func waitForLoadBalancerDelete(networkingClient *gophercloud.ServiceClient, lbID string) resource.StateRefreshFunc { 226 return func() (interface{}, string, error) { 227 log.Printf("[DEBUG] Attempting to delete OpenStack LBaaSV2 LoadBalancer %s", lbID) 228 229 lb, err := loadbalancers.Get(networkingClient, lbID).Extract() 230 if err != nil { 231 if _, ok := err.(gophercloud.ErrDefault404); ok { 232 log.Printf("[DEBUG] Successfully deleted OpenStack LBaaSV2 LoadBalancer %s", lbID) 233 return lb, "DELETED", nil 234 } 235 return lb, "ACTIVE", err 236 } 237 238 log.Printf("[DEBUG] Openstack LoadBalancerV2: %+v", lb) 239 err = loadbalancers.Delete(networkingClient, lbID).ExtractErr() 240 if err != nil { 241 if _, ok := err.(gophercloud.ErrDefault404); ok { 242 log.Printf("[DEBUG] Successfully deleted OpenStack LBaaSV2 LoadBalancer %s", lbID) 243 return lb, "DELETED", nil 244 } 245 246 if errCode, ok := err.(gophercloud.ErrUnexpectedResponseCode); ok { 247 if errCode.Actual == 409 { 248 log.Printf("[DEBUG] OpenStack LBaaSV2 LoadBalancer (%s) is still in use.", lbID) 249 return lb, "ACTIVE", nil 250 } 251 } 252 253 return lb, "ACTIVE", err 254 } 255 256 log.Printf("[DEBUG] OpenStack LBaaSV2 LoadBalancer (%s) still active.", lbID) 257 return lb, "ACTIVE", nil 258 } 259 }