Revision e108efd2 image_creator/disk.py

b/image_creator/disk.py
165 165
    def __init__(self, device, bootable=True):
166 166
        """Create a new DiskDevice."""
167 167

  
168
        self.device = device
168
        self.real_device = device
169 169
        self.bootable = bootable
170 170
        self.progress_bar = None
171
        self.guestfs_device = None
172
        self.size = None
173
        self.parttype = None
171 174

  
172 175
        self.g = guestfs.GuestFS()
173
        self.g.add_drive_opts(self.device, readonly=0)
176
        self.g.add_drive_opts(self.real_device, readonly=0)
174 177

  
175 178
        #self.g.set_trace(1)
176 179
        #self.g.set_verbose(1)
......
200 203
            raise FatalError("Multiple operating systems found."
201 204
                            "We only support images with one filesystem.")
202 205
        self.root = roots[0]
203
        self.gdev = self.g.part_to_dev(self.root)
204
        self.parttype = self.g.part_get_parttype(self.gdev)
206
        self.guestfs_device = self.g.part_to_dev(self.root)
207
        self.size = self.g.blockdev_getsize64(self.guestfs_device)
208
        self.parttype = self.g.part_get_parttype(self.guestfs_device)
205 209

  
206 210
        self.ostype = self.g.inspect_get_type(self.root)
207 211
        self.distro = self.g.inspect_get_distro(self.root)
......
256 260
        This is accomplished by shrinking the last filesystem in the
257 261
        disk and then updating the partition table. The new disk size
258 262
        (in bytes) is returned.
263

  
264
        ATTENTION: make sure unmount is called before shrink
259 265
        """
260 266
        output("Shrinking image (this may take a while)...", False)
261 267

  
......
263 269
            raise FatalError("You have a %s partition table. "
264 270
                "Only msdos and gpt partitions are supported" % self.parttype)
265 271

  
266
        last_partition = self.g.part_list(self.gdev)[-1]
272
        last_partition = self.g.part_list(self.guestfs_device)[-1]
267 273

  
268 274
        if last_partition['part_num'] > 4:
269 275
            raise FatalError("This disk contains logical partitions. "
270 276
                "Only primary partitions are supported.")
271 277

  
272
        part_dev = "%s%d" % (self.gdev, last_partition['part_num'])
278
        part_dev = "%s%d" % (self.guestfs_device, last_partition['part_num'])
273 279
        fs_type = self.g.vfs_type(part_dev)
274 280
        if not re.match("ext[234]", fs_type):
275 281
            warn("Don't know how to resize %s partitions." % vfs_type)
......
284 290
        block_cnt = int(
285 291
            filter(lambda x: x[0] == 'Block count', out)[0][1])
286 292

  
287
        sector_size = self.g.blockdev_getss(self.gdev)
293
        sector_size = self.g.blockdev_getss(self.guestfs_device)
288 294

  
289 295
        start = last_partition['part_start'] / sector_size
290 296
        end = start + (block_size * block_cnt) / sector_size - 1
291 297

  
292
        self.g.part_del(self.gdev, last_partition['part_num'])
293
        self.g.part_add(self.gdev, 'p', start, end)
298
        self.g.part_del(self.guestfs_device, last_partition['part_num'])
299
        self.g.part_add(self.guestfs_device, 'p', start, end)
294 300

  
295
        new_size = (end + 1) * sector_size
301
        self.size = (end + 1) * sector_size
296 302
        success("new image size is %dMB" %
297
                            ((new_size + 2 ** 20 - 1) // 2 ** 20))
303
                            ((self.size + 2 ** 20 - 1) // 2 ** 20))
298 304

  
299 305
        if self.parttype == 'gpt':
300
            ptable = GPTPartitionTable(self.device)
301
            return ptable.shrink(new_size)
302

  
303
        return new_size
306
            ptable = GPTPartitionTable(self.real_device)
307
            self.size = ptable.shrink(self.size)
304 308

  
305
    def size(self):
306
        """Returns the "payload" size of the device.
307

  
308
        The size returned by this method is the size of the space occupied by
309
        the partitions (including the space before the first partition).
310
        """
311

  
312
        if self.parttype == 'msdos':
313
            dev = self.g.part_to_dev(self.root)
314
            last = self.g.part_list(dev)[-1]
315
            return last['part_end'] + 1
316
        elif self.parttype == 'gpt':
317
            ptable = GPTPartitionTable(self.device)
318
            return ptable.size()
319
        else:
320
            raise FatalError("Unsupported partition table type: %s" % parttype)
309
        return self.size
321 310

  
322 311
    def dump(self, outfile):
323 312
        """Dumps the content of device into a file.
......
326 315
        partition table. Empty space in the end of the device will be ignored.
327 316
        """
328 317
        blocksize = 2 ** 22  # 4MB
329
        size = self.size()
330
        progress_size = (size + 2 ** 20 - 1) // 2 ** 20  # in MB
318
        progress_size = (self.size + 2 ** 20 - 1) // 2 ** 20  # in MB
331 319
        progressbar = progress("Dumping image file: ", 'mb')
332 320
        progressbar.max = progress_size
333
        source = open(self.device, "r")
334
        try:
335
            dest = open(outfile, "w")
336
            try:
337
                left = size
321
        with open(self.real_device, 'r') as source:
322
            with open(outfile, "w") as dest:
323
                left = self.size
338 324
                offset = 0
339 325
                progressbar.next()
340 326
                while left > 0:
......
343 329
                                                                        length)
344 330
                    offset += sent
345 331
                    left -= sent
346
                    progressbar.goto((size - left) // 2 ** 20)
347
            finally:
348
                dest.close()
349
        finally:
350
            source.close()
332
                    progressbar.goto((self.size - left) // 2 ** 20)
351 333
        output("\rDumping image file...\033[K", False)
352 334
        success('image file %s was successfully created' % outfile)
353 335

  

Also available in: Unified diff