mirror of
https://github.com/ceph/ceph
synced 2025-04-01 14:51:13 +00:00
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:
parent
1b768332b1
commit
35e40c4e8f
@ -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
1
debian/control
vendored
@ -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>,
|
||||
|
@ -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
|
||||
|
||||
|
@ -4,5 +4,3 @@ bcrypt~=3.1
|
||||
python3-saml~=1.4
|
||||
requests~=2.26
|
||||
Routes~=2.4
|
||||
grpcio~=1.48
|
||||
grpcio-tools~=1.48
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -11,3 +11,5 @@ pyyaml
|
||||
natsort
|
||||
setuptools
|
||||
jsonpatch
|
||||
grpcio==1.46.5
|
||||
grpcio-tools==1.46.5
|
||||
|
@ -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):
|
||||
'''
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user