Skip to content

Commit

Permalink
Provide initial MEV NVMe implementation.
Browse files Browse the repository at this point in the history
This patch provides support for NVMe device creation/deletion
for MEV and leverage the existing functionality of opi-spdk-bridge
to handle subsystem/namespace related requests.

Signed-off-by: Artsiom Koltun <[email protected]>
  • Loading branch information
artek-koltun committed Mar 6, 2023
1 parent 09d175b commit b727593
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 326 deletions.
336 changes: 10 additions & 326 deletions pkg/frontend/frontend.go
Original file line number Diff line number Diff line change
@@ -1,347 +1,31 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2022 Dell Inc, or its subsidiaries.
// Copyright (C) 2023 Intel Corporation

// Package frontend implememnts the FrontEnd APIs (host facing) of the storage Server
// Package frontend implements the FrontEnd APIs (host facing) of the storage Server
package frontend

import (
"context"
"fmt"
"log"

pc "github.com/opiproject/opi-api/common/v1/gen/go"
pb "github.com/opiproject/opi-api/storage/v1alpha1/gen/go"
"github.com/opiproject/opi-spdk-bridge/pkg/frontend"
"github.com/opiproject/opi-spdk-bridge/pkg/server"

"github.com/ulule/deepcopier"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/emptypb"
)

// Server contains frontend related OPI services
type Server struct {
pb.UnimplementedFrontendNvmeServiceServer
Subsystems map[string]*pb.NVMeSubsystem
Controllers map[string]*pb.NVMeController
Namespaces map[string]*pb.NVMeNamespace
pb.FrontendNvmeServiceServer

rpc server.JSONRPC
nvme *frontend.NvmeParameters
rpc server.JSONRPC
}

// NewServer creates initialized instance of NVMe server
func NewServer(jsonRPC server.JSONRPC) *Server {
opiSpdkServer := frontend.NewServerWithJSONRPC(jsonRPC)
return &Server{
Subsystems: make(map[string]*pb.NVMeSubsystem),
Controllers: make(map[string]*pb.NVMeController),
Namespaces: make(map[string]*pb.NVMeNamespace),

rpc: jsonRPC,
}
}

// CreateNVMeSubsystem creates an NVMe Subsystem
func (s *Server) CreateNVMeSubsystem(ctx context.Context, in *pb.CreateNVMeSubsystemRequest) (*pb.NVMeSubsystem, error) {
log.Printf("CreateNVMeSubsystem: Received from client: %v", in)
// TODO
response := &pb.NVMeSubsystem{}
err := deepcopier.Copy(in.NvMeSubsystem).To(response)
if err != nil {
log.Printf("error: %v", err)
return nil, err
}
response.Status = &pb.NVMeSubsystemStatus{FirmwareRevision: "TBD"}
s.Subsystems[in.NvMeSubsystem.Spec.Id.Value] = response
return response, nil
}

// DeleteNVMeSubsystem deletes an NVMe Subsystem
func (s *Server) DeleteNVMeSubsystem(ctx context.Context, in *pb.DeleteNVMeSubsystemRequest) (*emptypb.Empty, error) {
log.Printf("DeleteNVMeSubsystem: Received from client: %v", in)
subsys, ok := s.Subsystems[in.Name]
if !ok {
err := fmt.Errorf("unable to find key %s", in.Name)
log.Printf("error: %v", err)
return nil, err
}
// TODO
delete(s.Subsystems, subsys.Spec.Id.Value)
return &emptypb.Empty{}, nil
}

// UpdateNVMeSubsystem updates an NVMe Subsystem
func (s *Server) UpdateNVMeSubsystem(ctx context.Context, in *pb.UpdateNVMeSubsystemRequest) (*pb.NVMeSubsystem, error) {
log.Printf("UpdateNVMeSubsystem: Received from client: %v", in)
return nil, status.Errorf(codes.Unimplemented, "UpdateNVMeSubsystem method is not implemented")
}

// ListNVMeSubsystems lists NVMe Subsystems
func (s *Server) ListNVMeSubsystems(ctx context.Context, in *pb.ListNVMeSubsystemsRequest) (*pb.ListNVMeSubsystemsResponse, error) {
log.Printf("ListNVMeSubsystems: Received from client: %v", in)
// TODO
Blobarray := make([]*pb.NVMeSubsystem, 3)
return &pb.ListNVMeSubsystemsResponse{NvMeSubsystems: Blobarray}, nil
}

// GetNVMeSubsystem gets NVMe Subsystems
func (s *Server) GetNVMeSubsystem(ctx context.Context, in *pb.GetNVMeSubsystemRequest) (*pb.NVMeSubsystem, error) {
log.Printf("GetNVMeSubsystem: Received from client: %v", in)
subsys, ok := s.Subsystems[in.Name]
if !ok {
err := fmt.Errorf("unable to find key %s", in.Name)
log.Printf("error: %v", err)
return nil, err
}
// TODO
msg := fmt.Sprintf("Could not find NQN: %s", subsys.Spec.Nqn)
log.Print(msg)
return nil, status.Errorf(codes.InvalidArgument, msg)
}

// NVMeSubsystemStats gets NVMe Subsystem stats
func (s *Server) NVMeSubsystemStats(ctx context.Context, in *pb.NVMeSubsystemStatsRequest) (*pb.NVMeSubsystemStatsResponse, error) {
log.Printf("NVMeSubsystemStats: Received from client: %v", in)
subsys, ok := s.Subsystems[in.SubsystemId.Value]
if !ok {
err := fmt.Errorf("unable to find key %s", in.SubsystemId.Value)
log.Printf("error: %v", err)
return nil, err
}
log.Printf("Found: %s", subsys.Spec.Nqn)
// TODO
return &pb.NVMeSubsystemStatsResponse{Stats: &pb.VolumeStats{ReadOpsCount: -1, WriteOpsCount: -1}}, nil
}

// CreateNVMeController creates an NVMe controller
func (s *Server) CreateNVMeController(ctx context.Context, in *pb.CreateNVMeControllerRequest) (*pb.NVMeController, error) {
log.Printf("CreateNVMeController: Received from client: %v", in)
subsys, ok := s.Subsystems[in.NvMeController.Spec.SubsystemId.Value]
if !ok {
err := fmt.Errorf("unable to find key %s", in.NvMeController.Spec.SubsystemId.Value)
log.Printf("error: %v", err)
return nil, err
}
log.Printf("Found: %s", subsys.Spec.Nqn)
// TODO
s.Controllers[in.NvMeController.Spec.Id.Value] = in.NvMeController
s.Controllers[in.NvMeController.Spec.Id.Value].Spec.NvmeControllerId = 22
s.Controllers[in.NvMeController.Spec.Id.Value].Status = &pb.NVMeControllerStatus{Active: true}
response := &pb.NVMeController{Spec: &pb.NVMeControllerSpec{Id: &pc.ObjectKey{Value: "TBD"}}}
err := deepcopier.Copy(in.NvMeController).To(response)
if err != nil {
log.Printf("error: %v", err)
return nil, err
}
return response, nil
}

// DeleteNVMeController deletes an NVMe controller
func (s *Server) DeleteNVMeController(ctx context.Context, in *pb.DeleteNVMeControllerRequest) (*emptypb.Empty, error) {
log.Printf("DeleteNVMeController: Received from client: %v", in)
controller, ok := s.Controllers[in.Name]
if !ok {
return nil, fmt.Errorf("error finding controller %s", in.Name)
}
subsys, ok := s.Subsystems[controller.Spec.SubsystemId.Value]
if !ok {
err := fmt.Errorf("unable to find key %s", controller.Spec.SubsystemId.Value)
log.Printf("error: %v", err)
return nil, err
}
log.Printf("Found: %s", subsys.Spec.Nqn)
// TODO
delete(s.Controllers, controller.Spec.Id.Value)
return &emptypb.Empty{}, nil
}

// UpdateNVMeController updates an NVMe controller
func (s *Server) UpdateNVMeController(ctx context.Context, in *pb.UpdateNVMeControllerRequest) (*pb.NVMeController, error) {
log.Printf("UpdateNVMeController: Received from client: %v", in)
subsys, ok := s.Subsystems[in.NvMeController.Spec.SubsystemId.Value]
if !ok {
err := fmt.Errorf("unable to find key %s", in.NvMeController.Spec.SubsystemId.Value)
log.Printf("error: %v", err)
return nil, err
}
log.Printf("Found: %s", subsys.Spec.Nqn)
// TODO
s.Controllers[in.NvMeController.Spec.Id.Value] = in.NvMeController
s.Controllers[in.NvMeController.Spec.Id.Value].Spec.NvmeControllerId = 22
s.Controllers[in.NvMeController.Spec.Id.Value].Status = &pb.NVMeControllerStatus{Active: true}
response := &pb.NVMeController{}
err := deepcopier.Copy(in.NvMeController).To(response)
if err != nil {
log.Printf("error: %v", err)
return nil, err
}
return response, nil
}

// ListNVMeControllers lists NVMe controllers
func (s *Server) ListNVMeControllers(ctx context.Context, in *pb.ListNVMeControllersRequest) (*pb.ListNVMeControllersResponse, error) {
log.Printf("ListNVMeControllers: Received from client: %v", in)
subsys, ok := s.Subsystems[in.Parent]
if !ok {
err := fmt.Errorf("unable to find key %s", in.Parent)
log.Printf("error: %v", err)
return nil, err
}
log.Printf("Found: %s", subsys.Spec.Nqn)
// TODO
Blobarray := make([]*pb.NVMeController, 3)
return &pb.ListNVMeControllersResponse{NvMeControllers: Blobarray}, nil
}

// GetNVMeController gets an NVMe controller
func (s *Server) GetNVMeController(ctx context.Context, in *pb.GetNVMeControllerRequest) (*pb.NVMeController, error) {
log.Printf("GetNVMeController: Received from client: %v", in)
controller, ok := s.Controllers[in.Name]
if !ok {
return nil, fmt.Errorf("error finding controller %s", in.Name)
}
subsys, ok := s.Subsystems[controller.Spec.SubsystemId.Value]
if !ok {
err := fmt.Errorf("unable to find key %s", controller.Spec.SubsystemId.Value)
log.Printf("error: %v", err)
return nil, err
}
log.Printf("Found: %s", subsys.Spec.Nqn)
// TODO
return &pb.NVMeController{Spec: &pb.NVMeControllerSpec{Id: &pc.ObjectKey{Value: in.Name}, NvmeControllerId: controller.Spec.NvmeControllerId}, Status: &pb.NVMeControllerStatus{Active: true}}, nil
}

// NVMeControllerStats gets an NVMe controller stats
func (s *Server) NVMeControllerStats(ctx context.Context, in *pb.NVMeControllerStatsRequest) (*pb.NVMeControllerStatsResponse, error) {
log.Printf("NVMeControllerStats: Received from client: %v", in)
controller, ok := s.Controllers[in.Id.Value]
if !ok {
return nil, fmt.Errorf("error finding controller %s", in.Id.Value)
}
subsys, ok := s.Subsystems[controller.Spec.SubsystemId.Value]
if !ok {
err := fmt.Errorf("unable to find key %s", controller.Spec.SubsystemId.Value)
log.Printf("error: %v", err)
return nil, err
}
log.Printf("Found: %s", subsys.Spec.Nqn)
// TODO
return &pb.NVMeControllerStatsResponse{Stats: &pb.VolumeStats{
ReadBytesCount: -1,
ReadOpsCount: -1,
WriteBytesCount: -1,
WriteOpsCount: -1,
ReadLatencyTicks: -1,
WriteLatencyTicks: -1,
}}, nil
}
opiSpdkServer,

// CreateNVMeNamespace creates an NVMe namespace
func (s *Server) CreateNVMeNamespace(ctx context.Context, in *pb.CreateNVMeNamespaceRequest) (*pb.NVMeNamespace, error) {
log.Printf("CreateNVMeNamespace: Received from client: %v", in)
subsys, ok := s.Subsystems[in.NvMeNamespace.Spec.SubsystemId.Value]
if !ok {
err := fmt.Errorf("unable to find key %s", in.NvMeNamespace.Spec.SubsystemId.Value)
log.Printf("error: %v", err)
return nil, err
}
log.Printf("Found: %s", subsys.Spec.Nqn)
// TODO
s.Namespaces[in.NvMeNamespace.Spec.Id.Value] = in.NvMeNamespace
response := &pb.NVMeNamespace{}
err := deepcopier.Copy(in.NvMeNamespace).To(response)
if err != nil {
log.Printf("error: %v", err)
return nil, err
}
response.Status = &pb.NVMeNamespaceStatus{PciState: 2, PciOperState: 1}
return response, nil
}

// DeleteNVMeNamespace deletes an NVMe namespace
func (s *Server) DeleteNVMeNamespace(ctx context.Context, in *pb.DeleteNVMeNamespaceRequest) (*emptypb.Empty, error) {
log.Printf("DeleteNVMeNamespace: Received from client: %v", in)
namespace, ok := s.Namespaces[in.Name]
if !ok {
err := fmt.Errorf("unable to find key %s", in.Name)
log.Printf("error: %v", err)
return nil, err
}
subsys, ok := s.Subsystems[namespace.Spec.SubsystemId.Value]
if !ok {
err := fmt.Errorf("unable to find subsystem %s", namespace.Spec.SubsystemId.Value)
log.Printf("error: %v", err)
return nil, err
}
log.Printf("Found: %s", subsys.Spec.Nqn)
// TODO
delete(s.Namespaces, namespace.Spec.Id.Value)
return &emptypb.Empty{}, nil
}

// UpdateNVMeNamespace updates an NVMe namespace
func (s *Server) UpdateNVMeNamespace(ctx context.Context, in *pb.UpdateNVMeNamespaceRequest) (*pb.NVMeNamespace, error) {
log.Printf("UpdateNVMeNamespace: Received from client: %v", in)
return nil, status.Errorf(codes.Unimplemented, "UpdateNVMeNamespace method is not implemented")
}

// ListNVMeNamespaces lists NVMe namespaces
func (s *Server) ListNVMeNamespaces(ctx context.Context, in *pb.ListNVMeNamespacesRequest) (*pb.ListNVMeNamespacesResponse, error) {
log.Printf("ListNVMeNamespaces: Received from client: %v", in)
subsys, ok := s.Subsystems[in.Parent]
if !ok {
err := fmt.Errorf("unable to find key %s", in.Parent)
log.Printf("error: %v", err)
return nil, err
}
log.Printf("Found: %s", subsys.Spec.Nqn)
// TODO
Blobarray := make([]*pb.NVMeNamespace, 3)
return &pb.ListNVMeNamespacesResponse{NvMeNamespaces: Blobarray}, nil
}

// GetNVMeNamespace gets an NVMe namespace
func (s *Server) GetNVMeNamespace(ctx context.Context, in *pb.GetNVMeNamespaceRequest) (*pb.NVMeNamespace, error) {
log.Printf("GetNVMeNamespace: Received from client: %v", in)
namespace, ok := s.Namespaces[in.Name]
if !ok {
err := fmt.Errorf("unable to find key %s", in.Name)
log.Printf("error: %v", err)
return nil, err
}
subsys, ok := s.Subsystems[namespace.Spec.SubsystemId.Value]
if !ok {
err := fmt.Errorf("unable to find key %s", namespace.Spec.SubsystemId.Value)
log.Printf("error: %v", err)
return nil, err
}
log.Printf("Found: %s", subsys.Spec.Nqn)
// TODO
return &pb.NVMeNamespace{Spec: &pb.NVMeNamespaceSpec{Id: &pc.ObjectKey{Value: in.Name}, Nguid: "33"}, Status: &pb.NVMeNamespaceStatus{PciState: 2, PciOperState: 1}}, nil
}

// NVMeNamespaceStats gets an NVMe namespace stats
func (s *Server) NVMeNamespaceStats(ctx context.Context, in *pb.NVMeNamespaceStatsRequest) (*pb.NVMeNamespaceStatsResponse, error) {
log.Printf("NVMeNamespaceStats: Received from client: %v", in)
namespace, ok := s.Namespaces[in.NamespaceId.Value]
if !ok {
err := fmt.Errorf("unable to find key %s", in.NamespaceId.Value)
log.Printf("error: %v", err)
return nil, err
}
subsys, ok := s.Subsystems[namespace.Spec.SubsystemId.Value]
if !ok {
err := fmt.Errorf("unable to find key %s", namespace.Spec.SubsystemId.Value)
log.Printf("error: %v", err)
return nil, err
&opiSpdkServer.Nvme,
jsonRPC,
}
log.Printf("Found: %s", subsys.Spec.Nqn)
// TODO
return &pb.NVMeNamespaceStatsResponse{Stats: &pb.VolumeStats{
ReadBytesCount: -1,
ReadOpsCount: -1,
WriteBytesCount: -1,
WriteOpsCount: -1,
ReadLatencyTicks: -1,
WriteLatencyTicks: -1,
}}, nil
}
Loading

0 comments on commit b727593

Please sign in to comment.