]>
git.proxmox.com Git - pmg-api.git/blob - PMG/Backup.pm
15 my ($dbh, $table, $ofh, $seq, $seqcol) = @_;
17 my $sth = $dbh->column_info(undef, undef, $table, undef);
19 my $attrs = $sth->fetchall_arrayref({});
22 foreach my $ref (@$attrs) {
23 push @col_arr, $ref->{COLUMN_NAME
};
28 my $cols = join (', ', @col_arr);
29 $cols || die "unable to fetch column definitions: ERROR";
31 print $ofh "COPY $table ($cols) FROM stdin;\n";
33 my $cmd = "COPY $table ($cols) TO STDOUT";
37 while ($dbh->pg_getcopydata($data) >= 0) {
43 if ($seq && $seqcol) {
44 print $ofh "SELECT setval('$seq', max($seqcol)) FROM $table;\n\n";
51 print $ofh "SET client_encoding = 'SQL_ASCII';\n";
52 print $ofh "SET check_function_bodies = false;\n\n";
54 my $dbh = PMG
::DBTools
::open_ruledb
();
56 print $ofh "BEGIN TRANSACTION;\n\n";
61 # read a consistent snapshot
62 $dbh->do("SET TRANSACTION ISOLATION LEVEL SERIALIZABLE");
64 dump_table
($dbh, 'attribut', $ofh);
65 dump_table
($dbh, 'object', $ofh, 'object_id_seq', 'id');
66 dump_table
($dbh, 'objectgroup', $ofh, 'objectgroup_id_seq', 'id');
67 dump_table
($dbh, 'rule', $ofh, 'rule_id_seq', 'id');
68 dump_table
($dbh, 'rulegroup', $ofh);
69 dump_table
($dbh, 'userprefs', $ofh);
71 # we do not save the following tables: cgreylist, cmailstore, cmsreceivers, clusterinfo
75 $dbh->rollback(); # end read-only transaction
81 print $ofh "COMMIT TRANSACTION;\n\n";
87 print $ofh "SET client_encoding = 'SQL_ASCII';\n";
88 print $ofh "SET check_function_bodies = false;\n\n";
90 my $dbh = PMG
::DBTools
::open_ruledb
();
95 # read a consistent snapshot
96 $dbh->do("SET TRANSACTION ISOLATION LEVEL SERIALIZABLE");
98 print $ofh "BEGIN TRANSACTION;\n\n";
100 dump_table
($dbh, 'dailystat', $ofh);
101 dump_table
($dbh, 'domainstat', $ofh);
102 dump_table
($dbh, 'virusinfo', $ofh);
103 dump_table
($dbh, 'localstat', $ofh);
105 # drop/create the index is a little bit faster (20%)
107 print $ofh "DROP INDEX cstatistic_time_index;\n\n";
108 print $ofh "ALTER TABLE cstatistic DROP CONSTRAINT cstatistic_id_key;\n\n";
109 print $ofh "ALTER TABLE cstatistic DROP CONSTRAINT cstatistic_pkey;\n\n";
110 dump_table
($dbh, 'cstatistic', $ofh, 'cstatistic_id_seq', 'id');
111 print $ofh "ALTER TABLE ONLY cstatistic ADD CONSTRAINT cstatistic_pkey PRIMARY KEY (cid, rid);\n\n";
112 print $ofh "ALTER TABLE ONLY cstatistic ADD CONSTRAINT cstatistic_id_key UNIQUE (id);\n\n";
113 print $ofh "CREATE INDEX CStatistic_Time_Index ON CStatistic (Time);\n\n";
115 print $ofh "DROP INDEX CStatistic_ID_Index;\n\n";
116 dump_table
($dbh, 'creceivers', $ofh);
117 print $ofh "CREATE INDEX CStatistic_ID_Index ON CReceivers (CStatistic_CID, CStatistic_RID);\n\n";
119 dump_table
($dbh, 'statinfo', $ofh);
121 print $ofh "COMMIT TRANSACTION;\n\n";
125 $dbh->rollback(); # end read-only transaction
133 my ($filename, $include_statistics) = @_;
136 my $dirname = "/tmp/proxbackup_$$.$time";
137 my $dbfn = "Proxmox_ruledb.sql";
138 my $statfn = "Proxmox_statdb.sql";
139 my $tarfn = "config_backup.tar";
140 my $sigfn = "proxmox_backup_v1.md5";
141 my $verfn = "version.txt";
145 my $targetdir = dirname
($filename);
146 mkdir $targetdir; # try to create target dir
148 die "unable to access target directory '$targetdir'\n";
150 # create a temporary directory
153 # dump the database first
154 my $fh = PMG
::AtomicFile-
>open("$dirname/$dbfn", "w") ||
155 die "cant open '$dirname/$dbfn' - $! :ERROR";
161 if ($include_statistics) {
162 # dump the statistic db
163 my $sfh = PMG
::AtomicFile-
>open("$dirname/$statfn", "w") ||
164 die "cant open '$dirname/$statfn' - $! :ERROR";
171 my $pkg = PMG
::pmgcfg
::package();
172 my $ver = PMG
::pmgcfg
::version
();
174 my $vfh = PMG
::AtomicFile-
>open ("$dirname/$verfn", "w") ||
175 die "cant open '$dirname/$verfn' - $! :ERROR";
179 print $vfh "product: $pkg\nversion: $ver\nbackuptime:$time:$now\n";
182 my $sshfiles = -d
'/root/.ssh' ?
'/root/.ssh' : '';
184 my $extra_cfgs = '/etc/passwd /etc/group';
186 my $extra_fn = '/etc/shadow';
187 $extra_cfgs .= " $extra_fn" if -e
$extra_fn;
189 $extra_fn = '/etc/gshadow';
190 $extra_cfgs .= " $extra_fn" if -e
$extra_fn;
192 $extra_fn = '/etc/mail/spamassassin/custom.cf';
193 $extra_cfgs .= " $extra_fn" if -e
$extra_fn;
195 #$extra_fn = '/etc/postfix/tls_policy';
196 #$extra_cfgs .= " $extra_fn" if -e $extra_fn;
198 my $extradb = $include_statistics ?
$statfn : '';
200 # we do not store cluster configurations (cluster.cfg)
202 system("/bin/tar cf $dirname/$tarfn -C / " .
203 "/etc/pmg $sshfiles $extra_cfgs>/dev/null 2>&1") == 0 ||
204 die "unable to create system configuration backup: ERROR";
206 system("cd $dirname; md5sum $tarfn $dbfn $extradb $verfn> $sigfn") == 0 ||
207 die "unable to create backup signature: ERROR";
209 system("rm -f $filename; tar czf $filename -C $dirname $verfn $sigfn $dbfn $extradb $tarfn") == 0 ||
210 die "unable to create backup archive: ERROR";
223 my ($filename, $restore_database, $restore_config, $restore_statistics) = @_;
225 my $dbname = 'Proxmox_ruledb';
228 my $dirname = "/tmp/proxrestore_$$.$time";
229 my $dbfn = "Proxmox_ruledb.sql";
230 my $statfn = "Proxmox_statdb.sql";
231 my $tarfn = "config_backup.tar";
232 my $sigfn = "proxmox_backup_v1.md5";
235 # create a temporary directory
238 system("cd $dirname; tar xzf $filename >/dev/null 2>&1") == 0 ||
239 die "unable to extract backup archive: ERROR";
241 system("cd $dirname; md5sum -c $sigfn") == 0 ||
242 die "proxmox backup signature check failed: ERROR";
244 if ($restore_config) {
245 # restore the tar file
246 mkdir "$dirname/config/";
247 system("tar xpf $dirname/$tarfn -C $dirname/config/") == 0 ||
248 die "unable to restore configuration tar archive: ERROR";
250 -d
"$dirname/config/etc/pmg" ||
251 die "backup does not contain a valid system configuration directory (/etc/pmg)\n";
252 # unlink unneeded files
253 unlink "$dirname/config/etc/pmg/cluster.conf"; # never restore cluster config
254 rmtree
"$dirname/config/etc/pmg/master";
256 # backup old config to /etc/pmg.oldremove current config
260 system("cp -a $dirname/config/etc/pmg/* /etc/pmg/") == 0 ||
261 die "unable to restore system configuration: ERROR";
263 my $cfg = PMG
::Config-
>new();
264 my $ruledb = PMG
::RuleDB-
>new();
265 my $rulecache = PMG
::RuleCache-
>new($ruledb);
266 $cfg->rewrite_config($rulecache, 1);
269 if ($restore_database) {
270 # recreate the database
272 # stop all services accessing the database
273 PMG
::Utils
::service_wait_stopped
(40, $PMG::Utils
::db_service_list
);
275 print "Destroy existing rule database\n";
276 PMG
::DBTools
::delete_ruledb
($dbname);
278 print "Create new database\n";
279 my $dbh = PMG
::DBTools
::create_ruledb
($dbname);
280 my $ruledb = PMG
::RuleDB-
>new($dbh);
281 PMG
::DBTools
::init_ruledb
($ruledb);
283 system("cat $dirname/$dbfn|psql $dbname >/dev/null 2>&1") == 0 ||
284 die "unable to restore rule database: ERROR";
286 if ($restore_statistics) {
287 if (-f
"$dirname/$statfn") {
288 system("cat $dirname/$statfn|psql $dbname >/dev/null 2>&1") == 0 ||
289 die "unable to restore statistic database: ERROR";
293 print STDERR
"run analyze to speed up database queries\n";
294 PMG
::DBTools
::postgres_admin_cmd
('psql', { input
=> 'analyze;' }, $dbname);
296 print "Analyzing/Upgrading existing Databases...";
297 PMG
::DBTools
::upgradedb
($ruledb);
300 # cleanup old spam/virus storage
301 PMG
::MailQueue
::create_spooldirs
(0, 1);
303 my $cfg = PMG
::Config-
>new();
304 my $rulecache = PMG
::RuleCache-
>new($ruledb);
305 $cfg->rewrite_config($rulecache, 1);
307 # and restart services as soon as possible
308 foreach my $service (reverse @$PMG::Utils
::db_service_list
) {
309 eval { PVE
::Tools
::run_command
(['systemctl', 'start', $service]); };