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
}
Get load balancer by name
package common
import (
	"errors"
	"fmt"
	"io"
	"net"
	"os"
	"strings"
	"time"
	"code.google.com/p/gcfg"
	"github.com/docker/distribution/uuid"
	"github.com/golang/glog"
	"github.com/gophercloud/gophercloud"
	"github.com/gophercloud/gophercloud/openstack"
	"github.com/gophercloud/gophercloud/openstack/identity/v2/tenants"
	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips"
	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers"
	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/members"
	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/monitors"
	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/pools"
	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/vips"
	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/portsbinding"
	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups"
	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules"
	"github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
	"github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
	"github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
	"github.com/gophercloud/gophercloud/pagination"
	"github.com/hyperhq/kubestack/pkg/plugins"
	provider "github.com/hyperhq/kubestack/pkg/types"
	_ "github.com/hyperhq/kubestack/pkg/plugins/openvswitch"
)
const (
	podNamePrefix     = "kube"
	securitygroupName = "kube-securitygroup-default"
	hostnameMaxLen    = 63
	ServiceAffinityNone     = "None"
	ServiceAffinityClientIP = "ClientIP"
)
var (
	adminStateUp = true
	ErrNotFound        = errors.New("NotFound")
	ErrMultipleResults = errors.New("MultipleResults")
)
type MyDuration struct {
	time.Duration
}
func (d *MyDuration) UnmarshalText(text []byte) error {
	res, err := time.ParseDuration(string(text))
	if err != nil {
		return err
	}
	d.Duration = res
	return nil
}
type LoadBalancerOpts struct {
	LBMethod          string     `gcfg:"lb-method"`
	CreateMonitor     bool       `gcfg:"create-monitor"`
	MonitorDelay      MyDuration `gcfg:"monitor-delay"`
	MonitorTimeout    MyDuration `gcfg:"monitor-timeout"`
	MonitorMaxRetries uint       `gcfg:"monitor-max-retries"`
}
type PluginOpts struct {
	PluginName        string `gcfg:"plugin-name"`
	IntegrationBridge string `gcfg:"integration-bridge"`
}
type OpenStack struct {
	network    *gophercloud.ServiceClient
	identity   *gophercloud.ServiceClient
	provider   *gophercloud.ProviderClient
	region     string
	lbOpts     LoadBalancerOpts
	pluginOpts PluginOpts
	ExtNetID   string
	Plugin     plugins.PluginInterface
}
type Config struct {
	Global struct {
		AuthUrl         string `gcfg:"auth-url"`
		Username        string `gcfg:"username"`
		UserId          string `gcfg:"user-id"`
		Password        string `gcfg: "password"`
		TokenID         string `gcfg:"token-id"`
		TenantId        string `gcfg:"tenant-id"`
		TenantName      string `gcfg:"tenant-name"`
		DomainId        string `gcfg:"domain-id"`
		DomainName      string `gcfg:"domain-name"`
		Region          string `gcfg:"region"`
		ExtNetID        string `gcfg:"ext-net-id"`
		KeystoneVersion string `gcfg:"keystone-version"`
	}
	LoadBalancer LoadBalancerOpts
	Plugin       PluginOpts
}
func (cfg Config) toAuthOptions() gophercloud.AuthOptions {
	return gophercloud.AuthOptions{
		IdentityEndpoint: cfg.Global.AuthUrl,
		Username:         cfg.Global.Username,
		UserID:           cfg.Global.UserId,
		Password:         cfg.Global.Password,
		TokenID:          cfg.Global.TokenID,
		TenantID:         cfg.Global.TenantId,
		TenantName:       cfg.Global.TenantName,
		DomainName:       cfg.Global.DomainName,
		AllowReauth: true,
	}
}
func NewOpenStack(config io.Reader) (*OpenStack, error) {
	var cfg Config
	err := gcfg.ReadInto(&cfg, config)
	if err != nil {
		glog.Warning("Failed to parse openstack configure file: %v", err)
		return nil, err
	}
	provider, err := openstack.AuthenticatedClient(cfg.toAuthOptions())
	if err != nil {
		glog.Warning("Failed to auth openstack: %v", err)
		return nil, err
	}
	var identity *gophercloud.ServiceClient
	if cfg.Global.KeystoneVersion == "3" {
		identity, err = openstack.NewIdentityV3(provider, gophercloud.EndpointOpts{
			Availability: gophercloud.AvailabilityAdmin,
		})
	} else {
		identity, err = openstack.NewIdentityV2(provider, gophercloud.EndpointOpts{
			Availability: gophercloud.AvailabilityAdmin,
		})
	}
	if err != nil {
		glog.Warning("Failed to find identity endpoint")
		return nil, err
	}
	network, err := openstack.NewNetworkV2(provider, gophercloud.EndpointOpts{
		Region: cfg.Global.Region,
	})
	if err != nil {
		glog.Warning("Failed to find neutron endpoint: %v", err)
		return nil, err
	}
	os := OpenStack{
		identity:   identity,
		network:    network,
		provider:   provider,
		region:     cfg.Global.Region,
		lbOpts:     cfg.LoadBalancer,
		pluginOpts: cfg.Plugin,
		ExtNetID:   cfg.Global.ExtNetID,
	}
	if cfg.Plugin.PluginName != "" {
		integrationBriage := "br-int"
		if cfg.Plugin.IntegrationBridge != "" {
			integrationBriage = cfg.Plugin.IntegrationBridge
		}
		plugin, _ := plugins.GetNetworkPlugin(cfg.Plugin.PluginName)
		if plugin != nil {
			plugin.Init(integrationBriage)
			os.Plugin = plugin
		}
	}
	return &os, nil
}
func getHostName() string {
	host, err := os.Hostname()
	if err != nil {
		return ""
	}
	return host
}
func (os *OpenStack) getOpenStackNetworkByID(id string) (*networks.Network, error) {
	opts := networks.ListOpts{ID: id}
	return os.getOpenStackNetwork(&opts)
}
func (os *OpenStack) getOpenStackNetworkByName(name string) (*networks.Network, error) {
	opts := networks.ListOpts{Name: name}
	return os.getOpenStackNetwork(&opts)
}
func (os *OpenStack) getOpenStackNetwork(opts *networks.ListOpts) (*networks.Network, error) {
	var osNetwork *networks.Network
	pager := networks.List(os.network, *opts)
	err := pager.EachPage(func(page pagination.Page) (bool, error) {
		networkList, e := networks.ExtractNetworks(page)
		if len(networkList) > 1 {
			return false, ErrMultipleResults
		}
		if len(networkList) == 1 {
			osNetwork = &networkList[0]
		}
		return true, e
	})
	if err == nil && osNetwork == nil {
		return nil, ErrNotFound
	}
	return osNetwork, err
}
func (os *OpenStack) getProviderSubnet(osSubnetID string) (*provider.Subnet, error) {
	s, err := subnets.Get(os.network, osSubnetID).Extract()
	if err != nil {
		glog.Errorf("Get openstack subnet failed: %v", err)
		return nil, err
	}
	var routes []*provider.Route
	for _, r := range s.HostRoutes {
		route := provider.Route{
			Nexthop:         r.NextHop,
			DestinationCIDR: r.DestinationCIDR,
		}
		routes = append(routes, &route)
	}
	providerSubnet := provider.Subnet{
		Uid:        s.ID,
		Cidr:       s.CIDR,
		Gateway:    s.GatewayIP,
		Name:       s.Name,
		Dnsservers: s.DNSNameservers,
		Routes:     routes,
	}
	return &providerSubnet, nil
}
func (os *OpenStack) GetNetworkByID(networkID string) (*provider.Network, error) {
	osNetwork, err := os.getOpenStackNetworkByID(networkID)
	if err != nil {
		glog.Errorf("Get openstack network failed: %v", err)
		return nil, err
	}
	return os.OSNetworktoProviderNetwork(osNetwork)
}
func (os *OpenStack) GetNetwork(networkName string) (*provider.Network, error) {
	osNetwork, err := os.getOpenStackNetworkByName(networkName)
	if err != nil {
		glog.Errorf("Get openstack network failed: %v", err)
		return nil, err
	}
	return os.OSNetworktoProviderNetwork(osNetwork)
}
func (os *OpenStack) OSNetworktoProviderNetwork(osNetwork *networks.Network) (*provider.Network, error) {
	var providerNetwork provider.Network
	var providerSubnets []*provider.Subnet
	providerNetwork.Name = osNetwork.Name
	providerNetwork.Uid = osNetwork.ID
	providerNetwork.Status = os.ToProviderStatus(osNetwork.Status)
	providerNetwork.TenantID = osNetwork.TenantID
	for _, subnetID := range osNetwork.Subnets {
		s, err := os.getProviderSubnet(subnetID)
		if err != nil {
			return nil, err
		}
		providerSubnets = append(providerSubnets, s)
	}
	providerNetwork.Subnets = providerSubnets
	return &providerNetwork, nil
}
func (os *OpenStack) ToProviderStatus(status string) string {
	switch status {
	case "ACTIVE":
		return "Active"
	case "BUILD":
		return "Pending"
	case "DOWN", "ERROR":
		return "Failed"
	default:
		return "Failed"
	}
	return "Failed"
}
func (os *OpenStack) CreateNetwork(network *provider.Network) error {
	if len(network.Subnets) == 0 {
		return errors.New("Subnets is null")
	}
	opts := networks.CreateOpts{
		Name:         network.Name,
		AdminStateUp: &adminStateUp,
		TenantID:     network.TenantID,
	}
	osNet, err := networks.Create(os.network, opts).Extract()
	if err != nil {
		glog.Errorf("Create openstack network %s failed: %v", network.Name, err)
		return err
	}
	routerOpts := routers.CreateOpts{
		Name:        network.Name,
		TenantID:    network.TenantID,
		GatewayInfo: &routers.GatewayInfo{NetworkID: os.ExtNetID},
	}
	osRouter, err := routers.Create(os.network, routerOpts).Extract()
	if err != nil {
		glog.Errorf("Create openstack router %s failed: %v", network.Name, err)
		delErr := os.DeleteNetwork(network.Name)
		if delErr != nil {
			glog.Errorf("Delete openstack network %s failed: %v", network.Name, delErr)
		}
		return err
	}
	networkID := osNet.ID
	network.Status = os.ToProviderStatus(osNet.Status)
	network.Uid = osNet.ID
	for _, sub := range network.Subnets {
		subnetOpts := subnets.CreateOpts{
			NetworkID:      networkID,
			CIDR:           sub.Cidr,
			Name:           sub.Name,
			IPVersion:      gophercloud.IPv4,
			TenantID:       network.TenantID,
			GatewayIP:      &sub.Gateway,
			DNSNameservers: sub.Dnsservers,
		}
		s, err := subnets.Create(os.network, subnetOpts).Extract()
		if err != nil {
			glog.Errorf("Create openstack subnet %s failed: %v", sub.Name, err)
			delErr := os.DeleteNetwork(network.Name)
			if delErr != nil {
				glog.Errorf("Delete openstack network %s failed: %v", network.Name, delErr)
			}
			return err
		}
		opts := routers.AddInterfaceOpts{
			SubnetID: s.ID,
		}
		_, err = routers.AddInterface(os.network, osRouter.ID, opts).Extract()
		if err != nil {
			glog.Errorf("Create openstack subnet %s failed: %v", sub.Name, err)
			delErr := os.DeleteNetwork(network.Name)
			if delErr != nil {
				glog.Errorf("Delete openstack network %s failed: %v", network.Name, delErr)
			}
			return err
		}
	}
	return nil
}
func (os *OpenStack) UpdateNetwork(network *provider.Network) error {
	return nil
}
func (os *OpenStack) getRouterByName(name string) (*routers.Router, error) {
	var result *routers.Router
	opts := routers.ListOpts{Name: name}
	pager := routers.List(os.network, opts)
	err := pager.EachPage(func(page pagination.Page) (bool, error) {
		routerList, e := routers.ExtractRouters(page)
		if len(routerList) > 1 {
			return false, ErrMultipleResults
		} else if len(routerList) == 1 {
			result = &routerList[0]
		}
		return true, e
	})
	if err != nil {
		return nil, err
	}
	return result, nil
}
func (os *OpenStack) DeleteNetwork(networkName string) error {
	osNetwork, err := os.getOpenStackNetworkByName(networkName)
	if err != nil {
		glog.Errorf("Get openstack network failed: %v", err)
		return err
	}
	if osNetwork != nil {
		opts := ports.ListOpts{NetworkID: osNetwork.ID}
		pager := ports.List(os.network, opts)
		err := pager.EachPage(func(page pagination.Page) (bool, error) {
			portList, err := ports.ExtractPorts(page)
			if err != nil {
				glog.Errorf("Get openstack ports error: %v", err)
				return false, err
			}
			for _, port := range portList {
				if port.DeviceOwner == "network:router_interface" {
					continue
				}
				err = ports.Delete(os.network, port.ID).ExtractErr()
				if err != nil {
					glog.Warningf("Delete port %v failed: %v", port.ID, err)
				}
			}
			return true, nil
		})
		if err != nil {
			glog.Errorf("Delete ports error: %v", err)
		}
		router, err := os.getRouterByName(networkName)
		if err != nil {
			glog.Errorf("Get openstack router %s error: %v", networkName, err)
			return err
		}
		for _, subnet := range osNetwork.Subnets {
			if router != nil {
				opts := routers.RemoveInterfaceOpts{SubnetID: subnet}
				_, err := routers.RemoveInterface(os.network, router.ID, opts).Extract()
				if err != nil {
					glog.Errorf("Get openstack router %s error: %v", networkName, err)
					return err
				}
			}
			err = subnets.Delete(os.network, subnet).ExtractErr()
			if err != nil {
				glog.Errorf("Delete openstack subnet %s error: %v", subnet, err)
				return err
			}
		}
		if router != nil {
			err = routers.Delete(os.network, router.ID).ExtractErr()
			if err != nil {
				glog.Errorf("Delete openstack router %s error: %v", router.ID, err)
				return err
			}
		}
		err = networks.Delete(os.network, osNetwork.ID).ExtractErr()
		if err != nil {
			glog.Errorf("Delete openstack network %s error: %v", osNetwork.ID, err)
			return err
		}
	}
	return nil
}
func (os *OpenStack) ListPorts(networkID, deviceOwner string) ([]ports.Port, error) {
	var results []ports.Port
	opts := ports.ListOpts{
		NetworkID:   networkID,
		DeviceOwner: deviceOwner,
	}
	pager := ports.List(os.network, opts)
	err := pager.EachPage(func(page pagination.Page) (bool, error) {
		portList, err := ports.ExtractPorts(page)
		if err != nil {
			glog.Errorf("Get openstack ports error: %v", err)
			return false, err
		}
		for _, port := range portList {
			results = append(results, port)
		}
		return true, err
	})
	if err != nil {
		return nil, err
	}
	return results, nil
}
func (os *OpenStack) ensureSecurityGroup(tenantID string) (string, error) {
	var securitygroup *groups.SecGroup
	opts := groups.ListOpts{
		TenantID: tenantID,
		Name:     securitygroupName,
	}
	pager := groups.List(os.network, opts)
	err := pager.EachPage(func(page pagination.Page) (bool, error) {
		sg, err := groups.ExtractGroups(page)
		if err != nil {
			glog.Errorf("Get openstack securitygroups error: %v", err)
			return false, err
		}
		if len(sg) > 0 {
			securitygroup = &sg[0]
		}
		return true, err
	})
	if err != nil {
		return "", err
	}
	if securitygroup == nil {
		securitygroup, err = groups.Create(os.network, groups.CreateOpts{
			Name:     securitygroupName,
			TenantID: tenantID,
		}).Extract()
		if err != nil {
			return "", err
		}
	}
	var secGroupsRules int
	listopts := rules.ListOpts{
		TenantID:   tenantID,
		Direction:  string(rules.DirIngress),
		SecGroupID: securitygroup.ID,
	}
	rulesPager := rules.List(os.network, listopts)
	err = rulesPager.EachPage(func(page pagination.Page) (bool, error) {
		r, err := rules.ExtractRules(page)
		if err != nil {
			glog.Errorf("Get openstack securitygroup rules error: %v", err)
			return false, err
		}
		secGroupsRules = len(r)
		return true, err
	})
	if err != nil {
		return "", err
	}
	if secGroupsRules == 0 {
		_, err = rules.Create(os.network, rules.CreateOpts{
			TenantID:   tenantID,
			SecGroupID: securitygroup.ID,
			Direction:  rules.DirEgress,
			EtherType:  rules.EtherType4,
		}).Extract()
		_, err := rules.Create(os.network, rules.CreateOpts{
			TenantID:   tenantID,
			SecGroupID: securitygroup.ID,
			Direction:  rules.DirIngress,
			EtherType:  rules.EtherType4,
		}).Extract()
		if err != nil {
			return "", err
		}
	}
	return securitygroup.ID, nil
}
func (os *OpenStack) CreatePort(networkID, tenantID, portName, podHostname string) (*portsbinding.Port, error) {
	securitygroup, err := os.ensureSecurityGroup(tenantID)
	if err != nil {
		glog.Errorf("EnsureSecurityGroup failed: %v", err)
		return nil, err
	}
	opts := portsbinding.CreateOpts{
		HostID:  getHostName(),
		DNSName: podHostname,
		CreateOptsBuilder: ports.CreateOpts{
			NetworkID:      networkID,
			Name:           portName,
			AdminStateUp:   &adminStateUp,
			TenantID:       tenantID,
			DeviceID:       uuid.Generate().String(),
			DeviceOwner:    fmt.Sprintf("compute:%s", getHostName()),
			SecurityGroups: []string{securitygroup},
		},
	}
	port, err := portsbinding.Create(os.network, opts).Extract()
	if err != nil {
		glog.Errorf("Create port %s failed: %v", portName, err)
		return nil, err
	}
	updateOpts := portsbinding.UpdateOpts{
		DNSName: podHostname,
	}
	_, err = portsbinding.Update(os.network, port.ID, updateOpts).Extract()
	if err != nil {
		ports.Delete(os.network, port.ID)
		glog.Errorf("Update port %s failed: %v", portName, err)
		return nil, err
	}
	return port, nil
}
func (os *OpenStack) BindPortToFloatingip(portID, floatingIPAddress, tenantID string) error {
	var fip *floatingips.FloatingIP
	opts := floatingips.ListOpts{
		FloatingIP: floatingIPAddress,
	}
	pager := floatingips.List(os.network, opts)
	err := pager.EachPage(func(page pagination.Page) (bool, error) {
		floatingipList, err := floatingips.ExtractFloatingIPs(page)
		if err != nil {
			glog.Errorf("Get openstack floatingips error: %v", err)
			return false, err
		}
		if len(floatingipList) > 0 {
			fip = &floatingipList[0]
		}
		return true, nil
	})
	if err != nil {
		return err
	}
	if fip != nil {
		if fip.PortID != "" {
			if fip.PortID == portID {
				glog.V(3).Infof("FIP %q has already been associated with port %q", floatingIPAddress, portID)
				return nil
			}
			return fmt.Errorf("FloatingIP %v is already been binded to %v", floatingIPAddress, fip.PortID)
		}
		floatOpts := floatingips.UpdateOpts{PortID: portID}
		_, err = floatingips.Update(os.network, fip.ID, floatOpts).Extract()
		if err != nil {
			glog.Errorf("Bind floatingip %v to %v failed: %v", floatingIPAddress, portID, err)
			return err
		}
	} else {
		opts := floatingips.CreateOpts{
			FloatingNetworkID: os.ExtNetID,
			TenantID:          tenantID,
			FloatingIP:        floatingIPAddress,
			PortID:            portID,
		}
		_, err := floatingips.Create(os.network, opts).Extract()
		if err != nil {
			glog.Errorf("Create openstack flaotingip failed: %v", err)
			return err
		}
	}
	return nil
}
func (os *OpenStack) BindPortToExternal(portName, tenantID string) (string, error) {
	port, err := os.GetPort(portName)
	if err != nil {
		glog.Errorf("Get openstack port failed: %v", err)
		return "", err
	}
	opts := floatingips.CreateOpts{
		FloatingNetworkID: os.ExtNetID,
		TenantID:          tenantID,
	}
	ip, err := floatingips.Create(os.network, opts).Extract()
	if err != nil {
		glog.Errorf("Create openstack flaotingip failed: %v", err)
		return "", err
	}
	floatOpts := floatingips.UpdateOpts{PortID: port.ID}
	_, err = floatingips.Update(os.network, ip.ID, floatOpts).Extract()
	if err != nil {
		glog.Errorf("Associate floatingip failed: %v", err)
		e := floatingips.Delete(os.network, ip.ID).ExtractErr()
		if e != nil {
			glog.Errorf("Delete floatingip error: %v", e)
		}
		return "", err
	}
	return ip.FloatingIP, nil
}
func (os *OpenStack) getFloatingIPByPort(portID string) (*floatingips.FloatingIP, error) {
	var result *floatingips.FloatingIP
	opts := floatingips.ListOpts{
		PortID: portID,
	}
	pager := floatingips.List(os.network, opts)
	err := pager.EachPage(func(page pagination.Page) (bool, error) {
		floatingipList, err := floatingips.ExtractFloatingIPs(page)
		if err != nil {
			glog.Errorf("Get openstack floatingips error: %v", err)
			return false, err
		}
		if len(floatingipList) > 0 {
			result = &floatingipList[0]
		}
		return true, err
	})
	return result, err
}
func (os *OpenStack) UnbindPortFromExternal(portName string) error {
	port, err := os.GetPort(portName)
	if err != nil {
		glog.Errorf("get port failed: %v", err)
		return err
	}
	fip, err := os.getFloatingIPByPort(port.ID)
	if err != nil {
		glog.Errorf("get floatingip failed: %v", err)
		return err
	}
	if fip != nil {
		err = floatingips.Delete(os.network, fip.ID).ExtractErr()
		if err != nil {
			glog.Errorf("delete floatingip failed: %v", err)
			return err
		}
	}
	err = ports.Delete(os.network, port.ID).ExtractErr()
	if err != nil {
		glog.Errorf("delete port failed: %v", err)
		return err
	}
	return nil
}
func (os *OpenStack) GetPort(name string) (*ports.Port, error) {
	opts := ports.ListOpts{Name: name}
	pager := ports.List(os.network, opts)
	var port *ports.Port
	err := pager.EachPage(func(page pagination.Page) (bool, error) {
		portList, err := ports.ExtractPorts(page)
		if err != nil {
			glog.Errorf("Get openstack ports error: %v", err)
			return false, err
		}
		if len(portList) > 1 {
			return false, ErrMultipleResults
		}
		if len(portList) == 0 {
			return false, ErrNotFound
		}
		port = &portList[0]
		return true, err
	})
	return port, err
}
func (os *OpenStack) DeletePort(portName string) error {
	port, err := os.GetPort(portName)
	if err == ErrNotFound {
		glog.V(4).Infof("Port %s already deleted", portName)
		return nil
	} else if err != nil {
		glog.Errorf("Get openstack port %s failed: %v", portName, err)
		return err
	}
	if port != nil {
		err := ports.Delete(os.network, port.ID).ExtractErr()
		if err != nil {
			glog.Errorf("Delete openstack port %s failed: %v", portName, err)
			return err
		}
	}
	return nil
}
func isNotFound(err error) bool {
	_, ok := err.(*gophercloud.ErrDefault404)
	return ok
}
func (os *OpenStack) getPoolByName(name string) (*pools.Pool, error) {
	opts := pools.ListOpts{
		Name: name,
	}
	pager := pools.List(os.network, opts)
	poolList := make([]pools.Pool, 0, 1)
	err := pager.EachPage(func(page pagination.Page) (bool, error) {
		p, err := pools.ExtractPools(page)
		if err != nil {
			return false, err
		}
		poolList = append(poolList, p...)
		if len(poolList) > 1 {
			return false, ErrMultipleResults
		}
		return true, nil
	})
	if err != nil {
		if isNotFound(err) {
			return nil, ErrNotFound
		}
		return nil, err
	}
	if len(poolList) == 0 {
		return nil, ErrNotFound
	} else if len(poolList) > 1 {
		return nil, ErrMultipleResults
	}
	return &poolList[0], nil
}
func (os *OpenStack) getVipByID(id string) (*vips.VirtualIP, error) {
	opts := vips.ListOpts{
		ID: id,
	}
	return os.getVipByOpts(opts)
}
func (os *OpenStack) getVipByName(name string) (*vips.VirtualIP, error) {
	opts := vips.ListOpts{
		Name: name,
	}
	return os.getVipByOpts(opts)
}
func (os *OpenStack) getVipByOpts(opts vips.ListOpts) (*vips.VirtualIP, error) {
	pager := vips.List(os.network, opts)
	vipList := make([]vips.VirtualIP, 0, 1)
	err := pager.EachPage(func(page pagination.Page) (bool, error) {
		v, err := vips.ExtractVIPs(page)
		if err != nil {
			return false, err
		}
		vipList = append(vipList, v...)
		if len(vipList) > 1 {
			return false, ErrMultipleResults
		}
		return true, nil
	})
	if err != nil {
		if isNotFound(err) {
			return nil, ErrNotFound
		}
		return nil, err
	}
	if len(vipList) == 0 {
		return nil, ErrNotFound
	} else if len(vipList) > 1 {
		return nil, ErrMultipleResults
	}
	return &vipList[0], nil
}