]>
git.frykholm.com Git - butterbackup.git/blob - butterbackup.py
210f8498c64b35f619f793257f32205bcc2e6796
4 from subprocess
import check_call
, CalledProcessError
10 def __init__(self
, name
, config
):
13 if not self
.config
.has_section('host'):
14 self
.config
.add_section('host')
15 self
.store_dir
= self
.config
['host']['store_dir']
16 self
.host_dir
= os
.path
.join(self
.store_dir
, name
)
17 self
.subvol_dir
= os
.path
.join(self
.host_dir
, "latest")
18 self
.keep
= int(self
.config
.get("host", "keep", fallback
=-1))
21 if not os
.path
.exists(self
.host_dir
):
22 print("New host",self
.name
,".")
23 os
.makedirs(self
.host_dir
)
24 if not os
.path
.exists(self
.subvol_dir
):
26 check_call(shlex
.split("btrfs subvol create %s"% self
.subvol_dir
))
27 except CalledProcessError
as ex
:
28 print("Failed to create subvol! Aborting backup.")
31 command
= ("rsync -a --acls --xattrs --whole-file --numeric-ids --delete --delete-excluded --human-readable --inplace ")
32 excludes
= " --exclude " + " --exclude ".join(self
.config
.get("host", "exclude").split(',')) #FIXME
34 print(command
+ excludes
+ " root@%s:/ "%(self
.name
) + self
.subvol_dir
)
35 check_call(shlex
.split(command
+ excludes
+ " root@%s:/ "%(self
.name
) + self
.subvol_dir
))
36 except CalledProcessError
as ex
:
37 if ex
.returncode
not in (12, 30):
38 print("Rsync did not transfer anything from %s, skipping snapshot."%self
.name
)
40 todays_date
= datetime
.datetime
.now().date().strftime("%F")
41 if os
.path
.exists(os
.path
.join(self
.host_dir
, todays_date
)):
42 #There is a snapshot for today, removing it and creating a new one
44 check_call(shlex
.split("btrfs subvol delete %s"%(os
.path
.join(self
.host_dir
, todays_date
))))
45 except CalledProcessError
as ex
:
48 check_call(shlex
.split("btrfs subvol snapshot -r %s %s"%(self
.subvol_dir
,os
.path
.join(self
.host_dir
, todays_date
))))
49 except CalledProcessError
as ex
:
52 def prune_snapshots(self
):
54 print("No keep specified for %s, keeping all"%self
.name
)
56 if not os
.path
.exists(self
.host_dir
):
57 print("New host, no pruning needed")
59 snaps
= sorted([snap
for snap
in os
.listdir(self
.host_dir
) if not snap
== "latest" ], reverse
=True)
60 while len(snaps
) > self
.keep
:
63 check_call(shlex
.split("btrfs subvol delete %s"%(os
.path
.join(self
.host_dir
, snap
))))
64 except CalledProcessError
as ex
:
68 def __init__(self
, config_dir
):
69 self
.config_dir
= config_dir
70 if not os
.path
.exists(self
.config_dir
):
71 print("No config found", self
.config_dir
)
75 self
.hosts
= os
.listdir(self
.config_dir
)
77 for host
in self
.hosts
:
78 if host
== 'default.cfg':
81 config
= configparser
.ConfigParser(strict
=False)
82 config
.read_file(open(os
.path
.join(self
.config_dir
, 'default.cfg'),'r'))
83 config
.read(os
.path
.join(self
.config_dir
, host
))
84 except BaseException
as ex
:
85 print("Config error for %s. Skipping host."%host
)
87 h
= Host(host
, config
)
91 if __name__
== "__main__":
93 print("You need to be root. Otherwise all permissions will be lost.")
95 br
= BackupRunner("/etc/butterbackup")