mgr/dashboard: adapt to new nvmeof APIs

Fixes: https://tracker.ceph.com/issues/64201
Signed-off-by: Nizamudeen A <nia@redhat.com>
This commit is contained in:
Nizamudeen A 2024-01-12 14:11:18 +05:30
parent 1b768332b1
commit 35e40c4e8f
15 changed files with 4907 additions and 926 deletions

View File

@ -625,6 +625,8 @@ Requires: ceph-mgr = %{_epoch_prefix}%{version}-%{release}
Requires: ceph-grafana-dashboards = %{_epoch_prefix}%{version}-%{release}
Requires: ceph-prometheus-alerts = %{_epoch_prefix}%{version}-%{release}
Requires: python%{python3_pkgversion}-setuptools
Requires: python%{python3_pkgversion}-grpcio
Requires: python%{python3_pkgversion}-grpcio-tools
%if 0%{?fedora} || 0%{?rhel} || 0%{?openEuler}
Requires: python%{python3_pkgversion}-cherrypy
Requires: python%{python3_pkgversion}-routes

1
debian/control vendored
View File

@ -96,6 +96,7 @@ Build-Depends: automake,
tox <pkg.ceph.check>,
python3-coverage <pkg.ceph.check>,
python3-dateutil <pkg.ceph.check>,
python3-grpcio <pkg.ceph.check>,
python3-openssl <pkg.ceph.check>,
python3-prettytable <pkg.ceph.check>,
python3-requests <pkg.ceph.check>,

View File

@ -121,7 +121,7 @@ class NvmeofService(CephService):
'name': daemon.hostname,
})
if not ret:
logger.info(f'{daemon.hostname} removed from iscsi gateways dashboard config')
logger.info(f'{daemon.hostname} removed from nvmeof gateways dashboard config')
# and any certificates being used for mTLS

View File

@ -4,5 +4,3 @@ bcrypt~=3.1
python3-saml~=1.4
requests~=2.26
Routes~=2.4
grpcio~=1.48
grpcio-tools~=1.48

View File

@ -1,108 +1,192 @@
# # import grpc
# from .proto import gateway_pb2 as pb2
# from .proto import gateway_pb2_grpc as pb2_grpc
# class NVMeoFClient(object):
# def __init__(self):
# self.host = '192.168.100.102'
# from ..cephnvmeof.control.cli import GatewayClient
# -*- coding: utf-8 -*-
import json
from typing import Optional
from ..security import Scope
from ..services.nvmeof_client import NVMeoFClient
# from ..services.proto import gateway_pb2 as pb2
from . import APIDoc, APIRouter, RESTController, Endpoint, ReadPermission, CreatePermission, \
DeletePermission, allow_empty_body, UpdatePermission
from . import APIDoc, APIRouter, CreatePermission, DeletePermission, Endpoint, \
EndpointDoc, ReadPermission, RESTController
@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()
try:
from google.protobuf.json_format import MessageToJson
from ..services.nvmeof_client import NVMeoFClient
except ImportError:
MessageToJson = None
else:
@APIRouter('/nvmeof/namespace', Scope.NVME_OF)
@APIDoc('NVMe-oF Namespace Management API', 'NVMe-oF')
class NvmeofNamespace(RESTController):
@ReadPermission
def list(self, subsystem_nqn: str):
"""
List all NVMeoF namespaces
"""
response = MessageToJson(NVMeoFClient().list_namespaces(subsystem_nqn))
return json.loads(response)
@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)
@CreatePermission
def create(self, rbd_pool: str, rbd_image: str, subsystem_nqn: str,
create_image: Optional[bool] = True, image_size: Optional[int] = 1024,
block_size: int = 512, nsid: Optional[int] = 1,
uuid: Optional[str] = None, anagrpid: Optional[int] = 1):
"""
Create a new NVMeoF namespace
:param rbd_pool: RBD pool name
:param rbd_image: RBD image name
:param subsystem_nqn: NVMeoF subsystem NQN
:param create_image: Create RBD image
:param image_size: RBD image size
:param block_size: NVMeoF namespace block size
:param nsid: NVMeoF namespace ID
:param uuid: NVMeoF namespace UUID
:param anagrpid: NVMeoF namespace ANA group ID
"""
response = NVMeoFClient().create_namespace(rbd_pool, rbd_image,
subsystem_nqn, block_size,
nsid, uuid, anagrpid,
create_image, image_size)
return json.loads(MessageToJson(response))
@Endpoint('DELETE', path='{subsystem_nqn}')
def delete(self, subsystem_nqn: str, nsid: int):
"""
Delete an existing NVMeoF namespace
:param subsystem_nqn: NVMeoF subsystem NQN
:param nsid: NVMeoF namespace ID
"""
response = NVMeoFClient().delete_namespace(subsystem_nqn, nsid)
return json.loads(MessageToJson(response))
@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/subsystem', Scope.NVME_OF)
@APIDoc('NVMe-oF Subsystem Management API', 'NVMe-oF')
class NvmeofSubsystem(RESTController):
@ReadPermission
@EndpointDoc("List all NVMeoF gateways",
parameters={
'subsystem_nqn': (str, 'NVMeoF subsystem NQN'),
'serial_number': (str, 'NVMeoF subsystem serial number')
})
def list(self, subsystem_nqn: Optional[str] = None, serial_number: Optional[str] = None):
response = MessageToJson(NVMeoFClient().list_subsystems(
subsystem_nqn=subsystem_nqn, serial_number=serial_number))
return json.loads(response)
@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)
@CreatePermission
def create(self, subsystem_nqn: str, serial_number: Optional[str] = None,
max_namespaces: Optional[int] = 256, ana_reporting: Optional[bool] = False,
enable_ha: Optional[bool] = False):
"""
Create a new NVMeoF subsystem
:param subsystem_nqn: NVMeoF subsystem NQN
:param serial_number: NVMeoF subsystem serial number
:param max_namespaces: NVMeoF subsystem maximum namespaces
:param ana_reporting: NVMeoF subsystem ANA reporting
:param enable_ha: NVMeoF subsystem enable HA
"""
response = NVMeoFClient().create_subsystem(subsystem_nqn, serial_number, max_namespaces,
ana_reporting, enable_ha)
return json.loads(MessageToJson(response))
@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)
@DeletePermission
@Endpoint('DELETE', path='{subsystem_nqn}')
def delete(self, subsystem_nqn: str):
"""
Delete an existing NVMeoF subsystem
:param subsystem_nqn: NVMeoF subsystem NQN
"""
response = NVMeoFClient().delete_subsystem(subsystem_nqn)
return json.loads(MessageToJson(response))
@APIRouter('/nvmeof/hosts', Scope.NVME_OF)
@APIDoc('NVMe-oF Host Management API', 'NVMe-oF')
class NvmeofHost(RESTController):
@ReadPermission
def list(self, subsystem_nqn: str):
"""
List all NVMeoF hosts
:param subsystem_nqn: NVMeoF subsystem NQN
"""
response = MessageToJson(NVMeoFClient().list_hosts(subsystem_nqn))
return json.loads(response)
@CreatePermission
def create(self, subsystem_nqn: str, host_nqn: str):
"""
Create a new NVMeoF host
:param subsystem_nqn: NVMeoF subsystem NQN
:param host_nqn: NVMeoF host NQN
"""
response = NVMeoFClient().add_host(subsystem_nqn, host_nqn)
return json.loads(MessageToJson(response))
@DeletePermission
def delete(self, subsystem_nqn: str, host_nqn: str):
"""
Delete an existing NVMeoF host
:param subsystem_nqn: NVMeoF subsystem NQN
:param host_nqn: NVMeoF host NQN
"""
response = NVMeoFClient().remove_host(subsystem_nqn, host_nqn)
return json.loads(MessageToJson(response))
@APIRouter('/nvmeof/listener', Scope.NVME_OF)
@APIDoc('NVMe-oF Listener Management API', 'NVMe-oF')
class NvmeofListener(RESTController):
@ReadPermission
def list(self, subsystem_nqn: str):
"""
List all NVMeoF listeners
:param nqn: NVMeoF subsystem NQN
"""
response = MessageToJson(NVMeoFClient().list_listeners(subsystem_nqn))
return json.loads(response)
@CreatePermission
def create(self, nqn: str, gateway: str, traddr: Optional[str] = None,
trtype: Optional[str] = 'TCP', adrfam: Optional[str] = 'IPV4',
trsvcid: Optional[int] = 4420,
auto_ha_state: Optional[str] = 'AUTO_HA_UNSET'):
"""
Create a new NVMeoF listener
:param nqn: NVMeoF subsystem NQN
:param gateway: NVMeoF gateway
:param traddr: NVMeoF transport address
:param trtype: NVMeoF transport type
:param adrfam: NVMeoF address family
:param trsvcid: NVMeoF transport service ID
:param auto_ha_state: NVMeoF auto HA state
"""
response = NVMeoFClient().create_listener(nqn, gateway, traddr,
trtype, adrfam, trsvcid, auto_ha_state)
return json.loads(MessageToJson(response))
@DeletePermission
def delete(self, nqn: str, gateway: str, traddr: Optional[str] = None,
transport_type: Optional[str] = 'TCP', addr_family: Optional[str] = 'IPV4',
transport_svc_id: Optional[int] = 4420):
"""
Delete an existing NVMeoF listener
:param nqn: NVMeoF subsystem NQN
:param gateway: NVMeoF gateway
:param traddr: NVMeoF transport address
:param transport_type: NVMeoF transport type
:param addr_family: NVMeoF address family
:param transport_svc_id: NVMeoF transport service ID
"""
response = NVMeoFClient().delete_listener(nqn, gateway, traddr, transport_type,
addr_family, transport_svc_id)
return json.loads(MessageToJson(response))
@APIRouter('/nvmeof/gateway', Scope.NVME_OF)
@APIDoc('NVMe-oF Gateway Management API', 'NVMe-oF')
class NvmeofGateway(RESTController):
@ReadPermission
@Endpoint()
def info(self):
"""
Get NVMeoF gateway information
"""
response = MessageToJson(NVMeoFClient().gateway_info())
return json.loads(response)

View File

@ -29,6 +29,7 @@ from mgr_util import ServerConfigException, build_url, \
from . import mgr
from .controllers import Router, json_error_page
from .grafana import push_local_dashboards
from .services import nvmeof_cli # noqa # pylint: disable=unused-import
from .services.auth import AuthManager, AuthManagerTool, JwtManager
from .services.exception import dashboard_exception_handler
from .services.rgw_client import configure_rgw_credentials
@ -37,9 +38,6 @@ from .settings import handle_option_command, options_command_list, options_schem
from .tools import NotificationQueue, RequestLoggingTool, TaskManager, \
prepare_url_prefix, str_to_bool
# pylint: disable=unused-import
from .services import nvmeof_cli
try:
import cherrypy
from cherrypy._cptools import HandlerWrapperTool

View File

@ -7318,6 +7318,550 @@ paths:
summary: Updates an NFS-Ganesha export
tags:
- NFS-Ganesha
/api/nvmeof/gateway/info:
get:
description: "\n Get NVMeoF gateway information\n "
parameters: []
responses:
'200':
content:
application/vnd.ceph.api.v1.0+json:
type: object
description: OK
'400':
description: Operation exception. Please check the response body for details.
'401':
description: Unauthenticated access. Please login first.
'403':
description: Unauthorized access. Please check your permissions.
'500':
description: Unexpected error. Please check the response body for the stack
trace.
security:
- jwt: []
tags:
- NVMe-oF
/api/nvmeof/hosts:
post:
description: "\n Create a new NVMeoF host\n :param subsystem_nqn:\
\ NVMeoF subsystem NQN\n :param host_nqn: NVMeoF host NQN\n \
\ "
parameters: []
requestBody:
content:
application/json:
schema:
properties:
host_nqn:
type: string
subsystem_nqn:
type: string
required:
- subsystem_nqn
- host_nqn
type: object
responses:
'201':
content:
application/vnd.ceph.api.v1.0+json:
type: object
description: Resource created.
'202':
content:
application/vnd.ceph.api.v1.0+json:
type: object
description: Operation is still executing. Please check the task queue.
'400':
description: Operation exception. Please check the response body for details.
'401':
description: Unauthenticated access. Please login first.
'403':
description: Unauthorized access. Please check your permissions.
'500':
description: Unexpected error. Please check the response body for the stack
trace.
security:
- jwt: []
tags:
- NVMe-oF
/api/nvmeof/hosts/{subsystem_nqn}:
get:
description: "\n List all NVMeoF hosts\n :param subsystem_nqn:\
\ NVMeoF subsystem NQN\n "
parameters:
- in: path
name: subsystem_nqn
required: true
schema:
type: string
responses:
'200':
content:
application/vnd.ceph.api.v1.0+json:
type: object
description: OK
'400':
description: Operation exception. Please check the response body for details.
'401':
description: Unauthenticated access. Please login first.
'403':
description: Unauthorized access. Please check your permissions.
'500':
description: Unexpected error. Please check the response body for the stack
trace.
security:
- jwt: []
tags:
- NVMe-oF
/api/nvmeof/hosts/{subsystem_nqn}/{host_nqn}:
delete:
description: "\n Delete an existing NVMeoF host\n :param\
\ subsystem_nqn: NVMeoF subsystem NQN\n :param host_nqn: NVMeoF\
\ host NQN\n "
parameters:
- in: path
name: subsystem_nqn
required: true
schema:
type: string
- in: path
name: host_nqn
required: true
schema:
type: string
responses:
'202':
content:
application/vnd.ceph.api.v1.0+json:
type: object
description: Operation is still executing. Please check the task queue.
'204':
content:
application/vnd.ceph.api.v1.0+json:
type: object
description: Resource deleted.
'400':
description: Operation exception. Please check the response body for details.
'401':
description: Unauthenticated access. Please login first.
'403':
description: Unauthorized access. Please check your permissions.
'500':
description: Unexpected error. Please check the response body for the stack
trace.
security:
- jwt: []
tags:
- NVMe-oF
/api/nvmeof/listener:
get:
description: "\n List all NVMeoF listeners\n :param nqn:\
\ NVMeoF subsystem NQN\n "
parameters:
- in: query
name: subsystem_nqn
required: true
schema:
type: string
responses:
'200':
content:
application/vnd.ceph.api.v1.0+json:
type: object
description: OK
'400':
description: Operation exception. Please check the response body for details.
'401':
description: Unauthenticated access. Please login first.
'403':
description: Unauthorized access. Please check your permissions.
'500':
description: Unexpected error. Please check the response body for the stack
trace.
security:
- jwt: []
tags:
- NVMe-oF
post:
description: "\n Create a new NVMeoF listener\n :param\
\ nqn: NVMeoF subsystem NQN\n :param gateway: NVMeoF gateway\n\
\ :param traddr: NVMeoF transport address\n :param trtype:\
\ NVMeoF transport type\n :param adrfam: NVMeoF address family\n\
\ :param trsvcid: NVMeoF transport service ID\n :param\
\ auto_ha_state: NVMeoF auto HA state\n "
parameters: []
requestBody:
content:
application/json:
schema:
properties:
adrfam:
default: IPV4
type: string
auto_ha_state:
default: AUTO_HA_UNSET
type: string
gateway:
type: string
nqn:
type: string
traddr:
type: string
trsvcid:
default: 4420
type: integer
trtype:
default: TCP
type: string
required:
- nqn
- gateway
type: object
responses:
'201':
content:
application/vnd.ceph.api.v1.0+json:
type: object
description: Resource created.
'202':
content:
application/vnd.ceph.api.v1.0+json:
type: object
description: Operation is still executing. Please check the task queue.
'400':
description: Operation exception. Please check the response body for details.
'401':
description: Unauthenticated access. Please login first.
'403':
description: Unauthorized access. Please check your permissions.
'500':
description: Unexpected error. Please check the response body for the stack
trace.
security:
- jwt: []
tags:
- NVMe-oF
/api/nvmeof/listener/{nqn}/{gateway}:
delete:
description: "\n Delete an existing NVMeoF listener\n \
\ :param nqn: NVMeoF subsystem NQN\n :param gateway: NVMeoF gateway\n\
\ :param traddr: NVMeoF transport address\n :param transport_type:\
\ NVMeoF transport type\n :param addr_family: NVMeoF address family\n\
\ :param transport_svc_id: NVMeoF transport service ID\n \
\ "
parameters:
- in: path
name: nqn
required: true
schema:
type: string
- in: path
name: gateway
required: true
schema:
type: string
- allowEmptyValue: true
in: query
name: traddr
schema:
type: string
- default: TCP
in: query
name: transport_type
schema:
type: string
- default: IPV4
in: query
name: addr_family
schema:
type: string
- default: 4420
in: query
name: transport_svc_id
schema:
type: integer
responses:
'202':
content:
application/vnd.ceph.api.v1.0+json:
type: object
description: Operation is still executing. Please check the task queue.
'204':
content:
application/vnd.ceph.api.v1.0+json:
type: object
description: Resource deleted.
'400':
description: Operation exception. Please check the response body for details.
'401':
description: Unauthenticated access. Please login first.
'403':
description: Unauthorized access. Please check your permissions.
'500':
description: Unexpected error. Please check the response body for the stack
trace.
security:
- jwt: []
tags:
- NVMe-oF
/api/nvmeof/namespace:
post:
description: "\n Create a new NVMeoF namespace\n :param\
\ rbd_pool: RBD pool name\n :param rbd_image: RBD image name\n\
\ :param subsystem_nqn: NVMeoF subsystem NQN\n :param\
\ create_image: Create RBD image\n :param image_size: RBD image\
\ size\n :param block_size: NVMeoF namespace block size\n \
\ :param nsid: NVMeoF namespace ID\n :param uuid: NVMeoF\
\ namespace UUID\n :param anagrpid: NVMeoF namespace ANA group\
\ ID\n "
parameters: []
requestBody:
content:
application/json:
schema:
properties:
anagrpid:
default: 1
type: integer
block_size:
default: 512
type: integer
create_image:
default: true
type: boolean
image_size:
default: 1024
type: integer
nsid:
default: 1
type: integer
rbd_image:
type: string
rbd_pool:
type: string
subsystem_nqn:
type: string
uuid:
type: string
required:
- rbd_pool
- rbd_image
- subsystem_nqn
type: object
responses:
'201':
content:
application/vnd.ceph.api.v1.0+json:
type: object
description: Resource created.
'202':
content:
application/vnd.ceph.api.v1.0+json:
type: object
description: Operation is still executing. Please check the task queue.
'400':
description: Operation exception. Please check the response body for details.
'401':
description: Unauthenticated access. Please login first.
'403':
description: Unauthorized access. Please check your permissions.
'500':
description: Unexpected error. Please check the response body for the stack
trace.
security:
- jwt: []
tags:
- NVMe-oF
/api/nvmeof/namespace/{subsystem_nqn}:
get:
description: "\n List all NVMeoF namespaces\n "
parameters:
- in: path
name: subsystem_nqn
required: true
schema:
type: string
responses:
'200':
content:
application/vnd.ceph.api.v1.0+json:
type: object
description: OK
'400':
description: Operation exception. Please check the response body for details.
'401':
description: Unauthenticated access. Please login first.
'403':
description: Unauthorized access. Please check your permissions.
'500':
description: Unexpected error. Please check the response body for the stack
trace.
security:
- jwt: []
tags:
- NVMe-oF
/api/nvmeof/namespace/{subsystem_nqn}/{nsid}:
delete:
description: "\n Delete an existing NVMeoF namespace\n \
\ :param subsystem_nqn: NVMeoF subsystem NQN\n :param nsid: NVMeoF\
\ namespace ID\n "
parameters:
- in: path
name: subsystem_nqn
required: true
schema:
type: string
- in: path
name: nsid
required: true
schema:
type: string
responses:
'202':
content:
application/vnd.ceph.api.v1.0+json:
type: object
description: Operation is still executing. Please check the task queue.
'204':
content:
application/vnd.ceph.api.v1.0+json:
type: object
description: Resource deleted.
'400':
description: Operation exception. Please check the response body for details.
'401':
description: Unauthenticated access. Please login first.
'403':
description: Unauthorized access. Please check your permissions.
'500':
description: Unexpected error. Please check the response body for the stack
trace.
security:
- jwt: []
tags:
- NVMe-oF
/api/nvmeof/subsystem:
get:
parameters:
- allowEmptyValue: true
description: NVMeoF subsystem NQN
in: query
name: subsystem_nqn
schema:
type: string
- allowEmptyValue: true
description: NVMeoF subsystem serial number
in: query
name: serial_number
schema:
type: string
responses:
'200':
content:
application/vnd.ceph.api.v1.0+json:
type: object
description: OK
'400':
description: Operation exception. Please check the response body for details.
'401':
description: Unauthenticated access. Please login first.
'403':
description: Unauthorized access. Please check your permissions.
'500':
description: Unexpected error. Please check the response body for the stack
trace.
security:
- jwt: []
summary: List all NVMeoF gateways
tags:
- NVMe-oF
post:
description: "\n Create a new NVMeoF subsystem\n\n :param\
\ subsystem_nqn: NVMeoF subsystem NQN\n :param serial_number: NVMeoF\
\ subsystem serial number\n :param max_namespaces: NVMeoF subsystem\
\ maximum namespaces\n :param ana_reporting: NVMeoF subsystem ANA\
\ reporting\n :param enable_ha: NVMeoF subsystem enable HA\n \
\ "
parameters: []
requestBody:
content:
application/json:
schema:
properties:
ana_reporting:
default: false
type: boolean
enable_ha:
default: false
type: boolean
max_namespaces:
default: 256
type: integer
serial_number:
type: integer
subsystem_nqn:
type: string
required:
- subsystem_nqn
type: object
responses:
'201':
content:
application/vnd.ceph.api.v1.0+json:
type: object
description: Resource created.
'202':
content:
application/vnd.ceph.api.v1.0+json:
type: object
description: Operation is still executing. Please check the task queue.
'400':
description: Operation exception. Please check the response body for details.
'401':
description: Unauthenticated access. Please login first.
'403':
description: Unauthorized access. Please check your permissions.
'500':
description: Unexpected error. Please check the response body for the stack
trace.
security:
- jwt: []
tags:
- NVMe-oF
/api/nvmeof/subsystem/{subsystem_nqn}:
delete:
description: "\n Delete an existing NVMeoF subsystem\n \
\ :param subsystem_nqn: NVMeoF subsystem NQN\n "
parameters:
- in: path
name: subsystem_nqn
required: true
schema:
type: string
responses:
'202':
content:
application/vnd.ceph.api.v1.0+json:
type: object
description: Operation is still executing. Please check the task queue.
'204':
content:
application/vnd.ceph.api.v1.0+json:
type: object
description: Resource deleted.
'400':
description: Operation exception. Please check the response body for details.
'401':
description: Unauthenticated access. Please login first.
'403':
description: Unauthorized access. Please check your permissions.
'500':
description: Unexpected error. Please check the response body for the stack
trace.
security:
- jwt: []
tags:
- NVMe-oF
/api/osd:
get:
parameters: []
@ -13180,6 +13724,8 @@ tags:
name: Monitor
- description: NFS-Ganesha Cluster Management API
name: NFS-Ganesha
- description: NVMe-oF Gateway Management API
name: NVMe-oF
- description: OSD management API
name: OSD
- description: OSD Perf Counters Management API

View File

@ -11,3 +11,5 @@ pyyaml
natsort
setuptools
jsonpatch
grpcio==1.46.5
grpcio-tools==1.46.5

View File

@ -5,8 +5,9 @@ import json
from mgr_module import CLICheckNonemptyFileInput, CLIReadCommand, CLIWriteCommand
from ..rest_client import RequestException
from .nvmeof_conf import NvmeofGatewaysConfig, NvmeofGatewayAlreadyExists, \
ManagedByOrchestratorException
from .nvmeof_conf import ManagedByOrchestratorException, \
NvmeofGatewayAlreadyExists, NvmeofGatewaysConfig
@CLIReadCommand('dashboard nvmeof-gateway-list')
def list_nvmeof_gateways(_):
@ -15,6 +16,7 @@ def list_nvmeof_gateways(_):
'''
return 0, json.dumps(NvmeofGatewaysConfig.get_gateways_config()), ''
@CLIWriteCommand('dashboard nvmeof-gateway-add')
@CLICheckNonemptyFileInput(desc='NVMe-oF gateway configuration')
def add_nvmeof_gateway(_, inbuf, name: str):
@ -32,6 +34,7 @@ def add_nvmeof_gateway(_, inbuf, name: str):
except RequestException as ex:
return -errno.EINVAL, '', str(ex)
@CLIWriteCommand('dashboard nvmeof-gateway-rm')
def remove_nvmeof_gateway(_, name: str):
'''

View File

@ -1,128 +1,152 @@
from enum import Enum
from typing import Optional
import grpc
import json
import logging
from typing import Optional
from .proto import gateway_pb2 as pb2
from .proto import gateway_pb2_grpc as pb2_grpc
from google.protobuf.json_format import MessageToJson
from .nvmeof_conf import NvmeofGatewaysConfig
from ..tools import str_to_bool
from .nvmeof_conf import NvmeofGatewaysConfig
logger = logging.getLogger('nvmeof_client')
try:
import grpc
class NVMeoFClient(object):
def __init__(self):
logger.info('Initiating nvmeof gateway connection...')
from .proto import gateway_pb2 as pb2
from .proto import gateway_pb2_grpc as pb2_grpc
except ImportError:
grpc = None
else:
class NVMeoFClient(object):
def __init__(self):
logger.info('Initiating nvmeof gateway connection...')
self.gateway_addr = list(NvmeofGatewaysConfig.get_gateways_config()['gateways'].values())[0]['service_url']
self.channel = grpc.insecure_channel(
'{}'.format(self.gateway_addr)
)
logger.info('Found nvmeof gateway at {}'.format(self.gateway_addr))
self.stub = pb2_grpc.GatewayStub(self.channel)
self.gateway_addr = list(NvmeofGatewaysConfig.get_gateways_config()[
'gateways'].values())[0]['service_url']
self.channel = grpc.insecure_channel(
'{}'.format(self.gateway_addr)
)
logger.info('Found nvmeof gateway at %s', self.gateway_addr)
self.stub = pb2_grpc.GatewayStub(self.channel)
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 list_subsystems(self, subsystem_nqn: Optional[str] = None,
serial_number: Optional[str] = None):
return self.stub.list_subsystems(pb2.list_subsystems_req(
subsystem_nqn=subsystem_nqn,
serial_number=serial_number
))
def create_listener(self, nqn: str, gateway: str, trtype: str, adrfam: str,
traddr: str, trsvcid: str):
req = pb2.create_listener_req(
def create_subsystem(self, subsystem_nqn: str, serial_number: str, max_namespaces: int,
ana_reporting: bool, enable_ha: bool):
return 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)
))
def delete_subsystem(self, subsystem_nqn: str):
return self.stub.delete_subsystem(pb2.delete_subsystem_req(
subsystem_nqn=subsystem_nqn
))
def list_namespaces(self, subsystem_nqn: str, nsid: Optional[int] = 1,
uuid: Optional[str] = None):
return self.stub.list_namespaces(pb2.list_namespaces_req(
subsystem=subsystem_nqn,
nsid=int(nsid),
uuid=uuid
))
def create_namespace(self, rbd_pool_name: str, rbd_image_name: str,
subsystem_nqn: str, block_size: int = 512,
nsid: Optional[int] = 1, uuid: Optional[str] = None,
anagrpid: Optional[int] = 1, create_image: Optional[bool] = True,
size: Optional[int] = 1024):
return self.stub.namespace_add(pb2.namespace_add_req(
rbd_pool_name=rbd_pool_name,
rbd_image_name=rbd_image_name,
subsystem_nqn=subsystem_nqn,
nsid=int(nsid),
block_size=block_size,
uuid=uuid,
anagrpid=anagrpid,
create_image=create_image,
size=size
))
def delete_namespace(self, subsystem_nqn: str, nsid: int):
return self.stub.remove_namespace(pb2.remove_namespace_req(
subsystem_nqn=subsystem_nqn,
nsid=nsid
))
def list_hosts(self, subsystem_nqn: str):
return self.stub.list_hosts(pb2.list_hosts_req(
subsystem=subsystem_nqn
))
def add_host(self, subsystem_nqn: str, host_nqn: str):
return self.stub.add_host(pb2.add_host_req(
subsystem_nqn=subsystem_nqn,
host_nqn=host_nqn
))
def remove_host(self, subsystem_nqn: str, host_nqn: str):
return self.stub.remove_host(pb2.remove_host_req(
subsystem_nqn=subsystem_nqn,
host_nqn=host_nqn
))
def list_listeners(self, subsystem_nqn: str):
return self.stub.list_listeners(pb2.list_listeners_req(
subsystem=subsystem_nqn
))
def create_listener(self, nqn: str, gateway: str, traddr: Optional[str] = None,
transport_type: Optional[str] = 'TCP',
addr_family: Optional[str] = 'IPV4',
transport_svc_id: Optional[int] = 4420,
auto_ha_state: Optional[str] = 'AUTO_HA_UNSET'):
traddr = None
if traddr is None:
addr = self.gateway_addr
ip_address, _ = addr.split(':')
traddr = self._escape_address_if_ipv6(ip_address)
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,
trtype=pb2.TransportType.Value(transport_type.upper()),
adrfam=pb2.AddressFamily.Value(addr_family.lower()),
trsvcid=transport_svc_id,
auto_ha_state=pb2.AutoHAState.Value(auto_ha_state.upper())
)
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))
return self.stub.create_listener(req)
def delete_listener(self, nqn: str, gateway: str, traddr: Optional[str] = None,
transport_type: Optional[str] = 'TCP',
addr_family: Optional[str] = 'IPV4',
transport_svc_id: Optional[int] = 4420):
traddr = None
if traddr is None:
addr = self.gateway_addr
ip_address, _ = addr.split(':')
traddr = self._escape_address_if_ipv6(ip_address)
return self.stub.delete_listener(pb2.delete_listener_req(
nqn=nqn,
gateway_name=gateway,
traddr=traddr,
trtype=pb2.TransportType.Value(transport_type.upper()),
adrfam=pb2.AddressFamily.Value(addr_family.lower()),
trsvcid=int(transport_svc_id)
))
def gateway_info(self):
return self.stub.get_gateway_info(pb2.get_gateway_info_req())
def _escape_address_if_ipv6(self, addr):
ret_addr = addr
if ":" in addr and not addr.strip().startswith("["):
ret_addr = f"[{addr}]"
return ret_addr

View File

@ -4,23 +4,28 @@ import json
from .. import mgr
class NvmeofGatewayAlreadyExists(Exception):
def __init__(self, gateway_name):
super(NvmeofGatewayAlreadyExists, self).__init__(
"NVMe-oF gateway '{}' already exists".format(gateway_name))
class NvmeofGatewayDoesNotExist(Exception):
def __init__(self, hostname):
super(NvmeofGatewayDoesNotExist, self).__init__(
"NVMe-oF gateway '{}' does not exist".format(hostname))
class ManagedByOrchestratorException(Exception):
def __init__(self):
super(ManagedByOrchestratorException, self).__init__(
"NVMe-oF configuration is managed by the orchestrator")
_NVMEOF_STORE_KEY = "_nvmeof_config"
class NvmeofGatewaysConfig(object):
@classmethod
def _load_config_from_store(cls):
@ -33,11 +38,11 @@ class NvmeofGatewaysConfig(object):
@classmethod
def _save_config(cls, config):
mgr.set_store(_NVMEOF_STORE_KEY, json.dumps(config))
@classmethod
def get_gateways_config(cls):
return cls._load_config_from_store()
@classmethod
def add_gateway(cls, name, service_url):
config = cls.get_gateways_config()
@ -45,7 +50,7 @@ class NvmeofGatewaysConfig(object):
raise NvmeofGatewayAlreadyExists(name)
config['gateways'][name] = {'service_url': service_url}
cls._save_config(config)
@classmethod
def remove_gateway(cls, name):
config = cls.get_gateways_config()

View File

@ -31,21 +31,21 @@ enum AddressFamily {
enum LogLevel {
DISABLED = 0;
ERROR = 1;
WARN = 2;
WARNING = 2;
NOTICE = 3;
INFO = 4;
DEBUG = 5;
}
enum AutoHAState {
AUTO_HA_UNSET = 0;
AUTO_HA_OFF = 1;
AUTO_HA_ON = 2;
}
service Gateway {
// Creates a bdev from an RBD image
rpc create_bdev(create_bdev_req) returns (bdev) {}
// Resizes a bdev
rpc resize_bdev(resize_bdev_req) returns (req_status) {}
// Deletes a bdev
rpc delete_bdev(delete_bdev_req) returns (req_status) {}
// Creates a namespace from an RBD image
rpc namespace_add(namespace_add_req) returns (nsid_status) {}
// Creates a subsystem
rpc create_subsystem(create_subsystem_req) returns(req_status) {}
@ -53,11 +53,23 @@ service Gateway {
// Deletes a subsystem
rpc delete_subsystem(delete_subsystem_req) returns(req_status) {}
// Adds a namespace to a subsystem
rpc add_namespace(add_namespace_req) returns(nsid_status) {}
// List namespaces
rpc list_namespaces(list_namespaces_req) returns(namespaces_info) {}
// Removes a namespace from a subsystem
rpc remove_namespace(remove_namespace_req) returns(req_status) {}
// Resizes a namespace
rpc namespace_resize(namespace_resize_req) returns (req_status) {}
// Gets namespace's IO stats
rpc namespace_get_io_stats(namespace_get_io_stats_req) returns (namespace_io_stats_info) {}
// Sets namespace's qos limits
rpc namespace_set_qos_limits(namespace_set_qos_req) returns (req_status) {}
// Changes namespace's load balancing group
rpc namespace_change_load_balancing_group(namespace_change_load_balancing_group_req) returns (req_status) {}
// Deletes a namespace
rpc namespace_delete(namespace_delete_req) returns (req_status) {}
// Adds a host to a subsystem
rpc add_host(add_host_req) returns (req_status) {}
@ -65,70 +77,104 @@ service Gateway {
// Removes a host from a subsystem
rpc remove_host(remove_host_req) returns (req_status) {}
// List hosts
rpc list_hosts(list_hosts_req) returns(hosts_info) {}
// List connections
rpc list_connections(list_connections_req) returns(connections_info) {}
// Creates a listener for a subsystem at a given IP/Port
rpc create_listener(create_listener_req) returns(req_status) {}
// Deletes a listener from a subsystem at a given IP/Port
rpc delete_listener(delete_listener_req) returns(req_status) {}
// Gets subsystems
rpc get_subsystems(get_subsystems_req) returns(subsystems_info) {}
// List listeners
rpc list_listeners(list_listeners_req) returns(listeners_info) {}
// List subsystems
rpc list_subsystems(list_subsystems_req) returns(subsystems_info) {}
// Gets spdk nvmf log flags and level
rpc get_spdk_nvmf_log_flags_and_level(get_spdk_nvmf_log_flags_and_level_req) returns(spdk_nvmf_log_flags_and_level_info) {}
// Disables spdk nvmf logs
rpc disable_spdk_nvmf_logs(disable_spdk_nvmf_logs_req) returns(req_status) {}
// Disables spdk nvmf logs
rpc disable_spdk_nvmf_logs(disable_spdk_nvmf_logs_req) returns(req_status) {}
// Set spdk nvmf logs
rpc set_spdk_nvmf_logs(set_spdk_nvmf_logs_req) returns(req_status) {}
// Set spdk nvmf logs
// Get gateway info
rpc get_gateway_info(get_gateway_info_req) returns(gateway_info) {}
}
// Request messages
message create_bdev_req {
string bdev_name = 1;
string rbd_pool_name = 2;
string rbd_image_name = 3;
int32 block_size = 4;
optional string uuid = 5;
message namespace_add_req {
string rbd_pool_name = 1;
string rbd_image_name = 2;
string subsystem_nqn = 3;
optional uint32 nsid = 4;
uint32 block_size = 5;
optional string uuid = 6;
optional int32 anagrpid = 7;
optional bool create_image = 8;
optional uint32 size = 9;
}
message resize_bdev_req {
string bdev_name = 1;
int32 new_size = 2;
message namespace_resize_req {
string subsystem_nqn = 1;
optional uint32 nsid = 2;
optional string uuid = 3;
uint32 new_size = 4;
}
message delete_bdev_req {
string bdev_name = 1;
bool force = 2;
message namespace_get_io_stats_req {
string subsystem_nqn = 1;
optional uint32 nsid = 2;
optional string uuid = 3;
}
message namespace_set_qos_req {
string subsystem_nqn = 1;
optional uint32 nsid = 2;
optional string uuid = 3;
optional uint64 rw_ios_per_second = 4;
optional uint64 rw_mbytes_per_second = 5;
optional uint64 r_mbytes_per_second = 6;
optional uint64 w_mbytes_per_second = 7;
}
message namespace_change_load_balancing_group_req {
string subsystem_nqn = 1;
optional uint32 nsid = 2;
optional string uuid = 3;
int32 anagrpid = 4;
}
message namespace_delete_req {
string subsystem_nqn = 1;
optional uint32 nsid = 2;
optional string uuid = 3;
}
message create_subsystem_req {
string subsystem_nqn = 1;
string serial_number = 2;
int32 max_namespaces = 3;
bool ana_reporting = 4;
bool enable_ha = 5;
optional uint32 max_namespaces = 3;
bool ana_reporting = 4;
bool enable_ha = 5;
}
message delete_subsystem_req {
string subsystem_nqn = 1;
optional bool force = 2;
}
message add_namespace_req {
string subsystem_nqn = 1;
string bdev_name = 2;
optional uint32 nsid = 3;
optional int32 anagrpid = 4;
}
message remove_namespace_req {
string subsystem_nqn = 1;
uint32 nsid = 2;
message list_namespaces_req {
string subsystem = 1;
optional uint32 nsid = 2;
optional string uuid = 3;
}
message add_host_req {
@ -141,25 +187,40 @@ message remove_host_req {
string host_nqn = 2;
}
message list_hosts_req {
string subsystem = 1;
}
message list_connections_req {
string subsystem = 1;
}
message create_listener_req {
string nqn = 1;
string gateway_name = 2;
TransportType trtype = 3;
AddressFamily adrfam = 4;
string traddr = 5;
string trsvcid = 6;
string traddr = 3;
optional TransportType trtype = 4;
optional AddressFamily adrfam = 5;
optional uint32 trsvcid = 6;
optional AutoHAState auto_ha_state = 7;
}
message delete_listener_req {
string nqn = 1;
string gateway_name = 2;
TransportType trtype = 3;
AddressFamily adrfam = 4;
string traddr = 5;
string trsvcid = 6;
string traddr = 3;
optional TransportType trtype = 4;
optional AddressFamily adrfam = 5;
optional uint32 trsvcid = 6;
}
message get_subsystems_req {
message list_listeners_req {
string subsystem = 1;
}
message list_subsystems_req {
optional string subsystem_nqn = 1;
optional string serial_number = 2;
}
message get_spdk_nvmf_log_flags_and_level_req {
@ -174,74 +235,175 @@ message set_spdk_nvmf_logs_req {
}
message get_gateway_info_req {
string cli_version = 1;
optional string cli_version = 1;
}
// Return messages
message bdev {
string bdev_name = 1;
bool status = 2;
message bdev_status {
int32 status = 1;
string error_message = 2;
string bdev_name = 3;
}
message req_status {
bool status = 1;
int32 status = 1;
string error_message = 2;
}
message nsid_status {
uint32 nsid = 1;
bool status = 2;
int32 status = 1;
string error_message = 2;
uint32 nsid = 3;
}
message subsystems_info {
repeated subsystem subsystems = 1;
int32 status = 1;
string error_message = 2;
repeated subsystem subsystems = 3;
}
message subsystem {
string nqn = 1;
string subtype = 2;
repeated listen_address listen_addresses = 3;
repeated host hosts = 4;
bool allow_any_host = 5;
optional string serial_number = 6;
optional string model_number = 7;
optional uint32 max_namespaces = 8;
optional uint32 min_cntlid = 9;
optional uint32 max_cntlid = 10;
repeated namespace namespaces = 11;
bool enable_ha = 2;
string serial_number = 3;
string model_number = 4;
uint32 min_cntlid = 5;
uint32 max_cntlid = 6;
uint32 namespace_count = 7;
string subtype = 8;
}
message gateway_info {
string cli_version = 1;
string gateway_version = 2;
string gateway_name = 3;
string gateway_group = 4;
string gateway_addr = 5;
string gateway_port = 6;
bool status = 7;
string version = 2;
string name = 3;
string group = 4;
string addr = 5;
string port = 6;
bool bool_status = 7;
int32 status = 8;
string error_message = 9;
string spdk_version = 10;
}
message listen_address {
string transport = 1;
message cli_version {
int32 status = 1;
string error_message = 2;
string version = 3;
}
message gw_version {
int32 status = 1;
string error_message = 2;
string version = 3;
}
message listener_info {
string gateway_name = 1;
TransportType trtype = 2;
AddressFamily adrfam = 3;
string traddr = 4;
string trsvcid = 5;
uint32 trsvcid = 5;
}
message listeners_info {
int32 status = 1;
string error_message = 2;
repeated listener_info listeners = 3;
}
message host {
string nqn = 1;
}
message hosts_info {
int32 status = 1;
string error_message = 2;
bool allow_any_host = 3;
string subsystem_nqn = 4;
repeated host hosts = 5;
}
message connection {
string nqn = 1;
string traddr = 2;
uint32 trsvcid = 3;
TransportType trtype = 4;
AddressFamily adrfam = 5;
bool connected = 6;
int32 qpairs_count = 7;
int32 controller_id = 8;
}
message connections_info {
int32 status = 1;
string error_message = 2;
string subsystem_nqn = 3;
repeated connection connections = 4;
}
message namespace {
uint32 nsid = 1;
string name = 2;
optional string bdev_name = 3;
optional string nguid = 4;
optional string uuid = 5;
optional uint32 anagrpid = 6;
uint32 nsid = 1;
string bdev_name = 2;
string rbd_image_name = 3;
string rbd_pool_name = 4;
uint32 load_balancing_group = 5;
uint32 block_size = 6;
uint64 rbd_image_size = 7;
string uuid = 8;
uint64 rw_ios_per_second = 9;
uint64 rw_mbytes_per_second = 10;
uint64 r_mbytes_per_second = 11;
uint64 w_mbytes_per_second = 12;
}
message namespaces_info {
int32 status = 1;
string error_message = 2;
string subsystem_nqn = 3;
repeated namespace namespaces = 4;
}
message namespace_io_stats_info {
int32 status = 1;
string error_message = 2;
string subsystem_nqn = 3;
uint32 nsid = 4;
string uuid = 5;
string bdev_name = 6;
uint64 tick_rate = 7;
uint64 ticks = 8;
uint64 bytes_read = 9;
uint64 num_read_ops = 10;
uint64 bytes_written = 11;
uint64 num_write_ops = 12;
uint64 bytes_unmapped = 13;
uint64 num_unmap_ops = 14;
uint64 read_latency_ticks = 15;
uint64 max_read_latency_ticks = 16;
uint64 min_read_latency_ticks = 17;
uint64 write_latency_ticks = 18;
uint64 max_write_latency_ticks = 19;
uint64 min_write_latency_ticks = 20;
uint64 unmap_latency_ticks = 21;
uint64 max_unmap_latency_ticks = 22;
uint64 min_unmap_latency_ticks = 23;
uint64 copy_latency_ticks = 24;
uint64 max_copy_latency_ticks = 25;
uint64 min_copy_latency_ticks = 26;
repeated uint32 io_error = 27;
}
message spdk_log_flag_info {
string name = 1;
bool enabled = 2;
}
message spdk_nvmf_log_flags_and_level_info {
string flags_level =1;
int32 status = 1;
string error_message = 2;
repeated spdk_log_flag_info nvmf_log_flags = 3;
LogLevel log_level = 4;
LogLevel log_print_level = 5;
}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -14,6 +14,7 @@ addopts =
--cov --cov-append --cov-report=term
--doctest-modules
--ignore=frontend/ --ignore=module.py
--ignore=services/proto/
--instafail
[base]
@ -70,6 +71,7 @@ exclude =
.eggs,
venv,
frontend,
services/proto
statistics = True
#TODO: Uncomment and refactor (https://tracker.ceph.com/issues/41221)
#max-complexity = 10