]>
git.proxmox.com Git - pve-manager.git/blob - www/manager6/grid/Replication.js
1 Ext
.define('PVE.window.ReplicaEdit', {
2 extend
: 'Proxmox.window.Edit',
3 xtype
: 'pveReplicaEdit',
5 subject
: gettext('Replication Job'),
8 url
: '/cluster/replication',
11 initComponent: function() {
14 var vmid
= me
.pveSelNode
.data
.vmid
;
15 var nodename
= me
.pveSelNode
.data
.node
;
20 xtype
: (me
.isCreate
&& !vmid
)?'pveGuestIDSelector':'displayfield',
22 fieldLabel
: 'CT/VM ID',
28 xtype
: me
.isCreate
? 'pveNodeSelector':'displayfield',
30 disallowedNodes
: [nodename
],
32 onlineValidator
: true,
33 fieldLabel
: gettext("Target"),
36 xtype
: 'pveCalendarEvent',
37 fieldLabel
: gettext('Schedule'),
38 emptyText
: '*/15 - ' + Ext
.String
.format(gettext('Every {0} minutes'), 15),
43 fieldLabel
: gettext('Rate limit') + ' (MB/s)',
46 emptyText
: gettext('unlimited'),
51 fieldLabel
: gettext('Comment'),
55 xtype
: 'proxmoxcheckbox',
59 fieldLabel
: gettext('Enabled'),
67 onlineHelp
: 'pvesr_schedule_time_format',
69 onGetValues: function(values
) {
70 var me
= this.up('window');
72 values
.disable
= values
.enabled
? 0 : 1;
73 delete values
.enabled
;
75 PVE
.Utils
.delete_if_default(values
, 'rate', '', me
.isCreate
);
76 PVE
.Utils
.delete_if_default(values
, 'disable', 0, me
.isCreate
);
77 PVE
.Utils
.delete_if_default(values
, 'schedule', '*/15', me
.isCreate
);
78 PVE
.Utils
.delete_if_default(values
, 'comment', '', me
.isCreate
);
81 values
.type
= 'local';
82 var vm
= vmid
|| values
.guest
;
84 if (me
.highestids
[vm
] !== undefined) {
85 id
= me
.highestids
[vm
];
88 values
.id
= vm
+ '-' + id
.toString();
101 success: function(response
) {
102 var jobs
= response
.result
.data
;
104 Ext
.Array
.forEach(jobs
, function(job
) {
105 var match
= /^([0-9]+)\-([0-9]+)$/.exec(job
.id
);
107 var vmid
= parseInt(match
[1], 10);
108 var id
= parseInt(match
[2], 10);
109 if (highestids
[vmid
] < id
||
110 highestids
[vmid
] === undefined) {
111 highestids
[vmid
] = id
;
116 me
.highestids
= highestids
;
122 success: function(response
, options
) {
123 response
.result
.data
.enabled
= !response
.result
.data
.disable
;
124 me
.setValues(response
.result
.data
);
125 me
.digest
= response
.result
.data
.digest
;
132 /* callback is a function and string */
133 Ext
.define('PVE.grid.ReplicaView', {
134 extend
: 'Ext.grid.Panel',
135 xtype
: 'pveReplicaView',
137 onlineHelp
: 'chapter_pvesr',
140 stateId
: 'grid-pve-replication-status',
143 xclass
: 'Ext.app.ViewController',
145 addJob: function(button
, event
, rec
) {
146 var me
= this.getView();
147 var controller
= this;
148 var win
= Ext
.create('PVE.window.ReplicaEdit', {
151 pveSelNode
: me
.pveSelNode
,
153 win
.on('destroy', function() { controller
.reload(); });
157 editJob: function(button
, event
, rec
) {
158 var me
= this.getView();
159 var controller
= this;
161 var win
= Ext
.create('PVE.window.ReplicaEdit', {
162 url
: '/cluster/replication/' + data
.id
,
164 pveSelNode
: me
.pveSelNode
,
166 win
.on('destroy', function() { controller
.reload(); });
170 scheduleJobNow: function(button
, event
, rec
) {
171 var me
= this.getView();
172 var controller
= this;
174 Proxmox
.Utils
.API2Request({
175 url
: "/api2/extjs/nodes/" + me
.nodename
+ "/replication/" + rec
.data
.id
+ "/schedule_now",
178 callback: function() { controller
.reload(); },
179 failure: function (response
, opts
) {
180 Ext
.Msg
.alert(gettext('Error'), response
.htmlStatus
);
185 showLog: function(button
, event
, rec
) {
186 var me
= this.getView();
187 var controller
= this;
188 var logView
= Ext
.create('Proxmox.panel.LogView', {
190 url
: "/api2/extjs/nodes/" + me
.nodename
+ "/replication/" + rec
.data
.id
+ "/log",
192 var win
= Ext
.create('Ext.window.Window', {
198 title
: gettext("Replication Log"),
202 logView
.requestUpdate();
206 Ext
.TaskManager
.start(task
);
207 win
.on('destroy', function() {
208 Ext
.TaskManager
.stop(task
);
215 var me
= this.getView();
219 dblClick: function(grid
, record
, item
) {
221 me
.editJob(undefined, undefined, record
);
225 // currently replication is for cluster only, so we disable the whole
227 checkPrerequisites: function() {
228 var me
= this.getView();
229 if (PVE
.data
.ResourceStore
.getNodes().length
< 2) {
230 me
.mask(gettext("Replication needs at least two nodes"), ['pve-static-mask']);
236 itemdblclick
: 'dblClick',
237 afterlayout
: 'checkPrerequisites',
244 text
: gettext('Add'),
249 xtype
: 'proxmoxButton',
250 text
: gettext('Edit'),
251 itemId
: 'editButton',
256 xtype
: 'proxmoxStdRemoveButton',
257 itemId
: 'removeButton',
258 baseurl
: '/api2/extjs/cluster/replication/',
263 xtype
: 'proxmoxButton',
264 text
: gettext('Log'),
270 xtype
: 'proxmoxButton',
271 text
: gettext('Schedule now'),
272 itemId
: 'scheduleNowButton',
273 handler
: 'scheduleJobNow',
278 initComponent: function() {
281 var url
= '/cluster/replication';
283 me
.nodename
= me
.pveSelNode
.data
.node
;
284 me
.vmid
= me
.pveSelNode
.data
.vmid
;
288 text
: gettext('Enabled'),
289 dataIndex
: 'enabled',
290 xtype
: 'checkcolumn',
301 text
: gettext('Guest'),
306 text
: gettext('Job'),
311 text
: gettext('Target'),
318 me
.stateId
= 'grid-pve-replication-dc';
319 } else if (!me
.vmid
) {
321 url
= '/nodes/' + me
.nodename
+ '/replication';
324 url
= '/nodes/' + me
.nodename
+ '/replication' + '?guest=' + me
.vmid
;
330 text
: gettext('Status'),
334 renderer: function(value
, metadata
, record
) {
336 if (record
.data
.pid
) {
337 metadata
.tdCls
= 'x-grid-row-loading';
344 if (record
.data
.remove_job
) {
345 icons
.push('<i class="fa fa-ban warning" title="'
346 + gettext("Removal Scheduled") + '"></i>');
347 states
.push(gettext("Removal Scheduled"));
350 if (record
.data
.error
) {
351 icons
.push('<i class="fa fa-times critical" title="'
352 + gettext("Error") + '"></i>');
353 states
.push(record
.data
.error
);
356 if (icons
.length
== 0) {
357 icons
.push('<i class="fa fa-check good"></i>');
358 states
.push(gettext('OK'));
361 return icons
.join(',') + ' ' + states
.join(',');
365 text
: gettext('Last Sync'),
366 dataIndex
: 'last_sync',
368 renderer: function(value
, metadata
, record
) {
373 if (record
.data
.pid
) {
374 return gettext('syncing');
377 return Proxmox
.Utils
.render_timestamp(value
);
381 text
: gettext('Duration'),
382 dataIndex
: 'duration',
384 renderer
: Proxmox
.Utils
.render_duration
,
387 text
: gettext('Next Sync'),
388 dataIndex
: 'next_sync',
390 renderer: function(value
) {
395 var now
= new Date();
396 var next
= new Date(value
*1000);
399 return gettext('pending');
402 return Proxmox
.Utils
.render_timestamp(value
);
410 text
: gettext('Schedule'),
412 dataIndex
: 'schedule',
415 text
: gettext('Rate limit'),
417 renderer: function(value
) {
419 return gettext('unlimited');
422 return value
.toString() + ' MB/s';
427 text
: gettext('Comment'),
428 dataIndex
: 'comment',
429 renderer
: Ext
.htmlEncode
,
433 me
.rstore
= Ext
.create('Proxmox.data.UpdateStore', {
434 storeid
: 'pve-replica-' + me
.nodename
+ me
.vmid
,
435 model
: (mode
=== 'dc')? 'pve-replication' : 'pve-replication-state',
439 url
: "/api2/json" + url
,
443 me
.store
= Ext
.create('Proxmox.data.DiffStore', {
457 // we cannot access the log and scheduleNow button
458 // in the datacenter, because
459 // we do not know where/if the jobs runs
461 me
.down('#logButton').setHidden(true);
462 me
.down('#scheduleNowButton').setHidden(true);
465 // if we set the warning mask, we do not want to load
466 // or set the mask on store errors
467 if (PVE
.data
.ResourceStore
.getNodes().length
< 2) {
471 Proxmox
.Utils
.monStoreErrors(me
, me
.rstore
);
473 me
.on('destroy', me
.rstore
.stopUpdate
);
474 me
.rstore
.startUpdate();
478 Ext
.define('pve-replication', {
479 extend
: 'Ext.data.Model',
481 'id', 'target', 'comment', 'rate', 'type',
482 { name
: 'guest', type
: 'integer' },
483 { name
: 'jobnum', type
: 'integer' },
484 { name
: 'schedule', defaultValue
: '*/15' },
485 { name
: 'disable', defaultValue
: '' },
486 { name
: 'enabled', calculate: function(data
) { return !data
.disable
; } },
490 Ext
.define('pve-replication-state', {
491 extend
: 'pve-replication',
493 'last_sync', 'next_sync', 'error', 'duration', 'state',
494 'fail_count', 'remove_job', 'pid',