Revision 979096dd
b/image_creator/disk.py | ||
---|---|---|
31 | 31 |
# interpreted as representing official policies, either expressed |
32 | 32 |
# or implied, of GRNET S.A. |
33 | 33 |
|
34 |
from image_creator.util import get_command, warn, progress_generator, success |
|
34 |
from image_creator.util import get_command |
|
35 |
from image_creator.util import warn, progress, success, output |
|
35 | 36 |
from image_creator import FatalError |
36 |
from clint.textui import puts |
|
37 | 37 |
|
38 | 38 |
import stat |
39 | 39 |
import os |
... | ... | |
101 | 101 |
the Disk instance. |
102 | 102 |
""" |
103 | 103 |
|
104 |
puts("Examining source media `%s'..." % self.source, False)
|
|
104 |
output("Examining source media `%s'..." % self.source, False)
|
|
105 | 105 |
sourcedev = self.source |
106 | 106 |
mode = os.stat(self.source).st_mode |
107 | 107 |
if stat.S_ISDIR(mode): |
... | ... | |
117 | 117 |
success('looks like a block device') |
118 | 118 |
|
119 | 119 |
# Take a snapshot and return it to the user |
120 |
puts("Snapshotting media source...", False)
|
|
120 |
output("Snapshotting media source...", False)
|
|
121 | 121 |
size = blockdev('--getsize', sourcedev) |
122 | 122 |
cowfd, cow = tempfile.mkstemp() |
123 | 123 |
os.close(cowfd) |
... | ... | |
177 | 177 |
|
178 | 178 |
def enable(self): |
179 | 179 |
"""Enable a newly created DiskDevice""" |
180 |
self.progressbar = progress_generator("Launching helper VM: ")
|
|
180 |
self.progressbar = progress("Launching helper VM: ") |
|
181 | 181 |
self.progressbar.next() |
182 | 182 |
eh = self.g.set_event_callback(self.progress_callback, |
183 | 183 |
guestfs.EVENT_PROGRESS) |
... | ... | |
188 | 188 |
self.progressbar.send(100) |
189 | 189 |
self.progressbar = None |
190 | 190 |
|
191 |
puts('Inspecting Operating System...', False)
|
|
191 |
output('Inspecting Operating System...', False)
|
|
192 | 192 |
roots = self.g.inspect_os() |
193 | 193 |
if len(roots) == 0: |
194 | 194 |
raise FatalError("No operating system found") |
... | ... | |
221 | 221 |
|
222 | 222 |
def mount(self): |
223 | 223 |
"""Mount all disk partitions in a correct order.""" |
224 |
|
|
225 |
output("Mounting image...", False) |
|
224 | 226 |
mps = self.g.inspect_get_mountpoints(self.root) |
225 | 227 |
|
226 | 228 |
# Sort the keys to mount the fs in a correct order. |
... | ... | |
237 | 239 |
try: |
238 | 240 |
self.g.mount(dev, mp) |
239 | 241 |
except RuntimeError as msg: |
240 |
print "%s (ignored)" % msg |
|
242 |
warn("%s (ignored)" % msg) |
|
243 |
success("done") |
|
241 | 244 |
|
242 | 245 |
def umount(self): |
243 | 246 |
"""Umount all mounted filesystems.""" |
... | ... | |
250 | 253 |
disk and then updating the partition table. The new disk size |
251 | 254 |
(in bytes) is returned. |
252 | 255 |
""" |
253 |
puts("Shrinking image (this may take a while)...", False) |
|
254 |
sys.stdout.flush() |
|
256 |
output("Shrinking image (this may take a while)...", False) |
|
255 | 257 |
|
256 | 258 |
dev = self.g.part_to_dev(self.root) |
257 | 259 |
parttype = self.g.part_get_parttype(dev) |
... | ... | |
313 | 315 |
blocksize = 2 ** 22 # 4MB |
314 | 316 |
size = self.size() |
315 | 317 |
progress_size = (size + 2 ** 20 - 1) // 2 ** 20 # in MB |
316 |
progressbar = progress_generator("Dumping image file: ", progress_size)
|
|
318 |
progressbar = progress("Dumping image file: ", progress_size) |
|
317 | 319 |
|
318 | 320 |
source = open(self.device, "r") |
319 | 321 |
try: |
b/image_creator/main.py | ||
---|---|---|
37 | 37 |
from image_creator import __version__ as version |
38 | 38 |
from image_creator import FatalError |
39 | 39 |
from image_creator.disk import Disk |
40 |
from image_creator.util import get_command, error, progress_generator, success |
|
41 |
from clint.textui import puts |
|
42 |
|
|
40 |
from image_creator.util import get_command, error, success, output |
|
41 |
from image_creator import util |
|
43 | 42 |
import sys |
44 | 43 |
import os |
45 | 44 |
import optparse |
... | ... | |
67 | 66 |
action="store_true", help="overwrite output files if they exist") |
68 | 67 |
|
69 | 68 |
parser.add_option("--no-cleanup", dest="cleanup", default=True, |
70 |
help="don't cleanup sensitive data", |
|
71 |
action="store_false") |
|
69 |
help="don't cleanup sensitive data", action="store_false") |
|
72 | 70 |
|
73 | 71 |
parser.add_option("--no-sysprep", dest="sysprep", default=True, |
74 |
help="don't perform system preperation", |
|
75 |
action="store_false") |
|
72 |
help="don't perform system preperation", action="store_false") |
|
76 | 73 |
|
77 | 74 |
parser.add_option("--no-shrink", dest="shrink", default=True, |
78 |
help="don't shrink any partition", |
|
79 |
action="store_false") |
|
75 |
help="don't shrink any partition", action="store_false") |
|
80 | 76 |
|
81 | 77 |
parser.add_option("-o", "--outfile", type="string", dest="outfile", |
82 | 78 |
default=None, action="callback", callback=check_writable_dir, |
83 |
help="dump image to FILE", |
|
84 |
metavar="FILE") |
|
79 |
help="dump image to FILE", metavar="FILE") |
|
80 |
|
|
81 |
parser.add_option("-s", "--silent", dest="silent", default=False, |
|
82 |
help="silent mode, only output error", action="store_true") |
|
85 | 83 |
|
86 | 84 |
parser.add_option("-u", "--upload", dest="upload", default=False, |
87 |
help="upload the image to pithos", |
|
88 |
action="store_true") |
|
85 |
help="upload the image to pithos", action="store_true") |
|
89 | 86 |
|
90 | 87 |
parser.add_option("-r", "--register", dest="register", default=False, |
91 | 88 |
help="register the image to ~okeanos", action="store_true") |
... | ... | |
108 | 105 |
|
109 | 106 |
|
110 | 107 |
def image_creator(): |
111 |
puts('snf-image-creator %s\n' % version) |
|
112 | 108 |
options = parse_options(sys.argv[1:]) |
113 | 109 |
|
110 |
if options.silent: |
|
111 |
util.silent = True |
|
112 |
|
|
113 |
output('snf-image-creator %s\n' % version) |
|
114 |
|
|
114 | 115 |
if os.geteuid() != 0: |
115 | 116 |
raise FatalError("You must run %s as root" \ |
116 | 117 |
% os.path.basename(sys.argv[0])) |
... | ... | |
131 | 132 |
image_os = osclass(dev.root, dev.g) |
132 | 133 |
metadata = image_os.get_metadata() |
133 | 134 |
|
134 |
puts()
|
|
135 |
output()
|
|
135 | 136 |
|
136 | 137 |
if options.sysprep: |
137 | 138 |
image_os.sysprep() |
... | ... | |
154 | 155 |
|
155 | 156 |
dev.dump(options.outfile) |
156 | 157 |
finally: |
157 |
puts('cleaning up...')
|
|
158 |
output('cleaning up...')
|
|
158 | 159 |
disk.cleanup() |
159 | 160 |
|
160 | 161 |
return 0 |
b/image_creator/os_type/__init__.py | ||
---|---|---|
31 | 31 |
# interpreted as representing official policies, either expressed |
32 | 32 |
# or implied, of GRNET S.A. |
33 | 33 |
|
34 |
from image_creator.util import output |
|
35 |
|
|
34 | 36 |
import re |
35 |
from clint.textui import indent, puts |
|
36 | 37 |
|
37 | 38 |
|
38 | 39 |
def add_prefix(target): |
... | ... | |
113 | 114 |
def data_cleanup(self): |
114 | 115 |
"""Cleanup sensitive data out of the OS image.""" |
115 | 116 |
|
116 |
puts('Cleaning up sensitive data out of the OS image:')
|
|
117 |
output('Cleaning up sensitive data out of the OS image:')
|
|
117 | 118 |
|
118 | 119 |
is_cleanup = lambda x: x.startswith('data_cleanup_') and \ |
119 | 120 |
callable(getattr(self, x)) |
... | ... | |
122 | 123 |
cnt = 0 |
123 | 124 |
for task in tasks: |
124 | 125 |
cnt += 1 |
125 |
puts(('(%d/%d)' % (cnt, size)).ljust(7), False)
|
|
126 |
output(('(%d/%d)' % (cnt, size)).ljust(7), False)
|
|
126 | 127 |
task() |
127 |
puts()
|
|
128 |
output()
|
|
128 | 129 |
|
129 | 130 |
def sysprep(self): |
130 | 131 |
"""Prepere system for image creation.""" |
131 | 132 |
|
132 |
puts('Preparing system for image creation:')
|
|
133 |
output('Preparing system for image creation:')
|
|
133 | 134 |
|
134 | 135 |
is_sysprep = lambda x: x.startswith('sysprep_') and \ |
135 | 136 |
callable(getattr(self, x)) |
... | ... | |
138 | 139 |
cnt = 0 |
139 | 140 |
for task in tasks: |
140 | 141 |
cnt += 1 |
141 |
puts(('(%d/%d)' % (cnt, size)).ljust(7), False)
|
|
142 |
output(('(%d/%d)' % (cnt, size)).ljust(7), False)
|
|
142 | 143 |
task() |
143 |
puts()
|
|
144 |
output()
|
|
144 | 145 |
|
145 | 146 |
# vim: set sta sts=4 shiftwidth=4 sw=4 et ai : |
b/image_creator/os_type/linux.py | ||
---|---|---|
32 | 32 |
# or implied, of GRNET S.A. |
33 | 33 |
|
34 | 34 |
from image_creator.os_type.unix import Unix |
35 |
from image_creator.util import warn |
|
36 |
|
|
37 |
from clint.textui import puts, indent |
|
35 |
from image_creator.util import warn, output |
|
38 | 36 |
|
39 | 37 |
import re |
40 | 38 |
import time |
... | ... | |
64 | 62 |
""" |
65 | 63 |
|
66 | 64 |
if print_header: |
67 |
print 'Fixing acpid powerdown action'
|
|
65 |
output('Fixing acpid powerdown action')
|
|
68 | 66 |
|
69 | 67 |
powerbtn_action = '#!/bin/sh\n\nPATH=/sbin:/bin:/usr/bin\n' \ |
70 | 68 |
'shutdown -h now \"Power button pressed\"\n' |
... | ... | |
119 | 117 |
""" |
120 | 118 |
|
121 | 119 |
if print_header: |
122 |
puts('Removing persistent network interface names')
|
|
120 |
output('Removing persistent network interface names')
|
|
123 | 121 |
|
124 | 122 |
rule_file = '/etc/udev/rules.d/70-persistent-net.rules' |
125 | 123 |
if self.g.is_file(rule_file): |
... | ... | |
131 | 129 |
""" |
132 | 130 |
|
133 | 131 |
if print_header: |
134 |
puts('Replacing fstab & grub non-persistent device appearences')
|
|
132 |
output('Replacing fstab & grub non-persistent device appearences')
|
|
135 | 133 |
|
136 | 134 |
# convert all devices in fstab to persistent |
137 | 135 |
persistent_root = self._persistent_fstab() |
b/image_creator/os_type/unix.py | ||
---|---|---|
35 | 35 |
import sys |
36 | 36 |
|
37 | 37 |
from image_creator.os_type import OSBase |
38 |
from image_creator.util import warn |
|
39 |
from clint.textui import puts |
|
38 |
from image_creator.util import warn, output |
|
40 | 39 |
|
41 | 40 |
|
42 | 41 |
class Unix(OSBase): |
... | ... | |
75 | 74 |
"""Remove all regular files under /var/cache""" |
76 | 75 |
|
77 | 76 |
if print_header: |
78 |
puts('Removing files under /var/cache')
|
|
77 |
output('Removing files under /var/cache')
|
|
79 | 78 |
|
80 | 79 |
self.foreach_file('/var/cache', self.g.rm, ftype='r') |
81 | 80 |
|
... | ... | |
83 | 82 |
"""Remove all files under /tmp and /var/tmp""" |
84 | 83 |
|
85 | 84 |
if print_header: |
86 |
puts('Removing files under /tmp and /var/tmp')
|
|
85 |
output('Removing files under /tmp and /var/tmp')
|
|
87 | 86 |
|
88 | 87 |
self.foreach_file('/tmp', self.g.rm_rf, maxdepth=1) |
89 | 88 |
self.foreach_file('/var/tmp', self.g.rm_rf, maxdepth=1) |
... | ... | |
92 | 91 |
"""Empty all files under /var/log""" |
93 | 92 |
|
94 | 93 |
if print_header: |
95 |
puts('Emptying all files under /var/log')
|
|
94 |
output('Emptying all files under /var/log')
|
|
96 | 95 |
|
97 | 96 |
self.foreach_file('/var/log', self.g.truncate, ftype='r') |
98 | 97 |
|
... | ... | |
100 | 99 |
"""Remove all files under /var/mail and /var/spool/mail""" |
101 | 100 |
|
102 | 101 |
if print_header: |
103 |
puts('Removing files under /var/mail and /var/spool/mail')
|
|
102 |
output('Removing files under /var/mail and /var/spool/mail')
|
|
104 | 103 |
|
105 | 104 |
self.foreach_file('/var/spool/mail', self.g.rm_rf, maxdepth=1) |
106 | 105 |
self.foreach_file('/var/mail', self.g.rm_rf, maxdepth=1) |
... | ... | |
111 | 110 |
homedirs = ['/root'] + self.ls('/home/') |
112 | 111 |
|
113 | 112 |
if print_header: |
114 |
puts('Removing sensitive user data under %s' % " ".join(homedirs)) |
|
113 |
output('Removing sensitive user data under %s' % " ". |
|
114 |
join(homedirs)) |
|
115 | 115 |
|
116 | 116 |
for homedir in homedirs: |
117 | 117 |
for data in self.sensitive_userdata: |
b/image_creator/util.py | ||
---|---|---|
31 | 31 |
# interpreted as representing official policies, either expressed |
32 | 32 |
# or implied, of GRNET S.A. |
33 | 33 |
|
34 |
import sys |
|
34 | 35 |
import pbs |
35 |
from clint.textui import puts, puts_err, colored, progress |
|
36 |
from clint.textui import colored, progress as uiprogress |
|
37 |
|
|
38 |
silent = False |
|
36 | 39 |
|
37 | 40 |
|
38 | 41 |
def get_command(command): |
... | ... | |
50 | 53 |
|
51 | 54 |
|
52 | 55 |
def error(msg, new_line=True): |
53 |
puts_err(colored.red("Error: %s\n" % msg), new_line) |
|
56 |
nl = "\n" if new_line else '' |
|
57 |
sys.stderr.write('Error: %s' % msg + nl) |
|
54 | 58 |
|
55 | 59 |
|
56 | 60 |
def warn(msg, new_line=True): |
57 |
puts_err(colored.yellow("Warning: %s" % msg), new_line) |
|
61 |
if not silent: |
|
62 |
nl = "\n" if new_line else '' |
|
63 |
sys.stderr.write(colored.yellow("Warning: %s" % msg) + nl) |
|
58 | 64 |
|
59 | 65 |
|
60 | 66 |
def success(msg, new_line=True): |
61 |
puts(colored.green(msg), new_line) |
|
67 |
if not silent: |
|
68 |
nl = "\n" if new_line else '' |
|
69 |
sys.stdout.write(colored.green(msg) + nl) |
|
70 |
if not nl: |
|
71 |
sys.stdout.flush() |
|
72 |
|
|
73 |
|
|
74 |
def output(msg="", new_line=True): |
|
75 |
if not silent: |
|
76 |
nl = "\n" if new_line else '' |
|
77 |
sys.stdout.write(msg + nl) |
|
78 |
if not nl: |
|
79 |
sys.stdout.flush() |
|
80 |
|
|
81 |
|
|
82 |
def progress(label='', n=100): |
|
62 | 83 |
|
84 |
PROGRESS_LENGTH = 32 |
|
85 |
MESSAGE_LENGTH = 32 |
|
63 | 86 |
|
64 |
def progress_generator(label='', n=100): |
|
65 |
position = 0 |
|
66 |
for i in progress.bar(range(n), label): |
|
67 |
if i < position: |
|
68 |
continue |
|
69 |
position = yield |
|
70 |
yield # suppress the StopIteration exception |
|
87 |
def progress_generator(label, n): |
|
88 |
position = 0 |
|
89 |
for i in uiprogress.bar(range(n), label.ljust(MESSAGE_LENGTH), \ |
|
90 |
PROGRESS_LENGTH, silent): |
|
91 |
if i < position: |
|
92 |
continue |
|
93 |
position = yield |
|
94 |
yield # suppress the StopIteration exception |
|
95 |
return progress_generator(label, n) |
|
71 | 96 |
|
72 | 97 |
# vim: set sta sts=4 shiftwidth=4 sw=4 et ai : |
Also available in: Unified diff