Revision 71b0ab28

b/image_creator/dialog_menu.py
38 38
import StringIO
39 39

  
40 40
from image_creator import __version__ as version
41
from image_creator.util import MD5
41
from image_creator.util import MD5, FatalError
42 42
from image_creator.output.dialog import GaugeOutput, InfoBoxOutput
43 43
from image_creator.kamaki_wrapper import Kamaki, ClientError
44 44
from image_creator.help import get_help_file
......
568 568
            try:
569 569
                image.out.add(infobox)
570 570
                try:
571
                    image.mount(readonly=False)
572
                    try:
573
                        err = "Unable to execute the system preparation " \
574
                            "tasks. Couldn't mount the media%s."
575
                        title = "System Preparation"
576
                        if not image.mounted:
577
                            d.msgbox(err % "", title=title, width=SMALL_WIDTH)
578
                            return
579
                        elif image.mounted_ro:
580
                            d.msgbox(err % " read-write", title=title,
581
                                     width=SMALL_WIDTH)
582
                            return
583

  
584
                        # The checksum is invalid. We have mounted the image rw
585
                        if 'checksum' in session:
586
                            del session['checksum']
587

  
588
                        # Monitor the metadata changes during syspreps
589
                        with MetadataMonitor(session, image.os.meta):
571
                    # The checksum is invalid. We have mounted the image rw
572
                    if 'checksum' in session:
573
                        del session['checksum']
574

  
575
                    # Monitor the metadata changes during syspreps
576
                    with MetadataMonitor(session, image.os.meta):
577
                        try:
590 578
                            image.os.do_sysprep()
591 579
                            infobox.finalize()
592

  
593
                    finally:
594
                        image.umount()
580
                        except FatalError as e:
581
                            title = "System Preparation"
582
                            d.msgbox("System Preparation failed: %s" % e,
583
                                     title=title, width=SMALL_WIDTH)
595 584
                finally:
596 585
                    image.out.remove(infobox)
597 586
            finally:
b/image_creator/dialog_wizard.py
266 266
        out.clear()
267 267

  
268 268
        #Sysprep
269
        image.mount(False)
270
        err_msg = "Unable to execute the system preparation tasks."
271
        if not image.mounted:
272
            raise FatalError("%s Couldn't mount the media." % err_msg)
273
        elif image.mounted_ro:
274
            raise FatalError("%s Couldn't mount the media read-write."
275
                             % err_msg)
276 269
        image.os.do_sysprep()
277 270
        metadata = image.os.meta
278
        image.umount()
279 271

  
280 272
        #Shrink
281 273
        size = image.shrink()
b/image_creator/image.py
53 53
        self.progress_bar = None
54 54
        self.guestfs_device = None
55 55
        self.size = 0
56
        self.mounted = False
57
        self.mounted_ro = False
58 56

  
59 57
        self.g = guestfs.GuestFS()
60 58
        self.g.add_drive_opts(self.device, readonly=0, format="raw")
......
120 118
        if not self.guestfs_enabled:
121 119
            self.enable()
122 120

  
123
        if not self.mounted:
124
            do_unmount = True
125
            self.mount(readonly=True)
126
        else:
127
            do_unmount = False
128

  
129
        try:
130
            cls = os_cls(self.distro, self.ostype)
131
            self._os = cls(self.root, self.g, self.out)
121
        cls = os_cls(self.distro, self.ostype)
122
        self._os = cls(self.root, self.g, self.out)
132 123

  
133
        finally:
134
            if do_unmount:
135
                self.umount()
124
        self._os.collect_metadata()
136 125

  
137 126
        return self._os
138 127

  
......
156 145
#
157 146
#        self.progressbar.goto((position * 100) // total)
158 147

  
159
    def mount(self, readonly=False):
160
        """Mount all disk partitions in a correct order."""
161

  
162
        msg = "Mounting the media%s ..." % (" read-only" if readonly else "")
163
        self.out.output(msg, False)
164

  
165
        #If something goes wrong when mounting rw, remount the filesystem ro
166
        remount_ro = False
167
        rw_mpoints = ('/', '/etc', '/root', '/home', '/var')
168

  
169
        # Sort the keys to mount the fs in a correct order.
170
        # / should be mounted befor /boot, etc
171
        def compare(a, b):
172
            if len(a[0]) > len(b[0]):
173
                return 1
174
            elif len(a[0]) == len(b[0]):
175
                return 0
176
            else:
177
                return -1
178
        mps = self.g.inspect_get_mountpoints(self.root)
179
        mps.sort(compare)
180

  
181
        mopts = 'ro' if readonly else 'rw'
182
        for mp, dev in mps:
183
            if self.ostype == 'freebsd':
184
                # libguestfs can't handle correct freebsd partitions on GUID
185
                # Partition Table. We have to do the translation to linux
186
                # device names ourselves
187
                m = re.match('^/dev/((?:ada)|(?:vtbd))(\d+)p(\d+)$', dev)
188
                if m:
189
                    m2 = int(m.group(2))
190
                    m3 = int(m.group(3))
191
                    dev = '/dev/sd%c%d' % (chr(ord('a') + m2), m3)
192
            try:
193
                self.g.mount_options(mopts, dev, mp)
194
            except RuntimeError as msg:
195
                if self.ostype == 'freebsd':
196
                    freebsd_mopts = "ufstype=ufs2,%s" % mopts
197
                    try:
198
                        self.g.mount_vfs(freebsd_mopts, 'ufs', dev, mp)
199
                    except RuntimeError as msg:
200
                        if readonly is False and mp in rw_mpoints:
201
                            remount_ro = True
202
                            break
203
                elif readonly is False and mp in rw_mpoints:
204
                    remount_ro = True
205
                    break
206
                else:
207
                    self.out.warn("%s (ignored)" % msg)
208
        if remount_ro:
209
            self.out.warn("Unable to mount %s read-write. "
210
                          "Remounting everything read-only..." % mp)
211
            self.umount()
212
            self.mount(True)
213
        else:
214
            self.mounted = True
215
            self.mounted_ro = readonly
216
            self.out.success("done")
217

  
218
    def umount(self):
219
        """Umount all mounted filesystems."""
220
        self.g.umount_all()
221
        self.mounted = False
222

  
223 148
    def _last_partition(self):
224 149
        """Return the last partition of the image disk"""
225 150
        if self.meta['PARTITION_TABLE'] not in 'msdos' 'gpt':
b/image_creator/main.py
221 221

  
222 222
        image = disk.get_image(snapshot)
223 223

  
224
        # If no customization is to be done, the image should be mounted ro
225
        ro = (not (options.sysprep or options.shrink) or options.print_sysprep)
226
        image.mount(ro)
227
        try:
228
            for sysprep in options.disabled_syspreps:
229
                image.os.disable_sysprep(image.os.get_sysprep_by_name(sysprep))
224
        for sysprep in options.disabled_syspreps:
225
            image.os.disable_sysprep(image.os.get_sysprep_by_name(sysprep))
230 226

  
231
            for sysprep in options.enabled_syspreps:
232
                image.os.enable_sysprep(image.os.get_sysprep_by_name(sysprep))
227
        for sysprep in options.enabled_syspreps:
228
            image.os.enable_sysprep(image.os.get_sysprep_by_name(sysprep))
233 229

  
234
            if options.print_sysprep:
235
                image.os.print_syspreps()
236
                out.output()
230
        if options.print_sysprep:
231
            image.os.print_syspreps()
232
            out.output()
233

  
234
        if options.outfile is None and not options.upload:
235
            return 0
236

  
237
        if options.sysprep:
238
            image.os.do_sysprep()
237 239

  
238
            if options.outfile is None and not options.upload:
239
                return 0
240

  
241
            if options.sysprep:
242
                err_msg = "Unable to perform the system preparation tasks. " \
243
                    "Couldn't mount the media%s. Use --no-sysprep if you " \
244
                    "don't won't to perform any system preparation task."
245
                if not image.mounted:
246
                    raise FatalError(err_msg % "")
247
                elif image.mounted_ro:
248
                    raise FatalError(err_msg % " read-write")
249
                image.os.do_sysprep()
250

  
251
            metadata = image.os.meta
252
        finally:
253
            image.umount()
240
        metadata = image.os.meta
254 241

  
255 242
        size = options.shrink and image.shrink() or image.size
256 243
        metadata.update(image.meta)
b/image_creator/os_type/__init__.py
77 77
        self.root = rootdev
78 78
        self.g = ghandler
79 79
        self.out = output
80

  
81
        # Collect metadata about the OS
82 80
        self.meta = {}
81

  
82
    def collect_metadata(self):
83
        """Collect metadata about the OS"""
84

  
85
        try:
86
            if not self.mount(readonly=True):
87
                raise FatalError("Unable to mount the media read-only")
88

  
89
            self.out.output('Collecting image metadata ...', False)
90
            self._do_collect_metadata()
91
            self.out.success('done')
92
        finally:
93
            self.umount()
94

  
95
    def _do_collect_metadata(self):
96

  
83 97
        self.meta['ROOT_PARTITION'] = "%d" % self.g.part_to_partnum(self.root)
84 98
        self.meta['OSFAMILY'] = self.g.inspect_get_type(self.root)
85 99
        self.meta['OS'] = self.g.inspect_get_distro(self.root)
......
212 226
    def do_sysprep(self):
213 227
        """Prepere system for image creation."""
214 228

  
215
        self.out.output('Preparing system for image creation:')
229
        try:
230
            if not self.mount(readonly=False):
231
                raise FatalError("Unable to mount the media read-write")
232

  
233
            self.out.output('Preparing system for image creation:')
234

  
235
            tasks = self.list_syspreps()
236
            enabled = filter(lambda x: x.enabled, tasks)
237

  
238
            size = len(enabled)
239
            cnt = 0
240
            for task in enabled:
241
                cnt += 1
242
                self.out.output(('(%d/%d)' % (cnt, size)).ljust(7), False)
243
                task()
244
                setattr(task.im_func, 'executed', True)
245
            self.out.output()
246
        finally:
247
            self.umount()
248

  
249
    def _do_mount(self, readonly):
250
        try:
251
            self.g.mount_options('ro' if readonly else 'rw', self.root, '/')
252
        except RuntimeError as msg:
253
            self.out.warn("unable to mount the root partition: %s" % msg)
254
            return False
255

  
256
        return True
257

  
258
    def mount(self, readonly=False):
259
        """Mount image."""
260

  
261
        if getattr(self, "mounted", False):
262
            return True
263

  
264
        mount_type = 'read-only' if readonly else 'read-write'
265
        self.out.output("Mount the media %s ..." % mount_type, False)
266

  
267
        if not self._do_mount(readonly):
268
            return False
216 269

  
217
        tasks = self.list_syspreps()
218
        enabled = filter(lambda x: x.enabled, tasks)
270
        self.mounted = True
271
        self.out.success('done')
272
        return True
219 273

  
220
        size = len(enabled)
221
        cnt = 0
222
        for task in enabled:
223
            cnt += 1
224
            self.out.output(('(%d/%d)' % (cnt, size)).ljust(7), False)
225
            task()
226
            setattr(task.im_func, 'executed', True)
227
        self.out.output()
274
    def umount(self):
275
        """Umount all mounted filesystems."""
276
        self.g.umount_all()
277
        self.mounted = False
228 278

  
229 279
# vim: set sta sts=4 shiftwidth=4 sw=4 et ai :
b/image_creator/os_type/freebsd.py
41 41
    def __init__(self, rootdev, ghandler, output):
42 42
        super(Freebsd, self).__init__(rootdev, ghandler, output)
43 43

  
44
    def _do_collect_metadata(self):
45

  
46
        super(Freebsd, self)._do_collect_metadata()
44 47
        self.meta["USERS"] = " ".join(self._get_passworded_users())
45 48

  
46 49
        #The original product name key is long and ugly
......
72 75

  
73 76
        return users
74 77

  
78
    def _do_mount(self, readonly):
79
        """Mount partitions in the correct order"""
80

  
81
        critical_mpoints = ('/', '/etc', '/root', '/home', '/var')
82

  
83
        # libguestfs can't handle correct freebsd partitions on GUID
84
        # Partition Table. We have to do the translation to linux
85
        # device names ourselves
86
        guid_device = re.compile('^/dev/((?:ada)|(?:vtbd))(\d+)p(\d+)$')
87

  
88
        mopts = "ufstype=ufs2,%s" % ('ro' if readonly else 'rw')
89
        for mp, dev in self._mountpoints():
90
            match = guid_device.match(dev)
91
            if match:
92
                m2 = int(match.group(2))
93
                m3 = int(match.group(3))
94
                dev = '/dev/sd%c%d' % (chr(ord('a') + m2), m3)
95
            try:
96
                self.g.mount_vfs(mopts, 'ufs', dev, mp)
97
            except RuntimeError as msg:
98
                if mp in critical_mpoints:
99
                    self.out.warn('unable to mount %s. Reason: %s' % (mp, msg))
100
                    return False
101
                else:
102
                    self.out.warn('%s (ignored)' % msg)
103

  
104
        return True
105

  
75 106
    @sysprep()
76 107
    def cleanup_password(self, print_header=True):
77 108
        """Remove all passwords and lock all user accounts"""
b/image_creator/os_type/linux.py
44 44
        self._uuid = dict()
45 45
        self._persistent = re.compile('/dev/[hsv]d[a-z][1-9]*')
46 46

  
47
    def _do_collect_metadata(self):
48
        """Collect metadata about the OS"""
49

  
50
        super(Linux, self)._do_collect_metadata()
47 51
        self.meta["USERS"] = " ".join(self._get_passworded_users())
48 52

  
49 53
        # Delete the USERS metadata if empty
b/image_creator/os_type/ubuntu.py
39 39
    def __init__(self, rootdev, ghandler, output):
40 40
        super(Ubuntu, self).__init__(rootdev, ghandler, output)
41 41

  
42
    def _do_collect_metadata(self):
43
        """Collect metadata about the OS"""
44

  
45
        super(Ubuntu, self)._do_collect_metadata()
42 46
        apps = self.g.inspect_list_applications(self.root)
43 47
        for app in apps:
44 48
            if app['app_name'] == 'kubuntu-desktop':
b/image_creator/os_type/unix.py
47 47
        '.kamaki.history'
48 48
    ]
49 49

  
50
    def __init__(self, rootdev, ghandler, output):
51
        super(Unix, self).__init__(rootdev, ghandler, output)
50
    def _mountpoints(self):
51
        """Return mountpoints in the correct order.
52
        / should be mounted before /boot or /usr, /usr befor /usr/bin ...
53
        """
54
        mps = self.g.inspect_get_mountpoints(self.root)
55

  
56
        def compare(a, b):
57
            if len(a[0]) > len(b[0]):
58
                return 1
59
            elif len(a[0]) == len(b[0]):
60
                return 0
61
            else:
62
                return -1
63
        mps.sort(compare)
64

  
65
        for mp in mps:
66
            yield mp
67

  
68
    def _do_mount(self, readonly):
69
        """Mount partitions in the correct order"""
70

  
71
        critical_mpoints = ('/', '/etc', '/root', '/home', '/var')
72

  
73
        mopts = 'ro' if readonly else 'rw'
74
        for mp, dev in self._mountpoints():
75
            try:
76
                self.g.mount_options(mopts, dev, mp)
77
            except RuntimeError as msg:
78
                if mp in critical_mpoint:
79
                    self.out.warn('unable to mount %s. Reason: %s' % (mp, msg))
80
                    return False
81
                else:
82
                    self.out.warn('%s (ignored)' % msg)
83

  
84
        return True
52 85

  
53 86
    @sysprep()
54 87
    def cleanup_cache(self, print_header=True):
b/image_creator/version.py
1 1
__version__ = "0.3next"
2 2
__version_info__ = ['0', '3next']
3
__version_vcs_info__ = {'branch': 'develop',
4
 'revid': '9c060ab',
5
 'revno': 297,
6
 'toplevel': '/home/skalkoto/src/snf-image-creator'}
3
__version_vcs_info__ = {
4
    'branch': 'develop',
5
    'revid': '9c060ab',
6
    'revno': 297,
7
    'toplevel': '/home/skalkoto/src/snf-image-creator'}
7 8
__version_user_info__ = "skalkoto@darkstar.admin.grnet.gr"

Also available in: Unified diff