1 |
gordonr |
1.1 |
# |
2 |
|
|
# partedUtils.py: helper functions for use with parted objects |
3 |
|
|
# |
4 |
|
|
# Matt Wilson <msw@redhat.com> |
5 |
|
|
# Jeremy Katz <katzj@redhat.com> |
6 |
|
|
# Mike Fulbright <msf@redhat.com> |
7 |
|
|
# Karsten Hopp <karsten@redhat.com> |
8 |
|
|
# |
9 |
|
|
# Copyright 2002-2003 Red Hat, Inc. |
10 |
|
|
# |
11 |
|
|
# This software may be freely redistributed under the terms of the GNU |
12 |
|
|
# library public license. |
13 |
|
|
# |
14 |
|
|
# You should have received a copy of the GNU Library Public License |
15 |
|
|
# along with this program; if not, write to the Free Software |
16 |
|
|
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
17 |
|
|
# |
18 |
|
|
"""Helper functions for use when dealing with parted objects.""" |
19 |
|
|
|
20 |
|
|
import parted |
21 |
|
|
import math |
22 |
|
|
import os, sys, string, struct |
23 |
|
|
|
24 |
|
|
from product import * |
25 |
|
|
import fsset |
26 |
|
|
import iutil, isys |
27 |
|
|
import raid |
28 |
|
|
import lvm |
29 |
|
|
from flags import flags |
30 |
|
|
from partErrors import * |
31 |
|
|
|
32 |
|
|
from rhpl.log import log |
33 |
|
|
from rhpl.translate import _ |
34 |
|
|
|
35 |
|
|
fsTypes = {} |
36 |
|
|
|
37 |
|
|
fs_type = parted.file_system_type_get_next () |
38 |
|
|
while fs_type: |
39 |
|
|
fsTypes[fs_type.name] = fs_type |
40 |
|
|
fs_type = parted.file_system_type_get_next (fs_type) |
41 |
|
|
|
42 |
|
|
|
43 |
|
|
|
44 |
|
|
def get_flags (part): |
45 |
|
|
"""Retrieve a list of strings representing the flags on the partition.""" |
46 |
|
|
string="" |
47 |
|
|
if not part.is_active (): |
48 |
|
|
return string |
49 |
|
|
first=1 |
50 |
|
|
flag = parted.partition_flag_next (0) |
51 |
|
|
while flag: |
52 |
|
|
if part.get_flag (flag): |
53 |
|
|
string = string + parted.partition_flag_get_name (flag) |
54 |
|
|
if first: |
55 |
|
|
first = 0 |
56 |
|
|
else: |
57 |
|
|
string = string + ", " |
58 |
|
|
flag = parted.partition_flag_next (flag) |
59 |
|
|
return string |
60 |
|
|
|
61 |
|
|
def start_sector_to_cyl(device, sector): |
62 |
|
|
"""Return the closest cylinder (round down) to sector on device.""" |
63 |
|
|
return int(math.floor((float(sector) |
64 |
|
|
/ (device.heads * device.sectors)) + 1)) |
65 |
|
|
|
66 |
|
|
def end_sector_to_cyl(device, sector): |
67 |
|
|
"""Return the closest cylinder (round up) to sector on device.""" |
68 |
|
|
return int(math.ceil(float((sector + 1)) |
69 |
|
|
/ (device.heads * device.sectors))) |
70 |
|
|
|
71 |
|
|
def start_cyl_to_sector(device, cyl): |
72 |
|
|
"Return the sector corresponding to cylinder as a starting cylinder." |
73 |
|
|
return long((cyl - 1) * (device.heads * device.sectors)) |
74 |
|
|
|
75 |
|
|
def end_cyl_to_sector(device, cyl): |
76 |
|
|
"Return the sector corresponding to cylinder as a ending cylinder." |
77 |
|
|
return long(((cyl) * (device.heads * device.sectors)) - 1) |
78 |
|
|
|
79 |
|
|
def getPartSize(partition): |
80 |
|
|
"""Return the size of partition in sectors.""" |
81 |
|
|
return partition.geom.length |
82 |
|
|
|
83 |
|
|
def getPartSizeMB(partition): |
84 |
|
|
"""Return the size of partition in megabytes.""" |
85 |
|
|
return (partition.geom.length * partition.geom.dev.sector_size |
86 |
|
|
/ 1024.0 / 1024.0) |
87 |
|
|
|
88 |
|
|
def getDeviceSizeMB(dev): |
89 |
|
|
"""Return the size of dev in megabytes.""" |
90 |
|
|
return (float(dev.heads * dev.cylinders * dev.sectors) / (1024 * 1024) |
91 |
|
|
* dev.sector_size) |
92 |
|
|
|
93 |
|
|
def get_partition_by_name(disks, partname): |
94 |
|
|
"""Return the parted part object associated with partname. |
95 |
|
|
|
96 |
|
|
Arguments: |
97 |
|
|
disks -- Dictionary of diskname->PedDisk objects |
98 |
|
|
partname -- Name of partition to find |
99 |
|
|
|
100 |
|
|
Return: |
101 |
|
|
PedPartition object with name partname. None if no such partition. |
102 |
|
|
""" |
103 |
|
|
for diskname in disks.keys(): |
104 |
|
|
disk = disks[diskname] |
105 |
|
|
part = disk.next_partition() |
106 |
|
|
while part: |
107 |
|
|
if get_partition_name(part) == partname: |
108 |
|
|
return part |
109 |
|
|
|
110 |
|
|
part = disk.next_partition(part) |
111 |
|
|
|
112 |
|
|
return None |
113 |
|
|
|
114 |
|
|
def get_partition_name(partition): |
115 |
|
|
"""Return the device name for the PedPartition partition.""" |
116 |
|
|
if (partition.geom.dev.type == parted.DEVICE_DAC960 |
117 |
|
|
or partition.geom.dev.type == parted.DEVICE_CPQARRAY): |
118 |
|
|
return "%sp%d" % (partition.geom.dev.path[5:], |
119 |
|
|
partition.num) |
120 |
|
|
if (parted.__dict__.has_key("DEVICE_SX8") and |
121 |
|
|
partition.geom.dev.type == parted.DEVICE_SX8): |
122 |
|
|
return "%sp%d" % (partition.geom.dev.path[5:], |
123 |
|
|
partition.num) |
124 |
|
|
|
125 |
|
|
return "%s%d" % (partition.geom.dev.path[5:], |
126 |
|
|
partition.num) |
127 |
|
|
|
128 |
|
|
|
129 |
|
|
def get_partition_file_system_type(part): |
130 |
|
|
"""Return the file system type of the PedPartition part. |
131 |
|
|
|
132 |
|
|
Arguments: |
133 |
|
|
part -- PedPartition object |
134 |
|
|
|
135 |
|
|
Return: |
136 |
|
|
Filesystem object (as defined in fsset.py) |
137 |
|
|
""" |
138 |
|
|
if part.fs_type is None and part.native_type == 0x41: |
139 |
|
|
ptype = fsset.fileSystemTypeGet("PPC PReP Boot") |
140 |
|
|
elif part.fs_type == None: |
141 |
|
|
return None |
142 |
|
|
elif part.fs_type.name == "linux-swap": |
143 |
|
|
ptype = fsset.fileSystemTypeGet("swap") |
144 |
|
|
elif (part.fs_type.name == "FAT" or part.fs_type.name == "fat16" |
145 |
|
|
or part.fs_type.name == "fat32"): |
146 |
|
|
ptype = fsset.fileSystemTypeGet("vfat") |
147 |
|
|
else: |
148 |
|
|
try: |
149 |
|
|
ptype = fsset.fileSystemTypeGet(part.fs_type.name) |
150 |
|
|
except: |
151 |
|
|
ptype = fsset.fileSystemTypeGet("foreign") |
152 |
|
|
|
153 |
|
|
return ptype |
154 |
|
|
|
155 |
|
|
|
156 |
|
|
def set_partition_file_system_type(part, fstype): |
157 |
|
|
"""Set partition type of part to PedFileSystemType implied by fstype.""" |
158 |
|
|
if fstype == None: |
159 |
|
|
return |
160 |
|
|
try: |
161 |
|
|
for flag in fstype.getPartedPartitionFlags(): |
162 |
|
|
if not part.is_flag_available(flag): |
163 |
|
|
raise PartitioningError, ("requested FileSystemType needs " |
164 |
|
|
"a flag that is not available.") |
165 |
|
|
part.set_flag(flag, 1) |
166 |
|
|
part.set_system(fstype.getPartedFileSystemType()) |
167 |
|
|
except: |
168 |
|
|
print "Failed to set partition type to ",fstype.getName() |
169 |
|
|
pass |
170 |
|
|
|
171 |
|
|
def get_partition_drive(partition): |
172 |
|
|
"""Return the device name for disk that PedPartition partition is on.""" |
173 |
|
|
return "%s" %(partition.geom.dev.path[5:]) |
174 |
|
|
|
175 |
|
|
def get_max_logical_partitions(disk): |
176 |
|
|
if not disk.type.check_feature(parted.DISK_TYPE_EXTENDED): |
177 |
|
|
return 0 |
178 |
|
|
dev = disk.dev.path[5:] |
179 |
|
|
for key in max_logical_partition_count.keys(): |
180 |
|
|
if dev.startswith(key): |
181 |
|
|
return max_logical_partition_count[key] |
182 |
|
|
# FIXME: if we don't know about it, should we pretend it can't have |
183 |
|
|
# logicals? probably safer to just use something reasonable |
184 |
|
|
return 11 |
185 |
|
|
|
186 |
|
|
def map_foreign_to_fsname(type): |
187 |
|
|
"""Return the partition type associated with the numeric type.""" |
188 |
|
|
if type in allPartitionTypesDict.keys(): |
189 |
|
|
return allPartitionTypesDict[type] |
190 |
|
|
else: |
191 |
|
|
return _("Foreign") |
192 |
|
|
|
193 |
|
|
def filter_partitions(disk, func): |
194 |
|
|
rc = [] |
195 |
|
|
part = disk.next_partition () |
196 |
|
|
while part: |
197 |
|
|
if func(part): |
198 |
|
|
rc.append(part) |
199 |
|
|
part = disk.next_partition (part) |
200 |
|
|
|
201 |
|
|
return rc |
202 |
|
|
|
203 |
|
|
def get_all_partitions(disk): |
204 |
|
|
"""Return a list of all PedPartition objects on disk.""" |
205 |
|
|
func = lambda part: part.is_active() |
206 |
|
|
return filter_partitions(disk, func) |
207 |
|
|
|
208 |
|
|
def get_logical_partitions(disk): |
209 |
|
|
"""Return a list of logical PedPartition objects on disk.""" |
210 |
|
|
func = lambda part: (part.is_active() |
211 |
|
|
and part.type & parted.PARTITION_LOGICAL) |
212 |
|
|
return filter_partitions(disk, func) |
213 |
|
|
|
214 |
|
|
def get_primary_partitions(disk): |
215 |
|
|
"""Return a list of primary PedPartition objects on disk.""" |
216 |
|
|
func = lambda part: part.type == parted.PARTITION_PRIMARY |
217 |
|
|
return filter_partitions(disk, func) |
218 |
|
|
|
219 |
|
|
def get_raid_partitions(disk): |
220 |
|
|
"""Return a list of RAID-type PedPartition objects on disk.""" |
221 |
|
|
func = lambda part: (part.is_active() |
222 |
|
|
and part.get_flag(parted.PARTITION_RAID) == 1) |
223 |
|
|
return filter_partitions(disk, func) |
224 |
|
|
|
225 |
|
|
def get_lvm_partitions(disk): |
226 |
|
|
"""Return a list of physical volume-type PedPartition objects on disk.""" |
227 |
|
|
func = lambda part: (part.is_active() |
228 |
|
|
and part.get_flag(parted.PARTITION_LVM) == 1) |
229 |
|
|
return filter_partitions(disk, func) |
230 |
|
|
|
231 |
|
|
|
232 |
|
|
def getDefaultDiskType(): |
233 |
|
|
"""Get the default partition table type for this architecture.""" |
234 |
|
|
if iutil.getArch() == "i386": |
235 |
|
|
return parted.disk_type_get("msdos") |
236 |
|
|
elif iutil.getArch() == "ia64": |
237 |
|
|
return parted.disk_type_get("gpt") |
238 |
|
|
elif iutil.getArch() == "s390": |
239 |
|
|
# the "default" type is dasd, but we don't really do dasd |
240 |
|
|
# formatting with parted and use dasdfmt directly for them |
241 |
|
|
# so if we get here, it's an fcp disk and we should write |
242 |
|
|
# an msdos partition table (#144199) |
243 |
|
|
return parted.disk_type_get("msdos") |
244 |
|
|
elif iutil.getArch() == "alpha": |
245 |
|
|
return parted.disk_type_get("bsd") |
246 |
|
|
elif iutil.getArch() == "sparc": |
247 |
|
|
return parted.disk_type_get("sun") |
248 |
|
|
elif iutil.getArch() == "ppc": |
249 |
|
|
if iutil.getPPCMachine() == "PMac": |
250 |
|
|
return parted.disk_type_get("mac") |
251 |
|
|
else: |
252 |
|
|
return parted.disk_type_get("msdos") |
253 |
|
|
else: |
254 |
|
|
return parted.disk_type_get("msdos") |
255 |
|
|
|
256 |
|
|
archLabels = {'i386': ['msdos'], |
257 |
|
|
's390': ['dasd', 'msdos'], |
258 |
|
|
'alpha': ['bsd', 'msdos'], |
259 |
|
|
'sparc': ['sun'], |
260 |
|
|
'ia64': ['msdos', 'gpt'], |
261 |
|
|
'ppc': ['msdos', 'mac'], |
262 |
|
|
'x86_64': ['msdos']} |
263 |
|
|
|
264 |
|
|
# this is kind of crappy, but we don't really want to allow LDL formatted |
265 |
|
|
# dasd to be used during the install |
266 |
|
|
def checkDasdFmt(disk, intf): |
267 |
|
|
if iutil.getArch() != "s390": |
268 |
|
|
return 0 |
269 |
|
|
|
270 |
|
|
if disk.type.name != "dasd": |
271 |
|
|
return 0 |
272 |
|
|
|
273 |
|
|
# FIXME: there has to be a better way to check LDL vs CDL |
274 |
|
|
# how do I test ldl vs cdl? |
275 |
|
|
if disk.max_primary_partition_count > 1: |
276 |
|
|
return 0 |
277 |
|
|
|
278 |
|
|
if intf: |
279 |
|
|
try: |
280 |
|
|
devs = isys.getDasdDevPort() |
281 |
|
|
dev = "/dev/%s (%s)" %(disk.dev.path[5:], devs[device]) |
282 |
|
|
except Exception, e: |
283 |
|
|
log("exception getting dasd dev ports: %s" %(e,)) |
284 |
|
|
dev = "/dev/%s" %(disk.dev.path[5:],) |
285 |
|
|
|
286 |
|
|
rc = intf.messageWindow(_("Warning"), |
287 |
|
|
_("The device %s is LDL formatted instead of " |
288 |
|
|
"CDL formatted. LDL formatted DASDs are not " |
289 |
|
|
"supported for usage during an install of %s. " |
290 |
|
|
"If you wish to use this disk for installation, " |
291 |
|
|
"it must be re-initialized causing the loss of " |
292 |
|
|
"ALL DATA on this drive.\n\n" |
293 |
|
|
"Would you like to reformat this DASD using CDL " |
294 |
|
|
"format?") |
295 |
|
|
%(dev, productName), type = "yesno") |
296 |
|
|
if rc == 0: |
297 |
|
|
return 1 |
298 |
|
|
else: |
299 |
|
|
return -1 |
300 |
|
|
else: |
301 |
|
|
return 1 |
302 |
|
|
|
303 |
|
|
|
304 |
|
|
def checkDiskLabel(disk, intf): |
305 |
|
|
"""Check that the disk label on disk is valid for this machine type.""" |
306 |
|
|
arch = iutil.getArch() |
307 |
|
|
if arch in archLabels.keys(): |
308 |
|
|
if disk.type.name in archLabels[arch]: |
309 |
|
|
# this is kind of a hack since we don't want LDL to be used |
310 |
|
|
return checkDasdFmt(disk, intf) |
311 |
|
|
else: |
312 |
|
|
if disk.type.name == "msdos": |
313 |
|
|
return 0 |
314 |
|
|
|
315 |
|
|
if intf: |
316 |
|
|
rc = intf.messageWindow(_("Warning"), |
317 |
|
|
_("/dev/%s currently has a %s partition " |
318 |
|
|
"layout. To use this disk for " |
319 |
|
|
"the installation of %s, it must be " |
320 |
|
|
"re-initialized, causing the loss of " |
321 |
|
|
"ALL DATA on this drive.\n\n" |
322 |
|
|
"Would you like to format this " |
323 |
|
|
"drive?") |
324 |
|
|
%(disk.dev.path[5:], disk.type.name, |
325 |
|
|
productName), type="custom", |
326 |
|
|
custom_buttons = [ _("_Ignore drive"), |
327 |
|
|
_("_Format drive") ], |
328 |
|
|
custom_icon="question") |
329 |
|
|
|
330 |
|
|
if rc == 0: |
331 |
|
|
return 1 |
332 |
|
|
else: |
333 |
|
|
return -1 |
334 |
|
|
else: |
335 |
|
|
return 1 |
336 |
|
|
|
337 |
|
|
# attempt to associate a parted filesystem type on a partition that |
338 |
|
|
# didn't probe as one type or another. |
339 |
|
|
def validateFsType(part): |
340 |
|
|
# we only care about primary and logical partitions |
341 |
|
|
if not part.type in (parted.PARTITION_PRIMARY, |
342 |
|
|
parted.PARTITION_LOGICAL): |
343 |
|
|
return |
344 |
|
|
# if the partition already has a type, no need to search |
345 |
|
|
if part.fs_type: |
346 |
|
|
return |
347 |
|
|
|
348 |
|
|
# first fsystem to probe wins, so sort the types into a preferred |
349 |
|
|
# order. |
350 |
|
|
fsnames = fsTypes.keys() |
351 |
|
|
goodTypes = ['ext3', 'ext2'] |
352 |
|
|
badTypes = ['linux-swap',] |
353 |
|
|
for fstype in goodTypes: |
354 |
|
|
fsnames.remove(fstype) |
355 |
|
|
fsnames = goodTypes + fsnames |
356 |
|
|
for fstype in badTypes: |
357 |
|
|
fsnames.remove(fstype) |
358 |
|
|
fsnames.extend(badTypes) |
359 |
|
|
|
360 |
|
|
# now check each type, and set the partition system accordingly. |
361 |
|
|
for fsname in fsnames: |
362 |
|
|
fstype = fsTypes[fsname] |
363 |
|
|
if fstype.probe_specific(part.geom) != None: |
364 |
|
|
# XXX verify that this will not modify system type |
365 |
|
|
# in the case where a user does not modify partitions |
366 |
|
|
part.set_system(fstype) |
367 |
|
|
return |
368 |
|
|
|
369 |
|
|
def isLinuxNativeByNumtype(numtype): |
370 |
|
|
"""Check if the type is a 'Linux native' filesystem.""" |
371 |
|
|
linuxtypes = [0x82, 0x83, 0x8e, 0xfd] |
372 |
|
|
|
373 |
|
|
for t in linuxtypes: |
374 |
|
|
if int(numtype) == t: |
375 |
|
|
return 1 |
376 |
|
|
|
377 |
|
|
return 0 |
378 |
|
|
|
379 |
|
|
def sniffFilesystemType(device): |
380 |
|
|
"""Sniff to determine the type of fs on device. |
381 |
|
|
|
382 |
|
|
device - name of device to sniff. we try to create it if it doesn't exist. |
383 |
|
|
""" |
384 |
|
|
|
385 |
|
|
if os.access(device, os.O_RDONLY): |
386 |
|
|
dev = device |
387 |
|
|
else: |
388 |
|
|
dev = "/tmp/" + device |
389 |
|
|
if not os.access(dev, os.O_RDONLY): |
390 |
|
|
try: |
391 |
|
|
isys.makeDevInode(device, dev) |
392 |
|
|
except: |
393 |
|
|
pass |
394 |
|
|
|
395 |
|
|
pagesize = isys.getpagesize() |
396 |
|
|
if pagesize > 2048: |
397 |
|
|
num = pagesize |
398 |
|
|
else: |
399 |
|
|
num = 2048 |
400 |
|
|
try: |
401 |
|
|
fd = os.open(dev, os.O_RDONLY) |
402 |
|
|
buf = os.read(fd, num) |
403 |
|
|
os.close(fd) |
404 |
|
|
except: |
405 |
|
|
return None |
406 |
|
|
|
407 |
|
|
if len(buf) < pagesize: |
408 |
|
|
try: |
409 |
|
|
log("Tried to read pagesize for %s in sniffFilesystemType and only read %s", dev, len(buf)) |
410 |
|
|
except: |
411 |
|
|
pass |
412 |
|
|
return None |
413 |
|
|
|
414 |
|
|
# physical volumes start with HM (see linux/lvm.h |
415 |
|
|
# and LVM/ver/tools/lib/pv_copy.c) |
416 |
|
|
if buf.startswith("HM"): |
417 |
|
|
return "physical volume (LVM)" |
418 |
|
|
# sniff for LVM2 label. see LVM/ver/lib/label/label.[ch] for a |
419 |
|
|
# description of the label and LVM/ver/lib/format_text/layout.h |
420 |
|
|
for sec in range(0, 4): |
421 |
|
|
off = (sec * 512) + 24 |
422 |
|
|
if buf[off:].startswith("LVM2"): |
423 |
|
|
return "physical volume (LVM)" |
424 |
|
|
|
425 |
|
|
try: |
426 |
|
|
isys.raidsbFromDevice(dev) |
427 |
|
|
return "software RAID" |
428 |
|
|
except: |
429 |
|
|
pass |
430 |
|
|
|
431 |
|
|
# ext2 check |
432 |
|
|
if struct.unpack("<H", buf[1080:1082]) == (0xef53,): |
433 |
|
|
if isys.ext2HasJournal(dev, makeDevNode = 0): |
434 |
|
|
return "ext3" |
435 |
|
|
else: |
436 |
|
|
return "ext2" |
437 |
|
|
|
438 |
|
|
# xfs signature |
439 |
|
|
if buf.startswith("XFSB"): |
440 |
|
|
return "xfs" |
441 |
|
|
|
442 |
|
|
# 2.6 doesn't support version 0, so we don't like SWAP-SPACE |
443 |
|
|
if (buf[pagesize - 10:] == "SWAPSPACE2"): |
444 |
|
|
return "swap" |
445 |
|
|
|
446 |
|
|
if fsset.isValidReiserFS(dev): |
447 |
|
|
return "reiserfs" |
448 |
|
|
|
449 |
|
|
if fsset.isValidJFS(dev): |
450 |
|
|
return "jfs" |
451 |
|
|
|
452 |
|
|
# FIXME: we don't look for vfat |
453 |
|
|
|
454 |
|
|
return None |
455 |
|
|
|
456 |
|
|
def getCentOSReleaseString(mountpoint): |
457 |
|
|
if os.access(mountpoint + "/etc/e-smith-release", os.R_OK): |
458 |
|
|
f = open(mountpoint + "/etc/e-smith-release", "r") |
459 |
|
|
try: |
460 |
|
|
lines = f.readlines() |
461 |
|
|
except IOError: |
462 |
|
|
try: |
463 |
|
|
f.close() |
464 |
|
|
except: |
465 |
|
|
pass |
466 |
|
|
return "" |
467 |
|
|
f.close() |
468 |
|
|
# return the first line with the newline at the end stripped |
469 |
|
|
if len(lines) == 0: |
470 |
|
|
return "" |
471 |
|
|
relstr = string.strip(lines[0][:-1]) |
472 |
|
|
|
473 |
|
|
# get the release name and version |
474 |
|
|
# assumes that form is something |
475 |
|
|
# like "Red Hat Linux release 6.2 (Zoot)" |
476 |
|
|
if relstr.find("release") != -1: |
477 |
|
|
try: |
478 |
|
|
idx = relstr.find("release") |
479 |
|
|
prod = relstr[:idx - 1] |
480 |
|
|
|
481 |
|
|
ver = "" |
482 |
|
|
for a in relstr[idx + 8:]: |
483 |
|
|
if a in string.digits + ".": |
484 |
|
|
ver = ver + a |
485 |
|
|
else: |
486 |
|
|
break |
487 |
|
|
|
488 |
|
|
relstr = prod + " " + ver |
489 |
|
|
except: |
490 |
|
|
pass # don't worry, just use the relstr as we have it |
491 |
|
|
return relstr |
492 |
|
|
return "" |
493 |
|
|
|
494 |
|
|
def productMatches(oldproduct, newproduct): |
495 |
|
|
"""Determine if this is a reasonable product to upgrade old product""" |
496 |
|
|
if oldproduct.startswith(newproduct): |
497 |
|
|
return 1 |
498 |
|
|
|
499 |
|
|
productUpgrades = { |
500 |
slords |
1.3 |
"SME Server": ("Mitel Networks", "SME Server"), |
501 |
gordonr |
1.1 |
"Red Hat Enterprise Linux AS": ("Red Hat Linux Advanced Server", ), |
502 |
|
|
"Red Hat Enterprise Linux WS": ("Red Hat Linux Advanced Workstation",), |
503 |
|
|
# FIXME: this probably shouldn't be in a release... |
504 |
|
|
"Red Hat Enterprise Linux": ("Red Hat Linux Advanced Server", |
505 |
|
|
"Red Hat Linux Advanced Workstation", |
506 |
|
|
"Red Hat Enterprise Linux AS", |
507 |
|
|
"Red Hat Enterprise Linux ES", |
508 |
|
|
"Red Hat Enterprise Linux WS"), |
509 |
|
|
"Fedora Core": ("Red Hat Linux",) |
510 |
|
|
} |
511 |
|
|
|
512 |
|
|
if productUpgrades.has_key(newproduct): |
513 |
|
|
acceptable = productUpgrades[newproduct] |
514 |
|
|
else: |
515 |
|
|
acceptable = () |
516 |
|
|
|
517 |
|
|
for p in acceptable: |
518 |
|
|
if oldproduct.startswith(p): |
519 |
|
|
return 1 |
520 |
|
|
|
521 |
|
|
return 0 |
522 |
|
|
|
523 |
|
|
class DiskSet: |
524 |
|
|
"""The disks in the system.""" |
525 |
|
|
|
526 |
|
|
skippedDisks = [] |
527 |
|
|
mdList = [] |
528 |
|
|
def __init__ (self): |
529 |
|
|
self.disks = {} |
530 |
|
|
self.onlyPrimary = None |
531 |
|
|
|
532 |
|
|
def onlyPrimaryParts(self): |
533 |
|
|
for disk in self.disks.values(): |
534 |
|
|
if disk.type.check_feature(parted.DISK_TYPE_EXTENDED): |
535 |
|
|
return 0 |
536 |
|
|
|
537 |
|
|
return 1 |
538 |
|
|
|
539 |
|
|
|
540 |
|
|
def startAllRaid(self): |
541 |
|
|
"""Start all of the raid devices associated with the DiskSet.""" |
542 |
|
|
driveList = [] |
543 |
|
|
origDriveList = self.driveList() |
544 |
|
|
for drive in origDriveList: |
545 |
|
|
if not drive in DiskSet.skippedDisks: |
546 |
|
|
driveList.append(drive) |
547 |
|
|
DiskSet.mdList.extend(raid.startAllRaid(driveList)) |
548 |
|
|
|
549 |
|
|
def stopAllRaid(self): |
550 |
|
|
"""Stop all of the raid devices associated with the DiskSet.""" |
551 |
|
|
raid.stopAllRaid(DiskSet.mdList) |
552 |
|
|
while DiskSet.mdList: |
553 |
|
|
DiskSet.mdList.pop() |
554 |
|
|
|
555 |
|
|
def getLabels(self): |
556 |
|
|
"""Return a list of all of the labels used on partitions.""" |
557 |
|
|
labels = {} |
558 |
|
|
|
559 |
|
|
drives = self.disks.keys() |
560 |
|
|
drives.sort() |
561 |
|
|
|
562 |
|
|
for drive in drives: |
563 |
|
|
disk = self.disks[drive] |
564 |
|
|
func = lambda part: (part.is_active() and |
565 |
|
|
not (part.get_flag(parted.PARTITION_RAID) |
566 |
|
|
or part.get_flag(parted.PARTITION_LVM)) |
567 |
|
|
and part.fs_type |
568 |
|
|
and (part.fs_type.name in ("ext2", |
569 |
|
|
"ext3", "xfs"))) |
570 |
|
|
parts = filter_partitions(disk, func) |
571 |
|
|
for part in parts: |
572 |
|
|
node = get_partition_name(part) |
573 |
|
|
label = isys.readFSLabel(node) |
574 |
|
|
if label: |
575 |
|
|
labels[node] = label |
576 |
|
|
|
577 |
|
|
for dev, devices, level, numActive in DiskSet.mdList: |
578 |
|
|
label = isys.readFSLabel(dev) |
579 |
|
|
if label: |
580 |
|
|
labels[dev] = label |
581 |
|
|
|
582 |
|
|
return labels |
583 |
|
|
|
584 |
|
|
def findExistingRootPartitions(self, intf, mountpoint, upgradeany = 0): |
585 |
|
|
"""Return a list of all of the partitions which look like a root fs.""" |
586 |
|
|
rootparts = [] |
587 |
|
|
|
588 |
|
|
self.startAllRaid() |
589 |
|
|
|
590 |
|
|
for dev, devices, level, numActive in self.mdList: |
591 |
|
|
(errno, msg) = (None, None) |
592 |
|
|
found = 0 |
593 |
|
|
for fs in fsset.getFStoTry(dev): |
594 |
|
|
try: |
595 |
|
|
isys.mount(dev, mountpoint, fs, readOnly = 1) |
596 |
|
|
found = 1 |
597 |
|
|
break |
598 |
|
|
except SystemError, (errno, msg): |
599 |
|
|
pass |
600 |
|
|
|
601 |
|
|
if found: |
602 |
|
|
if os.access (mountpoint + '/etc/fstab', os.R_OK): |
603 |
|
|
relstr = getCentOSReleaseString(mountpoint) |
604 |
|
|
cmdline = open('/proc/cmdline', 'r').read() |
605 |
|
|
|
606 |
|
|
if ((cmdline.find("upgradeany") != -1) or |
607 |
|
|
(upgradeany == 1) or |
608 |
|
|
(productMatches(relstr, productName))): |
609 |
|
|
rootparts.append ((dev, fs, relstr)) |
610 |
|
|
isys.umount(mountpoint) |
611 |
|
|
|
612 |
|
|
# now, look for candidate lvm roots |
613 |
|
|
lvm.vgscan() |
614 |
|
|
lvm.vgactivate() |
615 |
|
|
|
616 |
|
|
for (vg, lv, size) in lvm.lvlist(): |
617 |
|
|
dev = "/dev/%s/%s" %(vg, lv) |
618 |
|
|
found = 0 |
619 |
|
|
for fs in fsset.getFStoTry(dev): |
620 |
|
|
try: |
621 |
|
|
isys.mount(dev, mountpoint, fs, readOnly = 1) |
622 |
|
|
found = 1 |
623 |
|
|
break |
624 |
|
|
except SystemError: |
625 |
|
|
pass |
626 |
|
|
|
627 |
|
|
if found: |
628 |
|
|
if os.access (mountpoint + '/etc/fstab', os.R_OK): |
629 |
|
|
relstr = getCentOSReleaseString(mountpoint) |
630 |
|
|
cmdline = open('/proc/cmdline', 'r').read() |
631 |
|
|
|
632 |
|
|
if ((cmdline.find("upgradeany") != -1) or |
633 |
|
|
(upgradeany == 1) or |
634 |
|
|
(productMatches(relstr, productName))): |
635 |
|
|
rootparts.append ((dev, fs, relstr)) |
636 |
|
|
isys.umount(mountpoint) |
637 |
|
|
|
638 |
|
|
lvm.vgdeactivate() |
639 |
|
|
|
640 |
|
|
# don't stop raid until after we've looked for lvm on top of it |
641 |
|
|
self.stopAllRaid() |
642 |
|
|
|
643 |
|
|
drives = self.disks.keys() |
644 |
|
|
drives.sort() |
645 |
|
|
|
646 |
|
|
for drive in drives: |
647 |
|
|
disk = self.disks[drive] |
648 |
|
|
part = disk.next_partition () |
649 |
|
|
while part: |
650 |
|
|
if (part.is_active() |
651 |
|
|
and (part.get_flag(parted.PARTITION_RAID) |
652 |
|
|
or part.get_flag(parted.PARTITION_LVM))): |
653 |
|
|
pass |
654 |
|
|
elif (part.fs_type and |
655 |
|
|
part.fs_type.name in fsset.getUsableLinuxFs()): |
656 |
|
|
node = get_partition_name(part) |
657 |
|
|
try: |
658 |
|
|
isys.mount(node, mountpoint, part.fs_type.name) |
659 |
|
|
except SystemError, (errno, msg): |
660 |
|
|
intf.messageWindow(_("Error"), |
661 |
|
|
_("Error mounting file system on " |
662 |
|
|
"%s: %s") % (node, msg)) |
663 |
|
|
part = disk.next_partition(part) |
664 |
|
|
continue |
665 |
|
|
if os.access (mountpoint + '/etc/fstab', os.R_OK): |
666 |
|
|
relstr = getCentOSReleaseString(mountpoint) |
667 |
|
|
cmdline = open('/proc/cmdline', 'r').read() |
668 |
|
|
|
669 |
|
|
if ((cmdline.find("upgradeany") != -1) or |
670 |
|
|
(upgradeany == 1) or |
671 |
|
|
(productMatches(relstr, productName))): |
672 |
|
|
rootparts.append ((node, part.fs_type.name, |
673 |
|
|
relstr)) |
674 |
|
|
isys.umount(mountpoint) |
675 |
|
|
|
676 |
|
|
part = disk.next_partition(part) |
677 |
|
|
return rootparts |
678 |
|
|
|
679 |
|
|
def driveList (self): |
680 |
|
|
"""Return the list of drives on the system.""" |
681 |
|
|
drives = isys.hardDriveDict().keys() |
682 |
|
|
drives.sort (isys.compareDrives) |
683 |
|
|
return drives |
684 |
|
|
|
685 |
|
|
def drivesByName (self): |
686 |
|
|
"""Return a dictionary of the drives on the system.""" |
687 |
|
|
return isys.hardDriveDict() |
688 |
|
|
|
689 |
|
|
def addPartition (self, device, type, spec): |
690 |
|
|
"""Add a new partition to the device. - UNUSED.""" |
691 |
|
|
if not self.disks.has_key (device): |
692 |
|
|
raise PartitioningError, ("unknown device passed to " |
693 |
|
|
"addPartition: %s" % (device,)) |
694 |
|
|
disk = self.disks[device] |
695 |
|
|
|
696 |
|
|
part = disk.next_partition () |
697 |
|
|
status = 0 |
698 |
|
|
while part: |
699 |
|
|
if (part.type == parted.PARTITION_FREESPACE |
700 |
|
|
and part.geom.length >= spec.size): |
701 |
|
|
newp = disk.partition_new (type, spec.fs_type, |
702 |
|
|
part.geom.start, |
703 |
|
|
part.geom.start + spec.size) |
704 |
|
|
constraint = disk.dev.constraint_any () |
705 |
|
|
try: |
706 |
|
|
disk.add_partition (newp, constraint) |
707 |
|
|
status = 1 |
708 |
|
|
break |
709 |
|
|
except parted.error, msg: |
710 |
|
|
raise PartitioningError, msg |
711 |
|
|
part = disk.next_partition (part) |
712 |
|
|
if not status: |
713 |
|
|
raise PartitioningError, ("Not enough free space on %s to create " |
714 |
|
|
"new partition" % (device,)) |
715 |
|
|
return newp |
716 |
|
|
|
717 |
|
|
def deleteAllPartitions (self): |
718 |
|
|
"""Delete all partitions from all disks. - UNUSED.""" |
719 |
|
|
for disk in self.disks.values(): |
720 |
|
|
disk.delete_all () |
721 |
|
|
|
722 |
|
|
def savePartitions (self): |
723 |
|
|
"""Write the partition tables out to the disks.""" |
724 |
|
|
for disk in self.disks.values(): |
725 |
|
|
disk.commit() |
726 |
|
|
#disk.close() |
727 |
|
|
del disk |
728 |
|
|
self.refreshDevices() |
729 |
|
|
|
730 |
|
|
def refreshDevices (self, intf = None, initAll = 0, |
731 |
|
|
zeroMbr = 0, clearDevs = []): |
732 |
|
|
"""Reread the state of the disks as they are on disk.""" |
733 |
|
|
self.closeDevices() |
734 |
|
|
self.disks = {} |
735 |
|
|
self.openDevices(intf, initAll, zeroMbr, clearDevs) |
736 |
|
|
|
737 |
|
|
def closeDevices (self): |
738 |
|
|
"""Close all of the disks which are open.""" |
739 |
|
|
for disk in self.disks.keys(): |
740 |
|
|
#self.disks[disk].close() |
741 |
|
|
del self.disks[disk] |
742 |
|
|
|
743 |
|
|
def dasdFmt (self, intf = None, drive = None): |
744 |
|
|
"""Format dasd devices (s390).""" |
745 |
|
|
|
746 |
|
|
if self.disks.has_key(drive): |
747 |
|
|
del self.disks[drive] |
748 |
|
|
|
749 |
|
|
w = intf.progressWindow (_("Initializing"), |
750 |
|
|
_("Please wait while formatting drive %s...\n" |
751 |
|
|
) % (drive,), 100) |
752 |
|
|
try: |
753 |
|
|
isys.makeDevInode(drive, '/tmp/' + drive) |
754 |
|
|
except: |
755 |
|
|
pass |
756 |
|
|
|
757 |
|
|
argList = [ "/sbin/dasdfmt", |
758 |
|
|
"-y", |
759 |
|
|
"-b", "4096", |
760 |
|
|
"-d", "cdl", |
761 |
|
|
"-P", |
762 |
|
|
"-F", |
763 |
|
|
"-f", |
764 |
|
|
"/tmp/%s" % drive] |
765 |
|
|
|
766 |
|
|
fd = os.open("/dev/null", os.O_RDWR | os.O_CREAT | os.O_APPEND) |
767 |
|
|
p = os.pipe() |
768 |
|
|
childpid = os.fork() |
769 |
|
|
if not childpid: |
770 |
|
|
os.close(p[0]) |
771 |
|
|
os.dup2(p[1], 1) |
772 |
|
|
os.dup2(fd, 2) |
773 |
|
|
os.close(p[1]) |
774 |
|
|
os.close(fd) |
775 |
|
|
os.execv(argList[0], argList) |
776 |
|
|
log("failed to exec %s", argList) |
777 |
|
|
os._exit(1) |
778 |
|
|
|
779 |
|
|
os.close(p[1]) |
780 |
|
|
|
781 |
|
|
num = '' |
782 |
|
|
sync = 0 |
783 |
|
|
s = 'a' |
784 |
|
|
while s: |
785 |
|
|
try: |
786 |
|
|
s = os.read(p[0], 1) |
787 |
|
|
os.write(fd, s) |
788 |
|
|
|
789 |
|
|
if s != '\n': |
790 |
|
|
try: |
791 |
|
|
num = num + s |
792 |
|
|
except: |
793 |
|
|
pass |
794 |
|
|
else: |
795 |
|
|
if num: |
796 |
|
|
val = string.split(num) |
797 |
|
|
if (val[0] == 'cyl'): |
798 |
|
|
# printf("cyl %5d of %5d | %3d%%\n", |
799 |
|
|
val = int(val[5][:-1]) |
800 |
|
|
w and w.set(val) |
801 |
|
|
# sync every 10% |
802 |
|
|
if sync + 10 <= val: |
803 |
|
|
isys.sync() |
804 |
|
|
sync = val |
805 |
|
|
num = '' |
806 |
|
|
except OSError, args: |
807 |
|
|
(errno, str) = args |
808 |
|
|
if (errno != 4): |
809 |
|
|
raise IOError, args |
810 |
|
|
|
811 |
|
|
try: |
812 |
|
|
(pid, status) = os.waitpid(childpid, 0) |
813 |
|
|
except OSError, (num, msg): |
814 |
|
|
print __name__, "waitpid:", msg |
815 |
|
|
|
816 |
|
|
os.close(fd) |
817 |
|
|
|
818 |
|
|
w and w.pop() |
819 |
|
|
|
820 |
|
|
if os.WIFEXITED(status) and (os.WEXITSTATUS(status) == 0): |
821 |
|
|
return 0 |
822 |
|
|
|
823 |
|
|
return 1 |
824 |
|
|
|
825 |
|
|
def openDevices (self, intf = None, initAll = 0, |
826 |
|
|
zeroMbr = 0, clearDevs = []): |
827 |
|
|
"""Open the disks on the system and skip unopenable devices.""" |
828 |
|
|
if self.disks: |
829 |
|
|
return |
830 |
|
|
for drive in self.driveList (): |
831 |
|
|
if drive in DiskSet.skippedDisks and not initAll: |
832 |
|
|
continue |
833 |
|
|
deviceFile = isys.makeDevInode(drive) |
834 |
|
|
if isys.driveIsRemovable(drive) and not flags.expert: |
835 |
|
|
DiskSet.skippedDisks.append(drive) |
836 |
|
|
continue |
837 |
|
|
# FIXME: need the right fix for z/VM formatted dasd |
838 |
|
|
if iutil.getArch() == "s390" and drive[:4] == "dasd" and isys.getDasdState(drive): |
839 |
|
|
devs = isys.getDasdDevPort() |
840 |
|
|
if intf is None: |
841 |
|
|
DiskSet.skippedDisks.append(drive) |
842 |
|
|
continue |
843 |
|
|
rc = intf.messageWindow(_("Warning"), |
844 |
|
|
_("The partition table on device %s (%s) was unreadable. " |
845 |
|
|
"To create new partitions it must be initialized, " |
846 |
|
|
"causing the loss of ALL DATA on this drive.\n\n" |
847 |
|
|
"This operation will override any previous " |
848 |
|
|
"installation choices about which drives to " |
849 |
|
|
"ignore.\n\n" |
850 |
|
|
"Would you like to initialize this drive, " |
851 |
|
|
"erasing ALL DATA?") |
852 |
|
|
% (drive, devs[drive]), type = "yesno") |
853 |
|
|
if rc == 0: |
854 |
|
|
DiskSet.skippedDisks.append(drive) |
855 |
|
|
continue |
856 |
|
|
else: |
857 |
|
|
if (self.dasdFmt(intf, drive)): |
858 |
|
|
DiskSet.skippedDisks.append(drive) |
859 |
|
|
continue |
860 |
|
|
|
861 |
|
|
try: |
862 |
|
|
dev = parted.PedDevice.get (deviceFile) |
863 |
|
|
except parted.error, msg: |
864 |
|
|
DiskSet.skippedDisks.append(drive) |
865 |
|
|
continue |
866 |
|
|
|
867 |
|
|
if (initAll and ((clearDevs is None) or (len(clearDevs) == 0) |
868 |
|
|
or drive in clearDevs) and not flags.test): |
869 |
|
|
if iutil.getArch() == "s390" and drive[:4] == "dasd": |
870 |
|
|
if (intf is None or self.dasdFmt(intf, drive)): |
871 |
|
|
DiskSet.skippedDisks.append(drive) |
872 |
|
|
continue |
873 |
|
|
else: |
874 |
|
|
try: |
875 |
|
|
disk = dev.disk_new_fresh(getDefaultDiskType()) |
876 |
|
|
disk.commit() |
877 |
|
|
self.disks[drive] = disk |
878 |
|
|
except parted.error, msg: |
879 |
|
|
DiskSet.skippedDisks.append(drive) |
880 |
|
|
continue |
881 |
|
|
|
882 |
|
|
try: |
883 |
|
|
disk = parted.PedDisk.new(dev) |
884 |
|
|
self.disks[drive] = disk |
885 |
|
|
except parted.error, msg: |
886 |
|
|
recreate = 0 |
887 |
|
|
if zeroMbr: |
888 |
|
|
log("zeroMBR was set and invalid partition table found " |
889 |
|
|
"on %s" % (dev.path[5:])) |
890 |
|
|
recreate = 1 |
891 |
|
|
elif not intf: |
892 |
|
|
DiskSet.skippedDisks.append(drive) |
893 |
|
|
continue |
894 |
|
|
else: |
895 |
|
|
if iutil.getArch() == "s390" and drive[:4] == "dasd": |
896 |
|
|
devs = isys.getDasdDevPort() |
897 |
|
|
format = drive + " (" + devs[drive] + ")" |
898 |
|
|
else: |
899 |
|
|
format = drive |
900 |
|
|
rc = intf.messageWindow(_("Warning"), |
901 |
|
|
_("The partition table on device %s was unreadable. " |
902 |
|
|
"To create new partitions it must be initialized, " |
903 |
|
|
"causing the loss of ALL DATA on this drive.\n\n" |
904 |
|
|
"This operation will override any previous " |
905 |
|
|
"installation choices about which drives to " |
906 |
|
|
"ignore.\n\n" |
907 |
|
|
"Would you like to initialize this drive, " |
908 |
|
|
"erasing ALL DATA?") |
909 |
|
|
% (format,), type = "yesno") |
910 |
|
|
if rc == 0: |
911 |
|
|
DiskSet.skippedDisks.append(drive) |
912 |
|
|
continue |
913 |
|
|
else: |
914 |
|
|
recreate = 1 |
915 |
|
|
|
916 |
|
|
if recreate == 1 and not flags.test: |
917 |
|
|
if iutil.getArch() == "s390" and drive[:4] == "dasd": |
918 |
|
|
if (intf is None or self.dasdFmt(intf, drive)): |
919 |
|
|
DiskSet.skippedDisks.append(drive) |
920 |
|
|
continue |
921 |
|
|
else: |
922 |
|
|
try: |
923 |
|
|
disk = dev.disk_new_fresh(getDefaultDiskType()) |
924 |
|
|
disk.commit() |
925 |
|
|
except parted.error, msg: |
926 |
|
|
DiskSet.skippedDisks.append(drive) |
927 |
|
|
continue |
928 |
|
|
try: |
929 |
|
|
disk = parted.PedDisk.new(dev) |
930 |
|
|
self.disks[drive] = disk |
931 |
|
|
except parted.error, msg: |
932 |
|
|
DiskSet.skippedDisks.append(drive) |
933 |
|
|
continue |
934 |
|
|
|
935 |
|
|
filter_partitions(disk, validateFsType) |
936 |
|
|
|
937 |
|
|
# check that their partition table is valid for their architecture |
938 |
|
|
ret = checkDiskLabel(disk, intf) |
939 |
|
|
if ret == 1: |
940 |
|
|
DiskSet.skippedDisks.append(drive) |
941 |
|
|
continue |
942 |
|
|
elif ret == -1: |
943 |
|
|
if iutil.getArch() == "s390" and drive[:4] == "dasd": |
944 |
|
|
if (intf is None or self.dasdFmt(intf, drive)): |
945 |
|
|
DiskSet.skippedDisks.append(drive) |
946 |
|
|
continue |
947 |
|
|
else: |
948 |
|
|
try: |
949 |
|
|
disk = dev.disk_new_fresh(getDefaultDiskType()) |
950 |
|
|
disk.commit() |
951 |
|
|
except parted.error, msg: |
952 |
|
|
DiskSet.skippedDisks.append(drive) |
953 |
|
|
continue |
954 |
|
|
try: |
955 |
|
|
disk = parted.PedDisk.new(dev) |
956 |
|
|
self.disks[drive] = disk |
957 |
|
|
except parted.error, msg: |
958 |
|
|
DiskSet.skippedDisks.append(drive) |
959 |
|
|
continue |
960 |
|
|
|
961 |
|
|
def partitionTypes (self): |
962 |
|
|
"""Return list of (partition, partition type) tuples for all parts.""" |
963 |
|
|
rc = [] |
964 |
|
|
drives = self.disks.keys() |
965 |
|
|
drives.sort() |
966 |
|
|
|
967 |
|
|
for drive in drives: |
968 |
|
|
disk = self.disks[drive] |
969 |
|
|
part = disk.next_partition () |
970 |
|
|
while part: |
971 |
|
|
if part.type in (parted.PARTITION_PRIMARY, |
972 |
|
|
parted.PARTITION_LOGICAL): |
973 |
|
|
device = get_partition_name(part) |
974 |
|
|
if part.fs_type: |
975 |
|
|
ptype = part.fs_type.name |
976 |
|
|
else: |
977 |
|
|
ptype = None |
978 |
|
|
rc.append((device, ptype)) |
979 |
|
|
part = disk.next_partition (part) |
980 |
|
|
|
981 |
|
|
return rc |
982 |
|
|
|
983 |
|
|
def diskState (self): |
984 |
|
|
"""Print out current disk state. DEBUG.""" |
985 |
|
|
rc = "" |
986 |
|
|
for disk in self.disks.values(): |
987 |
|
|
rc = rc + ("%s: %s length %ld, maximum " |
988 |
|
|
"primary partitions: %d\n" % |
989 |
|
|
(disk.dev.path, |
990 |
|
|
disk.dev.model, |
991 |
|
|
disk.dev.length, |
992 |
|
|
disk.max_primary_partition_count)) |
993 |
|
|
|
994 |
|
|
part = disk.next_partition() |
995 |
|
|
if part: |
996 |
|
|
rc = rc + ("Device Type Filesystem Start " |
997 |
|
|
"End Length Flags\n") |
998 |
|
|
rc = rc + ("------ ---- ---------- ----- " |
999 |
|
|
"--- ------ -----\n") |
1000 |
|
|
while part: |
1001 |
|
|
if not part.type & parted.PARTITION_METADATA: |
1002 |
|
|
device = "" |
1003 |
|
|
fs_type_name = "" |
1004 |
|
|
if part.num > 0: |
1005 |
|
|
device = get_partition_name(part) |
1006 |
|
|
if part.fs_type: |
1007 |
|
|
fs_type_name = part.fs_type.name |
1008 |
|
|
partFlags = get_flags (part) |
1009 |
|
|
rc = rc + ("%-9s %-12s %-12s %-10ld %-10ld %-10ld %7s\n" |
1010 |
|
|
% (device, part.type_name, fs_type_name, |
1011 |
|
|
part.geom.start, part.geom.end, part.geom.length, |
1012 |
|
|
partFlags)) |
1013 |
|
|
part = disk.next_partition(part) |
1014 |
|
|
return rc |
1015 |
|
|
|
1016 |
|
|
def checkNoDisks(self, intf): |
1017 |
|
|
"""Check that there are valid disk devices.""" |
1018 |
|
|
if len(self.disks.keys()) == 0: |
1019 |
|
|
intf.messageWindow(_("No Drives Found"), |
1020 |
|
|
_("An error has occurred - no valid devices were " |
1021 |
|
|
"found on which to create new file systems. " |
1022 |
|
|
"Please check your hardware for the cause " |
1023 |
|
|
"of this problem.")) |
1024 |
|
|
sys.exit(0) |
1025 |
|
|
|
1026 |
|
|
|
1027 |
|
|
|
1028 |
|
|
|
1029 |
|
|
|
1030 |
|
|
# XXX is this all of the possibilities? |
1031 |
|
|
dosPartitionTypes = [ 1, 6, 7, 11, 12, 14, 15 ] |
1032 |
|
|
|
1033 |
|
|
# master list of partition types |
1034 |
|
|
allPartitionTypesDict = { |
1035 |
|
|
0 : "Empty", |
1036 |
|
|
1: "DOS 12-bit FAT", |
1037 |
|
|
2: "XENIX root", |
1038 |
|
|
3: "XENIX usr", |
1039 |
|
|
4: "DOS 16-bit <32M", |
1040 |
|
|
5: "Extended", |
1041 |
|
|
6: "DOS 16-bit >=32M", |
1042 |
|
|
7: "NTFS/HPFS", |
1043 |
|
|
8: "AIX", |
1044 |
|
|
9: "AIX bootable", |
1045 |
|
|
10: "OS/2 Boot Manager", |
1046 |
|
|
0xb: "Win95 FAT32", |
1047 |
|
|
0xc: "Win95 FAT32", |
1048 |
|
|
0xe: "Win95 FAT16", |
1049 |
|
|
0xf: "Win95 Ext'd", |
1050 |
|
|
0x10: "OPUS", |
1051 |
|
|
0x11: "Hidden FAT12", |
1052 |
|
|
0x12: "Compaq Setup", |
1053 |
|
|
0x14: "Hidden FAT16 <32M", |
1054 |
|
|
0x16: "Hidden FAT16", |
1055 |
|
|
0x17: "Hidden HPFS/NTFS", |
1056 |
|
|
0x18: "AST SmartSleep", |
1057 |
|
|
0x1b: "Hidden Win95 FAT32", |
1058 |
|
|
0x1c: "Hidden Win95 FAT32 (LBA)", |
1059 |
|
|
0x1e: "Hidden Win95 FAT16 (LBA)", |
1060 |
|
|
0x24: "NEC_DOS", |
1061 |
|
|
0x39: "Plan 9", |
1062 |
|
|
0x40: "Venix 80286", |
1063 |
|
|
0x41: "PPC_PReP Boot", |
1064 |
|
|
0x42: "SFS", |
1065 |
|
|
0x4d: "QNX4.x", |
1066 |
|
|
0x4e: "QNX4.x 2nd part", |
1067 |
|
|
0x4f: "QNX4.x 2nd part", |
1068 |
|
|
0x51: "Novell?", |
1069 |
|
|
0x52: "Microport", |
1070 |
|
|
0x63: "GNU HURD", |
1071 |
|
|
0x64: "Novell Netware 286", |
1072 |
|
|
0x65: "Novell Netware 386", |
1073 |
|
|
0x75: "PC/IX", |
1074 |
|
|
0x80: "Old MINIX", |
1075 |
|
|
0x81: "Linux/MINIX", |
1076 |
|
|
0x82: "Linux swap", |
1077 |
|
|
0x83: "Linux native", |
1078 |
|
|
0x84: "OS/2 hidden C:", |
1079 |
|
|
0x85: "Linux Extended", |
1080 |
|
|
0x86: "NTFS volume set", |
1081 |
|
|
0x87: "NTFS volume set", |
1082 |
|
|
0x8e: "Linux LVM", |
1083 |
|
|
0x93: "Amoeba", |
1084 |
|
|
0x94: "Amoeba BBT", |
1085 |
|
|
0x9f: "BSD/OS", |
1086 |
|
|
0xa0: "IBM Thinkpad hibernation", |
1087 |
|
|
0xa5: "BSD/386", |
1088 |
|
|
0xa6: "OpenBSD", |
1089 |
|
|
0xb7: "BSDI fs", |
1090 |
|
|
0xb8: "BSDI swap", |
1091 |
|
|
0xc7: "Syrinx", |
1092 |
|
|
0xdb: "CP/M", |
1093 |
|
|
0xde: "Dell Utility", |
1094 |
|
|
0xe1: "DOS access", |
1095 |
|
|
0xe3: "DOS R/O", |
1096 |
|
|
0xeb: "BEOS", |
1097 |
|
|
0xee: "EFI GPT", |
1098 |
|
|
0xef: "EFI (FAT-12/16/32)", |
1099 |
|
|
0xf2: "DOS secondary", |
1100 |
|
|
0xfd: "Linux RAID", |
1101 |
|
|
0xff: "BBT" |
1102 |
|
|
} |
1103 |
|
|
|
1104 |
|
|
max_logical_partition_count = { |
1105 |
|
|
"hd": 59, |
1106 |
|
|
"sd": 11, |
1107 |
|
|
"ataraid/": 11, |
1108 |
|
|
"rd/": 3, |
1109 |
|
|
"cciss/": 11, |
1110 |
|
|
"i2o/": 11, |
1111 |
|
|
"iseries/vd": 3, |
1112 |
|
|
"ida/": 11, |
1113 |
|
|
"sx8/": 11, |
1114 |
|
|
} |