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