Make sure EnforcePersonality runs last
[snf-image] / snf-image-helper / inject-files.py
1 #!/usr/bin/env python
2 #
3 # Copyright (C) 2011 GRNET S.A.
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 # General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 # 02110-1301, USA.
19
20 """Inject files into a directory
21
22 This program injects files into a target directory.
23 The files are passed to the program through a JSON string either read from a
24 file or from standard input.
25
26 """
27
28 import sys
29 import os
30 import json
31 import datetime
32 import base64
33 from optparse import OptionParser
34
35
36 def timestamp():
37     now = datetime.datetime.now()
38     current_time = now.strftime("%Y%m%d.%H%M%S")
39     return current_time
40
41
42 def parse_arguments(input_args):
43     usage = "Usage: %prog [options] <target>"
44     parser = OptionParser(usage=usage)
45     parser.add_option("-i", "--input",
46                         action="store", type='string', dest="input_file",
47                         help="get input from FILE instead of stdin",
48                         metavar="FILE")
49     parser.add_option("-d", "--decode",
50                         action="store_true", dest="decode", default=False,
51                         help="decode files under target and create manifest")
52
53     opts, args = parser.parse_args(input_args)
54
55     if len(args) != 1:
56         parser.error('target is missing')
57
58     target = args[0]
59     if not os.path.isdir(target):
60         parser.error('target is not a directory')
61
62     input_file = opts.input_file
63     if input_file is None:
64         input_file = sys.stdin
65     else:
66         if not os.path.isfile(input_file):
67             parser.error('input file does not exist')
68         input_file = open(input_file, 'r')
69
70     return (input_file, target, opts.decode)
71
72
73 def main():
74     (input_file, target, decode) = parse_arguments(sys.argv[1:])
75
76     files = json.load(input_file)
77
78     if decode:
79         manifest = open(target + '/manifest', 'w')
80
81     count = 0
82     for f in files:
83         count += 1
84         owner = f['owner'] if 'owner' in f else "root"
85         group = f['group'] if 'group' in f else "root"
86         mode = f['mode'] if 'mode' in f else 0440
87
88         filepath = f['path'] if not decode else str(count)
89         filepath = target + "/" + filepath
90
91         if os.path.lexists(filepath):
92             backup_file = filepath + '.bak.' + timestamp()
93             os.rename(filepath, backup_file)
94
95         parentdir = os.path.dirname(filepath)
96         if not os.path.exists(parentdir):
97             os.makedirs(parentdir)
98
99         newfile = open(filepath, 'w')
100         newfile.write(base64.b64decode(f['contents']))
101         newfile.close()
102
103         if decode:
104             manifest.write("%s\x00%s\x00%s\x00%o\x00%s\x00" %
105                            (count, owner, group, mode, f['path']))
106
107     sys.stderr.write('Files were injected successfully\n')
108
109     if decode:
110         manifest.close()
111
112     input_file.close()
113     return 0
114
115 if __name__ == "__main__":
116     sys.exit(main())
117
118 # vim: set sta sts=4 shiftwidth=4 sw=4 et ai :