Statistics
| Branch: | Tag: | Revision:

root / image_creator / dialog_util.py @ 12c97404

History | View | Annotate | Download (8.8 kB)

1 121f3bc0 Nikos Skalkotos
# -*- coding: utf-8 -*-
2 121f3bc0 Nikos Skalkotos
#
3 023e1217 Nikos Skalkotos
# Copyright 2012 GRNET S.A. All rights reserved.
4 023e1217 Nikos Skalkotos
#
5 023e1217 Nikos Skalkotos
# Redistribution and use in source and binary forms, with or
6 023e1217 Nikos Skalkotos
# without modification, are permitted provided that the following
7 023e1217 Nikos Skalkotos
# conditions are met:
8 023e1217 Nikos Skalkotos
#
9 023e1217 Nikos Skalkotos
#   1. Redistributions of source code must retain the above
10 023e1217 Nikos Skalkotos
#      copyright notice, this list of conditions and the following
11 023e1217 Nikos Skalkotos
#      disclaimer.
12 023e1217 Nikos Skalkotos
#
13 023e1217 Nikos Skalkotos
#   2. Redistributions in binary form must reproduce the above
14 023e1217 Nikos Skalkotos
#      copyright notice, this list of conditions and the following
15 023e1217 Nikos Skalkotos
#      disclaimer in the documentation and/or other materials
16 023e1217 Nikos Skalkotos
#      provided with the distribution.
17 023e1217 Nikos Skalkotos
#
18 023e1217 Nikos Skalkotos
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
19 023e1217 Nikos Skalkotos
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 023e1217 Nikos Skalkotos
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 023e1217 Nikos Skalkotos
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
22 023e1217 Nikos Skalkotos
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 023e1217 Nikos Skalkotos
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 023e1217 Nikos Skalkotos
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
25 023e1217 Nikos Skalkotos
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 023e1217 Nikos Skalkotos
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 023e1217 Nikos Skalkotos
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 023e1217 Nikos Skalkotos
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 023e1217 Nikos Skalkotos
# POSSIBILITY OF SUCH DAMAGE.
30 023e1217 Nikos Skalkotos
#
31 023e1217 Nikos Skalkotos
# The views and conclusions contained in the software and
32 023e1217 Nikos Skalkotos
# documentation are those of the authors and should not be
33 023e1217 Nikos Skalkotos
# interpreted as representing official policies, either expressed
34 023e1217 Nikos Skalkotos
# or implied, of GRNET S.A.
35 023e1217 Nikos Skalkotos
36 121f3bc0 Nikos Skalkotos
"""Module providing useful functions for the dialog-based version of
37 121f3bc0 Nikos Skalkotos
snf-image-creator.
38 121f3bc0 Nikos Skalkotos
"""
39 121f3bc0 Nikos Skalkotos
40 023e1217 Nikos Skalkotos
import os
41 49c07ce3 Nikos Skalkotos
import re
42 8e58e699 Nikos Skalkotos
import json
43 0a116b9d Nikos Skalkotos
from image_creator.output.dialog import GaugeOutput
44 0a116b9d Nikos Skalkotos
from image_creator.util import MD5
45 49c07ce3 Nikos Skalkotos
from image_creator.kamaki_wrapper import Kamaki
46 023e1217 Nikos Skalkotos
47 023e1217 Nikos Skalkotos
SMALL_WIDTH = 60
48 023e1217 Nikos Skalkotos
WIDTH = 70
49 023e1217 Nikos Skalkotos
50 023e1217 Nikos Skalkotos
51 023e1217 Nikos Skalkotos
def update_background_title(session):
52 88f83027 Nikos Skalkotos
    """Update the backgroud title of the dialog page"""
53 023e1217 Nikos Skalkotos
    d = session['dialog']
54 b044e29e Nikos Skalkotos
    disk = session['disk']
55 f5174d2c Nikos Skalkotos
    image = session['image']
56 023e1217 Nikos Skalkotos
57 023e1217 Nikos Skalkotos
    MB = 2 ** 20
58 023e1217 Nikos Skalkotos
59 f5174d2c Nikos Skalkotos
    size = (image.size + MB - 1) // MB
60 023e1217 Nikos Skalkotos
    shrinked = 'shrinked' in session and session['shrinked']
61 023e1217 Nikos Skalkotos
    postfix = " (shrinked)" if shrinked else ''
62 023e1217 Nikos Skalkotos
63 b044e29e Nikos Skalkotos
    title = "OS: %s, Distro: %s, Size: %dMB%s, Source: %s" % \
64 f5174d2c Nikos Skalkotos
            (image.ostype, image.distro, size, postfix,
65 b044e29e Nikos Skalkotos
             os.path.abspath(disk.source))
66 023e1217 Nikos Skalkotos
67 023e1217 Nikos Skalkotos
    d.setBackgroundTitle(title)
68 023e1217 Nikos Skalkotos
69 023e1217 Nikos Skalkotos
70 023e1217 Nikos Skalkotos
def confirm_exit(d, msg=''):
71 88f83027 Nikos Skalkotos
    """Ask the user to confirm when exiting the program"""
72 023e1217 Nikos Skalkotos
    return not d.yesno("%s Do you want to exit?" % msg, width=SMALL_WIDTH)
73 023e1217 Nikos Skalkotos
74 023e1217 Nikos Skalkotos
75 023e1217 Nikos Skalkotos
def confirm_reset(d):
76 88f83027 Nikos Skalkotos
    """Ask the user to confirm a reset action"""
77 023e1217 Nikos Skalkotos
    return not d.yesno("Are you sure you want to reset everything?",
78 023e1217 Nikos Skalkotos
                       width=SMALL_WIDTH, defaultno=1)
79 023e1217 Nikos Skalkotos
80 023e1217 Nikos Skalkotos
81 023e1217 Nikos Skalkotos
class Reset(Exception):
82 88f83027 Nikos Skalkotos
    """Exception used to reset the program"""
83 023e1217 Nikos Skalkotos
    pass
84 023e1217 Nikos Skalkotos
85 023e1217 Nikos Skalkotos
86 0a116b9d Nikos Skalkotos
def extract_metadata_string(session):
87 88f83027 Nikos Skalkotos
    """Convert image metadata to text"""
88 8e58e699 Nikos Skalkotos
    metadata = {}
89 8e58e699 Nikos Skalkotos
    metadata.update(session['metadata'])
90 0a116b9d Nikos Skalkotos
    if 'task_metadata' in session:
91 8e58e699 Nikos Skalkotos
        for key in session['task_metadata']:
92 8e58e699 Nikos Skalkotos
            metadata[key] = 'yes'
93 0a116b9d Nikos Skalkotos
94 8e58e699 Nikos Skalkotos
    return unicode(json.dumps({'properties': metadata,
95 8e58e699 Nikos Skalkotos
                               'disk-format': 'diskdump'}, ensure_ascii=False))
96 0a116b9d Nikos Skalkotos
97 0a116b9d Nikos Skalkotos
98 023e1217 Nikos Skalkotos
def extract_image(session):
99 88f83027 Nikos Skalkotos
    """Dump the image to a local file"""
100 023e1217 Nikos Skalkotos
    d = session['dialog']
101 023e1217 Nikos Skalkotos
    dir = os.getcwd()
102 023e1217 Nikos Skalkotos
    while 1:
103 023e1217 Nikos Skalkotos
        if dir and dir[-1] != os.sep:
104 023e1217 Nikos Skalkotos
            dir = dir + os.sep
105 023e1217 Nikos Skalkotos
106 023e1217 Nikos Skalkotos
        (code, path) = d.fselect(dir, 10, 50, title="Save image as...")
107 023e1217 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
108 023e1217 Nikos Skalkotos
            return False
109 023e1217 Nikos Skalkotos
110 023e1217 Nikos Skalkotos
        if os.path.isdir(path):
111 023e1217 Nikos Skalkotos
            dir = path
112 023e1217 Nikos Skalkotos
            continue
113 023e1217 Nikos Skalkotos
114 023e1217 Nikos Skalkotos
        if os.path.isdir("%s.meta" % path):
115 023e1217 Nikos Skalkotos
            d.msgbox("Can't overwrite directory `%s.meta'" % path,
116 023e1217 Nikos Skalkotos
                     width=SMALL_WIDTH)
117 023e1217 Nikos Skalkotos
            continue
118 023e1217 Nikos Skalkotos
119 023e1217 Nikos Skalkotos
        if os.path.isdir("%s.md5sum" % path):
120 023e1217 Nikos Skalkotos
            d.msgbox("Can't overwrite directory `%s.md5sum'" % path,
121 023e1217 Nikos Skalkotos
                     width=SMALL_WIDTH)
122 023e1217 Nikos Skalkotos
            continue
123 023e1217 Nikos Skalkotos
124 023e1217 Nikos Skalkotos
        basedir = os.path.dirname(path)
125 023e1217 Nikos Skalkotos
        name = os.path.basename(path)
126 023e1217 Nikos Skalkotos
        if not os.path.exists(basedir):
127 023e1217 Nikos Skalkotos
            d.msgbox("Directory `%s' does not exist" % basedir,
128 023e1217 Nikos Skalkotos
                     width=SMALL_WIDTH)
129 023e1217 Nikos Skalkotos
            continue
130 023e1217 Nikos Skalkotos
131 023e1217 Nikos Skalkotos
        dir = basedir
132 023e1217 Nikos Skalkotos
        if len(name) == 0:
133 023e1217 Nikos Skalkotos
            continue
134 023e1217 Nikos Skalkotos
135 023e1217 Nikos Skalkotos
        files = ["%s%s" % (path, ext) for ext in ('', '.meta', '.md5sum')]
136 023e1217 Nikos Skalkotos
        overwrite = filter(os.path.exists, files)
137 023e1217 Nikos Skalkotos
138 023e1217 Nikos Skalkotos
        if len(overwrite) > 0:
139 023e1217 Nikos Skalkotos
            if d.yesno("The following file(s) exist:\n"
140 023e1217 Nikos Skalkotos
                       "%s\nDo you want to overwrite them?" %
141 023e1217 Nikos Skalkotos
                       "\n".join(overwrite), width=SMALL_WIDTH):
142 023e1217 Nikos Skalkotos
                continue
143 023e1217 Nikos Skalkotos
144 023e1217 Nikos Skalkotos
        gauge = GaugeOutput(d, "Image Extraction", "Extracting image...")
145 023e1217 Nikos Skalkotos
        try:
146 f5174d2c Nikos Skalkotos
            image = session['image']
147 f5174d2c Nikos Skalkotos
            out = image.out
148 023e1217 Nikos Skalkotos
            out.add(gauge)
149 023e1217 Nikos Skalkotos
            try:
150 023e1217 Nikos Skalkotos
                if "checksum" not in session:
151 023e1217 Nikos Skalkotos
                    md5 = MD5(out)
152 f5174d2c Nikos Skalkotos
                    session['checksum'] = md5.compute(image.device, image.size)
153 023e1217 Nikos Skalkotos
154 023e1217 Nikos Skalkotos
                # Extract image file
155 f5174d2c Nikos Skalkotos
                image.dump(path)
156 023e1217 Nikos Skalkotos
157 023e1217 Nikos Skalkotos
                # Extract metadata file
158 3afe6b44 Nikos Skalkotos
                out.output("Extracting metadata file ...")
159 023e1217 Nikos Skalkotos
                with open('%s.meta' % path, 'w') as f:
160 023e1217 Nikos Skalkotos
                    f.write(extract_metadata_string(session))
161 023e1217 Nikos Skalkotos
                out.success('done')
162 023e1217 Nikos Skalkotos
163 023e1217 Nikos Skalkotos
                # Extract md5sum file
164 3afe6b44 Nikos Skalkotos
                out.output("Extracting md5sum file ...")
165 023e1217 Nikos Skalkotos
                md5str = "%s %s\n" % (session['checksum'], name)
166 023e1217 Nikos Skalkotos
                with open('%s.md5sum' % path, 'w') as f:
167 023e1217 Nikos Skalkotos
                    f.write(md5str)
168 023e1217 Nikos Skalkotos
                out.success("done")
169 023e1217 Nikos Skalkotos
            finally:
170 023e1217 Nikos Skalkotos
                out.remove(gauge)
171 023e1217 Nikos Skalkotos
        finally:
172 023e1217 Nikos Skalkotos
            gauge.cleanup()
173 023e1217 Nikos Skalkotos
        d.msgbox("Image file `%s' was successfully extracted!" % path,
174 023e1217 Nikos Skalkotos
                 width=SMALL_WIDTH)
175 023e1217 Nikos Skalkotos
        break
176 023e1217 Nikos Skalkotos
177 023e1217 Nikos Skalkotos
    return True
178 023e1217 Nikos Skalkotos
179 49c07ce3 Nikos Skalkotos
180 49c07ce3 Nikos Skalkotos
def _check_cloud(session, name, description, url, token):
181 49c07ce3 Nikos Skalkotos
    """Checks if the provided info for a cloud are valid"""
182 49c07ce3 Nikos Skalkotos
    d = session['dialog']
183 49c07ce3 Nikos Skalkotos
    regexp = re.compile('^[a-zA-Z0-9_]+$')
184 49c07ce3 Nikos Skalkotos
185 49c07ce3 Nikos Skalkotos
    if not re.match(regexp, name):
186 49c07ce3 Nikos Skalkotos
        d.msgbox("Allowed characters for name: [a-zA-Z0-9_]", width=WIDTH)
187 49c07ce3 Nikos Skalkotos
        return False
188 49c07ce3 Nikos Skalkotos
189 49c07ce3 Nikos Skalkotos
    if len(url) == 0:
190 49c07ce3 Nikos Skalkotos
        d.msgbox("Url cannot be empty!", width=WIDTH)
191 49c07ce3 Nikos Skalkotos
        return False
192 49c07ce3 Nikos Skalkotos
193 49c07ce3 Nikos Skalkotos
    if len(token) == 0:
194 49c07ce3 Nikos Skalkotos
        d.msgbox("Token cannot be empty!", width=WIDTH)
195 49c07ce3 Nikos Skalkotos
        return False
196 49c07ce3 Nikos Skalkotos
197 49c07ce3 Nikos Skalkotos
    if Kamaki.create_account(url, token) is None:
198 49c07ce3 Nikos Skalkotos
        d.msgbox("The cloud info you provided is not valid. Please check the "
199 49c07ce3 Nikos Skalkotos
                 "Authentication URL and the token values again!", width=WIDTH)
200 49c07ce3 Nikos Skalkotos
        return False
201 49c07ce3 Nikos Skalkotos
202 49c07ce3 Nikos Skalkotos
    return True
203 49c07ce3 Nikos Skalkotos
204 49c07ce3 Nikos Skalkotos
205 49c07ce3 Nikos Skalkotos
def add_cloud(session):
206 49c07ce3 Nikos Skalkotos
    """Add a new cloud account"""
207 49c07ce3 Nikos Skalkotos
208 49c07ce3 Nikos Skalkotos
    d = session['dialog']
209 49c07ce3 Nikos Skalkotos
210 49c07ce3 Nikos Skalkotos
    name = ""
211 49c07ce3 Nikos Skalkotos
    description = ""
212 49c07ce3 Nikos Skalkotos
    url = ""
213 49c07ce3 Nikos Skalkotos
    token = ""
214 49c07ce3 Nikos Skalkotos
215 49c07ce3 Nikos Skalkotos
    while 1:
216 49c07ce3 Nikos Skalkotos
        fields = [
217 49c07ce3 Nikos Skalkotos
            ("Name:", name, 60),
218 49c07ce3 Nikos Skalkotos
            ("Description (optional): ", description, 80),
219 49c07ce3 Nikos Skalkotos
            ("Authentication URL: ", url, 200),
220 49c07ce3 Nikos Skalkotos
            ("Token:", token, 100)]
221 49c07ce3 Nikos Skalkotos
222 49c07ce3 Nikos Skalkotos
        (code, output) = d.form("Add a new cloud account:", height=13,
223 49c07ce3 Nikos Skalkotos
                                width=WIDTH, form_height=4, fields=fields)
224 49c07ce3 Nikos Skalkotos
225 49c07ce3 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
226 49c07ce3 Nikos Skalkotos
            return False
227 49c07ce3 Nikos Skalkotos
228 49c07ce3 Nikos Skalkotos
        name, description, url, token = output
229 49c07ce3 Nikos Skalkotos
230 49c07ce3 Nikos Skalkotos
        name = name.strip()
231 49c07ce3 Nikos Skalkotos
        description = description.strip()
232 49c07ce3 Nikos Skalkotos
        url = url.strip()
233 49c07ce3 Nikos Skalkotos
        token = token.strip()
234 49c07ce3 Nikos Skalkotos
235 49c07ce3 Nikos Skalkotos
        if _check_cloud(session, name, description, url, token):
236 49c07ce3 Nikos Skalkotos
            if name in Kamaki.get_clouds().keys():
237 49c07ce3 Nikos Skalkotos
                d.msgbox("A cloud with name `%s' already exists. If you want "
238 49c07ce3 Nikos Skalkotos
                         "to edit the existing cloud account, use the edit "
239 49c07ce3 Nikos Skalkotos
                         "menu." % name, width=WIDTH)
240 49c07ce3 Nikos Skalkotos
            else:
241 49c07ce3 Nikos Skalkotos
                Kamaki.save_cloud(name, url, token, description)
242 49c07ce3 Nikos Skalkotos
                break
243 49c07ce3 Nikos Skalkotos
244 49c07ce3 Nikos Skalkotos
        continue
245 49c07ce3 Nikos Skalkotos
246 49c07ce3 Nikos Skalkotos
    return True
247 49c07ce3 Nikos Skalkotos
248 49c07ce3 Nikos Skalkotos
249 49c07ce3 Nikos Skalkotos
def edit_cloud(session, name):
250 49c07ce3 Nikos Skalkotos
    """Edit a cloud account"""
251 49c07ce3 Nikos Skalkotos
252 49c07ce3 Nikos Skalkotos
    info = Kamaki.get_cloud_by_name(name)
253 49c07ce3 Nikos Skalkotos
254 49c07ce3 Nikos Skalkotos
    assert info, "Cloud: `%s' does not exist" % name
255 49c07ce3 Nikos Skalkotos
256 49c07ce3 Nikos Skalkotos
    description = info['description'] if 'description' in info else ""
257 5a380da9 Nikos Skalkotos
    url = info['url'] if 'url' in info else ""
258 5a380da9 Nikos Skalkotos
    token = info['token'] if 'token' in info else ""
259 49c07ce3 Nikos Skalkotos
260 49c07ce3 Nikos Skalkotos
    d = session['dialog']
261 49c07ce3 Nikos Skalkotos
262 49c07ce3 Nikos Skalkotos
    while 1:
263 49c07ce3 Nikos Skalkotos
        fields = [
264 49c07ce3 Nikos Skalkotos
            ("Description (optional): ", description, 80),
265 49c07ce3 Nikos Skalkotos
            ("Authentication URL: ", url, 200),
266 49c07ce3 Nikos Skalkotos
            ("Token:", token, 100)]
267 49c07ce3 Nikos Skalkotos
268 49c07ce3 Nikos Skalkotos
        (code, output) = d.form("Edit cloud account: `%s'" % name, height=13,
269 49c07ce3 Nikos Skalkotos
                                width=WIDTH, form_height=3, fields=fields)
270 49c07ce3 Nikos Skalkotos
271 49c07ce3 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
272 49c07ce3 Nikos Skalkotos
            return False
273 49c07ce3 Nikos Skalkotos
274 49c07ce3 Nikos Skalkotos
        description, url, token = output
275 49c07ce3 Nikos Skalkotos
276 49c07ce3 Nikos Skalkotos
        description = description.strip()
277 49c07ce3 Nikos Skalkotos
        url = url.strip()
278 49c07ce3 Nikos Skalkotos
        token = token.strip()
279 49c07ce3 Nikos Skalkotos
280 49c07ce3 Nikos Skalkotos
        if _check_cloud(session, name, description, url, token):
281 49c07ce3 Nikos Skalkotos
            Kamaki.save_cloud(name, url, token, description)
282 49c07ce3 Nikos Skalkotos
            break
283 49c07ce3 Nikos Skalkotos
284 49c07ce3 Nikos Skalkotos
        continue
285 49c07ce3 Nikos Skalkotos
286 49c07ce3 Nikos Skalkotos
    return True
287 49c07ce3 Nikos Skalkotos
288 023e1217 Nikos Skalkotos
# vim: set sta sts=4 shiftwidth=4 sw=4 et ai :