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) }
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") } }
// 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 }
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) }
// 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 }