1 import { Component, OnInit, ViewChild } from '@angular/core';
2 import { FormControl, Validators } from '@angular/forms';
3 import { Router } from '@angular/router';
5 import { I18n } from '@ngx-translate/i18n-polyfill';
6 import * as _ from 'lodash';
7 import { BsModalService } from 'ngx-bootstrap/modal';
9 import { OrchestratorService } from '../../../../shared/api/orchestrator.service';
10 import { SubmitButtonComponent } from '../../../../shared/components/submit-button/submit-button.component';
11 import { ActionLabelsI18n } from '../../../../shared/constants/app.constants';
12 import { Icons } from '../../../../shared/enum/icons.enum';
13 import { CdFormGroup } from '../../../../shared/forms/cd-form-group';
14 import { CdTableColumn } from '../../../../shared/models/cd-table-column';
15 import { AuthStorageService } from '../../../../shared/services/auth-storage.service';
16 import { InventoryDevice } from '../../inventory/inventory-devices/inventory-device.model';
17 import { OsdCreationPreviewModalComponent } from '../osd-creation-preview-modal/osd-creation-preview-modal.component';
18 import { DevicesSelectionChangeEvent } from '../osd-devices-selection-groups/devices-selection-change-event.interface';
19 import { DevicesSelectionClearEvent } from '../osd-devices-selection-groups/devices-selection-clear-event.interface';
20 import { OsdDevicesSelectionGroupsComponent } from '../osd-devices-selection-groups/osd-devices-selection-groups.component';
21 import { DriveGroup } from './drive-group.model';
22 import { OsdFeature } from './osd-feature.interface';
25 selector: 'cd-osd-form',
26 templateUrl: './osd-form.component.html',
27 styleUrls: ['./osd-form.component.scss']
29 export class OsdFormComponent implements OnInit {
30 @ViewChild('dataDeviceSelectionGroups', { static: false })
31 dataDeviceSelectionGroups: OsdDevicesSelectionGroupsComponent;
33 @ViewChild('walDeviceSelectionGroups', { static: false })
34 walDeviceSelectionGroups: OsdDevicesSelectionGroupsComponent;
36 @ViewChild('dbDeviceSelectionGroups', { static: false })
37 dbDeviceSelectionGroups: OsdDevicesSelectionGroupsComponent;
39 @ViewChild('previewButton', { static: false })
40 previewButton: SubmitButtonComponent;
45 columns: Array<CdTableColumn> = [];
48 allDevices: InventoryDevice[] = [];
50 availDevices: InventoryDevice[] = [];
51 dataDeviceFilters: any[] = [];
52 dbDeviceFilters: any[] = [];
53 walDeviceFilters: any[] = [];
55 driveGroup = new DriveGroup();
60 features: { [key: string]: OsdFeature };
61 featureList: OsdFeature[] = [];
63 hasOrchestrator = false;
67 public actionLabels: ActionLabelsI18n,
68 private authStorageService: AuthStorageService,
70 private orchService: OrchestratorService,
71 private router: Router,
72 private bsModalService: BsModalService
74 this.resource = this.i18n('OSDs');
75 this.action = this.actionLabels.CREATE;
79 desc: this.i18n('Encryption')
82 this.featureList = _.map(this.features, (o, key) => Object.assign(o, { key: key }));
87 this.orchService.status().subscribe((status) => {
88 this.hasOrchestrator = status.available;
89 if (this.hasOrchestrator) {
90 this.getDataDevices();
94 this.form.get('walSlots').valueChanges.subscribe((value) => this.setSlots('wal', value));
95 this.form.get('dbSlots').valueChanges.subscribe((value) => this.setSlots('db', value));
96 _.each(this.features, (feature) => {
100 .valueChanges.subscribe((value) => this.featureFormUpdate(feature.key, value));
105 this.form = new CdFormGroup({
106 walSlots: new FormControl(0, {
108 validators: [Validators.min(0)]
110 dbSlots: new FormControl(0, {
112 validators: [Validators.min(0)]
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 });
129 this.orchService.inventoryDeviceList().subscribe(
130 (devices: InventoryDevice[]) => {
131 this.allDevices = _.filter(devices, 'available');
132 this.availDevices = [...this.allDevices];
133 this.loading = false;
136 this.allDevices = [];
137 this.availDevices = [];
138 this.loading = false;
143 setSlots(type: string, slots: number) {
144 if (typeof slots !== 'number') {
148 this.driveGroup.setSlots(type, slots);
152 featureFormUpdate(key: string, checked: boolean) {
153 this.driveGroup.setFeature(key, checked);
157 this.featureList.forEach((feature) => {
158 this.form.get(feature.key).enable({ emitEvent: false });
163 this.featureList.forEach((feature) => {
164 const control = this.form.get(feature.key);
165 control.disable({ emitEvent: false });
166 control.setValue(false, { emitEvent: false });
170 onDevicesSelected(event: DevicesSelectionChangeEvent) {
171 this.availDevices = event.dataOut;
173 if (event.type === 'data') {
174 // If user selects data devices for a single host, make only remaining devices on
175 // that host as available.
176 const hostnameFilter = _.find(event.filters, { prop: 'hostname' });
177 if (hostnameFilter) {
178 this.hostname = hostnameFilter.value.raw;
179 this.availDevices = event.dataOut.filter((device: InventoryDevice) => {
180 return device.hostname === this.hostname;
182 this.driveGroup.setHostPattern(this.hostname);
184 this.driveGroup.setHostPattern('*');
186 this.enableFeatures();
188 this.driveGroup.setDeviceSelection(event.type, event.filters);
191 onDevicesCleared(event: DevicesSelectionClearEvent) {
192 if (event.type === 'data') {
193 this.availDevices = [...this.allDevices];
194 this.walDeviceSelectionGroups.devices = [];
195 this.dbDeviceSelectionGroups.devices = [];
196 this.disableFeatures();
197 this.driveGroup.reset();
198 this.form.get('walSlots').setValue(0, { emitEvent: false });
199 this.form.get('dbSlots').setValue(0, { emitEvent: false });
201 this.availDevices = [...this.availDevices, ...event.clearedDevices];
202 this.driveGroup.clearDeviceSelection(event.type);
203 const slotControlName = `${event.type}Slots`;
204 this.form.get(slotControlName).setValue(0, { emitEvent: false });
209 // use user name and timestamp for drive group name
210 const user = this.authStorageService.getUsername();
211 this.driveGroup.setName(`dashboard-${user}-${_.now()}`);
212 const modalRef = this.bsModalService.show(OsdCreationPreviewModalComponent, {
213 initialState: { driveGroups: [this.driveGroup.spec] }
215 modalRef.content.submitAction.subscribe(() => {
216 this.router.navigate(['/osd']);
218 this.previewButton.loading = false;