]>
Commit | Line | Data |
---|---|---|
9b81768f | 1 | Ext.define('PVE.ha.VMResourceInputPanel', { |
ef4ef788 | 2 | extend: 'Proxmox.panel.InputPanel', |
95cf0210 | 3 | onlineHelp: 'ha_manager_resource_config', |
9b81768f | 4 | vmid: undefined, |
2a4971d8 | 5 | |
9b81768f DM |
6 | onGetValues: function(values) { |
7 | var me = this; | |
8 | ||
11480a8c | 9 | if (values.vmid) { |
9b81768f DM |
10 | values.sid = values.vmid; |
11 | } | |
9b81768f DM |
12 | delete values.vmid; |
13 | ||
d5e771ce EK |
14 | PVE.Utils.delete_if_default(values, 'group', '', me.isCreate); |
15 | PVE.Utils.delete_if_default(values, 'max_restart', '1', me.isCreate); | |
16 | PVE.Utils.delete_if_default(values, 'max_relocate', '1', me.isCreate); | |
b2f9a9e4 | 17 | |
9b81768f DM |
18 | return values; |
19 | }, | |
20 | ||
8058410f | 21 | initComponent: function() { |
9b81768f | 22 | var me = this; |
0a4651f0 | 23 | var MIN_QUORUM_VOTES = 3; |
9b81768f | 24 | |
390b8555 | 25 | var disabledHint = Ext.createWidget({ |
1c289bc8 | 26 | xtype: 'displayfield', // won't get submitted by default |
f71b7c28 | 27 | userCls: 'pmx-hint', |
49e19905 DC |
28 | value: 'Disabling the resource will stop the guest system. ' + |
29 | 'See the online help for details.', | |
f6710aac | 30 | hidden: true, |
390b8555 EK |
31 | }); |
32 | ||
0a4651f0 EK |
33 | var fewVotesHint = Ext.createWidget({ |
34 | itemId: 'fewVotesHint', | |
35 | xtype: 'displayfield', | |
f71b7c28 | 36 | userCls: 'pmx-hint', |
1c289bc8 | 37 | value: 'At least three quorum votes are recommended for reliable HA.', |
f6710aac | 38 | hidden: true, |
0a4651f0 EK |
39 | }); |
40 | ||
e7ade592 | 41 | Proxmox.Utils.API2Request({ |
0a4651f0 EK |
42 | url: '/cluster/config/nodes', |
43 | method: 'GET', | |
44 | failure: function(response) { | |
45 | Ext.Msg.alert(gettext('Error'), response.htmlStatus); | |
46 | }, | |
47 | success: function(response) { | |
48 | var nodes = response.result.data; | |
49 | var votes = 0; | |
50 | Ext.Array.forEach(nodes, function(node) { | |
51 | var vote = parseInt(node.quorum_votes, 10); // parse as base 10 | |
52 | votes += vote || 0; // parseInt might return NaN, which is false | |
53 | }); | |
54 | ||
55 | if (votes < MIN_QUORUM_VOTES) { | |
0a4651f0 EK |
56 | fewVotesHint.setVisible(true); |
57 | } | |
f6710aac | 58 | }, |
0a4651f0 EK |
59 | }); |
60 | ||
53e3ea84 | 61 | var vmidStore = me.vmid ? {} : { |
9f50d504 TL |
62 | model: 'PVEResources', |
63 | autoLoad: true, | |
64 | sorters: 'vmid', | |
65 | filters: [ | |
66 | { | |
67 | property: 'type', | |
f6710aac | 68 | value: /lxc|qemu/, |
9f50d504 TL |
69 | }, |
70 | { | |
71 | property: 'hastate', | |
f6710aac TL |
72 | value: /unmanaged/, |
73 | }, | |
74 | ], | |
9f50d504 TL |
75 | }; |
76 | ||
77 | // value is a string above, but a number below | |
9b81768f DM |
78 | me.column1 = [ |
79 | { | |
9f50d504 TL |
80 | xtype: me.vmid ? 'displayfield' : 'vmComboSelector', |
81 | submitValue: me.isCreate, | |
9b81768f | 82 | name: 'vmid', |
53e3ea84 | 83 | fieldLabel: me.vmid && me.guestType === 'ct' ? 'CT' : 'VM', |
9b81768f | 84 | value: me.vmid, |
9f50d504 | 85 | store: vmidStore, |
f6710aac | 86 | validateExists: true, |
b2f9a9e4 TL |
87 | }, |
88 | { | |
bf96f60d | 89 | xtype: 'proxmoxintegerfield', |
b2f9a9e4 TL |
90 | name: 'max_restart', |
91 | fieldLabel: gettext('Max. Restart'), | |
92 | value: 1, | |
93 | minValue: 0, | |
94 | maxValue: 10, | |
f6710aac | 95 | allowBlank: false, |
b2f9a9e4 TL |
96 | }, |
97 | { | |
bf96f60d | 98 | xtype: 'proxmoxintegerfield', |
b2f9a9e4 TL |
99 | name: 'max_relocate', |
100 | fieldLabel: gettext('Max. Relocate'), | |
101 | value: 1, | |
102 | minValue: 0, | |
103 | maxValue: 10, | |
f6710aac TL |
104 | allowBlank: false, |
105 | }, | |
9b81768f DM |
106 | ]; |
107 | ||
108 | me.column2 = [ | |
109 | { | |
110 | xtype: 'pveHAGroupSelector', | |
111 | name: 'group', | |
f6710aac | 112 | fieldLabel: gettext('Group'), |
9b81768f DM |
113 | }, |
114 | { | |
09cacce7 | 115 | xtype: 'proxmoxKVComboBox', |
ecd45352 TL |
116 | name: 'state', |
117 | value: 'started', | |
118 | fieldLabel: gettext('Request State'), | |
119 | comboItems: [ | |
e49da95b DC |
120 | ['started', 'started'], |
121 | ['stopped', 'stopped'], | |
840cd466 | 122 | ['ignored', 'ignored'], |
f6710aac | 123 | ['disabled', 'disabled'], |
ecd45352 | 124 | ], |
390b8555 EK |
125 | listeners: { |
126 | 'change': function(field, newValue) { | |
ecd45352 | 127 | if (newValue === 'disabled') { |
390b8555 | 128 | disabledHint.setVisible(true); |
8af03a8d | 129 | } else if (disabledHint.isVisible()) { |
390b8555 EK |
130 | disabledHint.setVisible(false); |
131 | } | |
f6710aac TL |
132 | }, |
133 | }, | |
390b8555 | 134 | }, |
f6710aac | 135 | disabledHint, |
9b81768f DM |
136 | ]; |
137 | ||
138 | me.columnB = [ | |
139 | { | |
140 | xtype: 'textfield', | |
141 | name: 'comment', | |
f6710aac | 142 | fieldLabel: gettext('Comment'), |
0a4651f0 | 143 | }, |
f6710aac | 144 | fewVotesHint, |
9b81768f | 145 | ]; |
2a4971d8 | 146 | |
9b81768f | 147 | me.callParent(); |
f6710aac | 148 | }, |
9b81768f DM |
149 | }); |
150 | ||
151 | Ext.define('PVE.ha.VMResourceEdit', { | |
9fccc702 | 152 | extend: 'Proxmox.window.Edit', |
9b81768f DM |
153 | |
154 | vmid: undefined, | |
ed416f20 | 155 | guestType: undefined, |
11480a8c | 156 | isCreate: undefined, |
9b81768f | 157 | |
8058410f | 158 | initComponent: function() { |
9b81768f | 159 | var me = this; |
2a4971d8 | 160 | |
11480a8c TL |
161 | if (me.isCreate === undefined) { |
162 | me.isCreate = !me.vmid; | |
163 | } | |
9b81768f | 164 | |
d5e771ce | 165 | if (me.isCreate) { |
9b81768f DM |
166 | me.url = '/api2/extjs/cluster/ha/resources'; |
167 | me.method = 'POST'; | |
168 | } else { | |
169 | me.url = '/api2/extjs/cluster/ha/resources/' + me.vmid; | |
170 | me.method = 'PUT'; | |
171 | } | |
172 | ||
173 | var ipanel = Ext.create('PVE.ha.VMResourceInputPanel', { | |
d5e771ce | 174 | isCreate: me.isCreate, |
ed416f20 | 175 | vmid: me.vmid, |
f6710aac | 176 | guestType: me.guestType, |
9b81768f DM |
177 | }); |
178 | ||
179 | Ext.apply(me, { | |
8f8ec25d EK |
180 | subject: gettext('Resource') + ': ' + gettext('Container') + |
181 | '/' + gettext('Virtual Machine'), | |
9b81768f | 182 | isAdd: true, |
8058410f | 183 | items: [ipanel], |
9b81768f | 184 | }); |
2a4971d8 | 185 | |
9b81768f DM |
186 | me.callParent(); |
187 | ||
d5e771ce | 188 | if (!me.isCreate) { |
9b81768f | 189 | me.load({ |
8058410f | 190 | success: function(response, options) { |
9b81768f DM |
191 | var values = response.result.data; |
192 | ||
8058410f | 193 | var regex = /^(\S+):(\S+)$/; |
9b81768f DM |
194 | var res = regex.exec(values.sid); |
195 | ||
a764c5f7 DC |
196 | if (res[1] !== 'vm' && res[1] !== 'ct') { |
197 | throw "got unexpected resource type"; | |
198 | } | |
9b81768f DM |
199 | |
200 | values.vmid = res[2]; | |
2a4971d8 | 201 | |
9b81768f | 202 | ipanel.setValues(values); |
f6710aac | 203 | }, |
9b81768f DM |
204 | }); |
205 | } | |
f6710aac | 206 | }, |
9b81768f | 207 | }); |