|
a/trunk/wharfie/lib/makefile.py |
|
b/trunk/wharfie/lib/makefile.py |
|
... |
|
... |
23 |
# |
23 |
# |
24 |
################################################################################ |
24 |
################################################################################ |
25 |
# We use templates, which are checking their execution context, |
25 |
# We use templates, which are checking their execution context, |
26 |
# to be sure, that target commands are really only executed |
26 |
# to be sure, that target commands are really only executed |
27 |
# in the change root of the image. |
27 |
# in the change root of the image. |
28 |
templateTrgCmd = "#!/bin/bash\n[ -f ../Wharfile ] && exit 2;\n%s\nexit \$$?\n" |
28 |
# |
29 |
templateHostCmd = "#!/bin/bash\n[ ! -f ../Wharfile ] && exit 2;\n%s\nexit \$$?\n" |
29 |
# We use snar files to create incremental archives. Those files are targeted |
30 |
|
30 |
# to incremental backups, where the filestructure stays roughly the same. So |
31 |
archiveName = 'rootfs.tar'; |
31 |
# beside the name and timestamps of the files, it also relies on inodes. |
32 |
makeTargets = list(); |
32 |
# |
33 |
environment = list(); |
33 |
# As we are packing and extracting the images for every step, the inodes are |
34 |
finalTarget = list(); |
34 |
# constantly changing. As tar doesn't support to ignore inodes on incremental |
35 |
|
35 |
# backups, we are refreshing the backups in every step. |
36 |
# |
36 |
# |
37 |
# Write a Makefile |
37 |
# input snar output snar output tar |
38 |
# |
38 |
# level 0: <none> l0.snar l0.tar |
39 |
def write_makefile(filename, dry_run, installpath='.'): |
39 |
# level 1: l0.snar l1.snar l1.tar |
40 |
f = open(filename, 'w'); |
40 |
# level 2: l1.snar l2.snar l2.tar |
41 |
# write header |
41 |
# |
42 |
f.write("ifneq (${VERBOSE},y)\n") |
42 |
# When we prepare the rootfs for level 2, we have to do the following: |
43 |
f.write("Q=@\n") |
43 |
# |
44 |
f.write("endif\n") |
44 |
# - tar -xf l0.tar -g l0.snar |
45 |
f.write("\n") |
45 |
# |
46 |
f.write("OUTPUT_FILE=%s\n" % archiveName) |
46 |
# - tar -xf l1.tar -g l1.snar |
47 |
f.write("%s: %s\n" % (archiveName, "".join(finalTarget))); |
47 |
# - cp l0.snar l1.snar |
48 |
f.write("\tcp $< $@\n"); |
48 |
# - tar -cf /dev/zero -g l1.snar . |
49 |
f.write("\n"); |
49 |
# |
50 |
|
50 |
# - tar -xf l2.tar -g l2.snar |
51 |
|
51 |
# - cp l1.snar l2.snar |
52 |
# write all environment variables |
52 |
# - tar -cf /dev/zero -g l2.snar . |
53 |
for env in environment: |
53 |
# |
54 |
l = env.lstrip().split(" ") |
54 |
################################################################################# |
55 |
f.write("export %s=%s\n" % (l[0], " ".join(l[1:]))); |
55 |
templateTrgCmd = "#!/bin/bash\n[ -f ../Wharfile ] && exit 2;\n%s\nexit \$$?\n" |
56 |
|
56 |
templateHostCmd = "#!/bin/bash\n[ ! -f ../Wharfile ] && exit 2;\n%s\nexit \$$?\n" |
57 |
# write all targets |
57 |
|
58 |
for target in makeTargets: |
58 |
makeTargets = list(); |
59 |
if 'comment' in target: |
59 |
environment = list(); |
60 |
f.write("# %s\n" % target['comment']); |
60 |
finalTarget = list(); |
61 |
f.write("%s: %s\n" % (target['name'], " ".join(target['dep']))); |
61 |
|
62 |
# target and host commands have to extract and repack always. |
62 |
# |
63 |
# simple commands don't do that. |
63 |
# Write a Makefile |
64 |
if 'trgcmd' in target or 'hostcmd' in target: |
64 |
# |
65 |
f.write("\t${Q}-mkdir $$(basename $@ .tar)\n"); |
65 |
def write_makefile(filename, dry_run, installpath='.', incremental=False): |
66 |
|
66 |
backup_levels=list() |
67 |
if 'trgcmd' in target: |
67 |
f = open(filename, 'w'); |
68 |
cmd = templateTrgCmd % (target['trgcmd'].replace('$', '\\$$').replace('"', '\\"')); |
68 |
# write header |
69 |
f.write("\t${Q}echo '******************************'\n"); |
69 |
f.write("ifneq (${VERBOSE},y)\n") |
70 |
f.write("\t${Q}echo '%s'\n" % target['comment']); |
70 |
f.write("Q=@\n") |
71 |
f.write("\t${Q}echo '******************************'\n"); |
71 |
f.write("endif\n") |
72 |
f.write("\t${Q}(echo -e \"%s\") | tee ./$$(basename $@ .tar)/.trg.sh\n" % cmd.replace('\\n', '\\\\\\n').replace('\n', '\\n').replace('!', '"\'!\'"')); |
72 |
f.write("\n") |
73 |
f.write("\t${Q}chmod a+x ./$$(basename $@ .tar)/.trg.sh\n"); |
73 |
f.write("all: %s\n\n" % (finalTarget[0])); |
74 |
|
74 |
|
75 |
if 'hostcmd' in target: |
75 |
# write all environment variables |
76 |
cmd = templateHostCmd % (target['hostcmd'].replace('$', '\\$$').replace('"', '\\"')); |
76 |
for env in environment: |
77 |
f.write("\t${Q}echo '******************************'\n"); |
77 |
l = env.lstrip().split(" ") |
78 |
f.write("\t${Q}echo '%s'\n" % target['comment']); |
78 |
f.write("export %s=%s\n" % (l[0], " ".join(l[1:]))); |
79 |
f.write("\t${Q}echo '******************************'\n"); |
79 |
|
80 |
f.write("\t${Q}(echo -e \"%s\") | tee ./$$(basename $@ .tar)/.hst.sh\n" % cmd.replace('\\n', '\\\\\\\\n').replace('\n', '\\n').replace('!', '"\'!\'"')); |
80 |
# write all targets |
81 |
f.write("\t${Q}chmod a+x ./$$(basename $@ .tar)/.hst.sh\n"); |
81 |
for target in makeTargets: |
82 |
|
82 |
if 'comment' in target: |
83 |
# start command here ... |
83 |
f.write("# %s\n" % target['comment']); |
84 |
f.write("\t${Q}${SUDO} bash -c \""); |
84 |
f.write("%s: %s\n" % (target['name'], " ".join(target['dep']))); |
85 |
|
85 |
# target and host commands have to extract and repack always. |
86 |
f.write("cd $$(basename $@ .tar); tar -xf ../$<; "); |
86 |
# simple commands don't do that. |
87 |
if not dry_run: |
87 |
if 'trgcmd' in target or 'hostcmd' in target or 'temporary' in target: |
88 |
f.write("if [ -f .trg.sh ]; then chroot . ./.trg.sh || exit 1; fi; rm -f ./.trg.sh;"); |
88 |
f.write("\t${Q}-mkdir $$(basename $@ .tar)\n"); |
89 |
f.write("if [ -f .hst.sh ]; then ./.hst.sh || exit 1; fi; rm -f ./.hst.sh;"); |
89 |
|
90 |
if not 'temporary' in target or not target['temporary']: |
90 |
if 'trgcmd' in target: |
91 |
f.write("tar -cf '../$@' .;"); |
91 |
cmd = templateTrgCmd % (target['trgcmd'].replace('$', '\\$$').replace('"', '\\"')); |
92 |
f.write("\"\n"); |
92 |
f.write("\t${Q}echo '******************************'\n"); |
93 |
# ... end command |
93 |
f.write("\t${Q}echo '%s'\n" % target['comment']); |
94 |
|
94 |
f.write("\t${Q}echo '******************************'\n"); |
95 |
|
95 |
f.write("\t${Q}(echo -e \"%s\") | ${SUDO} tee .trg.sh\n" % cmd.replace('\\n', '\\\\\\n').replace('\n', '\\n').replace('!', '"\'!\'"')); |
96 |
if 'temporary' in target and target['temporary']: |
96 |
f.write("\t${Q}${SUDO} chmod a+x .trg.sh\n"); |
97 |
f.write("\t${Q}cp $< $@\n"); |
97 |
|
|
|
98 |
if 'hostcmd' in target: |
|
|
99 |
cmd = templateHostCmd % (target['hostcmd'].replace('$', '\\$$').replace('"', '\\"')); |
|
|
100 |
f.write("\t${Q}echo '******************************'\n"); |
|
|
101 |
f.write("\t${Q}echo '%s'\n" % target['comment']); |
|
|
102 |
f.write("\t${Q}echo '******************************'\n"); |
|
|
103 |
f.write("\t${Q}(echo -e \"%s\") | ${SUDO} tee .hst.sh\n" % cmd.replace('\\n', '\\\\\\\\n').replace('\n', '\\n').replace('!', '"\'!\'"')); |
|
|
104 |
f.write("\t${Q}${SUDO} chmod a+x .hst.sh\n"); |
|
|
105 |
|
|
|
106 |
# start command here ... |
|
|
107 |
f.write("\t${Q}${SUDO} bash -c \""); |
|
|
108 |
|
|
|
109 |
# extracting from multiple backup levels |
|
|
110 |
backup_levels.append(target["dep"][0]) |
|
|
111 |
f.write("cd $$(basename $@ .tar);") |
|
|
112 |
lastincrement = None |
|
|
113 |
for increment in backup_levels[-1:]: |
|
|
114 |
if lastincrement == None: |
|
|
115 |
# level-0 backup |
|
|
116 |
f.write("[ -f ../%s.snar ]" % increment); |
|
|
117 |
f.write(" && tar -g ../%s.snar -xf ../%s" % (increment, increment)); |
|
|
118 |
f.write(" || tar -xf ../%s;" % increment); |
|
|
119 |
else: |
|
|
120 |
# level-x backup, update snar after extract |
|
|
121 |
f.write("tar -g ../%s.snar -xf ../%s;" % (increment, increment)); |
|
|
122 |
|
|
|
123 |
lastincrement = increment |
|
|
124 |
|
|
|
125 |
if not dry_run: |
|
|
126 |
f.write("if [ -f ../.trg.sh ]; then mv ../.trg.sh .; chroot . ./.trg.sh || exit 1; fi; rm -f ./.trg.sh;"); |
|
|
127 |
f.write("if [ -f ../.hst.sh ]; then ../.hst.sh || exit 1; fi; rm -f ../.hst.sh;"); |
|
|
128 |
if not 'temporary' in target or not target['temporary']: |
|
|
129 |
# copy over snar file from previous level and add changes to the new one |
|
|
130 |
f.write("[ ! -f ../$<.snar ] || cp ../$<.snar ../$@.snar;"); |
|
|
131 |
if incremental: |
|
|
132 |
f.write("tar -g ../$@.snar -cf '../$@' .;"); |
|
|
133 |
else: |
|
|
134 |
f.write("tar -cf '../$@' .;"); |
|
|
135 |
f.write("\"\n"); |
|
|
136 |
# ... end command |
|
|
137 |
|
|
|
138 |
|
|
|
139 |
if 'temporary' in target and target['temporary']: |
|
|
140 |
f.write("\t[ ! -f $< ] || cp $< $@;"); |
|
|
141 |
f.write("\t[ ! -f $<.snar ] || cp $<.snar $@.snar;\n"); |
98 |
|
142 |
|
99 |
f.write("\t${Q}-${SUDO} rm -Rf ./$$(basename $@ .tar)\n"); |
143 |
f.write("\t${Q}-${SUDO} rm -Rf ./$$(basename $@ .tar)\n"); |
100 |
# |
144 |
# |
101 |
# end of target/host commands. |
145 |
# end of target/host commands. |
102 |
# we keep it open that those command types can still be combined |
146 |
# we keep it open that those command types can still be combined |