Skip to content

Commit

Permalink
add share network support for openstack
Browse files Browse the repository at this point in the history
  • Loading branch information
kon-angelo committed Feb 2, 2024
1 parent 93e90a7 commit e02e36f
Show file tree
Hide file tree
Showing 10 changed files with 145 additions and 77 deletions.
7 changes: 6 additions & 1 deletion pkg/controller/infrastructure/actuator_reconcile.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,12 @@ func computeProviderStatusFromFlowState(state *infraflow.PersistentState) (*open
status.Networks.Router.IP = shared.ValidValue(state.Data[infraflow.RouterIP])
status.Networks.FloatingPool.ID = shared.ValidValue(state.Data[infraflow.IdentifierFloatingNetwork])
status.Networks.FloatingPool.Name = shared.ValidValue(state.Data[infraflow.NameFloatingNetwork])
status.Networks.ShareNetwork.ID = shared.ValidValue(state.Data[infraflow.IdentifierShareNetwork])
if v := shared.ValidValue(state.Data[infraflow.IdentifierShareNetwork]); v != "" {
status.Networks.ShareNetwork = &openstackv1alpha1.ShareNetworkStatus{
ID: v,
Name: shared.ValidValue(state.Data[infraflow.NameShareNetwork]),
}
}

subnetID := shared.ValidValue(state.Data[infraflow.IdentifierSubnet])
if subnetID != "" {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import (
"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/subnets"
"github.com/gophercloud/gophercloud/openstack/sharedfilesystems/v2/sharenetworks"

"github.com/gardener/gardener-extension-provider-openstack/pkg/openstack/client"
)
Expand Down Expand Up @@ -62,10 +61,6 @@ type NetworkingAccess interface {
GetSecurityGroupByID(id string) (*groups.SecGroup, error)
GetSecurityGroupByName(name string) ([]*groups.SecGroup, error)
UpdateSecurityGroupRules(group *groups.SecGroup, desiredRules []rules.SecGroupRule, allowDelete func(rule *rules.SecGroupRule) bool) (modified bool, err error)

// Share
CreateShareNetwork(desired *sharenetworks.ShareNetwork) (*sharenetworks.ShareNetwork, error)
GetShareNetworkByName(name string) ([]*sharenetworks.ShareNetwork, error)
}

// Router is a simplified router resource
Expand Down Expand Up @@ -523,34 +518,3 @@ func (a *networkingAccess) findMatchingRule(rule *rules.SecGroupRule, desiredRul
}
return nil, false
}

// CreateShareNetwork creates a share network.
func (a *networkingAccess) CreateShareNetwork(desired *sharenetworks.ShareNetwork) (*sharenetworks.ShareNetwork, error) {
shareNetwork, err := a.networking.CreateShareNetwork(sharenetworks.CreateOpts{
NeutronNetID: desired.NeutronNetID,
NeutronSubnetID: desired.NeutronSubnetID,
Name: desired.Name,
Description: fmt.Sprintf("share network for shoot %s", desired.Name),
})
if err != nil {
return nil, err
}
return shareNetwork, nil
}

// GetShareNetworkByName retrieves a share network by the name.
func (a *networkingAccess) GetShareNetworkByName(name string) ([]*sharenetworks.ShareNetwork, error) {
list, err := a.networking.ListShareNetworks(sharenetworks.ListOpts{
Name: name,
})
if err != nil {
return nil, err
}

var result []*sharenetworks.ShareNetwork
for _, sn := range list {
result = append(result, &sn)
}

return result, nil
}
8 changes: 8 additions & 0 deletions pkg/controller/infrastructure/infraflow/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ const (
NameKeyPair = "KeyPair"
// NameSecGroup is the name of the security group
NameSecGroup = "SecurityGroupName"
// NameShareNetwork is the name of the shared network
NameShareNetwork = "ShareNetworkName"

// RouterIP is the key for the router IP address
RouterIP = "RouterIP"
Expand All @@ -74,6 +76,7 @@ type FlowContext struct {
cloudProfileConfig *openstackapi.CloudProfileConfig
networking osclient.Networking
loadbalancing osclient.Loadbalancing
sharedFilesystem osclient.SharedFilesystem
access access.NetworkingAccess
compute osclient.Compute
}
Expand Down Expand Up @@ -105,6 +108,10 @@ func NewFlowContext(log logr.Logger, clientFactory osclient.Factory,
if err != nil {
return nil, err
}
sharedFilesytem, err := clientFactory.SharedFilesystem(osclient.WithRegion(infra.Spec.Region))
if err != nil {
return nil, err
}

flowContext := &FlowContext{
BasicFlowContext: *shared.NewBasicFlowContext(log, whiteboard, persistor),
Expand All @@ -117,6 +124,7 @@ func NewFlowContext(log logr.Logger, clientFactory osclient.Factory,
loadbalancing: loadbalancing,
access: access,
compute: compute,
sharedFilesystem: sharedFilesytem,
}
return flowContext, nil
}
Expand Down
37 changes: 37 additions & 0 deletions pkg/controller/infrastructure/infraflow/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import (
"context"

"github.com/gardener/gardener/pkg/utils/flow"
"github.com/gophercloud/gophercloud/openstack/sharedfilesystems/v2/sharenetworks"
"k8s.io/utils/pointer"

. "github.com/gardener/gardener-extension-provider-openstack/pkg/controller/infrastructure/infraflow/shared"
"github.com/gardener/gardener-extension-provider-openstack/pkg/internal/infrastructure"
Expand Down Expand Up @@ -76,6 +78,9 @@ func (c *FlowContext) buildDeleteGraph() *flow.Graph {
Timeout(defaultTimeout),
)

_ = c.AddTask(g, "delete share network",
c.deleteShareNetwork,
Timeout(defaultTimeout), Dependencies(recoverSubnetID))
deleteRouterInterface := c.AddTask(g, "delete router interface",
c.deleteRouterInterface,
Timeout(defaultTimeout), Dependencies(recoverRouterID, recoverSubnetID, k8sRoutes))
Expand Down Expand Up @@ -231,3 +236,35 @@ func (c *FlowContext) deleteSSHKeyPair(ctx context.Context) error {
}
return nil
}

func (c *FlowContext) deleteShareNetwork(ctx context.Context) error {
log := c.LogFromContext(ctx)
networkID := pointer.StringDeref(c.state.Get(IdentifierNetwork), "")
subnetID := pointer.StringDeref(c.state.Get(IdentifierSubnet), "")
current, err := findExisting(c.state.Get(IdentifierShareNetwork),
c.namespace,
noopFinder[sharenetworks.ShareNetwork],
func(name string) ([]*sharenetworks.ShareNetwork, error) {
list, err := c.sharedFilesystem.ListShareNetworks(sharenetworks.ListOpts{
AllTenants: false,
NeutronNetID: networkID,
NeutronSubnetID: subnetID,
})
if err != nil {
return nil, err
}
return sliceToPtr(list), nil
})
if err != nil {
return err
}
if current != nil {
log.Info("deleting...", "securityGroup", current.ID)
if err := c.sharedFilesystem.DeleteShareNetwork(current.ID); err != nil {
return err
}
}
c.state.Set(IdentifierNetwork, "")
c.state.Set(NameShareNetwork, "")
return nil
}
33 changes: 18 additions & 15 deletions pkg/controller/infrastructure/infraflow/reconcile.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules"
"github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
"github.com/gophercloud/gophercloud/openstack/sharedfilesystems/v2/sharenetworks"
"k8s.io/utils/pointer"

"github.com/gardener/gardener-extension-provider-openstack/pkg/apis/openstack/helper"
"github.com/gardener/gardener-extension-provider-openstack/pkg/controller/infrastructure/infraflow/access"
Expand Down Expand Up @@ -464,23 +465,21 @@ func (c *FlowContext) ensureSSHKeyPair(ctx context.Context) error {

func (c *FlowContext) ensureShareNetwork(ctx context.Context) error {
log := c.LogFromContext(ctx)
networkID := *c.state.Get(IdentifierNetwork)
subnetID := *c.state.Get(IdentifierSubnet)
desired := &sharenetworks.ShareNetwork{
Name: c.namespace,
NeutronNetID: networkID,
NeutronSubnetID: subnetID,
}

networkID := pointer.StringDeref(c.state.Get(IdentifierNetwork), "")
subnetID := pointer.StringDeref(c.state.Get(IdentifierSubnet), "")
current, err := findExisting(c.state.Get(IdentifierShareNetwork),
c.namespace,
noopFinder[sharenetworks.ShareNetwork],
c.access.GetShareNetworkByName,
func(item *sharenetworks.ShareNetwork) bool {
if item.NeutronSubnetID == networkID && item.NeutronSubnetID == subnetID {
return true
func(name string) ([]*sharenetworks.ShareNetwork, error) {
list, err := c.sharedFilesystem.ListShareNetworks(sharenetworks.ListOpts{
Name: name,
NeutronNetID: networkID,
NeutronSubnetID: subnetID,
})
if err != nil {
return nil, err
}
return false
return sliceToPtr(list), nil
})

if err != nil {
Expand All @@ -492,11 +491,15 @@ func (c *FlowContext) ensureShareNetwork(ctx context.Context) error {
}

log.Info("creating...")
created, err := c.access.CreateShareNetwork(desired)
created, err := c.sharedFilesystem.CreateShareNetwork(sharenetworks.CreateOpts{
NeutronNetID: networkID,
NeutronSubnetID: subnetID,
Name: c.namespace,
})
if err != nil {
return err
}
c.state.Set(IdentifierShareNetwork, created.ID)
c.state.Set(NameShareNetwork, created.Name)
return nil

}
8 changes: 8 additions & 0 deletions pkg/controller/infrastructure/infraflow/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,11 @@ func copyMap(src map[string]string) map[string]string {
}
return dst
}

func sliceToPtr[T any](slice []T) []*T {
res := make([]*T, len(slice))
for _, t := range slice {
res = append(res, &t)
}
return res
}
16 changes: 16 additions & 0 deletions pkg/openstack/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,23 @@ func (oc *OpenstackClientFactory) Loadbalancing(options ...Option) (Loadbalancin
return &LoadbalancingClient{
client: client,
}, nil
}

// SharedFilesystem creates a new Manila client.
func (oc *OpenstackClientFactory) SharedFilesystem(options ...Option) (SharedFilesystem, error) {
eo := gophercloud.EndpointOpts{}
for _, opt := range options {
eo = opt(eo)
}

client, err := openstack.NewSharedFileSystemV2(oc.providerClient, eo)
if err != nil {
return nil, err
}

return &SharedFilesystemClient{
client: client,
}, nil
}

// IsNotFoundError checks if an error returned by OpenStack is caused by HTTP 404 status code.
Expand Down
20 changes: 0 additions & 20 deletions pkg/openstack/client/networking.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import (
"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/sharedfilesystems/v2/sharenetworks"
"k8s.io/utils/pointer"
)

Expand Down Expand Up @@ -290,22 +289,3 @@ func (c *NetworkingClient) GetRouterInterfacePort(routerID, subnetID string) (*p
}
return &list[0], nil
}

// CreateShareNetwork creates the share network.
func (c *NetworkingClient) CreateShareNetwork(createOpts sharenetworks.CreateOpts) (*sharenetworks.ShareNetwork, error) {
return sharenetworks.Create(c.client, createOpts).Extract()
}

// ListShareNetworks returns a list of subnets
func (c *NetworkingClient) ListShareNetworks(listOpts sharenetworks.ListOpts) ([]sharenetworks.ShareNetwork, error) {
page, err := sharenetworks.ListDetail(c.client, listOpts).AllPages()
if err != nil {
return nil, err
}
return sharenetworks.ExtractShareNetworks(page)
}

// DeleteShareNetwork deletes a subnet by identifier
func (c *NetworkingClient) DeleteShareNetwork(id string) error {
return sharenetworks.Delete(c.client, id).ExtractErr()
}
38 changes: 38 additions & 0 deletions pkg/openstack/client/sharedfilesystem.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) 2024 SAP SE or an SAP affiliate company. All rights reserved. This file is licensed under the Apache Software License, v. 2 except as noted otherwise in the LICENSE file
//
// 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 client

import (
"github.com/gophercloud/gophercloud/openstack/sharedfilesystems/v2/sharenetworks"
)

// CreateShareNetwork creates the share network.
func (c *SharedFilesystemClient) CreateShareNetwork(createOpts sharenetworks.CreateOpts) (*sharenetworks.ShareNetwork, error) {
return sharenetworks.Create(c.client, createOpts).Extract()
}

// ListShareNetworks returns a list of subnets
func (c *SharedFilesystemClient) ListShareNetworks(listOpts sharenetworks.ListOpts) ([]sharenetworks.ShareNetwork, error) {
page, err := sharenetworks.ListDetail(c.client, listOpts).AllPages()
if err != nil {
return nil, err
}
return sharenetworks.ExtractShareNetworks(page)
}

// DeleteShareNetwork deletes a subnet by identifier
func (c *SharedFilesystemClient) DeleteShareNetwork(id string) error {
return sharenetworks.Delete(c.client, id).ExtractErr()
}
19 changes: 14 additions & 5 deletions pkg/openstack/client/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ type LoadbalancingClient struct {
client *gophercloud.ServiceClient
}

// SharedFilesystemClient is a client for Manila service.
type SharedFilesystemClient struct {
client *gophercloud.ServiceClient
}

// Option can be passed to Factory implementations to modify the produced clients.
type Option func(opts gophercloud.EndpointOpts) gophercloud.EndpointOpts

Expand All @@ -77,6 +82,7 @@ type Factory interface {
DNS(options ...Option) (DNS, error)
Networking(options ...Option) (Networking, error)
Loadbalancing(options ...Option) (Loadbalancing, error)
SharedFilesystem(options ...Option) (SharedFilesystem, error)
}

// Storage describes the operations of a client interacting with OpenStack's ObjectStorage service.
Expand Down Expand Up @@ -160,11 +166,6 @@ type Networking interface {
// Ports
GetPort(portID string) (*ports.Port, error)
GetRouterInterfacePort(routerID, subnetID string) (*ports.Port, error)

// Share Networks
CreateShareNetwork(createOpts sharenetworks.CreateOpts) (*sharenetworks.ShareNetwork, error)
ListShareNetworks(listOpts sharenetworks.ListOpts) ([]sharenetworks.ShareNetwork, error)
DeleteShareNetwork(id string) error
}

// Loadbalancing describes the operations of a client interacting with OpenStack's Octavia service.
Expand All @@ -174,6 +175,14 @@ type Loadbalancing interface {
GetLoadbalancer(id string) (*loadbalancers.LoadBalancer, error)
}

// SharedFilesystem describes operations for OpenStack's Manila service.
type SharedFilesystem interface {
// Share Networks
CreateShareNetwork(createOpts sharenetworks.CreateOpts) (*sharenetworks.ShareNetwork, error)
ListShareNetworks(listOpts sharenetworks.ListOpts) ([]sharenetworks.ShareNetwork, error)
DeleteShareNetwork(id string) error
}

// FactoryFactory creates instances of Factory.
type FactoryFactory interface {
// NewFactory creates a new instance of Factory for the given Openstack credentials.
Expand Down

0 comments on commit e02e36f

Please sign in to comment.