From 926aedfef1921f32da0c692fceb314a4cf3d6e5e Mon Sep 17 00:00:00 2001 From: Dnyaneshwari Date: Tue, 19 Nov 2024 12:31:52 +0530 Subject: [PATCH] mgr/dashboard: list smb Tracker: https://tracker.ceph.com/issues/69080 Signed-off-by: Dnyaneshwari Talwekar --- .../frontend/cypress/e2e/ui/navigation.po.ts | 3 +- .../frontend/src/app/app-routing.module.ts | 8 ++ .../frontend/src/app/ceph/ceph.module.ts | 2 + .../smb-cluster-list.component.html | 15 ++++ .../smb-cluster-list.component.scss | 0 .../smb-cluster-list.component.spec.ts | 35 +++++++++ .../smb-cluster-list.component.ts | 73 +++++++++++++++++++ .../frontend/src/app/ceph/smb/smb.model.ts | 28 +++++++ .../frontend/src/app/ceph/smb/smb.module.ts | 44 +++++++++++ .../navigation/navigation.component.html | 8 +- .../src/app/shared/api/smb.service.spec.ts | 31 ++++++++ .../src/app/shared/api/smb.service.ts | 18 +++++ .../src/app/shared/models/permission.spec.ts | 9 ++- .../src/app/shared/models/permissions.ts | 2 + 14 files changed, 271 insertions(+), 5 deletions(-) create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/ceph/smb/smb-cluster-list/smb-cluster-list.component.html create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/ceph/smb/smb-cluster-list/smb-cluster-list.component.scss create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/ceph/smb/smb-cluster-list/smb-cluster-list.component.spec.ts create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/ceph/smb/smb-cluster-list/smb-cluster-list.component.ts create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/ceph/smb/smb.model.ts create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/ceph/smb/smb.module.ts create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/shared/api/smb.service.spec.ts create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/shared/api/smb.service.ts diff --git a/src/pybind/mgr/dashboard/frontend/cypress/e2e/ui/navigation.po.ts b/src/pybind/mgr/dashboard/frontend/cypress/e2e/ui/navigation.po.ts index 89c4c7394d9..ae0e5b64f25 100644 --- a/src/pybind/mgr/dashboard/frontend/cypress/e2e/ui/navigation.po.ts +++ b/src/pybind/mgr/dashboard/frontend/cypress/e2e/ui/navigation.po.ts @@ -48,7 +48,8 @@ export class NavigationPageHelper extends PageHelper { menu: 'File', submenus: [ { menu: 'File Systems', component: 'cd-cephfs-list' }, - { menu: 'NFS', component: 'cd-error' } + { menu: 'NFS', component: 'cd-error' }, + { menu: 'SMB', component: 'cd-smb-cluster-list' } ] }, { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/app-routing.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/app-routing.module.ts index 99d7bd0e2d8..f389b64a454 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/app-routing.module.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/app-routing.module.ts @@ -51,6 +51,7 @@ import { UpgradeProgressComponent } from './ceph/cluster/upgrade/upgrade-progres import { MultiClusterComponent } from './ceph/cluster/multi-cluster/multi-cluster.component'; import { MultiClusterListComponent } from './ceph/cluster/multi-cluster/multi-cluster-list/multi-cluster-list.component'; import { MultiClusterDetailsComponent } from './ceph/cluster/multi-cluster/multi-cluster-details/multi-cluster-details.component'; +import { SmbClusterListComponent } from './ceph/smb/smb-cluster-list/smb-cluster-list.component'; @Injectable() export class PerformanceCounterBreadcrumbsResolver extends BreadcrumbsResolver { @@ -429,6 +430,13 @@ const routes: Routes = [ data: { breadcrumbs: ActionLabels.EDIT } } ] + }, + { + path: 'smb', + data: { + breadcrumbs: 'File/SMB' + }, + children: [{ path: '', component: SmbClusterListComponent }] } ] }, diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/ceph.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/ceph.module.ts index 47772304b50..d269b6aa912 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/ceph.module.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/ceph.module.ts @@ -7,6 +7,7 @@ import { ClusterModule } from './cluster/cluster.module'; import { DashboardModule } from './dashboard/dashboard.module'; import { NfsModule } from './nfs/nfs.module'; import { PerformanceCounterModule } from './performance-counter/performance-counter.module'; +import { SmbModule } from './smb/smb.module'; @NgModule({ imports: [ @@ -16,6 +17,7 @@ import { PerformanceCounterModule } from './performance-counter/performance-coun PerformanceCounterModule, CephfsModule, NfsModule, + SmbModule, SharedModule ], declarations: [] diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/smb/smb-cluster-list/smb-cluster-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/smb/smb-cluster-list/smb-cluster-list.component.html new file mode 100644 index 00000000000..1a73e58cdd2 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/smb/smb-cluster-list/smb-cluster-list.component.html @@ -0,0 +1,15 @@ + + + + diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/smb/smb-cluster-list/smb-cluster-list.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/smb/smb-cluster-list/smb-cluster-list.component.scss new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/smb/smb-cluster-list/smb-cluster-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/smb/smb-cluster-list/smb-cluster-list.component.spec.ts new file mode 100644 index 00000000000..d1c24d1dbe1 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/smb/smb-cluster-list/smb-cluster-list.component.spec.ts @@ -0,0 +1,35 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SmbClusterListComponent } from './smb-cluster-list.component'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { SharedModule } from '~/app/shared/shared.module'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { RouterTestingModule } from '@angular/router/testing'; + +import { ToastrModule } from 'ngx-toastr'; + +describe('SmbClusterListComponent', () => { + let component: SmbClusterListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ + BrowserAnimationsModule, + SharedModule, + HttpClientTestingModule, + ToastrModule.forRoot(), + RouterTestingModule + ], + declarations: [SmbClusterListComponent] + }).compileComponents(); + + fixture = TestBed.createComponent(SmbClusterListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/smb/smb-cluster-list/smb-cluster-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/smb/smb-cluster-list/smb-cluster-list.component.ts new file mode 100644 index 00000000000..bf61643a0cc --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/smb/smb-cluster-list/smb-cluster-list.component.ts @@ -0,0 +1,73 @@ +import { Component, OnInit, ViewChild } from '@angular/core'; +import { catchError, switchMap } from 'rxjs/operators'; +import { BehaviorSubject, Observable, of } from 'rxjs'; + +import _ from 'lodash'; + +import { ActionLabelsI18n } from '~/app/shared/constants/app.constants'; +import { TableComponent } from '~/app/shared/datatable/table/table.component'; +import { CdTableAction } from '~/app/shared/models/cd-table-action'; +import { CdTableColumn } from '~/app/shared/models/cd-table-column'; +import { CdTableFetchDataContext } from '~/app/shared/models/cd-table-fetch-data-context'; +import { ListWithDetails } from '~/app/shared/classes/list-with-details.class'; +import { Permission } from '~/app/shared/models/permissions'; + +import { AuthStorageService } from '~/app/shared/services/auth-storage.service'; +import { SmbService } from '~/app/shared/api/smb.service'; +import { SMBCluster } from '../smb.model'; + +@Component({ + selector: 'cd-smb-cluster-list', + templateUrl: './smb-cluster-list.component.html', + styleUrls: ['./smb-cluster-list.component.scss'] +}) +export class SmbClusterListComponent extends ListWithDetails implements OnInit { + @ViewChild('table', { static: true }) + table: TableComponent; + columns: CdTableColumn[]; + permission: Permission; + tableActions: CdTableAction[]; + context: CdTableFetchDataContext; + + smbClusters$: Observable; + subject$ = new BehaviorSubject([]); + + constructor( + private authStorageService: AuthStorageService, + public actionLabels: ActionLabelsI18n, + private smbService: SmbService + ) { + super(); + this.permission = this.authStorageService.getPermissions().smb; + } + + ngOnInit() { + this.columns = [ + { + name: $localize`Name`, + prop: 'cluster_id', + flexGrow: 2 + }, + { + name: $localize`Authentication Mode`, + prop: 'auth_mode', + flexGrow: 2 + } + ]; + + this.smbClusters$ = this.subject$.pipe( + switchMap(() => + this.smbService.listClusters().pipe( + catchError(() => { + this.context.error(); + return of(null); + }) + ) + ) + ); + } + + loadSMBCluster() { + this.subject$.next([]); + } +} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/smb/smb.model.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/smb/smb.model.ts new file mode 100644 index 00000000000..3796d924565 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/smb/smb.model.ts @@ -0,0 +1,28 @@ +import { CephServicePlacement } from '~/app/shared/models/service.interface'; + +export interface SMBCluster { + cluster_id: string; + auth_mode: AuthMode; + intent: string; + domain_settings?: DomainSettings; + user_group_settings?: string[]; + custom_dns?: string[]; + placement?: CephServicePlacement; + clustering?: string; + public_addrs?: PublicAddress; +} + +export interface DomainSettings { + realm?: string; + join_sources_ref?: string[]; +} + +export interface PublicAddress { + address: string; + destination: string; +} + +export interface AuthMode { + user: 'User'; + activeDirectory: 'active-directory'; +} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/smb/smb.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/smb/smb.module.ts new file mode 100644 index 00000000000..7cd237dd8e0 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/smb/smb.module.ts @@ -0,0 +1,44 @@ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { ReactiveFormsModule } from '@angular/forms'; +import { RouterModule } from '@angular/router'; + +import { NgbNavModule, NgbTooltipModule, NgbTypeaheadModule } from '@ng-bootstrap/ng-bootstrap'; + +import { SharedModule } from '~/app/shared/shared.module'; + +import { + ButtonModule, + GridModule, + IconModule, + IconService, + InputModule, + SelectModule +} from 'carbon-components-angular'; + +import Close from '@carbon/icons/es/close/32'; +import { SmbClusterListComponent } from './smb-cluster-list/smb-cluster-list.component'; + +@NgModule({ + imports: [ + ReactiveFormsModule, + RouterModule, + SharedModule, + NgbNavModule, + CommonModule, + NgbTypeaheadModule, + NgbTooltipModule, + GridModule, + SelectModule, + InputModule, + ButtonModule, + IconModule + ], + exports: [SmbClusterListComponent], + declarations: [SmbClusterListComponent] +}) +export class SmbModule { + constructor(private iconService: IconService) { + this.iconService.registerAll([Close]); + } +} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.html b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.html index 0150896e883..0bcb5278f91 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.html @@ -240,7 +240,7 @@ NFS + SMB { + let service: SmbService; + let httpTesting: HttpTestingController; + + configureTestBed({ + providers: [SmbService], + imports: [HttpClientTestingModule] + }); + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(SmbService); + httpTesting = TestBed.inject(HttpTestingController); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); + + it('should call list', () => { + service.listClusters().subscribe(); + const req = httpTesting.expectOne('api/smb/cluster'); + expect(req.request.method).toBe('GET'); + }); +}); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/smb.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/smb.service.ts new file mode 100644 index 00000000000..4f4ebcb423c --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/smb.service.ts @@ -0,0 +1,18 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; + +import { SMBCluster } from '~/app/ceph/smb/smb.model'; + +@Injectable({ + providedIn: 'root' +}) +export class SmbService { + baseURL = 'api/smb'; + + constructor(private http: HttpClient) {} + + listClusters(): Observable { + return this.http.get(`${this.baseURL}/cluster`); + } +} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/permission.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/permission.spec.ts index 213fb416ea5..d1010a3408a 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/permission.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/permission.spec.ts @@ -19,7 +19,8 @@ describe('cd-notification classes', () => { rbdImage: { create: false, delete: false, read: false, update: false }, rbdMirroring: { create: false, delete: false, read: false, update: false }, rgw: { create: false, delete: false, read: false, update: false }, - user: { create: false, delete: false, read: false, update: false } + user: { create: false, delete: false, read: false, update: false }, + smb: { create: false, delete: false, read: false, update: false } }); }); @@ -40,7 +41,8 @@ describe('cd-notification classes', () => { 'rbd-image': ['create', 'read', 'update', 'delete'], 'rbd-mirroring': ['create', 'read', 'update', 'delete'], rgw: ['create', 'read', 'update', 'delete'], - user: ['create', 'read', 'update', 'delete'] + user: ['create', 'read', 'update', 'delete'], + smb: ['create', 'read', 'update', 'delete'] }; expect(new Permissions(fullyGranted)).toEqual({ cephfs: { create: true, delete: true, read: true, update: true }, @@ -59,7 +61,8 @@ describe('cd-notification classes', () => { rbdImage: { create: true, delete: true, read: true, update: true }, rbdMirroring: { create: true, delete: true, read: true, update: true }, rgw: { create: true, delete: true, read: true, update: true }, - user: { create: true, delete: true, read: true, update: true } + user: { create: true, delete: true, read: true, update: true }, + smb: { create: true, delete: true, read: true, update: true } }); }); }); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/permissions.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/permissions.ts index 5e9fe4aae47..838385d840a 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/permissions.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/permissions.ts @@ -29,6 +29,7 @@ export class Permissions { grafana: Permission; prometheus: Permission; nfs: Permission; + smb: Permission; constructor(serverPermissions: any) { this.hosts = new Permission(serverPermissions['hosts']); @@ -48,5 +49,6 @@ export class Permissions { this.grafana = new Permission(serverPermissions['grafana']); this.prometheus = new Permission(serverPermissions['prometheus']); this.nfs = new Permission(serverPermissions['nfs-ganesha']); + this.smb = new Permission(serverPermissions['smb']); } } -- 2.39.5