diff --git a/pkg/host/internal/bridge/ovs/ovs.go b/pkg/host/internal/bridge/ovs/ovs.go index 6d232b0fb..7ad8a3e8c 100644 --- a/pkg/host/internal/bridge/ovs/ovs.go +++ b/pkg/host/internal/bridge/ovs/ovs.go @@ -5,8 +5,10 @@ import ( "encoding/json" "errors" "fmt" + "os" "reflect" "sort" + "strings" "time" "github.com/google/uuid" @@ -17,6 +19,7 @@ import ( sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" ovsStorePkg "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/bridge/ovs/store" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" ) @@ -627,6 +630,35 @@ func updateMap(old, new map[string]string) map[string]string { return result } +// returns path for the OVDSB socket +// for unix sockets it is taking into account current FS root and possible symlinks +func getDBSocketPath() (string, error) { + if !strings.HasPrefix(vars.OVSDBSocketPath, "unix://") { + // no need to apply modifications to tcp sockets + return vars.OVSDBSocketPath, nil + } + origPathNoPrefix, _ := strings.CutPrefix(vars.OVSDBSocketPath, "unix://") + resolvedPath := utils.GetHostExtensionPath(origPathNoPrefix) + + // in some OSes /var/run is an absolute symlink to /run, + // this can be a problem when we are trying to access OVSDB socket from the daemon POD. + // first we a trying to use original path, if we can't find the OVSDB socket, + // we try to replace /var/run with /run in the socket path + var err error + _, err = os.Stat(resolvedPath) + if err != nil && !os.IsNotExist(err) { + return "", err + } + if os.IsNotExist(err) { + resolvedPath = strings.Replace(resolvedPath, "/var/run/", "/run/", 1) + _, err = os.Stat(resolvedPath) + if err != nil { + return "", err + } + } + return "unix://" + resolvedPath, nil +} + // initialize and return OVSDB client func getClient(ctx context.Context) (client.Client, error) { openvSwitchEntry := &OpenvSwitchEntry{} @@ -638,8 +670,13 @@ func getClient(ctx context.Context) (client.Client, error) { return nil, fmt.Errorf("can't create client DB model: %v", err) } + socketPath, err := getDBSocketPath() + if err != nil { + return nil, fmt.Errorf("can't find OVSDB socket %s: %v", vars.OVSDBSocketPath, err) + } + dbClient, err := client.NewOVSDBClient(clientDBModel, - client.WithEndpoint(vars.OVSDBSocketPath), + client.WithEndpoint(socketPath), client.WithLogger(&log.Log)) if err != nil { return nil, fmt.Errorf("can't create DB client: %v", err) diff --git a/pkg/host/internal/bridge/ovs/ovs_test.go b/pkg/host/internal/bridge/ovs/ovs_test.go index 039696672..666fe9218 100644 --- a/pkg/host/internal/bridge/ovs/ovs_test.go +++ b/pkg/host/internal/bridge/ovs/ovs_test.go @@ -22,6 +22,8 @@ import ( sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" ovsStoreMockPkg "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/bridge/ovs/store/mock" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" + "github.com/k8snetworkplumbingwg/sriov-network-operator/test/util/fakefilesystem" + "github.com/k8snetworkplumbingwg/sriov-network-operator/test/util/helpers" ) func getManagedBridges() map[string]*sriovnetworkv1.OVSConfigExt { @@ -162,6 +164,14 @@ var _ = Describe("OVS", func() { ) BeforeEach(func() { ctx = context.Background() + origInChroot := vars.InChroot + origSocketValue := vars.OVSDBSocketPath + origFSRoot := vars.FilesystemRoot + DeferCleanup(func() { + vars.InChroot = origInChroot + vars.OVSDBSocketPath = origSocketValue + vars.FilesystemRoot = origFSRoot + }) }) Context("setDefaultTimeout", func() { It("use default", func() { @@ -179,7 +189,7 @@ var _ = Describe("OVS", func() { timeoutCtx, timeoutFunc := context.WithTimeout(ctx, time.Millisecond*100) defer timeoutFunc() newCtx, _ := setDefaultTimeout(timeoutCtx) - time.Sleep(time.Millisecond * 200) + time.Sleep(time.Second) Expect(newCtx.Err()).To(MatchError(context.DeadlineExceeded)) }) It("use explicit timeout - should return noop cancel function", func() { @@ -212,6 +222,56 @@ var _ = Describe("OVS", func() { }) }) + Context("client", func() { + It("can't find socket", func() { + helpers.GinkgoConfigureFakeFS(&fakefilesystem.FS{}) + c, err := getClient(ctx) + Expect(c).To(BeNil()) + Expect(err).To(MatchError(ContainSubstring("can't find OVSDB socket"))) + }) + Context("getDBSocketPath()", func() { + It("tcp socket", func() { + vars.OVSDBSocketPath = "tcp://127.0.0.1:4444" + sock, err := getDBSocketPath() + Expect(err).NotTo(HaveOccurred()) + Expect(sock).To(Equal("tcp://127.0.0.1:4444")) + }) + It("unix socket - in container", func() { + helpers.GinkgoConfigureFakeFS(&fakefilesystem.FS{ + Dirs: []string{"/host/ovs"}, + Files: map[string][]byte{"/host/ovs/ovsdb.sock": {}}, + }) + vars.InChroot = false + vars.OVSDBSocketPath = "unix:///ovs/ovsdb.sock" + sock, err := getDBSocketPath() + Expect(err).NotTo(HaveOccurred()) + Expect(sock).To(Equal("unix://" + vars.FilesystemRoot + "/host/ovs/ovsdb.sock")) + }) + It("unix socket - host", func() { + helpers.GinkgoConfigureFakeFS(&fakefilesystem.FS{ + Dirs: []string{"/ovs"}, + Files: map[string][]byte{"/ovs/ovsdb.sock": {}}, + }) + vars.InChroot = true + vars.OVSDBSocketPath = "unix:///ovs/ovsdb.sock" + sock, err := getDBSocketPath() + Expect(err).NotTo(HaveOccurred()) + Expect(sock).To(Equal("unix://" + vars.FilesystemRoot + "/ovs/ovsdb.sock")) + }) + It("unix socket - alternative /var/run path", func() { + helpers.GinkgoConfigureFakeFS(&fakefilesystem.FS{ + Dirs: []string{"/host/run/ovs"}, + Files: map[string][]byte{"/host/run/ovs/ovsdb.sock": {}}, + }) + vars.InChroot = false + vars.OVSDBSocketPath = "unix:///var/run/ovs/ovsdb.sock" + sock, err := getDBSocketPath() + Expect(err).NotTo(HaveOccurred()) + Expect(sock).To(Equal("unix://" + vars.FilesystemRoot + "/host/run/ovs/ovsdb.sock")) + }) + }) + }) + Context("manage bridges", func() { var ( store *ovsStoreMockPkg.MockStore @@ -224,6 +284,7 @@ var _ = Describe("OVS", func() { ovs Interface ) BeforeEach(func() { + vars.InChroot = true tempDir, err = os.MkdirTemp("", "sriov-operator-ovs-test-dir*") testServerSocket = filepath.Join(tempDir, "ovsdb.sock") Expect(err).NotTo(HaveOccurred()) @@ -231,13 +292,7 @@ var _ = Describe("OVS", func() { store = ovsStoreMockPkg.NewMockStore(testCtrl) _ = store stopServerFunc = startServer("unix", testServerSocket) - - origSocketValue := vars.OVSDBSocketPath vars.OVSDBSocketPath = "unix://" + testServerSocket - DeferCleanup(func() { - vars.OVSDBSocketPath = origSocketValue - }) - ovsClient, err = getClient(ctx) Expect(err).NotTo(HaveOccurred()) ovs = New(store)