Package pyanaconda :: Module platform
[hide private]
[frames] | no frames]

Source Code for Module pyanaconda.platform

  1  # 
  2  # platform.py:  Architecture-specific information 
  3  # 
  4  # Copyright (C) 2009-2011 
  5  # Red Hat, Inc.  All rights reserved. 
  6  # 
  7  # This program is free software; you can redistribute it and/or modify 
  8  # it under the terms of the GNU General Public License as published by 
  9  # the Free Software Foundation; either version 2 of the License, or 
 10  # (at your option) any later version. 
 11  # 
 12  # This program is distributed in the hope that it will be useful, 
 13  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 14  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 15  # GNU General Public License for more details. 
 16  # 
 17  # You should have received a copy of the GNU General Public License 
 18  # along with this program.  If not, see <http://www.gnu.org/licenses/>. 
 19  # 
 20  # Authors: Chris Lumens <clumens@redhat.com> 
 21  # 
 22  import logging 
 23  log = logging.getLogger("anaconda") 
 24   
 25  import parted 
 26   
 27  from pyanaconda import bootloader 
 28  from pyanaconda.storage.devicelibs import mdraid 
 29   
 30  import iutil 
 31  from flags import flags 
 32   
 33  import gettext 
 34  _ = lambda x: gettext.ldgettext("anaconda", x) 
 35  N_ = lambda x: x 
36 37 -class Platform(object):
38 """Platform 39 40 A class containing platform-specific information and methods for use 41 during installation. The intent is to eventually encapsulate all the 42 architecture quirks in one place to avoid lots of platform checks 43 throughout anaconda.""" 44 _minimumSector = 0 45 _packages = [] 46 47 _bootloaderClass = bootloader.BootLoader 48 # requirements for bootloader stage1 devices 49 _boot_stage1_device_types = [] 50 _boot_stage1_format_types = [] 51 _boot_stage1_mountpoints = [] 52 _boot_stage1_max_end_mb = None 53 _boot_stage1_raid_levels = [] 54 _boot_stage1_raid_metadata = [] 55 _boot_stage1_raid_member_types = [] 56 _boot_stage1_description = N_("bootloader device") 57 _boot_raid_description = N_("RAID Device") 58 _boot_partition_description = N_("First sector of boot partition") 59 _boot_descriptions = {} 60 61 _disklabel_types = [] 62 _non_linux_format_types = [] 63
64 - def __init__(self, anaconda):
65 """Creates a new Platform object. This is basically an abstract class. 66 You should instead use one of the platform-specific classes as 67 returned by getPlatform below. Not all subclasses need to provide 68 all the methods in this class.""" 69 self.anaconda = anaconda 70 71 if flags.nogpt and "gpt" in self._disklabel_types and \ 72 len(self._disklabel_types) > 1: 73 self._disklabel_types.remove("gpt")
74 75 @property
76 - def diskLabelTypes(self):
77 """A list of valid disklabel types for this architecture.""" 78 return self._disklabel_types
79 80 @property
81 - def defaultDiskLabelType(self):
82 """The default disklabel type for this architecture.""" 83 return self.diskLabelTypes[0]
84 85 @property
86 - def bootStage1ConstraintDict(self):
87 d = {"device_types": self._boot_stage1_device_types, 88 "format_types": self._boot_stage1_format_types, 89 "mountpoints": self._boot_stage1_mountpoints, 90 "max_end_mb": self._boot_stage1_max_end_mb, 91 "raid_levels": self._boot_stage1_raid_levels, 92 "raid_metadata": self._boot_stage1_raid_metadata, 93 "raid_member_types": self._boot_stage1_raid_member_types, 94 "descriptions": self._boot_descriptions} 95 return d
96
97 - def requiredDiskLabelType(self, device_type):
98 return None
99
100 - def bestDiskLabelType(self, device):
101 """The best disklabel type for the specified device.""" 102 # if there's a required type for this device type, use that 103 labelType = self.requiredDiskLabelType(device.partedDevice.type) 104 log.debug("required disklabel type for %s (%s) is %s" 105 % (device.name, device.partedDevice.type, labelType)) 106 if not labelType: 107 # otherwise, use the first supported type for this platform 108 # that is large enough to address the whole device 109 labelType = self.defaultDiskLabelType 110 log.debug("default disklabel type for %s is %s" % (device.name, 111 labelType)) 112 for lt in self.diskLabelTypes: 113 l = parted.freshDisk(device=device.partedDevice, ty=lt) 114 if l.maxPartitionStartSector > device.partedDevice.length: 115 labelType = lt 116 log.debug("selecting %s disklabel for %s based on size" 117 % (labelType, device.name)) 118 break 119 120 return labelType
121 122 @property
123 - def minimumSector(self, disk):
124 """Return the minimum starting sector for the provided disk.""" 125 return self._minimumSector
126 127 @property
128 - def packages (self):
129 _packages = self._packages 130 if flags.cmdline.get('fips', None) == '1': 131 _packages.append('dracut-fips') 132 return _packages
133
134 - def setDefaultPartitioning(self):
135 """Return the default platform-specific partitioning information.""" 136 from storage.partspec import PartSpec 137 return [PartSpec(mountpoint="/boot", 138 fstype=self.anaconda.storage.defaultBootFSType, 139 size=500, weight=self.weight(mountpoint="/boot"))]
140
141 - def weight(self, fstype=None, mountpoint=None):
142 """ Given an fstype (as a string) or a mountpoint, return an integer 143 for the base sorting weight. This is used to modify the sort 144 algorithm for partition requests, mainly to make sure bootable 145 partitions and /boot are placed where they need to be.""" 146 if mountpoint == "/boot": 147 return 2000 148 else: 149 return 0
150
151 -class X86(Platform):
152 _bootloaderClass = bootloader.GRUB2 153 _boot_stage1_device_types = ["disk"] 154 _boot_mbr_description = N_("Master Boot Record") 155 _boot_descriptions = {"disk": _boot_mbr_description, 156 "partition": Platform._boot_partition_description, 157 "mdarray": Platform._boot_raid_description} 158 159 160 _disklabel_types = ["gpt", "msdos"] 161 # XXX hpfs, if reported by blkid/udev, will end up with a type of None 162 _non_linux_format_types = ["vfat", "ntfs", "hpfs"] 163
164 - def __init__(self, anaconda):
165 super(X86, self).__init__(anaconda)
166
167 - def setDefaultPartitioning(self):
168 """Return the default platform-specific partitioning information.""" 169 from storage.partspec import PartSpec 170 ret = Platform.setDefaultPartitioning(self) 171 ret.append(PartSpec(fstype="biosboot", size=1, 172 weight=self.weight(fstype="biosboot"))) 173 return ret
174
175 - def weight(self, fstype=None, mountpoint=None):
176 score = Platform.weight(self, fstype=fstype, mountpoint=mountpoint) 177 if score: 178 return score 179 elif fstype == "biosboot": 180 return 5000 181 else: 182 return 0
183
184 -class EFI(Platform):
185 _bootloaderClass = bootloader.EFIGRUB 186 187 _boot_stage1_format_types = ["efi"] 188 _boot_stage1_device_types = ["partition", "mdarray"] 189 _boot_stage1_raid_levels = [mdraid.RAID1] 190 _boot_stage1_raid_metadata = ["1.0"] 191 _boot_stage1_raid_member_types = ["partition"] 192 _boot_stage1_mountpoints = ["/boot/efi"] 193 _boot_efi_description = N_("EFI System Partition") 194 _boot_descriptions = {"partition": _boot_efi_description, 195 "mdarray": Platform._boot_raid_description} 196 197 _disklabel_types = ["gpt"] 198 # XXX hpfs, if reported by blkid/udev, will end up with a type of None 199 _non_linux_format_types = ["vfat", "ntfs", "hpfs"] 200
201 - def setDefaultPartitioning(self):
202 from storage.partspec import PartSpec 203 ret = Platform.setDefaultPartitioning(self) 204 ret.append(PartSpec(mountpoint="/boot/efi", fstype="efi", size=20, 205 maxSize=200, 206 grow=True, weight=self.weight(fstype="efi"))) 207 return ret
208
209 - def weight(self, fstype=None, mountpoint=None):
210 score = Platform.weight(self, fstype=fstype, mountpoint=mountpoint) 211 if score: 212 return score 213 elif fstype == "efi" or mountpoint == "/boot/efi": 214 return 5000 215 else: 216 return 0
217
218 -class MacEFI(EFI):
219 _boot_stage1_format_types = ["hfs+"] 220 _boot_efi_description = N_("Apple EFI Boot Partition") 221 _non_linux_format_types = ["hfs+"] 222 _packages = ["mactel-boot"] 223
224 - def setDefaultPartitioning(self):
225 from storage.partspec import PartSpec 226 ret = Platform.setDefaultPartitioning(self) 227 ret.append(PartSpec(mountpoint="/boot/efi", fstype="hfs+", size=20, 228 maxSize=200, 229 grow=True, weight=self.weight(mountpoint="/boot/efi"))) 230 return ret
231
232 -class PPC(Platform):
233 _ppcMachine = iutil.getPPCMachine() 234 _bootloaderClass = bootloader.Yaboot 235 _boot_stage1_device_types = ["partition"] 236 237 @property
238 - def ppcMachine(self):
239 return self._ppcMachine
240
241 -class IPSeriesPPC(PPC):
242 _bootloaderClass = bootloader.IPSeriesYaboot 243 _boot_stage1_format_types = ["prepboot"] 244 _boot_stage1_max_end_mb = 10 245 _boot_prep_description = N_("PReP Boot Partition") 246 _boot_descriptions = {"partition": _boot_prep_description} 247 _disklabel_types = ["msdos"] 248
249 - def setDefaultPartitioning(self):
250 from storage.partspec import PartSpec 251 ret = PPC.setDefaultPartitioning(self) 252 ret.append(PartSpec(fstype="prepboot", size=4, 253 weight=self.weight(fstype="prepboot"))) 254 return ret
255
256 - def weight(self, fstype=None, mountpoint=None):
257 score = Platform.weight(self, fstype=fstype, mountpoint=mountpoint) 258 if score: 259 return score 260 elif fstype == "prepboot": 261 return 5000 262 else: 263 return 0
264
265 -class NewWorldPPC(PPC):
266 _bootloaderClass = bootloader.MacYaboot 267 _boot_stage1_format_types = ["appleboot"] 268 _boot_apple_description = N_("Apple Bootstrap Partition") 269 _boot_descriptions = {"partition": _boot_apple_description} 270 _disklabel_types = ["mac"] 271 _non_linux_format_types = ["hfs", "hfs+"] 272
273 - def setDefaultPartitioning(self):
274 from storage.partspec import PartSpec 275 ret = Platform.setDefaultPartitioning(self) 276 ret.append(PartSpec(fstype="appleboot", size=1, maxSize=1, 277 weight=self.weight(fstype="appleboot"))) 278 return ret
279
280 - def weight(self, fstype=None, mountpoint=None):
281 score = Platform.weight(self, fstype=fstype, mountpoint=mountpoint) 282 if score: 283 return score 284 elif fstype == "appleboot": 285 return 5000 286 else: 287 return 0
288
289 -class PS3(PPC):
290 pass
291
292 -class S390(Platform):
293 _bootloaderClass = bootloader.ZIPL 294 _packages = ["s390utils"] 295 _disklabel_types = ["msdos", "dasd"] 296 _boot_stage1_device_types = ["disk", "partition"] 297 _boot_dasd_description = N_("DASD") 298 _boot_zfcp_description = N_("zFCP") 299 _boot_descriptions = {"dasd": _boot_dasd_description, 300 "zfcp": _boot_zfcp_description, 301 "partition": Platform._boot_partition_description} 302
303 - def __init__(self, anaconda):
304 Platform.__init__(self, anaconda)
305
306 - def setDefaultPartitioning(self):
307 """Return the default platform-specific partitioning information.""" 308 from storage.partspec import PartSpec 309 return [PartSpec(mountpoint="/boot", size=500, 310 fstype=self.anaconda.storage.defaultBootFSType, 311 weight=self.weight(mountpoint="/boot"), lv=True, 312 singlePV=True)]
313
314 - def requiredDiskLabelType(self, device_type):
315 """The required disklabel type for the specified device type.""" 316 if device_type == parted.DEVICE_DASD: 317 return "dasd" 318 319 return super(S390, self).requiredDiskLabelType(device_type)
320
321 -class Sparc(Platform):
322 _bootloaderClass = bootloader.SILO 323 _boot_stage1_format_types = [] 324 _boot_stage1_mountpoints = [] 325 _boot_stage1_max_end_mb = None 326 _disklabel_types = ["sun"] 327 328 @property
329 - def minimumSector(self, disk):
330 (cylinders, heads, sectors) = disk.device.biosGeometry 331 start = long(sectors * heads) 332 start /= long(1024 / disk.device.sectorSize) 333 return start+1
334
335 -def getPlatform(anaconda):
336 """Check the architecture of the system and return an instance of a 337 Platform subclass to match. If the architecture could not be determined, 338 raise an exception.""" 339 if iutil.isPPC(): 340 ppcMachine = iutil.getPPCMachine() 341 342 if (ppcMachine == "PMac" and iutil.getPPCMacGen() == "NewWorld"): 343 return NewWorldPPC(anaconda) 344 elif ppcMachine in ["iSeries", "pSeries"]: 345 return IPSeriesPPC(anaconda) 346 elif ppcMachine == "PS3": 347 return PS3(anaconda) 348 else: 349 raise SystemError, "Unsupported PPC machine type" 350 elif iutil.isS390(): 351 return S390(anaconda) 352 elif iutil.isSparc(): 353 return Sparc(anaconda) 354 elif iutil.isEfi(): 355 if iutil.isMactel(): 356 return MacEFI(anaconda) 357 else: 358 return EFI(anaconda) 359 elif iutil.isX86(): 360 return X86(anaconda) 361 else: 362 raise SystemError, "Could not determine system architecture."
363