import logging
from typing import Any, Dict, Optional
+from orchestrator import OrchestratorError
+
from .. import mgr
from ..model import nvmeof as model
from ..security import Scope
NVMeoFClient.pb2.get_gateway_info_req()
)
+ @ReadPermission
+ @Endpoint('GET')
+ def group(self):
+ try:
+ orch = OrchClient.instance()
+ return orch.services.list(service_type='nvmeof')
+ except OrchestratorError as e:
+ # just return none instead of raising an exception
+ # since we need this to work regardless of the status
+ # of orchestrator in UI
+ logger.error('Failed to fetch the gateway groups: %s', e)
+ return None
+
@APIRouter("/nvmeof/subsystem", Scope.NVME_OF)
@APIDoc("NVMe-oF Subsystem Management API", "NVMe-oF Subsystem")
class NVMeoFSubsystem(RESTController):
@CLIWriteCommand('dashboard nvmeof-gateway-add')
@CLICheckNonemptyFileInput(desc='NVMe-oF gateway configuration')
-def add_nvmeof_gateway(_, inbuf, name: str, group: str):
+def add_nvmeof_gateway(_, inbuf, name: str, group: str, daemon_name: str):
'''
Add NVMe-oF gateway configuration. Gateway URL read from -i <file>
'''
service_url = inbuf
try:
- NvmeofGatewaysConfig.add_gateway(name, service_url, group)
+ NvmeofGatewaysConfig.add_gateway(name, service_url, group, daemon_name)
return 0, 'Success', ''
except NvmeofGatewayAlreadyExists as ex:
return -errno.EEXIST, '', str(ex)
return cls._load_config_from_store()
@classmethod
- def add_gateway(cls, name, service_url, group):
+ def add_gateway(cls, name, service_url, group, daemon_name):
config = cls.get_gateways_config()
if name in config.get('gateways', {}):
existing_gateways = config['gateways'][name]
- if any(gateway['service_url'] == service_url for gateway in existing_gateways):
- return
+ for gateway in existing_gateways:
+ if 'daemon_name' not in gateway:
+ gateway['daemon_name'] = daemon_name
+ break
+ if gateway['service_url'] == service_url:
+ return
+
+ new_gateway = {
+ 'service_url': service_url,
+ 'group': group,
+ 'daemon_name': daemon_name
+ }
if name in config.get('gateways', {}):
- config['gateways'][name].append({'service_url': service_url, 'group': group})
+ config['gateways'][name].append(new_gateway)
else:
- config['gateways'][name] = [{'service_url': service_url, 'group': group}]
+ config['gateways'][name] = [new_gateway]
cls._save_config(config)
return None
if group:
- for service_name, entries in gateways.items():
- if group in service_name:
- entry = next((entry for entry in entries if entry['group'] == group), None)
- if entry['group'] == group: # type: ignore
- return service_name, entry['service_url'] # type: ignore
- return None
+ return cls._get_name_url_for_group(gateways, group)
+
+ return cls._get_default_service(gateways)
- service_name = list(gateways.keys())[0]
- return service_name, config['gateways'][service_name][0]['service_url']
except (KeyError, IndexError) as e:
raise DashboardException(
msg=f'NVMe-oF configuration is not set: {e}',
# just return None if any orchestrator error is raised
# otherwise nvmeof api will raise this error and doesn't proceed.
return None
+
+ @classmethod
+ def _get_name_url_for_group(cls, gateways, group):
+ try:
+ orch = OrchClient.instance()
+ for service_name, svc_config in gateways.items():
+ # get the group name of the service and match it against the
+ # group name provided
+ group_name_from_svc = orch.services.get(service_name)[0].spec.group
+ if group == group_name_from_svc:
+ running_daemons = cls._get_running_daemons(orch, service_name)
+ config = cls._get_running_daemon_svc_config(svc_config, running_daemons)
+
+ if config:
+ return service_name, config['service_url']
+ return None
+
+ except OrchestratorError:
+ return cls._get_default_service(gateways)
+
+ @classmethod
+ def _get_running_daemons(cls, orch, service_name):
+ # get the running nvmeof daemons
+ daemons = [d.to_dict()
+ for d in orch.services.list_daemons(service_name=service_name)]
+ return [d['daemon_name'] for d in daemons
+ if d['status_desc'] == 'running']
+
+ @classmethod
+ def _get_running_daemon_svc_config(cls, svc_config, running_daemons):
+ try:
+ return next(config for config in svc_config
+ if config['daemon_name'] in running_daemons)
+ except StopIteration:
+ return None
+
+ @classmethod
+ def _get_default_service(cls, gateways):
+ if gateways:
+ service_name = list(gateways.keys())[0]
+ return service_name, gateways[service_name][0]['service_url']
+ return None