if allow_all:
return NVMeoFClient(gw_group=gw_group,
- server_address=server_address).stub.add_host(
+ traddr=server_address).stub.add_host(
NVMeoFClient.pb2.add_host_req(
subsystem_nqn=subsystem_nqn,
host_nqn="*",
key = h.get("dhchap_key")
response = NVMeoFClient(gw_group=gw_group,
- server_address=server_address).stub.add_host(
+ traddr=server_address).stub.add_host(
NVMeoFClient.pb2.add_host_req(
subsystem_nqn=subsystem_nqn,
host_nqn=nqn,
for del_nqn in to_delete_nqns:
response = NVMeoFClient(gw_group=gw_group,
- server_address=server_address).stub.remove_host(
+ traddr=server_address).stub.remove_host(
NVMeoFClient.pb2.remove_host_req(subsystem_nqn=subsystem_nqn, host_nqn=del_nqn)
)
if response.status != 0:
for nqn in all_host_nqns:
response = NVMeoFClient(gw_group=gw_group,
- server_address=server_address).stub.namespace_add_host(
+ traddr=server_address).stub.namespace_add_host(
NVMeoFClient.pb2.namespace_add_host_req(subsystem_nqn=subsystem_nqn,
nsid=int(nsid),
host_nqn=nqn,
for del_nqn in to_delete_nqns:
response = NVMeoFClient(gw_group=gw_group,
- server_address=server_address).stub.namespace_delete_host(
+ traddr=server_address).stub.namespace_delete_host(
NVMeoFClient.pb2.namespace_delete_host_req(
subsystem_nqn=subsystem_nqn,
nsid=int(nsid),
import { of } from 'rxjs';
import { HttpClientModule } from '@angular/common/http';
import { SharedModule } from '~/app/shared/shared.module';
+import { provideAnimations } from '@angular/platform-browser/animations';
+import { provideToastr } from 'ngx-toastr';
describe('NvmeofGatewayGroupComponent', () => {
let component: NvmeofGatewayGroupComponent;
await TestBed.configureTestingModule({
imports: [HttpClientModule, SharedModule, TabsModule, GridModule],
declarations: [NvmeofGatewayGroupComponent],
- providers: [{ provide: NvmeofService, useValue: nvmeofServiceSpy }]
+ providers: [
+ provideAnimations(),
+ provideToastr(),
+ { provide: NvmeofService, useValue: nvmeofServiceSpy }
+ ]
}).compileComponents();
fixture = TestBed.createComponent(NvmeofGatewayGroupComponent);
import { ActivatedRoute } from '@angular/router';
import { BehaviorSubject, of, throwError } from 'rxjs';
-import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+import { BrowserAnimationsModule, provideAnimations } from '@angular/platform-browser/animations';
import { RouterTestingModule } from '@angular/router/testing';
import { CephModule } from '~/app/ceph/ceph.module';
import { configureTestBed } from '~/testing/unit-test-helper';
import { TagModule } from 'carbon-components-angular';
import { NvmeofGatewayNodeComponent } from './nvmeof-gateway-node.component';
+import { provideToastr } from 'ngx-toastr';
describe('NvmeofGatewayNodeComponent', () => {
let component: NvmeofGatewayNodeComponent;
hostname: 'gateway-node-3',
addr: '192.168.1.12',
status: '',
- labels: [],
- services: [],
+ labels: [] as string[],
+ services: [] as string[],
ceph_version: 'ceph version 18.0.0',
sources: {
ceph: true,
TagModule
],
providers: [
+ provideAnimations(),
+ provideToastr(),
{ provide: AuthStorageService, useValue: fakeAuthStorageService },
{
provide: ActivatedRoute,
const hosts = group.placement?.hosts || (group.spec as any)?.placement?.hosts || [];
hosts.forEach((hostname: string) => allUsedHostnames.add(hostname));
- const label = group.placement?.label || group.spec?.placement?.label;
+ const label = group.placement?.label || (group.spec as any)?.placement?.label;
if (label) {
(hostList || []).forEach((host: Host) => {
if (host.labels?.includes(label as string)) {
this.hosts = [];
} else {
const placementHosts =
- this.serviceSpec.placement?.hosts || this.serviceSpec.spec?.placement?.hosts || [];
+ this.serviceSpec.placement?.hosts || (this.serviceSpec.spec as any)?.placement?.hosts || [];
const placementLabel =
- this.serviceSpec.placement?.label || this.serviceSpec.spec?.placement?.label;
+ this.serviceSpec.placement?.label || (this.serviceSpec.spec as any)?.placement?.label;
if (placementHosts.length > 0) {
const currentGroupHosts = new Set<string>(placementHosts);
import { NvmeofService } from '~/app/shared/api/nvmeof.service';
import { SharedModule } from '~/app/shared/shared.module';
import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
+import { provideAnimations } from '@angular/platform-browser/animations';
+import { provideToastr } from 'ngx-toastr';
describe('NvmeofSubsystemNamespacesListComponent', () => {
let component: NvmeofSubsystemNamespacesListComponent;
declarations: [NvmeofSubsystemNamespacesListComponent],
imports: [HttpClientTestingModule, RouterTestingModule, SharedModule],
providers: [
+ provideAnimations(),
+ provideToastr(),
{
provide: ActivatedRoute,
useValue: {
}
.details-grid {
+ column-gap: layout.$spacing-07;
display: grid;
grid-template-columns: repeat(3, 1fr);
row-gap: layout.$spacing-06;
- column-gap: layout.$spacing-07;
}
.detail-item {
.cd-nvmeof-subsystem-step-two {
&-manual-hosts {
- display: flex;
align-items: flex-start;
+ display: flex;
}
&-manual-hosts-input {
removeHost(removedHost: string) {
const currentAddedHosts = this.formGroup.get('addedHosts')?.value ?? [];
- const newHostList = currentAddedHosts.filter((currentHost: string) => currentHost !== removedHost);
+ const newHostList = currentAddedHosts.filter(
+ (currentHost: string) => currentHost !== removedHost
+ );
this.addedHostsLength = newHostList.length;
this.formGroup.patchValue({
addedHosts: newHostList
.auth-radio {
+ align-items: flex-start;
display: flex;
flex-direction: column;
- align-items: flex-start;
}
.text-helper {
const request = {
nqn: mockNQN,
gw_group: mockGroupName,
- dhchap_key: null
+ dhchap_key: null as string | null
};
service.createSubsystem(request).subscribe();
const req = httpTesting.expectOne(`${API_PATH}/subsystem`);
describe('test initiators APIs', () => {
let request = { host_nqn: '', gw_group: mockGroupName };
- let addRequest = { hosts: [], allow_all: true, gw_group: mockGroupName };
+ let addRequest = {
+ hosts: [] as { dhchap_key: string; host_nqn: string }[],
+ allow_all: true,
+ gw_group: mockGroupName
+ };
it('should call getInitiators', () => {
service.getInitiators(mockNQN, mockGroupName).subscribe();
const req = httpTesting.expectOne(
it('should filter hosts by direct host placement', (done) => {
const mockGroups = [
- [{ spec: { group: 'default' }, placement: { hosts: ['host1', 'host3'], label: [] } }]
+ [
+ {
+ spec: { group: 'default' },
+ placement: { hosts: ['host1', 'host3'], label: [] as string[] }
+ }
+ ]
];
mockHostService.getAllHosts.mockReturnValue(of(allHosts));
it('should filter hosts by string label placement', (done) => {
const mockGroups = [
- [{ spec: { group: 'default' }, placement: { hosts: [], label: 'nvmeof' } }]
+ [{ spec: { group: 'default' }, placement: { hosts: [] as string[], label: 'nvmeof' } }]
];
mockHostService.getAllHosts.mockReturnValue(of(allHosts));
it('should return empty array when group not found', (done) => {
const mockGroups = [
- [{ spec: { group: 'other' }, placement: { hosts: ['host1'], label: [] } }]
+ [{ spec: { group: 'other' }, placement: { hosts: ['host1'], label: [] as string[] } }]
];
mockHostService.getAllHosts.mockReturnValue(of(allHosts));
});
it('should return empty array when placement has no hosts or labels', (done) => {
- const mockGroups = [[{ spec: { group: 'default' }, placement: { hosts: [], label: [] } }]];
+ const mockGroups = [
+ [
+ {
+ spec: { group: 'default' },
+ placement: { hosts: [] as string[], label: [] as string[] }
+ }
+ ]
+ ];
mockHostService.getAllHosts.mockReturnValue(of(allHosts));
service.getHostsForGroup('default').subscribe((hosts: any[]) => {
TagModule,
LinkModule,
LayerModule,
- TilesModule
+ TilesModule,
+ ThemeModule
} from 'carbon-components-angular';
import { MotdComponent } from '~/app/shared/components/motd/motd.component';
import { ProgressComponent } from './progress/progress.component';
import { TearsheetComponent } from './tearsheet/tearsheet.component';
import { TearsheetStepComponent } from './tearsheet-step/tearsheet-step.component';
+import { SidePanelComponent } from './side-panel/side-panel.component';
+
// Icons
import InfoIcon from '@carbon/icons/es/information/16';
import CopyIcon from '@carbon/icons/es/copy/32';
import InformationFilledIcon from '@carbon/icons/es/information--filled/16';
import WarningFilledIcon from '@carbon/icons/es/warning--filled/16';
import NotificationFilledIcon from '@carbon/icons/es/notification--filled/16';
+import DataViewAlt16 from '@carbon/icons/es/data--view--alt/16';
+import DataCenter16 from '@carbon/icons/es/data--center/16';
+import Upgrade16 from '@carbon/icons/es/upgrade/16';
+import Close16 from '@carbon/icons/es/close/16';
+import WarningAltFilled16 from '@carbon/icons/es/warning--alt--filled/16';
+import Help16 from '@carbon/icons/es/help/16';
+import IncidentReporter16 from '@carbon/icons/es/incident-reporter/16';
+import IbmStreamSets16 from '@carbon/icons/es/ibm--streamsets/16';
+import DataEnrichment16 from '@carbon/icons/es/data-enrichment/16';
+import Network116 from '@carbon/icons/es/network--1/16';
+import Chip16 from '@carbon/icons/es/chip/16';
+import Plug16 from '@carbon/icons/es/plug/16';
+import VmdkDisk16 from '@carbon/icons/es/vmdk-disk/16';
+import WarningAlt16 from '@carbon/icons/es/warning--alt/16';
+import CheckMarkOutline16 from '@carbon/icons/es/checkmark--outline/16';
+import ArrowUpRight16 from '@carbon/icons/es/arrow--up-right/16';
+import InProgress16 from '@carbon/icons/es/in-progress/16';
+import ArrowDown16 from '@carbon/icons/es/arrow--down/16';
import Warning16 from '@carbon/icons/es/warning/16';
import Deploy16 from '@carbon/icons/es/deploy/16';
-import Close16 from '@carbon/icons/es/close/16';
import { SidebarLayoutComponent } from './sidebar-layout/sidebar-layout.component';
@NgModule({
TagModule,
LinkModule,
LayerModule,
- TilesModule
+ TilesModule,
+ ThemeModule
],
declarations: [
SparklineComponent,
IconComponent,
TearsheetComponent,
TearsheetStepComponent,
+ SidePanelComponent,
SidebarLayoutComponent
],
providers: [provideCharts(withDefaultRegisterables())],
IconComponent,
TearsheetComponent,
TearsheetStepComponent,
+ SidePanelComponent,
SidebarLayoutComponent
]
})
WarningFilledIcon,
NotificationFilledIcon,
Close16,
+ DataViewAlt16,
+ DataCenter16,
+ Upgrade16,
+ WarningAltFilled16,
+ Help16,
+ IncidentReporter16,
+ IbmStreamSets16,
+ DataEnrichment16,
+ Network116,
+ Chip16,
+ Plug16,
+ VmdkDisk16,
+ WarningAlt16,
+ CheckMarkOutline16,
+ ArrowUpRight16,
+ InProgress16,
+ ArrowDown16,
Deploy16,
- Warning16,
+ Warning16
]);
}
-}
+}
\ No newline at end of file
}
.danger-icon {
- fill: theme.$support-error !important;
-}
-
-.error-icon {
- fill: theme.$support-error !important;
+ color: theme.$support-error !important;
}
//@TODO: this naming needs to be changed
}
.warning-icon {
- color: theme.$support-caution-major;
+ fill: theme.$support-caution-major !important;
}
.warningAltFilled-icon {
- color: theme.$support-caution-major;
+ fill: theme.$support-caution-major !important;
+}
+
+.error-icon {
+ fill: var(--cds-text-error) !important;
+}
+
+.info-icon {
+ fill: theme.$support-info !important;
}
.deploy-icon {
.emptySearch-icon {
fill: theme.$layer-selected-disabled !important;
}
+
+.warningAlt-icon {
+ fill: theme.$support-caution-major !important;
+}
+
+.checkMarkOutline-icon {
+ fill: theme.$support-success !important;
+}
+
+.inProgress-icon {
+ fill: theme.$support-info !important;
+}
+
+.arrowDown-icon {
+ fill: theme.$support-error !important;
+}
@use '@carbon/layout';
.sidebar-layout-container {
+ background-color: var(--cds-background);
min-height: calc(100vh - (vv.$navbar-height + layout.rem(55px)));
padding-right: var(--cds-spacing-07);
- background-color: var(--cds-background);
}
.sidebar-layout-shell {
- transform: translate(0);
- position: relative;
height: 100vh;
+ position: relative;
+ transform: translate(0);
}
.sidebar-layout-nav {
// No css variable to apply css to modal div.
// This is needed to set the width of tearsheet as per carbon standards.
.cds--modal-container.cds--modal-container--lg {
- position: fixed;
+ // Fill remaining viewport height
+ block-size: calc(100vh - 88px);
+ display: flex;
+ flex-direction: column;
+ inline-size: auto;
// 88px from top
inset-block-start: 88px;
-
- // Fill remaining viewport height
- block-size: calc(100vh - 88px);
- max-block-size: calc(100vh - 88px);
+ inset-inline-end: 64px;
// 64px margins left & right
inset-inline-start: 64px;
- inset-inline-end: 64px;
- inline-size: auto;
+ max-block-size: calc(100vh - 88px);
max-inline-size: none;
- display: flex;
- flex-direction: column;
+ position: fixed;
}
// Global Carbon override sets .cds--modal-scroll-content to max-height: 70vh.
// For tearsheets this causes content area to shrink and footer to float up.
.cds--modal-container.cds--modal-container--lg .cds--modal-scroll-content {
- max-height: none;
- height: 100%;
flex: 1 1 auto;
+ height: 100%;
+ max-height: none;
min-height: 0;
}
.cds--modal-container.cds--modal-container--sm {
- inset-block-start: 88px;
block-size: 50vh;
- max-block-size: 50vh;
- inset-inline-start: 35%;
- inset-inline-end: 35%;
inline-size: auto;
+ inset-block-start: 88px;
+ inset-inline-end: 35%;
+ inset-inline-start: 35%;
+ max-block-size: 50vh;
max-inline-size: none;
}
// HEADER
.tearsheet-header {
- fill: var(--cds-icon-primary);
background-color: var(--cds-background);
- padding: var(--cds-spacing-06) var(--cds-spacing-07);
border-block-end: 1px solid var(--cds-border-subtle-01);
fill: var(--cds-icon-primary);
+ fill: var(--cds-icon-primary);
+ padding: var(--cds-spacing-06) var(--cds-spacing-07);
padding: var(--cds-spacing-06) var(--cds-spacing-07);
&-title {
// BODY
.tearsheet-body {
height: 100%;
+ height: 100%;
+ margin: 0;
margin: 0;
padding: 0;
+ padding: 0;
padding-block: 0;
padding-inline: 0;
- padding: 0;
- margin: 0;
- height: 100%;
}
.tearsheet-left-influencer {
background-color: var(--cds-background);
- padding: var(--cds-spacing-06) var(--cds-spacing-07);
- overflow-block: auto;
- overflow-y: auto;
border-inline-end: 1px solid var(--cds-border-subtle-01);
margin: 0;
+ overflow-block: auto;
+ overflow-y: auto;
+ padding: var(--cds-spacing-06) var(--cds-spacing-07);
}
.tearsheet-right-influencer {
}
.tearsheet-main {
- margin: 0;
- height: 100%;
display: flex;
flex-direction: column;
+ height: 100%;
+ margin: 0;
> div {
flex: 1;
}
.tearsheet-content {
- max-block-size: 39.7rem;
background-color: var(--cds-layer-01);
margin: 0;
- padding: var(--cds-spacing-06) var(--cds-spacing-07);
+ max-block-size: 39.7rem;
overflow-y: auto;
+ padding: var(--cds-spacing-06) var(--cds-spacing-07);
&--full {
padding-left: 0;
// make content fill the available modal height so footer stays pinned.
.tearsheet-main > .tearsheet-content {
flex: 1 1 auto;
- min-height: 0;
max-block-size: none;
+ min-height: 0;
}
//FOOTER
.tearsheet-footer {
- border-top: 1px solid var(--cds-border-subtle);
background-color: var(--cds-layer-01);
+ border-top: 1px solid var(--cds-border-subtle);
&-submit {
display: flex;
checkmarkOutline = 'checkmark--outline',
circleDash = 'circle-dash',
datastore = 'datastore',
+ ibmCloudBareMetalServer = 'ibm-cloud--bare-metal-server',
+ ibmCloudDedicatedHost = 'ibm-cloud--dedicated-host',
+ clusterIcon = 'web-services--cluster',
/* Icons for special effect */
large = 'fa fa-lg', // icon becomes 33% larger
large2x = 'fa fa-2x', // icon becomes 50% larger
pulse = 'fa fa-pulse', // To have spinner rotate with 8 steps
spin = 'fa fa-spin', // To get any icon to rotate
inverse = 'fa fa-inverse', // To get an alternative icon color
+ notification = 'notification',
+ error = 'error--filled',
+ notificationOff = 'notification--off',
+ notificationNew = 'notification--new',
+ emptySearch = 'search',
+ dataViewAlt = 'data--view--alt',
+ dataCenter = 'data--center',
+ upgrade = 'upgrade',
+ warningAltFilled = 'warning--alt--filled',
+ help = 'help',
+ incidentReporter = 'incident-reporter',
+ ibmStreamSets = 'ibm--streamsets',
+ dataEnrichment = 'data-enrichment',
+ network1 = 'network--1',
+ chip = 'chip',
+ plug = 'plug',
+ vmdkDisk = 'vmdk-disk',
+ checkMarkOutline = 'checkmark--outline',
+ warningAlt = 'warning--alt',
+ arrowUpRight = 'arrow--up-right',
+ inProgress = 'in-progress',
+ arrowDown = 'arrow--down'
}
export enum IconSize {
danger: 'warning--filled',
infoCircle: 'information--filled',
success: 'checkmark--filled',
- warning: 'warning',
- warningAltFilled: 'warning--alt--filled',
deploy: 'deploy',
edit: 'edit',
error: 'error--filled',
notificationOff: 'notification--off',
notificationNew: 'notification--new',
add: 'add',
- emptySearch: 'emptySearch'
+ emptySearch: 'emptySearch',
+ dataViewAlt: 'data--view--alt',
+ dataCenter: 'data--center',
+ upgrade: 'upgrade',
+ warningAltFilled: 'warning--alt--filled',
+ help: 'help',
+ incidentReporter: 'incident-reporter',
+ ibmStreamSets: 'ibm--streamsets',
+ dataEnrichment: 'data-enrichment',
+ network1: 'network--1',
+ chip: 'chip',
+ plug: 'plug',
+ vmdkDisk: 'vmdk-disk',
+ warningAlt: 'warning--alt',
+ checkMarkOutline: 'checkmark--outline',
+ arrowUpRight: ' arrow--up-right',
+ inProgress: 'in-progress',
+ arrowDown: 'arrow--down',
+ warning: 'warning',
} as const;
export const EMPTY_STATE_IMAGE = {
padding-top: layout.$spacing-03;
}
+.cds-pr-8 {
+ padding-right: layout.$spacing-08;
+}
+
// MARGINS
.cds-m-0 {
margin: 0;
margin-bottom: layout.$spacing-03;
}
+.cds-mb-4 {
+ margin-bottom: layout.$spacing-04;
+}
+
.cds-mb-5 {
margin-bottom: layout.$spacing-05;
}
margin-bottom: layout.$spacing-06;
}
+.cds-mt-1 {
+ margin-top: layout.$spacing-01;
+}
+
.cds-mt-3 {
margin-top: layout.$spacing-03;
}
-.cds-mt-1 {
- margin-top: layout.$spacing-01;
+.cds-mt-4 {
+ margin-top: layout.$spacing-04;
}
.cds-mt-5 {
margin-top: layout.$spacing-06;
}
+.cds-ml-2 {
+ margin-left: layout.$spacing-02;
+}
+
.cds-ml-3 {
margin-left: layout.$spacing-03;
}
margin-left: layout.$spacing-05;
}
+.cds-mr-1 {
+ margin-right: layout.$spacing-01;
+}
+
+.cds-mr-2 {
+ margin-right: layout.$spacing-02;
+}
+
.cds-mr-3 {
margin-right: layout.$spacing-03;
}
serial_number:
description: Subsystem serial number
type: string
- server_address:
+ traddr:
description: NVMeoF gateway address
type: string
required:
summary: Disallow hosts from accessing an NVMeoF subsystem
tags:
- NVMe-oF Subsystem Host Allowlist
-<<<<<<< HEAD
/api/nvmeof/subsystem/{nqn}/host/{host_nqn}/change_controller_key:
put:
parameters:
summary: Change host DH-HMAC-CHAP controller key
tags:
- NVMe-oF Subsystem Host Allowlist
-=======
->>>>>>> 77603435ca8 (mgr/dashboard: Fix nvmeof edit host key in subsystem resources page)
/api/nvmeof/subsystem/{nqn}/host/{host_nqn}/change_key:
put:
parameters:
gw_group:
description: NVMeoF gateway group
type: string
- server_address:
- description: NVMeoF gateway address
+ traddr:
type: string
required:
- dhchap_key
responses:
'200':
content:
- application/json:
- schema:
- type: object
application/vnd.ceph.api.v1.0+json:
- schema:
- type: object
+ type: object
description: Resource updated.
'202':
content:
- application/json:
- schema:
- type: object
application/vnd.ceph.api.v1.0+json:
- schema:
- type: object
+ type: object
description: Operation is still executing. Please check the task queue.
'400':
description: Operation exception. Please check the response body for details.
summary: Change host DH-HMAC-CHAP key
tags:
- NVMe-oF Subsystem Host Allowlist
+ /api/nvmeof/subsystem/{nqn}/host/{host_nqn}/del_controller_key:
+ put:
+ parameters:
+ - description: NVMeoF subsystem NQN
+ in: path
+ name: nqn
+ required: true
+ schema:
+ type: string
+ - description: NVMeoF host NQN.
+ in: path
+ name: host_nqn
+ required: true
+ schema:
+ type: string
+ requestBody:
+ content:
+ application/json:
+ schema:
+ properties:
+ gw_group:
+ description: NVMeoF gateway group
+ type: string
+ traddr:
+ type: string
+ type: object
+ responses:
+ '200':
+ content:
+ application/vnd.ceph.api.v1.0+json:
+ type: object
+ description: Resource updated.
+ '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: []
+ summary: Delete host DH-HMAC-CHAP controller key
+ tags:
+ - NVMe-oF Subsystem Host Allowlist
+ /api/nvmeof/subsystem/{nqn}/host/{host_nqn}/del_key:
+ put:
+ parameters:
+ - description: NVMeoF subsystem NQN
+ in: path
+ name: nqn
+ required: true
+ schema:
+ type: string
+ - description: NVMeoF host NQN.
+ in: path
+ name: host_nqn
+ required: true
+ schema:
+ type: string
+ requestBody:
+ content:
+ application/json:
+ schema:
+ properties:
+ gw_group:
+ description: NVMeoF gateway group
+ type: string
+ traddr:
+ type: string
+ type: object
+ responses:
+ '200':
+ content:
+ application/vnd.ceph.api.v1.0+json:
+ type: object
+ description: Resource updated.
+ '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: []
+ summary: Delete host DH-HMAC-CHAP key
+ tags:
+ - NVMe-oF Subsystem Host Allowlist
/api/nvmeof/subsystem/{nqn}/listener:
get:
parameters: