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

Contents of /cdrom.image/sme9/updates/storage/formats/__init__.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 # __init__.py
2 # Entry point for anaconda storage formats subpackage.
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
25 from iutil import notify_kernel, get_sysfs_path_by_name
26 from baseudev import udev_get_device
27 from ..storage_log import log_method_call
28 from ..errors import *
29 from ..devicelibs.dm import dm_node_from_name
30 from ..udev import udev_device_get_major, udev_device_get_minor
31
32 import gettext
33 _ = lambda x: gettext.ldgettext("anaconda", x)
34
35 import logging
36 log = logging.getLogger("storage")
37
38
39 device_formats = {}
40 def register_device_format(fmt_class):
41 if not issubclass(fmt_class, DeviceFormat):
42 raise ValueError("arg1 must be a subclass of DeviceFormat")
43
44 device_formats[fmt_class._type] = fmt_class
45 log.debug("registered device format class %s as %s" % (fmt_class.__name__,
46 fmt_class._type))
47
48 default_fstypes = ("ext4", "ext3", "ext2")
49 def get_default_filesystem_type(boot=None):
50 import platform
51
52 if boot:
53 fstypes = [platform.getPlatform(None).defaultBootFSType]
54 else:
55 fstypes = default_fstypes
56
57 for fstype in fstypes:
58 try:
59 supported = get_device_format_class(fstype).supported
60 except AttributeError:
61 supported = None
62
63 if supported:
64 return fstype
65
66 raise DeviceFormatError("None of %s is supported by your kernel" % ",".join(fstypes))
67
68 def getFormat(fmt_type, *args, **kwargs):
69 """ Return a DeviceFormat instance based on fmt_type and args.
70
71 Given a device format type and a set of constructor arguments,
72 return a DeviceFormat instance.
73
74 Return None if no suitable format class is found.
75
76 Arguments:
77
78 fmt_type -- the name of the format type (eg: 'ext3', 'swap')
79
80 Keyword Arguments:
81
82 The keyword arguments may vary according to the format type,
83 but here is the common set:
84
85 device -- path to the device on which the format resides
86 uuid -- the UUID of the (preexisting) formatted device
87 exists -- whether or not the format exists on the device
88
89 """
90 fmt_class = get_device_format_class(fmt_type)
91 fmt = None
92 if fmt_class:
93 fmt = fmt_class(*args, **kwargs)
94 try:
95 className = fmt.__class__.__name__
96 except AttributeError:
97 className = None
98 log.debug("getFormat('%s') returning %s instance" % (fmt_type, className))
99 return fmt
100
101 def collect_device_format_classes():
102 """ Pick up all device format classes from this directory.
103
104 Note: Modules must call register_device_format(FormatClass) in
105 order for the format class to be picked up.
106 """
107 dir = os.path.dirname(__file__)
108 for module_file in os.listdir(dir):
109 # make sure we're not importing this module
110 if module_file.endswith(".py") and module_file != __file__:
111 mod_name = module_file[:-3]
112 # imputil is deprecated in python 2.6
113 try:
114 globals()[mod_name] = __import__(mod_name, globals(), locals(), [], -1)
115 except ImportError, e:
116 log.debug("import of device format module '%s' failed" % mod_name)
117
118 def get_device_format_class(fmt_type):
119 """ Return an appropriate format class based on fmt_type. """
120 if not device_formats:
121 collect_device_format_classes()
122
123 fmt = device_formats.get(fmt_type)
124 if not fmt:
125 for fmt_class in device_formats.values():
126 if fmt_type and fmt_type == fmt_class._name:
127 fmt = fmt_class
128 break
129 elif fmt_type in fmt_class._udevTypes:
130 fmt = fmt_class
131 break
132
133 # default to no formatting, AKA "Unknown"
134 if not fmt:
135 fmt = DeviceFormat
136
137 return fmt
138
139 class DeviceFormat(object):
140 """ Generic device format. """
141 _type = None
142 _name = "Unknown"
143 _udevTypes = []
144 partedFlag = None
145 partedSystem = None
146 _formattable = False # can be formatted
147 _supported = False # is supported
148 _linuxNative = False # for clearpart
149 _packages = [] # required packages
150 _services = [] # required services
151 _resizable = False # can be resized
152 _bootable = False # can be used as boot
153 _migratable = False # can be migrated
154 _maxSize = 0 # maximum size in MB
155 _minSize = 0 # minimum size in MB
156 _dump = False
157 _check = False
158 _hidden = False # hide devices with this formatting?
159
160 def __init__(self, *args, **kwargs):
161 """ Create a DeviceFormat instance.
162
163 Keyword Arguments:
164
165 device -- path to the underlying device
166 uuid -- this format's UUID
167 exists -- indicates whether this is an existing format
168
169 """
170 self.device = kwargs.get("device")
171 self.uuid = kwargs.get("uuid")
172 self.exists = kwargs.get("exists")
173 self.options = kwargs.get("options")
174 self._majorminor = None
175 self._migrate = False
176
177 # don't worry about existence if this is a DeviceFormat instance
178 #if self.__class__ is DeviceFormat:
179 # self.exists = True
180
181 def __str__(self):
182 s = ("%(classname)s instance (%(id)s) --\n"
183 " type = %(type)s name = %(name)s status = %(status)s\n"
184 " device = %(device)s uuid = %(uuid)s exists = %(exists)s\n"
185 " options = %(options)s supported = %(supported)s"
186 " formattable = %(format)s resizable = %(resize)s\n" %
187 {"classname": self.__class__.__name__, "id": "%#x" % id(self),
188 "type": self.type, "name": self.name, "status": self.status,
189 "device": self.device, "uuid": self.uuid, "exists": self.exists,
190 "options": self.options, "supported": self.supported,
191 "format": self.formattable, "resize": self.resizable})
192 return s
193
194 @property
195 def dict(self):
196 d = {"type": self.type, "name": self.name, "device": self.device,
197 "uuid": self.uuid, "exists": self.exists,
198 "options": self.options, "supported": self.supported,
199 "resizable": self.resizable}
200 return d
201
202 def _setOptions(self, options):
203 self._options = options
204
205 def _getOptions(self):
206 return self._options
207
208 options = property(_getOptions, _setOptions)
209
210 def _setDevice(self, devspec):
211 if devspec and not devspec.startswith("/"):
212 raise ValueError("device must be a fully qualified path")
213 self._device = devspec
214
215 def _getDevice(self):
216 return self._device
217
218 device = property(lambda f: f._getDevice(),
219 lambda f,d: f._setDevice(d),
220 doc="Full path the device this format occupies")
221
222 @property
223 def name(self):
224 if self._name:
225 name = self._name
226 else:
227 name = self.type
228 return name
229
230 @property
231 def type(self):
232 return self._type
233
234 def probe(self):
235 log_method_call(self, device=self.device,
236 type=self.type, status=self.status)
237
238 def notifyKernel(self):
239 log_method_call(self, device=self.device,
240 type=self.type)
241 if not self.device:
242 return
243
244 if self.device.startswith("/dev/mapper/"):
245 try:
246 name = dm_node_from_name(os.path.basename(self.device))
247 except Exception, e:
248 log.warning("failed to get dm node for %s" % self.device)
249 return
250 else:
251 name = self.device
252
253 path = get_sysfs_path_by_name(name)
254 try:
255 notify_kernel(path, action="change")
256 except Exception, e:
257 log.warning("failed to notify kernel of change: %s" % e)
258
259 def cacheMajorminor(self):
260 """ Cache the value of self.majorminor.
261
262 Once a device node of this format's device disappears (for instance
263 after a teardown), it is no longer possible to figure out the value
264 of self.majorminor pseudo-unique string. Call this method before
265 that happens for caching this.
266 """
267 self._majorminor = None
268 try:
269 self.majorminor # this does the caching
270 except StorageError:
271 # entirely possible there's no majorminor, for instance an
272 # LVMVolumeGroup has got no device node and no sysfs path. In this
273 # case obviously, calling majorminor of this object later raises an
274 # exception.
275 pass
276 return self._majorminor
277
278 def create(self, *args, **kwargs):
279 log_method_call(self, device=self.device,
280 type=self.type, status=self.status)
281 # allow late specification of device path
282 device = kwargs.get("device")
283 if device:
284 self.device = device
285
286 if not os.path.exists(self.device):
287 raise FormatCreateError("invalid device specification", self.device)
288
289 def destroy(self, *args, **kwargs):
290 log_method_call(self, device=self.device,
291 type=self.type, status=self.status)
292 # zero out the 1MB at the beginning and end of the device in the
293 # hope that it will wipe any metadata from filesystems that
294 # previously occupied this device
295 log.debug("zeroing out beginning and end of %s..." % self.device)
296 fd = None
297
298 try:
299 fd = os.open(self.device, os.O_RDWR)
300 buf = '\0' * 1024 * 1024
301 os.write(fd, buf)
302 os.lseek(fd, -1024 * 1024, 2)
303 os.write(fd, buf)
304 os.close(fd)
305 except OSError as e:
306 if getattr(e, "errno", None) == 28: # No space left in device
307 pass
308 else:
309 log.error("error zeroing out %s: %s" % (self.device, e))
310
311 if fd:
312 os.close(fd)
313 except Exception as e:
314 log.error("error zeroing out %s: %s" % (self.device, e))
315 if fd:
316 os.close(fd)
317
318 self.exists = False
319
320 def setup(self, *args, **kwargs):
321 log_method_call(self, device=self.device,
322 type=self.type, status=self.status)
323
324 if not self.exists:
325 raise FormatSetupError("format has not been created")
326
327 if self.status:
328 return
329
330 # allow late specification of device path
331 device = kwargs.get("device")
332 if device:
333 self.device = device
334
335 if not self.device or not os.path.exists(self.device):
336 raise FormatSetupError("invalid device specification")
337
338 def teardown(self, *args, **kwargs):
339 log_method_call(self, device=self.device,
340 type=self.type, status=self.status)
341
342 @property
343 def status(self):
344 return (self.exists and
345 self.__class__ is not DeviceFormat and
346 isinstance(self.device, str) and
347 self.device and
348 os.path.exists(self.device))
349
350 @property
351 def formattable(self):
352 """ Can we create formats of this type? """
353 return self._formattable
354
355 @property
356 def supported(self):
357 """ Is this format a supported type? """
358 return self._supported
359
360 @property
361 def packages(self):
362 """ Packages required to manage formats of this type. """
363 return self._packages
364
365 @property
366 def services(self):
367 """ Services required to manage formats of this type. """
368 return self._services
369
370 @property
371 def resizable(self):
372 """ Can formats of this type be resized? """
373 return self._resizable and self.exists
374
375 @property
376 def bootable(self):
377 """ Is this format type suitable for a boot partition? """
378 return self._bootable
379
380 @property
381 def migratable(self):
382 """ Can formats of this type be migrated? """
383 return self._migratable
384
385 @property
386 def migrate(self):
387 return self._migrate
388
389 @property
390 def linuxNative(self):
391 """ Is this format type native to linux? """
392 return self._linuxNative
393
394 @property
395 def mountable(self):
396 """ Is this something we can mount? """
397 return False
398
399 @property
400 def dump(self):
401 """ Whether or not this format will be dumped by dump(8). """
402 return self._dump
403
404 @property
405 def check(self):
406 """ Whether or not this format is checked on boot. """
407 return self._check
408
409 @property
410 def maxSize(self):
411 """ Maximum size (in MB) for this format type. """
412 return self._maxSize
413
414 @property
415 def minSize(self):
416 """ Minimum size (in MB) for this format type. """
417 return self._minSize
418
419 @property
420 def hidden(self):
421 """ Whether devices with this formatting should be hidden in UIs. """
422 return self._hidden
423
424 @property
425 def majorminor(self):
426 """A string suitable for using as a pseudo-unique ID in kickstart."""
427 if not self._majorminor:
428 # If this is a device-mapper device, we have to get the DM node and
429 # build the sysfs path from that.
430 try:
431 device = dm_node_from_name(self.device)
432 except DMError:
433 device = self.device
434
435 try:
436 sysfs_path = get_sysfs_path_by_name(device)
437 except RuntimeError:
438 raise StorageError("DeviceFormat.majorminor: "
439 "can not get majorminor for '%s'" % device)
440
441 dev = udev_get_device(sysfs_path[4:])
442 self._majorminor = "%03d%03d" %\
443 (udev_device_get_major(dev), udev_device_get_minor(dev))
444 return self._majorminor
445
446 def writeKS(self, f):
447 return
448
449 collect_device_format_classes()

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