/[smeserver]/cdrom.image/sme9/updates/storage/formats/disklabel.py
ViewVC logotype

Annotation of /cdrom.image/sme9/updates/storage/formats/disklabel.py

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.1 - (hide annotations) (download) (as text)
Sun Oct 20 23:12:54 2013 UTC (10 years, 8 months ago) by charliebrady
Branch: MAIN
Content type: text/x-python
Add devicelibs and formats subdirectories of storage, and contained .py
files, in preparation to modifying to allow degraded RAID install.

1 charliebrady 1.1 # disklabel.py
2     # Device format classes for anaconda's storage configuration module.
3     #
4     # Copyright (C) 2009 Red Hat, Inc.
5     #
6     # This copyrighted material is made available to anyone wishing to use,
7     # modify, copy, or redistribute it subject to the terms and conditions of
8     # the GNU General Public License v.2, or (at your option) any later version.
9     # This program is distributed in the hope that it will be useful, but WITHOUT
10     # ANY WARRANTY expressed or implied, including the implied warranties of
11     # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
12     # Public License for more details. You should have received a copy of the
13     # GNU General Public License along with this program; if not, write to the
14     # Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15     # 02110-1301, USA. Any Red Hat trademarks that are incorporated in the
16     # source code or documentation are not subject to the GNU General Public
17     # License and may only be used or replicated with the express permission of
18     # Red Hat, Inc.
19     #
20     # Red Hat Author(s): Dave Lehman <dlehman@redhat.com>
21     #
22    
23     import os
24     import copy
25    
26     from ..storage_log import log_method_call
27     import parted
28     import _ped
29     import platform
30     from ..errors import *
31     from ..udev import udev_settle
32     from . import DeviceFormat, register_device_format
33    
34     import gettext
35     _ = lambda x: gettext.ldgettext("anaconda", x)
36    
37     import logging
38     log = logging.getLogger("storage")
39    
40    
41     class DiskLabel(DeviceFormat):
42     """ Disklabel """
43     _type = "disklabel"
44     _name = "partition table"
45     _formattable = True # can be formatted
46     _supported = False # is supported
47    
48     def __init__(self, *args, **kwargs):
49     """ Create a DiskLabel instance.
50    
51     Keyword Arguments:
52    
53     labelType -- type of disklabel to create
54     device -- path to the underlying device
55     exists -- indicates whether this is an existing format
56    
57     """
58     log_method_call(self, *args, **kwargs)
59     DeviceFormat.__init__(self, *args, **kwargs)
60    
61     if not self.exists:
62     self._labelType = kwargs.get("labelType", "msdos")
63     else:
64     self._labelType = None
65    
66     self._size = None
67    
68     self._partedDevice = None
69     self._partedDisk = None
70     self._origPartedDisk = None
71     self._alignment = None
72     self._endAlignment = None
73    
74     if self.partedDevice:
75     # set up the parted objects and raise exception on failure
76     self._origPartedDisk = self.partedDisk.duplicate()
77    
78     def __deepcopy__(self, memo):
79     """ Create a deep copy of a Disklabel instance.
80    
81     We can't do copy.deepcopy on parted objects, which is okay.
82     For these parted objects, we just do a shallow copy.
83     """
84     new = self.__class__.__new__(self.__class__)
85     memo[id(self)] = new
86     shallow_copy_attrs = ('_partedDevice', '_partedDisk', '_origPartedDisk')
87     for (attr, value) in self.__dict__.items():
88     if attr in shallow_copy_attrs:
89     setattr(new, attr, copy.copy(value))
90     else:
91     setattr(new, attr, copy.deepcopy(value, memo))
92    
93     return new
94    
95     def __str__(self):
96     s = DeviceFormat.__str__(self)
97     s += (" type = %(type)s partition count = %(count)s"
98     " sectorSize = %(sectorSize)s\n"
99     " align_offset = %(offset)s align_grain = %(grain)s\n"
100     " partedDisk = %(disk)r\n"
101     " origPartedDisk = %(orig_disk)r\n"
102     " partedDevice = %(dev)r\n" %
103     {"type": self.labelType, "count": len(self.partitions),
104     "sectorSize": self.partedDevice.sectorSize,
105     "offset": self.alignment.offset,
106     "grain": self.alignment.grainSize,
107     "disk": self.partedDisk, "orig_disk": self._origPartedDisk,
108     "dev": self.partedDevice})
109     return s
110    
111     @property
112     def dict(self):
113     d = super(DiskLabel, self).dict
114     d.update({"labelType": self.labelType,
115     "partitionCount": len(self.partitions),
116     "sectorSize": self.partedDevice.sectorSize,
117     "offset": self.alignment.offset,
118     "grainSize": self.alignment.grainSize})
119     return d
120    
121     def resetPartedDisk(self):
122     """ Set this instance's partedDisk to reflect the disk's contents. """
123     log_method_call(self, device=self.device)
124     self._partedDisk = self._origPartedDisk
125    
126     def freshPartedDisk(self):
127     """ Return a new, empty parted.Disk instance for this device. """
128     log_method_call(self, device=self.device, labelType=self._labelType)
129     return parted.freshDisk(device=self.partedDevice, ty=self._labelType)
130    
131     @property
132     def partedDisk(self):
133     if not self._partedDisk:
134     if self.exists:
135     try:
136     self._partedDisk = parted.Disk(device=self.partedDevice)
137     except (_ped.DiskLabelException, _ped.IOException,
138     NotImplementedError) as e:
139     raise InvalidDiskLabelError()
140    
141     if self._partedDisk.type == "loop":
142     # When the device has no partition table but it has a FS,
143     # it will be created with label type loop. Treat the
144     # same as if the device had no label (cause it really
145     # doesn't).
146     raise InvalidDiskLabelError()
147    
148     # here's where we correct the ctor-supplied disklabel type for
149     # preexisting disklabels if the passed type was wrong
150     self._labelType = self._partedDisk.type
151     else:
152     self._partedDisk = self.freshPartedDisk()
153    
154     return self._partedDisk
155    
156     @property
157     def partedDevice(self):
158     if not self._partedDevice and self.device:
159     if os.path.exists(self.device):
160     # We aren't guaranteed to be able to get a device. In
161     # particular, built-in USB flash readers show up as devices but
162     # do not always have any media present, so parted won't be able
163     # to find a device.
164     try:
165     self._partedDevice = parted.Device(path=self.device)
166     except (_ped.IOException, _ped.DeviceException) as e:
167     log.error("DiskLabel.partedDevice: Parted exception: %s" % e)
168     else:
169     log.info("DiskLabel.partedDevice: %s does not exist" % self.device)
170    
171     if not self._partedDevice:
172     log.info("DiskLabel.partedDevice returning None")
173     return self._partedDevice
174    
175     @property
176     def labelType(self):
177     """ The disklabel type (eg: 'gpt', 'msdos') """
178     return self.partedDisk.type
179    
180     @property
181     def name(self):
182     return "%s (%s)" % (self._name, self.labelType.upper())
183    
184     @property
185     def size(self):
186     size = self._size
187     if not size:
188     try:
189     size = self.partedDevice.getSize(unit="MB")
190     except Exception:
191     size = 0
192    
193     return size
194    
195     @property
196     def status(self):
197     """ Device status. """
198     return False
199    
200     def setup(self, *args, **kwargs):
201     """ Open, or set up, a device. """
202     log_method_call(self, device=self.device,
203     type=self.type, status=self.status)
204     if not self.exists:
205     raise DeviceFormatError("format has not been created")
206    
207     if self.status:
208     return
209    
210     DeviceFormat.setup(self, *args, **kwargs)
211    
212     def teardown(self, *args, **kwargs):
213     """ Close, or tear down, a device. """
214     log_method_call(self, device=self.device,
215     type=self.type, status=self.status)
216     if not self.exists:
217     raise DeviceFormatError("format has not been created")
218    
219     def create(self, *args, **kwargs):
220     """ Create the device. """
221     log_method_call(self, device=self.device,
222     type=self.type, status=self.status)
223     if self.exists:
224     raise DeviceFormatError("format already exists")
225    
226     if self.status:
227     raise DeviceFormatError("device exists and is active")
228    
229     DeviceFormat.create(self, *args, **kwargs)
230    
231     # We're relying on someone having called resetPartedDisk -- we
232     # could ensure a fresh disklabel by setting self._partedDisk to
233     # None right before calling self.commit(), but that might hide
234     # other problems.
235     self.commit()
236     self.exists = True
237    
238     def destroy(self, *args, **kwargs):
239     """ Wipe the disklabel from the device. """
240     log_method_call(self, device=self.device,
241     type=self.type, status=self.status)
242     if not self.exists:
243     raise DeviceFormatError("format does not exist")
244    
245     if not os.access(self.device, os.W_OK):
246     raise DeviceFormatError("device path does not exist")
247    
248     self.partedDevice.clobber()
249     self.exists = False
250    
251     def commit(self):
252     """ Commit the current partition table to disk and notify the OS. """
253     log_method_call(self, device=self.device,
254     numparts=len(self.partitions))
255     try:
256     self.partedDisk.commit()
257     except parted.DiskException as msg:
258     raise DiskLabelCommitError(msg)
259     else:
260     udev_settle()
261    
262     def commitToDisk(self):
263     """ Commit the current partition table to disk. """
264     log_method_call(self, device=self.device,
265     numparts=len(self.partitions))
266     try:
267     self.partedDisk.commitToDevice()
268     except parted.DiskException as msg:
269     raise DiskLabelCommitError(msg)
270    
271     def addPartition(self, *args, **kwargs):
272     partition = kwargs.get("partition", None)
273     if not partition:
274     partition = args[0]
275     geometry = partition.geometry
276     constraint = kwargs.get("constraint", None)
277     if not constraint and len(args) > 1:
278     constraint = args[1]
279     elif not constraint:
280     constraint = parted.Constraint(exactGeom=geometry)
281    
282     new_partition = parted.Partition(disk=self.partedDisk,
283     type=partition.type,
284     geometry=geometry)
285     self.partedDisk.addPartition(partition=new_partition,
286     constraint=constraint)
287    
288     def removePartition(self, partition):
289     self.partedDisk.removePartition(partition)
290    
291     @property
292     def extendedPartition(self):
293     try:
294     extended = self.partedDisk.getExtendedPartition()
295     except Exception:
296     extended = None
297     return extended
298    
299     @property
300     def logicalPartitions(self):
301     try:
302     logicals = self.partedDisk.getLogicalPartitions()
303     except Exception:
304     logicals = []
305     return logicals
306    
307     @property
308     def firstPartition(self):
309     try:
310     part = self.partedDisk.getFirstPartition()
311     except Exception:
312     part = None
313     return part
314    
315     @property
316     def partitions(self):
317     try:
318     parts = self.partedDisk.partitions
319     except Exception:
320     parts = []
321     return parts
322    
323     @property
324     def alignment(self):
325     """ Alignment requirements for this device. """
326     if not self._alignment:
327     try:
328     disklabel_alignment = self.partedDisk.partitionAlignment
329     except _ped.CreateException:
330     disklabel_alignment = parted.Alignment(offset=0, grainSize=1)
331    
332     try:
333     optimum_device_alignment = self.partedDevice.optimumAlignment
334     except _ped.CreateException:
335     optimum_device_alignment = None
336    
337     try:
338     minimum_device_alignment = self.partedDevice.minimumAlignment
339     except _ped.CreateException:
340     minimum_device_alignment = None
341    
342     try:
343     a = optimum_device_alignment.intersect(disklabel_alignment)
344     except (ArithmeticError, AttributeError):
345     try:
346     a = minimum_device_alignment.intersect(disklabel_alignment)
347     except (ArithmeticError, AttributeError):
348     a = disklabel_alignment
349    
350     self._alignment = a
351    
352     return self._alignment
353    
354     @property
355     def endAlignment(self):
356     if not self._endAlignment:
357     self._endAlignment = parted.Alignment(
358     offset = self.alignment.offset - 1,
359     grainSize = self.alignment.grainSize)
360    
361     return self._endAlignment
362    
363     register_device_format(DiskLabel)
364    

admin@koozali.org
ViewVC Help
Powered by ViewVC 1.2.1 RSS 2.0 feed