Skip to content

Commit

Permalink
Merge pull request #585 from stgraber/ovn
Browse files Browse the repository at this point in the history
More OVSDB work
  • Loading branch information
hallyn committed Mar 6, 2024
2 parents 6ee49ff + 398504c commit 823db2f
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 35 deletions.
2 changes: 1 addition & 1 deletion cmd/incusd/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -2449,7 +2449,7 @@ func (d *Daemon) setupOVN() error {
}

// Get the OVN southbound address.
ovnSBAddr, err := vswitch.OVNSouthboundDBRemoteAddress()
ovnSBAddr, err := vswitch.GetOVNSouthboundDBRemoteAddress(d.shutdownCtx)
if err != nil {
return fmt.Errorf("Failed to get OVN southbound connection string: %w", err)
}
Expand Down
6 changes: 3 additions & 3 deletions internal/server/device/nic_ovn.go
Original file line number Diff line number Diff line change
Expand Up @@ -862,7 +862,7 @@ func (d *nicOVN) Stop() (*deviceConfig.RunConfig, error) {

var ovsExternalOVNPort string
if d.config["nested"] == "" {
ovsExternalOVNPort, err = vswitch.InterfaceAssociatedOVNSwitchPort(d.config["host_name"])
ovsExternalOVNPort, err = vswitch.GetInterfaceAssociatedOVNSwitchPort(context.TODO(), d.config["host_name"])
if err != nil {
d.logger.Warn("Could not find OVN Switch port associated to OVS interface", logger.Ctx{"interface": d.config["host_name"]})
}
Expand All @@ -884,7 +884,7 @@ func (d *nicOVN) Stop() (*deviceConfig.RunConfig, error) {
integrationBridge := d.state.GlobalConfig.NetworkOVNIntegrationBridge()

// Detach host-side end of veth pair from OVS integration bridge.
err = vswitch.BridgePortDelete(integrationBridge, integrationBridgeNICName)
err = vswitch.DeleteBridgePort(context.TODO(), integrationBridge, integrationBridgeNICName)
if err != nil {
// Don't fail here as we want the postStop hook to run to clean up the local veth pair.
d.logger.Error("Failed detaching interface from OVS integration bridge", logger.Ctx{"interface": integrationBridgeNICName, "bridge": integrationBridge, "err": err})
Expand Down Expand Up @@ -1166,7 +1166,7 @@ func (d *nicOVN) setupHostNIC(hostName string, ovnPortName ovn.OVNSwitchPort, up
return nil, err
}

revert.Add(func() { _ = vswitch.BridgePortDelete(integrationBridge, hostName) })
revert.Add(func() { _ = vswitch.DeleteBridgePort(context.TODO(), integrationBridge, hostName) })

// Link OVS port to OVN logical port.
err = vswitch.InterfaceAssociateOVNSwitchPort(hostName, string(ovnPortName))
Expand Down
2 changes: 1 addition & 1 deletion internal/server/network/network_utils_bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ func DetachInterface(bridgeName string, devName string) error {
return fmt.Errorf("Failed to connect to OVS: %w", err)
}

err = vswitch.BridgePortDelete(bridgeName, devName)
err = vswitch.DeleteBridgePort(context.TODO(), bridgeName, devName)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion internal/server/network/ovn/ovn_icsb.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
ovsdbClient "github.com/ovn-org/libovsdb/client"
ovsdbModel "github.com/ovn-org/libovsdb/model"

ovnICSB "github.com/lxc/incus/internal/server/network/ovn/schema/ovn-ic-nb"
ovnICSB "github.com/lxc/incus/internal/server/network/ovn/schema/ovn-ic-sb"
)

// ICSB client.
Expand Down
47 changes: 34 additions & 13 deletions internal/server/network/ovn/ovn_nb_actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ type OVNSwitchPortOpts struct {
Parent OVNSwitchPort // Optional, if set a nested port is created.
VLAN uint16 // Optional, use with Parent to request a specific VLAN for nested port.
Location string // Optional, use to indicate the name of the server this port is bound to.
RouterPort string // Optional, the name of the associated logical router port.
}

// OVNACLRule represents an ACL rule that can be added to a logical switch or port group.
Expand Down Expand Up @@ -348,6 +349,20 @@ func (o *NB) LogicalRouterRouteDelete(routerName OVNRouter, prefixes ...net.IPNe
return nil
}

// GetLogicalRouterPort gets the OVN database record for the logical router port.
func (o *NB) GetLogicalRouterPort(ctx context.Context, portName OVNRouterPort) (*ovnNB.LogicalRouterPort, error) {
logicalRouterPort := &ovnNB.LogicalRouterPort{
Name: string(portName),
}

err := o.get(ctx, logicalRouterPort)
if err != nil {
return nil, err
}

return logicalRouterPort, nil
}

// CreateLogicalRouterPort adds a named logical router port to a logical router.
func (o *NB) CreateLogicalRouterPort(ctx context.Context, routerName OVNRouter, portName OVNRouterPort, mac net.HardwareAddr, gatewayMTU uint32, ipAddr []*net.IPNet, haChassisGroupName OVNChassisGroup, mayExist bool) error {
// Prepare the addresses.
Expand Down Expand Up @@ -1205,21 +1220,27 @@ func (o *NB) CreateLogicalSwitchPort(ctx context.Context, switchName OVNSwitch,
logicalSwitchPort.Tag = &tag
}

ipStr := make([]string, 0, len(opts.IPs))
for _, ip := range opts.IPs {
ipStr = append(ipStr, ip.String())
}

var addresses string
if opts.MAC != nil && len(ipStr) > 0 {
addresses = fmt.Sprintf("%s %s", opts.MAC.String(), strings.Join(ipStr, " "))
} else if opts.MAC != nil && len(ipStr) <= 0 {
addresses = fmt.Sprintf("%s %s", opts.MAC.String(), "dynamic")
if opts.RouterPort != "" {
logicalSwitchPort.Type = "router"
logicalSwitchPort.Addresses = []string{"router"}
logicalSwitchPort.Options = map[string]string{"router-port": opts.RouterPort}
} else {
addresses = "dynamic"
}
ipStr := make([]string, 0, len(opts.IPs))
for _, ip := range opts.IPs {
ipStr = append(ipStr, ip.String())
}

logicalSwitchPort.Addresses = []string{addresses}
var addresses string
if opts.MAC != nil && len(ipStr) > 0 {
addresses = fmt.Sprintf("%s %s", opts.MAC.String(), strings.Join(ipStr, " "))
} else if opts.MAC != nil && len(ipStr) <= 0 {
addresses = fmt.Sprintf("%s %s", opts.MAC.String(), "dynamic")
} else {
addresses = "dynamic"
}

logicalSwitchPort.Addresses = []string{addresses}
}

if opts.DHCPv4OptsID != "" {
dhcp4opts := string(opts.DHCPv4OptsID)
Expand Down
87 changes: 71 additions & 16 deletions internal/server/network/ovs/ovs_actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,9 +250,56 @@ func (o *VSwitch) CreateBridgePort(ctx context.Context, bridgeName string, portN
return nil
}

// BridgePortDelete deletes a port from the bridge (if already detached does nothing).
func (o *VSwitch) BridgePortDelete(bridgeName string, portName string) error {
_, err := subprocess.RunCommand("ovs-vsctl", "--if-exists", "del-port", bridgeName, portName)
// DeleteBridgePort deletes a port from the bridge (if already detached does nothing).
func (o *VSwitch) DeleteBridgePort(ctx context.Context, bridgeName string, portName string) error {
operations := []ovsdb.Operation{}

// Get the bridge port.
bridgePort := ovsSwitch.Port{
Name: string(portName),
}

err := o.client.Get(ctx, &bridgePort)
if err != nil {
// Logical switch port is already gone.
if err == ErrNotFound {
return nil
}

return err
}

// Remove the port from the bridge.
bridge := ovsSwitch.Bridge{
Name: string(bridgeName),
}

updateOps, err := o.client.Where(&bridge).Mutate(&bridge, ovsdbModel.Mutation{
Field: &bridge.Ports,
Mutator: ovsdb.MutateOperationDelete,
Value: []string{bridgePort.UUID},
})
if err != nil {
return err
}

operations = append(operations, updateOps...)

// Delete the port itself.
deleteOps, err := o.client.Where(&bridgePort).Delete()
if err != nil {
return err
}

operations = append(operations, deleteOps...)

// Apply the changes.
resp, err := o.client.Transact(ctx, operations...)
if err != nil {
return err
}

_, err = ovsdb.CheckOperationResults(resp, operations)
if err != nil {
return err
}
Expand Down Expand Up @@ -303,18 +350,25 @@ func (o *VSwitch) InterfaceAssociateOVNSwitchPort(interfaceName string, ovnSwitc
return nil
}

// InterfaceAssociatedOVNSwitchPort returns the OVN switch port associated to the interface.
func (o *VSwitch) InterfaceAssociatedOVNSwitchPort(interfaceName string) (string, error) {
ovnSwitchPort, err := subprocess.RunCommand("ovs-vsctl", "get", "interface", interfaceName, "external_ids:iface-id")
// GetInterfaceAssociatedOVNSwitchPort returns the OVN switch port associated to the interface.
func (o *VSwitch) GetInterfaceAssociatedOVNSwitchPort(ctx context.Context, interfaceName string) (string, error) {
// Get the OVS interface.
ovsInterface := ovsSwitch.Interface{
Name: interfaceName,
}

err := o.client.Get(ctx, &ovsInterface)
if err != nil {
return "", err
}

return strings.TrimSpace(ovnSwitchPort), nil
// Return the iface-id.
return ovsInterface.ExternalIDs["iface-id"], nil
}

// GetChassisID returns the local chassis ID.
func (o *VSwitch) GetChassisID(ctx context.Context) (string, error) {
// Get the root switch.
vSwitch := &ovsSwitch.OpenvSwitch{
UUID: o.rootUUID,
}
Expand All @@ -324,8 +378,8 @@ func (o *VSwitch) GetChassisID(ctx context.Context) (string, error) {
return "", err
}

val := vSwitch.ExternalIDs["system-id"]
return val, nil
// Return the system-id.
return vSwitch.ExternalIDs["system-id"], nil
}

// OVNEncapIP returns the enscapsulation IP used for OVN underlay tunnels.
Expand Down Expand Up @@ -484,17 +538,18 @@ func (o *VSwitch) HardwareOffloadingEnabled() bool {
return offload == "true"
}

// OVNSouthboundDBRemoteAddress gets the address of the southbound ovn database.
func (o *VSwitch) OVNSouthboundDBRemoteAddress() (string, error) {
result, err := subprocess.RunCommand("ovs-vsctl", "get", "open_vswitch", ".", "external_ids:ovn-remote")
if err != nil {
return "", err
// GetOVNSouthboundDBRemoteAddress gets the address of the southbound ovn database.
func (o *VSwitch) GetOVNSouthboundDBRemoteAddress(ctx context.Context) (string, error) {
vSwitch := &ovsSwitch.OpenvSwitch{
UUID: o.rootUUID,
}

addr, err := unquote(strings.TrimSuffix(result, "\n"))
err := o.client.Get(ctx, vSwitch)
if err != nil {
return "", err
}

return addr, nil
val := vSwitch.ExternalIDs["ovn-remote"]

return val, nil
}

0 comments on commit 823db2f

Please sign in to comment.