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