From 8a357076cf51677997eafea229fe2fcb490b5c9d Mon Sep 17 00:00:00 2001 From: Jamie Cameron Date: Wed, 27 Jun 2007 21:04:56 +0000 Subject: [PATCH] First checkin of Bacula module --- bacula-backup/BaculaNode.class | Bin 0 -> 2525 bytes bacula-backup/BorderPanel.class | Bin 0 -> 1773 bytes bacula-backup/BorderPanel.java | 1 + bacula-backup/CHANGELOG | 2 + bacula-backup/CbButton.class | Bin 0 -> 4796 bytes bacula-backup/CbButton.java | 1 + bacula-backup/CbButtonCallback.class | Bin 0 -> 137 bytes bacula-backup/CbButtonGroup.class | Bin 0 -> 675 bytes bacula-backup/CbScrollbar.class | Bin 0 -> 4304 bytes bacula-backup/CbScrollbar.java | 1 + bacula-backup/CbScrollbarArrow.class | Bin 0 -> 1941 bytes bacula-backup/CbScrollbarCallback.class | Bin 0 -> 164 bytes bacula-backup/ErrorWindow.class | Bin 0 -> 1489 bytes bacula-backup/ErrorWindow.java | 1 + bacula-backup/FixedFrame.class | Bin 0 -> 1162 bytes bacula-backup/FixedFrame.java | 1 + bacula-backup/GrayPanel.class | Bin 0 -> 571 bytes bacula-backup/GrayPanel.java | 1 + bacula-backup/Hierarchy.class | Bin 0 -> 5825 bytes bacula-backup/Hierarchy.java | 1 + bacula-backup/HierarchyCallback.class | Bin 0 -> 219 bytes bacula-backup/HierarchyNode.class | Bin 0 -> 528 bytes bacula-backup/Makefile | 2 + bacula-backup/TreeChooser.class | Bin 0 -> 6027 bytes bacula-backup/TreeChooser.java | 295 ++++ bacula-backup/Util.class | Bin 0 -> 4440 bytes bacula-backup/Util.java | 1 + bacula-backup/apply.cgi | 11 + bacula-backup/backup.cgi | 81 + bacula-backup/backup_form.cgi | 24 + bacula-backup/bacula-backup-lib.pl | 1532 +++++++++++++++++ bacula-backup/bootup.cgi | 21 + bacula-backup/cancel_jobs.cgi | 32 + bacula-backup/clientstatus_form.cgi | 93 + bacula-backup/config | 11 + bacula-backup/config-windows | 11 + bacula-backup/config.info | 15 + bacula-backup/delete_clients.cgi | 27 + bacula-backup/delete_fdirectors.cgi | 25 + bacula-backup/delete_filesets.cgi | 27 + bacula-backup/delete_gjobs.cgi | 33 + bacula-backup/delete_groups.cgi | 34 + bacula-backup/delete_jobs.cgi | 27 + bacula-backup/delete_pools.cgi | 27 + bacula-backup/delete_schedules.cgi | 27 + bacula-backup/delete_sdirectors.cgi | 25 + bacula-backup/delete_storages.cgi | 27 + bacula-backup/delete_volumes.cgi | 24 + bacula-backup/dirstatus_form.cgi | 92 + bacula-backup/edit_client.cgi | 84 + bacula-backup/edit_device.cgi | 74 + bacula-backup/edit_director.cgi | 49 + bacula-backup/edit_fdirector.cgi | 51 + bacula-backup/edit_file.cgi | 40 + bacula-backup/edit_fileset.cgi | 62 + bacula-backup/edit_gjob.cgi | 144 ++ bacula-backup/edit_group.cgi | 87 + bacula-backup/edit_job.cgi | 164 ++ bacula-backup/edit_pool.cgi | 78 + bacula-backup/edit_schedule.cgi | 62 + bacula-backup/edit_sdirector.cgi | 51 + bacula-backup/edit_storage.cgi | 94 + bacula-backup/edit_storagec.cgi | 43 + bacula-backup/fixaddr.cgi | 19 + bacula-backup/fixpass.cgi | 18 + bacula-backup/gbackup.cgi | 71 + bacula-backup/help/backup.html | 8 + bacula-backup/help/clients.html | 18 + bacula-backup/help/clientstatus.html | 8 + bacula-backup/help/devices.html | 19 + bacula-backup/help/director.html | 13 + bacula-backup/help/dirstatus.html | 8 + bacula-backup/help/fdirectors.html | 12 + bacula-backup/help/file.html | 10 + bacula-backup/help/filesets.html | 10 + bacula-backup/help/gbackup.html | 9 + bacula-backup/help/gjobs.html | 10 + bacula-backup/help/groups.html | 13 + bacula-backup/help/intro.html | 29 + bacula-backup/help/jobs.html | 31 + bacula-backup/help/label.html | 13 + bacula-backup/help/mount.html | 8 + bacula-backup/help/pools.html | 13 + bacula-backup/help/poolstatus.html | 8 + bacula-backup/help/schedules.html | 12 + bacula-backup/help/sdirectors.html | 12 + bacula-backup/help/storagec.html | 10 + bacula-backup/help/storages.html | 32 + bacula-backup/help/storagestatus.html | 8 + bacula-backup/help/sync.html | 11 + bacula-backup/images/.xvpics/backup.gif | Bin 0 -> 2374 bytes bacula-backup/images/.xvpics/clientstatus.gif | Bin 0 -> 2369 bytes bacula-backup/images/.xvpics/dirstatus.gif | Bin 0 -> 2370 bytes bacula-backup/images/.xvpics/gbackup.gif | Bin 0 -> 2370 bytes bacula-backup/images/.xvpics/gjobs.gif | Bin 0 -> 2370 bytes bacula-backup/images/.xvpics/jobs.gif | Bin 0 -> 2374 bytes bacula-backup/images/.xvpics/label.gif | 5 + bacula-backup/images/.xvpics/mount.gif | Bin 0 -> 2374 bytes bacula-backup/images/.xvpics/restore.gif | 5 + .../images/.xvpics/storagestatus.gif | Bin 0 -> 2369 bytes bacula-backup/images/Thumbs.db | Bin 0 -> 62464 bytes bacula-backup/images/backup.gif | Bin 0 -> 2153 bytes bacula-backup/images/clients.gif | Bin 0 -> 274 bytes bacula-backup/images/clientstatus.gif | Bin 0 -> 574 bytes bacula-backup/images/devices.gif | Bin 0 -> 308 bytes bacula-backup/images/dir.gif | Bin 0 -> 88 bytes bacula-backup/images/director.gif | Bin 0 -> 1745 bytes bacula-backup/images/dirstatus.gif | Bin 0 -> 1840 bytes bacula-backup/images/fdirectors.gif | Bin 0 -> 1418 bytes bacula-backup/images/file.gif | Bin 0 -> 274 bytes bacula-backup/images/filesets.gif | Bin 0 -> 266 bytes bacula-backup/images/gbackup.gif | Bin 0 -> 2080 bytes bacula-backup/images/gjobs.gif | Bin 0 -> 2322 bytes bacula-backup/images/grestore.gif | Bin 0 -> 2154 bytes bacula-backup/images/groups.gif | Bin 0 -> 287 bytes bacula-backup/images/icon.gif | Bin 0 -> 1443 bytes bacula-backup/images/jobs.gif | Bin 0 -> 2344 bytes bacula-backup/images/label.gif | Bin 0 -> 2313 bytes bacula-backup/images/mount.gif | Bin 0 -> 1854 bytes bacula-backup/images/pools.gif | Bin 0 -> 387 bytes bacula-backup/images/poolstatus.gif | Bin 0 -> 1413 bytes bacula-backup/images/restore.gif | Bin 0 -> 2154 bytes bacula-backup/images/rfile.gif | Bin 0 -> 91 bytes bacula-backup/images/schedules.gif | Bin 0 -> 1970 bytes bacula-backup/images/sdir.gif | Bin 0 -> 88 bytes bacula-backup/images/sdirectors.gif | Bin 0 -> 1418 bytes bacula-backup/images/smallicon.gif | Bin 0 -> 1029 bytes bacula-backup/images/srfile.gif | Bin 0 -> 91 bytes bacula-backup/images/storagec.gif | Bin 0 -> 245 bytes bacula-backup/images/storages.gif | Bin 0 -> 416 bytes bacula-backup/images/storagestatus.gif | Bin 0 -> 556 bytes bacula-backup/images/sync.gif | Bin 0 -> 568 bytes bacula-backup/index.cgi | 212 +++ bacula-backup/label.cgi | 66 + bacula-backup/label_form.cgi | 31 + bacula-backup/lang/en | 640 +++++++ bacula-backup/list.cgi | 102 ++ bacula-backup/list_clients.cgi | 41 + bacula-backup/list_devices.cgi | 41 + bacula-backup/list_fdirectors.cgi | 40 + bacula-backup/list_filesets.cgi | 43 + bacula-backup/list_gbackup.cgi | 27 + bacula-backup/list_gjobs.cgi | 47 + bacula-backup/list_grestore.cgi | 51 + bacula-backup/list_groups.cgi | 61 + bacula-backup/list_jobs.cgi | 51 + bacula-backup/list_pools.cgi | 41 + bacula-backup/list_schedules.cgi | 42 + bacula-backup/list_sdirectors.cgi | 40 + bacula-backup/list_storages.cgi | 45 + bacula-backup/list_sync.cgi | 27 + bacula-backup/log_parser.pl | 28 + bacula-backup/manual.sxw | Bin 0 -> 25393 bytes bacula-backup/module.info | 4 + bacula-backup/mount.cgi | 33 + bacula-backup/mount_form.cgi | 23 + bacula-backup/poolstatus_form.cgi | 70 + bacula-backup/restart.cgi | 11 + bacula-backup/restore.cgi | 174 ++ bacula-backup/restore_form.cgi | 117 ++ bacula-backup/save_client.cgi | 82 + bacula-backup/save_device.cgi | 64 + bacula-backup/save_director.cgi | 38 + bacula-backup/save_fdirector.cgi | 58 + bacula-backup/save_file.cgi | 36 + bacula-backup/save_fileset.cgi | 81 + bacula-backup/save_gjob.cgi | 93 + bacula-backup/save_group.cgi | 82 + bacula-backup/save_job.cgi | 92 + bacula-backup/save_pool.cgi | 77 + bacula-backup/save_schedule.cgi | 59 + bacula-backup/save_sdirector.cgi | 58 + bacula-backup/save_storage.cgi | 77 + bacula-backup/save_storagec.cgi | 36 + bacula-backup/save_sync.cgi | 32 + bacula-backup/schedule_chooser.cgi | 92 + bacula-backup/schedule_select.cgi | 38 + bacula-backup/start.cgi | 11 + bacula-backup/stop.cgi | 11 + bacula-backup/storagestatus_form.cgi | 96 ++ bacula-backup/sync.pl | 17 + bacula-backup/treechooser.cgi | 43 + 182 files changed, 7440 insertions(+) create mode 100644 bacula-backup/BaculaNode.class create mode 100644 bacula-backup/BorderPanel.class create mode 120000 bacula-backup/BorderPanel.java create mode 100644 bacula-backup/CHANGELOG create mode 100644 bacula-backup/CbButton.class create mode 120000 bacula-backup/CbButton.java create mode 100644 bacula-backup/CbButtonCallback.class create mode 100644 bacula-backup/CbButtonGroup.class create mode 100644 bacula-backup/CbScrollbar.class create mode 120000 bacula-backup/CbScrollbar.java create mode 100644 bacula-backup/CbScrollbarArrow.class create mode 100644 bacula-backup/CbScrollbarCallback.class create mode 100644 bacula-backup/ErrorWindow.class create mode 120000 bacula-backup/ErrorWindow.java create mode 100644 bacula-backup/FixedFrame.class create mode 120000 bacula-backup/FixedFrame.java create mode 100644 bacula-backup/GrayPanel.class create mode 120000 bacula-backup/GrayPanel.java create mode 100644 bacula-backup/Hierarchy.class create mode 120000 bacula-backup/Hierarchy.java create mode 100644 bacula-backup/HierarchyCallback.class create mode 100644 bacula-backup/HierarchyNode.class create mode 100644 bacula-backup/Makefile create mode 100644 bacula-backup/TreeChooser.class create mode 100644 bacula-backup/TreeChooser.java create mode 100644 bacula-backup/Util.class create mode 120000 bacula-backup/Util.java create mode 100755 bacula-backup/apply.cgi create mode 100755 bacula-backup/backup.cgi create mode 100755 bacula-backup/backup_form.cgi create mode 100644 bacula-backup/bacula-backup-lib.pl create mode 100755 bacula-backup/bootup.cgi create mode 100755 bacula-backup/cancel_jobs.cgi create mode 100755 bacula-backup/clientstatus_form.cgi create mode 100644 bacula-backup/config create mode 100644 bacula-backup/config-windows create mode 100644 bacula-backup/config.info create mode 100755 bacula-backup/delete_clients.cgi create mode 100755 bacula-backup/delete_fdirectors.cgi create mode 100755 bacula-backup/delete_filesets.cgi create mode 100755 bacula-backup/delete_gjobs.cgi create mode 100755 bacula-backup/delete_groups.cgi create mode 100755 bacula-backup/delete_jobs.cgi create mode 100755 bacula-backup/delete_pools.cgi create mode 100755 bacula-backup/delete_schedules.cgi create mode 100755 bacula-backup/delete_sdirectors.cgi create mode 100755 bacula-backup/delete_storages.cgi create mode 100755 bacula-backup/delete_volumes.cgi create mode 100755 bacula-backup/dirstatus_form.cgi create mode 100755 bacula-backup/edit_client.cgi create mode 100755 bacula-backup/edit_device.cgi create mode 100755 bacula-backup/edit_director.cgi create mode 100755 bacula-backup/edit_fdirector.cgi create mode 100755 bacula-backup/edit_file.cgi create mode 100755 bacula-backup/edit_fileset.cgi create mode 100755 bacula-backup/edit_gjob.cgi create mode 100755 bacula-backup/edit_group.cgi create mode 100755 bacula-backup/edit_job.cgi create mode 100755 bacula-backup/edit_pool.cgi create mode 100755 bacula-backup/edit_schedule.cgi create mode 100755 bacula-backup/edit_sdirector.cgi create mode 100755 bacula-backup/edit_storage.cgi create mode 100755 bacula-backup/edit_storagec.cgi create mode 100755 bacula-backup/fixaddr.cgi create mode 100755 bacula-backup/fixpass.cgi create mode 100755 bacula-backup/gbackup.cgi create mode 100644 bacula-backup/help/backup.html create mode 100644 bacula-backup/help/clients.html create mode 100644 bacula-backup/help/clientstatus.html create mode 100644 bacula-backup/help/devices.html create mode 100644 bacula-backup/help/director.html create mode 100644 bacula-backup/help/dirstatus.html create mode 100644 bacula-backup/help/fdirectors.html create mode 100644 bacula-backup/help/file.html create mode 100644 bacula-backup/help/filesets.html create mode 100644 bacula-backup/help/gbackup.html create mode 100644 bacula-backup/help/gjobs.html create mode 100644 bacula-backup/help/groups.html create mode 100644 bacula-backup/help/intro.html create mode 100644 bacula-backup/help/jobs.html create mode 100644 bacula-backup/help/label.html create mode 100644 bacula-backup/help/mount.html create mode 100644 bacula-backup/help/pools.html create mode 100644 bacula-backup/help/poolstatus.html create mode 100644 bacula-backup/help/schedules.html create mode 100644 bacula-backup/help/sdirectors.html create mode 100644 bacula-backup/help/storagec.html create mode 100644 bacula-backup/help/storages.html create mode 100644 bacula-backup/help/storagestatus.html create mode 100644 bacula-backup/help/sync.html create mode 100644 bacula-backup/images/.xvpics/backup.gif create mode 100644 bacula-backup/images/.xvpics/clientstatus.gif create mode 100644 bacula-backup/images/.xvpics/dirstatus.gif create mode 100644 bacula-backup/images/.xvpics/gbackup.gif create mode 100644 bacula-backup/images/.xvpics/gjobs.gif create mode 100644 bacula-backup/images/.xvpics/jobs.gif create mode 100644 bacula-backup/images/.xvpics/label.gif create mode 100644 bacula-backup/images/.xvpics/mount.gif create mode 100644 bacula-backup/images/.xvpics/restore.gif create mode 100644 bacula-backup/images/.xvpics/storagestatus.gif create mode 100755 bacula-backup/images/Thumbs.db create mode 100644 bacula-backup/images/backup.gif create mode 100644 bacula-backup/images/clients.gif create mode 100644 bacula-backup/images/clientstatus.gif create mode 100644 bacula-backup/images/devices.gif create mode 100644 bacula-backup/images/dir.gif create mode 100755 bacula-backup/images/director.gif create mode 100755 bacula-backup/images/dirstatus.gif create mode 100755 bacula-backup/images/fdirectors.gif create mode 100644 bacula-backup/images/file.gif create mode 100644 bacula-backup/images/filesets.gif create mode 100644 bacula-backup/images/gbackup.gif create mode 100644 bacula-backup/images/gjobs.gif create mode 100644 bacula-backup/images/grestore.gif create mode 100644 bacula-backup/images/groups.gif create mode 100644 bacula-backup/images/icon.gif create mode 100644 bacula-backup/images/jobs.gif create mode 100644 bacula-backup/images/label.gif create mode 100644 bacula-backup/images/mount.gif create mode 100644 bacula-backup/images/pools.gif create mode 100755 bacula-backup/images/poolstatus.gif create mode 100644 bacula-backup/images/restore.gif create mode 100644 bacula-backup/images/rfile.gif create mode 100644 bacula-backup/images/schedules.gif create mode 100644 bacula-backup/images/sdir.gif create mode 100755 bacula-backup/images/sdirectors.gif create mode 100644 bacula-backup/images/smallicon.gif create mode 100644 bacula-backup/images/srfile.gif create mode 100644 bacula-backup/images/storagec.gif create mode 100755 bacula-backup/images/storages.gif create mode 100644 bacula-backup/images/storagestatus.gif create mode 100644 bacula-backup/images/sync.gif create mode 100755 bacula-backup/index.cgi create mode 100755 bacula-backup/label.cgi create mode 100755 bacula-backup/label_form.cgi create mode 100644 bacula-backup/lang/en create mode 100755 bacula-backup/list.cgi create mode 100755 bacula-backup/list_clients.cgi create mode 100755 bacula-backup/list_devices.cgi create mode 100755 bacula-backup/list_fdirectors.cgi create mode 100755 bacula-backup/list_filesets.cgi create mode 100755 bacula-backup/list_gbackup.cgi create mode 100755 bacula-backup/list_gjobs.cgi create mode 100755 bacula-backup/list_grestore.cgi create mode 100755 bacula-backup/list_groups.cgi create mode 100755 bacula-backup/list_jobs.cgi create mode 100755 bacula-backup/list_pools.cgi create mode 100755 bacula-backup/list_schedules.cgi create mode 100755 bacula-backup/list_sdirectors.cgi create mode 100755 bacula-backup/list_storages.cgi create mode 100755 bacula-backup/list_sync.cgi create mode 100644 bacula-backup/log_parser.pl create mode 100755 bacula-backup/manual.sxw create mode 100644 bacula-backup/module.info create mode 100755 bacula-backup/mount.cgi create mode 100755 bacula-backup/mount_form.cgi create mode 100755 bacula-backup/poolstatus_form.cgi create mode 100755 bacula-backup/restart.cgi create mode 100755 bacula-backup/restore.cgi create mode 100755 bacula-backup/restore_form.cgi create mode 100755 bacula-backup/save_client.cgi create mode 100755 bacula-backup/save_device.cgi create mode 100755 bacula-backup/save_director.cgi create mode 100755 bacula-backup/save_fdirector.cgi create mode 100755 bacula-backup/save_file.cgi create mode 100755 bacula-backup/save_fileset.cgi create mode 100755 bacula-backup/save_gjob.cgi create mode 100755 bacula-backup/save_group.cgi create mode 100755 bacula-backup/save_job.cgi create mode 100755 bacula-backup/save_pool.cgi create mode 100755 bacula-backup/save_schedule.cgi create mode 100755 bacula-backup/save_sdirector.cgi create mode 100755 bacula-backup/save_storage.cgi create mode 100755 bacula-backup/save_storagec.cgi create mode 100755 bacula-backup/save_sync.cgi create mode 100755 bacula-backup/schedule_chooser.cgi create mode 100755 bacula-backup/schedule_select.cgi create mode 100755 bacula-backup/start.cgi create mode 100755 bacula-backup/stop.cgi create mode 100755 bacula-backup/storagestatus_form.cgi create mode 100755 bacula-backup/sync.pl create mode 100755 bacula-backup/treechooser.cgi diff --git a/bacula-backup/BaculaNode.class b/bacula-backup/BaculaNode.class new file mode 100644 index 0000000000000000000000000000000000000000..894e13bd92fd1925bd5807c7eaef55e1a17e0c96 GIT binary patch literal 2525 zcmZ`)TWl0%6#o9b?{+G%P@r5FsAan?t%8Db6)H$^DI!P(RG4v_6m!l6EnY5TAJPRY|;GqwxVTQNhG0_?_97E>Irkoc}*_?&q5`pPc*XIJ}sK z4WnoOhtwNGQmJ4YVvO>shVXCZ*@N|0+t0IVq{tT=R;f@H_ph+%w%4w~Tbwbt) zxl731A>0$f2C?24gdV|YEDNDoc#Du!1O{5gMVoluB*YA2vlwiVixon<=%ho)gvmQX z*ecu>VKxXSgj@*QBB(~E7;P7$9ip)_f_rga5cewtI&|AeI|`-A)wW^OZ^~q{hCN5Y z*P%O`6r#z^`Zm4J($j5qs~p=*xAC3d%%)6RL9OF?OFGk;Cf8FbBc>sadV4TG2_UpOwMjGmYCvYXi?R*QmTgesMjzXH)@z8 zYFpaO1q{qu_TddSsd8J!%C#H3 zzlm9#X65EgGcWrk^|$c0Ldjy=&e%<6I+f{E7_&rYs;QWhiM1I{O!Cgga_N*|$2gAI z?3lFi9U%)e9KgF84&uEa-q+CW=CIT>Y~60zv_k;GQDr&|&e78{fViTT5r-2o3U%}B0>Y1*};)7cU^bS_c&!wg~`TmqHi&vOC`w((6 z1to9 zwU<=a*L#Iww$Yy1W-PR<#RX+fDUh=**Foi#({r zg7PMm$RnH>--Xg+h^#$|l5Y4^FSMFyX&zT~K}$qSdoiRN(_P8XE)1*j*5onFm&zkb z<(k?4a=$1KpBYHhlm&bn^B6&kBTPbJA?YFvCHUyc~D{(#ltsY8dC3+C(LMU3+4S#fGl9i0= z!l+{y%{t1XWAYeV%_om>$plq>ys-8O1BpeM5^xGb@Ea01&3^yRJJ(!apbZS;rKHa7 zQ4h2esPxVqOJ7CzJOm)qVcQfdCWSQT)j;f1w0tSn*j@;BQuY z2DSKyt{3+QQ;i5oFy*0B&tCjT#^TNvf=waw^%qvbqU7F0;{Om=^BS!zlKFZtwND(s zSX@;Qvm<#VlGWbnoa25>JBI4D{mxm2IQNUwX(X04uAgPhdoK u54>IQ`wsCCOm?3??LEYo1+b2k?@3LBN5v3OlQ2Y0#wb<6w@azxLBs!=wp9QC literal 0 HcmV?d00001 diff --git a/bacula-backup/BorderPanel.class b/bacula-backup/BorderPanel.class new file mode 100644 index 0000000000000000000000000000000000000000..9444caae9de107630f00835be86cc35d77e69396 GIT binary patch literal 1773 zcma)7T~iZh6n( zH}twUo#~Z!1ZLV9FTL=}OMgw<=WJpE5yi~pyl2n*p65C5bIvAj{{8zEVkqKH8ePbz z(23C$OccZ$6R#-VDKXiMglg3$`OJNG<#Y{`=LK+t_Bi^izIUVx~iRB=) zolrrQ6||MWn^4Fs{$TxNjawVl@lxOg;Y@93lFM>n|IDOW*LSPTj^#(cX0#O8jzY(x z>pM$N*Or~|fwk;0qUFo7-<>bFB1-u9hvB`Bo!$S~UTMejtt-PiMFe&kY}jnwydRY+2% zXc$DQrc$-}kfg3gQYlzl4}3>-(<<&W(&ToEd(~ZY{E8d+)VG<`h*I-}6 zO76$5=iPHw=r$8dfnQ~FWOS2uXl=;wVUTY@7XXc4s!j_LJX$Gtv{G@dNq*TJDD=_0 zj5d0}VRIYGOm3ph{0p&7Xk6l(NW9>lLO*Q|aoTn=#F0V*8R%@J!B`Il>S$%6wJ|dA z5j3-p1Wm|Z!T=pDkQvf-MzBZfu=fZWV`TVKu;$n%^d|NZmIn&4yWA|Xa~NXbQufh0 z{x`%I;YRku*UaKBO=={)EhK#;>BmW`A|!)#l7}P_1&g0YV)kfz+-I)enGq=$G5=Lz~u!VzWVH+LwsAkXAH#B=* zk~Aj8rnIakMf{Evg)II4tY&AqlZl?P+5n&V^oyqc`0t%$C3a^O3z8wHnwjq-yR+Xm z2W)|F05Cy0CON`qD9|}dHHBH6=a1Jk?&1O-@n6TIA2Rw3bNChW_zjovC;jLAEmWKm IuvsJj11ZHqE&u=k literal 0 HcmV?d00001 diff --git a/bacula-backup/BorderPanel.java b/bacula-backup/BorderPanel.java new file mode 120000 index 000000000..2a2a302f3 --- /dev/null +++ b/bacula-backup/BorderPanel.java @@ -0,0 +1 @@ +../file/BorderPanel.java \ No newline at end of file diff --git a/bacula-backup/CHANGELOG b/bacula-backup/CHANGELOG new file mode 100644 index 000000000..9dbe888f8 --- /dev/null +++ b/bacula-backup/CHANGELOG @@ -0,0 +1,2 @@ +---- Changes since 1.350 ---- +First version of this module, which allows Bacula to be configured and both backups and restores to be executed. diff --git a/bacula-backup/CbButton.class b/bacula-backup/CbButton.class new file mode 100644 index 0000000000000000000000000000000000000000..6223866f6ef77f24ecfbe7fa500c38cc00b4409b GIT binary patch literal 4796 zcma)9X>?TO8GdeN?o2YdfdsNJga85w$qf6}kRVDz0%=()Yqb?J$y|~PlbLifNf2w@ zOx6?m8r#<~;`@G-1GZV<*>6|m~_Pxuu zyvxkFPo6&m7iQukA8K)v4~y~DJlu?1^2pvQ)NMlDF4P@D-6_<7P7g#egR(-@O2+ozai8ELhTXiL9zIz4-a9lu=|91Sg8F14)|~ohlF}Wz@t8V3x@?f z=ED(uTV&r6>hU}*#CHV@itGsi-}B)pzAxZO0mmfJQ$js02Rts+GZO8DP|u3&WImD@ z66%x}r+xJHoG{OO@q!mGYH+V=YTlqhYtc~97>o8KLea#gP^8y%fgcU}x|S6yHwdGV zS=O+2QM%7FuG${z3(XGoCuX;Zq+WxkClR-z9U8{iYmrd2 zWA=I_<7#euC=zK4weOJi#U$-W<0Y`Ny?@^K7V~nOAV7D&sN%L(WOl?r7to7>EI+zhX` zcF}EVbxr0)ms?#XQ!5r_LgaVx$-8>HY&Ead)nQZPsu?P~iEn+ZH{NbGTk_Basmz}x zuV!Ei+68oY@sfcv_=17W0)8OiS^+;4aGii33HYLb9}D=BfR_baFJL*E3^ZeffzP7e zz)G|jcm=N-_?)n3g<2)lPw-POerDhtUNf-PUVGiZ=Y?90dM|!%;1_tqz#5Tkz(y~A zY2a5lZ(tkFd-0}$U!%joHCSih0{RWSC5pchuwG=Fu+EFO4g40rGw^%7W8hr@f50CN z{0VQN+A>-@pfU9O)tH_L9DSxu_2f^r4@rm%2w*c3QJB z6zvQ3u*^0ltO#=>BJE?V8J2$KZi|I);PZz=@g0t+AhW);(_%V^ilU6PmSS@|%*1B9 zDP_rXHq<;StaO@{Yg@F736#l&=2$eb+GHDK?rJDb?{=7+d1d!bCrZ|WV;mMH;V9)o z75wUubV^rOXeWzCQjp8(6mx3b6$-P(6=W)2RZ!-B8)IGFv8Za6-ni*hp1ViYf$nr! zPpZilrMI7|N4pKEhIw%tuzRTL6WgpvWF31g@0gq9Hl=xlv!`7h-X{+2 zaiyWm@pw^NRr@YXWnQYY^XA(lmdrKv0-JCJ$L?ZI%W?3d4)vU^OJtDZO7csG@mG<* zdKkZqe8Vulkyb2gLP%vR%(_;XMXoTbTVd9=!YpBhS-lFg!WCwHE6lQ0n5C*P3tVAV zt-|a+3bXep%+8}Q`;NlwItsJr5Et=mTd32ck6mkM5;7Yl$V5$C_f2< zs33_^fnXA&12d8+3{)gh6!5!~7!x>&(P!Zg2tJLmNfbL|NfMStGgjrXLS(t|T ze8E~&F;AzX5!DFo%qa1y)y=(``vZ9!I?v-3A$V*x;tFrafgQx2>QJ#nI3ix zA;@J{iAU#JFzC;fwUoACw}?{$x9uZnZ#1K>(>cGo9@cGjTcD@i(o0S71ZE6jCT&@o z|0H4!eoRz!0J{PuIw^m+&_hq&@F~oy%abUhOLTu8j~`a6bRQ}4h@gs;T2KtHX7*-L zFC3w+lv?%H61leWR@Is2(0B-Q2XTS2BKKi<260YE{V>)#QOOpoXe3G{dU;r)i&!MX zBa-*qOQm+>V>so$k1Iue+uK=)cQ9k`#7!8$Zrp_ja5oO&9t`4M9HZn6?!z1GUvF{c9qhqB z@E|_HUd@etT0S1u{MfHe#sO^s4r=XqMB9hQH2zc9j^c6c0-n(RjidZOd@LsyPvw;2 z>6~Rak+Txd=2#eFRdlCn0~4JV;0XkWFfX%j54C{PgkMISu$5epx>C>i0Zyc;y!R@4PT?->on|58%CY2 zE}d`?^C}Kv)&v?$1s}oG3Y)Atf^mGoF=tUADDWKS=YUHK0^H=Ku_m&GfFoog&U5s< ziP;<_^Z7Wn{5!D(Z!l3z8tD2Xjn*Iw|cr9H|;CJFFEIOXPEBkWarPj{0RRuY* zk`D8kOI6?FarkG13KAg7BTIvCE+3%l;(=)M1R+WXqP6bIGWXs?@K&<(l(}p5GTnIS vQFx46-Pug>K$*UMx6&5kqHUGZFYrDu^8@DVha4Fnah`t6s5ercgRlG#Q@|GK literal 0 HcmV?d00001 diff --git a/bacula-backup/CbButton.java b/bacula-backup/CbButton.java new file mode 120000 index 000000000..7c7c7d083 --- /dev/null +++ b/bacula-backup/CbButton.java @@ -0,0 +1 @@ +../file/CbButton.java \ No newline at end of file diff --git a/bacula-backup/CbButtonCallback.class b/bacula-backup/CbButtonCallback.class new file mode 100644 index 0000000000000000000000000000000000000000..c86fabc4151538aa430464ad9fd31f95d6805fc6 GIT binary patch literal 137 zcmX^0Z`VEsW(HjbPId-%b_Nbc2G-=9%;aoF23`#x=Om}nl9K#9Yt1l52Cm@z(xT*4 zx6GVWpd?I6FDtPuk&!_F#&=H4$w^8C=@$UW=;tKnrR)1AWu+#UurV+&GB7cK03!<{ Q&{7rfgc5Pf5By|L@i@KI<>_@=~3nnrLftppLEN>O_NRe}SO-K>x+$BrBuB+mR2 z4)lx!sRR<@%$eVUdT2{$9a2y^?Ck99yf^Rd{y6&b4JKMxcHm-8V%~v)IUCbh(Ai}j zsybYexN4(>YYwjChQv*YTLc;8S(d~@!ny8_|JrZoSs1mq)OMDnD+KF)7>C&!!Sw1| z1kp))iZIg+W3`d@1C>7WgNQ4p-|G>|UbhoGEC^S0yERl1GZCDpNuF-2$D!^mPkNU1 zKo>Kp5GtpKyC~y~i`!UqaR)UQ9_obB1nZ)Kro@uV)){`n`6Ny9!GtdI<5%s?U}vm> zB|eH&U&SnF)*HM1r=w6ThT&Un$E&XsY*w$^9~6M~`u`9XG`6VNJ-y&ZENu91vUVrw z50bbTCQ~)=!#Lx2pXN^jh!?x#X!2tJTsh0x5});5rLhNUe1-9R59Vixk6dGJj`|~k zUl7>m{X8!GK`wG#-`I^$5X}*$PD2j(=MTAI_5|{hhY7CSGgqq`HG=gXHJw#Qkl#_- xXf<0OAjK{Oi?CZGIPVPF{r&SV_W~?d#?Ma%=E+2j1e$!lOBM^e$m|9#9RoeHg604K literal 0 HcmV?d00001 diff --git a/bacula-backup/CbScrollbar.class b/bacula-backup/CbScrollbar.class new file mode 100644 index 0000000000000000000000000000000000000000..726106fc199f2cdba19a8d6081432e830ae1e1a7 GIT binary patch literal 4304 zcmZ`+Yj9K75&o`pC0Rl?;vokkDFGTlzBW*xb%}WtFfX?TQl14`K-Rrj7xXZ)Yy%+# z(l#L^O`9f!n$SQ~8s$MKP|HprkG4sZG}BJn&h$syw9}uR=}i7~`lHjCPQN|6mgJDa zcz4g9J$rV~`F79M2mihKCft~Z_XGGm@&UA=&rhk~M?VHc8Wib>NJm9FCenQ(9T(|- zkxq#8fJi4rIwjJBB7H-gep94x33(`hhjH46M*?WX8PPl{n#V-?wvfk#d`HN4W#tnA zd=F0wdCHFkI4k67nLX#HgL46VA45XU3wcH+E(rO7kY|Nl6mn?-eu(G9%a44x9H5UM zi}UA&6vf~LF?i93mwb3xL*0(GTefv}tm@LBb!w>Z$YuKqiELpA78bVzM69b6_iNV5xj$AsIr)y3uQgktC zN{mQFlS)$K>gHP4QEFXBsdOC?=?Ep=%qMynLL#5f4N^I|Hu6=Xl(5w-t-Z_atX){4 zp();3YgkFKc?Vr~NN6Ad$ z&Ag1dF)MBqS0;gE%1RzmccYBB%F~;$7LOO-~M97zfTodwTA=ia;3ArI;qmZ8p*(Bs^_<9hlu_TD)SmDEP5G9O^ zk3hjdHXjXQ8@31WDqag>he#c=aE*|)Lb{Rk;bsuGB+l1yFo-uq{icvFVxFxlC^^D|o7bWK}sn3ddA|+$jpZPa)bfXqyEdtv6-KIcS(vIj6BwDOa27FdC+e z3qhKWs?P&;HM9|gjbThVk5lt><<_Z;fF!r4^XS!0(2RsZ1-(zd1E6lb+J^LPxT z(SiptA7}YIzkr220QM&5820dZbb4!%BqBz%gs2fKA;uh{{EJ;??!rYsiaU)F+*J+a zPWZUA9Uh`7fMpD8Ic5<@bBH2?_|dQz`<#tpo*b%vei7<>H-sRGqoaS$WU_OU(~#ekV;Gq zIA6`GL1Aelv)P1Jwowfxtg>tO9%9DN61pgU&O^V>1DP?5naj(3)(YxBGo-eeHjKN^ z6C}f!t|Xscgzj$B!}<_`I*bWLf@~O`cF&lmzO3=Jd&e{r%Nl>XuZ5i9+RwDMD99A;xmR&*W@e0Q;wj7c?uPMGfW?6{q`(=}gR&d5i>WcU$h*)}k!t%Au5(>838xajXuhnld%5yeXA$&8muy zf~*uk%#-D<9y6vAZ_)QtaGX}O6nOh{t6+YKg$Tajb^O4X#@5-+&x^fmgS~8?M_6qq z*(4ugQ#{X}aEV>vbr$T~ti=yljUTb5{>7^L4@@ltOPhrQ+9LF5tNG!u4YroTLG3sW zX{V6Z&LN{+MK9amVeJj%wGYv!{T&7EWAwY+7;uF#=$efqF8!6H+2h=WpFhrCPqU~!+^gG&NJk%4o3cU#+|zWOm!m36LYdC; zjhX7g%DN&X0$PQ2-3;pj3}r_@G#jTK*E(nMM!=s*A{x}l423wlMx)x+dWoY$6*tu`Jc5Ov zG<}|?X=F&H3%|qjmzUvWdB>H~HsjCn@gt8GMzE-e1EOob%tkFbrP?Y_sbMH%wv5Gc zD@81qx1?qK;%3pcj$7PVUaXAA7VFiwViAIj=Vd-RukbFf@(>&sMn2lN5g-?=M z%*&N#sTxNt751gon=(7Bhds(jf~Jw@Hls1bhP~q<`?)e?C6;Q6ZG6n+=zaV|Z^FBT z#d~~B-)GtWioZF2&EotG)AP5feuI@WseGC1G`~I1S{1GAf7k*a!6*KTR`tD^+E*$) literal 0 HcmV?d00001 diff --git a/bacula-backup/CbScrollbar.java b/bacula-backup/CbScrollbar.java new file mode 120000 index 000000000..ff9b1ebc3 --- /dev/null +++ b/bacula-backup/CbScrollbar.java @@ -0,0 +1 @@ +../file/CbScrollbar.java \ No newline at end of file diff --git a/bacula-backup/CbScrollbarArrow.class b/bacula-backup/CbScrollbarArrow.class new file mode 100644 index 0000000000000000000000000000000000000000..1d814eccdba751b1c5e405deb889d232f8f88045 GIT binary patch literal 1941 zcmZWqOH&+G6#mY1_w>xrgqJ{uhY2K@c@PkYMtQ}^BTghC0>K0{rkUw5O`7RR&j3-Y zTv+8gRa!2R6+0HXu>`c#a+!rc!Hre^2Hk1mIo&V=W~%19x6k9d=brQR%x}+r`V|V! z<6#UhOJKuXtuLZ)Zy*k{MlhH%iu|yHy}G z9|@Y;nIp_1w95_ zc`RaxOZb1&q=W|s&LLsIlVVB&Wo#JO#1^5cnlSY+YZc43%a=QPlgpmxa$ubwD6N|? z3!7$%Csa+H+b9%*UI#`$%v~?K1%IGw$^L}<(~?M52QX=`TReQXz+Sqn9p)+*v=SQ$+CJXcR7>+AyTr+ zJ_YyWhy(&w8Fl2I?KpE*mMhT{8UBc|MvOOH=i^mrTO_fZSq>bLoM&!{5;@wl4g}bG zK)~zDn&w-Gw$5tl{z0F7(H!$PQw`E;_6p^TaBinqlpj z$EbK}hr{V0`@}x#(u&g2xsUqrFR@`=Ai_T733}tY(xExCab4|DbG&HEY&@a}sGVYn zXtM0!k;JRpNO1ytIo!|E{H)^%3Wwj7aBbV?55fcXgYZsCuACqV{gM#g#<>dr3+4DZ zemUv5CU=VK@kn?d4RX)M$B4w$9cXd3h)eC`1N!(vylQ>>XsSeoB}xsV6!!AB8dV+Q z8rpb73hGHkiZo187k=#h^N$q->DgYQY-$ZlT<@( z)I=S0mOAMoouV;1P1Dpxx2T&OIzyka=S%8gS@h%8KpgzHp!)J@PpNxoWM#aR`Wel) zS!*pzduZLqN%h;~N~0t+N+C*V#Hp8Q1}bD@ELG8BJf$3x?V|OmFD#~tzd$v>RD(=4 zgjTx1RD-PcK=li(c~O0$f&Lohj)(ja7oR{6?Lg&zwzYrpBiea?tv)xp^ZXCai}Rb- bg$~|TUJDw5N@HB;IJ)T)doD0%2(SGIlB;xY literal 0 HcmV?d00001 diff --git a/bacula-backup/CbScrollbarCallback.class b/bacula-backup/CbScrollbarCallback.class new file mode 100644 index 0000000000000000000000000000000000000000..ffa8927a9df83141eafcf59bd5c5fb653b072676 GIT binary patch literal 164 zcmX^0Z`VEsW(HjbE_MbEb_PyH2G-pCveXnt20;xU=cM4|qWqkkq{Jd?Pt7n!1~#Bv zW?niY16Ock)#%|1-yBi`q2lmx~Y z^J9SthPjqTS>OZ~(zq_Lh);O=G>wWt6-yc1z)eBRXDt5Q#n)O` z8ZEy;aJk|E9vg^d-7yVS_F3uZHDk0{^8-(BUt)X*MUc{XnJ!kf`(hq=N=LBBi8)P#ONC95M?=?nIFc!k1fmJBGKA-XoMExv{}W z-xEK?L%43E>0lkV9Qd4fD&oV&9S0kjv_ZZ%5jfD;a_|FdWCs`{GRyuw<&}-xWHR^M zlw_+_mrVXpktxsb=Tp)_D5+A!Nv5sBy#P<`7MBT+WmOr-rZRDfi;IkM{*VqhyeF~^ z-3h{o|8^9^B4t)wj8JmxvR&0i4ct=kGJ(1m8(0`CPW~U3V5CRXy91Gy^yZchs1&oi z1|0r@(8AnvBYs-*Ip&8Z{4B>2LnHeH$E{4yVk_c5*tHZXbzS4?|rf`$*N2Jshd_Vb?C?(>-LCruq=I zi(O>t!XX_x=I&#H#KSBe>EUP>$JYM%@3EWDPjxZ6*2fs(jn53$V?+{P%qr7`@3ar{i<@fRG&ucZAO3b>Dxgf>M}InMta?aWAu{JwPHiYGO2 Onp~YBg-di!VEPHl| zu|NyK(kl1*QI@BNFmd5xZclfgd(OG{_U}L6e-*%Rzzho_!cv6)s6cnI(&2oz+IlUv@Kp>l&UAK0u zytNzT!=usOH^eyPbhe#E`#m!obG;SNlE+iO9nIcyR)sn z=xzHea>iEj>F{F4w;VaB6b&@tqJi^hG;jfp8txky#{&%y4NRaz!=!;JOdFU{h(`+X z*gyfT8lD(Tuq`f+A`|yFezYC9nDflQC3Fbr6&nJz5j^z8=Di5)68jo# zkgHPjlIN8+?0^;5MH%HYHepo;iz~jA?r9TFNlTWynxC@*H6Wi2_ndG*Q=G%DT?~)c zq`kVv5mZc1dd{ZjhI2_c-VVD~aaf*LGO&CKM)pFTh2?d*qU^=&B0C*6Y|_>CmYz9VQ=r4PA{J^r2JUsGaZ?-;4i%oS*1Yz}!+NN}x%PSt9(!@v+~LdDjy zVxFGj#HXpKn=MMQm5LRj+VHxbL>UrgnZ{>OPM%=0Dyf|=s?ATxay9Dl>myR;F=`SA zX5R^F4J literal 0 HcmV?d00001 diff --git a/bacula-backup/FixedFrame.java b/bacula-backup/FixedFrame.java new file mode 120000 index 000000000..ba13f3893 --- /dev/null +++ b/bacula-backup/FixedFrame.java @@ -0,0 +1 @@ +../file/FixedFrame.java \ No newline at end of file diff --git a/bacula-backup/GrayPanel.class b/bacula-backup/GrayPanel.class new file mode 100644 index 0000000000000000000000000000000000000000..5e0cdb790fe165b599470d57eac74e28ae600308 GIT binary patch literal 571 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 X4y*6Pnu1;JJH}8R}pR!=)A literal 0 HcmV?d00001 diff --git a/bacula-backup/Hierarchy.java b/bacula-backup/Hierarchy.java new file mode 120000 index 000000000..ed58e5552 --- /dev/null +++ b/bacula-backup/Hierarchy.java @@ -0,0 +1 @@ +../file/Hierarchy.java \ No newline at end of file diff --git a/bacula-backup/HierarchyCallback.class b/bacula-backup/HierarchyCallback.class new file mode 100644 index 0000000000000000000000000000000000000000..ca85e3973faa2888dba7d1765db3600451f75879 GIT binary patch literal 219 zcmX^0Z`VEsW(Hjb9(D#Ub_Q-n29ErK)I7iZlvG9rSq&eL%+#X9qU4N9YXlP{X{{N? z$iSJLlV6+)Q43^eCTBy~Tq*gbNjXpnuHgLAqU2P!%p9PJd~oyhvJ%S@85soO0?vs! zIZ27h*^CSVASwNv#JqHU|D>$chSOQ|6|wA?_n}C)%O;@E!vLE$=o@@ zw|slDx|G}KC}3B|7Lqzr*w&#Vts{dhA-(DBMQ_SQ+ehK|qbcu+3jdY{FhV9ULWV@l zIT3SI#5wFloR3&x&4WSMV|C0-%yHul^vZ&;&zO)V)masAz*@Gpp&-s&lC4HLgkoHT nh#9pIs!>!!#DDIW6*AO9fv!=c8%{gq6a~d^>~3CW literal 0 HcmV?d00001 diff --git a/bacula-backup/Makefile b/bacula-backup/Makefile new file mode 100644 index 000000000..37119eec7 --- /dev/null +++ b/bacula-backup/Makefile @@ -0,0 +1,2 @@ +TreeChooser.class: TreeChooser.java + CLASSPATH=/usr/local/netscape7/plugins/java2/lib/javaplugin.jar:. javac -target 1.1 *.java diff --git a/bacula-backup/TreeChooser.class b/bacula-backup/TreeChooser.class new file mode 100644 index 0000000000000000000000000000000000000000..3a08be287f0ad6beb5f670ab689cb1717aef8c57 GIT binary patch literal 6027 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 FF9G*&`kw#* literal 0 HcmV?d00001 diff --git a/bacula-backup/TreeChooser.java b/bacula-backup/TreeChooser.java new file mode 100644 index 000000000..51fdf28fc --- /dev/null +++ b/bacula-backup/TreeChooser.java @@ -0,0 +1,295 @@ +import java.awt.*; +import java.io.*; +import java.applet.*; +import java.net.*; +import java.util.*; +import netscape.javascript.JSObject; + +public class TreeChooser extends Applet + implements CbButtonCallback, HierarchyCallback +{ + CbButton add_b, remove_b, close_b; + Hierarchy tree; + BaculaNode root; + String volume; + String session; + String job; + Vector added = new Vector(); + + public void init() + { + // Create the root + String rpath = getParameter("root"); + root = new BaculaNode(this, rpath, true, null); + volume = getParameter("volume"); + session = getParameter("session"); + job = getParameter("job"); + + // Build the UI + setLayout(new BorderLayout()); + BorderPanel top = new BorderPanel(2); + top.setLayout(new FlowLayout(FlowLayout.LEFT)); + top.add(add_b = new CbButton("Add", this)); + top.add(remove_b = new CbButton("Remove", this)); + top.add(close_b = new CbButton("Close", this)); + add("North", top); + add("Center", tree = new Hierarchy(root, this)); + } + + Image get_image(String img) + { + return getImage(getDocumentBase(), "images/"+img); + } + + String[] get_text(String url) + { + Cursor orig = getCursor(); + try { + Cursor busy = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR); + setCursor(busy); + long now = System.currentTimeMillis(); + if (url.indexOf('?') > 0) url += "&rand="+now; + else url += "?rand="+now; + URL u = new URL(getDocumentBase(), url); + URLConnection uc = u.openConnection(); + set_cookie(uc); + String charset = get_charset(uc.getContentType()); + BufferedReader is = new BufferedReader( + (charset == null) ? + new InputStreamReader(uc.getInputStream()) : + new InputStreamReader(uc.getInputStream(), charset)); + Vector lv = new Vector(); + while(true) { + String l = is.readLine(); + if (l == null) { break; } + lv.addElement(l); + } + is.close(); + String rv[] = new String[lv.size()]; + lv.copyInto(rv); + return rv; + } + catch(Exception e) { + e.printStackTrace(); + //return null; + String err[] = { e.getMessage() }; + return err; + } + finally { + setCursor(orig); + } + } + + void set_cookie(URLConnection conn) + { + if (session != null) + conn.setRequestProperty("Cookie", session); + } + + // Gets charset parameter from Content-Type: header + String get_charset(String ct) + { + if (ct == null) + return null; + StringTokenizer st = new StringTokenizer(ct, ";"); + while (st.hasMoreTokens()) { + String l = st.nextToken().trim().toLowerCase(); + if (l.startsWith("charset=")) { + // get the value of charset= param. + return l.substring(8); + } + } + return null; + } + + public void openNode(Hierarchy h, HierarchyNode n) + { + // Get the files under this directory, and expand the tree + BaculaNode bn = (BaculaNode)n; + bn.fill(); + } + + public void closeNode(Hierarchy h, HierarchyNode n) + { + // No need to do anything + } + + public void clickNode(Hierarchy h, HierarchyNode n) + { + // Also no need to do anything + } + + public void doubleNode(Hierarchy h, HierarchyNode n) + { + // add or remove a file + BaculaNode sel = (BaculaNode)n; + if (sel.added) remove_node(sel); + else add_node(sel); + } + + public void click(CbButton b) + { + BaculaNode sel = (BaculaNode)tree.selected(); + if (b == close_b) { + // Close the window, and update the text box + try { + JSObject win = JSObject.getWindow(this); + String params1[] = { "" }; + win.call("clear_files", params1); + for(int i=0; iU>dF!a-ERfI<6OfgOD2y3fyF158fo?W&>}= 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 Dwb&gW literal 0 HcmV?d00001 diff --git a/bacula-backup/Util.java b/bacula-backup/Util.java new file mode 120000 index 000000000..1ba3fa0ff --- /dev/null +++ b/bacula-backup/Util.java @@ -0,0 +1 @@ +../file/Util.java \ No newline at end of file diff --git a/bacula-backup/apply.cgi b/bacula-backup/apply.cgi new file mode 100755 index 000000000..dc8026922 --- /dev/null +++ b/bacula-backup/apply.cgi @@ -0,0 +1,11 @@ +#!/usr/local/bin/perl +# Apply the Bacula configuration + +require './bacula-backup-lib.pl'; +&error_setup($text{'apply_err'}); +$err = &apply_configuration(); +&error($err) if ($err); +&webmin_log("restart"); +&redirect(""); + + diff --git a/bacula-backup/backup.cgi b/bacula-backup/backup.cgi new file mode 100755 index 000000000..65d6ceffd --- /dev/null +++ b/bacula-backup/backup.cgi @@ -0,0 +1,81 @@ +#!/usr/local/bin/perl +# Actually execute a backup + +require './bacula-backup-lib.pl'; +&ui_print_unbuffered_header(undef, $text{'backup_title'}, ""); +&ReadParse(); + +print "",&text('backup_run', "$in{'job'}"),"\n"; +print "
";
+$h = &open_console();
+
+# Clear messages
+&console_cmd($h, "messages");
+
+# Select the job to run
+&sysprint($h->{'infh'}, "run\n");
+&wait_for($h->{'outfh'}, 'run\\n');
+$rv = &wait_for($h->{'outfh'}, 'Select Job.*:');
+print $wait_for_input;
+if ($rv == 0 && $wait_for_input =~ /(\d+):\s+\Q$in{'job'}\E/) {
+	&sysprint($h->{'infh'}, "$1\n");
+	}
+else {
+	&job_error($text{'backup_ejob'});
+	}
+
+# Say that it is OK
+$rv = &wait_for($h->{'outfh'}, 'OK to run.*:');
+print $wait_for_input;
+if ($rv == 0) {
+	&sysprint($h->{'infh'}, "yes\n");
+	}
+else {
+	&job_error($text{'backup_eok'});
+	}
+
+print "
"; + +if ($in{'wait'}) { + # Wait till we have a status + print "\n"; + print "",$text{'backup_running'},"\n"; + print "
";
+	while(1) {
+		$out = &console_cmd($h, "messages");
+		if ($out !~ /You\s+have\s+no\s+messages/i) {
+			print $out;
+			}
+		if ($out =~ /Termination:\s+(.*)/) {
+			$status = $1;
+			last;
+			}
+		sleep(1);
+		}
+	print "
\n"; + if ($status =~ /Backup\s+OK/i && $status !~ /warning/i) { + print "",$text{'backup_done'},"

\n"; + } + else { + print "",$text{'backup_failed'},"

\n"; + } + } +else { + # Let it fly + print "",$text{'backup_running2'},"

\n"; + } + +&close_console($h); +&webmin_log("backup", $in{'job'}); + +&ui_print_footer("backup_form.cgi", $text{'backup_return'}); + +sub job_error +{ +&close_console($h); +print "\n"; +print "",@_,"

\n"; +&ui_print_footer("backup_form.cgi", $text{'backup_return'}); +exit; +} + diff --git a/bacula-backup/backup_form.cgi b/bacula-backup/backup_form.cgi new file mode 100755 index 000000000..17d663839 --- /dev/null +++ b/bacula-backup/backup_form.cgi @@ -0,0 +1,24 @@ +#!/usr/local/bin/perl +# Show a form for running one backup job + +require './bacula-backup-lib.pl'; +&ui_print_header(undef, $text{'backup_title'}, "", "backup"); + +print &ui_form_start("backup.cgi", "post"); +print &ui_table_start($text{'backup_header'}, undef, 2); + +# Job to run +@jobs = sort { lc($a->{'name'}) cmp lc($b->{'name'}) } + grep { !&is_oc_object($_) } &get_bacula_jobs(); +print &ui_table_row($text{'backup_job'}, + &ui_select("job", undef, + [ map { [ $_->{'name'}, &text('backup_jd', $_->{'name'}, $_->{'fileset'}, $_->{'client'}) ] } @jobs ])); + +# Wait for completion? +print &ui_table_row($text{'backup_wait'}, + &ui_yesno_radio("wait", $config{'wait'})); + +print &ui_table_end(); +print &ui_form_end([ [ "backup", $text{'backup_ok'} ] ]); + +&ui_print_footer("", $text{'index_return'}); diff --git a/bacula-backup/bacula-backup-lib.pl b/bacula-backup/bacula-backup-lib.pl new file mode 100644 index 000000000..133de454e --- /dev/null +++ b/bacula-backup/bacula-backup-lib.pl @@ -0,0 +1,1532 @@ +# Common functions for the bacula config file +# XXX other schedule-level overrides, like pool, storage, etc.. +# XXX schedule chooser on IE + +do '../web-lib.pl'; +&init_config(); +do '../ui-lib.pl'; +use Time::Local; +if (&foreign_check("node-groups")) { + &foreign_require("node-groups", "node-groups-lib.pl"); + } + +$dir_conf_file = "$config{'bacula_dir'}/bacula-dir.conf"; +$fd_conf_file = "$config{'bacula_dir'}/bacula-fd.conf"; +$sd_conf_file = "$config{'bacula_dir'}/bacula-sd.conf"; +$bconsole_conf_file = "$config{'bacula_dir'}/bconsole.conf"; +$console_conf_file = "$config{'bacula_dir'}/console.conf"; +$console_cmd = -r "$config{'bacula_dir'}/bconsole" ? + "$config{'bacula_dir'}/bconsole" : + "$config{'bacula_dir'}/console"; +$bacula_cmd = "$config{'bacula_dir'}/bacula"; + +@backup_levels = ( "Full", "Incremental", "Differential", + "InitCatalog", "Catalog", "VolumeToCatalog", "DiskToCatalog" ); +@pool_types = ( "Backup", + "*Archive", "*Cloned", "*Migration", "*Copy", "*Save" ); + +$cron_cmd = "$module_config_directory/sync.pl"; + +# connect_to_database() +# Connects to the Bacula database, and returns the DBI handle +sub connect_to_database +{ +local $drh; +eval <install_driver(\$config{'driver'} || "mysql"); +EOF +if ($@) { + die $text{'connect_emysql'}."\n"; + } +local $dbistr = &make_dbistr($config{'driver'}, $config{'db'}, $config{'host'}); +local $dbh = $drh->connect($dbistr, + $config{'user'}, $config{'pass'}, { }); +$dbh || die &text('connect_elogin', "$config{'db'}",$drh->errstr)."\n"; +local $testcmd = $dbh->prepare("select count(*) from job"); +if (!$testcmd) { + die &text('connect_equery', "$config{'db'}")."\n". + ($config{'driver'} eq "SQLite" ? $text{'connect_equery2'} : ""); + } +$testcmd->finish(); +return $dbh; +} + +# read_config_file(file) +# Parses a bacula config file +sub read_config_file +{ +local ($file) = @_; +if (!defined($config_file_cache{$file})) { + local @rv = ( ); + local $parent = { 'members' => \@rv }; + local $lnum = 0; + open(CONF, $_[0]) || return undef; + while() { + s/\r|\n//g; + s/#.*$//; + if (/^\s*\@(.*\S)/) { + # An include file reference .. parse it + local $incfile = $1; + if ($incfile !~ /^\//) { + $incfile = "$config{'bacula_dir'}/$incfile"; + } + if (-d $incfile) { + # Read a whole directory of files + opendir(INCDIR, $incfile); + foreach my $f (readdir(INCDIR)) { + next if ($f eq "." || $f eq ".."); + local $inc = &read_config_file( + "$incfile/$f"); + push(@{$parent->{'members'}}, @$inc); + } + closedir(INCDIR); + } + else { + # Read just one file + local $inc = &read_config_file($incfile); + push(@{$parent->{'members'}}, @$inc); + } + } + elsif (/^\s*}\s*$/) { + # End of a section + $parent->{'eline'} = $lnum; + $parent = $parent->{'parent'}; + $parent || + die "Too many section ends at line ".($lnum+1); + } + elsif (/^\s*(\S+)\s*{\s*(\S[^=]*\S)\s*=\s*"(.*)"(.*)$/ || + /^\s*(\S+)\s*{\s*(\S[^=]*\S)\s*=\s*([^\{]*\S)(.*)$/) { + # Start of a section, with a name=value record on + # the same line! + local $dir = { 'name' => $1, + 'parent' => $parent, + 'line' => $lnum, + 'eline' => $lnum, + 'file' => $file, + 'type' => 1, + 'members' => [ ] }; + push(@{$parent->{'members'}}, $dir); + $parent = $dir; + local $dir = { 'name' => $2, + 'value' => $3, + 'line' => $lnum, + 'eline' => $lnum, + 'file' => $file, + 'type' => 0, + 'parent' => $parent }; + push(@{$parent->{'members'}}, $dir); + } + elsif (/^\s*(\S[^=]*\S)\s*=\s*"(.*)"(.*)$/ || + /^\s*(\S[^=]*\S)\s*=\s*([^\{]*\S)(.*)$/) { + # A name=value record + local $rest = $3; + local $dir = { 'name' => $1, + 'value' => $2, + 'line' => $lnum, + 'eline' => $lnum, + 'file' => $file, + 'type' => 0, + 'parent' => $parent }; + push(@{$parent->{'members'}}, $dir); + + if ($rest =~ /\s*{\s*$/) { + # Also start of a section! + $dir->{'type'} = 2; + $dir->{'members'} = [ ]; + $parent = $dir; + } + } + elsif (/^\s*(\S+)\s*{\s*$/) { + # Start of a section + local $dir = { 'name' => $1, + 'parent' => $parent, + 'line' => $lnum, + 'eline' => $lnum, + 'file' => $file, + 'type' => 1, + 'members' => [ ] }; + push(@{$parent->{'members'}}, $dir); + $parent = $dir; + } + $lnum++; + } + close(CONF); + $config_file_cache{$file} = \@rv; + } +return $config_file_cache{$file}; +} + +# read_config_file_parent(file) +sub read_config_file_parent +{ +local ($file) = @_; +if (!$config_file_parent_cache{$file}) { + local $conf = &read_config_file($file); + return undef if (!$conf); + local $lref = &read_file_lines($file); + $config_file_parent_cache{$file} = + { 'members' => $conf, + 'type' => 2, + 'file' => $file, + 'line' => 0, + 'eline' => scalar(@$lref) }; + } +return $config_file_parent_cache{$file}; +} + +# find(name, &conf) +sub find +{ +local ($name, $conf) = @_; +local @rv = grep { lc($_->{'name'}) eq lc($name) } @$conf; +return wantarray ? @rv : $rv[0]; +} + +sub find_value +{ +local ($name, $conf) = @_; +local @rv = map { $_->{'value'} } &find(@_); +return wantarray ? @rv : $rv[0]; +} + +sub find_by +{ +local ($field, $value, $conf) = @_; +foreach my $f (@$conf) { + my $name = &find_value($field, $f->{'members'}); + return $f if ($name eq $value); + } +return undef; +} + +sub get_director_config +{ +return &read_config_file($dir_conf_file); +} + +sub get_director_config_parent +{ +return &read_config_file_parent($dir_conf_file); +} + +sub get_storage_config +{ +return &read_config_file($sd_conf_file); +} + +sub get_storage_config_parent +{ +return &read_config_file_parent($sd_conf_file); +} + +sub get_file_config +{ +return &read_config_file($fd_conf_file); +} + +sub get_file_config_parent +{ +return &read_config_file_parent($fd_conf_file); +} + +sub get_bconsole_config +{ +return &read_config_file($bconsole_conf_file); +} + +sub get_bconsole_config_parent +{ +return &read_config_file_parent($bconsole_conf_file); +} + +# save_directive(&conf, &parent, name|&old, &new, indent) +# Updates a section or value in the Bacula config file +sub save_directive +{ +local ($conf, $parent, $name, $new, $indent) = @_; +local $old; +if (ref($name)) { + $old = $name; + $name = $old->{'name'}; + } +else { + $old = &find($name, $parent->{'members'}); + } +local $lref = $old && $old->{'file'} ? &read_file_lines($old->{'file'}) : + $parent->{'file'} ? &read_file_lines($parent->{'file'}) : undef; +if (defined($new) && !ref($new)) { + $new = { 'name' => $name, + 'value' => $new }; + } + +local @lines = $new ? &directive_lines($new, $indent) : ( ); +local $len = $old ? $old->{'eline'} - $old->{'line'} + 1 : undef; +if ($old && $new) { + # Update this object + if ($lref) { + splice(@$lref, $old->{'line'}, $len, @lines); + &renumber($conf, $old->{'line'}, scalar(@lines)-$len, + $old->{'file'}); + } + $old->{'value'} = $new->{'value'}; + $old->{'members'} = $new->{'members'}; + $old->{'type'} = $new->{'type'}; + $old->{'eline'} = $old->{'line'} + scalar(@lines) - 1; + } +elsif (!$old && $new) { + # Add to the parent + $new->{'line'} = $parent->{'eline'}; + $new->{'eline'} = $new->{'line'} + scalar(@lines) - 1; + $new->{'file'} = $parent->{'file'}; + if ($lref) { + splice(@$lref, $parent->{'eline'}, 0, @lines); + &renumber($conf, $new->{'line'}-1, scalar(@lines), + $parent->{'file'}); + } + push(@{$parent->{'members'}}, $new); + } +elsif ($old && !$new) { + # Delete from the parent + if ($lref) { + splice(@$lref, $old->{'line'}, $len); + &renumber($conf, $old->{'line'}, -$len, $old->{'file'}); + } + @{$parent->{'members'}} = grep { $_ ne $old } @{$parent->{'members'}}; + } +} + +# save_directives(&conf, &parent, name, &newvalues, indent) +# Updates multiple directives in a section +sub save_directives +{ +local ($conf, $parent, $name, $news, $indent) = @_; +local @news = map { ref($_) ? $_ : { 'name' => $name, 'value' => $_ } } @$news; +local @olds = &find($name, $parent->{'members'}); +for(my $i=0; $i<@news || $i<@olds; $i++) { + &save_directive($conf, $parent, $olds[$i], $news[$i], $indent); + } +} + +# renumber(&conf, start, offset, file) +sub renumber +{ +local ($conf, $line, $offset, $file) = @_; +foreach my $c (@$conf) { + $c->{'line'} += $offset if ($c->{'line'} > $line && + $c->{'file'} eq $file); + $c->{'eline'} += $offset if ($c->{'eline'} > $line && + $c->{'file'} eq $file); + if ($c->{'type'}) { + &renumber($c->{'members'}, $line, $offset); + } + } +local $parent = $config_file_parent_cache{$file}; +if ($conf eq $parent->{'members'}) { + # Update parent lines too + $parent->{'line'} += $offset if ($parent->{'line'} > $line); + $parent->{'eline'} += $offset if ($parent->{'eline'} > $line); + } +} + +# directive_lines(&object, indent) +# Returns the text lines of a Bacula directive +sub directive_lines +{ +local ($dir, $indent) = @_; +local $istr = " " x $indent; +local @rv; +if ($dir->{'type'}) { + # A section + push(@rv, $istr.$dir->{'name'}. + ($dir->{'value'} ? " $dir->{'value'}" : "")." {"); + foreach my $m (@{$dir->{'members'}}) { + push(@rv, &directive_lines($m, $indent+1)); + } + push(@rv, $istr."}"); + } +else { + # A single line + local $qstr = $dir->{'value'} =~ /^\S+$/ || + $dir->{'value'} =~ /^\d+\s+(secs|mins|hours|days|weeks|months|years)$/i || + $dir->{'name'} eq 'Run' ? $dir->{'value'} : + $dir->{'value'} =~ /"/ ? "'$dir->{'value'}'" : + "\"$dir->{'value'}\""; + push(@rv, $istr.$dir->{'name'}." = ".$qstr); + } +return @rv; +} + +# bacula_file_button(filesfield, [jobfield], [volume]) +# Pops up a window for selecting multiple files, using a tree-like view +sub bacula_file_button +{ +return "\n"; +} + +sub tape_select +{ +local $t; +print "\n"; +print " ",&file_chooser_button("other", 1),"\n"; +} + +# job_select(&dbh, [volumne]) +# XXX needs value input? +# XXX needs flag for use of 'any' field? +sub job_select +{ +local $cmd; +if ($_[1]) { + $cmd = $_[0]->prepare("select Job.JobId,Job.Name,Job.SchedTime ". + "from Job,JobMedia,Media ". + "where Job.JobId = JobMedia.JobId ". + "and Media.MediaId = JobMedia.MediaId ". + "and Media.VolumeName = '$_[1]'") || + &error("prepare failed : ",$dbh->errstr); + } +else { + $cmd = $_[0]->prepare("select JobId,Name,SchedTime from Job") || + &error("prepare failed : ",$dbh->errstr); + } +$cmd->execute(); +print "\n"; +} + +# client_select(&dbh) +sub client_select +{ +local $cmd = $_[0]->prepare("select ClientId,Name from Client order by ClientId asc"); +$cmd->execute(); +print "\n"; +} + +sub unix_to_dos +{ +local $rv = $_[0]; +$rv =~ s/^\/([a-zA-Z]):/$1:/; +return $rv; +} + +sub dos_to_unix +{ +local $rv = $_[0]; +$rv =~ s/^([a-zA-Z]):/\/$1:/; +return $rv; +} + +# check_bacula() +# Returns an error message if bacula is not installed, or undef if OK +sub check_bacula +{ +if (!-d $config{'bacula_dir'}) { + return &text('check_edir', "$config{'bacula_dir'}"); + } +local $got = 0; +if (-r $dir_conf_file) { + if (!-x $bacula_cmd) { + return &text('check_ebacula', "$bacula_cmd"); + } + if (!-x $console_cmd) { + return &text('check_econsole', "$console_cmd"); + } + $got++; + } +elsif (-r $fd_conf_file) { + $got++; + } +elsif (-r $sd_conf_file) { + $got++; + } +return &text('check_econfigs', "$config{'bacula_dir'}") if (!$got); +return undef; +} + +# Returns 1 if this system is a Bacula director +sub has_bacula_dir +{ +return -r $dir_conf_file; +} + +# Returns 1 if this system is a Bacula file daemon +sub has_bacula_fd +{ +return -r $fd_conf_file; +} + +# Returns 1 if this system is a Bacula storage daemon +sub has_bacula_sd +{ +return -r $sd_conf_file; +} + +# Names of the Bacula programs +@bacula_processes = ( &has_bacula_dir() ? ( "bacula-dir" ) : ( ), + &has_bacula_sd() ? ( "bacula-sd" ) : ( ), + &has_bacula_fd() ? ( "bacula-fd" ) : ( ), + ); +if ($gconfig{'os_type'} eq 'windows') { + # On Windows, the bootup action is just called Bacula (for the FD) + @bacula_inits = ( "Bacula" ); + } +else { + # On Unix, each daemon has an action + @bacula_inits = @bacula_processes; + } + +# is_bacula_running(process) +# Returns 1 if the specified Bacula process is running, 0 of not +sub is_bacula_running +{ +local ($proc) = @_; +if (&has_command($bacula_cmd)) { + # Get status from bacula status command + $bacula_status_cache ||= `$bacula_cmd status 2>&1 &1 $out" : undef; + } +else { + return &run_all_inits("start"); + } +} + +# stop_bacula() +# Attempts to stop the Bacula processes, return undef on success or an +# error message on failure +sub stop_bacula +{ +undef($bacula_status_cache); +if (&has_command($bacula_cmd)) { + local $out = &backquote_logged("$bacula_cmd stop 2>&1 $out" : undef; + } +else { + return &run_all_inits("stop"); + } +} + +# restart_bacula() +# Attempts to re-start the Bacula processes, return undef on success or an +# error message on failure +sub restart_bacula +{ +undef($bacula_status_cache); +if (&has_command($bacula_cmd)) { + local $out = &backquote_logged("$bacula_cmd restart 2>&1 $out" : undef; + } +else { + return &run_all_inits("restart"); + } +} + +# run_all_inits(action) +# Runs all the Bacula init script with some action +sub run_all_inits +{ +local ($action) = @_; +&foreign_require("init", "init-lib.pl"); +foreach my $i (@bacula_inits) { + local $st = &init::action_status($i); + return &text('start_einit', "$i") if (!$st); + } +foreach my $i (@bacula_inits) { + local $func = $action eq "start" ? \&init::start_action : + $action eq "stop" ? \&init::stop_action : + $action eq "restart" ? \&init::restart_action : + undef; + $func || return "Unknown init action $action"; + local $err = &$func($i); + if ($err) { + return &text('start_erun', "$i", "

$err
"); + } + } +return undef; +} + +# apply_configuration() +# Tells Bacula to re-read it's config files +sub apply_configuration +{ +if (&has_bacula_dir()) { + # Call console reload + local $h = &open_console(); + local $out = &console_cmd($h, "reload"); + &close_console($h); + return defined($out) ? undef : $text{'apply_failed'}."
$out
"; + } +else { + # Need to do a restart + return &restart_bacula(); + } +} + +# auto_apply_configuration() +# Apply the configuration if automatic apply is enabled +sub auto_apply_configuration +{ +if ($config{'apply'} && &is_bacula_running($bacula_processes[0])) { + local $err = &apply_configuration(); + &error(&text('apply_problem', $err)) if ($err); + } +} + +# show_period_input(name, value) +# Returns HTML for selection a retention period +sub show_period_input +{ +local ($name, $value) = @_; +local ($t, $u) = split(/\s+/, $value); +$u ||= "days"; +$u .= "s" if ($u !~ /s$/); +return &ui_textbox($name."_t", $t, 5)." ". + &ui_select($name."_u", $u, + [ [ "seconds" ], [ "minutes" ], [ "hours" ], [ "days" ], + [ "weeks" ], [ "months" ], [ "years" ] ], 1, 0, 1); +} + +# parse_period_input(name) +sub parse_period_input +{ +local ($name) = @_; +$in{$name."_t"} =~ /^\d+$/ || return undef; +return $in{$name."_t"}." ".$in{$name."_u"}; +} + +# find_dependency(field, value, &types, &conf) +# Checks if any of the given object types have the specified field, and returns +# the name of the dependent object +sub find_dependency +{ +local ($field, $value, $types, $conf) = @_; +foreach my $name (@$types) { + local @children = &find($name, $conf); + local $child = &find_by($field, $value, \@children); + if ($child) { + local $cname = &find_value("Name", $child->{'members'}); + return $cname; + } + } +return undef; +} + +# open_console() +# Starts the Bacula console process, and returns a handle object for it +sub open_console +{ +##&foreign_require("proc", "proc-lib.pl"); +#$ENV{'TERM'} = "dumb"; +#local ($fh, $fpid) = &proc::pty_process_exec($console_cmd); +#&wait_for($fh, '\\*'); # skip first prompt +#return { 'fh' => $fh, +# 'fpid' => $fpid }; + +pipe(INr, INw); +pipe(OUTr, OUTw); +local $pid; +if (!($pid = fork())) { + untie(*STDIN); + untie(*STDOUT); + untie(*STDERR); + close(STDIN); + close(STDOUT); + close(STDERR); + open(STDIN, "<&INr"); + open(STDOUT, ">&OUTw"); + open(STDERR, ">&OUTw"); + $| = 1; + close(INw); + close(OUTr); + chdir($config{'bacula_dir'}); + exec($console_cmd); + print STDERR "exec failed : $!\n"; + exit(1); + } +close(INr); +close(OUTw); +local $infh = \*INw; +local $outfh = \*OUTr; +local $old = select($infh); $| = 1; +select($outfh); $| = 1; select($old); +return { 'infh' => $infh, + 'outfh' => $outfh, + 'fpid' => $pid }; +} + +# console_cmd(&handle, command) +# Runs one Bacula command, and returns the output +sub console_cmd +{ +local ($h, $cmd) = @_; +&sysprint($h->{'infh'}, $cmd."\n"); +&sysprint($h->{'infh'}, "time\n"); +local $rv = &wait_for($h->{'outfh'}, 'time\n(\d+\-\S+\-\d+ \d+:\d+:\d+)\n', + 'Unable to connect to Director'); +return undef if ($rv == 1); +$wait_for_input =~ s/time\n(\d+\-\S+\-\d+ \d+:\d+:\d+)\n//; +$wait_for_input =~ s/^\Q$cmd\E\n//; +return $rv == 0 ? $wait_for_input : undef; +} + +# close_console(&handle) +sub close_console +{ +local ($h) = @_; +&console_cmd($h, "quit"); +close($h->{'infh'}); +close($h->{'outfh'}); +kill('TERM', $h->{'fpid'}); +waitpid($h->{'pid'}, -1); +} + +# get_bacula_version() +# Get the Bacula version, either from one of the command-line programs, or +# from the console +sub get_bacula_version +{ +foreach my $p (@bacula_processes) { + if (&has_command($p)) { + local $out = `$p -\? 2>&1`; + if ($out =~ /Version:\s+(\S+)/) { + return $1; + } + } + } +local $h = &open_console(); +local $out = &console_cmd($h, "version"); +&close_console($h); +if ($out =~ /Version:\s+(\S+)/) { + &open_tempfile(CACHE, ">$module_config_directory/version"); + &print_tempfile(CACHE, $1,"\n"); + &close_tempfile(CACHE); + return $1; + } +return undef; +} + +sub get_bacula_version_cached +{ +open(CACHE, "$module_config_directory/version"); +chop($version = ); +close(CACHE); +return $version || &get_bacula_version(); +} + +# get_bacula_jobs() +# Returns a list of all jobs known to Bacula +sub get_bacula_jobs +{ +local $h = &open_console(); +local $jobs = &console_cmd($h, "show jobs"); +&close_console($h); +local @rv; +local $job; +foreach my $l (split(/\r?\n/, $jobs)) { + if ($l =~ /^Job:\s+name=([^=]*\S)\s/) { + $job = { 'name' => $1 }; + push(@rv, $job); + } + elsif ($l =~ /Client:\s+name=([^=]*\S)\s/ && $job) { + $job->{'client'} = $1; + } + elsif ($l =~ /FileSet:\s+name=([^=]*\S)\s/ && $job) { + $job->{'fileset'} = $1; + } + } +return @rv; +} + +# get_bacula_clients() +# Returns a list of all clients known to Bacula +sub get_bacula_clients +{ +local $h = &open_console(); +local $clients = &console_cmd($h, "show clients"); +&close_console($h); +local @rv; +local $client; +foreach my $l (split(/\r?\n/, $clients)) { + if ($l =~ /^Client:\s+name=([^=]*\S)\s/) { + $client = { 'name' => $1 }; + if ($l =~ /address=(\S+)/ && $client) { + $client->{'address'} = $1; + } + if ($l =~ /FDport=(\d+)/ && $client) { + $client->{'port'} = $1; + } + push(@rv, $client); + } + } +return @rv; +} + +# get_bacula_storages() +# Returns a list of all storage daemons known to Bacula +sub get_bacula_storages +{ +local $h = &open_console(); +local $storages = &console_cmd($h, "show storages"); +&close_console($h); +local @rv; +local $storage; +foreach my $l (split(/\r?\n/, $storages)) { + if ($l =~ /^Storage:\s+name=([^=]*\S)\s/) { + $storage = { 'name' => $1 }; + if ($l =~ /address=(\S+)/) { + $storage->{'address'} = $1; + } + if ($l =~ /SDport=(\d+)/) { + $storage->{'port'} = $1; + } + push(@rv, $storage); + } + } +return @rv; +} + +# get_bacula_pools() +# Returns a list of all pools known to Bacula +sub get_bacula_pools +{ +local $h = &open_console(); +local $pools = &console_cmd($h, "show pools"); +&close_console($h); +local @rv; +local $pool; +foreach my $l (split(/\r?\n/, $pools)) { + if ($l =~ /^Pool:\s+name=([^=]*\S)\s/) { + $pool = { 'name' => $1 }; + if ($l =~ /PoolType=(\S+)/) { + $pool->{'type'} = $1; + } + push(@rv, $pool); + } + } +return @rv; +} + +# get_director_status() +# Returns three arrays, containing the status of scheduled, running and finished +# jobs respectively +sub get_director_status +{ +local $h = &open_console(); +local $status = &console_cmd($h, "status dir"); +&close_console($h); +local $sect = 0; +local (@sched, @run, @done); +foreach my $l (split(/\r?\n/, $status)) { + if ($l =~ /^Scheduled\s+Jobs/i) { $sect = 1; } + elsif ($l =~ /^Running\s+Jobs/i) { $sect = 2; } + elsif ($l =~ /^Terminated\s+Jobs/i) { $sect = 3; } + + if ($sect == 1 && $l =~ /^\s*(\S+)\s+(\S+)\s+(\d+)\s+(\S+\s+\S+)\s+(\S+)\s+(\S+)\s*$/) { + push(@sched, { 'level' => &full_level($1), + 'type' => $2, + 'pri' => $3, + 'date' => $4, + 'name' => $5, + 'volume' => $6 }); + } + elsif ($sect == 2 && $l =~ /^\s*(\d+)\s+(\S+)\s+(\S+)\.(\d+\-\d+\-\S+)\s+(.*)/) { + push(@run, { 'id' => $1, + 'level' => &full_level($2), + 'name' => &job_name($3), + 'status' => $5 }); + } + elsif ($sect == 2 && $l =~ /^\s*(\d+)\s+(\S+)\.(\d+\-\d+\-\S+)\s+(.*)/) { + push(@run, { 'id' => $1, + 'level' => "Restore", + 'name' => &job_name($2), + 'status' => $4 }); + } + elsif ($sect == 3 && $l =~ /^\s*(\d+)\s+(\S+)\s+([0-9,]+)\s+([0-9,]+)\s+(\S+)\s+(\S+\s+\S+)\s+(\S+)\s*$/) { + push(@done, { 'id' => $1, + 'level' => &full_level($2), + 'files' => &remove_comma($3), + 'bytes' => &remove_comma($4), + 'status' => $5, + 'date' => $6, + 'name' => &job_name($7) }); + } + } +return (\@sched, \@run, \@done); +} + +# get_client_status(client) +# Returns a status message, OK flag, running jobs and done jobs for some client +sub get_client_status +{ +local ($client) = @_; +local $h = &open_console(); +local $status = &console_cmd($h, "status client=$client"); +&close_console($h); +local $msg; +if ($status =~ /Connecting\s+to\s+Client.*\n(\n?)(.*)\n/i) { + $msg = $2; + $msg =~ s/^\s*$client\s//; + } +local $sect = 0; +local (@run, @done); +foreach my $l (split(/\r?\n/, $status)) { + if ($l =~ /^Running\s+Jobs/i) { $sect = 2; } + elsif ($l =~ /^Terminated\s+Jobs/i) { $sect = 3; } + + if ($sect == 2 && $l =~ /^\s*JobID\s+(\d+)\s+Job\s+(\S+)\.(\d+\-\d+\-\S+)\s+(.*)/i) { + push(@run, { 'id' => $1, + 'name' => &job_name($2), + 'status' => $4 }); + } + elsif ($sect == 2 && $l =~ /^\s*Backup\s+Job\s+started:\s+(\S+\s+\S+)/) { + $run[$#run]->{'date'} = $1; + } + elsif ($sect == 3 && $l =~ /^\s*(\d+)\s+(\S+)\s+([0-9,]+)\s+([0-9,]+)\s+(\S+)\s+(\S+\s+\S+)\s+(\S+)\s*$/) { + push(@done, { 'id' => $1, + 'level' => &full_level($2), + 'files' => &remove_comma($3), + 'bytes' => &remove_comma($4), + 'status' => $5, + 'date' => $6, + 'name' => &job_name($7) }); + } + } +return ($msg, $msg =~ /failed|error/i ? 0 : 1, \@run, \@done); +} + +# get_storage_status(storage) +# Returns a status message, OK flag, running jobs and done jobs for some +# storage daemon +sub get_storage_status +{ +local ($storage) = @_; +local $h = &open_console(); +local $status = &console_cmd($h, "status storage=$storage"); +&close_console($h); +local $msg; +if ($status =~ /Connecting\s+to\s+Storage.*\n(\n?)(.*)\n/i) { + $msg = $2; + } +local $sect = 0; +local (@run, @done); +local $old_style = 0; +foreach my $l (split(/\r?\n/, $status)) { + if ($l =~ /^Running\s+Jobs/i) { $sect = 2; } + elsif ($l =~ /^Terminated\s+Jobs/i) { $sect = 3; } + + if ($sect == 2 && $l =~ /^\s*Backup\s+Job\s+(\S+)\.(\d+\-\d+\-\S+)\s+(.*)/) { + push(@run, { 'name' => &job_name($1), + 'status' => $3 }); + } + elsif ($sect == 2 && $l =~ /^\s*(\S+)\s+Backup\s+job\s+(\S+)\s+JobId=(\d+)\s+Volume="(.*)"(\s+device="(.*)")?/i) { + if (!@run || $old_style) { + push(@run, { 'name' => $2 }); + $old_style = 1; + } + $run[$#run]->{'level'} = $1; + $run[$#run]->{'id'} = $3; + $run[$#run]->{'volume'} = $4; + $run[$#run]->{'device'} = $6; + } + elsif ($sect == 3 && $l =~ /^\s*(\d+)\s+(\S+)\s+([0-9,]+)\s+([0-9,]+)\s+(\S+)\s+(\S+\s+\S+)\s+(\S+)\s*$/) { + push(@done, { 'id' => $1, + 'level' => &full_level($2), + 'files' => &remove_comma($3), + 'bytes' => &remove_comma($4), + 'status' => $5, + 'date' => $6, + 'name' => &job_name($7) }); + } + } +return ($msg, $msg =~ /failed|error/i ? 0 : 1, \@run, \@done); +} + +# get_pool_volumes(pool) +# Returns a list of volumes in some pool +sub get_pool_volumes +{ +local ($pool) = @_; +local $h = &open_console(); +local $volumes = &console_cmd($h, "llist volumes pool=$pool"); +&close_console($h); +local @volumes; +local $volume; +foreach my $l (split(/\r?\n/, $volumes)) { + if ($l =~ /^\s*(\S+):\s*(.*)/) { + # A setting in this volume + local ($n, $v) = (lc($1), $2); + $volume ||= { }; + if ($v =~ /^[0-9,]+$/) { + $v = &remove_comma($v); + } + elsif ($v eq "0000-00-00 00:00:00") { + $v = undef; + } + $volume->{$n} = $v; + } + elsif ($l =~ /^\s*$/) { + # End of this volume + push(@volumes, $volume); + $volume = undef; + } + } +push(@volumes, $volume) if ($volume && &indexof($volume, @volumes) < 0); +return @volumes; +} + +# full_level(level) +# Converts a shortened backup level to a long one +sub full_level +{ +local ($level) = @_; +foreach my $l (@backup_levels) { + return $l if ($l =~ /^\Q$level\E/i); + } +return $level; +} + +sub remove_comma +{ +local ($n) = @_; +$n =~ s/,//g; +return $n; +} + +# job_name(name) +# Converts a job name that has had spaces replaced with _ to the real name +sub job_name +{ +local ($name) = @_; +$name =~ s/_/./g; +local $conf = &get_director_config(); +foreach my $j (&find("Job", $conf)) { + local $n = &find_value("Name", $j->{'members'}); + if ($n =~ /^$name$/) { + return $n; + } + } +return $name; +} + +sub bacula_yesno +{ +local ($id, $name, $mems) = @_; +local $v = &find_value($name, $mems); +return &ui_radio($id, $v =~ /^yes/i ? "yes" : $v =~ /^no/i ? "no" : "", + [ [ "yes", $text{'yes'} ], + [ "no", $text{'no'} ], + [ "", $text{'default'} ] ]); +} + +# has_node_groups() +# Returns 1 if the system supports OC-Manager node groups +sub has_node_groups +{ +return $config{'groupmode'} && &foreign_check("node-groups"); +} + +# check_node_groups() +# Returns an error message if the node group database could not be contacted +sub check_node_groups +{ +if ($config{'groupmode'} eq 'oc') { + return $text{'check_engmod'} if (!&foreign_check("node-groups")); + return &node_groups::check_node_groups(); + } +elsif ($config{'groupmode'} eq 'webmin') { + &foreign_require("servers", "servers-lib.pl"); + local @groups = &servers::list_all_groups(); + return @groups ? undef : $text{'check_eservers'}; + } +else { + return undef; + } +} + +# list_node_groups() +# Returns a list of groups, each of which is a hash containing a name and +# a list of members +sub list_node_groups +{ +if ($config{'groupmode'} eq 'webmin') { + # Get list of groups from Webmin + &foreign_require("servers", "servers-lib.pl"); + return &servers::list_all_groups(); + } +elsif ($config{'groupmode'} eq 'oc') { + # Get list from OC database + return &node_groups::list_node_groups(); + } +else { + &error("Node groups not enabled!"); + } +} + +sub make_dbistr +{ +local ($driver, $db, $host) = @_; +local $rv; +if ($driver eq "mysql") { + $rv = "database=$db"; + } +elsif ($driver eq "Pg") { + $rv = "dbname=$db"; + } +else { + $rv = $db; + } +if ($host) { + $rv .= ";host=$host"; + } +return $rv; +} + +# is_oc_object(&client|&job|name, [force-scalar]) +# Returns the group name if the given object is associated with an OC group. +# In an array context, returns the job or client name too +sub is_oc_object +{ +local ($object, $scalar) = @_; +local $name = ref($object) && defined($object->{'members'}) ? + &find_value("Name", $object->{'members'}) : + ref($object) ? $object->{'name'} + : $object; +local @rv = $name =~ /^ocgroup[_\.](.*)$/ ? ( $1 ) : + $name =~ /^occlientjob[_\.]([^_\.]*)[_\.](.*)$/ ? ( $1, $2 ) : + $name =~ /^ocjob[_\.](.*)$/ ? ( $1 ) : + $name =~ /^occlient[_\.]([^_\.]*)[_\.](.*)$/ ? ( $1, $2 ) : ( ); +return wantarray && !$scalar ? @rv : $rv[0]; +} + +# sync_group_clients(&nodegroup) +# Update or delete all clients created from the given node group +sub sync_group_clients +{ +local ($group) = @_; +local $conf = &get_director_config(); +local $parent = &get_director_config_parent(); + +# First delete old clients and jobs +local $gclient; +local %doneclient; +foreach my $client (&find("Client", $conf)) { + local ($g, $c) = &is_oc_object($client); + if ($g eq $group->{'name'} && $c) { + # Delete this client which was generated from the group + &save_directive($conf, $parent, $client, undef); + $doneclient{$c} = 1; + } + elsif ($g eq $group->{'name'} && !$c) { + # Found the special group definition client + $gclient = $client; + } + } +foreach my $job (&find("Job", $conf)) { + local ($j, $c) = &is_oc_object($job); + if ($j && $c && $doneclient{$c}) { + # Delete this job which is associated with a group's client + &save_directive($conf, $parent, $job, undef); + } + } + +if ($gclient) { + # Create one client for each group + foreach my $m (@{$group->{'members'}}) { + local $newclient = &clone_object($gclient); + &save_directive($conf, $newclient, + "Name", "occlient_".$group->{'name'}."_".$m); + &save_directive($conf, $newclient, "Address", $m); + &save_directive($conf, $parent, undef, $newclient, 0); + } + + # Create one real job for each group job and for each client in it! + foreach my $job (&find_by("Client", "ocgroup_".$group->{'name'}, $conf)) { + local $name = &is_oc_object($job); + next if (!$name); + foreach my $m (@{$group->{'members'}}) { + local $newjob = { 'name' => 'Job', + 'type' => 1, + 'members' => [ + { 'name' => 'Name', + 'value' => "occlientjob_".$name."_".$m }, + { 'name' => 'JobDefs', + 'value' => "ocjob_".$name }, + { 'name' => 'Client', + 'value' => "occlient_". + $group->{'name'}."_".$m }, + ] }; + &save_directive($conf, $parent, undef, $newjob, 0); + } + } + } +} + +# clone_object(&object) +# Deep-clones a Bacula object, minus any file or line details +sub clone_object +{ +local ($src) = @_; +local %dest = %$src; +delete($dest{'file'}); +delete($dest{'line'}); +delete($dest{'eline'}); +$dest{'members'} = [ ]; +foreach my $sm (@{$src->{'members'}}) { + push(@{$dest{'members'}}, &clone_object($sm)); + } +return \%dest; +} + +sub find_cron_job +{ +&foreign_require("cron", "cron-lib.pl"); +local ($job) = grep { $_->{'command'} eq $cron_cmd } &cron::list_cron_jobs(); +return $job; +} + +# joblink(jobname) +# Returns a link for editing some job, if possible +sub joblink +{ +if (!defined(%joblink_jobs)) { + local $conf = &get_director_config(); + %joblink_jobs = map { $n=&find_value("Name", $_->{'members'}), 1 } + &find("Job", $conf); + } +local ($name) = @_; +local $job = $joblink_jobs{$name}; +local ($j, $c) = &is_oc_object($name); +if (!$job) { + return $j ? "$j ($c)" : $name; + } +else { + if ($j) { + return "$j ($c)"; + } + else { + return "$name"; + } + } +} + +sub sort_by_name +{ +local ($list) = @_; +@$list = sort { $na = &find_value("Name", $a->{'members'}); + $nb = &find_value("Name", $b->{'members'}); + return lc($na) cmp lc($nb) } @$list; +} + +# show_tls_directives(&object) +# Print inputs for TLS directives for a director, client or storage +sub show_tls_directives +{ +local ($object) = @_; +local $mems = $object->{'members'}; +return if (&get_bacula_version_cached() < 1.38); +print &ui_table_hr(); + +print &ui_table_row($text{'tls_enable'}, + &bacula_yesno("tls_enable", "TLS Enable", $mems)); + +print &ui_table_row($text{'tls_require'}, + &bacula_yesno("tls_require", "TLS Require", $mems)); + +print &ui_table_row($text{'tls_verify'}, + &bacula_yesno("tls_verify", "TLS Verify Peer", $mems)); + +local $cert = &find_value("TLS Certificate", $mems); +print &ui_table_row($text{'tls_cert'}, + &ui_opt_textbox("tls_cert", $cert, 60, $text{'tls_none'})." ". + &file_chooser_button("tls_cert", 0), 3); + +local $key = &find_value("TLS Key", $mems); +print &ui_table_row($text{'tls_key'}, + &ui_opt_textbox("tls_key", $key, 60, $text{'tls_none'})." ". + &file_chooser_button("tls_key", 0), 3); + +local $cacert = &find_value("TLS CA Certificate File", $mems); +print &ui_table_row($text{'tls_cacert'}, + &ui_opt_textbox("tls_cacert", $cacert, 60, $text{'tls_none'})." ". + &file_chooser_button("tls_cacert", 0), 3); +} + +# parse_tls_directives(&config, &object, indent) +sub parse_tls_directives +{ +local ($conf, $object, $indent) = @_; +return if (&get_bacula_version_cached() < 1.38); + +&save_directive($conf, $object, "TLS Enable", $in{'tls_enable'} || undef, + $indent); +&save_directive($conf, $object, "TLS Require", $in{'tls_require'} || undef, + $indent); +&save_directive($conf, $object, "TLS Verify Peer", $in{'tls_verify'} || undef, + $indent); + +$in{'tls_cert_def'} || -r $in{'tls_cert'} || &error($text{'tls_ecert'}); +&save_directive($conf, $object, "TLS Certificate", + $text{'tls_ecert_def'} ? undef : $in{'tls_cert'}, $indent); + +$in{'tls_key_def'} || -r $in{'tls_key'} || &error($text{'tls_ekey'}); +&save_directive($conf, $object, "TLS Key", + $text{'tls_ekey_def'} ? undef : $in{'tls_key'}, $indent); + +$in{'tls_cacert_def'} || -r $in{'tls_cacert'} || &error($text{'tls_ecacert'}); +&save_directive($conf, $object, "TLS CA Certificate File", + $text{'tls_ecacert_def'} ? undef : $in{'tls_cacert'}, $indent); + +if ($in{'tls_enable'} eq 'yes' && + ($in{'tls_cert_def'} || $in{'tls_key_def'} || $in{'tls_cacert_def'})) { + &error($text{'tls_ecerts'}); + } + +if (!$in{'tls_cert_def'}) { + &foreign_require("webmin", "webmin-lib.pl"); + &webmin::validate_key_cert($in{'tls_cert'}, + $in{'tls_key_def'} ? undef : $in{'tls_key'}); + } + +} + +# schedule_chooser_button(name) +# Returns a button for choosing a Bacula schedule in a popup window +sub schedule_chooser_button +{ +local ($name) = @_; +return "\n"; +} + +# parse_schedule(string) +# Returns an object containing details of a schedule, or undef if not parseable +# XXX hourly at mins +sub parse_schedule +{ +local ($str) = @_; +local @w = split(/\s+/, $str); +local $rv = { }; + +# Look for month spec +if ($w[0] eq "monthly") { + # Monthyl + $rv->{'months_all'} = 1; + shift(@w); + } +elsif ($w[0] =~ /^(\S+)\-(\S+)$/ && + defined(&is_month($1)) && defined(&is_month($2))) { + # A month range + $rv->{'months'} = [ &is_month($1) .. &is_month($2) ]; + shift(@w); + } +elsif (defined(&is_month($w[0]))) { + # One month + $rv->{'months'} = [ &is_month($w[0]) ]; + shift(@w); + } +else { + $rv->{'months_all'} = 2; + } + +# Look for days of month spec +if ($w[0] eq "on") { + shift(@w); + } +if ($w[0] =~ /^(\d+)\-(\d+)$/) { + $rv->{'days'} = [ $1 .. $2 ]; + shift(@w); + } +elsif ($w[0] =~ /^\d+$/) { + $rv->{'days'} = [ $w[0] ]; + shift(@w); + } +else { + $rv->{'days_all'} = 1; + } + +# Look for days of week +if ($w[0] =~ /^(\S+)\-(\S+)$/ && + defined(&is_nth($1)) && defined(&is_nth($2))) { + # nth weekday range + $rv->{'weekdaynums'} = [ &is_nth($1) .. &is_nth($2) ]; + shift(@w); + } +elsif (defined(&is_nth($w[0]))) { + # nth weekday of month + $rv->{'weekdaynums'} = [ &is_nth($w[0]) ]; + shift(@w); + } +else { + # Any weekday num + $rv->{'weekdaynums_all'} = 1; + } +if ($w[0] =~ /^(\S+)\-(\S+)$/ && + defined(&is_weekday($1)) && defined(&is_weekday($2))) { + # Day or week range + $rv->{'weekdays'} = [ &is_weekday($1) .. &is_weekday($2) ]; + shift(@w); + } +elsif (defined(&is_weekday($w[0]))) { + # One day of week + $rv->{'weekdays'} = [ &is_weekday($w[0]) ]; + shift(@w); + } +else { + # Any weekday + return "Missing weekday when weekday number was specified" + if (!$rv->{'weekdaynums_all'}); + $rv->{'weekdays_all'} = 1; + } + +# Look for time of day +if ($w[0] eq "at") { + shift(@w); + } +if ($w[0] =~ /^(\d+):(\d+)$/) { + $rv->{'hour'} = $1; + $rv->{'minute'} = $2; + } +elsif ($w[0] =~ /^(\d+):(\d+)(am|pm)$/i) { + $rv->{'hour'} = $1; + $rv->{'minute'} = $2; + $rv->{'hour'} += 12 if (lc($3) eq 'pm'); + } +else { + return "Missing hour:minute spec"; + } + +return $rv; +} + +sub is_month +{ +local $m = lc(substr($_[0], 0, 3)); +return $month_to_number_map{$m}; +} + +sub is_nth +{ +local $n = lc($_[0]); +return $n eq "1st" || $n eq "first" ? 1 : + $n eq "2nd" || $n eq "second" ? 2 : + $n eq "3rd" || $n eq "third" ? 3 : + $n eq "4th" || $n eq "fourth" ? 4 : + $n eq "5th" || $n eq "fifth" ? 5 : undef; +} + +sub is_weekday +{ +local $w = lc(substr($_[0], 0, 3)); +return $w eq "sun" ? 0 : + $w eq "mon" ? 1 : + $w eq "tue" ? 2 : + $w eq "wed" ? 3 : + $w eq "thu" ? 4 : + $w eq "fri" ? 5 : + $w eq "sat" ? 6 : undef; +} + +# join_schedule(&sched) +# Converts a schedule object into a string +sub join_schedule +{ +local ($sched) = @_; +local @w; + +if (!$sched->{'months_all'}) { + local $r = &make_range($sched->{'months'}, \%number_to_month_map); + defined($r) || &error($text{'chooser_emonthsrange'}); + push(@w, $r); + } + +if (!$sched->{'days_all'}) { + local %days_map = map { $_, $_ } (1 .. 31); + local $r = &make_range($sched->{'days'}, \%days_map); + defined($r) || &error($text{'chooser_edaysrange'}); + push(@w, "on", $r); + } + +if (!$sched->{'weekdaynums_all'}) { + local %weekdaynums_map = ( 1 => '1st', 2 => '2nd', 3 => '3rd', + 4 => '4th', 5 => '5th' ); + local $r = &make_range($sched->{'weekdaynums'}, \%weekdaynums_map); + defined($r) || &error($text{'chooser_eweekdaynumsrange'}); + push(@w, $r); + } + +if (!$sched->{'weekdays_all'}) { + local %weekdays_map = ( 0 => 'sun', 1 => 'mon', 2 => 'tue', + 3 => 'wed', 4 => 'thu', 5 => 'fri', 6 => 'sat' ); + local $r = &make_range($sched->{'weekdays'}, \%weekdays_map); + defined($r) || &error($text{'chooser_eweekdaysrange'}); + push(@w, $r); + } + +push(@w, "at"); +push(@w, $sched->{'hour'}.":".$sched->{'minute'}); + +return join(" ", @w); +} + +# make_range(&nums, &map) +sub make_range +{ +local ($nums, $map) = @_; +if (scalar(@$nums) == 1) { + return $map->{$nums->[0]}; + } +@$nums = sort { $a <=> $b } @$nums; +$prev = undef; +foreach my $n (@$nums) { + if (defined($prev) && $prev != $n-1) { + return undef; + } + $prev = $n; + } +return $map->{$nums->[0]}."-".$map->{$nums->[@$nums-1]}; +} + +# date_to_unix(string) +# Converts a MySQL date string to a Unix time_t +sub date_to_unix +{ +local ($str) = @_; +if ($str =~ /^(\d{4})\-(\d\d)\-(\d\d)\s+(\d\d):(\d\d):(\d\d)$/) { + # MySQL time + return timelocal($6, $5, $4, $3, $2-1, $1-1900); + } +return undef; +} + +1; + diff --git a/bacula-backup/bootup.cgi b/bacula-backup/bootup.cgi new file mode 100755 index 000000000..d0cc6b399 --- /dev/null +++ b/bacula-backup/bootup.cgi @@ -0,0 +1,21 @@ +#!/usr/local/bin/perl +# Start or stop Bacula at boot + +require './bacula-backup-lib.pl'; +&ReadParse(); +&foreign_require("init", "init-lib.pl"); + +if ($in{'boot'}) { + foreach $p (@bacula_inits) { + &init::enable_at_boot($p); + } + &webmin_log("bootup"); + } +else { + foreach $p (@bacula_inits) { + &init::disable_at_boot($p); + } + &webmin_log("bootdown"); + } +&redirect(""); + diff --git a/bacula-backup/cancel_jobs.cgi b/bacula-backup/cancel_jobs.cgi new file mode 100755 index 000000000..752bf6c99 --- /dev/null +++ b/bacula-backup/cancel_jobs.cgi @@ -0,0 +1,32 @@ +#!/usr/local/bin/perl +# Cancel running jobs + +require './bacula-backup-lib.pl'; +&ReadParse(); + +if (!$in{'refresh'}) { + # Cancel jobs if not refreshing + &error_setup($text{'cancel_err'}); + @d = split(/\0/, $in{'d'}); + @d || &error($text{'cancel_enone'}); + + $h = &open_console(); + foreach $d (@d) { + $out = &console_cmd($h, "cancel JobId=$d"); + if ($out =~ /failed|error/i) { + &error(&text('dvolumes_ebacula', "$out")); + } + } + &close_console($h); + } + +if ($in{'client'}) { + &redirect("clientstatus_form.cgi?client=$in{'client'}"); + } +elsif ($in{'storage'}) { + &redirect("storagestatus_form.cgi?storage=$in{'storage'}"); + } +else { + &redirect("dirstatus_form.cgi"); + } + diff --git a/bacula-backup/clientstatus_form.cgi b/bacula-backup/clientstatus_form.cgi new file mode 100755 index 000000000..88b5f9561 --- /dev/null +++ b/bacula-backup/clientstatus_form.cgi @@ -0,0 +1,93 @@ +#!/usr/local/bin/perl +# Show a form for displaying the status of one client + +require './bacula-backup-lib.pl'; +&ui_print_header(undef, $text{'clientstatus_title'}, "", "clientstatus"); +&ReadParse(); + +# Client selector +@clients = sort { lc($a->{'name'}) cmp lc($b->{'name'}) } + grep { !&is_oc_object($_, 1) } &get_bacula_clients(); +if (@clients == 1) { + $in{'client'} ||= $clients[0]->{'name'}; + } +print &ui_form_start("clientstatus_form.cgi"); +print "$text{'clientstatus_show'}\n"; +print &ui_select("client", $in{'client'}, + [ map { [ $_->{'name'}, + &text('clientstatus_on', $_->{'name'}, $_->{'address'}) ] } + @clients ]); +print &ui_submit($text{'clientstatus_ok'}),"
\n"; +print &ui_form_end(); + +if ($in{'client'}) { + # Show this client + ($msg, $ok, $run, $done) = &get_client_status($in{'client'}); + + if ($ok) { + print &text('clientstatus_msg', $in{'client'}, $msg),"

\n"; + + # Running jobs + print &ui_subheading($text{'dirstatus_run'}); + if (@$run) { + print &ui_form_start("cancel_jobs.cgi", "post"); + print &ui_hidden("client", $in{'client'}),"\n"; + @links = ( &select_all_link("d", 1), + &select_invert_link("d", 1) ); + print &ui_links_row(\@links); + @tds = ( "width=5" ); + print &ui_columns_start([ "", $text{'dirstatus_name'}, + $text{'dirstatus_id'}, + $text{'dirstatus_date2'} ], + "100%", 0, \@tds); + foreach $j (@$run) { + print &ui_checked_columns_row([ + &joblink($j->{'name'}), + $j->{'id'}, + $j->{'date'} ], \@tds, "d", $j->{'id'}); + } + print &ui_columns_end(); + print &ui_links_row(\@links); + print &ui_form_end([ [ "cancel", $text{'dirstatus_cancel'} ] ]); + } + else { + print "$text{'dirstatus_runnone'}

\n"; + } + + # Completed jobs + print &ui_subheading($text{'dirstatus_done'}); + if (@$done) { + print &ui_columns_start([ $text{'dirstatus_name'}, + $text{'dirstatus_id'}, + $text{'dirstatus_level'}, + $text{'dirstatus_date'}, + $text{'dirstatus_bytes'}, + $text{'dirstatus_files'}, + $text{'dirstatus_status2'} ], + "100%"); + foreach $j (@$done) { + print &ui_columns_row([ + &joblink($j->{'name'}), + $j->{'id'}, + $j->{'level'}, + $j->{'date'}, + &nice_size($j->{'bytes'}), + $j->{'files'}, + $j->{'status'} ]); + } + print &ui_columns_end(); + } + else { + print "$text{'dirstatus_donenone'}

\n"; + } + } + else { + # Couldn't connect! + print "",&text('clientstatus_err', $in{'client'}, $msg), + "

\n"; + } + } + +&ui_print_footer("", $text{'index_return'}); + + diff --git a/bacula-backup/config b/bacula-backup/config new file mode 100644 index 000000000..5ee523e36 --- /dev/null +++ b/bacula-backup/config @@ -0,0 +1,11 @@ +driver=Pg +user=bacula +pass= +db=bacula +bacula_dir=/etc/bacula +bextract=bextract +bls=bls +btape=btape +wait=1 +apply=1 +showdirs=0 diff --git a/bacula-backup/config-windows b/bacula-backup/config-windows new file mode 100644 index 000000000..ead350686 --- /dev/null +++ b/bacula-backup/config-windows @@ -0,0 +1,11 @@ +driver=Pg +user=bacula +pass=opencountry +db=bacula +bacula_dir=c:/bacula/bin +bextract=bextract +bls=bls +btape=btape +wait=1 +apply=1 +showdirs=0 diff --git a/bacula-backup/config.info b/bacula-backup/config.info new file mode 100644 index 000000000..6d5cc1c31 --- /dev/null +++ b/bacula-backup/config.info @@ -0,0 +1,15 @@ +line0=Configurable options,11 +wait=Default backup wait mode,1,1-Wait for completion,0-Run in background +apply=Automatically apply director configuration?,1,1-Yes,0-No +groupmode=Get node group information from,1,webmin-Webmin Servers Index module,oc-OCM Manager database,-Nowhere +showdirs=Always show remote directors?,1,1-Yes,0-No +line1=Bacula database settings,11 +driver=Database type,1,Pg-PostgreSQL,mysql-MySQL,SQLite-SQLite +user=User to login to database as,0 +pass=Password to login with,0 +db=Database or file containing Bacula information,0 +line2=File settings,11 +bacula_dir=Bacula configuration directory,0 +bextract=Full path to bextract command,0 +bls=Full path to bls command,0 +btape=Full path to btape command,0 diff --git a/bacula-backup/delete_clients.cgi b/bacula-backup/delete_clients.cgi new file mode 100755 index 000000000..e93ab1935 --- /dev/null +++ b/bacula-backup/delete_clients.cgi @@ -0,0 +1,27 @@ +#!/usr/local/bin/perl +# Delete multiple clients + +require './bacula-backup-lib.pl'; +&ReadParse(); +$conf = &get_director_config(); +$parent = &get_director_config_parent(); +@clients = &find("Client", $conf); + +&error_setup($text{'clients_derr'}); +@d = split(/\0/, $in{'d'}); +@d || &error($text{'filesets_ednone'}); + +&lock_file($parent->{'file'}); +foreach $d (@d) { + $client = &find_by("Name", $d, \@clients); + if ($client) { + $child = &find_dependency("Client", $d, [ "Job", "JobDefs" ], $conf); + $child && &error(&text('client_echild', $child)); + &save_directive($conf, $parent, $client, undef, 0); + } + } +&flush_file_lines($parent->{'file'}); +&unlock_file($parent->{'file'}); +&webmin_log("delete", "clients", scalar(@d)); +&redirect("list_clients.cgi"); + diff --git a/bacula-backup/delete_fdirectors.cgi b/bacula-backup/delete_fdirectors.cgi new file mode 100755 index 000000000..6e15ad819 --- /dev/null +++ b/bacula-backup/delete_fdirectors.cgi @@ -0,0 +1,25 @@ +#!/usr/local/bin/perl +# Delete multiple fdirector devices + +require './bacula-backup-lib.pl'; +&ReadParse(); +$conf = &get_file_config(); +$parent = &get_file_config_parent(); +@fdirectors = &find("Director", $conf); + +&error_setup($text{'fdirectors_derr'}); +@d = split(/\0/, $in{'d'}); +@d || &error($text{'filesets_ednone'}); + +&lock_file($parent->{'file'}); +foreach $d (@d) { + $fdirector = &find_by("Name", $d, \@fdirectors); + if ($fdirector) { + &save_directive($conf, $parent, $fdirector, undef, 0); + } + } +&flush_file_lines($parent->{'file'}); +&unlock_file($parent->{'file'}); +&webmin_log("delete", "fdirectors", scalar(@d)); +&redirect("list_fdirectors.cgi"); + diff --git a/bacula-backup/delete_filesets.cgi b/bacula-backup/delete_filesets.cgi new file mode 100755 index 000000000..3ff3feeb8 --- /dev/null +++ b/bacula-backup/delete_filesets.cgi @@ -0,0 +1,27 @@ +#!/usr/local/bin/perl +# Delete multiple filesets + +require './bacula-backup-lib.pl'; +&ReadParse(); +$conf = &get_director_config(); +$parent = &get_director_config_parent(); +@filesets = &find("FileSet", $conf); + +&error_setup($text{'filesets_derr'}); +@d = split(/\0/, $in{'d'}); +@d || &error($text{'filesets_ednone'}); + +&lock_file($parent->{'file'}); +foreach $d (@d) { + $fileset = &find_by("Name", $d, \@filesets); + if ($fileset) { + $child = &find_dependency("Client", $d, [ "Job", "JobDefs" ], $conf); + $child && &error(&text('fileset_echild', $child)); + &save_directive($conf, $parent, $fileset, undef, 0); + } + } +&flush_file_lines($parent->{'file'}); +&unlock_file($parent->{'file'}); +&webmin_log("delete", "filesets", scalar(@d)); +&redirect("list_filesets.cgi"); + diff --git a/bacula-backup/delete_gjobs.cgi b/bacula-backup/delete_gjobs.cgi new file mode 100755 index 000000000..89d67433a --- /dev/null +++ b/bacula-backup/delete_gjobs.cgi @@ -0,0 +1,33 @@ +#!/usr/local/bin/perl +# Delete group backup jobs + +require './bacula-backup-lib.pl'; +&ReadParse(); +$conf = &get_director_config(); +$parent = &get_director_config_parent(); +@jobs = &find("JobDefs", $conf); + +@nodegroups = &list_node_groups(); + +&error_setup($text{'gjobs_derr'}); +@d = split(/\0/, $in{'d'}); +@d || &error($text{'filesets_ednone'}); + +&lock_file($parent->{'file'}); +foreach $d (@d) { + $job = &find_by("Name", "ocjob_".$d, \@jobs); + if ($job) { + $client = &find_value("Client", $job->{'members'}); + &save_directive($conf, $parent, $job, undef, 0); + + ($nodegroup) = grep { $_->{'name'} eq $client } @nodegroups; + if ($nodegroup) { + &sync_group_clients($nodegroup); + } + } + } +&flush_file_lines($parent->{'file'}); +&unlock_file($parent->{'file'}); +&webmin_log("delete", "gjobs", scalar(@d)); +&redirect("list_gjobs.cgi"); + diff --git a/bacula-backup/delete_groups.cgi b/bacula-backup/delete_groups.cgi new file mode 100755 index 000000000..1f30b16be --- /dev/null +++ b/bacula-backup/delete_groups.cgi @@ -0,0 +1,34 @@ +#!/usr/local/bin/perl +# Delete multiple node groups + +require './bacula-backup-lib.pl'; +&ReadParse(); +$conf = &get_director_config(); +$parent = &get_director_config_parent(); +@clients = &find("Client", $conf); + +@nodegroups = &list_node_groups(); + +&error_setup($text{'groups_derr'}); +@d = split(/\0/, $in{'d'}); +@d || &error($text{'filesets_ednone'}); + +&lock_file($parent->{'file'}); +foreach $d (@d) { + $client = &find_by("Name", "ocgroup_".$d, \@clients); + if ($client) { + $child = &find_dependency("Client", $d, [ "Job", "JobDefs" ], $conf); + $child && &error(&text('client_echild', $child)); + &save_directive($conf, $parent, $client, undef, 0); + + ($nodegroup) = grep { $_->{'name'} eq $d } @nodegroups; + if ($nodegroup) { + &sync_group_clients($nodegroup); + } + } + } +&flush_file_lines($parent->{'file'}); +&unlock_file($parent->{'file'}); +&webmin_log("delete", "groups", scalar(@d)); +&redirect("list_groups.cgi"); + diff --git a/bacula-backup/delete_jobs.cgi b/bacula-backup/delete_jobs.cgi new file mode 100755 index 000000000..dfd184551 --- /dev/null +++ b/bacula-backup/delete_jobs.cgi @@ -0,0 +1,27 @@ +#!/usr/local/bin/perl +# Delete multiple jobs + +require './bacula-backup-lib.pl'; +&ReadParse(); +$conf = &get_director_config(); +$parent = &get_director_config_parent(); +@jobs = ( &find("JobDefs", $conf), &find("Job", $conf) ); + +&error_setup($text{'jobs_derr'}); +@d = split(/\0/, $in{'d'}); +@d || &error($text{'filesets_ednone'}); + +&lock_file($parent->{'file'}); +foreach $d (@d) { + $job = &find_by("Name", $d, \@jobs); + if ($job) { + $child = &find_dependency("JobDefs", $d, [ "Job" ], $conf); + $child && &error(&text('job_echild', $child)); + &save_directive($conf, $parent, $job, undef, 0); + } + } +&flush_file_lines($parent->{'file'}); +&unlock_file($parent->{'file'}); +&webmin_log("delete", "jobs", scalar(@d)); +&redirect("list_jobs.cgi"); + diff --git a/bacula-backup/delete_pools.cgi b/bacula-backup/delete_pools.cgi new file mode 100755 index 000000000..c2dd47382 --- /dev/null +++ b/bacula-backup/delete_pools.cgi @@ -0,0 +1,27 @@ +#!/usr/local/bin/perl +# Delete multiple pool devices + +require './bacula-backup-lib.pl'; +&ReadParse(); +$conf = &get_director_config(); +$parent = &get_director_config_parent(); +@pools = &find("Pool", $conf); + +&error_setup($text{'pools_derr'}); +@d = split(/\0/, $in{'d'}); +@d || &error($text{'filesets_ednone'}); + +&lock_file($parent->{'file'}); +foreach $d (@d) { + $pool = &find_by("Name", $d, \@pools); + if ($pool) { + $child = &find_dependency("Pool", $d, [ "Job", "JobDefs" ], $conf); + $child && &error(&text('pool_echild', $child)); + &save_directive($conf, $parent, $pool, undef, 0); + } + } +&flush_file_lines($parent->{'file'}); +&unlock_file($parent->{'file'}); +&webmin_log("delete", "pools", scalar(@d)); +&redirect("list_pools.cgi"); + diff --git a/bacula-backup/delete_schedules.cgi b/bacula-backup/delete_schedules.cgi new file mode 100755 index 000000000..6fc384e56 --- /dev/null +++ b/bacula-backup/delete_schedules.cgi @@ -0,0 +1,27 @@ +#!/usr/local/bin/perl +# Delete multiple schedules + +require './bacula-backup-lib.pl'; +&ReadParse(); +$conf = &get_director_config(); +$parent = &get_director_config_parent(); +@schedules = &find("Schedule", $conf); + +&error_setup($text{'schedules_derr'}); +@d = split(/\0/, $in{'d'}); +@d || &error($text{'filesets_ednone'}); + +&lock_file($parent->{'file'}); +foreach $d (@d) { + $schedule = &find_by("Name", $d, \@schedules); + if ($schedule) { + $child = &find_dependency("Schedule", $d, [ "Job", "JobDefs" ], $conf); + $child && &error(&text('schedule_echild', $child)); + &save_directive($conf, $parent, $schedule, undef, 0); + } + } +&flush_file_lines($parent->{'file'}); +&unlock_file($parent->{'file'}); +&webmin_log("delete", "schedules", scalar(@d)); +&redirect("list_schedules.cgi"); + diff --git a/bacula-backup/delete_sdirectors.cgi b/bacula-backup/delete_sdirectors.cgi new file mode 100755 index 000000000..8c6dd6b3d --- /dev/null +++ b/bacula-backup/delete_sdirectors.cgi @@ -0,0 +1,25 @@ +#!/usr/local/bin/perl +# Delete multiple storage daemon directors + +require './bacula-backup-lib.pl'; +&ReadParse(); +$conf = &get_storage_config(); +$parent = &get_storage_config_parent(); +@sdirectors = &find("Director", $conf); + +&error_setup($text{'sdirectors_derr'}); +@d = split(/\0/, $in{'d'}); +@d || &error($text{'filesets_ednone'}); + +&lock_file($parent->{'file'}); +foreach $d (@d) { + $sdirector = &find_by("Name", $d, \@sdirectors); + if ($sdirector) { + &save_directive($conf, $parent, $sdirector, undef, 0); + } + } +&flush_file_lines($parent->{'file'}); +&unlock_file($parent->{'file'}); +&webmin_log("delete", "sdirectors", scalar(@d)); +&redirect("list_sdirectors.cgi"); + diff --git a/bacula-backup/delete_storages.cgi b/bacula-backup/delete_storages.cgi new file mode 100755 index 000000000..446881956 --- /dev/null +++ b/bacula-backup/delete_storages.cgi @@ -0,0 +1,27 @@ +#!/usr/local/bin/perl +# Delete multiple storage devices + +require './bacula-backup-lib.pl'; +&ReadParse(); +$conf = &get_director_config(); +$parent = &get_director_config_parent(); +@storages = &find("Storage", $conf); + +&error_setup($text{'storages_derr'}); +@d = split(/\0/, $in{'d'}); +@d || &error($text{'filesets_ednone'}); + +&lock_file($parent->{'file'}); +foreach $d (@d) { + $storage = &find_by("Name", $d, \@storages); + if ($storage) { + $child = &find_dependency("Storage", $d, [ "Job", "JobDefs" ], $conf); + $child && &error(&text('storage_echild', $child)); + &save_directive($conf, $parent, $storage, undef, 0); + } + } +&flush_file_lines($parent->{'file'}); +&unlock_file($parent->{'file'}); +&webmin_log("delete", "storages", scalar(@d)); +&redirect("list_storages.cgi"); + diff --git a/bacula-backup/delete_volumes.cgi b/bacula-backup/delete_volumes.cgi new file mode 100755 index 000000000..79f2318d7 --- /dev/null +++ b/bacula-backup/delete_volumes.cgi @@ -0,0 +1,24 @@ +#!/usr/local/bin/perl +# Delete a bunch of volumes from a pool + +require './bacula-backup-lib.pl'; +&ReadParse(); +&error_setup($text{'dvolumes_err'}); +@d = split(/\0/, $in{'d'}); +@d || &error($text{'dvolumes_enone'}); + +$h = &open_console(); +foreach $d (@d) { + &sysprint($h->{'infh'}, "delete media volume=$d\n"); + $rv = &wait_for($h->{'outfh'}, "Are you sure.*:"); + if ($rv == 0) { + &sysprint($h->{'infh'}, "yes\n"); + } + else { + &error(&text('dvolumes_ebacula', "$wait_for_input")); + } + } +&close_console($h); + +&redirect("poolstatus_form.cgi?pool=$in{'pool'}"); + diff --git a/bacula-backup/dirstatus_form.cgi b/bacula-backup/dirstatus_form.cgi new file mode 100755 index 000000000..87afb8863 --- /dev/null +++ b/bacula-backup/dirstatus_form.cgi @@ -0,0 +1,92 @@ +#!/usr/local/bin/perl +# Show the status of the director, including recent jobs + +require './bacula-backup-lib.pl'; +&ui_print_header(undef, $text{'dirstatus_title'}, "", "dirstatus"); + +($sched, $run, $done) = &get_director_status(); + +# Running jobs +print &ui_subheading($text{'dirstatus_run'}); +if (@$run) { + print &ui_form_start("cancel_jobs.cgi", "post"); + @links = ( &select_all_link("d"), + &select_invert_link("d") ); + print &ui_links_row(\@links); + @tds = ( "width=5" ); + print &ui_columns_start([ "", + $text{'dirstatus_name'}, + $text{'dirstatus_id'}, + $text{'dirstatus_level'}, + $text{'dirstatus_status'} ], "100%", + 0, \@tds); + foreach $j (@$run) { + print &ui_checked_columns_row([ + &joblink($j->{'name'}), + $j->{'id'}, + $j->{'level'}, + $j->{'status'} ], \@tds, "d", $j->{'id'}); + } + print &ui_columns_end(); + print &ui_links_row(\@links); + print &ui_form_end([ [ "cancel", $text{'dirstatus_cancel'} ], + [ "refresh", $text{'dirstatus_refresh'} ] ]); + } +else { + print "$text{'dirstatus_runnone'}

\n"; + print &ui_form_start("cancel_jobs.cgi"); + print &ui_form_end([ [ "refresh", $text{'dirstatus_refresh'} ] ]); + } + +# Completed jobs +print &ui_subheading($text{'dirstatus_done'}); +if (@$done) { + print &ui_columns_start([ $text{'dirstatus_name'}, + $text{'dirstatus_id'}, + $text{'dirstatus_level'}, + $text{'dirstatus_date'}, + $text{'dirstatus_bytes'}, + $text{'dirstatus_files'}, + $text{'dirstatus_status2'} ], "100%"); + foreach $j (@$done) { + print &ui_columns_row([ + &joblink($j->{'name'}), + $j->{'id'}, + $j->{'level'}, + $j->{'date'}, + &nice_size($j->{'bytes'}), + $j->{'files'}, + $j->{'status'} ]); + } + print &ui_columns_end(); + } +else { + print "$text{'dirstatus_donenone'}

\n"; + } + + + +# Scheduled jobs +print &ui_subheading($text{'dirstatus_sched'}); +if (@$sched) { + print &ui_columns_start([ $text{'dirstatus_name'}, + $text{'dirstatus_level'}, + $text{'dirstatus_type'}, + $text{'dirstatus_date'}, + $text{'dirstatus_volume'} ], "100%"); + foreach $j (@$sched) { + print &ui_columns_row([ + &joblink($j->{'name'}), + $j->{'level'}, + $j->{'type'}, + $j->{'date'}, + $j->{'volume'} ]); + } + print &ui_columns_end(); + } +else { + print "$text{'dirstatus_schednone'}

\n"; + } + +&ui_print_footer("", $text{'index_return'}); + diff --git a/bacula-backup/edit_client.cgi b/bacula-backup/edit_client.cgi new file mode 100755 index 000000000..075a99152 --- /dev/null +++ b/bacula-backup/edit_client.cgi @@ -0,0 +1,84 @@ +#!/usr/local/bin/perl +# Show the details of one client + +require './bacula-backup-lib.pl'; +&ReadParse(); +$conf = &get_director_config(); +@clients = &find("Client", $conf); +@catalogs = map { $n=&find_value("Name", $_->{'members'}) } + &find("Catalog", $conf); +if ($in{'new'}) { + &ui_print_header(undef, $text{'client_title1'}, ""); + $mems = [ { 'name' => 'FDPort', + 'value' => 9102 }, + { 'name' => 'Catalog', + 'value' => $catalogs[0] }, + { 'name' => 'File Retention', + 'value' => '30 days' }, + { 'name' => 'Job Retention', + 'value' => '6 months' }, + ]; + $client = { 'members' => $mems }; + } +else { + &ui_print_header(undef, $text{'client_title2'}, ""); + $client = &find_by("Name", $in{'name'}, \@clients); + $client || &error($text{'client_egone'}); + $mems = $client->{'members'}; + } + +# Show details +print &ui_form_start("save_client.cgi", "post"); +print &ui_hidden("new", $in{'new'}),"\n"; +print &ui_hidden("old", $in{'name'}),"\n"; +print &ui_table_start($text{'client_header'}, "width=100%", 4); + +# Client name +print &ui_table_row($text{'client_name'}, + &ui_textbox("name", $name=&find_value("Name", $mems), 40), 3); + +# Password for remote +print &ui_table_row($text{'client_pass'}, + &ui_textbox("pass", $pass=&find_value("Password", $mems), 60), 3); + +# Connection details +print &ui_table_row($text{'client_address'}, + &ui_textbox("address", $address=&find_value("Address", $mems), 20)); +print &ui_table_row($text{'client_port'}, + &ui_textbox("port", $port=&find_value("FDPort", $mems), 6)); + +# Catalog +print &ui_table_row($text{'client_catalog'}, + &ui_select("catalog", $catalog=&find_value("Catalog", $mems), + [ map { [ $_ ] } @catalogs ], 1, 0, 1)); + +# Prune option +$prune = &find_value("AutoPrune", $mems); +print &ui_table_row($text{'client_prune'}, + &ui_radio("prune", $prune, + [ [ "yes", $text{'yes'} ], [ "no", $text{'no'} ], + [ "", $text{'default'} ] ])); + +# Retention options +$fileret = &find_value("File Retention", $mems); +print &ui_table_row($text{'client_fileret'}, + &show_period_input("fileret", $fileret)); +$jobret = &find_value("Job Retention", $mems); +print &ui_table_row($text{'client_jobret'}, + &show_period_input("jobret", $jobret)); + +# SSL options +&show_tls_directives($client); + +# All done +print &ui_table_end(); +if ($in{'new'}) { + print &ui_form_end([ [ "create", $text{'create'} ] ]); + } +else { + print &ui_form_end([ [ "save", $text{'save'} ], + [ "status", $text{'client_status'} ], + [ "delete", $text{'delete'} ] ]); + } +&ui_print_footer("list_clients.cgi", $text{'clients_return'}); + diff --git a/bacula-backup/edit_device.cgi b/bacula-backup/edit_device.cgi new file mode 100755 index 000000000..32013e013 --- /dev/null +++ b/bacula-backup/edit_device.cgi @@ -0,0 +1,74 @@ +#!/usr/local/bin/perl +# Show the details of one device device + +require './bacula-backup-lib.pl'; +&ReadParse(); +$conf = &get_storage_config(); +@devices = &find("Device", $conf); + +if ($in{'new'}) { + &ui_print_header(undef, $text{'device_title1'}, ""); + $mems = [ { 'name' => 'Media Type', + 'value' => 'File' }, + { 'name' => 'LabelMedia', + 'value' => 'yes' }, + { 'name' => 'Random Access', + 'value' => 'yes' }, + { 'name' => 'AutomaticMount', + 'value' => 'yes' }, + { 'name' => 'RemovableMedia', + 'value' => 'no' }, + { 'name' => 'AlwaysOpen', + 'value' => 'no' }, + ]; + $device = { 'members' => $mems }; + } +else { + &ui_print_header(undef, $text{'device_title2'}, ""); + $device = &find_by("Name", $in{'name'}, \@devices); + $device || &error($text{'device_egone'}); + $mems = $device->{'members'}; + } + +# Show details +print &ui_form_start("save_device.cgi", "post"); +print &ui_hidden("new", $in{'new'}),"\n"; +print &ui_hidden("old", $in{'name'}),"\n"; +print &ui_table_start($text{'device_header'}, "width=100%", 4); + +# Device name +print &ui_table_row($text{'device_name'}, + &ui_textbox("name", $name=&find_value("Name", $mems), 40), 3); + +# Archive device or file +print &ui_table_row($text{'device_device'}, + &ui_textbox("device", $device=&find_value("Archive Device", $mems), 40)." ". + &file_chooser_button("device", 0), 3); + +# Media type +print &ui_table_row($text{'device_media'}, + &ui_textbox("media", $media=&find_value("Media Type", $mems), 20)); + +# Various yes/no options +print &ui_table_row($text{'device_label'}, + &bacula_yesno("label", "LabelMedia", $mems)); +print &ui_table_row($text{'device_random'}, + &bacula_yesno("random", "Random Access", $mems)); +print &ui_table_row($text{'device_auto'}, + &bacula_yesno("auto", "AutomaticMount", $mems)); +print &ui_table_row($text{'device_removable'}, + &bacula_yesno("removable", "RemovableMedia", $mems)); +print &ui_table_row($text{'device_always'}, + &bacula_yesno("always", "AlwaysOpen", $mems)); + +# All done +print &ui_table_end(); +if ($in{'new'}) { + print &ui_form_end([ [ "create", $text{'create'} ] ]); + } +else { + print &ui_form_end([ [ "save", $text{'save'} ], + [ "delete", $text{'delete'} ] ]); + } +&ui_print_footer("list_devices.cgi", $text{'devices_return'}); + diff --git a/bacula-backup/edit_director.cgi b/bacula-backup/edit_director.cgi new file mode 100755 index 000000000..c9b75077a --- /dev/null +++ b/bacula-backup/edit_director.cgi @@ -0,0 +1,49 @@ +#!/usr/local/bin/perl +# Show the global director configuration + +require './bacula-backup-lib.pl'; +&ReadParse(); +$conf = &get_director_config(); +$director = &find("Director", $conf); +$director || &error($text{'director_enone'}); +$mems = $director->{'members'}; + +@messages = map { $n=&find_value("Name", $_->{'members'}) } + &find("Messages", $conf); + +&ui_print_header(undef, $text{'director_title'}, "", "director"); + +print &ui_form_start("save_director.cgi", "post"); +print &ui_table_start($text{'director_header'}, "width=100%", 4); + +$name = &find_value("Name", $mems); +print &ui_table_row($text{'director_name'}, + &ui_textbox("name", $name, 20)); + +$port = &find_value("DIRport", $mems); +print &ui_table_row($text{'director_port'}, + &ui_textbox("port", $port, 6)); + +$jobs = &find_value("Maximum Concurrent Jobs", $mems); +print &ui_table_row($text{'director_jobs'}, + &ui_opt_textbox("jobs", $jobs, 6, $text{'default'})); + +$messages = &find_value("Messages", $mems); +print &ui_table_row($text{'director_messages'}, + &ui_select("messages", $messages, + [ [ "", "<$text{'default'}>" ], + map { [ $_ ] } @messages ], 1, 0, 1)); + +$dir = &find_value("WorkingDirectory", $mems); +print &ui_table_row($text{'director_dir'}, + &ui_textbox("dir", $dir, 60)." ". + &file_chooser_button("dir", 1), 3); + +# SSL options +&show_tls_directives($director); + +print &ui_table_end(); +print &ui_form_end([ [ "save", $text{'save'} ] ]); + +&ui_print_footer("", $text{'index_return'}); + diff --git a/bacula-backup/edit_fdirector.cgi b/bacula-backup/edit_fdirector.cgi new file mode 100755 index 000000000..11a71071b --- /dev/null +++ b/bacula-backup/edit_fdirector.cgi @@ -0,0 +1,51 @@ +#!/usr/local/bin/perl +# Show the details of one file fdirector daemon + +require './bacula-backup-lib.pl'; +&ReadParse(); +$conf = &get_file_config(); +@fdirectors = &find("Director", $conf); + +if ($in{'new'}) { + &ui_print_header(undef, $text{'fdirector_title1'}, ""); + $mems = [ ]; + $fdirector = { 'members' => $mems }; + } +else { + &ui_print_header(undef, $text{'fdirector_title2'}, ""); + $fdirector = &find_by("Name", $in{'name'}, \@fdirectors); + $fdirector || &error($text{'fdirector_egone'}); + $mems = $fdirector->{'members'}; + } + +# Show details +print &ui_form_start("save_fdirector.cgi", "post"); +print &ui_hidden("new", $in{'new'}),"\n"; +print &ui_hidden("old", $in{'name'}),"\n"; +print &ui_table_start($text{'fdirector_header'}, "width=100%", 4); + +# Director name +print &ui_table_row($text{'fdirector_name'}, + &ui_textbox("name", $name=&find_value("Name", $mems), 40), 3); + +# Password for remote +print &ui_table_row($text{'fdirector_pass'}, + &ui_textbox("pass", $pass=&find_value("Password", $mems), 60), 3); + +# Monitor mode +print &ui_table_row($text{'fdirector_monitor'}, + &bacula_yesno("monitor", "Monitor", $mems)); + +&show_tls_directives($fdirector); + +# All done +print &ui_table_end(); +if ($in{'new'}) { + print &ui_form_end([ [ "create", $text{'create'} ] ]); + } +else { + print &ui_form_end([ [ "save", $text{'save'} ], + [ "delete", $text{'delete'} ] ]); + } +&ui_print_footer("list_fdirectors.cgi", $text{'fdirectors_return'}); + diff --git a/bacula-backup/edit_file.cgi b/bacula-backup/edit_file.cgi new file mode 100755 index 000000000..560a793df --- /dev/null +++ b/bacula-backup/edit_file.cgi @@ -0,0 +1,40 @@ +#!/usr/local/bin/perl +# Show the global file daemon configuration + +require './bacula-backup-lib.pl'; +&ReadParse(); +$conf = &get_file_config(); +$file = &find("FileDaemon", $conf); +$file || &error($text{'file_enone'}); +$mems = $file->{'members'}; + +&ui_print_header(undef, $text{'file_title'}, "", "file"); + +print &ui_form_start("save_file.cgi", "post"); +print &ui_table_start($text{'file_header'}, "width=100%", 4); + +$name = &find_value("Name", $mems); +print &ui_table_row($text{'file_name'}, + &ui_textbox("name", $name, 20)); + +$port = &find_value("FDport", $mems); +print &ui_table_row($text{'file_port'}, + &ui_textbox("port", $port, 6)); + +$jobs = &find_value("Maximum Concurrent Jobs", $mems); +print &ui_table_row($text{'file_jobs'}, + &ui_opt_textbox("jobs", $jobs, 6, $text{'default'})); + +$dir = &find_value("WorkingDirectory", $mems); +print &ui_table_row($text{'file_dir'}, + &ui_textbox("dir", $dir, 60)." ". + &file_chooser_button("dir", 1), 3); + +# SSL options +&show_tls_directives($file); + +print &ui_table_end(); +print &ui_form_end([ [ "save", $text{'save'} ] ]); + +&ui_print_footer("", $text{'index_return'}); + diff --git a/bacula-backup/edit_fileset.cgi b/bacula-backup/edit_fileset.cgi new file mode 100755 index 000000000..7093b9df5 --- /dev/null +++ b/bacula-backup/edit_fileset.cgi @@ -0,0 +1,62 @@ +#!/usr/local/bin/perl +# Show the details of one fileset + +require './bacula-backup-lib.pl'; +&ReadParse(); +$conf = &get_director_config(); +@filesets = &find("FileSet", $conf); +if ($in{'new'}) { + &ui_print_header(undef, $text{'fileset_title1'}, ""); + $mems = [ ]; + $fileset = { }; + } +else { + &ui_print_header(undef, $text{'fileset_title2'}, ""); + $fileset = &find_by("Name", $in{'name'}, \@filesets); + $fileset || &error($text{'fileset_egone'}); + $mems = $fileset->{'members'}; + } + +# Show details +print &ui_form_start("save_fileset.cgi", "post"); +print &ui_hidden("new", $in{'new'}),"\n"; +print &ui_hidden("old", $in{'name'}),"\n"; +print &ui_table_start($text{'fileset_header'}, "width=100%", 4); + +# File set name +print &ui_table_row($text{'fileset_name'}, + &ui_textbox("name", $name=&find_value("Name", $mems), 40), 3); + +# Included files +$inc = &find("Include", $mems); +@files = $inc ? &find_value("File", $inc->{'members'}) : ( ); +print &ui_table_row($text{'fileset_include'}, + &ui_textarea("include", join("\n", @files), 5, 60)."\n". + &file_chooser_button("include", 0, 0, undef, 1), 3); + +# Options +$opts = $inc ? &find("Options", $inc->{'members'}) : undef; +$sig = $opts ? &find_value("signature", $opts->{'members'}) : undef; +print &ui_table_row($text{'fileset_sig'}, + &ui_select("signature", $sig, + [ [ "", $text{'fileset_none'} ], + [ "MD5" ], [ "SHA1" ] ], 1, 0, 1)); + +# Excluded files +$exc = &find("Exclude", $mems); +@files = $exc ? &find_value("File", $exc->{'members'}) : ( ); +print &ui_table_row($text{'fileset_exclude'}, + &ui_textarea("exclude", join("\n", @files), 5, 60)."\n". + &file_chooser_button("exclude", 0, 0, undef, 1), 3); + +# All done +print &ui_table_end(); +if ($in{'new'}) { + print &ui_form_end([ [ "create", $text{'create'} ] ]); + } +else { + print &ui_form_end([ [ "save", $text{'save'} ], + [ "delete", $text{'delete'} ] ]); + } +&ui_print_footer("list_filesets.cgi", $text{'filesets_return'}); + diff --git a/bacula-backup/edit_gjob.cgi b/bacula-backup/edit_gjob.cgi new file mode 100755 index 000000000..22519003b --- /dev/null +++ b/bacula-backup/edit_gjob.cgi @@ -0,0 +1,144 @@ +#!/usr/local/bin/perl +# Show the details of one backup job + +require './bacula-backup-lib.pl'; +&ReadParse(); +$conf = &get_director_config(); +@jobs = &find("JobDefs", $conf); +@clients = map { $n=&find_value("Name", $_->{'members'}); } + grep { ($g, $c) = &is_oc_object($_); $g && !$c } + &find("Client", $conf); +@filesets = map { $n=&find_value("Name", $_->{'members'}) } + &find("FileSet", $conf); +@schedules = map { $n=&find_value("Name", $_->{'members'}) } + &find("Schedule", $conf); +@storages = map { $n=&find_value("Name", $_->{'members'}) } + &find("Storage", $conf); +@pools = map { $n=&find_value("Name", $_->{'members'}) } + &find("Pool", $conf); +@messages = map { $n=&find_value("Name", $_->{'members'}) } + &find("Messages", $conf); +if ($in{'new'}) { + &ui_print_header(undef, $text{'gjob_title1'}, ""); + $mems = [ { 'name' => 'Type', + 'value' => 'Backup' }, + { 'name' => 'Level', + 'value' => 'Incremental' }, + { 'name' => 'Client', + 'value' => $clients[0] }, + { 'name' => 'FileSet', + 'value' => $filesets[0] }, + { 'name' => 'Schedule', + 'value' => $schedules[0] }, + { 'name' => 'Storage', + 'value' => $storages[0] }, + { 'name' => 'Messages', + 'value' => $messages[0] }, + { 'name' => 'Pool', + 'value' => $pools[0] }, + ]; + $job = { 'name' => 'Job', + 'members' => $mems }; + } +else { + &ui_print_header(undef, $text{'gjob_title2'}, ""); + $job = &find_by("Name", "ocjob_".$in{'name'}, \@jobs); + $job || &error($text{'job_egone'}); + $mems = $job->{'members'}; + } + +# Show details +print &ui_form_start("save_gjob.cgi", "post"); +print &ui_hidden("new", $in{'new'}),"\n"; +print &ui_hidden("old", $in{'name'}),"\n"; +print &ui_table_start($text{'gjob_header'}, "width=100%", 4); + +# Job name +print &ui_table_row($text{'job_name'}, + &ui_textbox("name", $in{'name'}, 40), 3); + +# Job type +$type = &find_value("Type", $mems); +print &ui_table_row($text{'job_type'}, + &ui_select("type", $type, + [ [ "Backup" ], [ "Restore" ], [ "Verify" ], [ "Admin" ] ], + 1, 0, 1)); + +# Backup level +$level = &find_value("Level", $mems); +print &ui_table_row($text{'job_level'}, + &ui_select("level", $level, + [ map { [ $_ ] } @backup_levels ], + 1, 0, 1)); + +# Client being backed up +$client = &find_value("Client", $mems); +print &ui_table_row($text{'gjob_client'}, + &ui_select("client", $client, + [ map { [ $_, &is_oc_object($_) ] } @clients ], 1, 0, 1)); + +# Files to be backed up +$fileset = &find_value("FileSet", $mems); +print &ui_table_row($text{'job_fileset'}, + &ui_select("fileset", $fileset, + [ map { [ $_ ] } @filesets ], 1, 0, 1)); + +# Backup schedule +$schedule = &find_value("Schedule", $mems); +print &ui_table_row($text{'job_schedule'}, + &ui_select("schedule", $schedule, + [ [ "", "<$text{'default'}>" ], + map { [ $_ ] } @schedules ], 1, 0, 1)); + +# Storage device +$storage = &find_value("Storage", $mems); +print &ui_table_row($text{'job_storage'}, + &ui_select("storage", $storage, + [ map { [ $_ ] } @storages ], 1, 0, 1)); + +# Backup pool +$pool = &find_value("Pool", $mems); +print &ui_table_row($text{'job_pool'}, + &ui_select("pool", $pool, + [ map { [ $_ ] } @pools ], 1, 0, 1)); + +# Backup messages +$messages = &find_value("Messages", $mems); +print &ui_table_row($text{'job_messages'}, + &ui_select("messages", $messages, + [ map { [ $_ ] } @messages ], 1, 0, 1)); + +# Priority level +$prority = &find_value("Priority", $mems); +print &ui_table_row($text{'job_prority'}, + &ui_opt_textbox("priority", $priority, 4, $text{'default'})); + +# Before and after commands +print &ui_table_hr(); + +$before = &find_value("Run Before Job", $mems); +print &ui_table_row($text{'job_before'}, + &ui_opt_textbox("before", $before, 60, $text{'default'}), 3); +$after = &find_value("Run After Job", $mems); +print &ui_table_row($text{'job_after'}, + &ui_opt_textbox("after", $after, 60, $text{'default'}), 3); + +$cbefore = &find_value("Client Run Before Job", $mems); +print &ui_table_row($text{'job_cbefore'}, + &ui_opt_textbox("cbefore", $cbefore, 60, $text{'default'}), 3); +$cafter = &find_value("Client Run After Job", $mems); +print &ui_table_row($text{'job_cafter'}, + &ui_opt_textbox("cafter", $cafter, 60, $text{'default'}), 3); + +# All done +print &ui_table_end(); +if ($in{'new'}) { + print &ui_form_end([ [ "create", $text{'create'} ] ]); + } +else { + print &ui_form_end([ [ "save", $text{'save'} ], + [ "run", $text{'job_run'} ], + [ "delete", $text{'delete'} ] ]); + } +&ui_print_footer("list_gjobs.cgi", $text{'jobs_return'}); + diff --git a/bacula-backup/edit_group.cgi b/bacula-backup/edit_group.cgi new file mode 100755 index 000000000..a4f00f49d --- /dev/null +++ b/bacula-backup/edit_group.cgi @@ -0,0 +1,87 @@ +#!/usr/local/bin/perl +# Show the details of one node group, which is actually a special client + +require './bacula-backup-lib.pl'; +&ReadParse(); +$conf = &get_director_config(); +@groups = &find("Client", $conf); +@catalogs = map { $n=&find_value("Name", $_->{'members'}) } + &find("Catalog", $conf); +if ($in{'new'}) { + &ui_print_header(undef, $text{'group_title1'}, ""); + $mems = [ { 'name' => 'FDPort', + 'value' => 9102 }, + { 'name' => 'Catalog', + 'value' => $catalogs[0] }, + { 'name' => 'File Retention', + 'value' => '30 days' }, + { 'name' => 'Job Retention', + 'value' => '6 months' }, + ]; + $group = { 'members' => $mems }; + } +else { + &ui_print_header(undef, $text{'group_title2'}, ""); + $group = &find_by("Name", "ocgroup_".$in{'name'}, \@groups); + $group || &error($text{'group_egone'}); + $mems = $group->{'members'}; + } + +# Get node group +@nodegroups = &list_node_groups(); +$ngname = $in{'name'} || $in{'new'}; +($nodegroup) = grep { $_->{'name'} eq $ngname } @nodegroups; + +# Show details +print &ui_form_start("save_group.cgi", "post"); +print &ui_hidden("new", $in{'new'}),"\n"; +print &ui_hidden("old", $in{'name'}),"\n"; +print &ui_table_start($text{'group_header'}, "width=100%", 4); + +# Group name +print &ui_table_row($text{'group_name'}, + $in{'new'} || $in{'name'}); + +# Password for remote +print &ui_table_row($text{'client_pass'}, + &ui_textbox("pass", $pass=&find_value("Password", $mems), 60), 3); + +# FD port +print &ui_table_row($text{'client_port'}, + &ui_textbox("port", $port=&find_value("FDPort", $mems), 6), 3); + +# Catalog +print &ui_table_row($text{'client_catalog'}, + &ui_select("catalog", $catalog=&find_value("Catalog", $mems), + [ map { [ $_ ] } @catalogs ], 1, 0, 1)); + +# Prune option +$prune = &find_value("AutoPrune", $mems); +print &ui_table_row($text{'client_prune'}, + &ui_radio("prune", $prune, + [ [ "yes", $text{'yes'} ], [ "no", $text{'no'} ], + [ "", $text{'default'} ] ])); + +# Retention options +$fileret = &find_value("File Retention", $mems); +print &ui_table_row($text{'client_fileret'}, + &show_period_input("fileret", $fileret)); +$jobret = &find_value("Job Retention", $mems); +print &ui_table_row($text{'client_jobret'}, + &show_period_input("jobret", $jobret)); + +# Members +print &ui_table_row($text{'group_members'}, + join(", ", @{$nodegroup->{'members'}}), 3); + +# All done +print &ui_table_end(); +if ($in{'new'}) { + print &ui_form_end([ [ "create", $text{'create'} ] ]); + } +else { + print &ui_form_end([ [ "save", $text{'save'} ], + [ "delete", $text{'delete'} ] ]); + } +&ui_print_footer("list_groups.cgi", $text{'groups_return'}); + diff --git a/bacula-backup/edit_job.cgi b/bacula-backup/edit_job.cgi new file mode 100755 index 000000000..2d56b61dc --- /dev/null +++ b/bacula-backup/edit_job.cgi @@ -0,0 +1,164 @@ +#!/usr/local/bin/perl +# Show the details of one backup job + +require './bacula-backup-lib.pl'; +&ReadParse(); +$conf = &get_director_config(); +@jobs = ( &find("JobDefs", $conf), &find("Job", $conf) ); +@clients = map { $n=&find_value("Name", $_->{'members'}) } + grep { !&is_oc_object($_) } &find("Client", $conf); +@filesets = map { $n=&find_value("Name", $_->{'members'}) } + &find("FileSet", $conf); +@schedules = map { $n=&find_value("Name", $_->{'members'}) } + &find("Schedule", $conf); +@storages = map { $n=&find_value("Name", $_->{'members'}) } + &find("Storage", $conf); +@pools = map { $n=&find_value("Name", $_->{'members'}) } + &find("Pool", $conf); +@messages = map { $n=&find_value("Name", $_->{'members'}) } + &find("Messages", $conf); +@defs = map { $n=&find_value("Name", $_->{'members'}) } + &find("JobDefs", $conf); +if ($in{'new'}) { + &ui_print_header(undef, $text{'job_title1'}, ""); + $mems = [ { 'name' => 'Type', + 'value' => 'Backup' }, + { 'name' => 'Level', + 'value' => 'Incremental' }, + { 'name' => 'Client', + 'value' => $clients[0] }, + { 'name' => 'FileSet', + 'value' => $filesets[0] }, + { 'name' => 'Schedule', + 'value' => $schedules[0] }, + { 'name' => 'Storage', + 'value' => $storages[0] }, + { 'name' => 'Messages', + 'value' => $messages[0] }, + { 'name' => 'Pool', + 'value' => $pools[0] }, + ]; + $job = { 'name' => 'Job', + 'members' => $mems }; + } +else { + &ui_print_header(undef, $text{'job_title2'}, ""); + $job = &find_by("Name", $in{'name'}, \@jobs); + $job || &error($text{'job_egone'}); + $mems = $job->{'members'}; + } + +# Show details +print &ui_form_start("save_job.cgi", "post"); +print &ui_hidden("new", $in{'new'}),"\n"; +print &ui_hidden("old", $in{'name'}),"\n"; +print &ui_table_start($text{'job_header'}, "width=100%", 4); + +# Job name +print &ui_table_row($text{'job_name'}, + &ui_textbox("name", $name=&find_value("Name", $mems), 40), 3); + +# Default or source +$defs = &find_value("JobDefs", $mems); +$dmode = $defs ? 2 : $job->{'name'} eq 'Job' ? 1 : 0; +print &ui_table_row($text{'job_def'}, + &ui_radio("dmode", $dmode, + [ [ 0, $text{'job_def0'} ], + [ 1, $text{'job_def1'} ], + [ 2, &text('job_def2', + &ui_select("defs", $defs, [ map { [ $_ ] } @defs ])) ] ]), 3); + +# Job type +$type = &find_value("Type", $mems); +print &ui_table_row($text{'job_type'}, + &ui_select("type", $type, + [ [ "", "<$text{'default'}>" ], + [ "Backup" ], [ "Restore" ], [ "Verify" ], [ "Admin" ] ], + 1, 0, 1)); + +# Backup level +$level = &find_value("Level", $mems); +print &ui_table_row($text{'job_level'}, + &ui_select("level", $level, + [ [ "", "<$text{'default'}>" ], + map { [ $_ ] } @backup_levels ], + 1, 0, 1)); + +# Client being backed up +$client = &find_value("Client", $mems); +print &ui_table_row($text{'job_client'}, + &ui_select("client", $client, + [ [ "", "<$text{'default'}>" ], + map { [ $_ ] } @clients ], 1, 0, 1)); + +# Files to be backed up +$fileset = &find_value("FileSet", $mems); +print &ui_table_row($text{'job_fileset'}, + &ui_select("fileset", $fileset, + [ [ "", "<$text{'default'}>" ], + map { [ $_ ] } @filesets ], 1, 0, 1)); + +# Backup schedule +$schedule = &find_value("Schedule", $mems); +print &ui_table_row($text{'job_schedule'}, + &ui_select("schedule", $schedule, + [ [ "", "<$text{'default'}>" ], + map { [ $_ ] } @schedules ], 1, 0, 1)); + +# Storage device +$storage = &find_value("Storage", $mems); +print &ui_table_row($text{'job_storage'}, + &ui_select("storage", $storage, + [ [ "", "<$text{'default'}>" ], + map { [ $_ ] } @storages ], 1, 0, 1)); + +# Backup pool +$pool = &find_value("Pool", $mems); +print &ui_table_row($text{'job_pool'}, + &ui_select("pool", $pool, + [ [ "", "<$text{'default'}>" ], + map { [ $_ ] } @pools ], 1, 0, 1)); + +# Backup messages +$messages = &find_value("Messages", $mems); +print &ui_table_row($text{'job_messages'}, + &ui_select("messages", $messages, + [ [ "", "<$text{'default'}>" ], + map { [ $_ ] } @messages ], 1, 0, 1)); + +# Priority level +$prority = &find_value("Priority", $mems); +print &ui_table_row($text{'job_prority'}, + &ui_opt_textbox("priority", $priority, 4, $text{'default'})); + +# Before and after commands +print &ui_table_hr(); + +$before = &find_value("Run Before Job", $mems); +print &ui_table_row($text{'job_before'}, + &ui_opt_textbox("before", $before, 60, $text{'default'}), 3); +$after = &find_value("Run After Job", $mems); +print &ui_table_row($text{'job_after'}, + &ui_opt_textbox("after", $after, 60, $text{'default'}), 3); + +$cbefore = &find_value("Client Run Before Job", $mems); +print &ui_table_row($text{'job_cbefore'}, + &ui_opt_textbox("cbefore", $cbefore, 60, $text{'default'}), 3); +$cafter = &find_value("Client Run After Job", $mems); +print &ui_table_row($text{'job_cafter'}, + &ui_opt_textbox("cafter", $cafter, 60, $text{'default'}), 3); + +# All done +print &ui_table_end(); +if ($in{'new'}) { + print &ui_form_end([ [ "create", $text{'create'} ] ]); + } +else { + ($bjob) = grep { $_->{'name'} eq $in{'name'} } &get_bacula_jobs(); + print &ui_form_end([ [ "save", $text{'save'} ], + ( $job->{'name'} eq 'Job' && $bjob ? + ( [ "run", $text{'job_run'} ] ) : ( ) ), + [ "delete", $text{'delete'} ] ]); + } +&ui_print_footer("list_jobs.cgi", $text{'jobs_return'}); + diff --git a/bacula-backup/edit_pool.cgi b/bacula-backup/edit_pool.cgi new file mode 100755 index 000000000..f2804bb89 --- /dev/null +++ b/bacula-backup/edit_pool.cgi @@ -0,0 +1,78 @@ +#!/usr/local/bin/perl +# Show the details of one file pool daemon + +require './bacula-backup-lib.pl'; +&ReadParse(); +$conf = &get_director_config(); +@pools = &find("Pool", $conf); + +if ($in{'new'}) { + &ui_print_header(undef, $text{'pool_title1'}, ""); + $mems = [ { 'name' => 'Pool Type', + 'value' => 'Backup' }, + { 'name' => 'Recycle', + 'value' => 'yes' }, + { 'name' => 'AutoPrune', + 'value' => 'yes' }, + { 'name' => 'Accept Any Volume', + 'value' => 'yes' }, + { 'name' => 'Volume Retention', + 'value' => '365 days' }, + ]; + $pool = { 'members' => $mems }; + } +else { + &ui_print_header(undef, $text{'pool_title2'}, ""); + $pool = &find_by("Name", $in{'name'}, \@pools); + $pool || &error($text{'pool_egone'}); + $mems = $pool->{'members'}; + } + +# Show details +print &ui_form_start("save_pool.cgi", "post"); +print &ui_hidden("new", $in{'new'}),"\n"; +print &ui_hidden("old", $in{'name'}),"\n"; +print &ui_table_start($text{'pool_header'}, "width=100%", 4); + +# Pool name +print &ui_table_row($text{'pool_name'}, + &ui_textbox("name", $name=&find_value("Name", $mems), 40), 3); + +# Pool type +print &ui_table_row($text{'pool_type'}, + &ui_select("type", $type=&find_value("Pool Type", $mems), + [ map { [ $_, $_ =~ /^\*(.*)$/ ? $1 : $_ ] } + @pool_types ], 1, 0, 1)); + +# Maximum Volume Jobs +$max = &find_value("Maximum Volume Jobs", $mems); +print &ui_table_row($text{'pool_max'}, + &ui_radio("maxmode", $max == 0 ? 0 : 1, + [ [ 0, $text{'pool_unlimited'} ], + [ 1, &ui_textbox('max', $max == 0 ? "" : $max, 6) ] ])); + +# Retention period +$reten = &find_value("Volume Retention", $mems); +print &ui_table_row($text{'pool_reten'}, + &show_period_input("reten", $reten)); + +# Various yes/no options +print &ui_table_row($text{'pool_recycle'}, + &bacula_yesno("recycle", "Recycle", $mems)); +print &ui_table_row($text{'pool_auto'}, + &bacula_yesno("auto", "AutoPrune", $mems)); +print &ui_table_row($text{'pool_any'}, + &bacula_yesno("any", "Accept Any Volume", $mems)); + +# All done +print &ui_table_end(); +if ($in{'new'}) { + print &ui_form_end([ [ "create", $text{'create'} ] ]); + } +else { + print &ui_form_end([ [ "save", $text{'save'} ], + [ "status", $text{'pool_status'} ], + [ "delete", $text{'delete'} ] ]); + } +&ui_print_footer("list_pools.cgi", $text{'pools_return'}); + diff --git a/bacula-backup/edit_schedule.cgi b/bacula-backup/edit_schedule.cgi new file mode 100755 index 000000000..147719489 --- /dev/null +++ b/bacula-backup/edit_schedule.cgi @@ -0,0 +1,62 @@ +#!/usr/local/bin/perl +# Show the details of one schedule + +require './bacula-backup-lib.pl'; +&ReadParse(); +$conf = &get_director_config(); +@schedules = &find("Schedule", $conf); +if ($in{'new'}) { + &ui_print_header(undef, $text{'schedule_title1'}, ""); + $mems = [ ]; + $schedule = { }; + } +else { + &ui_print_header(undef, $text{'schedule_title2'}, ""); + $schedule = &find_by("Name", $in{'name'}, \@schedules); + $schedule || &error($text{'schedule_egone'}); + $mems = $schedule->{'members'}; + } + +# Show details +print &ui_form_start("save_schedule.cgi", "post"); +print &ui_hidden("new", $in{'new'}),"\n"; +print &ui_hidden("old", $in{'name'}),"\n"; +print &ui_table_start($text{'schedule_header'}, "width=100%", 4); + +# Schedule +print &ui_table_row($text{'schedule_name'}, + &ui_textbox("name", $name=&find_value("Name", $mems), 40), 3); + +# Run files +@runs = &find_value("Run", $schedule->{'members'}); +$rtable = &ui_columns_start([ $text{'schedule_level'}, + $text{'schedule_times'} ], "width=100%"); +$i = 0; +foreach $r (@runs, undef, undef, undef) { + ($level, $times) = split(/\s+/, $r, 2); + $level =~ s/^Level\s*=\s*//; + $sched = &parse_schedule($times); + $rtable .= &ui_columns_row([ + &ui_select("level_$i", $level, + [ [ "", " " ], [ "Full" ], + [ "Incremental" ], [ "Differential" ] ], + 1, 0, 1), + &ui_textbox("times_$i", $times, + $sched || !$r ? "40 readonly" : 40)." ". + &schedule_chooser_button("times_$i") ]); + $i++; + } +$rtable .= &ui_columns_end(); +print &ui_table_row($text{'schedule_runs'}, $rtable); + +# All done +print &ui_table_end(); +if ($in{'new'}) { + print &ui_form_end([ [ "create", $text{'create'} ] ]); + } +else { + print &ui_form_end([ [ "save", $text{'save'} ], + [ "delete", $text{'delete'} ] ]); + } +&ui_print_footer("list_schedules.cgi", $text{'schedules_return'}); + diff --git a/bacula-backup/edit_sdirector.cgi b/bacula-backup/edit_sdirector.cgi new file mode 100755 index 000000000..54ed443eb --- /dev/null +++ b/bacula-backup/edit_sdirector.cgi @@ -0,0 +1,51 @@ +#!/usr/local/bin/perl +# Show the details of one file daemon director + +require './bacula-backup-lib.pl'; +&ReadParse(); +$conf = &get_storage_config(); +@sdirectors = &find("Director", $conf); + +if ($in{'new'}) { + &ui_print_header(undef, $text{'sdirector_title1'}, ""); + $mems = [ ]; + $sdirector = { 'members' => $mems }; + } +else { + &ui_print_header(undef, $text{'sdirector_title2'}, ""); + $sdirector = &find_by("Name", $in{'name'}, \@sdirectors); + $sdirector || &error($text{'sdirector_egone'}); + $mems = $sdirector->{'members'}; + } + +# Show details +print &ui_form_start("save_sdirector.cgi", "post"); +print &ui_hidden("new", $in{'new'}),"\n"; +print &ui_hidden("old", $in{'name'}),"\n"; +print &ui_table_start($text{'sdirector_header'}, "width=100%", 4); + +# Director name +print &ui_table_row($text{'sdirector_name'}, + &ui_textbox("name", $name=&find_value("Name", $mems), 40), 3); + +# Password for remote +print &ui_table_row($text{'sdirector_pass'}, + &ui_textbox("pass", $pass=&find_value("Password", $mems), 60), 3); + +# Monitor mode +print &ui_table_row($text{'sdirector_monitor'}, + &bacula_yesno("monitor", "Monitor", $mems)); + +&show_tls_directives($sdirector); + +# All done +print &ui_table_end(); +if ($in{'new'}) { + print &ui_form_end([ [ "create", $text{'create'} ] ]); + } +else { + print &ui_form_end([ [ "save", $text{'save'} ], + [ "delete", $text{'delete'} ] ]); + } +&ui_print_footer("list_sdirectors.cgi", $text{'sdirectors_return'}); + diff --git a/bacula-backup/edit_storage.cgi b/bacula-backup/edit_storage.cgi new file mode 100755 index 000000000..bc328fd97 --- /dev/null +++ b/bacula-backup/edit_storage.cgi @@ -0,0 +1,94 @@ +#!/usr/local/bin/perl +# Show the details of one file storage daemon + +require './bacula-backup-lib.pl'; +&ReadParse(); +$conf = &get_director_config(); +@storages = &find("Storage", $conf); +$sconf = &get_storage_config(); +if ($sconf) { + @devices = map { $n=&find_value("Name", $_->{'members'}) } + &find("Device", $sconf); + } + +if ($in{'new'}) { + &ui_print_header(undef, $text{'storage_title1'}, ""); + $mems = [ { 'name' => 'SDPort', + 'value' => 9103 }, + { 'name' => 'Address', + 'value' => &get_system_hostname() }, + { 'name' => 'Media Type', + 'value' => 'File' }, + { 'name' => 'Device', + 'value' => $devices[0] }, + ]; + if (@storages) { + push(@$mems, + { 'name' => 'Password', + 'value' => &find_value("Password", + $storages[0]->{'members'}) + }); + } + $storage = { 'members' => $mems }; + } +else { + &ui_print_header(undef, $text{'storage_title2'}, ""); + $storage = &find_by("Name", $in{'name'}, \@storages); + $storage || &error($text{'storage_egone'}); + $mems = $storage->{'members'}; + } + +# Show details +print &ui_form_start("save_storage.cgi", "post"); +print &ui_hidden("new", $in{'new'}),"\n"; +print &ui_hidden("old", $in{'name'}),"\n"; +print &ui_table_start($text{'storage_header'}, "width=100%", 4); + +# Storage name +print &ui_table_row($text{'storage_name'}, + &ui_textbox("name", $name=&find_value("Name", $mems), 40), 3); + +# Password for remote +print &ui_table_row($text{'storage_pass'}, + &ui_textbox("pass", $pass=&find_value("Password", $mems), 60), 3); + +# Connection details +print &ui_table_row($text{'storage_address'}, + &ui_textbox("address", $address=&find_value("Address", $mems), 20)); +print &ui_table_row($text{'storage_port'}, + &ui_textbox("port", $port=&find_value("SDPort", $mems), 6)); + +# Device name +if (@devices) { + $device=&find_value("Device", $mems); + $found = &indexof($device, @devices) >= 0; + print &ui_table_row($text{'storage_device'}, + &ui_select("device", $found ? $device : "", + [ (map { [ $_ ] } @devices), + [ "", $text{'storage_other'} ] ])."\n". + &ui_textbox("other", $found ? "" : $device, 10)); + } +else { + print &ui_table_row($text{'storage_device'}, + &ui_textbox("device", $device=&find_value("Device",$mems), 20)); + } + +# Media type +print &ui_table_row($text{'storage_media'}, + &ui_textbox("media", $media=&find_value("Media Type", $mems), 20)); + +# SSL options +&show_tls_directives($storage); + +# All done +print &ui_table_end(); +if ($in{'new'}) { + print &ui_form_end([ [ "create", $text{'create'} ] ]); + } +else { + print &ui_form_end([ [ "save", $text{'save'} ], + [ "status", $text{'storage_status'} ], + [ "delete", $text{'delete'} ] ]); + } +&ui_print_footer("list_storages.cgi", $text{'storages_return'}); + diff --git a/bacula-backup/edit_storagec.cgi b/bacula-backup/edit_storagec.cgi new file mode 100755 index 000000000..18456b8c5 --- /dev/null +++ b/bacula-backup/edit_storagec.cgi @@ -0,0 +1,43 @@ +#!/usr/local/bin/perl +# Show the global storage daemon configuration + +require './bacula-backup-lib.pl'; +&ReadParse(); +$conf = &get_storage_config(); +$storagec = &find("Storage", $conf); +$storagec || &error($text{'storagec_enone'}); +$mems = $storagec->{'members'}; + +@messages = map { $n=&find_value("Name", $_->{'members'}) } + &find("Messages", $conf); + +&ui_print_header(undef, $text{'storagec_title'}, "", "storagec"); + +print &ui_form_start("save_storagec.cgi", "post"); +print &ui_table_start($text{'storagec_header'}, "width=100%", 4); + +$name = &find_value("Name", $mems); +print &ui_table_row($text{'storagec_name'}, + &ui_textbox("name", $name, 20)); + +$port = &find_value("SDport", $mems); +print &ui_table_row($text{'storagec_port'}, + &ui_textbox("port", $port, 6)); + +$jobs = &find_value("Maximum Concurrent Jobs", $mems); +print &ui_table_row($text{'storagec_jobs'}, + &ui_opt_textbox("jobs", $jobs, 6, $text{'default'})); + +$dir = &find_value("WorkingDirectory", $mems); +print &ui_table_row($text{'storagec_dir'}, + &ui_textbox("dir", $dir, 60)." ". + &file_chooser_button("dir", 1), 3); + +# SSL options +&show_tls_directives($storagec); + +print &ui_table_end(); +print &ui_form_end([ [ "save", $text{'save'} ] ]); + +&ui_print_footer("", $text{'index_return'}); + diff --git a/bacula-backup/fixaddr.cgi b/bacula-backup/fixaddr.cgi new file mode 100755 index 000000000..02145df1a --- /dev/null +++ b/bacula-backup/fixaddr.cgi @@ -0,0 +1,19 @@ +#!/usr/local/bin/perl +# Update the host in bconsole.conf to match this system + +require './bacula-backup-lib.pl'; + +&lock_file($bconsole_conf_file); +$conconf = &get_bconsole_config(); +$condir = &find("Director", $conconf); +$addr = &get_system_hostname(); +if (!gethostbyname($addr)) { + $addr = "localhost"; + } +&save_directive($conconf, $condir, "Address", $addr, 1); +&flush_file_lines(); +&unlock_file($bconsole_conf_file); + +&webmin_log("fixaddr"); +&redirect(""); + diff --git a/bacula-backup/fixpass.cgi b/bacula-backup/fixpass.cgi new file mode 100755 index 000000000..019e6242e --- /dev/null +++ b/bacula-backup/fixpass.cgi @@ -0,0 +1,18 @@ +#!/usr/local/bin/perl +# Update the password in bconsole.conf to match bacula-dir.conf + +require './bacula-backup-lib.pl'; + +&lock_file($bconsole_conf_file); +$dirconf = &get_director_config(); +$dirdir = &find("Director", $dirconf); +$conconf = &get_bconsole_config(); +$condir = &find("Director", $conconf); +$dirpass = &find_value("Password", $dirdir->{'members'}); +&save_directive($conconf, $condir, "Password", $dirpass, 1); +&flush_file_lines(); +&unlock_file($bconsole_conf_file); + +&webmin_log("fixpass"); +&redirect(""); + diff --git a/bacula-backup/gbackup.cgi b/bacula-backup/gbackup.cgi new file mode 100755 index 000000000..3a1f10ff7 --- /dev/null +++ b/bacula-backup/gbackup.cgi @@ -0,0 +1,71 @@ +#!/usr/local/bin/perl +# Execute multiple backup jobs, one for each client + +require './bacula-backup-lib.pl'; +&ui_print_unbuffered_header(undef, $text{'gbackup_title'}, ""); +&ReadParse(); + +# Get the backup job def and real jobs +$conf = &get_director_config(); +@jobdefs = &find("JobDefs", $conf); +$jobdef = &find_by("Name", "ocjob_".$in{'job'}, \@jobdefs); +foreach $job (&get_bacula_jobs()) { + ($j, $c) = &is_oc_object($job); + if ($j eq $in{'job'} && $c) { + push(@jobs, $job); + } + } + +print "",&text('gbackup_run', "$in{'job'}", + scalar(@jobs)),"\n"; + +# Clear messages +$h = &open_console(); +&console_cmd($h, "messages"); + +# Run the real jobs +print "

\n"; +foreach $job (@jobs) { + ($j, $c) = &is_oc_object($job); + print "
",&text('gbackup_on', "$c"),"\n"; + print "
";
+
+	# Select the job to run
+	&sysprint($h->{'infh'}, "run\n");
+	&wait_for($h->{'outfh'}, 'run\\n');
+	$rv = &wait_for($h->{'outfh'}, 'Select Job.*:');
+	print $wait_for_input;
+	if ($rv == 0 && $wait_for_input =~ /(\d+):\s+\Q$job->{'name'}\E/) {
+		&sysprint($h->{'infh'}, "$1\n");
+		}
+	else {
+		&job_error($text{'backup_ejob'});
+		}
+
+	# Say that it is OK
+	$rv = &wait_for($h->{'outfh'}, 'OK to run.*:');
+	print $wait_for_input;
+	if ($rv == 0) {
+		&sysprint($h->{'infh'}, "yes\n");
+		}
+	else {
+		&job_error($text{'backup_eok'});
+		}
+
+	print "
"; + } +print "
\n"; +&close_console($h); +&webmin_log("gbackup", $in{'job'}); + +&ui_print_footer("", $text{'index_return'}); + +sub job_error +{ +print "\n"; +print "",@_,"

\n"; +&close_console($h); +&ui_print_footer("backup_form.cgi", $text{'backup_return'}); +exit; +} + diff --git a/bacula-backup/help/backup.html b/bacula-backup/help/backup.html new file mode 100644 index 000000000..e501ed2cd --- /dev/null +++ b/bacula-backup/help/backup.html @@ -0,0 +1,8 @@ +

Run Backup Job
+ +This form can be used to start the immediate execution of a Bacula backup +job. To run a job, you only need to select it from the list, and select whether +or not Webmin should wait for its final status to be displayed.

+ +