diff --git a/lxd/network/openvswitch/ovn.go b/lxd/network/openvswitch/ovn.go index d15d50825311..7d2155b26861 100644 --- a/lxd/network/openvswitch/ovn.go +++ b/lxd/network/openvswitch/ovn.go @@ -302,7 +302,17 @@ func (o *OVN) xbctl(southbound bool, extraArgs ...string) (string, error) { } if strings.HasPrefix(dbAddr, "unix:") { - dbAddr = fmt.Sprintf("unix:%s", shared.HostPathFollow(strings.TrimPrefix(dbAddr, "unix:"))) + targetPath, _ := os.Readlink("/run/openvswitch") + if MicroovnTargetChassisPath.MatchString(targetPath) { + // If using MicroOVN, then we need to use the microovn socket. + if cmd == "ovn-nbctl" { + dbAddr = "unix:/var/snap/microovn/common/run/ovn/ovnnb_db.sock" + } else { + dbAddr = "unix:/var/snap/microovn/common/run/ovn/ovnsb_db.sock" + } + } else { + dbAddr = fmt.Sprintf("unix:%s", shared.HostPathFollow(strings.TrimPrefix(dbAddr, "unix:"))) + } } // Figure out args. diff --git a/lxd/network/openvswitch/ovs.go b/lxd/network/openvswitch/ovs.go index 06bf54d09d7d..2f7cd90bcb7c 100644 --- a/lxd/network/openvswitch/ovs.go +++ b/lxd/network/openvswitch/ovs.go @@ -43,7 +43,8 @@ func (o *OVS) Installed() bool { // BridgeExists returns true if OVS bridge exists. func (o *OVS) BridgeExists(bridgeName string) (bool, error) { - _, err := shared.RunCommand("ovs-vsctl", "br-exists", bridgeName) + v, args := vsctl("br-exists", bridgeName) + _, err := shared.RunCommand(v, args...) if err != nil { runErr, ok := err.(shared.RunError) if ok { @@ -79,7 +80,8 @@ func (o *OVS) BridgeAdd(bridgeName string, mayExist bool, hwaddr net.HardwareAdd args = append(args, "--", "set", "int", bridgeName, fmt.Sprintf(`mtu_request=%d`, mtu)) } - _, err := shared.RunCommand("ovs-vsctl", args...) + v, args := vsctl(args...) + _, err := shared.RunCommand(v, args...) if err != nil { return err } @@ -89,7 +91,8 @@ func (o *OVS) BridgeAdd(bridgeName string, mayExist bool, hwaddr net.HardwareAdd // BridgeDelete deletes an OVS bridge. func (o *OVS) BridgeDelete(bridgeName string) error { - _, err := shared.RunCommand("ovs-vsctl", "del-br", bridgeName) + v, args := vsctl("del-br", bridgeName) + _, err := shared.RunCommand(v, args...) if err != nil { return err } @@ -105,9 +108,8 @@ func (o *OVS) BridgePortAdd(bridgeName string, portName string, mayExist bool) e args = append(args, "--may-exist") } - args = append(args, "add-port", bridgeName, portName) - - _, err := shared.RunCommand("ovs-vsctl", args...) + v, args := vsctl(append(args, "add-port", bridgeName, portName)...) + _, err := shared.RunCommand(v, args...) if err != nil { return err } @@ -117,7 +119,8 @@ func (o *OVS) BridgePortAdd(bridgeName string, portName string, mayExist bool) e // BridgePortDelete deletes a port from the bridge (if already detached does nothing). func (o *OVS) BridgePortDelete(bridgeName string, portName string) error { - _, err := shared.RunCommand("ovs-vsctl", "--if-exists", "del-port", bridgeName, portName) + v, args := vsctl("--if-exists", "del-port", bridgeName, portName) + _, err := shared.RunCommand(v, args...) if err != nil { return err } @@ -127,7 +130,8 @@ func (o *OVS) BridgePortDelete(bridgeName string, portName string) error { // BridgePortSet sets port options. func (o *OVS) BridgePortSet(portName string, options ...string) error { - _, err := shared.RunCommand("ovs-vsctl", append([]string{"set", "port", portName}, options...)...) + v, args := vsctl(append([]string{"set", "port", portName}, options...)...) + _, err := shared.RunCommand(v, args...) if err != nil { return err } @@ -139,15 +143,17 @@ func (o *OVS) BridgePortSet(portName string, options ...string) error { // and then associates the specified interfaceName to the OVN switch port. func (o *OVS) InterfaceAssociateOVNSwitchPort(interfaceName string, ovnSwitchPortName OVNSwitchPort) error { // Clear existing ports that were formerly associated to ovnSwitchPortName. - existingPorts, err := shared.RunCommand("ovs-vsctl", "--format=csv", "--no-headings", "--data=bare", "--colum=name", "find", "interface", fmt.Sprintf("external-ids:iface-id=%s", string(ovnSwitchPortName))) + v, args := vsctl("--format=csv", "--no-headings", "--data=bare", "--colum=name", "find", "interface", fmt.Sprintf("external-ids:iface-id=%s", string(ovnSwitchPortName))) + existingPorts, err := shared.RunCommand(v, args...) if err != nil { return err } existingPorts = strings.TrimSpace(existingPorts) if existingPorts != "" { + v, args := vsctl("del-port") for _, port := range strings.Split(existingPorts, "\n") { - _, err = shared.RunCommand("ovs-vsctl", "del-port", port) + _, err = shared.RunCommand(v, append(args, port)...) if err != nil { return err } @@ -160,7 +166,8 @@ func (o *OVS) InterfaceAssociateOVNSwitchPort(interfaceName string, ovnSwitchPor } } - _, err = shared.RunCommand("ovs-vsctl", "set", "interface", interfaceName, fmt.Sprintf("external_ids:iface-id=%s", string(ovnSwitchPortName))) + v, args = vsctl("set", "interface", interfaceName, fmt.Sprintf("external_ids:iface-id=%s", string(ovnSwitchPortName))) + _, err = shared.RunCommand(v, args...) if err != nil { return err } @@ -170,7 +177,8 @@ func (o *OVS) InterfaceAssociateOVNSwitchPort(interfaceName string, ovnSwitchPor // InterfaceAssociatedOVNSwitchPort returns the OVN switch port associated to the OVS interface. func (o *OVS) InterfaceAssociatedOVNSwitchPort(interfaceName string) (OVNSwitchPort, error) { - ovnSwitchPort, err := shared.RunCommand("ovs-vsctl", "get", "interface", interfaceName, "external_ids:iface-id") + v, args := vsctl("get", "interface", interfaceName, "external_ids:iface-id") + ovnSwitchPort, err := shared.RunCommand(v, args...) if err != nil { return "", err } @@ -184,7 +192,8 @@ func (o *OVS) ChassisID() (string, error) { // However ovs-vsctl's find and list commands don't support retrieving a single column's map field. // And ovs-vsctl's JSON output is unfriendly towards statically typed languages as it mixes data types // in a slice. So stick with "get" command and use Go's strconv.Unquote to return the actual values. - chassisID, err := shared.RunCommand("ovs-vsctl", "get", "open_vswitch", ".", "external_ids:system-id") + v, args := vsctl("get", "open_vswitch", ".", "external_ids:system-id") + chassisID, err := shared.RunCommand(v, args...) if err != nil { return "", err } @@ -204,7 +213,8 @@ func (o *OVS) OVNEncapIP() (net.IP, error) { // However ovs-vsctl's find and list commands don't support retrieving a single column's map field. // And ovs-vsctl's JSON output is unfriendly towards statically typed languages as it mixes data types // in a slice. So stick with "get" command and use Go's strconv.Unquote to return the actual values. - encapIPStr, err := shared.RunCommand("ovs-vsctl", "get", "open_vswitch", ".", "external_ids:ovn-encap-ip") + v, args := vsctl("get", "open_vswitch", ".", "external_ids:ovn-encap-ip") + encapIPStr, err := shared.RunCommand(v, args...) if err != nil { return nil, err } @@ -229,7 +239,8 @@ func (o *OVS) OVNBridgeMappings(bridgeName string) ([]string, error) { // However ovs-vsctl's find and list commands don't support retrieving a single column's map field. // And ovs-vsctl's JSON output is unfriendly towards statically typed languages as it mixes data types // in a slice. So stick with "get" command and use Go's strconv.Unquote to return the actual values. - mappings, err := shared.RunCommand("ovs-vsctl", "--if-exists", "get", "open_vswitch", ".", "external-ids:ovn-bridge-mappings") + v, args := vsctl("--if-exists", "get", "open_vswitch", ".", "external-ids:ovn-bridge-mappings") + mappings, err := shared.RunCommand(v, args...) if err != nil { return nil, err } @@ -267,7 +278,8 @@ func (o *OVS) OVNBridgeMappingAdd(bridgeName string, providerName string) error mappings = append(mappings, newMapping) // Set new mapping string back into OVS database. - _, err = shared.RunCommand("ovs-vsctl", "set", "open_vswitch", ".", fmt.Sprintf("external-ids:ovn-bridge-mappings=%s", strings.Join(mappings, ","))) + v, args := vsctl("set", "open_vswitch", ".", fmt.Sprintf("external-ids:ovn-bridge-mappings=%s", strings.Join(mappings, ","))) + _, err = shared.RunCommand(v, args...) if err != nil { return err } @@ -299,13 +311,15 @@ func (o *OVS) OVNBridgeMappingDelete(bridgeName string, providerName string) err if changed { if len(newMappings) < 1 { // Remove mapping key in OVS database. - _, err = shared.RunCommand("ovs-vsctl", "remove", "open_vswitch", ".", "external-ids", "ovn-bridge-mappings") + v, args := vsctl("remove", "open_vswitch", ".", "external-ids", "ovn-bridge-mappings") + _, err = shared.RunCommand(v, args...) if err != nil { return err } } else { // Set updated mapping string back into OVS database. - _, err = shared.RunCommand("ovs-vsctl", "set", "open_vswitch", ".", fmt.Sprintf("external-ids:ovn-bridge-mappings=%s", strings.Join(newMappings, ","))) + v, args := vsctl("set", "open_vswitch", ".", fmt.Sprintf("external-ids:ovn-bridge-mappings=%s", strings.Join(newMappings, ","))) + _, err = shared.RunCommand(v, args...) if err != nil { return err } @@ -318,7 +332,8 @@ func (o *OVS) OVNBridgeMappingDelete(bridgeName string, providerName string) err // BridgePortList returns a list of ports that are connected to the bridge. func (o *OVS) BridgePortList(bridgeName string) ([]string, error) { // Clear existing ports that were formerly associated to ovnSwitchPortName. - portString, err := shared.RunCommand("ovs-vsctl", "list-ports", bridgeName) + v, args := vsctl("list-ports", bridgeName) + portString, err := shared.RunCommand(v, args...) if err != nil { return nil, err } @@ -341,7 +356,8 @@ func (o *OVS) HardwareOffloadingEnabled() bool { // However ovs-vsctl's find and list commands don't support retrieving a single column's map field. // And ovs-vsctl's JSON output is unfriendly towards statically typed languages as it mixes data types // in a slice. So stick with "get" command and use Go's strconv.Unquote to return the actual values. - offload, err := shared.RunCommand("ovs-vsctl", "--if-exists", "get", "open_vswitch", ".", "other_config:hw-offload") + v, args := vsctl("--if-exists", "get", "open_vswitch", ".", "other_config:hw-offload") + offload, err := shared.RunCommand(v, args...) if err != nil { return false } @@ -361,7 +377,8 @@ func (o *OVS) HardwareOffloadingEnabled() bool { // OVNSouthboundDBRemoteAddress gets the address of the southbound ovn database. func (o *OVS) OVNSouthboundDBRemoteAddress() (string, error) { - result, err := shared.RunCommand("ovs-vsctl", "get", "open_vswitch", ".", "external_ids:ovn-remote") + v, args := vsctl("get", "open_vswitch", ".", "external_ids:ovn-remote") + result, err := shared.RunCommand(v, args...) if err != nil { return "", err }