]>
Commit | Line | Data |
---|---|---|
9f95a23c TL |
1 | import { Component, OnInit, ViewChild } from '@angular/core'; |
2 | import { FormControl, Validators } from '@angular/forms'; | |
3 | import { Router } from '@angular/router'; | |
4 | ||
f67539c2 TL |
5 | import _ from 'lodash'; |
6 | ||
7 | import { InventoryDevice } from '~/app/ceph/cluster/inventory/inventory-devices/inventory-device.model'; | |
8 | import { HostService } from '~/app/shared/api/host.service'; | |
9 | import { OrchestratorService } from '~/app/shared/api/orchestrator.service'; | |
10 | import { FormButtonPanelComponent } from '~/app/shared/components/form-button-panel/form-button-panel.component'; | |
11 | import { ActionLabelsI18n } from '~/app/shared/constants/app.constants'; | |
12 | import { Icons } from '~/app/shared/enum/icons.enum'; | |
13 | import { CdForm } from '~/app/shared/forms/cd-form'; | |
14 | import { CdFormGroup } from '~/app/shared/forms/cd-form-group'; | |
15 | import { CdTableColumn } from '~/app/shared/models/cd-table-column'; | |
16 | import { AuthStorageService } from '~/app/shared/services/auth-storage.service'; | |
17 | import { ModalService } from '~/app/shared/services/modal.service'; | |
9f95a23c TL |
18 | import { OsdCreationPreviewModalComponent } from '../osd-creation-preview-modal/osd-creation-preview-modal.component'; |
19 | import { DevicesSelectionChangeEvent } from '../osd-devices-selection-groups/devices-selection-change-event.interface'; | |
20 | import { DevicesSelectionClearEvent } from '../osd-devices-selection-groups/devices-selection-clear-event.interface'; | |
21 | import { OsdDevicesSelectionGroupsComponent } from '../osd-devices-selection-groups/osd-devices-selection-groups.component'; | |
22 | import { DriveGroup } from './drive-group.model'; | |
23 | import { OsdFeature } from './osd-feature.interface'; | |
24 | ||
25 | @Component({ | |
26 | selector: 'cd-osd-form', | |
27 | templateUrl: './osd-form.component.html', | |
28 | styleUrls: ['./osd-form.component.scss'] | |
29 | }) | |
f67539c2 TL |
30 | export class OsdFormComponent extends CdForm implements OnInit { |
31 | @ViewChild('dataDeviceSelectionGroups') | |
9f95a23c TL |
32 | dataDeviceSelectionGroups: OsdDevicesSelectionGroupsComponent; |
33 | ||
f67539c2 | 34 | @ViewChild('walDeviceSelectionGroups') |
9f95a23c TL |
35 | walDeviceSelectionGroups: OsdDevicesSelectionGroupsComponent; |
36 | ||
f67539c2 | 37 | @ViewChild('dbDeviceSelectionGroups') |
9f95a23c TL |
38 | dbDeviceSelectionGroups: OsdDevicesSelectionGroupsComponent; |
39 | ||
f67539c2 TL |
40 | @ViewChild('previewButtonPanel') |
41 | previewButtonPanel: FormButtonPanelComponent; | |
9f95a23c TL |
42 | |
43 | icons = Icons; | |
44 | ||
45 | form: CdFormGroup; | |
46 | columns: Array<CdTableColumn> = []; | |
47 | ||
9f95a23c TL |
48 | allDevices: InventoryDevice[] = []; |
49 | ||
50 | availDevices: InventoryDevice[] = []; | |
51 | dataDeviceFilters: any[] = []; | |
52 | dbDeviceFilters: any[] = []; | |
53 | walDeviceFilters: any[] = []; | |
54 | hostname = ''; | |
55 | driveGroup = new DriveGroup(); | |
56 | ||
57 | action: string; | |
58 | resource: string; | |
59 | ||
60 | features: { [key: string]: OsdFeature }; | |
61 | featureList: OsdFeature[] = []; | |
62 | ||
f67539c2 | 63 | hasOrchestrator = true; |
9f95a23c TL |
64 | |
65 | constructor( | |
66 | public actionLabels: ActionLabelsI18n, | |
67 | private authStorageService: AuthStorageService, | |
9f95a23c | 68 | private orchService: OrchestratorService, |
f67539c2 | 69 | private hostService: HostService, |
9f95a23c | 70 | private router: Router, |
f67539c2 | 71 | private modalService: ModalService |
9f95a23c | 72 | ) { |
f67539c2 TL |
73 | super(); |
74 | this.resource = $localize`OSDs`; | |
9f95a23c TL |
75 | this.action = this.actionLabels.CREATE; |
76 | this.features = { | |
77 | encrypted: { | |
78 | key: 'encrypted', | |
f67539c2 | 79 | desc: $localize`Encryption` |
9f95a23c TL |
80 | } |
81 | }; | |
82 | this.featureList = _.map(this.features, (o, key) => Object.assign(o, { key: key })); | |
83 | this.createForm(); | |
84 | } | |
85 | ||
86 | ngOnInit() { | |
87 | this.orchService.status().subscribe((status) => { | |
88 | this.hasOrchestrator = status.available; | |
f67539c2 | 89 | if (status.available) { |
9f95a23c | 90 | this.getDataDevices(); |
f67539c2 TL |
91 | } else { |
92 | this.loadingNone(); | |
9f95a23c TL |
93 | } |
94 | }); | |
95 | ||
96 | this.form.get('walSlots').valueChanges.subscribe((value) => this.setSlots('wal', value)); | |
97 | this.form.get('dbSlots').valueChanges.subscribe((value) => this.setSlots('db', value)); | |
98 | _.each(this.features, (feature) => { | |
99 | this.form | |
100 | .get('features') | |
101 | .get(feature.key) | |
102 | .valueChanges.subscribe((value) => this.featureFormUpdate(feature.key, value)); | |
103 | }); | |
104 | } | |
105 | ||
106 | createForm() { | |
107 | this.form = new CdFormGroup({ | |
108 | walSlots: new FormControl(0, { | |
9f95a23c TL |
109 | validators: [Validators.min(0)] |
110 | }), | |
111 | dbSlots: new FormControl(0, { | |
9f95a23c TL |
112 | validators: [Validators.min(0)] |
113 | }), | |
114 | features: new CdFormGroup( | |
115 | this.featureList.reduce((acc: object, e) => { | |
116 | // disable initially because no data devices are selected | |
117 | acc[e.key] = new FormControl({ value: false, disabled: true }); | |
118 | return acc; | |
119 | }, {}) | |
120 | ) | |
121 | }); | |
122 | } | |
123 | ||
124 | getDataDevices() { | |
f67539c2 | 125 | this.hostService.inventoryDeviceList().subscribe( |
9f95a23c TL |
126 | (devices: InventoryDevice[]) => { |
127 | this.allDevices = _.filter(devices, 'available'); | |
128 | this.availDevices = [...this.allDevices]; | |
f67539c2 | 129 | this.loadingReady(); |
9f95a23c TL |
130 | }, |
131 | () => { | |
132 | this.allDevices = []; | |
133 | this.availDevices = []; | |
f67539c2 | 134 | this.loadingError(); |
9f95a23c TL |
135 | } |
136 | ); | |
137 | } | |
138 | ||
139 | setSlots(type: string, slots: number) { | |
140 | if (typeof slots !== 'number') { | |
141 | return; | |
142 | } | |
143 | if (slots >= 0) { | |
144 | this.driveGroup.setSlots(type, slots); | |
145 | } | |
146 | } | |
147 | ||
148 | featureFormUpdate(key: string, checked: boolean) { | |
149 | this.driveGroup.setFeature(key, checked); | |
150 | } | |
151 | ||
152 | enableFeatures() { | |
153 | this.featureList.forEach((feature) => { | |
154 | this.form.get(feature.key).enable({ emitEvent: false }); | |
155 | }); | |
156 | } | |
157 | ||
158 | disableFeatures() { | |
159 | this.featureList.forEach((feature) => { | |
160 | const control = this.form.get(feature.key); | |
161 | control.disable({ emitEvent: false }); | |
162 | control.setValue(false, { emitEvent: false }); | |
163 | }); | |
164 | } | |
165 | ||
166 | onDevicesSelected(event: DevicesSelectionChangeEvent) { | |
167 | this.availDevices = event.dataOut; | |
168 | ||
169 | if (event.type === 'data') { | |
170 | // If user selects data devices for a single host, make only remaining devices on | |
171 | // that host as available. | |
172 | const hostnameFilter = _.find(event.filters, { prop: 'hostname' }); | |
173 | if (hostnameFilter) { | |
174 | this.hostname = hostnameFilter.value.raw; | |
175 | this.availDevices = event.dataOut.filter((device: InventoryDevice) => { | |
176 | return device.hostname === this.hostname; | |
177 | }); | |
178 | this.driveGroup.setHostPattern(this.hostname); | |
179 | } else { | |
180 | this.driveGroup.setHostPattern('*'); | |
181 | } | |
182 | this.enableFeatures(); | |
183 | } | |
184 | this.driveGroup.setDeviceSelection(event.type, event.filters); | |
185 | } | |
186 | ||
187 | onDevicesCleared(event: DevicesSelectionClearEvent) { | |
188 | if (event.type === 'data') { | |
189 | this.availDevices = [...this.allDevices]; | |
190 | this.walDeviceSelectionGroups.devices = []; | |
191 | this.dbDeviceSelectionGroups.devices = []; | |
192 | this.disableFeatures(); | |
193 | this.driveGroup.reset(); | |
194 | this.form.get('walSlots').setValue(0, { emitEvent: false }); | |
195 | this.form.get('dbSlots').setValue(0, { emitEvent: false }); | |
196 | } else { | |
197 | this.availDevices = [...this.availDevices, ...event.clearedDevices]; | |
198 | this.driveGroup.clearDeviceSelection(event.type); | |
199 | const slotControlName = `${event.type}Slots`; | |
200 | this.form.get(slotControlName).setValue(0, { emitEvent: false }); | |
201 | } | |
202 | } | |
203 | ||
204 | submit() { | |
205 | // use user name and timestamp for drive group name | |
206 | const user = this.authStorageService.getUsername(); | |
207 | this.driveGroup.setName(`dashboard-${user}-${_.now()}`); | |
f67539c2 TL |
208 | const modalRef = this.modalService.show(OsdCreationPreviewModalComponent, { |
209 | driveGroups: [this.driveGroup.spec] | |
9f95a23c | 210 | }); |
f67539c2 | 211 | modalRef.componentInstance.submitAction.subscribe(() => { |
9f95a23c TL |
212 | this.router.navigate(['/osd']); |
213 | }); | |
f67539c2 | 214 | this.previewButtonPanel.submitButton.loading = false; |
9f95a23c TL |
215 | } |
216 | } |