Skip to content

Commit

Permalink
Allow Trunk configuration at a Port level.
Browse files Browse the repository at this point in the history
Signed-off-by: Anwar Hassen <anwar.hassen@est.tech>
  • Loading branch information
Anwar Hassen committed Jul 28, 2021
1 parent 3fd8106 commit 2d3f1c0
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 20 deletions.
2 changes: 2 additions & 0 deletions api/v1alpha4/types.go
Expand Up @@ -130,6 +130,8 @@ type PortOpts struct {
ProjectID string `json:"projectId,omitempty"`
SecurityGroups *[]string `json:"securityGroups,omitempty"`
AllowedAddressPairs []AddressPair `json:"allowedAddressPairs,omitempty"`
// Enables and disables trunk at port level. If not provided, openStackMachine.Spec.Trunk is inherited.
Trunk *bool `json:"trunk,omitempty"`

// The ID of the host where the port is allocated
HostID string `json:"hostId,omitempty"`
Expand Down
5 changes: 5 additions & 0 deletions api/v1alpha4/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Expand Up @@ -1308,6 +1308,10 @@ spec:
type: array
tenantId:
type: string
trunk:
description: Enables and disables trunk at port level.
If not provided, openStackMachine.Spec.Trunk is inherited.
type: boolean
vnicType:
description: The virtual network interface card (vNIC)
type that is bound to the neutron port.
Expand Down Expand Up @@ -1743,6 +1747,10 @@ spec:
type: array
tenantId:
type: string
trunk:
description: Enables and disables trunk at port level.
If not provided, openStackMachine.Spec.Trunk is inherited.
type: boolean
vnicType:
description: The virtual network interface card (vNIC)
type that is bound to the neutron port.
Expand Down Expand Up @@ -2007,6 +2015,10 @@ spec:
type: array
tenantId:
type: string
trunk:
description: Enables and disables trunk at port level. If
not provided, openStackMachine.Spec.Trunk is inherited.
type: boolean
vnicType:
description: The virtual network interface card (vNIC) type
that is bound to the neutron port.
Expand Down Expand Up @@ -2183,6 +2195,10 @@ spec:
type: array
tenantId:
type: string
trunk:
description: Enables and disables trunk at port level. If
not provided, openStackMachine.Spec.Trunk is inherited.
type: boolean
vnicType:
description: The virtual network interface card (vNIC) type
that is bound to the neutron port.
Expand Down
Expand Up @@ -290,6 +290,11 @@ spec:
type: array
tenantId:
type: string
trunk:
description: Enables and disables trunk at port
level. If not provided, openStackMachine.Spec.Trunk
is inherited.
type: boolean
vnicType:
description: The virtual network interface card
(vNIC) type that is bound to the neutron port.
Expand Down
Expand Up @@ -599,6 +599,10 @@ spec:
type: array
tenantId:
type: string
trunk:
description: Enables and disables trunk at port level. If not
provided, openStackMachine.Spec.Trunk is inherited.
type: boolean
vnicType:
description: The virtual network interface card (vNIC) type
that is bound to the neutron port.
Expand Down
Expand Up @@ -547,6 +547,10 @@ spec:
type: array
tenantId:
type: string
trunk:
description: Enables and disables trunk at port level.
If not provided, openStackMachine.Spec.Trunk is inherited.
type: boolean
vnicType:
description: The virtual network interface card (vNIC)
type that is bound to the neutron port.
Expand Down
52 changes: 32 additions & 20 deletions pkg/cloud/services/compute/instance.go
Expand Up @@ -151,19 +151,24 @@ func (s *Service) constructNetworks(openStackCluster *infrav1.OpenStackCluster,
}
}
for i, port := range openStackMachine.Spec.Ports {
pOpts := &openStackMachine.Spec.Ports[i]
// No Trunk field specified for the port, inherits openStackMachine.Spec.Trunk.
if pOpts.Trunk == nil {
pOpts.Trunk = &openStackMachine.Spec.Trunk
}
if port.NetworkID != "" {
nets = append(nets, infrav1.Network{
ID: port.NetworkID,
Subnet: &infrav1.Subnet{},
PortOpts: &openStackMachine.Spec.Ports[i],
PortOpts: pOpts,
})
} else {
nets = append(nets, infrav1.Network{
ID: openStackCluster.Status.Network.ID,
Subnet: &infrav1.Subnet{
ID: openStackCluster.Status.Network.Subnet.ID,
},
PortOpts: &openStackMachine.Spec.Ports[i],
PortOpts: pOpts,
})
}
}
Expand All @@ -174,6 +179,9 @@ func (s *Service) constructNetworks(openStackCluster *infrav1.OpenStackCluster,
Subnet: &infrav1.Subnet{
ID: openStackCluster.Status.Network.Subnet.ID,
},
PortOpts: &infrav1.PortOpts{
Trunk: &openStackMachine.Spec.Trunk,
},
}}
}
return &nets, nil
Expand All @@ -187,24 +195,16 @@ func (s *Service) createInstance(eventObject runtime.Object, clusterName string,
if network.ID == "" {
return nil, fmt.Errorf("no network was found or provided. Please check your machine configuration and try again")
}

iTags := []string{}
if len(instance.Tags) > 0 {
iTags = instance.Tags
}
portName := getPortName(instance.Name, network.PortOpts, i)
port, err := s.getOrCreatePort(eventObject, clusterName, portName, network, instance.SecurityGroups)
port, err := s.getOrCreatePort(eventObject, clusterName, portName, network, instance.SecurityGroups, iTags)
if err != nil {
return nil, err
}

if instance.Trunk {
trunk, err := s.getOrCreateTrunk(eventObject, clusterName, instance.Name, port.ID)
if err != nil {
return nil, err
}

if err = s.replaceAllAttributesTags(eventObject, trunk.ID, instance.Tags); err != nil {
return nil, err
}
}

for _, fip := range port.FixedIPs {
if fip.SubnetID == instance.Subnet {
accessIPv4 = fip.IPAddress
Expand Down Expand Up @@ -423,7 +423,7 @@ func (s *Service) getServerNetworks(networkParams []infrav1.NetworkParam) ([]inf
return nets, nil
}

func (s *Service) getOrCreatePort(eventObject runtime.Object, clusterName string, portName string, net infrav1.Network, instanceSecurityGroups *[]string) (*ports.Port, error) {
func (s *Service) getOrCreatePort(eventObject runtime.Object, clusterName string, portName string, net infrav1.Network, instanceSecurityGroups *[]string, tags []string) (*ports.Port, error) {
mc := metrics.NewMetricPrometheusContext("port", "list")
allPages, err := ports.List(s.networkClient, ports.ListOpts{
Name: portName,
Expand Down Expand Up @@ -508,21 +508,33 @@ func (s *Service) getOrCreatePort(eventObject runtime.Object, clusterName string
}

record.Eventf(eventObject, "SuccessfulCreatePort", "Created port %s with id %s", port.Name, port.ID)

if *portOpts.Trunk {
trunkDescription := names.GetDescription(clusterName)
trunk, err := s.getOrCreateTrunk(eventObject, trunkDescription, port.Name, port.ID)
if err != nil {
return nil, err
}
if err = s.replaceAllAttributesTags(eventObject, trunk.ID, tags); err != nil {
return nil, err
}
}

return port, nil
}

func (s *Service) getOrCreateTrunk(eventObject runtime.Object, clusterName, trunkName, portID string) (*trunks.Trunk, error) {
func (s *Service) getOrCreateTrunk(eventObject runtime.Object, description, trunkName, portID string) (*trunks.Trunk, error) {
mc := metrics.NewMetricPrometheusContext("trunk", "list")
allPages, err := trunks.List(s.networkClient, trunks.ListOpts{
Name: trunkName,
PortID: portID,
}).AllPages()
if mc.ObserveRequest(err) != nil {
return nil, fmt.Errorf("searching for existing trunk for server: %v", err)
return nil, fmt.Errorf("searching for existing trunk for port: %v", err)
}
trunkList, err := trunks.ExtractTrunks(allPages)
if err != nil {
return nil, fmt.Errorf("searching for existing trunk for server: %v", err)
return nil, fmt.Errorf("searching for existing trunk for port: %v", err)
}

if len(trunkList) != 0 {
Expand All @@ -532,7 +544,7 @@ func (s *Service) getOrCreateTrunk(eventObject runtime.Object, clusterName, trun
trunkCreateOpts := trunks.CreateOpts{
Name: trunkName,
PortID: portID,
Description: names.GetDescription(clusterName),
Description: description,
}

mc = metrics.NewMetricPrometheusContext("trunk", "create")
Expand Down
29 changes: 29 additions & 0 deletions test/e2e/shared/openstack.go
Expand Up @@ -34,6 +34,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/keypairs"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
"github.com/gophercloud/gophercloud/openstack/imageservice/v2/images"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/trunks"
"github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
"github.com/gophercloud/utils/openstack/clientconfig"
. "github.com/onsi/ginkgo"
Expand Down Expand Up @@ -149,6 +150,34 @@ func DumpOpenStackPorts(e2eCtx *E2EContext, filter ports.ListOpts) (*[]ports.Por
return &portsList, nil
}

func DumpOpenStackTrunks(e2eCtx *E2EContext, filter ports.ListOpts) (*[]trunks.Trunk, error) {
providerClient, clientOpts, err := getProviderClient(e2eCtx)
if err != nil {
_, _ = fmt.Fprintf(GinkgoWriter, "error creating provider client: %s\n", err)
return nil, err
}

networkClient, err := openstack.NewNetworkV2(providerClient, gophercloud.EndpointOpts{
Region: clientOpts.RegionName,
})
if err != nil {
return nil, fmt.Errorf("error creating network client: %s", err)
}
portID := filter.ID
allPages, err := trunks.List(networkClient, trunks.ListOpts{
PortID: portID,
}).AllPages()
if err != nil {
return nil, fmt.Errorf("unable to list trunks: %v", err)
}
trunkList, err := trunks.ExtractTrunks(allPages)
if err != nil {
return nil, fmt.Errorf("unable to extract trunk: %v", err)
}

return &trunkList, nil
}

// getOpenStackServers gets all OpenStack servers at once, to save on DescribeInstances
// calls.
func getOpenStackServers(e2eCtx *E2EContext) (map[string]server, error) {
Expand Down

0 comments on commit 2d3f1c0

Please sign in to comment.