]> git.proxmox.com Git - ceph.git/blame - ceph/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/inventory/inventory-devices/inventory-devices.component.ts
import 15.2.0 Octopus source
[ceph.git] / ceph / src / pybind / mgr / dashboard / frontend / src / app / ceph / cluster / inventory / inventory-devices / inventory-devices.component.ts
CommitLineData
9f95a23c
TL
1import {
2 Component,
3 EventEmitter,
4 Input,
5 OnDestroy,
6 OnInit,
7 Output,
8 ViewChild
9} from '@angular/core';
10import { I18n } from '@ngx-translate/i18n-polyfill';
11
12import * as _ from 'lodash';
13import { BsModalService } from 'ngx-bootstrap/modal';
14import { Subscription } from 'rxjs';
15
16import { OrchestratorService } from '../../../../shared/api/orchestrator.service';
17import { FormModalComponent } from '../../../../shared/components/form-modal/form-modal.component';
18import { TableComponent } from '../../../../shared/datatable/table/table.component';
19import { CellTemplate } from '../../../../shared/enum/cell-template.enum';
20import { Icons } from '../../../../shared/enum/icons.enum';
21import { NotificationType } from '../../../../shared/enum/notification-type.enum';
22import { CdTableAction } from '../../../../shared/models/cd-table-action';
23import { CdTableColumn } from '../../../../shared/models/cd-table-column';
24import { CdTableColumnFiltersChange } from '../../../../shared/models/cd-table-column-filters-change';
25import { CdTableSelection } from '../../../../shared/models/cd-table-selection';
26import { Permission } from '../../../../shared/models/permissions';
27import { DimlessBinaryPipe } from '../../../../shared/pipes/dimless-binary.pipe';
28import { AuthStorageService } from '../../../../shared/services/auth-storage.service';
29import { NotificationService } from '../../../../shared/services/notification.service';
30import { InventoryDevice } from './inventory-device.model';
31
32@Component({
33 selector: 'cd-inventory-devices',
34 templateUrl: './inventory-devices.component.html',
35 styleUrls: ['./inventory-devices.component.scss']
36})
37export class InventoryDevicesComponent implements OnInit, OnDestroy {
38 @ViewChild(TableComponent, { static: true })
39 table: TableComponent;
40
41 // Devices
42 @Input() devices: InventoryDevice[] = [];
43
44 // Do not display these columns
45 @Input() hiddenColumns: string[] = [];
46
47 // Show filters for these columns, specify empty array to disable
48 @Input() filterColumns = [
49 'hostname',
50 'human_readable_type',
51 'available',
52 'sys_api.vendor',
53 'sys_api.model',
54 'sys_api.size'
55 ];
56
57 // Device table row selection type
58 @Input() selectionType: string = undefined;
59
60 @Output() filterChange = new EventEmitter<CdTableColumnFiltersChange>();
61
62 @Output() fetchInventory = new EventEmitter();
63
64 icons = Icons;
65 columns: Array<CdTableColumn> = [];
66 selection: CdTableSelection = new CdTableSelection();
67 permission: Permission;
68 tableActions: CdTableAction[];
69 fetchInventorySub: Subscription;
70
71 constructor(
72 private authStorageService: AuthStorageService,
73 private dimlessBinary: DimlessBinaryPipe,
74 private i18n: I18n,
75 private modalService: BsModalService,
76 private notificationService: NotificationService,
77 private orchService: OrchestratorService
78 ) {}
79
80 ngOnInit() {
81 this.permission = this.authStorageService.getPermissions().osd;
82 this.tableActions = [
83 {
84 permission: 'update',
85 icon: Icons.show,
86 click: () => this.identifyDevice(),
87 name: this.i18n('Identify'),
88 disable: () => !this.selection.hasSingleSelection,
89 canBePrimary: (selection: CdTableSelection) => !selection.hasSingleSelection,
90 visible: () => _.isString(this.selectionType)
91 }
92 ];
93 const columns = [
94 {
95 name: this.i18n('Hostname'),
96 prop: 'hostname',
97 flexGrow: 1
98 },
99 {
100 name: this.i18n('Device path'),
101 prop: 'path',
102 flexGrow: 1
103 },
104 {
105 name: this.i18n('Type'),
106 prop: 'human_readable_type',
107 flexGrow: 1,
108 cellTransformation: CellTemplate.badge,
109 customTemplateConfig: {
110 map: {
111 hdd: { value: 'HDD', class: 'badge-hdd' },
112 ssd: { value: 'SSD', class: 'badge-ssd' }
113 }
114 }
115 },
116 {
117 name: this.i18n('Available'),
118 prop: 'available',
119 flexGrow: 1
120 },
121 {
122 name: this.i18n('Vendor'),
123 prop: 'sys_api.vendor',
124 flexGrow: 1
125 },
126 {
127 name: this.i18n('Model'),
128 prop: 'sys_api.model',
129 flexGrow: 1
130 },
131 {
132 name: this.i18n('Size'),
133 prop: 'sys_api.size',
134 flexGrow: 1,
135 pipe: this.dimlessBinary
136 },
137 {
138 name: this.i18n('OSDs'),
139 prop: 'osd_ids',
140 flexGrow: 1,
141 cellTransformation: CellTemplate.badge,
142 customTemplateConfig: {
143 class: 'badge-dark',
144 prefix: 'osd.'
145 }
146 }
147 ];
148
149 this.columns = columns.filter((col: any) => {
150 return !this.hiddenColumns.includes(col.prop);
151 });
152
153 // init column filters
154 _.forEach(this.filterColumns, (prop) => {
155 const col = _.find(this.columns, { prop: prop });
156 if (col) {
157 col.filterable = true;
158 }
159 });
160
161 if (this.fetchInventory.observers.length > 0) {
162 this.fetchInventorySub = this.table.fetchData.subscribe(() => {
163 this.fetchInventory.emit();
164 });
165 }
166 }
167
168 ngOnDestroy() {
169 if (this.fetchInventorySub) {
170 this.fetchInventorySub.unsubscribe();
171 }
172 }
173
174 onColumnFiltersChanged(event: CdTableColumnFiltersChange) {
175 this.filterChange.emit(event);
176 }
177
178 updateSelection(selection: CdTableSelection) {
179 this.selection = selection;
180 }
181
182 identifyDevice() {
183 const selected = this.selection.first();
184 const hostname = selected.hostname;
185 const device = selected.path || selected.device_id;
186 this.modalService.show(FormModalComponent, {
187 initialState: {
188 titleText: this.i18n(`Identify device {{device}}`, { device }),
189 message: this.i18n('Please enter the duration how long to blink the LED.'),
190 fields: [
191 {
192 type: 'select',
193 name: 'duration',
194 value: 300,
195 required: true,
196 options: [
197 { text: this.i18n('1 minute'), value: 60 },
198 { text: this.i18n('2 minutes'), value: 120 },
199 { text: this.i18n('5 minutes'), value: 300 },
200 { text: this.i18n('10 minutes'), value: 600 },
201 { text: this.i18n('15 minutes'), value: 900 }
202 ]
203 }
204 ],
205 submitButtonText: this.i18n('Execute'),
206 onSubmit: (values: any) => {
207 this.orchService.identifyDevice(hostname, device, values.duration).subscribe(() => {
208 this.notificationService.show(
209 NotificationType.success,
210 this.i18n(`Identifying '{{device}}' started on host '{{hostname}}'`, {
211 hostname,
212 device
213 })
214 );
215 });
216 }
217 }
218 });
219 }
220}