From ac420f3707269c5232336a3cfc4fe41d7472c4f2 Mon Sep 17 00:00:00 2001 From: Super User Date: Tue, 3 Sep 2024 14:16:45 +0530 Subject: [PATCH] mgr/dashboard: service form hosts selection only show up to 10 entries exposed new UIRouter API to get all hosts Fixes: https://tracker.ceph.com/issues/67413 Signed-off-by: Naman Munet (cherry picked from commit ec3e4abeeb7feebd996681a7d8d4e950de5cf518) --- src/pybind/mgr/dashboard/controllers/host.py | 13 +++++++++ .../nvmeof-listeners-form.component.ts | 28 +++++++++++++------ .../cephfs-form/cephfs-form.component.ts | 4 +-- .../service-form/service-form.component.ts | 4 +-- .../rgw-multisite-import.component.ts | 4 +-- .../src/app/shared/api/host.service.ts | 4 +++ 6 files changed, 39 insertions(+), 18 deletions(-) diff --git a/src/pybind/mgr/dashboard/controllers/host.py b/src/pybind/mgr/dashboard/controllers/host.py index c0062b94d705e..645fc4cc44c55 100644 --- a/src/pybind/mgr/dashboard/controllers/host.py +++ b/src/pybind/mgr/dashboard/controllers/host.py @@ -512,3 +512,16 @@ class HostUi(BaseController): @handle_orchestrator_error('host') def inventory(self, refresh=None): return get_inventories(None, refresh) + + @Endpoint('GET') + @ReadPermission + @raise_if_no_orchestrator([OrchFeature.HOST_LIST]) + @handle_orchestrator_error('host') + def list(self): + """ + Get all hosts. + This endpoint is introduced to get all the available hosts in cases where + service instance is not needed (ex: hosts selection in forms), and also + get_hosts method helps in caching the response which makes it performant. + """ + return get_hosts() diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/nvmeof-listeners-form/nvmeof-listeners-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/nvmeof-listeners-form/nvmeof-listeners-form.component.ts index bc02ea99c98e6..412286bda2098 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/nvmeof-listeners-form/nvmeof-listeners-form.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/nvmeof-listeners-form/nvmeof-listeners-form.component.ts @@ -13,7 +13,10 @@ import { FormatterService } from '~/app/shared/services/formatter.service'; import { CdValidators } from '~/app/shared/forms/cd-validators'; import { DimlessBinaryPipe } from '~/app/shared/pipes/dimless-binary.pipe'; import { HostService } from '~/app/shared/api/host.service'; -import { CdTableFetchDataContext } from '~/app/shared/models/cd-table-fetch-data-context'; +import { DaemonService } from '~/app/shared/api/daemon.service'; +import { map } from 'rxjs/operators'; +import { forkJoin } from 'rxjs'; + @Component({ selector: 'cd-nvmeof-listeners-form', templateUrl: './nvmeof-listeners-form.component.html', @@ -39,7 +42,8 @@ export class NvmeofListenersFormComponent implements OnInit { private route: ActivatedRoute, public activeModal: NgbActiveModal, public formatterService: FormatterService, - public dimlessBinaryPipe: DimlessBinaryPipe + public dimlessBinaryPipe: DimlessBinaryPipe, + private daemonService: DaemonService ) { this.permission = this.authStorageService.getPermissions().nvmeof; this.hostPermission = this.authStorageService.getPermissions().hosts; @@ -48,13 +52,19 @@ export class NvmeofListenersFormComponent implements OnInit { } setHosts() { - const hostContext = new CdTableFetchDataContext(() => undefined); - this.hostService.list(hostContext.toParams(), 'false').subscribe((resp: any[]) => { - const nvmeofHosts = resp.filter((r) => - r.service_instances.some((si: any) => si.type === 'nvmeof') - ); - this.hosts = nvmeofHosts.map((h) => ({ hostname: h.hostname, addr: h.addr })); - }); + forkJoin({ + daemons: this.daemonService.list(['nvmeof']), + hosts: this.hostService.getAllHosts() + }) + .pipe( + map(({ daemons, hosts }) => { + const hostNamesFromDaemon = daemons.map((daemon: any) => daemon.hostname); + return hosts.filter((host: any) => hostNamesFromDaemon.includes(host.hostname)); + }) + ) + .subscribe((nvmeofHosts: any[]) => { + this.hosts = nvmeofHosts.map((h) => ({ hostname: h.hostname, addr: h.addr })); + }); } ngOnInit() { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-form/cephfs-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-form/cephfs-form.component.ts index 0506c4c77341f..5f6860b2ffdd0 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-form/cephfs-form.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-form/cephfs-form.component.ts @@ -21,7 +21,6 @@ import { CdValidators } from '~/app/shared/forms/cd-validators'; import { FinishedTask } from '~/app/shared/models/finished-task'; import { Permission } from '~/app/shared/models/permissions'; import { TaskWrapperService } from '~/app/shared/services/task-wrapper.service'; -import { CdTableFetchDataContext } from '~/app/shared/models/cd-table-fetch-data-context'; @Component({ selector: 'cd-cephfs-form', @@ -127,8 +126,7 @@ export class CephfsVolumeFormComponent extends CdForm implements OnInit { } }); } else { - const hostContext = new CdTableFetchDataContext(() => undefined); - this.hostService.list(hostContext.toParams(), 'false').subscribe((resp: object[]) => { + this.hostService.getAllHosts().subscribe((resp: object[]) => { const options: SelectOption[] = []; _.forEach(resp, (host: object) => { if (_.get(host, 'sources.orchestrator', false)) { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-form/service-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-form/service-form.component.ts index 9602c856aed81..bada177f735b4 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-form/service-form.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-form/service-form.component.ts @@ -30,7 +30,6 @@ import { CdForm } from '~/app/shared/forms/cd-form'; import { CdFormBuilder } from '~/app/shared/forms/cd-form-builder'; import { CdFormGroup } from '~/app/shared/forms/cd-form-group'; import { CdValidators } from '~/app/shared/forms/cd-validators'; -import { CdTableFetchDataContext } from '~/app/shared/models/cd-table-fetch-data-context'; import { FinishedTask } from '~/app/shared/models/finished-task'; import { CephServiceSpec } from '~/app/shared/models/service.interface'; import { ModalService } from '~/app/shared/services/modal.service'; @@ -470,8 +469,7 @@ export class ServiceFormComponent extends CdForm implements OnInit { this.serviceTypes = _.difference(resp, this.hiddenServices).sort(); }); - const hostContext = new CdTableFetchDataContext(() => undefined); - this.hostService.list(hostContext.toParams(), 'false').subscribe((resp: object[]) => { + this.hostService.getAllHosts().subscribe((resp: object[]) => { const options: SelectOption[] = []; _.forEach(resp, (host: object) => { if (_.get(host, 'sources.orchestrator', false)) { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-import/rgw-multisite-import.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-import/rgw-multisite-import.component.ts index deda890167077..6a3edfbf59a13 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-import/rgw-multisite-import.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-import/rgw-multisite-import.component.ts @@ -11,7 +11,6 @@ import { RgwZone } from '../models/rgw-multisite'; import _ from 'lodash'; import { SelectMessages } from '~/app/shared/components/select/select-messages.model'; import { HostService } from '~/app/shared/api/host.service'; -import { CdTableFetchDataContext } from '~/app/shared/models/cd-table-fetch-data-context'; import { SelectOption } from '~/app/shared/components/select/select-option.model'; import { Observable, Subject, merge } from 'rxjs'; import { debounceTime, distinctUntilChanged, filter, map } from 'rxjs/operators'; @@ -62,8 +61,7 @@ export class RgwMultisiteImportComponent implements OnInit { this.zoneNames = this.zoneList.map((zone) => { return zone['name']; }); - const hostContext = new CdTableFetchDataContext(() => undefined); - this.hostService.list(hostContext.toParams(), 'false').subscribe((resp: object[]) => { + this.hostService.getAllHosts().subscribe((resp: object[]) => { const options: SelectOption[] = []; _.forEach(resp, (host: object) => { if (_.get(host, 'sources.orchestrator', false)) { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/host.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/host.service.ts index 3bb569575836e..ce23302ba26de 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/host.service.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/host.service.ts @@ -162,4 +162,8 @@ export class HostService extends ApiClient { }) ); } + + getAllHosts(): Observable { + return this.http.get(`${this.baseUIURL}/list`); + } } -- 2.39.5