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

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

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


Revision 1.2 - (show annotations) (download) (as text)
Sun Dec 22 04:27:52 2013 UTC (10 years, 6 months ago) by wellsi
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +0 -0 lines
Content type: text/x-python
FILE REMOVED
anaconda updates now handled via patches

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