// Get load balancer by name func (os *OpenStack) GetLoadBalancer(name string) (*provider.LoadBalancer, error) { pool, err := os.getPoolByName(name) if err != nil { return nil, err } vip, err := os.getVipByID(pool.VIPID) if err != nil { return nil, err } var lb provider.LoadBalancer lb.Uid = pool.ID lb.Name = pool.Name lb.Status = pool.Status lb.LoadBalanceType = "TCP" lb.Vip = vip.Address lb.Subnets = []*provider.Subnet{{Uid: vip.SubnetID}} lb.Hosts = make([]*provider.HostPort, 0, 1) pager := members.List(os.network, members.ListOpts{PoolID: pool.ID}) err = pager.EachPage(func(page pagination.Page) (bool, error) { memList, err := members.ExtractMembers(page) if err != nil { return false, err } for _, member := range memList { host := provider.HostPort{ Ipaddress: member.Address, TargetPort: int32(member.ProtocolPort), ServicePort: int32(vip.ProtocolPort), } lb.Hosts = append(lb.Hosts, &host) } return true, nil }) if err != nil { return nil, err } return &lb, nil }
func TestMembersList(t *testing.T) { client, err := clients.NewNetworkV2Client() if err != nil { t.Fatalf("Unable to create a network client: %v", err) } allPages, err := members.List(client, members.ListOpts{}).AllPages() if err != nil { t.Fatalf("Unable to list members: %v", err) } allMembers, err := members.ExtractMembers(allPages) if err != nil { t.Fatalf("Unable to extract members: %v", err) } for _, member := range allMembers { PrintMember(t, &member) } }
func resourceLBPoolV1Update(d *schema.ResourceData, meta interface{}) error { config := meta.(*Config) networkingClient, err := config.networkingV2Client(d.Get("region").(string)) if err != nil { return fmt.Errorf("Error creating OpenStack networking client: %s", err) } var updateOpts pools.UpdateOpts // If either option changed, update both. // Gophercloud complains if one is empty. if d.HasChange("name") || d.HasChange("lb_method") { updateOpts.Name = d.Get("name").(string) lbMethod := resourceLBPoolV1DetermineLBMethod(d.Get("lb_method").(string)) updateOpts.LBMethod = lbMethod } log.Printf("[DEBUG] Updating OpenStack LB Pool %s with options: %+v", d.Id(), updateOpts) _, err = pools.Update(networkingClient, d.Id(), updateOpts).Extract() if err != nil { return fmt.Errorf("Error updating OpenStack LB Pool: %s", err) } if d.HasChange("monitor_ids") { oldMIDsRaw, newMIDsRaw := d.GetChange("security_groups") oldMIDsSet, newMIDsSet := oldMIDsRaw.(*schema.Set), newMIDsRaw.(*schema.Set) monitorsToAdd := newMIDsSet.Difference(oldMIDsSet) monitorsToRemove := oldMIDsSet.Difference(newMIDsSet) log.Printf("[DEBUG] Monitors to add: %v", monitorsToAdd) log.Printf("[DEBUG] Monitors to remove: %v", monitorsToRemove) for _, m := range monitorsToAdd.List() { _, err := pools.AssociateMonitor(networkingClient, d.Id(), m.(string)).Extract() if err != nil { return fmt.Errorf("Error associating monitor (%s) with OpenStack server (%s): %s", m.(string), d.Id(), err) } log.Printf("[DEBUG] Associated monitor (%s) with pool (%s)", m.(string), d.Id()) } for _, m := range monitorsToRemove.List() { _, err := pools.DisassociateMonitor(networkingClient, d.Id(), m.(string)).Extract() if err != nil { return fmt.Errorf("Error disassociating monitor (%s) from OpenStack server (%s): %s", m.(string), d.Id(), err) } log.Printf("[DEBUG] Disassociated monitor (%s) from pool (%s)", m.(string), d.Id()) } } if d.HasChange("member") { oldMembersRaw, newMembersRaw := d.GetChange("member") oldMembersSet, newMembersSet := oldMembersRaw.(*schema.Set), newMembersRaw.(*schema.Set) membersToAdd := newMembersSet.Difference(oldMembersSet) membersToRemove := oldMembersSet.Difference(newMembersSet) log.Printf("[DEBUG] Members to add: %v", membersToAdd) log.Printf("[DEBUG] Members to remove: %v", membersToRemove) for _, m := range membersToRemove.List() { oldMember := resourcePoolMemberV1(d, m) listOpts := members.ListOpts{ PoolID: d.Id(), Address: oldMember.Address, ProtocolPort: oldMember.ProtocolPort, } err = members.List(networkingClient, listOpts).EachPage(func(page pagination.Page) (bool, error) { extractedMembers, err := members.ExtractMembers(page) if err != nil { return false, err } for _, member := range extractedMembers { err := members.Delete(networkingClient, member.ID).ExtractErr() if err != nil { return false, fmt.Errorf("Error deleting member (%s) from OpenStack LB pool (%s): %s", member.ID, d.Id(), err) } log.Printf("[DEBUG] Deleted member (%s) from pool (%s)", member.ID, d.Id()) } return true, nil }) } for _, m := range membersToAdd.List() { createOpts := resourcePoolMemberV1(d, m) newMember, err := members.Create(networkingClient, createOpts).Extract() if err != nil { return fmt.Errorf("Error creating LB member: %s", err) } log.Printf("[DEBUG] Created member (%s) in OpenStack LB pool (%s)", newMember.ID, d.Id()) } } return resourceLBPoolV1Read(d, meta) }
func TestList(t *testing.T) { th.SetupHTTP() defer th.TeardownHTTP() th.Mux.HandleFunc("/v2.0/lb/members", func(w http.ResponseWriter, r *http.Request) { th.TestMethod(t, r, "GET") th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) w.Header().Add("Content-Type", "application/json") w.WriteHeader(http.StatusOK) fmt.Fprintf(w, ` { "members":[ { "status":"ACTIVE", "weight":1, "admin_state_up":true, "tenant_id":"83657cfcdfe44cd5920adaf26c48ceea", "pool_id":"72741b06-df4d-4715-b142-276b6bce75ab", "address":"10.0.0.4", "protocol_port":80, "id":"701b531b-111a-4f21-ad85-4795b7b12af6" }, { "status":"ACTIVE", "weight":1, "admin_state_up":true, "tenant_id":"83657cfcdfe44cd5920adaf26c48ceea", "pool_id":"72741b06-df4d-4715-b142-276b6bce75ab", "address":"10.0.0.3", "protocol_port":80, "id":"beb53b4d-230b-4abd-8118-575b8fa006ef" } ] } `) }) count := 0 members.List(fake.ServiceClient(), members.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) { count++ actual, err := members.ExtractMembers(page) if err != nil { t.Errorf("Failed to extract members: %v", err) return false, err } expected := []members.Member{ { Status: "ACTIVE", Weight: 1, AdminStateUp: true, TenantID: "83657cfcdfe44cd5920adaf26c48ceea", PoolID: "72741b06-df4d-4715-b142-276b6bce75ab", Address: "10.0.0.4", ProtocolPort: 80, ID: "701b531b-111a-4f21-ad85-4795b7b12af6", }, { Status: "ACTIVE", Weight: 1, AdminStateUp: true, TenantID: "83657cfcdfe44cd5920adaf26c48ceea", PoolID: "72741b06-df4d-4715-b142-276b6bce75ab", Address: "10.0.0.3", ProtocolPort: 80, ID: "beb53b4d-230b-4abd-8118-575b8fa006ef", }, } th.CheckDeepEquals(t, expected, actual) return true, nil }) if count != 1 { t.Errorf("Expected 1 page, got %d", count) } }
// Update load balancer func (os *OpenStack) UpdateLoadBalancer(name string, hosts []*provider.HostPort, externalIPs []string) (string, error) { if len(externalIPs) > 1 { return "", fmt.Errorf("multiple floatingips are not yet supported by openstack") } vip, err := os.getVipByName(name) if err != nil { return "", err } lb, err := os.GetLoadBalancer(name) if err != nil { return "", err } // Set of member (addresses) that _should_ exist addrs := make(map[string]*provider.HostPort) for _, host := range hosts { addrs[host.Ipaddress] = host } // Iterate over members that _do_ exist pager := members.List(os.network, members.ListOpts{PoolID: vip.PoolID}) err = pager.EachPage(func(page pagination.Page) (bool, error) { memList, err := members.ExtractMembers(page) if err != nil { return false, err } for _, member := range memList { if _, found := addrs[member.Address]; found { // Member already exists delete(addrs, member.Address) } else { // Member needs to be deleted err = members.Delete(os.network, member.ID).ExtractErr() if err != nil { return false, err } } } return true, nil }) if err != nil { return "", err } // Anything left in addrs is a new member that needs to be added for _, addr := range addrs { _, err := members.Create(os.network, members.CreateOpts{ TenantID: lb.TenantID, PoolID: vip.PoolID, Address: addr.Ipaddress, ProtocolPort: int(addr.TargetPort), }).Extract() if err != nil { return "", err } } // bind to external ip if len(externalIPs) > 0 { err := os.BindPortToFloatingip(vip.PortID, externalIPs[0], vip.TenantID) if err != nil { return "", err } } return lb.Vip, nil }