| OLD | NEW |
| 1 """ | 1 """ |
| 2 APIs to write tests and control files that handle partition creation, deletion | 2 APIs to write tests and control files that handle partition creation, deletion |
| 3 and formatting. | 3 and formatting. |
| 4 | 4 |
| 5 @copyright: Google 2006-2008 | 5 @copyright: Google 2006-2008 |
| 6 @author: Martin Bligh (mbligh@google.com) | 6 @author: Martin Bligh (mbligh@google.com) |
| 7 """ | 7 """ |
| 8 | 8 |
| 9 import os, re, string, sys, fcntl, logging | 9 import os, re, string, sys, fcntl, logging |
| 10 from autotest_lib.client.bin import os_dep, utils | 10 from autotest_lib.client.bin import os_dep, utils |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 169 | 169 |
| 170 if filter_func and not filter_func(partname): | 170 if filter_func and not filter_func(partname): |
| 171 logging.debug('Skipping %s - Filter func.' % partname) | 171 logging.debug('Skipping %s - Filter func.' % partname) |
| 172 continue | 172 continue |
| 173 | 173 |
| 174 partitions.append(partition(job, device)) | 174 partitions.append(partition(job, device)) |
| 175 | 175 |
| 176 return partitions | 176 return partitions |
| 177 | 177 |
| 178 | 178 |
| 179 def get_mount_info(partition_list): |
| 180 """ |
| 181 Picks up mount point information about the machine mounts. By default, we |
| 182 try to associate mount points with UUIDs, because in newer distros the |
| 183 partitions are uniquely identified using them. |
| 184 """ |
| 185 mount_info = set() |
| 186 for p in partition_list: |
| 187 try: |
| 188 uuid = utils.system_output('blkid -s UUID -o value %s' % p.device) |
| 189 except error.CmdError: |
| 190 # fall back to using the partition |
| 191 uuid = p.device |
| 192 mount_info.add((uuid, p.get_mountpoint())) |
| 193 |
| 194 return mount_info |
| 195 |
| 196 |
| 179 def filter_partition_list(partitions, devnames): | 197 def filter_partition_list(partitions, devnames): |
| 180 """ | 198 """ |
| 181 Pick and choose which partition to keep. | 199 Pick and choose which partition to keep. |
| 182 | 200 |
| 183 filter_partition_list accepts a list of partition objects and a list | 201 filter_partition_list accepts a list of partition objects and a list |
| 184 of strings. If a partition has the device name of the strings it | 202 of strings. If a partition has the device name of the strings it |
| 185 is returned in a list. | 203 is returned in a list. |
| 186 | 204 |
| 187 @param partitions: A list of L{partition} objects | 205 @param partitions: A list of L{partition} objects |
| 188 @param devnames: A list of devnames of the form '/dev/hdc3' that | 206 @param devnames: A list of devnames of the form '/dev/hdc3' that |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 304 if not partname[-1].isdigit(): | 322 if not partname[-1].isdigit(): |
| 305 # Disk name does not end in number, AFAIK | 323 # Disk name does not end in number, AFAIK |
| 306 # so use it as a reference to a disk | 324 # so use it as a reference to a disk |
| 307 if device.strip("/dev/") == partname: | 325 if device.strip("/dev/") == partname: |
| 308 return True | 326 return True |
| 309 | 327 |
| 310 return False | 328 return False |
| 311 | 329 |
| 312 | 330 |
| 313 def run_test_on_partitions(job, test, partitions, mountpoint_func, | 331 def run_test_on_partitions(job, test, partitions, mountpoint_func, |
| 314 tag, fs_opt, **dargs): | 332 tag, fs_opt, do_fsck=True, **dargs): |
| 315 """ | 333 """ |
| 316 Run a test that requires multiple partitions. Filesystems will be | 334 Run a test that requires multiple partitions. Filesystems will be |
| 317 made on the partitions and mounted, then the test will run, then the | 335 made on the partitions and mounted, then the test will run, then the |
| 318 filesystems will be unmounted and fsck'd. | 336 filesystems will be unmounted and optionally fsck'd. |
| 319 | 337 |
| 320 @param job: A job instance to run the test | 338 @param job: A job instance to run the test |
| 321 @param test: A string containing the name of the test | 339 @param test: A string containing the name of the test |
| 322 @param partitions: A list of partition objects, these are passed to the | 340 @param partitions: A list of partition objects, these are passed to the |
| 323 test as partitions= | 341 test as partitions= |
| 324 @param mountpoint_func: A callable that returns a mountpoint given a | 342 @param mountpoint_func: A callable that returns a mountpoint given a |
| 325 partition instance | 343 partition instance |
| 326 @param tag: A string tag to make this test unique (Required for control | 344 @param tag: A string tag to make this test unique (Required for control |
| 327 files that make multiple calls to this routine with the same value | 345 files that make multiple calls to this routine with the same value |
| 328 of 'test'.) | 346 of 'test'.) |
| 329 @param fs_opt: An FsOptions instance that describes what filesystem to make | 347 @param fs_opt: An FsOptions instance that describes what filesystem to make |
| 348 @param do_fsck: include fsck in post-test partition cleanup. |
| 330 @param dargs: Dictionary of arguments to be passed to job.run_test() and | 349 @param dargs: Dictionary of arguments to be passed to job.run_test() and |
| 331 eventually the test | 350 eventually the test |
| 332 """ | 351 """ |
| 333 # setup the filesystem parameters for all the partitions | 352 # setup the filesystem parameters for all the partitions |
| 334 for p in partitions: | 353 for p in partitions: |
| 335 p.set_fs_options(fs_opt) | 354 p.set_fs_options(fs_opt) |
| 336 | 355 |
| 337 # make and mount all the partitions in parallel | 356 # make and mount all the partitions in parallel |
| 338 parallel(partitions, 'setup_before_test', mountpoint_func=mountpoint_func) | 357 parallel(partitions, 'setup_before_test', mountpoint_func=mountpoint_func) |
| 339 | 358 |
| 340 mountpoint = mountpoint_func(partitions[0]) | 359 mountpoint = mountpoint_func(partitions[0]) |
| 341 | 360 |
| 342 # run the test against all the partitions | 361 # run the test against all the partitions |
| 343 job.run_test(test, tag=tag, partitions=partitions, dir=mountpoint, **dargs) | 362 job.run_test(test, tag=tag, partitions=partitions, dir=mountpoint, **dargs) |
| 344 | 363 |
| 345 # fsck and then remake all the filesystems in parallel | 364 parallel(partitions, 'unmount') # unmount all partitions in parallel |
| 346 parallel(partitions, 'cleanup_after_test') | 365 if do_fsck: |
| 366 parallel(partitions, 'fsck') # fsck all partitions in parallel |
| 367 # else fsck is done by caller |
| 347 | 368 |
| 348 | 369 |
| 349 class partition(object): | 370 class partition(object): |
| 350 """ | 371 """ |
| 351 Class for handling partitions and filesystems | 372 Class for handling partitions and filesystems |
| 352 """ | 373 """ |
| 353 | 374 |
| 354 def __init__(self, job, device, loop_size=0, mountpoint=None): | 375 def __init__(self, job, device, loop_size=0, mountpoint=None): |
| 355 """ | 376 """ |
| 356 @param job: A L{client.bin.job} instance. | 377 @param job: A L{client.bin.job} instance. |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 423 mountpoint = mountpoint_func(self) | 444 mountpoint = mountpoint_func(self) |
| 424 if not mountpoint: | 445 if not mountpoint: |
| 425 raise ValueError('Don\'t know where to put this partition') | 446 raise ValueError('Don\'t know where to put this partition') |
| 426 self.unmount(ignore_status=True, record=False) | 447 self.unmount(ignore_status=True, record=False) |
| 427 self.mkfs() | 448 self.mkfs() |
| 428 if not os.path.isdir(mountpoint): | 449 if not os.path.isdir(mountpoint): |
| 429 os.makedirs(mountpoint) | 450 os.makedirs(mountpoint) |
| 430 self.mount(mountpoint) | 451 self.mount(mountpoint) |
| 431 | 452 |
| 432 | 453 |
| 433 def cleanup_after_test(self): | |
| 434 """ | |
| 435 Cleans up a partition after running a filesystem test. The | |
| 436 filesystem is unmounted, and then checked for errors. | |
| 437 """ | |
| 438 self.unmount() | |
| 439 self.fsck() | |
| 440 | |
| 441 | |
| 442 def run_test_on_partition(self, test, mountpoint_func, **dargs): | 454 def run_test_on_partition(self, test, mountpoint_func, **dargs): |
| 443 """ | 455 """ |
| 444 Executes a test fs-style (umount,mkfs,mount,test) | 456 Executes a test fs-style (umount,mkfs,mount,test) |
| 445 | 457 |
| 446 Here we unmarshal the args to set up tags before running the test. | 458 Here we unmarshal the args to set up tags before running the test. |
| 447 Tests are also run by first umounting, mkfsing and then mounting | 459 Tests are also run by first umounting, mkfsing and then mounting |
| 448 before executing the test. | 460 before executing the test. |
| 449 | 461 |
| 450 @param test: name of test to run | 462 @param test: name of test to run |
| 451 @param mountpoint_func: function to return mount point string | 463 @param mountpoint_func: function to return mount point string |
| (...skipping 11 matching lines...) Expand all Loading... |
| 463 if suffix: | 475 if suffix: |
| 464 tag = '%s.%s' % (tag, suffix) | 476 tag = '%s.%s' % (tag, suffix) |
| 465 | 477 |
| 466 dargs['tag'] = test + '.' + tag | 478 dargs['tag'] = test + '.' + tag |
| 467 | 479 |
| 468 def _make_partition_and_run_test(test_tag, dir=None, **dargs): | 480 def _make_partition_and_run_test(test_tag, dir=None, **dargs): |
| 469 self.setup_before_test(mountpoint_func) | 481 self.setup_before_test(mountpoint_func) |
| 470 try: | 482 try: |
| 471 self.job.run_test(test, tag=test_tag, dir=mountpoint, **dargs) | 483 self.job.run_test(test, tag=test_tag, dir=mountpoint, **dargs) |
| 472 finally: | 484 finally: |
| 473 self.cleanup_after_test() | 485 self.unmount() |
| 486 self.fsck() |
| 487 |
| 474 | 488 |
| 475 mountpoint = mountpoint_func(self) | 489 mountpoint = mountpoint_func(self) |
| 476 | 490 |
| 477 # The tag is the tag for the group (get stripped off by run_group) | 491 # The tag is the tag for the group (get stripped off by run_group) |
| 478 # The test_tag is the tag for the test itself | 492 # The test_tag is the tag for the test itself |
| 479 self.job.run_group(_make_partition_and_run_test, | 493 self.job.run_group(_make_partition_and_run_test, |
| 480 test_tag=tag, dir=mountpoint, **dargs) | 494 test_tag=tag, dir=mountpoint, **dargs) |
| 481 | 495 |
| 482 | 496 |
| 483 def get_mountpoint(self, open_func=open, filename=None): | 497 def get_mountpoint(self, open_func=open, filename=None): |
| 484 """ | 498 """ |
| 485 Find the mount point of this partition object. | 499 Find the mount point of this partition object. |
| 486 | 500 |
| 487 @param open_func: the function to use for opening the file containing | 501 @param open_func: the function to use for opening the file containing |
| 488 the mounted partitions information | 502 the mounted partitions information |
| 489 @param filename: where to look for the mounted partitions information | 503 @param filename: where to look for the mounted partitions information |
| 490 (default None which means it will search /proc/mounts and/or | 504 (default None which means it will search /proc/mounts and/or |
| 491 /etc/mtab) | 505 /etc/mtab) |
| 492 | 506 |
| 493 @returns a string with the mount point of the partition or None if not | 507 @returns a string with the mount point of the partition or None if not |
| 494 mounted | 508 mounted |
| 495 """ | 509 """ |
| 496 if filename: | 510 if filename: |
| 497 for line in open_func(filename).readlines(): | 511 for line in open_func(filename).readlines(): |
| 498 parts = line.split() | 512 parts = line.split() |
| 499 if parts[0] == self.device: | 513 if parts[0] == self.device or parts[1] == self.mountpoint: |
| 500 return parts[1] # The mountpoint where it's mounted | 514 return parts[1] # The mountpoint where it's mounted |
| 501 return None | 515 return None |
| 502 | 516 |
| 503 # no specific file given, look in /proc/mounts | 517 # no specific file given, look in /proc/mounts |
| 504 res = self.get_mountpoint(open_func=open_func, filename='/proc/mounts') | 518 res = self.get_mountpoint(open_func=open_func, filename='/proc/mounts') |
| 505 if not res: | 519 if not res: |
| 506 # sometimes the root partition is reported as /dev/root in | 520 # sometimes the root partition is reported as /dev/root in |
| 507 # /proc/mounts in this case, try /etc/mtab | 521 # /proc/mounts in this case, try /etc/mtab |
| 508 res = self.get_mountpoint(open_func=open_func, filename='/etc/mtab') | 522 res = self.get_mountpoint(open_func=open_func, filename='/etc/mtab') |
| 509 | 523 |
| (...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 977 os.remove(self.img) | 991 os.remove(self.img) |
| 978 except: | 992 except: |
| 979 e_msg = 'Error removing image file %s' % self.img | 993 e_msg = 'Error removing image file %s' % self.img |
| 980 raise error.AutotestError(e_msg) | 994 raise error.AutotestError(e_msg) |
| 981 | 995 |
| 982 # import a site partition module to allow it to override functions | 996 # import a site partition module to allow it to override functions |
| 983 try: | 997 try: |
| 984 from autotest_lib.client.bin.site_partition import * | 998 from autotest_lib.client.bin.site_partition import * |
| 985 except ImportError: | 999 except ImportError: |
| 986 pass | 1000 pass |
| OLD | NEW |