]>
Commit | Line | Data |
---|---|---|
0b659b8e DC |
1 | Ext.define('PVE.dc.Health', { |
2 | extend: 'Ext.panel.Panel', | |
3 | alias: 'widget.pveDcHealth', | |
4 | ||
8f8ec25d | 5 | title: gettext('Health'), |
0b659b8e | 6 | |
5da98a05 | 7 | bodyPadding: 10, |
769d716b | 8 | height: 250, |
701acf20 DC |
9 | layout: { |
10 | type: 'hbox', | |
f6710aac | 11 | align: 'stretch', |
701acf20 | 12 | }, |
0b659b8e DC |
13 | |
14 | defaults: { | |
701acf20 | 15 | flex: 1, |
0b659b8e DC |
16 | xtype: 'box', |
17 | style: { | |
8058410f | 18 | 'text-align': 'center', |
f6710aac | 19 | }, |
0b659b8e DC |
20 | }, |
21 | ||
b8786899 DC |
22 | nodeList: [], |
23 | nodeIndex: 0, | |
0b659b8e DC |
24 | |
25 | updateStatus: function(store, records, success) { | |
8295f55e | 26 | let me = this; |
0b659b8e DC |
27 | if (!success) { |
28 | return; | |
29 | } | |
30 | ||
8295f55e | 31 | let cluster = { |
428bc4a2 | 32 | iconCls: PVE.Utils.get_health_icon('good', true), |
f6710aac | 33 | text: gettext("Standalone node - no cluster defined"), |
0b659b8e | 34 | }; |
8295f55e | 35 | let nodes = { |
0b659b8e | 36 | online: 0, |
f6710aac | 37 | offline: 0, |
0b659b8e | 38 | }; |
8295f55e TL |
39 | let numNodes = 1; // by default we have one node |
40 | for (const { data } of records) { | |
41 | if (data.type === 'node') { | |
42 | nodes[data.online === 1 ? 'online':'offline']++; | |
43 | } else if (data.type === 'cluster') { | |
44 | cluster.text = `${gettext("Cluster")}: ${data.name}, ${gettext("Quorate")}: `; | |
45 | cluster.text += Proxmox.Utils.format_boolean(data.quorate); | |
46 | if (data.quorate !== 1) { | |
428bc4a2 | 47 | cluster.iconCls = PVE.Utils.get_health_icon('critical', true); |
0b659b8e | 48 | } |
8295f55e | 49 | numNodes = data.nodes; |
0b659b8e DC |
50 | } |
51 | } | |
52 | ||
53e3ea84 | 53 | if (numNodes !== nodes.online + nodes.offline) { |
0b659b8e DC |
54 | nodes.offline = numNodes - nodes.online; |
55 | } | |
56 | ||
046e640c | 57 | me.getComponent('clusterstatus').updateHealth(cluster); |
0b659b8e DC |
58 | me.getComponent('nodestatus').update(nodes); |
59 | }, | |
60 | ||
61 | updateCeph: function(store, records, success) { | |
8295f55e TL |
62 | let me = this; |
63 | let cephstatus = me.getComponent('ceph'); | |
0b659b8e | 64 | if (!success || records.length < 1) { |
d43f7042 | 65 | if (cephstatus.isVisible()) { |
8295f55e | 66 | return; // if ceph status is already visible don't stop to update |
d43f7042 | 67 | } |
8295f55e | 68 | // try all nodes until we either get a successful api call, or we tried all nodes |
b8786899 | 69 | if (++me.nodeIndex >= me.nodeList.length) { |
0b659b8e | 70 | me.cephstore.stopUpdate(); |
b8786899 | 71 | } else { |
8295f55e | 72 | store.getProxy().setUrl(`/api2/json/nodes/${me.nodeList[me.nodeIndex].node}/ceph/status`); |
0b659b8e DC |
73 | } |
74 | return; | |
75 | } | |
76 | ||
8295f55e | 77 | let state = PVE.Utils.render_ceph_health(records[0].data.health || {}); |
046e640c | 78 | cephstatus.updateHealth(state); |
0b659b8e DC |
79 | cephstatus.setVisible(true); |
80 | }, | |
81 | ||
82 | listeners: { | |
83 | destroy: function() { | |
8295f55e | 84 | let me = this; |
0b659b8e | 85 | me.cephstore.stopUpdate(); |
f6710aac | 86 | }, |
0b659b8e DC |
87 | }, |
88 | ||
89 | items: [ | |
90 | { | |
91 | itemId: 'clusterstatus', | |
046e640c | 92 | xtype: 'pveHealthWidget', |
f6710aac | 93 | title: gettext('Status'), |
0b659b8e DC |
94 | }, |
95 | { | |
96 | itemId: 'nodestatus', | |
97 | data: { | |
98 | online: 0, | |
f6710aac | 99 | offline: 0, |
0b659b8e DC |
100 | }, |
101 | tpl: [ | |
102 | '<h3>' + gettext('Nodes') + '</h3><br />', | |
103 | '<div style="width: 150px;margin: auto;font-size: 12pt">', | |
104 | '<div class="left-aligned">', | |
105 | '<i class="good fa fa-fw fa-check"> </i>', | |
106 | gettext('Online'), | |
107 | '</div>', | |
108 | '<div class="right-aligned">{online}</div>', | |
109 | '<br /><br />', | |
110 | '<div class="left-aligned">', | |
111 | '<i class="critical fa fa-fw fa-times"> </i>', | |
112 | gettext('Offline'), | |
113 | '</div>', | |
114 | '<div class="right-aligned">{offline}</div>', | |
f6710aac TL |
115 | '</div>', |
116 | ], | |
0b659b8e DC |
117 | }, |
118 | { | |
119 | itemId: 'ceph', | |
120 | width: 250, | |
121 | columnWidth: undefined, | |
c359b437 | 122 | userCls: 'pointer', |
2ce6111f | 123 | title: 'Ceph', |
046e640c | 124 | xtype: 'pveHealthWidget', |
c359b437 DC |
125 | hidden: true, |
126 | listeners: { | |
127 | element: 'el', | |
128 | click: function() { | |
8295f55e | 129 | Ext.state.Manager.getProvider().set('dctab', { value: 'ceph' }, true); |
f6710aac TL |
130 | }, |
131 | }, | |
132 | }, | |
0b659b8e DC |
133 | ], |
134 | ||
135 | initComponent: function() { | |
8295f55e | 136 | let me = this; |
0b659b8e | 137 | |
b8786899 DC |
138 | me.nodeList = PVE.data.ResourceStore.getNodes(); |
139 | me.nodeIndex = 0; | |
0c7c0d6b | 140 | me.cephstore = Ext.create('Proxmox.data.UpdateStore', { |
0b659b8e DC |
141 | interval: 3000, |
142 | storeid: 'pve-cluster-ceph', | |
143 | proxy: { | |
56a353b9 | 144 | type: 'proxmox', |
8295f55e | 145 | url: `/api2/json/nodes/${me.nodeList[me.nodeIndex].node}/ceph/status`, |
f6710aac | 146 | }, |
0b659b8e DC |
147 | }); |
148 | me.callParent(); | |
0b659b8e | 149 | me.mon(me.cephstore, 'load', me.updateCeph, me); |
b8786899 | 150 | me.cephstore.startUpdate(); |
f6710aac | 151 | }, |
0b659b8e | 152 | }); |