Revision 3f70f242 image_creator/disk.py

b/image_creator/disk.py
100 100
        the Disk instance.
101 101
        """
102 102

  
103
        puts("Examining source media `%s'" % self.source)
104
        with indent(4):
105
            sourcedev = self.source
106
            mode = os.stat(self.source).st_mode
107
            if stat.S_ISDIR(mode):
108
                puts(colored.green('Looks like a directory'))
109
                return self._losetup(self._dir_to_disk())
110
            elif stat.S_ISREG(mode):
111
                puts(colored.green('Looks like an image file'))
112
                sourcedev = self._losetup(self.source)
113
            elif not stat.S_ISBLK(mode):
114
                raise ValueError("Invalid media source. Only block devices, "
115
                                "regular files and directories are supported.")
116
            else:
117
                puts(colored.green('Looks like a block device'))
118
            #puts()
103
        puts("Examining source media `%s'..." % self.source, False)
104
        sourcedev = self.source
105
        mode = os.stat(self.source).st_mode
106
        if stat.S_ISDIR(mode):
107
            puts(colored.green('looks like a directory'))
108
            return self._losetup(self._dir_to_disk())
109
        elif stat.S_ISREG(mode):
110
            puts(colored.green('looks like an image file'))
111
            sourcedev = self._losetup(self.source)
112
        elif not stat.S_ISBLK(mode):
113
            raise ValueError("Invalid media source. Only block devices, "
114
                            "regular files and directories are supported.")
115
        else:
116
            puts(colored.green('looks like a block device'))
119 117

  
120 118
        # Take a snapshot and return it to the user
121
        puts("Snapshotting media source")
122
        with indent(4):
123
            size = blockdev('--getsize', sourcedev)
124
            cowfd, cow = tempfile.mkstemp()
125
            os.close(cowfd)
126
            self._add_cleanup(os.unlink, cow)
127
            # Create 1G cow sparse file
128
            dd('if=/dev/null', 'of=%s' % cow, 'bs=1k', \
129
                                            'seek=%d' % (1024 * 1024))
130
            cowdev = self._losetup(cow)
131
    
132
            snapshot = uuid.uuid4().hex
133
            tablefd, table = tempfile.mkstemp()
134
            try:
135
                os.write(tablefd, "0 %d snapshot %s %s n 8" % \
136
                                            (int(size), sourcedev, cowdev))
137
                dmsetup('create', snapshot, table)
138
                self._add_cleanup(dmsetup, 'remove', snapshot)
139
                # Sometimes dmsetup remove fails with Device or resource busy,
140
                # although everything is cleaned up and the snapshot is not
141
                # used by anyone. Add a 2 seconds delay to be on the safe side.
142
                self._add_cleanup(time.sleep, 2)
143

  
144
            finally:
145
                os.unlink(table)
146
            puts(colored.green('Done'))
147
        # puts()
119
        puts("Snapshotting media source...", False)
120
        size = blockdev('--getsize', sourcedev)
121
        cowfd, cow = tempfile.mkstemp()
122
        os.close(cowfd)
123
        self._add_cleanup(os.unlink, cow)
124
        # Create 1G cow sparse file
125
        dd('if=/dev/null', 'of=%s' % cow, 'bs=1k', \
126
                                        'seek=%d' % (1024 * 1024))
127
        cowdev = self._losetup(cow)
128

  
129
        snapshot = uuid.uuid4().hex
130
        tablefd, table = tempfile.mkstemp()
131
        try:
132
            os.write(tablefd, "0 %d snapshot %s %s n 8" % \
133
                                        (int(size), sourcedev, cowdev))
134
            dmsetup('create', snapshot, table)
135
            self._add_cleanup(dmsetup, 'remove', snapshot)
136
            # Sometimes dmsetup remove fails with Device or resource busy,
137
            # although everything is cleaned up and the snapshot is not
138
            # used by anyone. Add a 2 seconds delay to be on the safe side.
139
            self._add_cleanup(time.sleep, 2)
140

  
141
        finally:
142
            os.unlink(table)
143
        puts(colored.green('done'))
148 144
        new_device = DiskDevice("/dev/mapper/%s" % snapshot)
149 145
        self._devices.append(new_device)
150 146
        new_device.enable()
......
181 177
    def enable(self):
182 178
        """Enable a newly created DiskDevice"""
183 179
        self.progressbar = progress_generator("Launching helper VM: ")
184
        with indent(4):
185
            self.progressbar.next()
186
            eh = self.g.set_event_callback(self.progress_callback,
187
                                                        guestfs.EVENT_PROGRESS)
188
            self.g.launch()
189
            self.guestfs_enabled = True
190
            self.g.delete_event_callback(eh)
191
            if self.progressbar is not None:
192
                self.progressbar.send(100)
193
                self.progressbar = None
194
            puts(colored.green('Done'))
195

  
196
        puts('Inspecting Operating System')
197
        with indent(4):
198
            roots = self.g.inspect_os()
199
            if len(roots) == 0:
200
                raise FatalError("No operating system found")
201
            if len(roots) > 1:
202
                raise FatalError("Multiple operating systems found."
203
                                "We only support images with one filesystem.")
204
            self.root = roots[0]
205
            self.ostype = self.g.inspect_get_type(self.root)
206
            self.distro = self.g.inspect_get_distro(self.root)
207
            puts(colored.green('Found a %s system' % self.distro))
208
        puts()
180
        self.progressbar.next()
181
        eh = self.g.set_event_callback(self.progress_callback,
182
                                                    guestfs.EVENT_PROGRESS)
183
        self.g.launch()
184
        self.guestfs_enabled = True
185
        self.g.delete_event_callback(eh)
186
        if self.progressbar is not None:
187
            self.progressbar.send(100)
188
            self.progressbar = None
189

  
190
        puts('Inspecting Operating System...', False)
191
        roots = self.g.inspect_os()
192
        if len(roots) == 0:
193
            raise FatalError("No operating system found")
194
        if len(roots) > 1:
195
            raise FatalError("Multiple operating systems found."
196
                            "We only support images with one filesystem.")
197
        self.root = roots[0]
198
        self.ostype = self.g.inspect_get_type(self.root)
199
        self.distro = self.g.inspect_get_distro(self.root)
200
        puts(colored.green('found a %s system' % self.distro))
209 201

  
210 202
    def destroy(self):
211 203
        """Destroy this DiskDevice instance."""
......
257 249
        disk and then updating the partition table. The new disk size
258 250
        (in bytes) is returned.
259 251
        """
260
        puts("Shrinking image (this may take a while)")
261
        
252
        puts("Shrinking image (this may take a while)...", False)
253

  
262 254
        dev = self.g.part_to_dev(self.root)
263 255
        parttype = self.g.part_get_parttype(dev)
264 256
        if parttype != 'msdos':
......
277 269
            warn("Don't know how to resize %s partitions." % vfs_type)
278 270
            return
279 271

  
280
        with indent(4):
281
            self.g.e2fsck_f(part_dev)
282
            self.g.resize2fs_M(part_dev)
272
        self.g.e2fsck_f(part_dev)
273
        self.g.resize2fs_M(part_dev)
274

  
275
        output = self.g.tune2fs_l(part_dev)
276
        block_size = int(
277
            filter(lambda x: x[0] == 'Block size', output)[0][1])
278
        block_cnt = int(
279
            filter(lambda x: x[0] == 'Block count', output)[0][1])
283 280

  
284
            output = self.g.tune2fs_l(part_dev)
285
            block_size = int(
286
                filter(lambda x: x[0] == 'Block size', output)[0][1])
287
            block_cnt = int(
288
                filter(lambda x: x[0] == 'Block count', output)[0][1])
281
        sector_size = self.g.blockdev_getss(dev)
289 282

  
290
            sector_size = self.g.blockdev_getss(dev)
283
        start = last_partition['part_start'] / sector_size
284
        end = start + (block_size * block_cnt) / sector_size - 1
291 285

  
292
            start = last_partition['part_start'] / sector_size
293
            end = start + (block_size * block_cnt) / sector_size - 1
286
        self.g.part_del(dev, last_partition['part_num'])
287
        self.g.part_add(dev, 'p', start, end)
294 288

  
295
            self.g.part_del(dev, last_partition['part_num'])
296
            self.g.part_add(dev, 'p', start, end)
289
        new_size = (end + 1) * sector_size
290
        puts(colored.green("new image size is %dMB\n" % (new_size // 2 ** 20)))
297 291

  
298
            new_size = (end + 1) * sector_size
299
            puts("  New image size is %dMB\n" % (new_size // 2 ** 20))
300 292
        return new_size
301 293

  
302 294
    def size(self):

Also available in: Unified diff