Revision 789a3763 image_creator/dialog_main.py
b/image_creator/dialog_main.py | ||
---|---|---|
43 | 43 |
|
44 | 44 |
from image_creator import __version__ as version |
45 | 45 |
from image_creator.util import FatalError, MD5 |
46 |
from image_creator.output import Output, CombinedOutput |
|
47 |
from image_creator.output.cli import SimpleOutput |
|
46 | 48 |
from image_creator.output.dialog import GaugeOutput, InfoBoxOutput |
47 | 49 |
from image_creator.disk import Disk |
48 | 50 |
from image_creator.os_type import os_cls |
... | ... | |
201 | 203 |
"\n".join(overwrite), width=YESNO_WIDTH): |
202 | 204 |
continue |
203 | 205 |
|
204 |
out = GaugeOutput(d, "Image Extraction", "Extracting image...")
|
|
206 |
gauge = GaugeOutput(d, "Image Extraction", "Extracting image...")
|
|
205 | 207 |
try: |
206 | 208 |
dev = session['device'] |
207 |
if "checksum" not in session: |
|
208 |
size = dev.size |
|
209 |
md5 = MD5(out) |
|
210 |
session['checksum'] = md5.compute(session['snapshot'], size) |
|
211 |
|
|
212 |
# Extract image file |
|
213 |
dev.out = out |
|
214 |
dev.dump(path) |
|
215 |
|
|
216 |
# Extract metadata file |
|
217 |
out.output("Extracting metadata file...") |
|
218 |
with open('%s.meta' % path, 'w') as f: |
|
219 |
f.write(extract_metadata_string(session)) |
|
220 |
out.success('done') |
|
221 |
|
|
222 |
# Extract md5sum file |
|
223 |
out.output("Extracting md5sum file...") |
|
224 |
md5str = "%s %s\n" % (session['checksum'], name) |
|
225 |
with open('%s.md5sum' % path, 'w') as f: |
|
226 |
f.write(md5str) |
|
227 |
out.success("done") |
|
228 |
|
|
209 |
out = dev.out |
|
210 |
out.add(gauge) |
|
211 |
try: |
|
212 |
if "checksum" not in session: |
|
213 |
size = dev.size |
|
214 |
md5 = MD5(out) |
|
215 |
session['checksum'] = md5.compute(session['snapshot'], |
|
216 |
size) |
|
217 |
|
|
218 |
# Extract image file |
|
219 |
dev.dump(path) |
|
220 |
|
|
221 |
# Extract metadata file |
|
222 |
out.output("Extracting metadata file...") |
|
223 |
with open('%s.meta' % path, 'w') as f: |
|
224 |
f.write(extract_metadata_string(session)) |
|
225 |
out.success('done') |
|
226 |
|
|
227 |
# Extract md5sum file |
|
228 |
out.output("Extracting md5sum file...") |
|
229 |
md5str = "%s %s\n" % (session['checksum'], name) |
|
230 |
with open('%s.md5sum' % path, 'w') as f: |
|
231 |
f.write(md5str) |
|
232 |
out.success("done") |
|
233 |
finally: |
|
234 |
out.remove(gauge) |
|
229 | 235 |
finally: |
230 |
out.cleanup()
|
|
236 |
gauge.cleanup()
|
|
231 | 237 |
d.msgbox("Image file `%s' was successfully extracted!" % path, |
232 | 238 |
width=MSGBOX_WIDTH) |
233 | 239 |
break |
... | ... | |
237 | 243 |
|
238 | 244 |
def upload_image(session): |
239 | 245 |
d = session["dialog"] |
240 |
size = session['device'].size |
|
246 |
dev = session['device'] |
|
247 |
size = dev.size |
|
241 | 248 |
|
242 | 249 |
if "account" not in session: |
243 | 250 |
d.msgbox("You need to provide your ~okeanos login username before you " |
... | ... | |
265 | 272 |
|
266 | 273 |
break |
267 | 274 |
|
268 |
out = GaugeOutput(d, "Image Upload", "Uploading...")
|
|
275 |
gauge = GaugeOutput(d, "Image Upload", "Uploading...")
|
|
269 | 276 |
try: |
270 |
if 'checksum' not in session: |
|
271 |
md5 = MD5(out) |
|
272 |
session['checksum'] = md5.compute(session['snapshot'], size) |
|
273 |
kamaki = Kamaki(session['account'], session['token'], out) |
|
277 |
out = dev.out |
|
278 |
out.add(gauge) |
|
274 | 279 |
try: |
275 |
# Upload image file |
|
276 |
with open(session['snapshot'], 'rb') as f: |
|
277 |
session["upload"] = kamaki.upload(f, size, filename, |
|
278 |
"Calculating block hashes", |
|
279 |
"Uploading missing blocks") |
|
280 |
# Upload metadata file |
|
281 |
out.output("Uploading metadata file...") |
|
282 |
metastring = extract_metadata_string(session) |
|
283 |
kamaki.upload(StringIO.StringIO(metastring), size=len(metastring), |
|
284 |
remote_path="%s.meta" % filename) |
|
285 |
out.success("done") |
|
286 |
|
|
287 |
# Upload md5sum file |
|
288 |
out.output("Uploading md5sum file...") |
|
289 |
md5str = "%s %s\n" % (session['checksum'], filename) |
|
290 |
kamaki.upload(StringIO.StringIO(md5str), size=len(md5str), |
|
291 |
remote_path="%s.md5sum" % filename) |
|
292 |
out.success("done") |
|
293 |
|
|
294 |
except ClientError as e: |
|
295 |
d.msgbox("Error in pithos+ client: %s" % e.message, |
|
296 |
title="Pithos+ Client Error", width=MSGBOX_WIDTH) |
|
297 |
if 'upload' in session: |
|
298 |
del session['upload'] |
|
299 |
return False |
|
280 |
if 'checksum' not in session: |
|
281 |
md5 = MD5(out) |
|
282 |
session['checksum'] = md5.compute(session['snapshot'], size) |
|
283 |
|
|
284 |
kamaki = Kamaki(session['account'], session['token'], out) |
|
285 |
try: |
|
286 |
# Upload image file |
|
287 |
with open(session['snapshot'], 'rb') as f: |
|
288 |
session["upload"] = kamaki.upload(f, size, filename, |
|
289 |
"Calculating block hashes", |
|
290 |
"Uploading missing blocks") |
|
291 |
# Upload metadata file |
|
292 |
out.output("Uploading metadata file...") |
|
293 |
metastring = extract_metadata_string(session) |
|
294 |
kamaki.upload(StringIO.StringIO(metastring), |
|
295 |
size=len(metastring), |
|
296 |
remote_path="%s.meta" % filename) |
|
297 |
out.success("done") |
|
298 |
|
|
299 |
# Upload md5sum file |
|
300 |
out.output("Uploading md5sum file...") |
|
301 |
md5str = "%s %s\n" % (session['checksum'], filename) |
|
302 |
kamaki.upload(StringIO.StringIO(md5str), size=len(md5str), |
|
303 |
remote_path="%s.md5sum" % filename) |
|
304 |
out.success("done") |
|
305 |
|
|
306 |
except ClientError as e: |
|
307 |
d.msgbox("Error in pithos+ client: %s" % e.message, |
|
308 |
title="Pithos+ Client Error", width=MSGBOX_WIDTH) |
|
309 |
if 'upload' in session: |
|
310 |
del session['upload'] |
|
311 |
return False |
|
312 |
finally: |
|
313 |
out.remove(gauge) |
|
300 | 314 |
finally: |
301 |
out.cleanup()
|
|
315 |
gauge.cleanup()
|
|
302 | 316 |
|
303 | 317 |
d.msgbox("Image file `%s' was successfully uploaded to pithos+" % filename, |
304 | 318 |
width=MSGBOX_WIDTH) |
... | ... | |
308 | 322 |
|
309 | 323 |
def register_image(session): |
310 | 324 |
d = session["dialog"] |
325 |
dev = session['device'] |
|
311 | 326 |
|
312 | 327 |
if "account" not in session: |
313 | 328 |
d.msgbox("You need to provide your ~okeanos login username before you " |
... | ... | |
344 | 359 |
for key in session['task_metadata']: |
345 | 360 |
metadata[key] = 'yes' |
346 | 361 |
|
347 |
out = GaugeOutput(d, "Image Registration", "Registrating image...")
|
|
362 |
gauge = GaugeOutput(d, "Image Registration", "Registrating image...")
|
|
348 | 363 |
try: |
349 |
out.output("Registring image to cyclades...") |
|
364 |
out = dev.out |
|
365 |
out.add(gauge) |
|
350 | 366 |
try: |
351 |
kamaki = Kamaki(session['account'], session['token'], out) |
|
352 |
kamaki.register(name, session['upload'], metadata) |
|
353 |
out.success('done') |
|
354 |
except ClientError as e: |
|
355 |
d.msgbox("Error in pithos+ client: %s" % e.message) |
|
356 |
return False |
|
367 |
out.output("Registring image to cyclades...") |
|
368 |
try: |
|
369 |
kamaki = Kamaki(session['account'], session['token'], out) |
|
370 |
kamaki.register(name, session['upload'], metadata) |
|
371 |
out.success('done') |
|
372 |
except ClientError as e: |
|
373 |
d.msgbox("Error in pithos+ client: %s" % e.message) |
|
374 |
return False |
|
375 |
finally: |
|
376 |
out.remove(gauge) |
|
357 | 377 |
finally: |
358 |
out.cleanup()
|
|
378 |
gauge.cleanup()
|
|
359 | 379 |
|
360 | 380 |
d.msgbox("Image `%s' was successfully registered to cyclades as `%s'" % |
361 | 381 |
(session['upload'], name), width=MSGBOX_WIDTH) |
... | ... | |
657 | 677 |
else: |
658 | 678 |
image_os.disable_sysprep(syspreps[i]) |
659 | 679 |
|
660 |
out = InfoBoxOutput(d, "Image Configuration")
|
|
680 |
infobox = InfoBoxOutput(d, "Image Configuration")
|
|
661 | 681 |
try: |
662 | 682 |
dev = session['device'] |
663 |
dev.out = out |
|
664 |
dev.mount(readonly=False) |
|
683 |
dev.out.add(infobox) |
|
665 | 684 |
try: |
666 |
# The checksum is invalid. We have mounted the image rw |
|
667 |
if 'checksum' in session: |
|
668 |
del session['checksum'] |
|
669 |
|
|
670 |
# Monitor the metadata changes during syspreps |
|
671 |
with metadata_monitor(session, image_os.meta): |
|
672 |
image_os.out = out |
|
673 |
image_os.do_sysprep() |
|
674 |
image_os.out.finalize() |
|
675 |
|
|
676 |
# Disable syspreps that have ran |
|
677 |
for sysprep in session['exec_syspreps']: |
|
678 |
image_os.disable_sysprep(sysprep) |
|
679 |
|
|
685 |
dev.mount(readonly=False) |
|
686 |
try: |
|
687 |
# The checksum is invalid. We have mounted the image rw |
|
688 |
if 'checksum' in session: |
|
689 |
del session['checksum'] |
|
690 |
|
|
691 |
# Monitor the metadata changes during syspreps |
|
692 |
with metadata_monitor(session, image_os.meta): |
|
693 |
image_os.do_sysprep() |
|
694 |
infobox.finalize() |
|
695 |
|
|
696 |
# Disable syspreps that have ran |
|
697 |
for sysprep in session['exec_syspreps']: |
|
698 |
image_os.disable_sysprep(sysprep) |
|
699 |
finally: |
|
700 |
dev.umount() |
|
680 | 701 |
finally: |
681 |
dev.umount()
|
|
702 |
dev.out.remove(infobox)
|
|
682 | 703 |
finally: |
683 |
out.cleanup()
|
|
704 |
infobox.cleanup()
|
|
684 | 705 |
break |
685 | 706 |
return True |
686 | 707 |
|
... | ... | |
705 | 726 |
if not d.yesno("%s\n\nDo you want to continue?" % msg, width=70, |
706 | 727 |
height=12, title="Image Shrinking"): |
707 | 728 |
with metadata_monitor(session, dev.meta): |
708 |
dev.out = InfoBoxOutput(d, "Image Shrinking", height=4) |
|
709 |
dev.shrink() |
|
710 |
dev.out.finalize() |
|
729 |
infobox = InfoBoxOutput(d, "Image Shrinking", height=4) |
|
730 |
dev.out.add(infobox) |
|
731 |
try: |
|
732 |
dev.shrink() |
|
733 |
infobox.finalize() |
|
734 |
finally: |
|
735 |
dev.out.remove(infobox) |
|
711 | 736 |
|
712 | 737 |
session['shrinked'] = True |
713 | 738 |
update_background_title(session) |
... | ... | |
784 | 809 |
actions[choice](session) |
785 | 810 |
|
786 | 811 |
|
787 |
def select_file(d, media): |
|
788 |
root = os.sep |
|
789 |
while 1: |
|
790 |
if media is not None: |
|
791 |
if not os.path.exists(media): |
|
792 |
d.msgbox("The file `%s' you choose does not exist." % media, |
|
793 |
width=MSGBOX_WIDTH) |
|
794 |
else: |
|
795 |
break |
|
796 |
|
|
797 |
(code, media) = d.fselect(root, 10, 50, |
|
798 |
title="Please select input media") |
|
799 |
if code in (d.DIALOG_CANCEL, d.DIALOG_ESC): |
|
800 |
if confirm_exit(d, "You canceled the media selection dialog box."): |
|
801 |
sys.exit(0) |
|
802 |
else: |
|
803 |
media = None |
|
804 |
continue |
|
805 |
|
|
806 |
return media |
|
807 |
|
|
808 |
|
|
809 |
def image_creator(d): |
|
810 |
|
|
811 |
usage = "Usage: %prog [options] [<input_media>]" |
|
812 |
parser = optparse.OptionParser(version=version, usage=usage) |
|
813 |
|
|
814 |
options, args = parser.parse_args(sys.argv[1:]) |
|
815 |
|
|
816 |
if len(args) > 1: |
|
817 |
parser.error("Wrong numver of arguments") |
|
812 |
def image_creator(d, media, out): |
|
818 | 813 |
|
819 | 814 |
d.setBackgroundTitle('snf-image-creator') |
820 | 815 |
|
821 |
if os.geteuid() != 0: |
|
822 |
raise FatalError("You must run %s as root" % parser.get_prog_name()) |
|
823 |
|
|
824 |
media = select_file(d, args[0] if len(args) == 1 else None) |
|
825 |
|
|
826 |
out = GaugeOutput(d, "Initialization", "Initializing...") |
|
816 |
gauge = GaugeOutput(d, "Initialization", "Initializing...") |
|
817 |
out.add(gauge) |
|
827 | 818 |
disk = Disk(media, out) |
828 | 819 |
|
829 | 820 |
def signal_handler(signum, frame): |
830 |
out.cleanup()
|
|
821 |
gauge.cleanup()
|
|
831 | 822 |
disk.cleanup() |
832 | 823 |
|
833 | 824 |
signal.signal(signal.SIGINT, signal_handler) |
... | ... | |
849 | 840 |
metadata[str(key)] = str(value) |
850 | 841 |
|
851 | 842 |
out.success("done") |
852 |
out.cleanup() |
|
843 |
gauge.cleanup() |
|
844 |
out.remove(gauge) |
|
853 | 845 |
|
854 |
# Make sure the signal handler does not call out.cleanup again
|
|
846 |
# Make sure the signal handler does not call gauge.cleanup again
|
|
855 | 847 |
def dummy(self): |
856 | 848 |
pass |
857 |
out.cleanup = type(GaugeOutput.cleanup)(dummy, out, GaugeOutput)
|
|
849 |
gauge.cleanup = type(GaugeOutput.cleanup)(dummy, gauge, GaugeOutput)
|
|
858 | 850 |
|
859 | 851 |
session = {"dialog": d, |
860 | 852 |
"disk": disk, |
... | ... | |
892 | 884 |
return 0 |
893 | 885 |
|
894 | 886 |
|
887 |
def select_file(d, media): |
|
888 |
root = os.sep |
|
889 |
while 1: |
|
890 |
if media is not None: |
|
891 |
if not os.path.exists(media): |
|
892 |
d.msgbox("The file `%s' you choose does not exist." % media, |
|
893 |
width=MSGBOX_WIDTH) |
|
894 |
else: |
|
895 |
break |
|
896 |
|
|
897 |
(code, media) = d.fselect(root, 10, 50, |
|
898 |
title="Please select input media") |
|
899 |
if code in (d.DIALOG_CANCEL, d.DIALOG_ESC): |
|
900 |
if confirm_exit(d, "You canceled the media selection dialog box."): |
|
901 |
sys.exit(0) |
|
902 |
else: |
|
903 |
media = None |
|
904 |
continue |
|
905 |
|
|
906 |
return media |
|
907 |
|
|
908 |
|
|
895 | 909 |
def main(): |
896 | 910 |
|
897 | 911 |
d = dialog.Dialog(dialog="dialog") |
... | ... | |
903 | 917 |
dialog._common_args_syntax["extra_label"] = \ |
904 | 918 |
lambda string: ("--extra-label", string) |
905 | 919 |
|
906 |
while 1: |
|
907 |
try: |
|
920 |
usage = "Usage: %prog [options] [<input_media>]" |
|
921 |
parser = optparse.OptionParser(version=version, usage=usage) |
|
922 |
parser.add_option("-l", "--logfile", type="string", dest="logfile", |
|
923 |
default=None, help="log all messages to FILE", |
|
924 |
metavar="FILE") |
|
925 |
|
|
926 |
options, args = parser.parse_args(sys.argv[1:]) |
|
927 |
|
|
928 |
if len(args) > 1: |
|
929 |
parser.error("Wrong number of arguments") |
|
930 |
|
|
931 |
d.setBackgroundTitle('snf-image-creator') |
|
932 |
|
|
933 |
try: |
|
934 |
if os.geteuid() != 0: |
|
935 |
raise FatalError("You must run %s as root" % \ |
|
936 |
parser.get_prog_name()) |
|
937 |
|
|
938 |
media = select_file(d, args[0] if len(args) == 1 else None) |
|
939 |
|
|
940 |
logfile = None |
|
941 |
if options.logfile is not None: |
|
908 | 942 |
try: |
909 |
ret = image_creator(d) |
|
910 |
sys.exit(ret) |
|
911 |
except FatalError as e: |
|
912 |
msg = textwrap.fill(str(e), width=70) |
|
913 |
d.infobox(msg, width=INFOBOX_WIDTH, title="Fatal Error") |
|
914 |
sys.exit(1) |
|
915 |
except Reset: |
|
916 |
continue |
|
943 |
logfile = open(options.logfile, 'w') |
|
944 |
except IOError as e: |
|
945 |
raise FatalError( |
|
946 |
"Unable to open logfile `%s' for writing. Reason: %s" % \ |
|
947 |
(options.logfile, e.strerror)) |
|
948 |
try: |
|
949 |
log = SimpleOutput(False, logfile) if logfile is not None \ |
|
950 |
else Output() |
|
951 |
while 1: |
|
952 |
try: |
|
953 |
out = CombinedOutput([log]) |
|
954 |
out.output("Starting %s version %s..." % \ |
|
955 |
(parser.get_prog_name(), version)) |
|
956 |
ret = image_creator(d, media, out) |
|
957 |
sys.exit(ret) |
|
958 |
except Reset: |
|
959 |
log.output("Resetting everything...") |
|
960 |
continue |
|
961 |
finally: |
|
962 |
if logfile is not None: |
|
963 |
logfile.close() |
|
964 |
except FatalError as e: |
|
965 |
msg = textwrap.fill(str(e), width=70) |
|
966 |
d.infobox(msg, width=INFOBOX_WIDTH, title="Fatal Error") |
|
967 |
sys.exit(1) |
|
917 | 968 |
|
918 | 969 |
# vim: set sta sts=4 shiftwidth=4 sw=4 et ai : |
Also available in: Unified diff