]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/blob
73af8e927ce51e72bb5ff87313d89c05ca9e61fc
[ceph-ci.git] /
1 import { Component, Input, OnChanges, OnInit, TemplateRef, ViewChild } from '@angular/core';
2
3 import { I18n } from '@ngx-translate/i18n-polyfill';
4 import * as _ from 'lodash';
5 import { NodeEvent, TreeModel } from 'ng2-tree';
6
7 import { TableComponent } from '../../../shared/datatable/table/table.component';
8 import { Icons } from '../../../shared/enum/icons.enum';
9 import { CdTableColumn } from '../../../shared/models/cd-table-column';
10 import { CdTableSelection } from '../../../shared/models/cd-table-selection';
11 import { IscsiBackstorePipe } from '../../../shared/pipes/iscsi-backstore.pipe';
12
13 @Component({
14   selector: 'cd-iscsi-target-details',
15   templateUrl: './iscsi-target-details.component.html',
16   styleUrls: ['./iscsi-target-details.component.scss']
17 })
18 export class IscsiTargetDetailsComponent implements OnChanges, OnInit {
19   @Input()
20   selection: CdTableSelection;
21   @Input()
22   settings: any;
23
24   @ViewChild('highlightTpl', { static: true })
25   highlightTpl: TemplateRef<any>;
26
27   private detailTable: TableComponent;
28   @ViewChild('detailTable', { static: false })
29   set content(content: TableComponent) {
30     this.detailTable = content;
31     if (content) {
32       content.updateColumns();
33     }
34   }
35
36   columns: CdTableColumn[];
37   data: any;
38   metadata: any = {};
39   selectedItem: any;
40   title: string;
41   tree: TreeModel;
42
43   constructor(private i18n: I18n, private iscsiBackstorePipe: IscsiBackstorePipe) {}
44
45   ngOnInit() {
46     this.columns = [
47       {
48         prop: 'displayName',
49         name: this.i18n('Name'),
50         flexGrow: 2,
51         cellTemplate: this.highlightTpl
52       },
53       {
54         prop: 'current',
55         name: this.i18n('Current'),
56         flexGrow: 1,
57         cellTemplate: this.highlightTpl
58       },
59       {
60         prop: 'default',
61         name: this.i18n('Default'),
62         flexGrow: 1,
63         cellTemplate: this.highlightTpl
64       }
65     ];
66   }
67
68   ngOnChanges() {
69     if (this.selection.hasSelection) {
70       this.selectedItem = this.selection.first();
71       this.generateTree();
72     }
73
74     this.data = undefined;
75   }
76
77   private generateTree() {
78     this.metadata = { root: this.selectedItem.target_controls };
79     const cssClasses = {
80       target: {
81         expanded: _.join(
82           this.selectedItem.cdExecuting
83             ? [Icons.large, Icons.spinner, Icons.spin]
84             : [Icons.large, Icons.bullseye],
85           ' '
86         )
87       },
88       initiators: {
89         expanded: _.join([Icons.large, Icons.user], ' '),
90         leaf: _.join([Icons.user], ' ')
91       },
92       groups: {
93         expanded: _.join([Icons.large, Icons.user], ' '),
94         leaf: _.join([Icons.user], ' ')
95       },
96       disks: {
97         expanded: _.join([Icons.large, Icons.disk], ' '),
98         leaf: _.join([Icons.disk], ' ')
99       },
100       portals: {
101         expanded: _.join([Icons.large, Icons.server], ' '),
102         leaf: _.join([Icons.large, Icons.server], ' ')
103       }
104     };
105
106     const disks = [];
107     _.forEach(this.selectedItem.disks, (disk) => {
108       const id = 'disk_' + disk.pool + '_' + disk.image;
109       this.metadata[id] = {
110         controls: disk.controls,
111         backstore: disk.backstore
112       };
113
114       disks.push({
115         value: `${disk.pool}/${disk.image}`,
116         id: id
117       });
118     });
119
120     const portals = [];
121     _.forEach(this.selectedItem.portals, (portal) => {
122       portals.push({ value: `${portal.host}:${portal.ip}` });
123     });
124
125     const clients = [];
126     _.forEach(this.selectedItem.clients, (client) => {
127       const client_metadata = _.cloneDeep(client.auth);
128       if (client.info) {
129         _.extend(client_metadata, client.info);
130         delete client_metadata['state'];
131         _.forEach(Object.keys(client.info.state), (state) => {
132           client_metadata[state.toLowerCase()] = client.info.state[state];
133         });
134       }
135       this.metadata['client_' + client.client_iqn] = client_metadata;
136
137       const luns = [];
138       client.luns.forEach((lun) => {
139         luns.push({
140           value: `${lun.pool}/${lun.image}`,
141           id: 'disk_' + lun.pool + '_' + lun.image,
142           settings: {
143             cssClasses: cssClasses.disks
144           }
145         });
146       });
147
148       let status = '';
149       if (client.info) {
150         status = Object.keys(client.info.state).includes('LOGGED_IN') ? 'logged_in' : 'logged_out';
151       }
152       clients.push({
153         value: client.client_iqn,
154         status: status,
155         id: 'client_' + client.client_iqn,
156         children: luns
157       });
158     });
159
160     const groups = [];
161     _.forEach(this.selectedItem.groups, (group) => {
162       const luns = [];
163       group.disks.forEach((disk) => {
164         luns.push({
165           value: `${disk.pool}/${disk.image}`,
166           id: 'disk_' + disk.pool + '_' + disk.image
167         });
168       });
169
170       const initiators = [];
171       group.members.forEach((member) => {
172         initiators.push({
173           value: member,
174           id: 'client_' + member
175         });
176       });
177
178       groups.push({
179         value: group.group_id,
180         children: [
181           {
182             value: 'Disks',
183             children: luns,
184             settings: {
185               selectionAllowed: false,
186               cssClasses: cssClasses.disks
187             }
188           },
189           {
190             value: 'Initiators',
191             children: initiators,
192             settings: {
193               selectionAllowed: false,
194               cssClasses: cssClasses.initiators
195             }
196           }
197         ]
198       });
199     });
200
201     this.tree = {
202       value: this.selectedItem.target_iqn,
203       id: 'root',
204       settings: {
205         static: true,
206         cssClasses: cssClasses.target
207       },
208       children: [
209         {
210           value: 'Disks',
211           children: disks,
212           settings: {
213             selectionAllowed: false,
214             cssClasses: cssClasses.disks
215           }
216         },
217         {
218           value: 'Portals',
219           children: portals,
220           settings: {
221             selectionAllowed: false,
222             cssClasses: cssClasses.portals
223           }
224         },
225         {
226           value: 'Initiators',
227           children: clients,
228           settings: {
229             selectionAllowed: false,
230             cssClasses: cssClasses.initiators
231           }
232         },
233         {
234           value: 'Groups',
235           children: groups,
236           settings: {
237             selectionAllowed: false,
238             cssClasses: cssClasses.groups
239           }
240         }
241       ]
242     };
243   }
244
245   onNodeSelected(e: NodeEvent) {
246     if (e.node.id) {
247       this.title = e.node.value;
248       const tempData = this.metadata[e.node.id] || {};
249
250       if (e.node.id === 'root') {
251         this.columns[2].isHidden = false;
252         this.data = _.map(this.settings.target_default_controls, (value, key) => {
253           return {
254             displayName: key,
255             default: value,
256             current: tempData[key] || value
257           };
258         });
259       } else if (e.node.id.toString().startsWith('disk_')) {
260         this.columns[2].isHidden = false;
261         this.data = _.map(this.settings.disk_default_controls[tempData.backstore], (value, key) => {
262           return {
263             displayName: key,
264             default: value,
265             current: !_.isUndefined(tempData.controls[key]) ? tempData.controls[key] : value
266           };
267         });
268         this.data.push({
269           displayName: 'backstore',
270           default: this.iscsiBackstorePipe.transform(this.settings.default_backstore),
271           current: this.iscsiBackstorePipe.transform(tempData.backstore)
272         });
273       } else {
274         this.columns[2].isHidden = true;
275         this.data = _.map(tempData, (value, key) => {
276           return {
277             displayName: key,
278             default: undefined,
279             current: value
280           };
281         });
282       }
283     } else {
284       this.data = undefined;
285     }
286
287     if (this.detailTable) {
288       this.detailTable.updateColumns();
289     }
290   }
291 }