mirror of https://github.com/kubernetes/kops.git
implement router interface task
This commit is contained in:
parent
063afb28d7
commit
f5f1ae8c3c
|
|
@ -28,3 +28,11 @@ type OpenstackModelContext struct {
|
||||||
func (c *OpenstackModelContext) LinkToNetwork() *openstacktasks.Network {
|
func (c *OpenstackModelContext) LinkToNetwork() *openstacktasks.Network {
|
||||||
return &openstacktasks.Network{Name: s(c.ClusterName())}
|
return &openstacktasks.Network{Name: s(c.ClusterName())}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *OpenstackModelContext) LinkToRouter(name *string) *openstacktasks.Router {
|
||||||
|
return &openstacktasks.Router{Name: name}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *OpenstackModelContext) LinkToSubnet(name *string) *openstacktasks.Subnet {
|
||||||
|
return &openstacktasks.Subnet{Name: name}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ var _ fi.ModelBuilder = &NetworkModelBuilder{}
|
||||||
|
|
||||||
func (b *NetworkModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
func (b *NetworkModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
||||||
clusterName := b.ClusterName()
|
clusterName := b.ClusterName()
|
||||||
|
routerName := strings.Replace(clusterName, ".", "-", -1)
|
||||||
|
|
||||||
{
|
{
|
||||||
t := &openstacktasks.Network{
|
t := &openstacktasks.Network{
|
||||||
|
|
@ -46,7 +47,7 @@ func (b *NetworkModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
||||||
|
|
||||||
{
|
{
|
||||||
t := &openstacktasks.Router{
|
t := &openstacktasks.Router{
|
||||||
Name: s(strings.Replace(clusterName, ".", "-", -1)),
|
Name: s(routerName),
|
||||||
Lifecycle: b.Lifecycle,
|
Lifecycle: b.Lifecycle,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -61,6 +62,14 @@ func (b *NetworkModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
||||||
Lifecycle: b.Lifecycle,
|
Lifecycle: b.Lifecycle,
|
||||||
}
|
}
|
||||||
c.AddTask(t)
|
c.AddTask(t)
|
||||||
|
|
||||||
|
t1 := &openstacktasks.RouterInterface{
|
||||||
|
Name: s("ri-" + sp.Name),
|
||||||
|
Subnet: b.LinkToSubnet(s(sp.Name)),
|
||||||
|
Router: b.LinkToRouter(s(routerName)),
|
||||||
|
Lifecycle: b.Lifecycle,
|
||||||
|
}
|
||||||
|
c.AddTask(t1)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ go_library(
|
||||||
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups:go_default_library",
|
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups:go_default_library",
|
||||||
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules:go_default_library",
|
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules:go_default_library",
|
||||||
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks:go_default_library",
|
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks:go_default_library",
|
||||||
|
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/ports:go_default_library",
|
||||||
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/subnets:go_default_library",
|
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/subnets:go_default_library",
|
||||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ import (
|
||||||
sg "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups"
|
sg "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups"
|
||||||
sgr "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules"
|
sgr "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/networks"
|
||||||
|
"github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
|
||||||
"github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
|
"github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
|
||||||
"k8s.io/api/core/v1"
|
"k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
|
|
@ -105,6 +106,12 @@ type OpenstackCloud interface {
|
||||||
|
|
||||||
//CreateSubnet will create a new Neutron subnet
|
//CreateSubnet will create a new Neutron subnet
|
||||||
CreateSubnet(opt subnets.CreateOptsBuilder) (*subnets.Subnet, error)
|
CreateSubnet(opt subnets.CreateOptsBuilder) (*subnets.Subnet, error)
|
||||||
|
|
||||||
|
//ListPorts will return the Neutron ports which match the options
|
||||||
|
ListPorts(opt ports.ListOptsBuilder) ([]ports.Port, error)
|
||||||
|
|
||||||
|
//CreateRouterInterface will create a new Neutron router interface
|
||||||
|
CreateRouterInterface(routerID string, opt routers.AddInterfaceOptsBuilder) (*routers.InterfaceInfo, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type openstackCloud struct {
|
type openstackCloud struct {
|
||||||
|
|
@ -483,3 +490,48 @@ func (c *openstackCloud) CreateSubnet(opt subnets.CreateOptsBuilder) (*subnets.S
|
||||||
return s, wait.ErrWaitTimeout
|
return s, wait.ErrWaitTimeout
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *openstackCloud) ListPorts(opt ports.ListOptsBuilder) ([]ports.Port, error) {
|
||||||
|
var p []ports.Port
|
||||||
|
|
||||||
|
done, err := vfs.RetryWithBackoff(readBackoff, func() (bool, error) {
|
||||||
|
allPages, err := ports.List(c.neutronClient, opt).AllPages()
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("error listing ports: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r, err := ports.ExtractPorts(allPages)
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("error extracting ports from pages: %v", err)
|
||||||
|
}
|
||||||
|
p = r
|
||||||
|
return true, nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return p, err
|
||||||
|
} else if done {
|
||||||
|
return p, nil
|
||||||
|
} else {
|
||||||
|
return p, wait.ErrWaitTimeout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *openstackCloud) CreateRouterInterface(routerID string, opt routers.AddInterfaceOptsBuilder) (*routers.InterfaceInfo, error) {
|
||||||
|
var i *routers.InterfaceInfo
|
||||||
|
|
||||||
|
done, err := vfs.RetryWithBackoff(writeBackoff, func() (bool, error) {
|
||||||
|
v, err := routers.AddInterface(c.neutronClient, routerID, opt).Extract()
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("error creating router interface: %v", err)
|
||||||
|
}
|
||||||
|
i = v
|
||||||
|
return true, nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return i, err
|
||||||
|
} else if done {
|
||||||
|
return i, nil
|
||||||
|
} else {
|
||||||
|
return i, wait.ErrWaitTimeout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@ go_library(
|
||||||
"network_fitask.go",
|
"network_fitask.go",
|
||||||
"router.go",
|
"router.go",
|
||||||
"router_fitask.go",
|
"router_fitask.go",
|
||||||
|
"routerinterface.go",
|
||||||
|
"routerinterface_fitask.go",
|
||||||
"securitygroup.go",
|
"securitygroup.go",
|
||||||
"securitygroup_fitask.go",
|
"securitygroup_fitask.go",
|
||||||
"securitygrouprule.go",
|
"securitygrouprule.go",
|
||||||
|
|
@ -27,6 +29,7 @@ go_library(
|
||||||
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups:go_default_library",
|
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups:go_default_library",
|
||||||
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules:go_default_library",
|
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules:go_default_library",
|
||||||
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks:go_default_library",
|
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks:go_default_library",
|
||||||
|
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/ports:go_default_library",
|
||||||
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/subnets:go_default_library",
|
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/subnets:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,135 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package openstacktasks
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/golang/glog"
|
||||||
|
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers"
|
||||||
|
"github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
|
||||||
|
"k8s.io/kops/upup/pkg/fi"
|
||||||
|
"k8s.io/kops/upup/pkg/fi/cloudup/openstack"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:generate fitask -type=RouterInterface
|
||||||
|
type RouterInterface struct {
|
||||||
|
ID *string
|
||||||
|
Name *string
|
||||||
|
Router *Router
|
||||||
|
Subnet *Subnet
|
||||||
|
Lifecycle *fi.Lifecycle
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ fi.CompareWithID = &RouterInterface{}
|
||||||
|
|
||||||
|
func (i *RouterInterface) CompareWithID() *string {
|
||||||
|
return i.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *RouterInterface) Find(context *fi.Context) (*RouterInterface, error) {
|
||||||
|
cloud := context.Cloud.(openstack.OpenstackCloud)
|
||||||
|
opt := ports.ListOpts{
|
||||||
|
NetworkID: fi.StringValue(i.Subnet.Network.ID),
|
||||||
|
DeviceOwner: "network:router_interface",
|
||||||
|
DeviceID: fi.StringValue(i.Router.ID),
|
||||||
|
ID: fi.StringValue(i.ID),
|
||||||
|
}
|
||||||
|
ps, err := cloud.ListPorts(opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if ps == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
subnetID := fi.StringValue(i.Subnet.ID)
|
||||||
|
iID := ""
|
||||||
|
n := 0
|
||||||
|
for _, p := range ps {
|
||||||
|
for _, ip := range p.FixedIPs {
|
||||||
|
if ip.SubnetID == subnetID {
|
||||||
|
n += 1
|
||||||
|
iID = p.ID
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch n {
|
||||||
|
case 0:
|
||||||
|
return nil, nil
|
||||||
|
case 1:
|
||||||
|
actual := &RouterInterface{
|
||||||
|
ID: fi.String(iID),
|
||||||
|
Name: i.Name,
|
||||||
|
Router: i.Router,
|
||||||
|
Subnet: i.Subnet,
|
||||||
|
Lifecycle: i.Lifecycle,
|
||||||
|
}
|
||||||
|
|
||||||
|
return actual, nil
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("find multiple interfaces which subnet:%s attach to", subnetID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *RouterInterface) Run(context *fi.Context) error {
|
||||||
|
return fi.DefaultDeltaRunMethod(i, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_ *RouterInterface) CheckChanges(a, e, changes *RouterInterface) error {
|
||||||
|
if a == nil {
|
||||||
|
if e.Router == nil {
|
||||||
|
return fi.RequiredField("Router")
|
||||||
|
}
|
||||||
|
if e.Subnet == nil {
|
||||||
|
return fi.RequiredField("Subnet")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if changes.Name != nil {
|
||||||
|
return fi.CannotChangeField("Name")
|
||||||
|
}
|
||||||
|
if changes.Router != nil {
|
||||||
|
return fi.CannotChangeField("Router")
|
||||||
|
}
|
||||||
|
if changes.Subnet != nil {
|
||||||
|
return fi.CannotChangeField("Subnet")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_ *RouterInterface) RenderOpenstack(t *openstack.OpenstackAPITarget, a, e, changes *RouterInterface) error {
|
||||||
|
if a == nil {
|
||||||
|
routerID := fi.StringValue(e.Router.ID)
|
||||||
|
subnetID := fi.StringValue(e.Subnet.ID)
|
||||||
|
glog.V(2).Infof("Creating RouterInterface for router:%s and subnet:%s", routerID, subnetID)
|
||||||
|
|
||||||
|
opt := routers.AddInterfaceOpts{SubnetID: subnetID}
|
||||||
|
v, err := t.Cloud.CreateRouterInterface(routerID, opt)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error creating router interface: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
e.ID = fi.String(v.PortID)
|
||||||
|
glog.V(2).Infof("Creating a new Openstack router interface, id=%s", v.PortID)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
e.ID = a.ID
|
||||||
|
glog.V(2).Infof("Using an existing Openstack router interface, id=%s", fi.StringValue(e.ID))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Code generated by ""fitask" -type=RouterInterface"; DO NOT EDIT
|
||||||
|
|
||||||
|
package openstacktasks
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"k8s.io/kops/upup/pkg/fi"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RouterInterface
|
||||||
|
|
||||||
|
// JSON marshalling boilerplate
|
||||||
|
type realRouterInterface RouterInterface
|
||||||
|
|
||||||
|
// UnmarshalJSON implements conversion to JSON, supporitng an alternate specification of the object as a string
|
||||||
|
func (o *RouterInterface) UnmarshalJSON(data []byte) error {
|
||||||
|
var jsonName string
|
||||||
|
if err := json.Unmarshal(data, &jsonName); err == nil {
|
||||||
|
o.Name = &jsonName
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var r realRouterInterface
|
||||||
|
if err := json.Unmarshal(data, &r); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*o = RouterInterface(r)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ fi.HasLifecycle = &RouterInterface{}
|
||||||
|
|
||||||
|
// GetLifecycle returns the Lifecycle of the object, implementing fi.HasLifecycle
|
||||||
|
func (o *RouterInterface) GetLifecycle() *fi.Lifecycle {
|
||||||
|
return o.Lifecycle
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLifecycle sets the Lifecycle of the object, implementing fi.SetLifecycle
|
||||||
|
func (o *RouterInterface) SetLifecycle(lifecycle fi.Lifecycle) {
|
||||||
|
o.Lifecycle = &lifecycle
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ fi.HasName = &RouterInterface{}
|
||||||
|
|
||||||
|
// GetName returns the Name of the object, implementing fi.HasName
|
||||||
|
func (o *RouterInterface) GetName() *string {
|
||||||
|
return o.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetName sets the Name of the object, implementing fi.SetName
|
||||||
|
func (o *RouterInterface) SetName(name string) {
|
||||||
|
o.Name = &name
|
||||||
|
}
|
||||||
|
|
||||||
|
// String is the stringer function for the task, producing readable output using fi.TaskAsString
|
||||||
|
func (o *RouterInterface) String() string {
|
||||||
|
return fi.TaskAsString(o)
|
||||||
|
}
|
||||||
17
vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/ports/BUILD.bazel
generated
vendored
Normal file
17
vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/ports/BUILD.bazel
generated
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "go_default_library",
|
||||||
|
srcs = [
|
||||||
|
"doc.go",
|
||||||
|
"requests.go",
|
||||||
|
"results.go",
|
||||||
|
"urls.go",
|
||||||
|
],
|
||||||
|
importpath = "github.com/gophercloud/gophercloud/openstack/networking/v2/ports",
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
deps = [
|
||||||
|
"//vendor/github.com/gophercloud/gophercloud:go_default_library",
|
||||||
|
"//vendor/github.com/gophercloud/gophercloud/pagination:go_default_library",
|
||||||
|
],
|
||||||
|
)
|
||||||
73
vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/ports/doc.go
generated
vendored
Normal file
73
vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/ports/doc.go
generated
vendored
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
Package ports contains functionality for working with Neutron port resources.
|
||||||
|
|
||||||
|
A port represents a virtual switch port on a logical network switch. Virtual
|
||||||
|
instances attach their interfaces into ports. The logical port also defines
|
||||||
|
the MAC address and the IP address(es) to be assigned to the interfaces
|
||||||
|
plugged into them. When IP addresses are associated to a port, this also
|
||||||
|
implies the port is associated with a subnet, as the IP address was taken
|
||||||
|
from the allocation pool for a specific subnet.
|
||||||
|
|
||||||
|
Example to List Ports
|
||||||
|
|
||||||
|
listOpts := ports.ListOpts{
|
||||||
|
DeviceID: "b0b89efe-82f8-461d-958b-adbf80f50c7d",
|
||||||
|
}
|
||||||
|
|
||||||
|
allPages, err := ports.List(networkClient, listOpts).AllPages()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
allPorts, err := ports.ExtractPorts(allPages)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, port := range allPorts {
|
||||||
|
fmt.Printf("%+v\n", port)
|
||||||
|
}
|
||||||
|
|
||||||
|
Example to Create a Port
|
||||||
|
|
||||||
|
createOtps := ports.CreateOpts{
|
||||||
|
Name: "private-port",
|
||||||
|
AdminStateUp: &asu,
|
||||||
|
NetworkID: "a87cc70a-3e15-4acf-8205-9b711a3531b7",
|
||||||
|
FixedIPs: []ports.IP{
|
||||||
|
{SubnetID: "a0304c3a-4f08-4c43-88af-d796509c97d2", IPAddress: "10.0.0.2"},
|
||||||
|
},
|
||||||
|
SecurityGroups: &[]string{"foo"},
|
||||||
|
AllowedAddressPairs: []ports.AddressPair{
|
||||||
|
{IPAddress: "10.0.0.4", MACAddress: "fa:16:3e:c9:cb:f0"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
port, err := ports.Create(networkClient, createOpts).Extract()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
Example to Update a Port
|
||||||
|
|
||||||
|
portID := "c34bae2b-7641-49b6-bf6d-d8e473620ed8"
|
||||||
|
|
||||||
|
updateOpts := ports.UpdateOpts{
|
||||||
|
Name: "new_name",
|
||||||
|
SecurityGroups: &[]string{},
|
||||||
|
}
|
||||||
|
|
||||||
|
port, err := ports.Update(networkClient, portID, updateOpts).Extract()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
Example to Delete a Port
|
||||||
|
|
||||||
|
portID := "c34bae2b-7641-49b6-bf6d-d8e473620ed8"
|
||||||
|
err := ports.Delete(networkClient, portID).ExtractErr()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
package ports
|
||||||
177
vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/ports/requests.go
generated
vendored
Normal file
177
vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/ports/requests.go
generated
vendored
Normal file
|
|
@ -0,0 +1,177 @@
|
||||||
|
package ports
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gophercloud/gophercloud"
|
||||||
|
"github.com/gophercloud/gophercloud/pagination"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListOptsBuilder allows extensions to add additional parameters to the
|
||||||
|
// List request.
|
||||||
|
type ListOptsBuilder interface {
|
||||||
|
ToPortListQuery() (string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListOpts allows the filtering and sorting of paginated collections through
|
||||||
|
// the API. Filtering is achieved by passing in struct field values that map to
|
||||||
|
// the port attributes you want to see returned. SortKey allows you to sort
|
||||||
|
// by a particular port attribute. SortDir sets the direction, and is either
|
||||||
|
// `asc' or `desc'. Marker and Limit are used for pagination.
|
||||||
|
type ListOpts struct {
|
||||||
|
Status string `q:"status"`
|
||||||
|
Name string `q:"name"`
|
||||||
|
AdminStateUp *bool `q:"admin_state_up"`
|
||||||
|
NetworkID string `q:"network_id"`
|
||||||
|
TenantID string `q:"tenant_id"`
|
||||||
|
DeviceOwner string `q:"device_owner"`
|
||||||
|
MACAddress string `q:"mac_address"`
|
||||||
|
ID string `q:"id"`
|
||||||
|
DeviceID string `q:"device_id"`
|
||||||
|
Limit int `q:"limit"`
|
||||||
|
Marker string `q:"marker"`
|
||||||
|
SortKey string `q:"sort_key"`
|
||||||
|
SortDir string `q:"sort_dir"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToPortListQuery formats a ListOpts into a query string.
|
||||||
|
func (opts ListOpts) ToPortListQuery() (string, error) {
|
||||||
|
q, err := gophercloud.BuildQueryString(opts)
|
||||||
|
return q.String(), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// List returns a Pager which allows you to iterate over a collection of
|
||||||
|
// ports. It accepts a ListOpts struct, which allows you to filter and sort
|
||||||
|
// the returned collection for greater efficiency.
|
||||||
|
//
|
||||||
|
// Default policy settings return only those ports that are owned by the tenant
|
||||||
|
// who submits the request, unless the request is submitted by a user with
|
||||||
|
// administrative rights.
|
||||||
|
func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
|
||||||
|
url := listURL(c)
|
||||||
|
if opts != nil {
|
||||||
|
query, err := opts.ToPortListQuery()
|
||||||
|
if err != nil {
|
||||||
|
return pagination.Pager{Err: err}
|
||||||
|
}
|
||||||
|
url += query
|
||||||
|
}
|
||||||
|
return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
|
||||||
|
return PortPage{pagination.LinkedPageBase{PageResult: r}}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get retrieves a specific port based on its unique ID.
|
||||||
|
func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
|
||||||
|
_, r.Err = c.Get(getURL(c, id), &r.Body, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOptsBuilder allows extensions to add additional parameters to the
|
||||||
|
// Create request.
|
||||||
|
type CreateOptsBuilder interface {
|
||||||
|
ToPortCreateMap() (map[string]interface{}, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOpts represents the attributes used when creating a new port.
|
||||||
|
type CreateOpts struct {
|
||||||
|
NetworkID string `json:"network_id" required:"true"`
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
AdminStateUp *bool `json:"admin_state_up,omitempty"`
|
||||||
|
MACAddress string `json:"mac_address,omitempty"`
|
||||||
|
FixedIPs interface{} `json:"fixed_ips,omitempty"`
|
||||||
|
DeviceID string `json:"device_id,omitempty"`
|
||||||
|
DeviceOwner string `json:"device_owner,omitempty"`
|
||||||
|
TenantID string `json:"tenant_id,omitempty"`
|
||||||
|
SecurityGroups *[]string `json:"security_groups,omitempty"`
|
||||||
|
AllowedAddressPairs []AddressPair `json:"allowed_address_pairs,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToPortCreateMap builds a request body from CreateOpts.
|
||||||
|
func (opts CreateOpts) ToPortCreateMap() (map[string]interface{}, error) {
|
||||||
|
return gophercloud.BuildRequestBody(opts, "port")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create accepts a CreateOpts struct and creates a new network using the values
|
||||||
|
// provided. You must remember to provide a NetworkID value.
|
||||||
|
func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
|
||||||
|
b, err := opts.ToPortCreateMap()
|
||||||
|
if err != nil {
|
||||||
|
r.Err = err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, r.Err = c.Post(createURL(c), b, &r.Body, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateOptsBuilder allows extensions to add additional parameters to the
|
||||||
|
// Update request.
|
||||||
|
type UpdateOptsBuilder interface {
|
||||||
|
ToPortUpdateMap() (map[string]interface{}, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateOpts represents the attributes used when updating an existing port.
|
||||||
|
type UpdateOpts struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
AdminStateUp *bool `json:"admin_state_up,omitempty"`
|
||||||
|
FixedIPs interface{} `json:"fixed_ips,omitempty"`
|
||||||
|
DeviceID string `json:"device_id,omitempty"`
|
||||||
|
DeviceOwner string `json:"device_owner,omitempty"`
|
||||||
|
SecurityGroups *[]string `json:"security_groups,omitempty"`
|
||||||
|
AllowedAddressPairs *[]AddressPair `json:"allowed_address_pairs,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToPortUpdateMap builds a request body from UpdateOpts.
|
||||||
|
func (opts UpdateOpts) ToPortUpdateMap() (map[string]interface{}, error) {
|
||||||
|
return gophercloud.BuildRequestBody(opts, "port")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update accepts a UpdateOpts struct and updates an existing port using the
|
||||||
|
// values provided.
|
||||||
|
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
|
||||||
|
b, err := opts.ToPortUpdateMap()
|
||||||
|
if err != nil {
|
||||||
|
r.Err = err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, r.Err = c.Put(updateURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
|
||||||
|
OkCodes: []int{200, 201},
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete accepts a unique ID and deletes the port associated with it.
|
||||||
|
func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) {
|
||||||
|
_, r.Err = c.Delete(deleteURL(c, id), nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// IDFromName is a convenience function that returns a port's ID,
|
||||||
|
// given its name.
|
||||||
|
func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) {
|
||||||
|
count := 0
|
||||||
|
id := ""
|
||||||
|
pages, err := List(client, nil).AllPages()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
all, err := ExtractPorts(pages)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, s := range all {
|
||||||
|
if s.Name == name {
|
||||||
|
count++
|
||||||
|
id = s.ID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch count {
|
||||||
|
case 0:
|
||||||
|
return "", gophercloud.ErrResourceNotFound{Name: name, ResourceType: "port"}
|
||||||
|
case 1:
|
||||||
|
return id, nil
|
||||||
|
default:
|
||||||
|
return "", gophercloud.ErrMultipleResourcesFound{Name: name, Count: count, ResourceType: "port"}
|
||||||
|
}
|
||||||
|
}
|
||||||
140
vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/ports/results.go
generated
vendored
Normal file
140
vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/ports/results.go
generated
vendored
Normal file
|
|
@ -0,0 +1,140 @@
|
||||||
|
package ports
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gophercloud/gophercloud"
|
||||||
|
"github.com/gophercloud/gophercloud/pagination"
|
||||||
|
)
|
||||||
|
|
||||||
|
type commonResult struct {
|
||||||
|
gophercloud.Result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract is a function that accepts a result and extracts a port resource.
|
||||||
|
func (r commonResult) Extract() (*Port, error) {
|
||||||
|
var s Port
|
||||||
|
err := r.ExtractInto(&s)
|
||||||
|
return &s, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r commonResult) ExtractInto(v interface{}) error {
|
||||||
|
return r.Result.ExtractIntoStructPtr(v, "port")
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateResult represents the result of a create operation. Call its Extract
|
||||||
|
// method to interpret it as a Port.
|
||||||
|
type CreateResult struct {
|
||||||
|
commonResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetResult represents the result of a get operation. Call its Extract
|
||||||
|
// method to interpret it as a Port.
|
||||||
|
type GetResult struct {
|
||||||
|
commonResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateResult represents the result of an update operation. Call its Extract
|
||||||
|
// method to interpret it as a Port.
|
||||||
|
type UpdateResult struct {
|
||||||
|
commonResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteResult represents the result of a delete operation. Call its
|
||||||
|
// ExtractErr method to determine if the request succeeded or failed.
|
||||||
|
type DeleteResult struct {
|
||||||
|
gophercloud.ErrResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// IP is a sub-struct that represents an individual IP.
|
||||||
|
type IP struct {
|
||||||
|
SubnetID string `json:"subnet_id"`
|
||||||
|
IPAddress string `json:"ip_address,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddressPair contains the IP Address and the MAC address.
|
||||||
|
type AddressPair struct {
|
||||||
|
IPAddress string `json:"ip_address,omitempty"`
|
||||||
|
MACAddress string `json:"mac_address,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Port represents a Neutron port. See package documentation for a top-level
|
||||||
|
// description of what this is.
|
||||||
|
type Port struct {
|
||||||
|
// UUID for the port.
|
||||||
|
ID string `json:"id"`
|
||||||
|
|
||||||
|
// Network that this port is associated with.
|
||||||
|
NetworkID string `json:"network_id"`
|
||||||
|
|
||||||
|
// Human-readable name for the port. Might not be unique.
|
||||||
|
Name string `json:"name"`
|
||||||
|
|
||||||
|
// Administrative state of port. If false (down), port does not forward
|
||||||
|
// packets.
|
||||||
|
AdminStateUp bool `json:"admin_state_up"`
|
||||||
|
|
||||||
|
// Indicates whether network is currently operational. Possible values include
|
||||||
|
// `ACTIVE', `DOWN', `BUILD', or `ERROR'. Plug-ins might define additional
|
||||||
|
// values.
|
||||||
|
Status string `json:"status"`
|
||||||
|
|
||||||
|
// Mac address to use on this port.
|
||||||
|
MACAddress string `json:"mac_address"`
|
||||||
|
|
||||||
|
// Specifies IP addresses for the port thus associating the port itself with
|
||||||
|
// the subnets where the IP addresses are picked from
|
||||||
|
FixedIPs []IP `json:"fixed_ips"`
|
||||||
|
|
||||||
|
// Owner of network.
|
||||||
|
TenantID string `json:"tenant_id"`
|
||||||
|
|
||||||
|
// Identifies the entity (e.g.: dhcp agent) using this port.
|
||||||
|
DeviceOwner string `json:"device_owner"`
|
||||||
|
|
||||||
|
// Specifies the IDs of any security groups associated with a port.
|
||||||
|
SecurityGroups []string `json:"security_groups"`
|
||||||
|
|
||||||
|
// Identifies the device (e.g., virtual server) using this port.
|
||||||
|
DeviceID string `json:"device_id"`
|
||||||
|
|
||||||
|
// Identifies the list of IP addresses the port will recognize/accept
|
||||||
|
AllowedAddressPairs []AddressPair `json:"allowed_address_pairs"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PortPage is the page returned by a pager when traversing over a collection
|
||||||
|
// of network ports.
|
||||||
|
type PortPage struct {
|
||||||
|
pagination.LinkedPageBase
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextPageURL is invoked when a paginated collection of ports has reached
|
||||||
|
// the end of a page and the pager seeks to traverse over a new one. In order
|
||||||
|
// to do this, it needs to construct the next page's URL.
|
||||||
|
func (r PortPage) NextPageURL() (string, error) {
|
||||||
|
var s struct {
|
||||||
|
Links []gophercloud.Link `json:"ports_links"`
|
||||||
|
}
|
||||||
|
err := r.ExtractInto(&s)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return gophercloud.ExtractNextURL(s.Links)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsEmpty checks whether a PortPage struct is empty.
|
||||||
|
func (r PortPage) IsEmpty() (bool, error) {
|
||||||
|
is, err := ExtractPorts(r)
|
||||||
|
return len(is) == 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExtractPorts accepts a Page struct, specifically a PortPage struct,
|
||||||
|
// and extracts the elements into a slice of Port structs. In other words,
|
||||||
|
// a generic collection is mapped into a relevant slice.
|
||||||
|
func ExtractPorts(r pagination.Page) ([]Port, error) {
|
||||||
|
var s []Port
|
||||||
|
err := ExtractPortsInto(r, &s)
|
||||||
|
return s, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExtractPortsInto(r pagination.Page, v interface{}) error {
|
||||||
|
return r.(PortPage).Result.ExtractIntoSlicePtr(v, "ports")
|
||||||
|
}
|
||||||
31
vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/ports/urls.go
generated
vendored
Normal file
31
vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/ports/urls.go
generated
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
package ports
|
||||||
|
|
||||||
|
import "github.com/gophercloud/gophercloud"
|
||||||
|
|
||||||
|
func resourceURL(c *gophercloud.ServiceClient, id string) string {
|
||||||
|
return c.ServiceURL("ports", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func rootURL(c *gophercloud.ServiceClient) string {
|
||||||
|
return c.ServiceURL("ports")
|
||||||
|
}
|
||||||
|
|
||||||
|
func listURL(c *gophercloud.ServiceClient) string {
|
||||||
|
return rootURL(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getURL(c *gophercloud.ServiceClient, id string) string {
|
||||||
|
return resourceURL(c, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func createURL(c *gophercloud.ServiceClient) string {
|
||||||
|
return rootURL(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateURL(c *gophercloud.ServiceClient, id string) string {
|
||||||
|
return resourceURL(c, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteURL(c *gophercloud.ServiceClient, id string) string {
|
||||||
|
return resourceURL(c, id)
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue