]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-ci.git/blob
f91d156d68bf3060ff145c1496a679399bcf4861
[ceph-ci.git] /
1 import { Component, OnInit, ViewChild } from '@angular/core';
2 import { UntypedFormControl, Validators } from '@angular/forms';
3 import { ActionLabelsI18n, URLVerbs } from '~/app/shared/constants/app.constants';
4 import { CdForm } from '~/app/shared/forms/cd-form';
5 import { CdFormGroup } from '~/app/shared/forms/cd-form-group';
6
7 import { Permission } from '~/app/shared/models/permissions';
8 import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
9 import { PoolService } from '~/app/shared/api/pool.service';
10 import { Pool } from '../../pool/pool';
11 import { NvmeofGatewayNodeComponent } from '../nvmeof-gateway-node/nvmeof-gateway-node.component';
12 import { TaskWrapperService } from '~/app/shared/services/task-wrapper.service';
13 import { CephServiceService } from '~/app/shared/api/ceph-service.service';
14 import { FinishedTask } from '~/app/shared/models/finished-task';
15 import { Router } from '@angular/router';
16 import { CdValidators } from '~/app/shared/forms/cd-validators';
17 import { NvmeofService } from '~/app/shared/api/nvmeof.service';
18
19 @Component({
20   selector: 'cd-nvmeof-group-form',
21   templateUrl: './nvmeof-group-form.component.html',
22   styleUrls: ['./nvmeof-group-form.component.scss'],
23   standalone: false
24 })
25 export class NvmeofGroupFormComponent extends CdForm implements OnInit {
26   @ViewChild(NvmeofGatewayNodeComponent) gatewayNodeComponent: NvmeofGatewayNodeComponent;
27
28   permission: Permission;
29   groupForm: CdFormGroup;
30   action: string;
31   resource: string;
32   group: string;
33   pools: Pool[] = [];
34   poolsLoading = false;
35   pageURL: string;
36   hasAvailableNodes = true;
37
38   constructor(
39     private authStorageService: AuthStorageService,
40     public actionLabels: ActionLabelsI18n,
41     private poolService: PoolService,
42     private taskWrapperService: TaskWrapperService,
43     private cephServiceService: CephServiceService,
44     private nvmeofService: NvmeofService,
45     private router: Router
46   ) {
47     super();
48     this.permission = this.authStorageService.getPermissions().nvmeof;
49     this.resource = $localize`gateway group`;
50   }
51
52   ngOnInit() {
53     this.action = this.actionLabels.CREATE;
54     this.createForm();
55     this.loadPools();
56   }
57
58   createForm() {
59     this.groupForm = new CdFormGroup({
60       groupName: new UntypedFormControl(
61         null,
62         [
63           Validators.required,
64           (control) => {
65             const value = control.value;
66             return value && /[^a-zA-Z0-9_-]/.test(value) ? { invalidChars: true } : null;
67           }
68         ],
69         [CdValidators.unique(this.nvmeofService.exists, this.nvmeofService)]
70       ),
71       pool: new UntypedFormControl('rbd', {
72         validators: [Validators.required]
73       }),
74       unmanaged: new UntypedFormControl(false)
75     });
76   }
77
78   onHostsLoaded(count: number): void {
79     this.hasAvailableNodes = count > 0;
80   }
81
82   get isCreateDisabled(): boolean {
83     if (!this.hasAvailableNodes) {
84       return true;
85     }
86     if (!this.groupForm) {
87       return true;
88     }
89     if (this.groupForm.pending) {
90       return true;
91     }
92     if (this.groupForm.invalid) {
93       return true;
94     }
95     const errors = this.groupForm.errors as { [key: string]: any } | null;
96     if (errors && errors.cdSubmitButton) {
97       return true;
98     }
99     if (this.gatewayNodeComponent) {
100       const selected = this.gatewayNodeComponent.getSelectedHostnames?.() || [];
101       if (selected.length === 0) {
102         return true;
103       }
104     }
105
106     return false;
107   }
108
109   loadPools() {
110     this.poolsLoading = true;
111     this.poolService.list().then(
112       (pools: Pool[]) => {
113         this.pools = (pools || []).filter(
114           (pool: Pool) => pool.application_metadata && pool.application_metadata.includes('rbd')
115         );
116         this.poolsLoading = false;
117         if (this.pools.length >= 1) {
118           const allPoolNames = this.pools.map((pool) => pool.pool_name);
119           const poolName = allPoolNames.includes('rbd') ? 'rbd' : this.pools[0].pool_name;
120           this.groupForm.patchValue({ pool: poolName });
121         }
122       },
123       () => {
124         this.pools = [];
125         this.poolsLoading = false;
126       }
127     );
128   }
129
130   onSubmit() {
131     if (this.groupForm.invalid) {
132       return;
133     }
134
135     if (this.groupForm.pending) {
136       this.groupForm.setErrors({ cdSubmitButton: true });
137       return;
138     }
139
140     const formValues = this.groupForm.value;
141     const selectedHostnames = this.gatewayNodeComponent?.getSelectedHostnames() || [];
142     if (selectedHostnames.length === 0) {
143       this.groupForm.setErrors({ cdSubmitButton: true });
144       return;
145     }
146     let taskUrl = `service/${URLVerbs.CREATE}`;
147     const serviceName = `${formValues.pool}.${formValues.groupName}`;
148
149     const serviceSpec = {
150       service_type: 'nvmeof',
151       service_id: serviceName,
152       pool: formValues.pool,
153       group: formValues.groupName,
154       placement: {
155         hosts: selectedHostnames
156       },
157       unmanaged: formValues.unmanaged
158     };
159
160     this.taskWrapperService
161       .wrapTaskAroundCall({
162         task: new FinishedTask(taskUrl, {
163           service_name: `nvmeof.${serviceName}`
164         }),
165         call: this.cephServiceService.create(serviceSpec)
166       })
167       .subscribe({
168         complete: () => {
169           this.goToListView();
170         },
171         error: () => {
172           this.groupForm.setErrors({ cdSubmitButton: true });
173         }
174       });
175   }
176
177   private goToListView() {
178     this.router.navigateByUrl('/block/nvmeof/gateways');
179   }
180 }