func TestAssociateHealthMonitor(t *testing.T) {
	th.SetupHTTP()
	defer th.TeardownHTTP()

	th.Mux.HandleFunc("/v2.0/lb/pools/332abe93-f488-41ba-870b-2ac66be7f853/health_monitors", func(w http.ResponseWriter, r *http.Request) {
		th.TestMethod(t, r, "POST")
		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
		th.TestHeader(t, r, "Content-Type", "application/json")
		th.TestHeader(t, r, "Accept", "application/json")
		th.TestJSONRequest(t, r, `
{
   "health_monitor":{
      "id":"b624decf-d5d3-4c66-9a3d-f047e7786181"
   }
}
			`)

		w.Header().Add("Content-Type", "application/json")
		w.WriteHeader(http.StatusCreated)
		fmt.Fprintf(w, `{}`)
	})

	_, err := pools.AssociateMonitor(fake.ServiceClient(), "332abe93-f488-41ba-870b-2ac66be7f853", "b624decf-d5d3-4c66-9a3d-f047e7786181").Extract()
	th.AssertNoErr(t, err)
}
func TestPoolsMonitors(t *testing.T) {
	client, err := clients.NewNetworkV2Client()
	if err != nil {
		t.Fatalf("Unable to create a network client: %v", err)
	}

	network, err := networking.CreateNetwork(t, client)
	if err != nil {
		t.Fatalf("Unable to create network: %v", err)
	}
	defer networking.DeleteNetwork(t, client, network.ID)

	subnet, err := networking.CreateSubnet(t, client, network.ID)
	if err != nil {
		t.Fatalf("Unable to create subnet: %v", err)
	}
	defer networking.DeleteSubnet(t, client, subnet.ID)

	pool, err := CreatePool(t, client, subnet.ID)
	if err != nil {
		t.Fatalf("Unable to create pool: %v", err)
	}
	defer DeletePool(t, client, pool.ID)

	monitor, err := CreateMonitor(t, client)
	if err != nil {
		t.Fatalf("Unable to create monitor: %v", err)
	}
	defer DeleteMonitor(t, client, monitor.ID)

	t.Logf("Associating monitor %s with pool %s", monitor.ID, pool.ID)
	if res := pools.AssociateMonitor(client, pool.ID, monitor.ID); res.Err != nil {
		t.Fatalf("Unable to associate monitor to pool")
	}

	t.Logf("Disassociating monitor %s with pool %s", monitor.ID, pool.ID)
	if res := pools.DisassociateMonitor(client, pool.ID, monitor.ID); res.Err != nil {
		t.Fatalf("Unable to disassociate monitor from pool")
	}

}
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 resourceLBPoolV1Create(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)
	}

	createOpts := pools.CreateOpts{
		Name:     d.Get("name").(string),
		SubnetID: d.Get("subnet_id").(string),
		TenantID: d.Get("tenant_id").(string),
		Provider: d.Get("lb_provider").(string),
	}

	if v, ok := d.GetOk("protocol"); ok {
		protocol := resourceLBPoolV1DetermineProtocol(v.(string))
		createOpts.Protocol = protocol
	}

	if v, ok := d.GetOk("lb_method"); ok {
		lbMethod := resourceLBPoolV1DetermineLBMethod(v.(string))
		createOpts.LBMethod = lbMethod
	}

	log.Printf("[DEBUG] Create Options: %#v", createOpts)
	p, err := pools.Create(networkingClient, createOpts).Extract()
	if err != nil {
		return fmt.Errorf("Error creating OpenStack LB pool: %s", err)
	}
	log.Printf("[INFO] LB Pool ID: %s", p.ID)

	log.Printf("[DEBUG] Waiting for OpenStack LB pool (%s) to become available.", p.ID)

	stateConf := &resource.StateChangeConf{
		Pending:    []string{"PENDING_CREATE"},
		Target:     []string{"ACTIVE"},
		Refresh:    waitForLBPoolActive(networkingClient, p.ID),
		Timeout:    2 * time.Minute,
		Delay:      5 * time.Second,
		MinTimeout: 3 * time.Second,
	}

	_, err = stateConf.WaitForState()
	if err != nil {
		return err
	}

	d.SetId(p.ID)

	if mIDs := resourcePoolMonitorIDsV1(d); mIDs != nil {
		for _, mID := range mIDs {
			_, err := pools.AssociateMonitor(networkingClient, p.ID, mID).Extract()
			if err != nil {
				return fmt.Errorf("Error associating monitor (%s) with OpenStack LB pool (%s): %s", mID, p.ID, err)
			}
		}
	}

	if memberOpts := resourcePoolMembersV1(d); memberOpts != nil {
		for _, memberOpt := range memberOpts {
			_, err := members.Create(networkingClient, memberOpt).Extract()
			if err != nil {
				return fmt.Errorf("Error creating OpenStack LB member: %s", err)
			}
		}
	}

	return resourceLBPoolV1Read(d, meta)
}
Exemple #5
0
// Create load balancer
func (os *OpenStack) CreateLoadBalancer(loadBalancer *provider.LoadBalancer, affinity string) (string, error) {
	if len(loadBalancer.ExternalIPs) > 1 {
		return "", fmt.Errorf("multiple floatingips are not yet supported by openstack")
	}

	servicePort := 0
	for _, p := range loadBalancer.Hosts {
		if servicePort == 0 {
			servicePort = int(p.ServicePort)
		} else if int(p.ServicePort) != servicePort {
			return "", fmt.Errorf("multiple ports are not yet supported in openstack load balancers")
		}
	}

	var persistence *vips.SessionPersistence
	switch affinity {
	case ServiceAffinityNone:
		persistence = nil
	case ServiceAffinityClientIP:
		persistence = &vips.SessionPersistence{Type: "SOURCE_IP"}
	default:
		return "", fmt.Errorf("unsupported load balancer affinity: %v", affinity)
	}

	glog.V(2).Info("Checking if openstack load balancer already exists: ", loadBalancer.Name)
	_, err := os.getPoolByName(loadBalancer.Name)
	if err != nil && err != ErrNotFound {
		return "", fmt.Errorf("error checking if openstack load balancer already exists: %v", err)
	}

	if err == nil {
		err := os.DeleteLoadBalancer(loadBalancer.Name)
		if err != nil {
			return "", fmt.Errorf("error deleting existing openstack load balancer: %v", err)
		}
	}

	lbmethod := pools.LBMethodRoundRobin
	if os.lbOpts.LBMethod != "" {
		lbmethod = pools.LBMethod(os.lbOpts.LBMethod)
	}
	pool, err := pools.Create(os.network, pools.CreateOpts{
		Name:     loadBalancer.Name,
		Protocol: pools.ProtocolTCP,
		SubnetID: loadBalancer.Subnets[0].Uid,
		LBMethod: lbmethod,
		TenantID: loadBalancer.TenantID,
	}).Extract()
	if err != nil {
		return "", err
	}

	for _, host := range loadBalancer.Hosts {
		_, err = members.Create(os.network, members.CreateOpts{
			PoolID:       pool.ID,
			ProtocolPort: int(host.TargetPort),
			Address:      host.Ipaddress,
			TenantID:     loadBalancer.TenantID,
		}).Extract()
		if err != nil {
			pools.Delete(os.network, pool.ID)
			return "", err
		}
	}

	var mon *monitors.Monitor
	if os.lbOpts.CreateMonitor {
		mon, err = monitors.Create(os.network, monitors.CreateOpts{
			Type:       monitors.TypeTCP,
			TenantID:   loadBalancer.TenantID,
			Delay:      int(os.lbOpts.MonitorDelay.Duration.Seconds()),
			Timeout:    int(os.lbOpts.MonitorTimeout.Duration.Seconds()),
			MaxRetries: int(os.lbOpts.MonitorMaxRetries),
		}).Extract()
		if err != nil {
			pools.Delete(os.network, pool.ID)
			return "", err
		}

		_, err = pools.AssociateMonitor(os.network, pool.ID, mon.ID).Extract()
		if err != nil {
			monitors.Delete(os.network, mon.ID)
			pools.Delete(os.network, pool.ID)
			return "", err
		}
	}

	createOpts := vips.CreateOpts{
		Name:         loadBalancer.Name,
		Description:  fmt.Sprintf("Kubernetes service %s", loadBalancer.Name),
		Protocol:     "TCP",
		ProtocolPort: servicePort,
		PoolID:       pool.ID,
		SubnetID:     loadBalancer.Subnets[0].Uid,
		Persistence:  persistence,
		TenantID:     loadBalancer.TenantID,
	}
	//if loadBalancer.Vip != "" {
	//	createOpts.Address = loadBalancer.Vip
	//}

	vip, err := vips.Create(os.network, createOpts).Extract()
	if err != nil {
		if mon != nil {
			monitors.Delete(os.network, mon.ID)
		}
		pools.Delete(os.network, pool.ID)
		return "", err
	}

	// bind external ip
	if len(loadBalancer.ExternalIPs) > 0 {
		err := os.BindPortToFloatingip(vip.PortID, loadBalancer.ExternalIPs[0], vip.TenantID)
		if err != nil {
			vips.Delete(os.network, vip.ID)
			if mon != nil {
				monitors.Delete(os.network, mon.ID)
			}
			pools.Delete(os.network, pool.ID)
			return "", err
		}
	}

	return vip.Address, nil
}