Skip to content

Commit 14d8df1

Browse files
committed
feat(storage/nvme): add get backend nvme path cmd
Signed-off-by: Artsiom Koltun <[email protected]>
1 parent a493c68 commit 14d8df1

File tree

6 files changed

+142
-0
lines changed

6 files changed

+142
-0
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,13 @@ alias dpu="docker run --rm --network host ghcr.io/opiproject/godpu:main"
9191
nvmf0=$(dpu storage create backend nvme controller --id nvmf0 --multipath disable)
9292
path0=$(dpu storage create backend nvme path tcp --controller "$nvmf0" --id path0 --ip "11.11.11.2" --port 4444 --nqn nqn.2016-06.io.spdk:cnode1 --hostnqn nqn.2014-08.org.nvmexpress:uuid:feb98abe-d51f-40c8-b348-2753f3571d3c)
9393
dpu storage get backend nvme controller --name $nvmf0
94+
dpu storage get backend nvme path --name $path0
9495

9596
# connect to local nvme/pcie ssd controller
9697
nvmf1=$(dpu storage create backend nvme controller --id nvmf1 --multipath disable)
9798
path1=$(dpu storage create backend nvme path pcie --controller "$nvmf1" --id path1 --bdf "0000:40:00.0")
9899
dpu storage get backend nvme controller --name $nvmf1
100+
dpu storage get backend nvme path --name $path1
99101

100102
# expose volume over nvme/tcp controller
101103
ss0=$(dpu storage create frontend nvme subsystem --id subsys0 --nqn "nqn.2022-09.io.spdk:opitest0")

cmd/storage/backend/backend.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ func newGetNvmeCommand() *cobra.Command {
109109
}
110110

111111
cmd.AddCommand(newGetNvmeControllerCommand())
112+
cmd.AddCommand(newGetNvmePathCommand())
112113

113114
return cmd
114115
}

cmd/storage/backend/nvme_path.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"github.com/opiproject/godpu/cmd/storage/common"
1212
backendclient "github.com/opiproject/godpu/storage/backend"
1313
"github.com/spf13/cobra"
14+
"google.golang.org/protobuf/encoding/protojson"
1415
)
1516

1617
func newCreateNvmePathCommand() *cobra.Command {
@@ -150,3 +151,37 @@ func newDeleteNvmePathCommand() *cobra.Command {
150151

151152
return cmd
152153
}
154+
155+
func newGetNvmePathCommand() *cobra.Command {
156+
name := ""
157+
cmd := &cobra.Command{
158+
Use: "path",
159+
Aliases: []string{"p"},
160+
Short: "Gets nvme path to an external nvme device",
161+
Args: cobra.NoArgs,
162+
Run: func(c *cobra.Command, _ []string) {
163+
addr, err := c.Flags().GetString(common.AddrCmdLineArg)
164+
cobra.CheckErr(err)
165+
166+
timeout, err := c.Flags().GetDuration(common.TimeoutCmdLineArg)
167+
cobra.CheckErr(err)
168+
169+
client, err := backendclient.New(addr)
170+
cobra.CheckErr(err)
171+
172+
ctx, cancel := context.WithTimeout(context.Background(), timeout)
173+
defer cancel()
174+
175+
ctrl, err := client.GetNvmePath(ctx, name)
176+
cobra.CheckErr(err)
177+
178+
common.PrintResponse(protojson.Format(ctrl))
179+
},
180+
}
181+
182+
cmd.Flags().StringVar(&name, "name", "", "name of path to get")
183+
184+
cobra.CheckErr(cmd.MarkFlagRequired("name"))
185+
186+
return cmd
187+
}

docker-compose.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ services:
187187
nvmf0=$$(/dpu storage create backend nvme controller --addr=opi-spdk-server:50051 --id nvmf0 --multipath failover) && \
188188
/dpu storage get backend nvme controller --addr=opi-spdk-server:50051 --name "$$nvmf0" && \
189189
path0=$$(/dpu storage create backend nvme path tcp --addr=opi-spdk-server:50051 --controller "$$nvmf0" --id path0 --ip $$(getent hosts spdk | cut -d" " -f1) --port 4444 --nqn nqn.2016-06.io.spdk:cnode1 --hostnqn nqn.2014-08.org.nvmexpress:uuid:feb98abe-d51f-40c8-b348-2753f3571d3c) && \
190+
/dpu storage get backend nvme path --addr=opi-spdk-server:50051 --name "$$path0" && \
190191
ss0=$$(/dpu storage create frontend nvme subsystem --addr=opi-spdk-server:50051 --id subsys0 --nqn "nqn.2022-09.io.spdk:opitest1") && \
191192
ctrl0=$$(/dpu storage create frontend nvme controller tcp --addr=opi-spdk-server:50051 --id ctrl0 --ip "127.0.0.1" --port 4420 --subsystem "$$ss0") && \
192193
ns0=$$(/dpu storage create frontend nvme namespace --addr=opi-spdk-server:50051 --id namespace0 --volume "Malloc0" --subsystem "$$ss0") && \

storage/backend/nvme_path.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,3 +108,22 @@ func (c *Client) DeleteNvmePath(
108108

109109
return err
110110
}
111+
112+
// GetNvmePath gets an nvme path to an external nvme controller
113+
func (c *Client) GetNvmePath(
114+
ctx context.Context,
115+
name string,
116+
) (*pb.NvmePath, error) {
117+
conn, connClose, err := c.connector.NewConn()
118+
if err != nil {
119+
return nil, err
120+
}
121+
defer connClose()
122+
123+
client := c.createNvmeClient(conn)
124+
return client.GetNvmePath(
125+
ctx,
126+
&pb.GetNvmePathRequest{
127+
Name: name,
128+
})
129+
}

storage/backend/nvme_path_test.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,3 +316,87 @@ func TestDeleteNvmePath(t *testing.T) {
316316
})
317317
}
318318
}
319+
320+
func TestGetNvmePath(t *testing.T) {
321+
testPathName := "pathget"
322+
testRequest := &pb.GetNvmePathRequest{
323+
Name: testPathName,
324+
}
325+
testPath := &pb.NvmePath{
326+
Name: testPathName,
327+
Trtype: pb.NvmeTransportType_NVME_TRANSPORT_TYPE_TCP,
328+
Traddr: "127.0.0.1",
329+
Fabrics: &pb.FabricsPath{
330+
Trsvcid: 4420,
331+
Subnqn: "nqn.2019-06.io.spdk:8",
332+
Adrfam: pb.NvmeAddressFamily_NVME_ADDRESS_FAMILY_IPV4,
333+
},
334+
}
335+
tests := map[string]struct {
336+
giveClientErr error
337+
giveConnectorErr error
338+
wantErr error
339+
wantRequest *pb.GetNvmePathRequest
340+
wantResponse *pb.NvmePath
341+
wantConnClosed bool
342+
}{
343+
"successful call": {
344+
giveConnectorErr: nil,
345+
giveClientErr: nil,
346+
wantErr: nil,
347+
wantRequest: proto.Clone(testRequest).(*pb.GetNvmePathRequest),
348+
wantResponse: proto.Clone(testPath).(*pb.NvmePath),
349+
wantConnClosed: true,
350+
},
351+
"client err": {
352+
giveConnectorErr: nil,
353+
giveClientErr: errors.New("Some client error"),
354+
wantErr: errors.New("Some client error"),
355+
wantRequest: proto.Clone(testRequest).(*pb.GetNvmePathRequest),
356+
wantResponse: nil,
357+
wantConnClosed: true,
358+
},
359+
"connector err": {
360+
giveConnectorErr: errors.New("Some conn error"),
361+
giveClientErr: nil,
362+
wantErr: errors.New("Some conn error"),
363+
wantRequest: nil,
364+
wantResponse: nil,
365+
wantConnClosed: false,
366+
},
367+
}
368+
369+
for testName, tt := range tests {
370+
t.Run(testName, func(t *testing.T) {
371+
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
372+
defer cancel()
373+
374+
mockClient := mocks.NewNvmeRemoteControllerServiceClient(t)
375+
if tt.wantRequest != nil {
376+
mockClient.EXPECT().GetNvmePath(ctx, tt.wantRequest).
377+
Return(proto.Clone(tt.wantResponse).(*pb.NvmePath), tt.giveClientErr)
378+
}
379+
380+
connClosed := false
381+
mockConn := mocks.NewConnector(t)
382+
mockConn.EXPECT().NewConn().Return(
383+
&grpc.ClientConn{},
384+
func() { connClosed = true },
385+
tt.giveConnectorErr,
386+
)
387+
388+
c, _ := NewWithArgs(
389+
mockConn,
390+
func(grpc.ClientConnInterface) pb.NvmeRemoteControllerServiceClient {
391+
return mockClient
392+
},
393+
)
394+
395+
response, err := c.GetNvmePath(ctx, testPathName)
396+
397+
require.Equal(t, tt.wantErr, err)
398+
require.True(t, proto.Equal(tt.wantResponse, response))
399+
require.Equal(t, tt.wantConnClosed, connClosed)
400+
})
401+
}
402+
}

0 commit comments

Comments
 (0)