root / image_creator / disk.py @ d57775d4
History | View | Annotate | Download (3 kB)
1 | d57775d4 | Nikos Skalkotos | #!/usr/bin/env python
|
---|---|---|---|
2 | d57775d4 | Nikos Skalkotos | |
3 | d57775d4 | Nikos Skalkotos | import losetup |
4 | d57775d4 | Nikos Skalkotos | import stat |
5 | d57775d4 | Nikos Skalkotos | import os |
6 | d57775d4 | Nikos Skalkotos | import tempfile |
7 | d57775d4 | Nikos Skalkotos | import uuid |
8 | d57775d4 | Nikos Skalkotos | import re |
9 | d57775d4 | Nikos Skalkotos | from pbs import dmsetup |
10 | d57775d4 | Nikos Skalkotos | from pbs import blockdev |
11 | d57775d4 | Nikos Skalkotos | from pbs import dd |
12 | d57775d4 | Nikos Skalkotos | from pbs import kpartx |
13 | d57775d4 | Nikos Skalkotos | from pbs import mount |
14 | d57775d4 | Nikos Skalkotos | from pbs import umount |
15 | d57775d4 | Nikos Skalkotos | |
16 | d57775d4 | Nikos Skalkotos | class Disk(object): |
17 | d57775d4 | Nikos Skalkotos | |
18 | d57775d4 | Nikos Skalkotos | def __init__(self, source): |
19 | d57775d4 | Nikos Skalkotos | self._cleanup_jobs = []
|
20 | d57775d4 | Nikos Skalkotos | self._devices = []
|
21 | d57775d4 | Nikos Skalkotos | self.source = source
|
22 | d57775d4 | Nikos Skalkotos | |
23 | d57775d4 | Nikos Skalkotos | def _add_cleanup(self, job, *args): |
24 | d57775d4 | Nikos Skalkotos | self._cleanup_jobs.append((job, args))
|
25 | d57775d4 | Nikos Skalkotos | |
26 | d57775d4 | Nikos Skalkotos | def _losetup(self, fname): |
27 | d57775d4 | Nikos Skalkotos | loop = losetup.find_unused_loop_device() |
28 | d57775d4 | Nikos Skalkotos | loop.mount(fname) |
29 | d57775d4 | Nikos Skalkotos | self._add_cleanup(loop.unmount)
|
30 | d57775d4 | Nikos Skalkotos | return loop.device
|
31 | d57775d4 | Nikos Skalkotos | |
32 | d57775d4 | Nikos Skalkotos | def _dir_to_disk(self): |
33 | d57775d4 | Nikos Skalkotos | raise NotImplementedError |
34 | d57775d4 | Nikos Skalkotos | |
35 | d57775d4 | Nikos Skalkotos | def cleanup(self): |
36 | d57775d4 | Nikos Skalkotos | while len(self._cleanup_jobs): |
37 | d57775d4 | Nikos Skalkotos | job, args = self._cleanup_jobs.pop()
|
38 | d57775d4 | Nikos Skalkotos | job(*args) |
39 | d57775d4 | Nikos Skalkotos | |
40 | d57775d4 | Nikos Skalkotos | def get_device(self): |
41 | d57775d4 | Nikos Skalkotos | sourcedev = self.source
|
42 | d57775d4 | Nikos Skalkotos | mode = os.stat(self.source).st_mode
|
43 | d57775d4 | Nikos Skalkotos | if stat.S_ISDIR(mode):
|
44 | d57775d4 | Nikos Skalkotos | return self._losetup(self._dir_to_disk()) |
45 | d57775d4 | Nikos Skalkotos | elif stat.S_ISREG(mode):
|
46 | d57775d4 | Nikos Skalkotos | sourcedev = self._losetup(self.source) |
47 | d57775d4 | Nikos Skalkotos | elif not stat.S_ISBLK(mode): |
48 | d57775d4 | Nikos Skalkotos | raise ValueError("Value for self.source is invalid") |
49 | d57775d4 | Nikos Skalkotos | |
50 | d57775d4 | Nikos Skalkotos | # Take a snapshot and return it to the user
|
51 | d57775d4 | Nikos Skalkotos | size = blockdev('--getsize', sourcedev)
|
52 | d57775d4 | Nikos Skalkotos | cowfd, cow = tempfile.mkstemp() |
53 | d57775d4 | Nikos Skalkotos | self._add_cleanup(os.unlink, cow)
|
54 | d57775d4 | Nikos Skalkotos | dd('if=/dev/zero', 'of=%s' % cow, 'count=%d' % (1024*1024))#(int(size)/4)) |
55 | d57775d4 | Nikos Skalkotos | cowdev = self._losetup(cow)
|
56 | d57775d4 | Nikos Skalkotos | |
57 | d57775d4 | Nikos Skalkotos | snapshot = uuid.uuid4().hex |
58 | d57775d4 | Nikos Skalkotos | tablefd, table = tempfile.mkstemp() |
59 | d57775d4 | Nikos Skalkotos | try:
|
60 | d57775d4 | Nikos Skalkotos | os.write(tablefd, "0 %d snapshot %s %s n 8" % \
|
61 | d57775d4 | Nikos Skalkotos | (int(size), sourcedev, cowdev))
|
62 | d57775d4 | Nikos Skalkotos | dmsetup('create', snapshot, table)
|
63 | d57775d4 | Nikos Skalkotos | self._add_cleanup(dmsetup, 'remove', snapshot) |
64 | d57775d4 | Nikos Skalkotos | finally:
|
65 | d57775d4 | Nikos Skalkotos | os.unlink(table) |
66 | d57775d4 | Nikos Skalkotos | |
67 | d57775d4 | Nikos Skalkotos | new_device = DiskDevice(self, "/dev/mapper/%s" % snapshot) |
68 | d57775d4 | Nikos Skalkotos | self._devices.append(new_device)
|
69 | d57775d4 | Nikos Skalkotos | return new_device
|
70 | d57775d4 | Nikos Skalkotos | |
71 | d57775d4 | Nikos Skalkotos | class DiskDevice(object): |
72 | d57775d4 | Nikos Skalkotos | |
73 | d57775d4 | Nikos Skalkotos | def __init__(self, disk, device): |
74 | d57775d4 | Nikos Skalkotos | self.disk = disk
|
75 | d57775d4 | Nikos Skalkotos | self.dev = device
|
76 | d57775d4 | Nikos Skalkotos | self.partitions_mapped = False |
77 | d57775d4 | Nikos Skalkotos | self.magic_number = uuid.uuid4().hex
|
78 | d57775d4 | Nikos Skalkotos | |
79 | d57775d4 | Nikos Skalkotos | def list_partitions(self): |
80 | d57775d4 | Nikos Skalkotos | output = kpartx("-l", "-p", self.magic_number, self.dev) |
81 | d57775d4 | Nikos Skalkotos | return [ "/dev/mapper/%s" % x for x in |
82 | d57775d4 | Nikos Skalkotos | re.findall('^\S+', str(output), flags=re.MULTILINE)] |
83 | d57775d4 | Nikos Skalkotos | |
84 | d57775d4 | Nikos Skalkotos | def mount(self, partition): |
85 | d57775d4 | Nikos Skalkotos | if not self.partitions_mapped: |
86 | d57775d4 | Nikos Skalkotos | kpartx("-a", "-p", self.magic_number, self.dev) |
87 | d57775d4 | Nikos Skalkotos | self.disk._cleanup_jobs.append(kpartx, "-d", "-p", |
88 | d57775d4 | Nikos Skalkotos | self.magic_number, self.dev) |
89 | d57775d4 | Nikos Skalkotos | self.partitions_mapped = True |
90 | d57775d4 | Nikos Skalkotos | |
91 | d57775d4 | Nikos Skalkotos | targetfd, target = tempfile.mkdtemp() |
92 | d57775d4 | Nikos Skalkotos | try:
|
93 | d57775d4 | Nikos Skalkotos | mount(dev, partition) |
94 | d57775d4 | Nikos Skalkotos | except:
|
95 | d57775d4 | Nikos Skalkotos | os.rmdir(table) |
96 | d57775d4 | Nikos Skalkotos | raise
|
97 | d57775d4 | Nikos Skalkotos | return target
|
98 | d57775d4 | Nikos Skalkotos | |
99 | d57775d4 | Nikos Skalkotos | def unmount(self, partition): |
100 | d57775d4 | Nikos Skalkotos | umount(target) |
101 | d57775d4 | Nikos Skalkotos | |
102 | d57775d4 | Nikos Skalkotos | mode = os.stat(self.source).st_mode
|
103 | d57775d4 | Nikos Skalkotos | if stat.S_ISDIR(mode):
|
104 | d57775d4 | Nikos Skalkotos | os.rmdir(target) |
105 | d57775d4 | Nikos Skalkotos | |
106 | d57775d4 | Nikos Skalkotos | # vim: set sta sts=4 shiftwidth=4 sw=4 et ai : |