-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Provide initial MEV NVMe implementation.
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 <artsiom.koltun@intel.com>
- Loading branch information
1 parent
09d175b
commit b727593
Showing
3 changed files
with
176 additions
and
326 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
Oops, something went wrong.