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