From 43e1fda35abd73b955a830a3dcbdde87f5617bad Mon Sep 17 00:00:00 2001 From: Harish P Date: Fri, 11 Nov 2022 15:28:19 +0530 Subject: [PATCH] Added CreateNamespace RPC Signed-off-by: Harish P --- .github/workflows/linters.yml | 2 +- README.md | 1 + go.mod | 2 +- go.sum | 4 +- goopicsi.go | 134 +++++++++++++++++++++++++++++----- goopicsi_test.go | 35 ++++++--- 6 files changed, 145 insertions(+), 33 deletions(-) diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml index 2254866..297f95a 100644 --- a/.github/workflows/linters.yml +++ b/.github/workflows/linters.yml @@ -23,7 +23,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: hadolint/hadolint-action@v2.1.0 + - uses: hadolint/hadolint-action@v3.0.0 with: recursive: true ignore: DL3041 diff --git a/README.md b/README.md index 21eea39..6bff8b0 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ [![Go](https://github.com/opiproject/goopicsi/actions/workflows/go.yml/badge.svg)](https://github.com/opiproject/goopicsi/actions/workflows/go.yml) [![License](https://img.shields.io/github/license/opiproject/goopicsi?style=flat-square&color=blue&label=License)](https://github.com/opiproject/goopicsi/blob/master/LICENSE) [![codecov](https://codecov.io/gh/opiproject/goopicsi/branch/main/graph/badge.svg)](https://codecov.io/gh/opiproject/goopicsi) +[![Go Report Card](https://goreportcard.com/badge/github.com/opiproject/goopicsi)](https://goreportcard.com/report/github.com/opiproject/goopicsi) [![Last Release](https://img.shields.io/github/v/release/opiproject/goopicsi?label=Latest&style=flat-square&logo=go)](https://github.com/opiproject/goopicsi/releases) A Container Storage Interface (CSI) library, client, and other helpful utilities created with Go for OPI diff --git a/go.mod b/go.mod index d1d1a52..bdd96b4 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/opiproject/goopicsi go 1.19 require ( - github.com/opiproject/opi-api v0.0.0-20221109134843-76522ac45e89 + github.com/opiproject/opi-api v0.0.0-20221111230258-34e208409ec2 github.com/stretchr/testify v1.8.1 google.golang.org/grpc v1.50.1 ) diff --git a/go.sum b/go.sum index 55429c5..2535c40 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= -github.com/opiproject/opi-api v0.0.0-20221109134843-76522ac45e89 h1:yg9wTkuglnqdqMehhQ03o3FpYijUQrSvoWmtJq6+jHw= -github.com/opiproject/opi-api v0.0.0-20221109134843-76522ac45e89/go.mod h1:92pv4ulvvPMuxCJ9ND3aYbmBfEMLx0VCjpkiR7ZTqPY= +github.com/opiproject/opi-api v0.0.0-20221111230258-34e208409ec2 h1:AAgyJQOtuN5+PFajjhLZIVDfaTWZQ8t5u3tqTnK3nzE= +github.com/opiproject/opi-api v0.0.0-20221111230258-34e208409ec2/go.mod h1:92pv4ulvvPMuxCJ9ND3aYbmBfEMLx0VCjpkiR7ZTqPY= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= diff --git a/goopicsi.go b/goopicsi.go index 3e3d7c1..d3cb8fe 100644 --- a/goopicsi.go +++ b/goopicsi.go @@ -10,6 +10,7 @@ import ( "log" "time" + pbc "github.com/opiproject/opi-api/common/v1/gen/go" pb "github.com/opiproject/opi-api/storage/v1alpha1/gen/go" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" @@ -51,14 +52,23 @@ func ConnectToRemoteAndExpose(addr string) error { // Expose emulated NVMe device to the Host (Step 1: Subsystem) c1 := pb.NewFrontendNvmeServiceClient(conn) - rs1, err := c1.NVMeSubsystemCreate(ctx, &pb.NVMeSubsystemCreateRequest{Subsystem: &pb.NVMeSubsystem{Nqn: "OpiMalloc7"}}) + rs1, err := c1.CreateNVMeSubsystem(ctx, &pb.CreateNVMeSubsystemRequest{ + Subsystem: &pb.NVMeSubsystem{ + Spec: &pb.NVMeSubsystemSpec{ + Id: &pbc.ObjectKey{Value: "controller-test-ss"}, + Nqn: "nqn.2022-09.io.spdk:opi2"}}}) if err != nil { log.Printf("could not create NVMe subsystem: %v", err) return err } log.Printf("Added: %v", rs1) // Step2: NVMeController - rc1, err := c1.NVMeControllerCreate(ctx, &pb.NVMeControllerCreateRequest{Controller: &pb.NVMeController{NvmeControllerId: 13}}) + rc1, err := c1.CreateNVMeController(ctx, &pb.CreateNVMeControllerRequest{ + Controller: &pb.NVMeController{ + Spec: &pb.NVMeControllerSpec{ + Id: &pbc.ObjectKey{Value: "controller-test"}, + SubsystemId: &pbc.ObjectKey{Value: "controller-test-ss"}, + NvmeControllerId: 13}}}) if err != nil { log.Printf("could not create NVMe subsystem: %v", err) return err @@ -66,7 +76,14 @@ func ConnectToRemoteAndExpose(addr string) error { log.Printf("Added: %v", rc1) // NVMeNamespace - rn1, err := c1.NVMeNamespaceCreate(ctx, &pb.NVMeNamespaceCreateRequest{Namespace: &pb.NVMeNamespace{HostNsid: 123}}) + rn1, err := c1.CreateNVMeNamespace(ctx, &pb.CreateNVMeNamespaceRequest{ + Namespace: &pb.NVMeNamespace{ + Spec: &pb.NVMeNamespaceSpec{ + Id: &pbc.ObjectKey{Value: "namespace-test"}, + SubsystemId: &pbc.ObjectKey{Value: "namespace-test-ss"}, + ControllerId: &pbc.ObjectKey{Value: "namespace-test-ctrler"}, + VolumeId: &pbc.ObjectKey{Value: "Malloc1"}, + HostNsid: 123}}}) if err != nil { log.Printf("could not create NVMe subsystem: %v", err) return err @@ -76,11 +93,11 @@ func ConnectToRemoteAndExpose(addr string) error { } // NVMeControllerConnect Connects to remote NVMf controller -func NVMeControllerConnect(request *pb.NVMfRemoteController) (*pb.NVMfRemoteControllerConnectResponse, error) { +func NVMeControllerConnect(id int64, trAddr string, subnqn string, trSvcID int64) error { if conn == nil { err := dialConnection() if err != nil { - return nil, err + return err } } @@ -88,7 +105,7 @@ func NVMeControllerConnect(request *pb.NVMfRemoteController) (*pb.NVMfRemoteCont ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() - data, err := client.NVMfRemoteControllerGet(ctx, &pb.NVMfRemoteControllerGetRequest{Id: request.Id}) + data, err := client.NVMfRemoteControllerGet(ctx, &pb.NVMfRemoteControllerGetRequest{Id: id}) if err != nil { log.Println(err) } @@ -96,25 +113,75 @@ func NVMeControllerConnect(request *pb.NVMfRemoteController) (*pb.NVMfRemoteCont // we will connect if there is no connection established if data == nil { // This means we are unable to get a connection with this ID - response, err := client.NVMfRemoteControllerConnect(ctx, &pb.NVMfRemoteControllerConnectRequest{Ctrl: request}) + request := &pb.NVMfRemoteControllerConnectRequest{Ctrl: &pb.NVMfRemoteController{ + Id: id, + Traddr: trAddr, + Subnqn: subnqn, + Trsvcid: trSvcID, + }} + response, err := client.NVMfRemoteControllerConnect(ctx, request) if err != nil { log.Printf("could not connect to Remote NVMf controller: %v", err) - return nil, err + return err } log.Printf("Connected: %v", response) - return response, nil + return nil } log.Printf("Remote NVMf controller is already connected with SubNQN: %v", data.GetCtrl().Subnqn) defer disconnectConnection() - return &pb.NVMfRemoteControllerConnectResponse{}, nil + return nil +} + +// NVMeControllerList lists all the connections to the remote NVMf controller +func NVMeControllerList() error { + if conn == nil { + err := dialConnection() + if err != nil { + return err + } + } + + client := pb.NewNVMfRemoteControllerServiceClient(conn) + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + + response, err := client.NVMfRemoteControllerList(ctx, &pb.NVMfRemoteControllerListRequest{}) + if err != nil { + log.Printf("could not list the connections to Remote NVMf controller: %v", err) + return err + } + log.Printf("Connections: %v", response) + return nil +} + +// NVMeControllerGet lists the connection to the remote NVMf controller corresponding to the given ID +func NVMeControllerGet(id int64) error { + if conn == nil { + err := dialConnection() + if err != nil { + return err + } + } + + client := pb.NewNVMfRemoteControllerServiceClient(conn) + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + + response, err := client.NVMfRemoteControllerGet(ctx, &pb.NVMfRemoteControllerGetRequest{Id: id}) + if err != nil { + log.Printf("could not list the connection to Remote NVMf controller corresponding to the given ID: %v", err) + return err + } + log.Printf("Connection corresponding to the given ID: %v", response) + return nil } // NVMeControllerDisconnect disconnects remote NVMf controller connection -func NVMeControllerDisconnect(request *pb.NVMfRemoteControllerDisconnectRequest) (*pb.NVMfRemoteControllerDisconnectResponse, error) { +func NVMeControllerDisconnect(id int64) error { if conn == nil { err := dialConnection() if err != nil { - return nil, err + return err } } @@ -122,26 +189,57 @@ func NVMeControllerDisconnect(request *pb.NVMfRemoteControllerDisconnectRequest) ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() - data, err := client.NVMfRemoteControllerGet(ctx, &pb.NVMfRemoteControllerGetRequest{Id: request.Id}) + data, err := client.NVMfRemoteControllerGet(ctx, &pb.NVMfRemoteControllerGetRequest{Id: id}) if err != nil { log.Println(err) - return nil, err + return err } log.Println(data) // we will disconnect if there is a connection if data != nil { - response, err := client.NVMfRemoteControllerDisconnect(ctx, &pb.NVMfRemoteControllerDisconnectRequest{Id: request.Id}) + response, err := client.NVMfRemoteControllerDisconnect(ctx, &pb.NVMfRemoteControllerDisconnectRequest{Id: id}) if err != nil { log.Printf("could not disconnect Remote NVMf controller: %v", err) - return nil, err + return err } log.Printf("disconnected: %v", response) - return response, nil + return nil } log.Printf("Remote NVMf controller disconnected successfully: %v", data.GetCtrl().Subnqn) defer disconnectConnection() - return &pb.NVMfRemoteControllerDisconnectResponse{}, nil + return nil +} + +// CreateNVMeNamespace Creates a new NVMe namespace +func CreateNVMeNamespace(id string, subSystemID string, volumeID string, hostID int32) (string, error) { + if conn == nil { + err := dialConnection() + if err != nil { + return "", err + } + } + + client := pb.NewFrontendNvmeServiceClient(conn) + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + + resp, err := client.CreateNVMeNamespace(ctx, &pb.CreateNVMeNamespaceRequest{ + Namespace: &pb.NVMeNamespace{ + Spec: &pb.NVMeNamespaceSpec{ + Id: &pbc.ObjectKey{Value: id}, + SubsystemId: &pbc.ObjectKey{Value: subSystemID}, + VolumeId: &pbc.ObjectKey{Value: volumeID}, + HostNsid: hostID, + }, + }, + }) + if err != nil { + log.Println(err) + return "", err + } + log.Println(resp) + return resp.Spec.Id.Value, nil } func dialConnection() error { diff --git a/goopicsi_test.go b/goopicsi_test.go index 96b1986..2d02b95 100644 --- a/goopicsi_test.go +++ b/goopicsi_test.go @@ -7,29 +7,42 @@ import ( "log" "testing" - pb "github.com/opiproject/opi-api/storage/v1alpha1/gen/go" "github.com/stretchr/testify/assert" ) func TestNVMeControllerConnect(t *testing.T) { - resp, err := NVMeControllerConnect(&pb.NVMfRemoteController{ - Id: 12, - Traddr: "0.0.0.0", // Add a valid target address - Subnqn: "nqn", // Add a valid NQN - Trsvcid: 4420, - }) + err := NVMeControllerConnect(12, "", "", 44565) + if err != nil { + log.Println(err) + } + assert.Error(t, err) +} + +func TestNVMeControllerList(t *testing.T) { + err := NVMeControllerList() + if err != nil { + log.Println(err) + } +} + +func TestNVMeControllerGet(t *testing.T) { + err := NVMeControllerGet(12) if err != nil { log.Println(err) } - log.Println(resp) - assert.Error(t, err, "connection failed") } func TestNVMeControllerDisconnect(t *testing.T) { - resp, err := NVMeControllerDisconnect(&pb.NVMfRemoteControllerDisconnectRequest{Id: 12}) + err := NVMeControllerDisconnect(12) + if err != nil { + log.Println(err) + } +} + +func TestCreateNVMeNamespace(t *testing.T) { + resp, err := CreateNVMeNamespace("1", "nqn", "opi", 1) if err != nil { log.Println(err) } log.Println(resp) - assert.Error(t, err, "disconnect failed") }