-
Notifications
You must be signed in to change notification settings - Fork 12
/
backup.py
118 lines (100 loc) · 3.47 KB
/
backup.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import docker
import sys
import pickle
import tarfile
import os
from subprocess import call
c = docker.Client(base_url='unix://var/run/docker.sock',
version='1.9',
timeout=10)
#Prints Help Message
def usage():
print "Running normally :"
print " python backup.py [backup/restore] data-container-name [restore-container-name]"
print "Running withing as a docker image (named docker-volume-backup) :"
print " docker run -t -i --rm \ "
print " -v /var/lib/docker/vfs:/var/lib/docker/vfs \ "
print " -v /var/run/docker.sock:/var/run/docker.sock -v /tmp:/backup docker-volume-backup \ "
print " backup <container>"
print "docker run -t -i --rm \ "
print " -v /var/lib/docker/vfs:/var/lib/docker/vfs \ "
print " -v /var/run/docker.sock:/var/run/docker.sock \ "
print " restore <backupedcontainer> <newcontainer> <tar storage absolute path on host>"
#Determines if we run within a docker container
#Might not be truly cleany as a way to check but it works ;)
def dockerized():
if 'docker' in open('/proc/1/cgroup').read():
return True
#first argument is the option backup/restore
if len(sys.argv) < 3:
print "Not enough arguments !!"
usage()
sys.exit(1)
#Location of the tar files (for a container running)
datadir = "/backup"
#first argument is the option backup/restore
option = sys.argv[1]
name = sys.argv[2]
if option == "backup":
# second argument is the container name
container = c.inspect_container(name)
container_name = container['Name']
print "Backing up : " + container_name
volumes = container['Volumes']
print "writing meta data to file "
pickle.dump ( container , open ("metadata","wb") )
if dockerized():
tar = tarfile.open(datadir + "/" + name + ".tar", "w:gz")
else:
tar = tarfile.open(name + ".tar", "w:gz")
tar.add("metadata")
for i, v in enumerate(volumes):
print v, volumes[v]
tar.add(volumes[v],v)
tar.close()
elif option == "restore":
#third argument is the restored container name
destname = sys.argv[3]
if dockerized() and len(sys.argv) < 5:
print "Restore Storage is missing !"
usage()
sys.exit(1)
print "Restoring"
if dockerized():
tar = tarfile.open(datadir + "/" + name + ".tar")
else:
tar = tarfile.open(name + ".tar")
metadatafile = tar.extractfile("metadata")
metadata = pickle.load(metadatafile)
imagename = metadata["Config"]["Image"]
volumes = metadata['Volumes']
vlist = []
for i, v in enumerate(volumes):
print v, volumes[v]
vlist.append(v)
#Start the restored container
restored_container = c.create_container(imagename,tty=True,volumes=vlist,name=destname)
c.start(restored_container);
#Recreate volumes_from (as it does not work when binds+volumes_from are used together
infodest = c.inspect_container(restored_container)
volumes = infodest['Volumes']
vlist = []
binds = {}
for i, v in enumerate(volumes):
vlist.append(v)
binding = { volumes[v]:{'bind':v} }
binds.update(binding)
#Add tar storage to bindings list
if dockerized():
datadir = sys.argv[4]
binds.update({str(datadir): {'bind': '/backup2'} })
else:
binds.update({ str(os.path.dirname(os.path.realpath(__file__))): {'bind': '/backup2'} })
#Start the restorer container
restorer_container = c.create_container('ubuntu',detach=False, tty=True, command="tar xvf /backup2/"+ name +".tar",volumes=vlist)
c.start(restorer_container,binds=binds)
c.wait(restorer_container)
print c.logs(restorer_container['Id'])
c.remove_container(restorer_container)
else:
usage()