Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(storage): get backend nvme controller/path cmds #440

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,14 @@ alias dpu="docker run --rm --network host ghcr.io/opiproject/godpu:main"
# connect to remote nvme/tcp controller
nvmf0=$(dpu storage create backend nvme controller --id nvmf0 --multipath disable)
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)
dpu storage get backend nvme controller --name $nvmf0
dpu storage get backend nvme path --name $path0

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

# expose volume over nvme/tcp controller
ss0=$(dpu storage create frontend nvme subsystem --id subsys0 --nqn "nqn.2022-09.io.spdk:opitest0")
Expand Down
36 changes: 36 additions & 0 deletions cmd/storage/backend/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,39 @@

return cmd
}

// NewGetCommand creates a new command to get backend resources
func NewGetCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "backend",
Aliases: []string{"b"},
Short: "Gets backend resource",
Args: cobra.NoArgs,
Run: func(c *cobra.Command, _ []string) {
err := c.Help()
cobra.CheckErr(err)
},

Check warning on line 91 in cmd/storage/backend/backend.go

View check run for this annotation

Codecov / codecov/patch

cmd/storage/backend/backend.go#L82-L91

Added lines #L82 - L91 were not covered by tests
}

cmd.AddCommand(newGetNvmeCommand())

return cmd

Check warning on line 96 in cmd/storage/backend/backend.go

View check run for this annotation

Codecov / codecov/patch

cmd/storage/backend/backend.go#L94-L96

Added lines #L94 - L96 were not covered by tests
}

func newGetNvmeCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "nvme",
Aliases: []string{"n"},
Short: "Gets nvme resource",
Args: cobra.NoArgs,
Run: func(c *cobra.Command, _ []string) {
err := c.Help()
cobra.CheckErr(err)
},

Check warning on line 108 in cmd/storage/backend/backend.go

View check run for this annotation

Codecov / codecov/patch

cmd/storage/backend/backend.go#L99-L108

Added lines #L99 - L108 were not covered by tests
}

cmd.AddCommand(newGetNvmeControllerCommand())
cmd.AddCommand(newGetNvmePathCommand())

return cmd

Check warning on line 114 in cmd/storage/backend/backend.go

View check run for this annotation

Codecov / codecov/patch

cmd/storage/backend/backend.go#L111-L114

Added lines #L111 - L114 were not covered by tests
}
35 changes: 35 additions & 0 deletions cmd/storage/backend/nvme_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
backendclient "github.com/opiproject/godpu/storage/backend"
pb "github.com/opiproject/opi-api/storage/v1alpha1/gen/go"
"github.com/spf13/cobra"
"google.golang.org/protobuf/encoding/protojson"
)

func newCreateNvmeControllerCommand() *cobra.Command {
Expand Down Expand Up @@ -93,3 +94,37 @@

return cmd
}

func newGetNvmeControllerCommand() *cobra.Command {
name := ""
cmd := &cobra.Command{
Use: "controller",
Aliases: []string{"c"},
Short: "Gets nvme controller representing an external nvme device",
Args: cobra.NoArgs,
Run: func(c *cobra.Command, _ []string) {
addr, err := c.Flags().GetString(common.AddrCmdLineArg)
cobra.CheckErr(err)

timeout, err := c.Flags().GetDuration(common.TimeoutCmdLineArg)
cobra.CheckErr(err)

client, err := backendclient.New(addr)
cobra.CheckErr(err)

ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()

ctrl, err := client.GetNvmeController(ctx, name)
cobra.CheckErr(err)

common.PrintResponse(protojson.Format(ctrl))
},

Check warning on line 122 in cmd/storage/backend/nvme_controller.go

View check run for this annotation

Codecov / codecov/patch

cmd/storage/backend/nvme_controller.go#L98-L122

Added lines #L98 - L122 were not covered by tests
}

cmd.Flags().StringVar(&name, "name", "", "name of remote controller to get")

cobra.CheckErr(cmd.MarkFlagRequired("name"))

return cmd

Check warning on line 129 in cmd/storage/backend/nvme_controller.go

View check run for this annotation

Codecov / codecov/patch

cmd/storage/backend/nvme_controller.go#L125-L129

Added lines #L125 - L129 were not covered by tests
}
35 changes: 35 additions & 0 deletions cmd/storage/backend/nvme_path.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"github.com/opiproject/godpu/cmd/storage/common"
backendclient "github.com/opiproject/godpu/storage/backend"
"github.com/spf13/cobra"
"google.golang.org/protobuf/encoding/protojson"
)

func newCreateNvmePathCommand() *cobra.Command {
Expand Down Expand Up @@ -150,3 +151,37 @@

return cmd
}

func newGetNvmePathCommand() *cobra.Command {
name := ""
cmd := &cobra.Command{
Use: "path",
Aliases: []string{"p"},
Short: "Gets nvme path to an external nvme device",
Args: cobra.NoArgs,
Run: func(c *cobra.Command, _ []string) {
addr, err := c.Flags().GetString(common.AddrCmdLineArg)
cobra.CheckErr(err)

timeout, err := c.Flags().GetDuration(common.TimeoutCmdLineArg)
cobra.CheckErr(err)

client, err := backendclient.New(addr)
cobra.CheckErr(err)

ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()

ctrl, err := client.GetNvmePath(ctx, name)
cobra.CheckErr(err)

common.PrintResponse(protojson.Format(ctrl))
},

Check warning on line 179 in cmd/storage/backend/nvme_path.go

View check run for this annotation

Codecov / codecov/patch

cmd/storage/backend/nvme_path.go#L155-L179

Added lines #L155 - L179 were not covered by tests
}

cmd.Flags().StringVar(&name, "name", "", "name of path to get")

cobra.CheckErr(cmd.MarkFlagRequired("name"))

return cmd

Check warning on line 186 in cmd/storage/backend/nvme_path.go

View check run for this annotation

Codecov / codecov/patch

cmd/storage/backend/nvme_path.go#L182-L186

Added lines #L182 - L186 were not covered by tests
}
18 changes: 18 additions & 0 deletions cmd/storage/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

cmd.AddCommand(newStorageCreateCommand())
cmd.AddCommand(newStorageDeleteCommand())
cmd.AddCommand(newStorageGetCommand())

Check warning on line 35 in cmd/storage/storage.go

View check run for this annotation

Codecov / codecov/patch

cmd/storage/storage.go#L35

Added line #L35 was not covered by tests
cmd.AddCommand(newStorageTestCommand())

return cmd
Expand Down Expand Up @@ -72,3 +73,20 @@

return cmd
}

func newStorageGetCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "get",
Aliases: []string{"g"},
Short: "Gets resource",
Args: cobra.NoArgs,
Run: func(c *cobra.Command, _ []string) {
err := c.Help()
cobra.CheckErr(err)
},

Check warning on line 86 in cmd/storage/storage.go

View check run for this annotation

Codecov / codecov/patch

cmd/storage/storage.go#L77-L86

Added lines #L77 - L86 were not covered by tests
}

cmd.AddCommand(backend.NewGetCommand())

return cmd

Check warning on line 91 in cmd/storage/storage.go

View check run for this annotation

Codecov / codecov/patch

cmd/storage/storage.go#L89-L91

Added lines #L89 - L91 were not covered by tests
}
2 changes: 2 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,9 @@ services:
command: |
'/dpu storage test --addr opi-spdk-server:50051 && \
nvmf0=$$(/dpu storage create backend nvme controller --addr=opi-spdk-server:50051 --id nvmf0 --multipath failover) && \
/dpu storage get backend nvme controller --addr=opi-spdk-server:50051 --name "$$nvmf0" && \
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) && \
/dpu storage get backend nvme path --addr=opi-spdk-server:50051 --name "$$path0" && \
ss0=$$(/dpu storage create frontend nvme subsystem --addr=opi-spdk-server:50051 --id subsys0 --nqn "nqn.2022-09.io.spdk:opitest1") && \
ctrl0=$$(/dpu storage create frontend nvme controller tcp --addr=opi-spdk-server:50051 --id ctrl0 --ip "127.0.0.1" --port 4420 --subsystem "$$ss0") && \
ns0=$$(/dpu storage create frontend nvme namespace --addr=opi-spdk-server:50051 --id namespace0 --volume "Malloc0" --subsystem "$$ss0") && \
Expand Down
20 changes: 20 additions & 0 deletions storage/backend/nvme_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,23 @@ func (c *Client) DeleteNvmeController(

return err
}

// GetNvmeController gets an nvme controller representing
// an external nvme device
func (c *Client) GetNvmeController(
ctx context.Context,
name string,
) (*pb.NvmeRemoteController, error) {
conn, connClose, err := c.connector.NewConn()
if err != nil {
return nil, err
}
defer connClose()

client := c.createNvmeClient(conn)
return client.GetNvmeRemoteController(
ctx,
&pb.GetNvmeRemoteControllerRequest{
Name: name,
})
}
78 changes: 78 additions & 0 deletions storage/backend/nvme_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,3 +173,81 @@ func TestDeleteNvmeController(t *testing.T) {
})
}
}

func TestGetNvmeController(t *testing.T) {
testControllerName := "remotenvmeget"
testRequest := &pb.GetNvmeRemoteControllerRequest{
Name: testControllerName,
}
testController := &pb.NvmeRemoteController{
Name: testControllerName,
Multipath: pb.NvmeMultipath_NVME_MULTIPATH_FAILOVER,
}
tests := map[string]struct {
giveClientErr error
giveConnectorErr error
wantErr error
wantRequest *pb.GetNvmeRemoteControllerRequest
wantResponse *pb.NvmeRemoteController
wantConnClosed bool
}{
"successful call": {
giveConnectorErr: nil,
giveClientErr: nil,
wantErr: nil,
wantRequest: proto.Clone(testRequest).(*pb.GetNvmeRemoteControllerRequest),
wantResponse: proto.Clone(testController).(*pb.NvmeRemoteController),
wantConnClosed: true,
},
"client err": {
giveConnectorErr: nil,
giveClientErr: errors.New("Some client error"),
wantErr: errors.New("Some client error"),
wantRequest: proto.Clone(testRequest).(*pb.GetNvmeRemoteControllerRequest),
wantResponse: nil,
wantConnClosed: true,
},
"connector err": {
giveConnectorErr: errors.New("Some conn error"),
giveClientErr: nil,
wantErr: errors.New("Some conn error"),
wantRequest: nil,
wantResponse: nil,
wantConnClosed: false,
},
}

for testName, tt := range tests {
t.Run(testName, func(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()

mockClient := mocks.NewNvmeRemoteControllerServiceClient(t)
if tt.wantRequest != nil {
mockClient.EXPECT().GetNvmeRemoteController(ctx, tt.wantRequest).
Return(proto.Clone(tt.wantResponse).(*pb.NvmeRemoteController), tt.giveClientErr)
}

connClosed := false
mockConn := mocks.NewConnector(t)
mockConn.EXPECT().NewConn().Return(
&grpc.ClientConn{},
func() { connClosed = true },
tt.giveConnectorErr,
)

c, _ := NewWithArgs(
mockConn,
func(grpc.ClientConnInterface) pb.NvmeRemoteControllerServiceClient {
return mockClient
},
)

response, err := c.GetNvmeController(ctx, testControllerName)

require.Equal(t, tt.wantErr, err)
require.True(t, proto.Equal(tt.wantResponse, response))
require.Equal(t, tt.wantConnClosed, connClosed)
})
}
}
19 changes: 19 additions & 0 deletions storage/backend/nvme_path.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,22 @@ func (c *Client) DeleteNvmePath(

return err
}

// GetNvmePath gets an nvme path to an external nvme controller
func (c *Client) GetNvmePath(
ctx context.Context,
name string,
) (*pb.NvmePath, error) {
conn, connClose, err := c.connector.NewConn()
if err != nil {
return nil, err
}
defer connClose()

client := c.createNvmeClient(conn)
return client.GetNvmePath(
ctx,
&pb.GetNvmePathRequest{
Name: name,
})
}
Loading
Loading