Revision 2a21ff92

b/image_creator/dialog_main.py
38 38
import os
39 39
import textwrap
40 40
import signal
41
import StringIO
41 42

  
42 43
from image_creator import __version__ as version
43 44
from image_creator.util import FatalError, MD5
44
from image_creator.output.dialog import InitializationOutput
45
from image_creator.output.dialog import InitializationOutput, GaugeOutput
45 46
from image_creator.disk import Disk
46 47
from image_creator.os_type import os_cls
48
from image_creator.kamaki_wrapper import Kamaki, ClientError
47 49

  
48 50
MSGBOX_WIDTH = 60
49 51
YESNO_WIDTH = 50
50 52
MENU_WIDTH = 70
53
INPUTBOX_WIDTH=70
51 54

  
52 55

  
53 56
class Reset(Exception):
......
63 66
        "Are you sure you want to reset everything?",
64 67
        width=YESNO_WIDTH)
65 68

  
69
def extract_image(session):
70
    d = session['dialog']
71
    dir = os.getcwd()
72
    while 1:
73
        if dir and dir[-1] != os.sep:
74
            dir = dir + os.sep
75

  
76
        (code, path) = d.fselect(dir, 10, 50, title="Save image as...")
77
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
78
            return False
79

  
80
        if os.path.isdir(path):
81
            dir=path
82
            continue
83

  
84
        if os.path.isdir("%s.meta" % path):
85
            d.msgbox("Can't overwrite directory `%s.meta'" % path,
86
                     width=MSGBOX_WIDTH)
87
            continue
88

  
89
        if os.path.isdir("%s.md5sum" % path):
90
            d.msgbox("Can't overwrite directory `%s.md5sum'" % path,
91
                     width=MSGBOX_WIDTH)
92
            continue
93

  
94
        basedir = os.path.dirname(path)
95
        name = os.path.basename(path)
96
        if not os.path.exists(basedir):
97
            d.msgbox("Directory `%s' does not exist" % basedir,
98
                     width=MSGBOX_WIDTH)
99
            continue
100

  
101
        dir = basedir
102
        if len(name) == 0:
103
            continue
104

  
105
        files = ["%s%s" % (path, ext) for ext in ('', '.meta', '.md5sum')]
106
        overwrite = filter(os.path.exists, files)
107

  
108
        if len(overwrite) > 0:
109
            if d.yesno("The following file(s) exist:\n"
110
                        "%s\nDo you want to overwrite them?" %
111
                        "\n".join(overwrite), width=YESNO_WIDTH):
112
                continue
113

  
114
        out = GaugeOutput(d, "Image Extraction", "Extracting image...")
115
        try:
116
            dev = session['device']
117
            if "checksum" not in session:
118
                size = dev.meta['SIZE']
119
                md5 = MD5(out)
120
                session['checksum'] = md5.compute(session['snapshot'], size)
121

  
122
            # Extract image file
123
            dev.out = out
124
            dev.dump(path)
125

  
126
            # Extract metadata file
127
            out.output("Extracting metadata file...")
128
            metastring = '\n'.join(
129
                ['%s=%s' % (k, v) for (k, v) in session['metadata'].items()])
130
            metastring += '\n'
131
            with open('%s.meta' % path, 'w') as f:
132
                f.write(metastring)
133
            out.success('done')
134

  
135
            # Extract md5sum file
136
            out.output("Extracting md5sum file...")
137
            md5str = "%s %s\n" % (session['checksum'], name)
138
            with open('%s.md5sum' % path, 'w') as f:
139
                f.write(md5str)
140
            out.success("done")
141

  
142
        finally:
143
            out.cleanup()
144
        d.msgbox("Image file `%s' was successfully extracted!" % path,
145
                 width=MSGBOX_WIDTH)
146
        break
147

  
148
    return True
149

  
66 150

  
67 151
def upload_image(session):
68 152
    d = session["dialog"]
153
    size = session['device'].meta['SIZE']
69 154

  
70 155
    if "account" not in session:
71 156
        d.msgbox("You need to provide your ~okeanos login username before you "
......
79 164
        return False
80 165

  
81 166
    while 1:
82
        (code, answer) = d.inputbox("Please provide a filename:",
83
                        init=session["upload"] if "upload" in session else '')
167
        init=session["upload"] if "upload" in session else ''
168
        (code, answer) = d.inputbox("Please provide a filename:", init=init,
169
                                    width=INPUTBOX_WIDTH)
170
            
84 171
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
85 172
            return False
86 173

  
87
        answer = answer.strip()
88
        if len(answer) == 0:
174
        filename = answer.strip()
175
        if len(filename) == 0:
89 176
            d.msgbox("Filename cannot be empty", width=MSGBOX_WIDTH)
90 177
            continue
178
        
179
        break
91 180

  
92
        session["upload"] = answer
93
        return True
181
    out = GaugeOutput(d, "Image Upload", "Uploading...")
182
    if 'checksum' not in session:
183
        md5 = MD5(out)
184
        session['checksum'] = md5.compute(session['snapshot'], size)
185
    try:
186
        kamaki = Kamaki(session['account'], session['token'], out)
187
        try:
188
            # Upload image file
189
            with open(session['snapshot'], 'rb') as f:
190
                session["upload"] = kamaki.upload(f, size, filename,
191
                                                  "Calculating block hashes",
192
                                                  "Uploading missing blocks")
193
            # Upload metadata file
194
            out.output("Uploading metadata file...")
195
            metastring = '\n'.join(
196
                ['%s=%s' % (k, v) for (k, v) in session['metadata'].items()])
197
            metastring += '\n'
198
            kamaki.upload(StringIO.StringIO(metastring), size=len(metastring),
199
                          remote_path="%s.meta" % filename)
200
            out.success("done")
201

  
202
            # Upload md5sum file
203
            out.output("Uploading md5sum file...")
204
            md5str = "%s %s\n" % (session['checksum'], filename)
205
            kamaki.upload(StringIO.StringIO(md5str), size=len(md5str),
206
                          remote_path="%s.md5sum" % filename)
207
            out.success("done")
208

  
209
        except ClientError as e:
210
            d.msgbox("Error in pithos+ client: %s" % e.message,
211
                     title="Pithos+ Client Error", width=MSGBOX_WIDTH)
212
            if 'upload' in session:
213
                del session['upload']
214
            return False
215
    finally:
216
        out.cleanup()
217

  
218
    d.msgbox("Image file `%s' was successfully uploaded to pithos+" % filename, 
219
             width=MSGBOX_WIDTH)
220
    return True
94 221

  
95 222

  
96 223
def register_image(session):
......
114 241
                 width=MSGBOX_WIDTH)
115 242
        return False
116 243

  
244
    while 1:
245
        (code, answer) = d.inputbox("Please provide a registration name:"
246
                                " be registered:", width=INPUTBOX_WIDTH)
247
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
248
            return False
249

  
250
        name = answer.strip()
251
        if len(name) == 0:
252
            d.msgbox("Registration name cannot be empty", width=MSGBOX_WIDTH)
253
            continue
254
        break
255

  
256
    out = GaugeOutput(d, "Image Registration", "Registrating image...")
257
    try:
258
        out.output("Registring image to cyclades...")
259
        try:
260
            kamaki = Kamaki(session['account'], session['token'], out)
261
            kamaki.register(name, session['upload'], session['metadata'])
262
            out.success('done')
263
        except ClientError as e:
264
            d.msgbox("Error in pithos+ client: %s" % e.message)
265
            return False
266
    finally:
267
        out.cleanup()
268

  
269
    d.msgbox("Image `%s' was successfully registered to cyclades as `%s'" %
270
             (session['upload'], name), width=MSGBOX_WIDTH)
117 271
    return True
118 272

  
119 273

  
......
129 283
            width=MENU_WIDTH,
130 284
            choices=[("Account", "Change your ~okeanos username: %s" %
131 285
                      account),
132
                     ("Token", "Change your ~okeanos token: %s" %
133
                      token),
286
                     ("Token", "Change your ~okeanos token: %s" % token),
134 287
                     ("Upload", "Upload image to pithos+"),
135 288
                     ("Register", "Register image to cyclades: %s" % upload)],
136 289
            cancel="Back",
......
182 335
    d = session['dialog']
183 336
    dev = session['device']
184 337
    d.setBackgroundTitle("OS: %s, Distro: %s" % (dev.ostype, dev.distro))
185
    actions = {"Register": kamaki_menu}
338
    actions = {"Register": kamaki_menu, "Extract": extract_image}
186 339
    default_item = "Customize"
187 340

  
188 341
    while 1:
......
238 391

  
239 392
def collect_metadata(dev, out):
240 393

  
241
    dev.mount(readonly=True)
242 394
    out.output("Collecting image metadata...")
395
    metadata = dev.meta
396
    dev.mount(readonly=True)
243 397
    cls = os_cls(dev.distro, dev.ostype)
244 398
    image_os = cls(dev.root, dev.g, out)
245
    out.success("done")
246 399
    dev.umount()
400
    metadata.update(image_os.meta)
401
    out.success("done")
247 402

  
248
    return image_os.meta
403
    return metadata
249 404

  
250 405

  
251 406
def image_creator(d):
......
283 438

  
284 439
        session = {"dialog": d,
285 440
                   "disk": disk,
441
                   "snapshot": snapshot,
286 442
                   "device": dev,
287 443
                   "metadata": metadata}
288 444

  

Also available in: Unified diff