Merge pull request #4878 from Fodoj/support-dvr
provider/openstack Add Distributed router support
This commit is contained in:
commit
dc5aa5e0bf
|
@ -655,8 +655,8 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/rackspace/gophercloud",
|
"ImportPath": "github.com/rackspace/gophercloud",
|
||||||
"Comment": "v1.0.0-774-g680aa02",
|
"Comment": "v1.0.0-803-g6769c3b",
|
||||||
"Rev": "680aa02616313d8399abc91f17a444cf9292f0e1"
|
"Rev": "6769c3b3e54a5cf1b0bdb10ea5b25f5cff0a3134"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/satori/go.uuid",
|
"ImportPath": "github.com/satori/go.uuid",
|
||||||
|
|
|
@ -37,6 +37,12 @@ func resourceNetworkingRouterV2() *schema.Resource {
|
||||||
ForceNew: false,
|
ForceNew: false,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
},
|
},
|
||||||
|
"distributed": &schema.Schema{
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
"external_gateway": &schema.Schema{
|
"external_gateway": &schema.Schema{
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
|
@ -69,6 +75,11 @@ func resourceNetworkingRouterV2Create(d *schema.ResourceData, meta interface{})
|
||||||
createOpts.AdminStateUp = &asu
|
createOpts.AdminStateUp = &asu
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if dRaw, ok := d.GetOk("distributed"); ok {
|
||||||
|
d := dRaw.(bool)
|
||||||
|
createOpts.Distributed = &d
|
||||||
|
}
|
||||||
|
|
||||||
externalGateway := d.Get("external_gateway").(string)
|
externalGateway := d.Get("external_gateway").(string)
|
||||||
if externalGateway != "" {
|
if externalGateway != "" {
|
||||||
gatewayInfo := routers.GatewayInfo{
|
gatewayInfo := routers.GatewayInfo{
|
||||||
|
@ -126,6 +137,7 @@ func resourceNetworkingRouterV2Read(d *schema.ResourceData, meta interface{}) er
|
||||||
|
|
||||||
d.Set("name", n.Name)
|
d.Set("name", n.Name)
|
||||||
d.Set("admin_state_up", n.AdminStateUp)
|
d.Set("admin_state_up", n.AdminStateUp)
|
||||||
|
d.Set("distributed", n.Distributed)
|
||||||
d.Set("tenant_id", n.TenantID)
|
d.Set("tenant_id", n.TenantID)
|
||||||
d.Set("external_gateway", n.GatewayInfo.NetworkID)
|
d.Set("external_gateway", n.GatewayInfo.NetworkID)
|
||||||
|
|
||||||
|
|
|
@ -91,10 +91,12 @@ var testAccNetworkingV2Router_basic = fmt.Sprintf(`
|
||||||
resource "openstack_networking_router_v2" "foo" {
|
resource "openstack_networking_router_v2" "foo" {
|
||||||
name = "router"
|
name = "router"
|
||||||
admin_state_up = "true"
|
admin_state_up = "true"
|
||||||
|
distributed = "false"
|
||||||
}`)
|
}`)
|
||||||
|
|
||||||
var testAccNetworkingV2Router_update = fmt.Sprintf(`
|
var testAccNetworkingV2Router_update = fmt.Sprintf(`
|
||||||
resource "openstack_networking_router_v2" "foo" {
|
resource "openstack_networking_router_v2" "foo" {
|
||||||
name = "router_2"
|
name = "router_2"
|
||||||
admin_state_up = "true"
|
admin_state_up = "true"
|
||||||
|
distributed = "false"
|
||||||
}`)
|
}`)
|
||||||
|
|
|
@ -3,6 +3,7 @@ package openstack
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/rackspace/gophercloud"
|
"github.com/rackspace/gophercloud"
|
||||||
tokens2 "github.com/rackspace/gophercloud/openstack/identity/v2/tokens"
|
tokens2 "github.com/rackspace/gophercloud/openstack/identity/v2/tokens"
|
||||||
|
@ -64,8 +65,8 @@ func AuthenticatedClient(options gophercloud.AuthOptions) (*gophercloud.Provider
|
||||||
// Authenticate or re-authenticate against the most recent identity service supported at the provided endpoint.
|
// Authenticate or re-authenticate against the most recent identity service supported at the provided endpoint.
|
||||||
func Authenticate(client *gophercloud.ProviderClient, options gophercloud.AuthOptions) error {
|
func Authenticate(client *gophercloud.ProviderClient, options gophercloud.AuthOptions) error {
|
||||||
versions := []*utils.Version{
|
versions := []*utils.Version{
|
||||||
&utils.Version{ID: v20, Priority: 20, Suffix: "/v2.0/"},
|
{ID: v20, Priority: 20, Suffix: "/v2.0/"},
|
||||||
&utils.Version{ID: v30, Priority: 30, Suffix: "/v3/"},
|
{ID: v30, Priority: 30, Suffix: "/v3/"},
|
||||||
}
|
}
|
||||||
|
|
||||||
chosen, endpoint, err := utils.ChooseVersion(client, versions)
|
chosen, endpoint, err := utils.ChooseVersion(client, versions)
|
||||||
|
@ -110,7 +111,7 @@ func v2auth(client *gophercloud.ProviderClient, endpoint string, options gopherc
|
||||||
if options.AllowReauth {
|
if options.AllowReauth {
|
||||||
client.ReauthFunc = func() error {
|
client.ReauthFunc = func() error {
|
||||||
client.TokenID = ""
|
client.TokenID = ""
|
||||||
return AuthenticateV2(client, options)
|
return v2auth(client, endpoint, options)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
client.TokenID = token.ID
|
client.TokenID = token.ID
|
||||||
|
@ -168,7 +169,7 @@ func v3auth(client *gophercloud.ProviderClient, endpoint string, options gopherc
|
||||||
if options.AllowReauth {
|
if options.AllowReauth {
|
||||||
client.ReauthFunc = func() error {
|
client.ReauthFunc = func() error {
|
||||||
client.TokenID = ""
|
client.TokenID = ""
|
||||||
return AuthenticateV3(client, options)
|
return v3auth(client, endpoint, options)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
client.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) {
|
client.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) {
|
||||||
|
@ -198,6 +199,40 @@ func NewIdentityV3(client *gophercloud.ProviderClient) *gophercloud.ServiceClien
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewIdentityAdminV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||||
|
eo.ApplyDefaults("identity")
|
||||||
|
eo.Availability = gophercloud.AvailabilityAdmin
|
||||||
|
|
||||||
|
url, err := client.EndpointLocator(eo)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force using v2 API
|
||||||
|
if strings.Contains(url, "/v3") {
|
||||||
|
url = strings.Replace(url, "/v3", "/v2.0", -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewIdentityAdminV3(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||||
|
eo.ApplyDefaults("identity")
|
||||||
|
eo.Availability = gophercloud.AvailabilityAdmin
|
||||||
|
|
||||||
|
url, err := client.EndpointLocator(eo)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force using v3 API
|
||||||
|
if strings.Contains(url, "/v2.0") {
|
||||||
|
url = strings.Replace(url, "/v2.0", "/v3", -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// NewObjectStorageV1 creates a ServiceClient that may be used with the v1 object storage package.
|
// NewObjectStorageV1 creates a ServiceClient that may be used with the v1 object storage package.
|
||||||
func NewObjectStorageV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
func NewObjectStorageV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||||
eo.ApplyDefaults("object-store")
|
eo.ApplyDefaults("object-store")
|
||||||
|
|
|
@ -15,6 +15,7 @@ const (
|
||||||
Volume SourceType = "volume"
|
Volume SourceType = "volume"
|
||||||
Snapshot SourceType = "snapshot"
|
Snapshot SourceType = "snapshot"
|
||||||
Image SourceType = "image"
|
Image SourceType = "image"
|
||||||
|
Blank SourceType = "blank"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BlockDevice is a structure with options for booting a server instance
|
// BlockDevice is a structure with options for booting a server instance
|
||||||
|
@ -32,6 +33,9 @@ type BlockDevice struct {
|
||||||
// and "local".
|
// and "local".
|
||||||
DestinationType string `json:"destination_type"`
|
DestinationType string `json:"destination_type"`
|
||||||
|
|
||||||
|
// GuestFormat [optional] specifies the format of the block device.
|
||||||
|
GuestFormat string `json:"guest_format"`
|
||||||
|
|
||||||
// SourceType [required] must be one of: "volume", "snapshot", "image".
|
// SourceType [required] must be one of: "volume", "snapshot", "image".
|
||||||
SourceType SourceType `json:"source_type"`
|
SourceType SourceType `json:"source_type"`
|
||||||
|
|
||||||
|
@ -82,6 +86,9 @@ func (opts CreateOptsExt) ToServerCreateMap() (map[string]interface{}, error) {
|
||||||
if bd.DestinationType != "" {
|
if bd.DestinationType != "" {
|
||||||
blockDevice[i]["destination_type"] = bd.DestinationType
|
blockDevice[i]["destination_type"] = bd.DestinationType
|
||||||
}
|
}
|
||||||
|
if bd.GuestFormat != "" {
|
||||||
|
blockDevice[i]["guest_format"] = bd.GuestFormat
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
serverMap["block_device_mapping_v2"] = blockDevice
|
serverMap["block_device_mapping_v2"] = blockDevice
|
||||||
|
|
12
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/fixtures.go
generated
vendored
12
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/fixtures.go
generated
vendored
|
@ -399,6 +399,18 @@ func HandleServerDeletionSuccessfully(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HandleAdminPasswordChangeSuccessfully sets up the test server to respond to a server password
|
||||||
|
// change request.
|
||||||
|
func HandleServerForceDeletionSuccessfully(t *testing.T) {
|
||||||
|
th.Mux.HandleFunc("/servers/asdfasdfasdf/action", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
th.TestMethod(t, r, "POST")
|
||||||
|
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||||
|
th.TestJSONRequest(t, r, `{ "forceDelete": "" }`)
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusAccepted)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// HandleServerGetSuccessfully sets up the test server to respond to a server Get request.
|
// HandleServerGetSuccessfully sets up the test server to respond to a server Get request.
|
||||||
func HandleServerGetSuccessfully(t *testing.T) {
|
func HandleServerGetSuccessfully(t *testing.T) {
|
||||||
th.Mux.HandleFunc("/servers/1234asdf", func(w http.ResponseWriter, r *http.Request) {
|
th.Mux.HandleFunc("/servers/1234asdf", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
11
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/requests.go
generated
vendored
11
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/servers/requests.go
generated
vendored
|
@ -303,6 +303,17 @@ func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ForceDelete(client *gophercloud.ServiceClient, id string) ActionResult {
|
||||||
|
var req struct {
|
||||||
|
ForceDelete string `json:"forceDelete"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var res ActionResult
|
||||||
|
_, res.Err = client.Post(actionURL(client, id), req, nil, nil)
|
||||||
|
return res
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Get requests details on a single server, by ID.
|
// Get requests details on a single server, by ID.
|
||||||
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
||||||
var result GetResult
|
var result GetResult
|
||||||
|
|
6
vendor/github.com/rackspace/gophercloud/openstack/identity/v3/tokens/requests.go
generated
vendored
6
vendor/github.com/rackspace/gophercloud/openstack/identity/v3/tokens/requests.go
generated
vendored
|
@ -15,9 +15,9 @@ type Scope struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func subjectTokenHeaders(c *gophercloud.ServiceClient, subjectToken string) map[string]string {
|
func subjectTokenHeaders(c *gophercloud.ServiceClient, subjectToken string) map[string]string {
|
||||||
h := c.AuthenticatedHeaders()
|
return map[string]string{
|
||||||
h["X-Subject-Token"] = subjectToken
|
"X-Subject-Token": subjectToken,
|
||||||
return h
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create authenticates and either generates a new token, or changes the Scope of an existing token.
|
// Create authenticates and either generates a new token, or changes the Scope of an existing token.
|
||||||
|
|
|
@ -16,6 +16,7 @@ type ListOpts struct {
|
||||||
ID string `q:"id"`
|
ID string `q:"id"`
|
||||||
Name string `q:"name"`
|
Name string `q:"name"`
|
||||||
AdminStateUp *bool `q:"admin_state_up"`
|
AdminStateUp *bool `q:"admin_state_up"`
|
||||||
|
Distributed *bool `q:"distributed"`
|
||||||
Status string `q:"status"`
|
Status string `q:"status"`
|
||||||
TenantID string `q:"tenant_id"`
|
TenantID string `q:"tenant_id"`
|
||||||
Limit int `q:"limit"`
|
Limit int `q:"limit"`
|
||||||
|
@ -46,6 +47,7 @@ func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager {
|
||||||
type CreateOpts struct {
|
type CreateOpts struct {
|
||||||
Name string
|
Name string
|
||||||
AdminStateUp *bool
|
AdminStateUp *bool
|
||||||
|
Distributed *bool
|
||||||
TenantID string
|
TenantID string
|
||||||
GatewayInfo *GatewayInfo
|
GatewayInfo *GatewayInfo
|
||||||
}
|
}
|
||||||
|
@ -62,6 +64,7 @@ func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult {
|
||||||
type router struct {
|
type router struct {
|
||||||
Name *string `json:"name,omitempty"`
|
Name *string `json:"name,omitempty"`
|
||||||
AdminStateUp *bool `json:"admin_state_up,omitempty"`
|
AdminStateUp *bool `json:"admin_state_up,omitempty"`
|
||||||
|
Distributed *bool `json:"distributed,omitempty"`
|
||||||
TenantID *string `json:"tenant_id,omitempty"`
|
TenantID *string `json:"tenant_id,omitempty"`
|
||||||
GatewayInfo *GatewayInfo `json:"external_gateway_info,omitempty"`
|
GatewayInfo *GatewayInfo `json:"external_gateway_info,omitempty"`
|
||||||
}
|
}
|
||||||
|
@ -73,6 +76,7 @@ func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult {
|
||||||
reqBody := request{Router: router{
|
reqBody := request{Router: router{
|
||||||
Name: gophercloud.MaybeString(opts.Name),
|
Name: gophercloud.MaybeString(opts.Name),
|
||||||
AdminStateUp: opts.AdminStateUp,
|
AdminStateUp: opts.AdminStateUp,
|
||||||
|
Distributed: opts.Distributed,
|
||||||
TenantID: gophercloud.MaybeString(opts.TenantID),
|
TenantID: gophercloud.MaybeString(opts.TenantID),
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
@ -96,6 +100,7 @@ func Get(c *gophercloud.ServiceClient, id string) GetResult {
|
||||||
type UpdateOpts struct {
|
type UpdateOpts struct {
|
||||||
Name string
|
Name string
|
||||||
AdminStateUp *bool
|
AdminStateUp *bool
|
||||||
|
Distributed *bool
|
||||||
GatewayInfo *GatewayInfo
|
GatewayInfo *GatewayInfo
|
||||||
Routes []Route
|
Routes []Route
|
||||||
}
|
}
|
||||||
|
@ -109,6 +114,7 @@ func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) UpdateResu
|
||||||
type router struct {
|
type router struct {
|
||||||
Name *string `json:"name,omitempty"`
|
Name *string `json:"name,omitempty"`
|
||||||
AdminStateUp *bool `json:"admin_state_up,omitempty"`
|
AdminStateUp *bool `json:"admin_state_up,omitempty"`
|
||||||
|
Distributed *bool `json:"distributed,omitempty"`
|
||||||
GatewayInfo *GatewayInfo `json:"external_gateway_info,omitempty"`
|
GatewayInfo *GatewayInfo `json:"external_gateway_info,omitempty"`
|
||||||
Routes []Route `json:"routes"`
|
Routes []Route `json:"routes"`
|
||||||
}
|
}
|
||||||
|
@ -120,6 +126,7 @@ func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) UpdateResu
|
||||||
reqBody := request{Router: router{
|
reqBody := request{Router: router{
|
||||||
Name: gophercloud.MaybeString(opts.Name),
|
Name: gophercloud.MaybeString(opts.Name),
|
||||||
AdminStateUp: opts.AdminStateUp,
|
AdminStateUp: opts.AdminStateUp,
|
||||||
|
Distributed: opts.Distributed,
|
||||||
}}
|
}}
|
||||||
|
|
||||||
if opts.GatewayInfo != nil {
|
if opts.GatewayInfo != nil {
|
||||||
|
|
|
@ -35,6 +35,9 @@ type Router struct {
|
||||||
// Administrative state of the router.
|
// Administrative state of the router.
|
||||||
AdminStateUp bool `json:"admin_state_up" mapstructure:"admin_state_up"`
|
AdminStateUp bool `json:"admin_state_up" mapstructure:"admin_state_up"`
|
||||||
|
|
||||||
|
// Whether router is disitrubted or not..
|
||||||
|
Distributed bool `json:"distributed" mapstructure:"distributed"`
|
||||||
|
|
||||||
// Human readable name for the router. Does not have to be unique.
|
// Human readable name for the router. Does not have to be unique.
|
||||||
Name string `json:"name" mapstructure:"name"`
|
Name string `json:"name" mapstructure:"name"`
|
||||||
|
|
||||||
|
|
8
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/ports/requests.go
generated
vendored
8
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/ports/requests.go
generated
vendored
|
@ -104,6 +104,7 @@ type CreateOpts struct {
|
||||||
DeviceOwner string
|
DeviceOwner string
|
||||||
TenantID string
|
TenantID string
|
||||||
SecurityGroups []string
|
SecurityGroups []string
|
||||||
|
AllowedAddressPairs []AddressPair
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToPortCreateMap casts a CreateOpts struct to a map.
|
// ToPortCreateMap casts a CreateOpts struct to a map.
|
||||||
|
@ -139,6 +140,9 @@ func (opts CreateOpts) ToPortCreateMap() (map[string]interface{}, error) {
|
||||||
if opts.MACAddress != "" {
|
if opts.MACAddress != "" {
|
||||||
p["mac_address"] = opts.MACAddress
|
p["mac_address"] = opts.MACAddress
|
||||||
}
|
}
|
||||||
|
if opts.AllowedAddressPairs != nil {
|
||||||
|
p["allowed_address_pairs"] = opts.AllowedAddressPairs
|
||||||
|
}
|
||||||
|
|
||||||
return map[string]interface{}{"port": p}, nil
|
return map[string]interface{}{"port": p}, nil
|
||||||
}
|
}
|
||||||
|
@ -174,6 +178,7 @@ type UpdateOpts struct {
|
||||||
DeviceID string
|
DeviceID string
|
||||||
DeviceOwner string
|
DeviceOwner string
|
||||||
SecurityGroups []string
|
SecurityGroups []string
|
||||||
|
AllowedAddressPairs []AddressPair
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToPortUpdateMap casts an UpdateOpts struct to a map.
|
// ToPortUpdateMap casts an UpdateOpts struct to a map.
|
||||||
|
@ -198,6 +203,9 @@ func (opts UpdateOpts) ToPortUpdateMap() (map[string]interface{}, error) {
|
||||||
if opts.Name != "" {
|
if opts.Name != "" {
|
||||||
p["name"] = opts.Name
|
p["name"] = opts.Name
|
||||||
}
|
}
|
||||||
|
if opts.AllowedAddressPairs != nil {
|
||||||
|
p["allowed_address_pairs"] = opts.AllowedAddressPairs
|
||||||
|
}
|
||||||
|
|
||||||
return map[string]interface{}{"port": p}, nil
|
return map[string]interface{}{"port": p}, nil
|
||||||
}
|
}
|
||||||
|
|
8
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/ports/results.go
generated
vendored
8
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/ports/results.go
generated
vendored
|
@ -19,7 +19,6 @@ func (r commonResult) Extract() (*Port, error) {
|
||||||
var res struct {
|
var res struct {
|
||||||
Port *Port `json:"port"`
|
Port *Port `json:"port"`
|
||||||
}
|
}
|
||||||
|
|
||||||
err := mapstructure.Decode(r.Body, &res)
|
err := mapstructure.Decode(r.Body, &res)
|
||||||
|
|
||||||
return res.Port, err
|
return res.Port, err
|
||||||
|
@ -51,6 +50,11 @@ type IP struct {
|
||||||
IPAddress string `mapstructure:"ip_address" json:"ip_address,omitempty"`
|
IPAddress string `mapstructure:"ip_address" json:"ip_address,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AddressPair struct {
|
||||||
|
IPAddress string `mapstructure:"ip_address" json:"ip_address,omitempty"`
|
||||||
|
MACAddress string `mapstructure:"mac_address" json:"mac_address,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// Port represents a Neutron port. See package documentation for a top-level
|
// Port represents a Neutron port. See package documentation for a top-level
|
||||||
// description of what this is.
|
// description of what this is.
|
||||||
type Port struct {
|
type Port struct {
|
||||||
|
@ -78,6 +82,8 @@ type Port struct {
|
||||||
SecurityGroups []string `mapstructure:"security_groups" json:"security_groups"`
|
SecurityGroups []string `mapstructure:"security_groups" json:"security_groups"`
|
||||||
// Identifies the device (e.g., virtual server) using this port.
|
// Identifies the device (e.g., virtual server) using this port.
|
||||||
DeviceID string `mapstructure:"device_id" json:"device_id"`
|
DeviceID string `mapstructure:"device_id" json:"device_id"`
|
||||||
|
// Identifies the list of IP addresses the port will recognize/accept
|
||||||
|
AllowedAddressPairs []AddressPair `mapstructure:"allowed_address_pairs" json:"allowed_address_pairs"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PortPage is the page returned by a pager when traversing over a collection
|
// PortPage is the page returned by a pager when traversing over a collection
|
||||||
|
|
|
@ -177,6 +177,9 @@ func (client *ProviderClient) Request(method, url string, options RequestOpts) (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set connection parameter to close the connection immediately when we've got the response
|
||||||
|
req.Close = true
|
||||||
|
|
||||||
// Issue the request.
|
// Issue the request.
|
||||||
resp, err := client.HTTPClient.Do(req)
|
resp, err := client.HTTPClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -246,6 +249,8 @@ func defaultOkCodes(method string) []int {
|
||||||
return []int{201, 202}
|
return []int{201, 202}
|
||||||
case method == "PUT":
|
case method == "PUT":
|
||||||
return []int{201, 202}
|
return []int{201, 202}
|
||||||
|
case method == "PATCH":
|
||||||
|
return []int{200, 204}
|
||||||
case method == "DELETE":
|
case method == "DELETE":
|
||||||
return []int{202, 204}
|
return []int{202, 204}
|
||||||
}
|
}
|
||||||
|
@ -299,6 +304,24 @@ func (client *ProviderClient) Put(url string, JSONBody interface{}, JSONResponse
|
||||||
return client.Request("PUT", url, *opts)
|
return client.Request("PUT", url, *opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (client *ProviderClient) Patch(url string, JSONBody interface{}, JSONResponse *interface{}, opts *RequestOpts) (*http.Response, error) {
|
||||||
|
if opts == nil {
|
||||||
|
opts = &RequestOpts{}
|
||||||
|
}
|
||||||
|
|
||||||
|
if v, ok := (JSONBody).(io.ReadSeeker); ok {
|
||||||
|
opts.RawBody = v
|
||||||
|
} else if JSONBody != nil {
|
||||||
|
opts.JSONBody = JSONBody
|
||||||
|
}
|
||||||
|
|
||||||
|
if JSONResponse != nil {
|
||||||
|
opts.JSONResponse = JSONResponse
|
||||||
|
}
|
||||||
|
|
||||||
|
return client.Request("PATCH", url, *opts)
|
||||||
|
}
|
||||||
|
|
||||||
func (client *ProviderClient) Delete(url string, opts *RequestOpts) (*http.Response, error) {
|
func (client *ProviderClient) Delete(url string, opts *RequestOpts) (*http.Response, error) {
|
||||||
if opts == nil {
|
if opts == nil {
|
||||||
opts = &RequestOpts{}
|
opts = &RequestOpts{}
|
||||||
|
|
|
@ -249,3 +249,38 @@ func ListEvents(client *gophercloud.ServiceClient, loadBalancerID int, opts List
|
||||||
return NodeEventPage{pagination.SinglePageBase(r)}
|
return NodeEventPage{pagination.SinglePageBase(r)}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetByIPPort locates a load balancer node by IP and port.
|
||||||
|
func GetByIPPort(
|
||||||
|
client *gophercloud.ServiceClient,
|
||||||
|
loadBalancerID int,
|
||||||
|
address string,
|
||||||
|
port int,
|
||||||
|
) (*Node, error) {
|
||||||
|
|
||||||
|
// nil until found
|
||||||
|
var found *Node
|
||||||
|
|
||||||
|
List(client, loadBalancerID, nil).EachPage(func(page pagination.Page) (bool, error) {
|
||||||
|
lbNodes, err := ExtractNodes(page)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, trialNode := range lbNodes {
|
||||||
|
if trialNode.Address == address && trialNode.Port == port {
|
||||||
|
found = &trialNode
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if found == nil {
|
||||||
|
return nil, errors.New("Unable to get node by IP and Port")
|
||||||
|
}
|
||||||
|
|
||||||
|
return found, nil
|
||||||
|
}
|
||||||
|
|
|
@ -36,6 +36,10 @@ The following arguments are supported:
|
||||||
(must be "true" or "false" if provided). Changing this updates the
|
(must be "true" or "false" if provided). Changing this updates the
|
||||||
`admin_state_up` of an existing router.
|
`admin_state_up` of an existing router.
|
||||||
|
|
||||||
|
* `distributed` - (Optional) Indicates whether or not to create a
|
||||||
|
distributed router. The default policy setting in Neutron restricts
|
||||||
|
usage of this property to administrative users only.
|
||||||
|
|
||||||
* `external_gateway` - (Optional) The network UUID of an external gateway for
|
* `external_gateway` - (Optional) The network UUID of an external gateway for
|
||||||
the router. A router with an external gateway is required if any compute
|
the router. A router with an external gateway is required if any compute
|
||||||
instances or load balancers will be using floating IPs. Changing this
|
instances or load balancers will be using floating IPs. Changing this
|
||||||
|
|
Loading…
Reference in New Issue