# from ..cephnvmeof.control.cli import GatewayClient
+from typing import Optional
from ..security import Scope
from ..services.nvmeof_client import NVMeoFClient
-from . import APIDoc, APIRouter, RESTController, Endpoint, ReadPermission, CreatePermission
+# from ..services.proto import gateway_pb2 as pb2
+from . import APIDoc, APIRouter, RESTController, Endpoint, ReadPermission, CreatePermission, \
+ DeletePermission, allow_empty_body, UpdatePermission
+
-@APIRouter('/nvmeof', Scope.ISCSI)
+@APIRouter('/nvmeof', Scope.NVME_OF)
@APIDoc('NVMe-oF Management API', 'NVMe-oF')
class Nvmeof(RESTController):
@ReadPermission
def list(self):
"""List all NVMeoF gateways"""
return NVMeoFClient().get_subsystems()
+
+
+@APIRouter('/nvmeof/bdev', Scope.NVME_OF)
+@APIDoc('NVMe-oF Block Device Management API', 'NVMe-oF')
+class NvmeofBdev(RESTController):
+ @CreatePermission
+ def create(self, name: str, rbd_pool: str, rbd_image: str, block_size: int, uuid: Optional[str] = None):
+ """Create a new NVMeoF block device"""
+ return NVMeoFClient().create_bdev(name, rbd_pool, rbd_image, block_size, uuid)
+
+ @DeletePermission
+ @allow_empty_body
+ def delete(self, name: str, force: bool):
+ """Delete an existing NVMeoF block device"""
+ return NVMeoFClient().delete_bdev(name, force)
+
+ @Endpoint('PUT')
+ @UpdatePermission
+ @allow_empty_body
+ def resize(self, name: str, size: int):
+ """Resize an existing NVMeoF block device"""
+ return NVMeoFClient().resize_bdev(name, size)
+
+
+@APIRouter('/nvmeof/namespace', Scope.NVME_OF)
+@APIDoc('NVMe-oF Namespace Management API', 'NVMe-oF')
+class NvmeofNamespace(RESTController):
+ @CreatePermission
+ def create(self, subsystem_nqn: str, bdev_name: str, nsid: int, anagrpid: Optional[str] = None):
+ """Create a new NVMeoF namespace"""
+ return NVMeoFClient().create_namespace(subsystem_nqn, bdev_name, nsid, anagrpid)
+
+ @Endpoint('DELETE', path='{subsystem_nqn}')
+ def delete(self, subsystem_nqn: str, nsid: int):
+ """Delete an existing NVMeoF namespace"""
+ return NVMeoFClient().delete_namespace(subsystem_nqn, nsid)
+
+@APIRouter('/nvmeof/subsystem', Scope.NVME_OF)
+@APIDoc('NVMe-oF Subsystem Management API', 'NVMe-oF')
+class NvmeofSubsystem(RESTController):
+ @CreatePermission
+ def create(self, subsystem_nqn: str, serial_number: str, max_namespaces: int,
+ ana_reporting: bool, enable_ha: bool) :
+ """Create a new NVMeoF subsystem"""
+ return NVMeoFClient().create_subsystem(subsystem_nqn, serial_number, max_namespaces,
+ ana_reporting, enable_ha)
+
+ @Endpoint('DELETE', path='{subsystem_nqn}')
+ def delete(self, subsystem_nqn: str):
+ """Delete an existing NVMeoF subsystem"""
+ return NVMeoFClient().delete_subsystem(subsystem_nqn)
+
+
+@APIRouter('/nvmeof/hosts', Scope.NVME_OF)
+@APIDoc('NVMe-oF Host Management API', 'NVMe-oF')
+class NvmeofHost(RESTController):
+ @CreatePermission
+ def create(self, subsystem_nqn: str, host_nqn: str):
+ """Create a new NVMeoF host"""
+ return NVMeoFClient().add_host(subsystem_nqn, host_nqn)
+
+ @Endpoint('DELETE')
+ def delete(self, subsystem_nqn: str, host_nqn: str):
+ """Delete an existing NVMeoF host"""
+ return NVMeoFClient().remove_host(subsystem_nqn, host_nqn)
+
+
+@APIRouter('/nvmeof/listener', Scope.NVME_OF)
+@APIDoc('NVMe-oF Listener Management API', 'NVMe-oF')
+class NvmeofListener(RESTController):
+ @CreatePermission
+ def create(self, nqn: str, gateway: str, trtype: str, adrfam: str,
+ traddr: str, trsvcid: str):
+ """Create a new NVMeoF listener"""
+ return NVMeoFClient().create_listener(nqn, gateway, trtype, adrfam, traddr, trsvcid)
+
+ @Endpoint('DELETE')
+ def delete(self, nqn: str, gateway: str, trtype, adrfam,
+ traddr: str, trsvcid: str):
+ """Delete an existing NVMeoF listener"""
+ return NVMeoFClient().delete_listener(nqn, gateway, trtype, adrfam, traddr, trsvcid)
\ No newline at end of file
+from enum import Enum
+from typing import Optional
import grpc
import json
from google.protobuf.json_format import MessageToJson
from .nvmeof_conf import NvmeofGatewaysConfig
+from ..tools import str_to_bool
logger = logging.getLogger('nvmeof_client')
def get_subsystems(self):
response = self.stub.get_subsystems(pb2.get_subsystems_req())
return json.loads(MessageToJson(response))
+
+ def create_bdev(self, name: str, rbd_pool: str, rbd_image: str, block_size: int, uuid: Optional[str] = None):
+ response = self.stub.create_bdev(pb2.create_bdev_req(
+ bdev_name=name,
+ rbd_pool_name=rbd_pool,
+ rbd_image_name=rbd_image,
+ block_size=block_size,
+ uuid=uuid
+ ))
+ return json.loads(MessageToJson(response))
+
+ def resize_bdev(self, name: str, size: int):
+ response = self.stub.resize_bdev(pb2.resize_bdev_req(
+ bdev_name=name,
+ new_size=size
+ ))
+ return json.loads(MessageToJson(response))
+
+ def delete_bdev(self, name: str, force: bool):
+ response = self.stub.delete_bdev(pb2.delete_bdev_req(
+ bdev_name=name,
+ force=str_to_bool(force)
+ ))
+ return json.loads(MessageToJson(response))
+
+ def create_subsystem(self, subsystem_nqn: str, serial_number: str, max_namespaces: int,
+ ana_reporting: bool, enable_ha: bool) :
+ response = self.stub.create_subsystem(pb2.create_subsystem_req(
+ subsystem_nqn=subsystem_nqn,
+ serial_number=serial_number,
+ max_namespaces=int(max_namespaces),
+ ana_reporting=str_to_bool(ana_reporting),
+ enable_ha=str_to_bool(enable_ha)
+ ))
+ return json.loads(MessageToJson(response))
+
+ def delete_subsystem(self, subsystem_nqn: str):
+ response = self.stub.delete_subsystem(pb2.delete_subsystem_req(
+ subsystem_nqn=subsystem_nqn
+ ))
+ return json.loads(MessageToJson(response))
+
+ def create_namespace(self, subsystem_nqn: str, bdev_name: str, nsid: int, anagrpid: Optional[str] = None):
+ response = self.stub.add_namespace(pb2.add_namespace_req(
+ subsystem_nqn=subsystem_nqn,
+ bdev_name=bdev_name,
+ nsid=int(nsid),
+ anagrpid=anagrpid
+ ))
+ return json.loads(MessageToJson(response))
+
+ def delete_namespace(self, subsystem_nqn: str, nsid: int):
+ response = self.stub.remove_namespace(pb2.remove_namespace_req(
+ subsystem_nqn=subsystem_nqn,
+ nsid=nsid
+ ))
+ return json.loads(MessageToJson(response))
+
+ def add_host(self, subsystem_nqn: str, host_nqn: str):
+ response = self.stub.add_host(pb2.add_host_req(
+ subsystem_nqn=subsystem_nqn,
+ host_nqn=host_nqn
+ ))
+ return json.loads(MessageToJson(response))
+
+ def remove_host(self, subsystem_nqn: str, host_nqn: str):
+ response = self.stub.remove_host(pb2.remove_host_req(
+ subsystem_nqn=subsystem_nqn,
+ host_nqn=host_nqn
+ ))
+ return json.loads(MessageToJson(response))
+
+ def create_listener(self, nqn: str, gateway: str, trtype: str, adrfam: str,
+ traddr: str, trsvcid: str):
+ req = pb2.create_listener_req(
+ nqn=nqn,
+ gateway_name=gateway,
+ trtype=pb2.TransportType.Value(trtype.upper()),
+ adrfam=pb2.AddressFamily.Value(adrfam.lower()),
+ traddr=traddr,
+ trsvcid=trsvcid,
+ )
+ ret = self.stub.create_listener(req)
+ return json.loads(MessageToJson(ret))
+
+ def delete_listener(self, nqn: str, gateway: str, trttype, adrfam,
+ traddr: str, trsvcid: str):
+ response = self.stub.delete_listener(pb2.delete_listener_req(
+ nqn=nqn,
+ gateway_name=gateway,
+ trtype=trttype,
+ adrfam=adrfam,
+ traddr=traddr,
+ trsvcid=trsvcid
+ ))
+ return json.loads(MessageToJson(response))