/[gli]/trunk/src/GLIStorageDevice.py
Gentoo

Diff of /trunk/src/GLIStorageDevice.py

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 596 Revision 826
1import commands, string, os, parted 1import commands, string, os, parted
2from GLIException import * 2from GLIException import *
3import GLIUtility 3import GLIUtility
4 4
5MEGABYTE = 1024 * 1024 5MEGABYTE = 1024 * 1024
6
7# these are here so that we can change them easily in future
8# the values were chosen to represent perfect floating point representations
9FREE_MINOR_FRAC_PRI = 1.0/32.0
10FREE_MINOR_FRAC_LOG = 1.0/8.0
6 11
7archinfo = { 'sparc': { 'fixedparts': [ { 'minor': 3, 'type': "wholedisk" } ], 'disklabel': 'sun', 'extended': False }, 12archinfo = { 'sparc': { 'fixedparts': [ { 'minor': 3, 'type': "wholedisk" } ], 'disklabel': 'sun', 'extended': False },
8 'hppa': { 'fixedparts': [ { 'minor': 1, 'type': "boot" } ], 'disklabel': 'msdos', 'extended': False }, 13 'hppa': { 'fixedparts': [ { 'minor': 1, 'type': "boot" } ], 'disklabel': 'msdos', 'extended': False },
9 'x86': { 'fixedparts': [], 'disklabel': 'msdos', 'extended': True }, 14 'x86': { 'fixedparts': [], 'disklabel': 'msdos', 'extended': True },
10 'amd64': { 'fixedparts': [], 'disklabel': 'msdos', 'extended': True }, 15 'amd64': { 'fixedparts': [], 'disklabel': 'msdos', 'extended': True },
32 37
33 ## 38 ##
34 # Initialization function for GLIStorageDevice class 39 # Initialization function for GLIStorageDevice class
35 # @param device Device node (e.g. /dev/hda) of device being represented 40 # @param device Device node (e.g. /dev/hda) of device being represented
36 # @param arch="x86" Architecture that we're partition for (defaults to 'x86' for now) 41 # @param arch="x86" Architecture that we're partition for (defaults to 'x86' for now)
37 def __init__(self, device, arch="x86", set_geometry=True): 42 def __init__(self, device, arch="x86", set_geometry=True, virtual=False, size_known=False):
38 self._device = device 43 self._device = device
39 self._partitions = {} 44 self._partitions = {}
40 self._geometry = {'cylinders': 0, 'heads': 0, 'sectors': 0, 'sectorsize': 512} 45 self._geometry = {'cylinders': 0, 'heads': 0, 'sectors': 0, 'sectorsize': 512}
41 self._total_bytes = 0 46 self._total_bytes = 0
42 self._cylinder_bytes = 0 47 self._cylinder_bytes = 0
57 self._geometry['heads'], self._geometry['sectors'], self._geometry['cylinders'] = self._parted_dev.heads, self._parted_dev.sectors, self._parted_dev.cylinders 62 self._geometry['heads'], self._geometry['sectors'], self._geometry['cylinders'] = self._parted_dev.heads, self._parted_dev.sectors, self._parted_dev.cylinders
58 self._sector_bytes = self._parted_dev.sector_size 63 self._sector_bytes = self._parted_dev.sector_size
59 self._cylinder_bytes = self._geometry['heads'] * self._geometry['sectors'] * self._sector_bytes 64 self._cylinder_bytes = self._geometry['heads'] * self._geometry['sectors'] * self._sector_bytes
60 self._total_sectors = self._parted_dev.length 65 self._total_sectors = self._parted_dev.length
61 self._sectors_in_cylinder = self._geometry['heads'] * self._geometry['sectors'] 66 self._sectors_in_cylinder = self._geometry['heads'] * self._geometry['sectors']
62 self._total_mb = int(self._total_bytes / MEGABYTE) 67 self._total_mb = long(self._total_bytes / MEGABYTE)
63 68
64 ## 69 ##
65 # Sets partition info from disk. 70 # Sets partition info from disk.
66 def set_partitions_from_disk(self): 71 def set_partitions_from_disk(self):
67 last_part = 0 72 last_part = 0
68 last_log_part = 4 73 last_log_part = 4
69 parted_part = self._parted_disk.next_partition() 74 parted_part = self._parted_disk.next_partition()
70 while parted_part: 75 while parted_part:
71 part_mb = int((parted_part.geom.end - parted_part.geom.start + 1) * self._sector_bytes / MEGABYTE) 76 part_mb = long((parted_part.geom.end - parted_part.geom.start + 1) * self._sector_bytes / MEGABYTE)
72 if parted_part.num >= 1: 77 if parted_part.num >= 1:
73 fs_type = "" 78 fs_type = ""
74 if parted_part.fs_type != None: fs_type = parted_part.fs_type.name 79 if parted_part.fs_type != None: fs_type = parted_part.fs_type.name
75 if parted_part.type == 2: fs_type = "extended" 80 if parted_part.type == 2: fs_type = "extended"
76 if archinfo[self._arch]['extended'] and parted_part.num > 4: 81 if archinfo[self._arch]['extended'] and parted_part.num > 4:
77 last_log_part = parted_part.num 82 last_log_part = parted_part.num
78 else: 83 else:
79 last_part = parted_part.num 84 last_part = parted_part.num
80 self._partitions[int(parted_part.num)] = Partition(self, parted_part.num, part_mb, parted_part.geom.start, parted_part.geom.end, fs_type, format=False, existing=True) 85 self._partitions[int(parted_part.num)] = Partition(self, parted_part.num, part_mb, parted_part.geom.start, parted_part.geom.end, fs_type, format=False, existing=True)
81 elif parted_part.type_name == "free": 86 elif parted_part.type_name == "free":
82 parent_part = self.get_partition_at(parted_part.geom.start, ignore_extended=0) 87# parent_part = self.get_partition_at(parted_part.geom.start, ignore_extended=0)
83 if parent_part: 88# if parent_part:
89 if self.get_extended_partition() and parted_part.geom.start >= self._partitions[self.get_extended_partition()].get_start() and parted_part.geom.end <= self._partitions[self.get_extended_partition()].get_end():
84 self._partitions[last_log_part+0.9] = Partition(self, last_log_part+0.9, part_mb, parted_part.geom.start, parted_part.geom.end, "free", format=False, existing=False) 90 self._partitions[last_log_part+FREE_MINOR_FRAC_LOG] = Partition(self, last_log_part+FREE_MINOR_FRAC_LOG, part_mb, parted_part.geom.start, parted_part.geom.end, "free", format=False, existing=False)
85 last_log_part += 1 91 last_log_part += 1
86 else: 92 else:
87 self._partitions[last_part+0.1] = Partition(self, last_part+0.1, part_mb, parted_part.geom.start, parted_part.geom.end, "free", format=False, existing=False) 93 self._partitions[last_part+FREE_MINOR_FRAC_PRI] = Partition(self, last_part+FREE_MINOR_FRAC_PRI, part_mb, parted_part.geom.start, parted_part.geom.end, "free", format=False, existing=False)
88 last_part += 1 94 last_part += 1
89 parted_part = self._parted_disk.next_partition(parted_part) 95 parted_part = self._parted_disk.next_partition(parted_part)
90 96
91 ## 97 ##
92 # Imports partition info from the install profile partition structure (currently does nothing) 98 # Imports partition info from the install profile partition structure
93 # @param ips Parameter structure returned from install_profile.get_partition_tables() 99 # @param ips Parameter structure returned from install_profile.get_partition_tables()
94 def set_partitions_from_install_profile_structure(self, ips): 100 def set_partitions_from_install_profile_structure(self, ips):
95 for part in ips: 101 for part in ips:
96 tmppart = ips[part] 102 tmppart = ips[part]
97 existing = False 103 existing = False
98 if tmppart['origminor'] and not tmppart['format']: 104 if tmppart['origminor'] and not tmppart['format']:
99 existing = True 105 existing = True
100 self._partitions[tmppart['minor']] = Partition(self, tmppart['minor'], tmppart['mb'], tmppart['start'], tmppart['end'], tmppart['type'], format=tmppart['format'], origminor=tmppart['origminor'], existing=existing, mountpoint=tmppart['mountpoint'], mountopts=['mountopts']) 106 self._partitions[tmppart['minor']] = Partition(self, tmppart['minor'], tmppart['mb'], tmppart['start'], tmppart['end'], tmppart['type'], format=tmppart['format'], origminor=tmppart['origminor'], existing=existing, mountpoint=tmppart['mountpoint'], mountopts=tmppart['mountopts'], mkfsopts=tmppart['mkfsopts'])
101 107
102 ## 108 ##
103 # Returns name of device (e.g. /dev/hda) being represented 109 # Returns name of device (e.g. /dev/hda) being represented
104 def get_device(self): 110 def get_device(self):
105 return self._device 111 return self._device
116 for part in parts: 122 for part in parts:
117 if archinfo[self._arch]['extended'] and part > 4: break 123 if archinfo[self._arch]['extended'] and part > 4: break
118 tmppart = self._partitions[part] 124 tmppart = self._partitions[part]
119 if tmppart.get_type() == "extended": 125 if tmppart.get_type() == "extended":
120 for part_log in parts: 126 for part_log in parts:
121 if part_log < 4.9: continue 127 if part_log < (4 + FREE_MINOR_FRAC_LOG): continue
122 tmppart_log = self._partitions[part_log] 128 tmppart_log = self._partitions[part_log]
123 if tmppart_log.get_type() == "free": 129 if tmppart_log.get_type() == "free":
124 if last_log_minor < last_log_free: 130 if last_log_minor < last_log_free:
125 self._partitions[last_log_free].set_mb(self._partitions[last_log_free].get_mb()+tmppart_log.get_mb()) 131 self._partitions[last_log_free].set_mb(self._partitions[last_log_free].get_mb()+tmppart_log.get_mb())
126 del self._partitions[part_log] 132 del self._partitions[part_log]
127 else: 133 else:
128 if not last_log_free: 134 if not last_log_free:
129 last_log_free = last_log_minor + 0.9 135 last_log_free = last_log_minor + FREE_MINOR_FRAC_LOG
130 else: 136 else:
131 lost_log_free = part_log 137 last_log_free = part_log
132 tmppart_log.set_minor(last_log_free) 138 tmppart_log.set_minor(last_log_free)
133 self._partitions[last_log_free] = tmppart_log 139 self._partitions[last_log_free] = tmppart_log
134 if part_log != last_log_free: del self._partitions[part_log] 140 if part_log != last_log_free: del self._partitions[part_log]
135 continue
136 else: 141 else:
137 if part_log > (last_log_minor + 1): 142 if part_log > (last_log_minor + 1):
138 tmppart_log.set_minor(last_log_minor + 1) 143 tmppart_log.set_minor(last_log_minor + 1)
139 last_log_minor = last_log_minor + 1 144 last_log_minor = last_log_minor + 1
140 self._partitions[last_log_minor] = tmppart_log 145 self._partitions[last_log_minor] = tmppart_log
141 del self._partitions[part_log] 146 del self._partitions[part_log]
142 continue
143 else: 147 else:
144 last_log_minor = part_log 148 last_log_minor = part_log
145 if tmppart.get_type() == "free": 149 elif tmppart.get_type() == "free":
146 if last_minor < last_free: 150 if last_minor < last_free:
147 self._partitions[last_free].set_mb(self._partitions[last_free].get_mb()+tmppart.get_mb()) 151 self._partitions[last_free].set_mb(self._partitions[last_free].get_mb()+tmppart.get_mb())
148 del self._partitions[part] 152 del self._partitions[part]
149 else: 153 else:
150 if not last_free: 154 if not last_free:
151 last_free = last_minor + 0.1 155 last_free = last_minor + FREE_MINOR_FRAC_PRI
152 else: 156 else:
153 last_free = part 157 last_free = part
154 tmppart.set_minor(last_free) 158 tmppart.set_minor(last_free)
155 self._partitions[last_free] = tmppart 159 self._partitions[last_free] = tmppart
156 if part != last_free: del self._partitions[part] 160 if part != last_free: del self._partitions[part]
157 continue
158 else: 161 else:
159 if part > (last_minor + 1): 162 if part > (last_minor + 1):
160 tmppart.set_minor(last_minor + 1) 163 tmppart.set_minor(last_minor + 1)
161 last_minor = last_minor + 1 164 last_minor = last_minor + 1
162 self._partitions[last_minor] = tmppart 165 self._partitions[last_minor] = tmppart
163 del self._partitions[part] 166 del self._partitions[part]
164 continue
165 else: 167 else:
166 last_minor = part 168 last_minor = part
167 169
168 ## 170 ##
169 # Adds a new partition to the partition info 171 # Adds a new partition to the partition info
172 # @param start Start sector (only used for existing partitions) 174 # @param start Start sector (only used for existing partitions)
173 # @param end End sector (only used for existing partitions) 175 # @param end End sector (only used for existing partitions)
174 # @param type Partition type (ext2, ext3, fat32, linux-swap, free, extended, etc.) 176 # @param type Partition type (ext2, ext3, fat32, linux-swap, free, extended, etc.)
175 # @param mountpoint='' Partition mountpoint 177 # @param mountpoint='' Partition mountpoint
176 # @param mountopts='' Partition mount options 178 # @param mountopts='' Partition mount options
179 # @param mkfsopts='' Additional mkfs options
177 def add_partition(self, free_minor, mb, start, end, type, mountpoint='', mountopts=''): 180 def add_partition(self, free_minor, mb, start, end, type, mountpoint='', mountopts='',mkfsopts=''):
178 free_minor = free_minor
179 new_minor = int(free_minor) + 1 181 new_minor = int(free_minor) + 1
180# print "add_partition(): free_minor=" + str(free_minor) + ", new_minor=" + str(new_minor)
181 if self._partitions.has_key(new_minor): 182 if self._partitions.has_key(new_minor):
182 parts = self._partitions.keys() 183 parts = self._partitions.keys()
183 parts.sort() 184 parts.sort()
184 parts.reverse() 185 parts.reverse()
185 hole_at = 0 186 hole_at = 0
198 if i == new_minor: stopscooting = 1 199 if i == new_minor: stopscooting = 1
199 if mb != self._partitions[free_minor].get_mb(): 200 if mb != self._partitions[free_minor].get_mb():
200 old_free_mb = self._partitions[free_minor].get_mb() 201 old_free_mb = self._partitions[free_minor].get_mb()
201 del self._partitions[free_minor] 202 del self._partitions[free_minor]
202 if archinfo[self._arch]['extended'] and new_minor >= 5: 203 if archinfo[self._arch]['extended'] and new_minor >= 5:
203 free_minor = new_minor + 0.9 204 free_minor = new_minor + FREE_MINOR_FRAC_LOG
204 else: 205 else:
205 free_minor = new_minor + 0.1 206 free_minor = new_minor + FREE_MINOR_FRAC_PRI
206 self._partitions[free_minor] = Partition(self, free_minor, old_free_mb-mb, 0, 0, "free") 207 self._partitions[free_minor] = Partition(self, free_minor, old_free_mb-mb, 0, 0, "free")
207# print "add_partition(): new part doesn't use all freespace. new free part is: minor=" + str(free_minor)
208 else: 208 else:
209 del self._partitions[free_minor] 209 del self._partitions[free_minor]
210 self._partitions[new_minor] = Partition(self, new_minor, mb, start, end, type, mountpoint=mountpoint, mountopts=mountopts) 210 self._partitions[new_minor] = Partition(self, new_minor, mb, start, end, type, mountpoint=mountpoint, mountopts=mountopts,mkfsopts=mkfsopts)
211 if type == "extended": 211 if type == "extended":
212 self._partitions[4.9] = Partition(self, 4.9, mb, 0, 0, "free") 212 self._partitions[4 + FREE_MINOR_FRAC_LOG] = Partition(self, (4 + FREE_MINOR_FRAC_LOG), mb, 0, 0, "free")
213 self.tidy_partitions() 213 self.tidy_partitions()
214 214
215 ## 215 ##
216 # Removes partition from partition info 216 # Removes partition from partition info
217 # @param minor Minor of partition to remove 217 # @param minor Minor of partition to remove
218 def remove_partition(self, minor): 218 def remove_partition(self, minor):
219 tmppart = self._partitions[int(minor)] 219 tmppart = self._partitions[int(minor)]
220 free_minor = 0 220 free_minor = 0
221 if tmppart.is_logical(): 221 if tmppart.is_logical():
222 free_minor = minor-0.1 222 free_minor = int(minor-1)+FREE_MINOR_FRAC_LOG
223 else: 223 else:
224 free_minor = minor-0.9 224 free_minor = int(minor-1)+FREE_MINOR_FRAC_PRI
225 if free_minor in self._partitions:
226 self._partitions[free_minor].set_mb(self._partitions[free_minor].get_mb() + tmppart.get_mb())
227 else:
225 self._partitions[free_minor] = Partition(self, free_minor, tmppart.get_mb(), 0, 0, "free", format=False, existing=False) 228 self._partitions[free_minor] = Partition(self, free_minor, tmppart.get_mb(), 0, 0, "free", format=False, existing=False)
226 del self._partitions[int(minor)] 229 del self._partitions[int(minor)]
227 self.tidy_partitions() 230 self.tidy_partitions()
228 231
229 ## 232 ##
230 # Returns free space (no longer used) 233 # Returns an ordered list (disk order) of partition minors
231 # @param start Start sector for search 234 def get_ordered_partition_list(self):
232 def get_free_space(self, start):
233 GAP_SIZE = 100
234 parts = self._partitions.keys() 235 parts = self._partitions.keys()
235 parts.sort() 236 parts.sort()
236 lastend_pri = 0 237 partlist = []
237 lastend_log = 0
238 free_start = -1
239 free_end = -1
240 if start > self._total_sectors: return (-1, -1)
241 for part in parts:
242 if part > 4: break
243 tmppart = self._partitions[part]
244 if (tmppart.get_start() > (lastend_pri + GAP_SIZE)) and (lastend_pri >= start):
245 free_start = lastend_pri
246 free_end = tmppart.get_start() - 1
247 break
248 if tmppart.is_extended() and start < tmppart.get_end():
249 lastend_log = tmppart.get_start()
250 for part_log in parts:
251 if part_log < 5: continue
252 tmppart_log = self._partitions[part_log]
253 if (tmppart_log.get_start() > (lastend_log + GAP_SIZE)) and (lastend_log >= start):
254 free_start = lastend_log
255 free_end = tmppart_log.get_start() - 1
256 break
257 lastend_log = tmppart_log.get_end() + 1
258 if free_start == -1 and lastend_log < tmppart.get_end():
259 free_start = lastend_log
260 free_end = tmppart.get_end()
261 break
262 lastend_pri = tmppart.get_end() + 1
263 if free_start == -1 and lastend_pri < self._total_sectors:
264 free_start = lastend_pri
265 free_end = self._total_sectors
266 return (free_start, free_end)
267
268 ##
269 # Gets partition containing a certain sector (no longer used)
270 # @param sector Sector to look at
271 # @param ignore_extended=1 Ignore extended partitions
272 def get_partition_at(self, sector, ignore_extended=1):
273 parts = self._partitions.keys()
274 parts.sort()
275 for part in parts:
276 tmppart = self._partitions[part]
277 if ignore_extended and tmppart.is_extended(): continue
278 if (sector >= tmppart.get_start()) and (sector <= tmppart.get_end()):
279 return part
280 return 0
281
282 ##
283 # Returns free minor (no longer used)
284 # @param start Parameter description
285 # @param end Parameter description
286 def get_free_minor_at(self, start, end):
287 parts = self._partitions.keys()
288 parts.sort()
289 minor = 1
290 lastpart = 0
291 for part in parts:
292 if part > 4: break
293 tmppart = self._partitions[part]
294 if end < tmppart.get_start():
295 minor = part
296 if (minor - 1) > lastpart: minor = lastpart + 1
297 break
298 if tmppart.is_extended() and start < tmppart.get_end():
299 minor = 5
300 lastpart = 4
301 for part_log in parts:
302 if part_log < 5: continue
303 tmppart_log = self._partitions[part_log]
304 if end < tmppart_log.get_start():
305 minor = part_log
306 if (minor - 1) > lastpart: minor = lastpart + 1
307 break
308 minor = part_log + 1
309 lastpart = part_log
310 break
311 minor = part + 1
312 lastpart = part
313 return minor
314
315 ##
316 # Returns an ordered list (disk order) of partition minors
317 def get_ordered_partition_list(self):
318 parts = self._partitions.keys()
319 parts.sort()
320 partlist = []
321 tmppart = None 238 tmppart = None
322 for part in parts: 239 for part in parts:
323 if archinfo[self._arch]['extended'] and part > 4.1: break 240 if archinfo[self._arch]['extended'] and part > (4 + FREE_MINOR_FRAC_PRI): break
324 tmppart = self._partitions[part] 241 tmppart = self._partitions[part]
325 partlist.append(part) 242 partlist.append(part)
326 if tmppart.is_extended(): 243 if tmppart.is_extended():
327 for part_log in parts: 244 for part_log in parts:
328 if part_log < 4.9: continue 245 if part_log < (4 + FREE_MINOR_FRAC_LOG): continue
329 partlist.append(part_log) 246 partlist.append(part_log)
330 return partlist 247 return partlist
331 248
332 ## 249 ##
333 # Returns partition info in a format suitable for passing to install_profile.set_partition_tables() 250 # Returns partition info in a format suitable for passing to install_profile.set_partition_tables()
334 def get_install_profile_structure(self): 251 def get_install_profile_structure(self):
335 devdic = {} 252 devdic = {}
336 for part in self._partitions: 253 for part in self._partitions:
337 tmppart = self._partitions[part] 254 tmppart = self._partitions[part]
338 devdic[part] = { 'mb': tmppart.get_mb(), 'minor': float(part), 'origminor': tmppart.get_orig_minor(), 'start': tmppart.get_start(), 'end': tmppart.get_end(), 'type': tmppart.get_type(), 'mountpoint': tmppart.get_mountpoint(), 'mountopts': tmppart.get_mountopts(), 'format': tmppart.get_format() } 255 devdic[part] = { 'mb': tmppart.get_mb(), 'minor': float(part), 'origminor': tmppart.get_orig_minor(), 'type': tmppart.get_type(), 'mountpoint': tmppart.get_mountpoint(), 'mountopts': tmppart.get_mountopts(), 'format': tmppart.get_format(), 'mkfsopts': tmppart.get_mkfsopts(), 'start': 0, 'end': 0 }
339 return devdic 256 return devdic
340 257
341 ## 258 ##
342 # Returns the minor of the extended partition, if any 259 # Returns the minor of the extended partition, if any
343 def get_extended_partition(self): 260 def get_extended_partition(self):
346 if tmppart.is_extended(): 263 if tmppart.is_extended():
347 return part 264 return part
348 return 0 265 return 0
349 266
350 ## 267 ##
268 # Returns the drive model
269 def get_model(self):
270 return self._parted_dev.model
271
272 ##
351 # Sets the disklabel type 273 # Sets the disklabel type
352 def set_disklabel(self, disklabel): 274 def set_disklabel(self, disklabel):
353 self._disklabel = disklabel 275 self._disklabel = disklabel
354 276
355 ## 277 ##
358 return self._disklabel 280 return self._disklabel
359 281
360 ## 282 ##
361 # Returns the number of sectors on the device 283 # Returns the number of sectors on the device
362 def get_num_sectors(self): 284 def get_num_sectors(self):
363 return int(self._total_sectors) 285 return long(self._total_sectors)
364 286
365 ## 287 ##
366 # Returns the size of a cylinder in bytes 288 # Returns the size of a cylinder in bytes
367 def get_cylinder_size(self): 289 def get_cylinder_size(self):
368 return int(self._cylinder_bytes) 290 return long(self._cylinder_bytes)
369 291
370 ## 292 ##
371 # Returns the size of a sector in bytes 293 # Returns the size of a sector in bytes
372 def get_sector_size(self): 294 def get_sector_size(self):
373 return int(self._sector_bytes) 295 return long(self._sector_bytes)
374 296
375 ## 297 ##
376 # Returns the number of cylinders 298 # Returns the number of cylinders
377 def get_num_cylinders(self): 299 def get_num_cylinders(self):
378 return int(self._geometry['cylinders']) 300 return long(self._geometry['cylinders'])
379 301
380 ## 302 ##
381 # Returns the total number of bytes on the device 303 # Returns the total number of bytes on the device
382 def get_drive_bytes(self): 304 def get_drive_bytes(self):
383 return int(self._total_bytes) 305 return long(self._total_bytes)
384 306
385 ## 307 ##
386 # Returns the total number of MB on the device 308 # Returns the total number of MB on the device
387 def get_total_mb(self): 309 def get_total_mb(self):
388 return self._total_mb 310 return self._total_mb
394 316
395 ## 317 ##
396 # Prints disk geometry to STDOUT (no longer used) 318 # Prints disk geometry to STDOUT (no longer used)
397 def print_geometry(self): 319 def print_geometry(self):
398 print self._total_bytes, self._geometry 320 print self._total_bytes, self._geometry
399
400 ##
401 # Utility function for running a command and returning it's output as a list
402 # @param cmd Command to run
403 def _run(self, cmd):
404 "Runs a command and returns the output"
405
406 # Run command
407 output_string = commands.getoutput(cmd)
408
409 # What we will return
410 output_list = []
411
412 # As long as there is a new line in the output_string
413 while output_string.find("\n") != -1:
414
415 # Find the \n in the string
416 index = output_string.find("\n") + 1
417
418 # Add the line to the output and remove it from
419 # the output_string
420 output_list.append(output_string[:index])
421 output_string = output_string[index:]
422
423 # return output
424 return output_list
425 321
426## 322##
427# This class represents a partition within a GLIStorageDevice object 323# This class represents a partition within a GLIStorageDevice object
428class Partition: 324class Partition:
429 "Class representing a single partition within a Device object" 325 "Class representing a single partition within a Device object"
438 _mountopts = None 334 _mountopts = None
439 _format = None 335 _format = None
440 _resizeable = None 336 _resizeable = None
441 _min_mb_for_resize = 0 337 _min_mb_for_resize = 0
442 _mb = 0 338 _mb = 0
339 _mkfsopts = None
443 340
444 ## 341 ##
445 # Initialization function for the Partition class 342 # Initialization function for the Partition class
446 # @param device Parent GLIStorageDevice object 343 # @param device Parent GLIStorageDevice object
447 # @param minor Minor of partition 344 # @param minor Minor of partition
449 # @param start Parameter Start sector of partition 346 # @param start Parameter Start sector of partition
450 # @param end Parameter Start sector of partition 347 # @param end Parameter Start sector of partition
451 # @param type Parameter Type of partition (ext2, ext3, fat32, linux-swap, free, extended, etc.) 348 # @param type Parameter Type of partition (ext2, ext3, fat32, linux-swap, free, extended, etc.)
452 # @param mountpoint='' Mountpoint of partition 349 # @param mountpoint='' Mountpoint of partition
453 # @param mountopts='' Mount options of partition 350 # @param mountopts='' Mount options of partition
351 # @param mkfsopts='' Additional mkfs options
454 # @param format=True Format partition 352 # @param format=True Format partition
455 # @param existing=False This partition exists on disk 353 # @param existing=False This partition exists on disk
456 def __init__(self, device, minor, mb, start, end, type, mountpoint='', mountopts='', format=True, existing=False, origminor=0): 354 def __init__(self, device, minor, mb, start, end, type, mountpoint='', mountopts='', format=True, existing=False, origminor=0, mkfsopts=''):
457 self._device = device 355 self._device = device
458 self._minor = float(minor) 356 self._minor = float(minor)
459 self._start = int(start) 357 self._start = long(start)
460 self._end = int(end) 358 self._end = long(end)
461 self._type = type or "unknown" 359 self._type = type or "unknown"
462 self._mountpoint = mountpoint 360 self._mountpoint = mountpoint
463 self._mountopts = mountopts 361 self._mountopts = mountopts
464 self._format = format 362 self._format = format
465 self._mb = mb 363 self._mb = mb
466 self._orig_minor = origminor 364 self._orig_minor = origminor
365 self._mkfsopts = mkfsopts
467 if type != "free": 366 if type != "free":
468 if existing and not origminor: 367 if existing and not origminor:
469 self._orig_minor = self._minor 368 self._orig_minor = self._minor
470 self._minor = int(self._minor) 369 self._minor = int(self._minor)
471 self._orig_minor = int(self._orig_minor) 370 self._orig_minor = int(self._orig_minor)
472 if existing: 371 if existing:
372 try:
473 parted_part = device._parted_disk.get_partition(self._orig_minor) 373 parted_part = device._parted_disk.get_partition(self._orig_minor)
474 label_type = device._parted_disk.type.name 374 label_type = device._parted_disk.type.name
475 if label_type == "loop": 375 if label_type == "loop":
476 dev_node = device._device 376 dev_node = device._device
477 else: 377 else:
478 dev_node = device._device + str(self._orig_minor) 378 dev_node = device._device + str(self._orig_minor)
479 print "dev_node = " + dev_node 379# print "dev_node = " + dev_node
480 if type == "ntfs": 380 if type == "ntfs":
481 min_bytes = int(commands.getoutput("ntfsresize -f --info " + dev_node + " | grep -e '^You might resize' | sed -e 's/You might resize at //' -e 's/ bytes or .\+//'")) 381 min_bytes = long(commands.getoutput("ntfsresize -f --info " + dev_node + " | grep -e '^You might resize' | sed -e 's/You might resize at //' -e 's/ bytes or .\+//'"))
482 self._min_mb_for_resize = int(min_bytes / MEGABYTE) + 1 382 self._min_mb_for_resize = long(min_bytes / MEGABYTE) + 1
483 self._resizeable = True 383 self._resizeable = True
484 elif type == "ext2" or type == "ext3": 384 elif type == "ext2" or type == "ext3":
485 block_size = int(string.strip(commands.getoutput("dumpe2fs -h " + dev_node + r" 2>&1 | grep -e '^Block size:' | sed -e 's/^Block size:\s\+//'"))) 385 block_size = long(string.strip(commands.getoutput("dumpe2fs -h " + dev_node + r" 2>&1 | grep -e '^Block size:' | sed -e 's/^Block size:\s\+//'")))
486 free_blocks = int(string.strip(commands.getoutput("dumpe2fs -h " + dev_node + r" 2>&1 | grep -e '^Free blocks:' | sed -e 's/^Free blocks:\s\+//'"))) 386 free_blocks = long(string.strip(commands.getoutput("dumpe2fs -h " + dev_node + r" 2>&1 | grep -e '^Free blocks:' | sed -e 's/^Free blocks:\s\+//'")))
487 free_bytes = int(block_size * free_blocks) 387 free_bytes = long(block_size * free_blocks)
488 # can't hurt to pad (the +50) it a bit since this is really just a guess 388 # can't hurt to pad (the +50) it a bit since this is really just a guess
489 self._min_mb_for_resize = self._mb - int(free_bytes / MEGABYTE) + 50 389 self._min_mb_for_resize = self._mb - long(free_bytes / MEGABYTE) + 50
490 self._resizeable = True 390 self._resizeable = True
491 else: 391 else:
492 parted_part = self._device._parted_disk.get_partition(int(self._orig_minor)) 392 parted_part = self._device._parted_disk.get_partition(int(self._orig_minor))
493 try:
494 parted_fs = parted_part.geom.file_system_open() 393 parted_fs = parted_part.geom.file_system_open()
495 except:
496 self._resizeable = False
497 return
498 resize_constraint = parted_fs.get_resize_constraint() 394 resize_constraint = parted_fs.get_resize_constraint()
499 min_bytes = resize_constraint.min_size * self._device._sector_bytes 395 min_bytes = resize_constraint.min_size * self._device._sector_bytes
500 self._min_mb_for_resize = int(min_bytes / MEGABYTE) + 1 396 self._min_mb_for_resize = long(min_bytes / MEGABYTE) + 1
501 self._resizeable = True 397 self._resizeable = True
398 except:
399 self._resizeable = False
502 400
503 ## 401 ##
504 # Returns whether or not the partition is extended 402 # Returns whether or not the partition is extended
505 def is_extended(self): 403 def is_extended(self):
506 if self._type == "extended": 404 if self._type == "extended":
510 408
511 ## 409 ##
512 # Returns whether or not the partition is logical 410 # Returns whether or not the partition is logical
513 def is_logical(self): 411 def is_logical(self):
514 if self._type == "free": 412 if self._type == "free":
515 if int(self._minor) + 0.9 == self._minor: 413 if int(self._minor) + FREE_MINOR_FRAC_LOG == self._minor:
516 return True 414 return True
517 else: 415 else:
518 return False 416 return False
519 elif archinfo[self._device._arch]['extended'] and self._minor > 4: 417 elif archinfo[self._device._arch]['extended'] and self._minor > 4:
520 return True 418 return True
542 return None 440 return None
543 else: 441 else:
544 return self._device.get_partition_at(self._start, ignore_extended=0) 442 return self._device.get_partition_at(self._start, ignore_extended=0)
545 443
546 ## 444 ##
445 # Sets the options passed to mkfs
446 # @param mkfsopts Options passed to mkfs
447 def set_mkfsopts(self, mkfsopts):
448 self._mkfsopts = mkfsopts
449
450 ##
451 # Returns the options passes to mkfs
452 def get_mkfsopts(self):
453 return self._mkfsopts
454
455 ##
547 # Sets the start sector for the partition 456 # Sets the start sector for the partition
548 # @param start Start sector 457 # @param start Start sector
549 def set_start(self, start): 458 def set_start(self, start):
550 self._start = int(start) 459 self._start = long(start)
551 460
552 ## 461 ##
553 # Returns the start sector for the partition 462 # Returns the start sector for the partition
554 def get_start(self): 463 def get_start(self):
555 return int(self._start) 464 return long(self._start)
556 465
557 ## 466 ##
558 # Sets the end sector of the partition 467 # Sets the end sector of the partition
559 # @param end End sector 468 # @param end End sector
560 def set_end(self, end): 469 def set_end(self, end):
561 self._end = int(end) 470 self._end = long(end)
562 471
563 ## 472 ##
564 # Returns end sector for the partition 473 # Returns end sector for the partition
565 def get_end(self): 474 def get_end(self):
566 return int(self._end) 475 return long(self._end)
567 476
568 ## 477 ##
569 # Returns size of partition in MB 478 # Returns size of partition in MB
570 def get_mb(self): 479 def get_mb(self):
571 return int(self._mb) 480 return long(self._mb)
572 481
573 ## 482 ##
574 # Sets size of partition in MB 483 # Sets size of partition in MB
575 # @param mb Parameter description 484 # @param mb Parameter description
576 def set_mb(self, mb): 485 def set_mb(self, mb):
577 self._mb = int(mb) 486 self._mb = long(mb)
578 487
579 ## 488 ##
580 # Sets type of partition 489 # Sets type of partition
581 # @param type Parameter description 490 # @param type Parameter description
582 def set_type(self, type): 491 def set_type(self, type):
671 # Returns maximum MB for resize 580 # Returns maximum MB for resize
672 def get_max_mb_for_resize(self): 581 def get_max_mb_for_resize(self):
673 if self._resizeable: 582 if self._resizeable:
674 free_minor = 0 583 free_minor = 0
675 if self.is_logical(): 584 if self.is_logical():
676 free_minor = self._minor + 0.9 585 free_minor = self._minor + FREE_MINOR_FRAC_LOG
677 else: 586 else:
678 free_minor = self._minor + 0.1 587 free_minor = self._minor + FREE_MINOR_FRAC_PRI
679 if free_minor in self._device._partitions: 588 if free_minor in self._device._partitions:
680 return self._mb + self._device._partitions[free_minor]._mb 589 return self._mb + self._device._partitions[free_minor]._mb
681 else: 590 else:
682 return self._mb 591 return self._mb
683 else: 592 else:
687 # Resizes the partition 596 # Resizes the partition
688 # @param mb New size in MB 597 # @param mb New size in MB
689 def resize(self, mb): 598 def resize(self, mb):
690 free_minor = self._minor 599 free_minor = self._minor
691 if self.is_logical(): 600 if self.is_logical():
692 free_minor += 0.9 601 free_minor += FREE_MINOR_FRAC_LOG
693 else: 602 else:
694 free_minor += 0.1 603 free_minor += FREE_MINOR_FRAC_PRI
695 if mb < self._mb: 604 if mb < self._mb:
696 # Shrinking 605 # Shrinking
697 if not free_minor in self._device._partitions: 606 if not free_minor in self._device._partitions:
698 self._device._partitions[free_minor] = Partition(self._device, free_minor, 0, 0, 0, "free", format=False, existing=False) 607 self._device._partitions[free_minor] = Partition(self._device, free_minor, 0, 0, 0, "free", format=False, existing=False)
699 self._device._partitions[free_minor]._mb += self._mb - mb 608 self._device._partitions[free_minor]._mb += self._mb - mb
711# Returns a list of detected partitionable devices 620# Returns a list of detected partitionable devices
712def detect_devices(): 621def detect_devices():
713 devices = [] 622 devices = []
714 623
715 # Make sure sysfs exists 624 # Make sure sysfs exists
625 # TODO: rewrite for 2.4 support
716 if not os.path.exists("/sys/bus"): 626 if not os.path.exists("/sys/bus"):
717 raise GLIException("GLIStorageDeviceError", 'fatal', 'detect_devices', "no sysfs found (you MUST use a kernel >2.6)") 627 raise GLIException("GLIStorageDeviceError", 'fatal', 'detect_devices', "no sysfs found (you MUST use a kernel >2.6)")
718 # Make sure /proc/partitions exists 628 # Make sure /proc/partitions exists
719 if not os.path.exists("/proc/partitions"): 629 if not os.path.exists("/proc/partitions"):
720 raise GLIException("GLIStorageDeviceError", 'fatal', 'detect_devices', "/proc/partitions does not exist! Please make sure procfs is in your kernel and mounted!") 630 raise GLIException("GLIStorageDeviceError", 'fatal', 'detect_devices', "/proc/partitions does not exist! Please make sure procfs is in your kernel and mounted!")
757 667
758 partitions.append(( major, minor, device )) 668 partitions.append(( major, minor, device ))
759 669
760 # Scan sysfs for the devices of type 'x' 670 # Scan sysfs for the devices of type 'x'
761 # 'x' being a member of the list below: 671 # 'x' being a member of the list below:
672 # TODO: rewrite for 2.4 support
762 for dev_type in [ "ide", "scsi" ]: # Other device types? usb? fw? 673 for dev_type in [ "ide", "scsi" ]: # Other device types? usb? fw?
763 if os.path.exists("/sys/bus/" + dev_type): 674 if os.path.exists("/sys/bus/" + dev_type):
764 sysfs_devices = os.listdir("/sys/bus/"+dev_type+"/devices") 675 sysfs_devices = os.listdir("/sys/bus/"+dev_type+"/devices")
765 676
766 # For each device in the devices on that bus 677 # For each device in the devices on that bus

Legend:
Removed from v.596  
changed lines
  Added in v.826

  ViewVC Help
Powered by ViewVC 1.1.20