func resourceLBVipV1Create(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)
	networkingClient, err := config.networkingV2Client(GetRegion(d))
	if err != nil {
		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
	}

	createOpts := vips.CreateOpts{
		Name:         d.Get("name").(string),
		SubnetID:     d.Get("subnet_id").(string),
		Protocol:     d.Get("protocol").(string),
		ProtocolPort: d.Get("port").(int),
		PoolID:       d.Get("pool_id").(string),
		TenantID:     d.Get("tenant_id").(string),
		Address:      d.Get("address").(string),
		Description:  d.Get("description").(string),
		Persistence:  resourceVipPersistenceV1(d),
		ConnLimit:    gophercloud.MaybeInt(d.Get("conn_limit").(int)),
	}

	asu := d.Get("admin_state_up").(bool)
	createOpts.AdminStateUp = &asu

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

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

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

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

	floatingIP := d.Get("floating_ip").(string)
	if floatingIP != "" {
		lbVipV1AssignFloatingIP(floatingIP, p.PortID, networkingClient)
	}

	d.SetId(p.ID)

	return resourceLBVipV1Read(d, meta)
}
Example #2
0
func TestRequiredCreateOpts(t *testing.T) {
	res := vips.Create(fake.ServiceClient(), vips.CreateOpts{})
	if res.Err == nil {
		t.Fatalf("Expected error, got none")
	}
	res = vips.Create(fake.ServiceClient(), vips.CreateOpts{Name: "foo"})
	if res.Err == nil {
		t.Fatalf("Expected error, got none")
	}
	res = vips.Create(fake.ServiceClient(), vips.CreateOpts{Name: "foo", SubnetID: "bar"})
	if res.Err == nil {
		t.Fatalf("Expected error, got none")
	}
	res = vips.Create(fake.ServiceClient(), vips.CreateOpts{Name: "foo", SubnetID: "bar", Protocol: "bar"})
	if res.Err == nil {
		t.Fatalf("Expected error, got none")
	}
	res = vips.Create(fake.ServiceClient(), vips.CreateOpts{Name: "foo", SubnetID: "bar", Protocol: "bar", ProtocolPort: 80})
	if res.Err == nil {
		t.Fatalf("Expected error, got none")
	}
}
Example #3
0
// CreateVIP will create a vip with a random name and a random port in a
// specified subnet and pool. An error will be returned if the vip could
// not be created.
func CreateVIP(t *testing.T, client *gophercloud.ServiceClient, subnetID, poolID string) (*vips.VirtualIP, error) {
	vipName := tools.RandomString("TESTACCT-", 8)
	vipPort := tools.RandomInt(100, 10000)

	t.Logf("Attempting to create VIP %s", vipName)

	createOpts := vips.CreateOpts{
		Name:         vipName,
		SubnetID:     subnetID,
		PoolID:       poolID,
		Protocol:     "TCP",
		ProtocolPort: vipPort,
	}

	vip, err := vips.Create(client, createOpts).Extract()
	if err != nil {
		return vip, err
	}

	t.Logf("Successfully created vip %s", vipName)

	return vip, nil
}
Example #4
0
func TestCreate(t *testing.T) {
	th.SetupHTTP()
	defer th.TeardownHTTP()

	th.Mux.HandleFunc("/v2.0/lb/vips", 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, `
{
    "vip": {
        "protocol": "HTTP",
        "name": "NewVip",
        "admin_state_up": true,
        "subnet_id": "8032909d-47a1-4715-90af-5153ffe39861",
        "pool_id": "61b1f87a-7a21-4ad3-9dda-7f81d249944f",
        "protocol_port": 80,
				"session_persistence": {"type": "SOURCE_IP"}
    }
}
			`)

		w.Header().Add("Content-Type", "application/json")
		w.WriteHeader(http.StatusCreated)

		fmt.Fprintf(w, `
{
    "vip": {
        "status": "PENDING_CREATE",
        "protocol": "HTTP",
        "description": "",
        "admin_state_up": true,
        "subnet_id": "8032909d-47a1-4715-90af-5153ffe39861",
        "tenant_id": "83657cfcdfe44cd5920adaf26c48ceea",
        "connection_limit": -1,
        "pool_id": "61b1f87a-7a21-4ad3-9dda-7f81d249944f",
        "address": "10.0.0.11",
        "protocol_port": 80,
        "port_id": "f7e6fe6a-b8b5-43a8-8215-73456b32e0f5",
        "id": "c987d2be-9a3c-4ac9-a046-e8716b1350e2",
        "name": "NewVip"
    }
}
		`)
	})

	opts := vips.CreateOpts{
		Protocol:     "HTTP",
		Name:         "NewVip",
		AdminStateUp: gophercloud.Enabled,
		SubnetID:     "8032909d-47a1-4715-90af-5153ffe39861",
		PoolID:       "61b1f87a-7a21-4ad3-9dda-7f81d249944f",
		ProtocolPort: 80,
		Persistence:  &vips.SessionPersistence{Type: "SOURCE_IP"},
	}

	r, err := vips.Create(fake.ServiceClient(), opts).Extract()
	th.AssertNoErr(t, err)

	th.AssertEquals(t, "PENDING_CREATE", r.Status)
	th.AssertEquals(t, "HTTP", r.Protocol)
	th.AssertEquals(t, "", r.Description)
	th.AssertEquals(t, true, r.AdminStateUp)
	th.AssertEquals(t, "8032909d-47a1-4715-90af-5153ffe39861", r.SubnetID)
	th.AssertEquals(t, "83657cfcdfe44cd5920adaf26c48ceea", r.TenantID)
	th.AssertEquals(t, -1, r.ConnLimit)
	th.AssertEquals(t, "61b1f87a-7a21-4ad3-9dda-7f81d249944f", r.PoolID)
	th.AssertEquals(t, "10.0.0.11", r.Address)
	th.AssertEquals(t, 80, r.ProtocolPort)
	th.AssertEquals(t, "f7e6fe6a-b8b5-43a8-8215-73456b32e0f5", r.PortID)
	th.AssertEquals(t, "c987d2be-9a3c-4ac9-a046-e8716b1350e2", r.ID)
	th.AssertEquals(t, "NewVip", r.Name)
}
Example #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
}