OLD | NEW |
1 """ | 1 """ |
2 Library to perform pre/post test setup for KVM autotest. | 2 Library to perform pre/post test setup for KVM autotest. |
3 """ | 3 """ |
4 import os, shutil, tempfile, re, ConfigParser, glob, inspect | 4 import os, logging |
5 import logging, time | |
6 from autotest_lib.client.common_lib import error | 5 from autotest_lib.client.common_lib import error |
7 from autotest_lib.client.bin import utils | 6 from autotest_lib.client.bin import utils |
8 | 7 |
9 | 8 |
10 @error.context_aware | |
11 def cleanup(dir): | |
12 """ | |
13 If dir is a mountpoint, do what is possible to unmount it. Afterwards, | |
14 try to remove it. | |
15 | |
16 @param dir: Directory to be cleaned up. | |
17 """ | |
18 error.context("cleaning up unattended install directory %s" % dir) | |
19 if os.path.ismount(dir): | |
20 utils.run('fuser -k %s' % dir, ignore_status=True) | |
21 utils.run('umount %s' % dir) | |
22 if os.path.isdir(dir): | |
23 shutil.rmtree(dir) | |
24 | |
25 | |
26 @error.context_aware | |
27 def clean_old_image(image): | |
28 """ | |
29 Clean a leftover image file from previous processes. If it contains a | |
30 mounted file system, do the proper cleanup procedures. | |
31 | |
32 @param image: Path to image to be cleaned up. | |
33 """ | |
34 error.context("cleaning up old leftover image %s" % image) | |
35 if os.path.exists(image): | |
36 mtab = open('/etc/mtab', 'r') | |
37 mtab_contents = mtab.read() | |
38 mtab.close() | |
39 if image in mtab_contents: | |
40 utils.run('fuser -k %s' % image, ignore_status=True) | |
41 utils.run('umount %s' % image) | |
42 os.remove(image) | |
43 | |
44 | |
45 def display_attributes(instance): | |
46 """ | |
47 Inspects a given class instance attributes and displays them, convenient | |
48 for debugging. | |
49 """ | |
50 logging.debug("Attributes set:") | |
51 for member in inspect.getmembers(instance): | |
52 name, value = member | |
53 attribute = getattr(instance, name) | |
54 if not (name.startswith("__") or callable(attribute) or not value): | |
55 logging.debug(" %s: %s", name, value) | |
56 | |
57 | |
58 class Disk(object): | |
59 """ | |
60 Abstract class for Disk objects, with the common methods implemented. | |
61 """ | |
62 def __init__(self): | |
63 self.path = None | |
64 | |
65 | |
66 def setup_answer_file(self, filename, contents): | |
67 utils.open_write_close(os.path.join(self.mount, filename), contents) | |
68 | |
69 | |
70 def copy_to(self, src): | |
71 logging.debug("Copying %s to disk image mount", src) | |
72 dst = os.path.join(self.mount, os.path.basename(src)) | |
73 if os.path.isdir(src): | |
74 shutil.copytree(src, dst) | |
75 elif os.path.isfile(src): | |
76 shutil.copyfile(src, dst) | |
77 | |
78 | |
79 def close(self): | |
80 os.chmod(self.path, 0755) | |
81 cleanup(self.mount) | |
82 logging.debug("Disk %s successfuly set", self.path) | |
83 | |
84 | |
85 class FloppyDisk(Disk): | |
86 """ | |
87 Represents a 1.44 MB floppy disk. We can copy files to it, and setup it in | |
88 convenient ways. | |
89 """ | |
90 @error.context_aware | |
91 def __init__(self, path, qemu_img_binary, tmpdir): | |
92 error.context("Creating unattended install floppy image %s" % path) | |
93 self.tmpdir = tmpdir | |
94 self.mount = tempfile.mkdtemp(prefix='floppy_', dir=self.tmpdir) | |
95 self.virtio_mount = None | |
96 self.path = path | |
97 clean_old_image(path) | |
98 if not os.path.isdir(os.path.dirname(path)): | |
99 os.makedirs(os.path.dirname(path)) | |
100 | |
101 try: | |
102 c_cmd = '%s create -f raw %s 1440k' % (qemu_img_binary, path) | |
103 utils.run(c_cmd) | |
104 f_cmd = 'mkfs.msdos -s 1 %s' % path | |
105 utils.run(f_cmd) | |
106 m_cmd = 'mount -o loop,rw %s %s' % (path, self.mount) | |
107 utils.run(m_cmd) | |
108 except error.CmdError, e: | |
109 cleanup(self.mount) | |
110 raise | |
111 | |
112 | |
113 def _copy_virtio_drivers(self, virtio_floppy): | |
114 """ | |
115 Copy the virtio drivers on the virtio floppy to the install floppy. | |
116 | |
117 1) Mount the floppy containing the viostor drivers | |
118 2) Copy its contents to the root of the install floppy | |
119 """ | |
120 virtio_mount = tempfile.mkdtemp(prefix='virtio_floppy_', | |
121 dir=self.tmpdir) | |
122 | |
123 pwd = os.getcwd() | |
124 try: | |
125 m_cmd = 'mount -o loop %s %s' % (virtio_floppy, virtio_mount) | |
126 utils.run(m_cmd) | |
127 os.chdir(virtio_mount) | |
128 path_list = glob.glob('*') | |
129 for path in path_list: | |
130 self.copy_to(path) | |
131 finally: | |
132 os.chdir(pwd) | |
133 cleanup(virtio_mount) | |
134 | |
135 | |
136 def setup_virtio_win2003(self, virtio_floppy, virtio_oemsetup_id): | |
137 """ | |
138 Setup the install floppy with the virtio storage drivers, win2003 style. | |
139 | |
140 Win2003 and WinXP depend on the file txtsetup.oem file to install | |
141 the virtio drivers from the floppy, which is a .ini file. | |
142 Process: | |
143 | |
144 1) Copy the virtio drivers on the virtio floppy to the install floppy | |
145 2) Parse the ini file with config parser | |
146 3) Modify the identifier of the default session that is going to be | |
147 executed on the config parser object | |
148 4) Re-write the config file to the disk | |
149 """ | |
150 self._copy_virtio_drivers(virtio_floppy) | |
151 txtsetup_oem = os.path.join(self.mount, 'txtsetup.oem') | |
152 if not os.path.isfile(txtsetup_oem): | |
153 raise IOError('File txtsetup.oem not found on the install ' | |
154 'floppy. Please verify if your floppy virtio ' | |
155 'driver image has this file') | |
156 parser = ConfigParser.ConfigParser() | |
157 parser.read(txtsetup_oem) | |
158 if not parser.has_section('Defaults'): | |
159 raise ValueError('File txtsetup.oem does not have the session ' | |
160 '"Defaults". Please check txtsetup.oem') | |
161 default_driver = parser.get('Defaults', 'SCSI') | |
162 if default_driver != virtio_oemsetup_id: | |
163 parser.set('Defaults', 'SCSI', virtio_oemsetup_id) | |
164 fp = open(txtsetup_oem, 'w') | |
165 parser.write(fp) | |
166 fp.close() | |
167 | |
168 | |
169 def setup_virtio_win2008(self, virtio_floppy): | |
170 """ | |
171 Setup the install floppy with the virtio storage drivers, win2008 style. | |
172 | |
173 Win2008, Vista and 7 require people to point out the path to the drivers | |
174 on the unattended file, so we just need to copy the drivers to the | |
175 driver floppy disk. | |
176 Process: | |
177 | |
178 1) Copy the virtio drivers on the virtio floppy to the install floppy | |
179 """ | |
180 self._copy_virtio_drivers(virtio_floppy) | |
181 | |
182 | |
183 class CdromDisk(Disk): | |
184 """ | |
185 Represents a CDROM disk that we can master according to our needs. | |
186 """ | |
187 def __init__(self, path, tmpdir): | |
188 self.mount = tempfile.mkdtemp(prefix='cdrom_unattended_', dir=tmpdir) | |
189 self.path = path | |
190 clean_old_image(path) | |
191 if not os.path.isdir(os.path.dirname(path)): | |
192 os.makedirs(os.path.dirname(path)) | |
193 | |
194 | |
195 @error.context_aware | |
196 def close(self): | |
197 error.context("Creating unattended install CD image %s" % self.path) | |
198 g_cmd = ('mkisofs -o %s -max-iso9660-filenames ' | |
199 '-relaxed-filenames -D --input-charset iso8859-1 ' | |
200 '%s' % (self.path, self.mount)) | |
201 utils.run(g_cmd) | |
202 | |
203 os.chmod(self.path, 0755) | |
204 cleanup(self.mount) | |
205 logging.debug("unattended install CD image %s successfuly created", | |
206 self.path) | |
207 | |
208 | |
209 class UnattendedInstallConfig(object): | |
210 """ | |
211 Creates a floppy disk image that will contain a config file for unattended | |
212 OS install. The parameters to the script are retrieved from environment | |
213 variables. | |
214 """ | |
215 def __init__(self, test, params): | |
216 """ | |
217 Sets class atributes from test parameters. | |
218 | |
219 @param test: KVM test object. | |
220 @param params: Dictionary with test parameters. | |
221 """ | |
222 root_dir = test.bindir | |
223 images_dir = os.path.join(root_dir, 'images') | |
224 self.deps_dir = os.path.join(root_dir, 'deps') | |
225 self.unattended_dir = os.path.join(root_dir, 'unattended') | |
226 | |
227 attributes = ['kernel_args', 'finish_program', 'cdrom_cd1', | |
228 'unattended_file', 'medium', 'url', 'kernel', 'initrd', | |
229 'nfs_server', 'nfs_dir', 'install_virtio', 'floppy', | |
230 'cdrom_unattended', 'boot_path', 'extra_params', | |
231 'qemu_img_binary', 'cdkey', 'finish_program'] | |
232 | |
233 for a in attributes: | |
234 setattr(self, a, params.get(a, '')) | |
235 | |
236 if self.install_virtio == 'yes': | |
237 v_attributes = ['virtio_floppy', 'virtio_storage_path', | |
238 'virtio_network_path', 'virtio_oemsetup_id', | |
239 'virtio_network_installer'] | |
240 for va in v_attributes: | |
241 setattr(self, va, params.get(va, '')) | |
242 | |
243 self.tmpdir = test.tmpdir | |
244 | |
245 if getattr(self, 'unattended_file'): | |
246 self.unattended_file = os.path.join(root_dir, self.unattended_file) | |
247 | |
248 if getattr(self, 'finish_program'): | |
249 self.finish_program = os.path.join(root_dir, self.finish_program) | |
250 | |
251 if getattr(self, 'qemu_img_binary'): | |
252 if not os.path.isfile(getattr(self, 'qemu_img_binary')): | |
253 self.qemu_img_binary = os.path.join(root_dir, | |
254 self.qemu_img_binary) | |
255 | |
256 if getattr(self, 'cdrom_cd1'): | |
257 self.cdrom_cd1 = os.path.join(root_dir, self.cdrom_cd1) | |
258 self.cdrom_cd1_mount = tempfile.mkdtemp(prefix='cdrom_cd1_', | |
259 dir=self.tmpdir) | |
260 if self.medium == 'nfs': | |
261 self.nfs_mount = tempfile.mkdtemp(prefix='nfs_', | |
262 dir=self.tmpdir) | |
263 | |
264 if getattr(self, 'floppy'): | |
265 self.floppy = os.path.join(root_dir, self.floppy) | |
266 if not os.path.isdir(os.path.dirname(self.floppy)): | |
267 os.makedirs(os.path.dirname(self.floppy)) | |
268 | |
269 self.image_path = os.path.dirname(self.kernel) | |
270 | |
271 | |
272 @error.context_aware | |
273 def render_answer_file(self): | |
274 """ | |
275 Replace KVM_TEST_CDKEY (in the unattended file) with the cdkey | |
276 provided for this test and replace the KVM_TEST_MEDIUM with | |
277 the tree url or nfs address provided for this test. | |
278 | |
279 @return: Answer file contents | |
280 """ | |
281 error.base_context('Rendering final answer file') | |
282 error.context('Reading answer file %s' % self.unattended_file) | |
283 unattended_contents = open(self.unattended_file).read() | |
284 dummy_cdkey_re = r'\bKVM_TEST_CDKEY\b' | |
285 if re.search(dummy_cdkey_re, unattended_contents): | |
286 if self.cdkey: | |
287 unattended_contents = re.sub(dummy_cdkey_re, self.cdkey, | |
288 unattended_contents) | |
289 else: | |
290 print ("WARNING: 'cdkey' required but not specified for " | |
291 "this unattended installation") | |
292 | |
293 dummy_medium_re = r'\bKVM_TEST_MEDIUM\b' | |
294 if self.medium == "cdrom": | |
295 content = "cdrom" | |
296 elif self.medium == "url": | |
297 content = "url --url %s" % self.url | |
298 elif self.medium == "nfs": | |
299 content = "nfs --server=%s --dir=%s" % (self.nfs_server, | |
300 self.nfs_dir) | |
301 else: | |
302 raise ValueError("Unexpected installation medium %s" % self.url) | |
303 | |
304 unattended_contents = re.sub(dummy_medium_re, content, | |
305 unattended_contents) | |
306 | |
307 def replace_virtio_key(contents, dummy_re, attribute_name): | |
308 """ | |
309 Replace a virtio dummy string with contents. | |
310 | |
311 If install_virtio is not set, replace it with a dummy string. | |
312 | |
313 @param contents: Contents of the unattended file | |
314 @param dummy_re: Regular expression used to search on the. | |
315 unattended file contents. | |
316 @param env: Name of the environment variable. | |
317 """ | |
318 dummy_path = "C:" | |
319 driver = getattr(self, attribute_name, '') | |
320 | |
321 if re.search(dummy_re, contents): | |
322 if self.install_virtio == "yes": | |
323 if driver.endswith("msi"): | |
324 driver = 'msiexec /passive /package ' + driver | |
325 else: | |
326 try: | |
327 # Let's escape windows style paths properly | |
328 drive, path = driver.split(":") | |
329 driver = drive + ":" + re.escape(path) | |
330 except: | |
331 pass | |
332 contents = re.sub(dummy_re, driver, contents) | |
333 else: | |
334 contents = re.sub(dummy_re, dummy_path, contents) | |
335 return contents | |
336 | |
337 vdict = {r'\bKVM_TEST_STORAGE_DRIVER_PATH\b': | |
338 'virtio_storage_path', | |
339 r'\bKVM_TEST_NETWORK_DRIVER_PATH\b': | |
340 'virtio_network_path', | |
341 r'\bKVM_TEST_VIRTIO_NETWORK_INSTALLER\b': | |
342 'virtio_network_installer_path'} | |
343 | |
344 for vkey in vdict: | |
345 unattended_contents = replace_virtio_key( | |
346 contents=unattended_contents, | |
347 dummy_re=vkey, | |
348 attribute_name=vdict[vkey]) | |
349 | |
350 logging.debug("Unattended install contents:") | |
351 for line in unattended_contents.splitlines(): | |
352 logging.debug(line) | |
353 return unattended_contents | |
354 | |
355 | |
356 def setup_boot_disk(self): | |
357 answer_contents = self.render_answer_file() | |
358 | |
359 if self.unattended_file.endswith('.sif'): | |
360 dest_fname = 'winnt.sif' | |
361 setup_file = 'winnt.bat' | |
362 boot_disk = FloppyDisk(self.floppy, self.qemu_img_binary, | |
363 self.tmpdir) | |
364 boot_disk.setup_answer_file(dest_fname, answer_contents) | |
365 setup_file_path = os.path.join(self.unattended_dir, setup_file) | |
366 boot_disk.copy_to(setup_file_path) | |
367 if self.install_virtio == "yes": | |
368 boot_disk.setup_virtio_win2003(self.virtio_floppy, | |
369 self.virtio_oemsetup_id) | |
370 boot_disk.copy_to(self.finish_program) | |
371 | |
372 elif self.unattended_file.endswith('.ks'): | |
373 # Red Hat kickstart install | |
374 dest_fname = 'ks.cfg' | |
375 if self.cdrom_unattended: | |
376 boot_disk = CdromDisk(self.cdrom_unattended, self.tmpdir) | |
377 elif self.floppy: | |
378 boot_disk = FloppyDisk(self.floppy, self.qemu_img_binary, | |
379 self.tmpdir) | |
380 else: | |
381 raise ValueError("Neither cdrom_unattended nor floppy set " | |
382 "on the config file, please verify") | |
383 boot_disk.setup_answer_file(dest_fname, answer_contents) | |
384 | |
385 elif self.unattended_file.endswith('.xml'): | |
386 if "autoyast" in self.extra_params: | |
387 # SUSE autoyast install | |
388 dest_fname = "autoinst.xml" | |
389 if self.cdrom_unattended: | |
390 boot_disk = CdromDisk(self.cdrom_unattended) | |
391 elif self.floppy: | |
392 boot_disk = FloppyDisk(self.floppy, self.qemu_img_binary, | |
393 self.tmpdir) | |
394 else: | |
395 raise ValueError("Neither cdrom_unattended nor floppy set " | |
396 "on the config file, please verify") | |
397 boot_disk.setup_answer_file(dest_fname, answer_contents) | |
398 | |
399 else: | |
400 # Windows unattended install | |
401 dest_fname = "autounattend.xml" | |
402 boot_disk = FloppyDisk(self.floppy, self.qemu_img_binary, | |
403 self.tmpdir) | |
404 boot_disk.setup_answer_file(dest_fname, answer_contents) | |
405 if self.install_virtio == "yes": | |
406 boot_disk.setup_virtio_win2008(self.virtio_floppy) | |
407 boot_disk.copy_to(self.finish_program) | |
408 | |
409 else: | |
410 raise ValueError('Unknown answer file type: %s' % | |
411 self.unattended_file) | |
412 | |
413 boot_disk.close() | |
414 | |
415 | |
416 @error.context_aware | |
417 def setup_cdrom(self): | |
418 """ | |
419 Mount cdrom and copy vmlinuz and initrd.img. | |
420 """ | |
421 error.context("Copying vmlinuz and initrd.img from install cdrom %s" % | |
422 self.cdrom_cd1) | |
423 m_cmd = ('mount -t iso9660 -v -o loop,ro %s %s' % | |
424 (self.cdrom_cd1, self.cdrom_cd1_mount)) | |
425 utils.run(m_cmd) | |
426 | |
427 try: | |
428 if not os.path.isdir(self.image_path): | |
429 os.makedirs(self.image_path) | |
430 kernel_fetch_cmd = ("cp %s/%s/%s %s" % | |
431 (self.cdrom_cd1_mount, self.boot_path, | |
432 os.path.basename(self.kernel), self.kernel)) | |
433 utils.run(kernel_fetch_cmd) | |
434 initrd_fetch_cmd = ("cp %s/%s/%s %s" % | |
435 (self.cdrom_cd1_mount, self.boot_path, | |
436 os.path.basename(self.initrd), self.initrd)) | |
437 utils.run(initrd_fetch_cmd) | |
438 finally: | |
439 cleanup(self.cdrom_cd1_mount) | |
440 | |
441 | |
442 @error.context_aware | |
443 def setup_url(self): | |
444 """ | |
445 Download the vmlinuz and initrd.img from URL. | |
446 """ | |
447 error.context("downloading vmlinuz and initrd.img from %s" % self.url) | |
448 os.chdir(self.image_path) | |
449 kernel_fetch_cmd = "wget -q %s/%s/%s" % (self.url, self.boot_path, | |
450 os.path.basename(self.kernel)) | |
451 initrd_fetch_cmd = "wget -q %s/%s/%s" % (self.url, self.boot_path, | |
452 os.path.basename(self.initrd)) | |
453 | |
454 if os.path.exists(self.kernel): | |
455 os.remove(self.kernel) | |
456 if os.path.exists(self.initrd): | |
457 os.remove(self.initrd) | |
458 | |
459 utils.run(kernel_fetch_cmd) | |
460 utils.run(initrd_fetch_cmd) | |
461 | |
462 | |
463 def setup_nfs(self): | |
464 """ | |
465 Copy the vmlinuz and initrd.img from nfs. | |
466 """ | |
467 error.context("copying the vmlinuz and initrd.img from NFS share") | |
468 | |
469 m_cmd = ("mount %s:%s %s -o ro" % | |
470 (self.nfs_server, self.nfs_dir, self.nfs_mount)) | |
471 utils.run(m_cmd) | |
472 | |
473 try: | |
474 kernel_fetch_cmd = ("cp %s/%s/%s %s" % | |
475 (self.nfs_mount, self.boot_path, | |
476 os.path.basename(self.kernel), self.image_path)) | |
477 utils.run(kernel_fetch_cmd) | |
478 initrd_fetch_cmd = ("cp %s/%s/%s %s" % | |
479 (self.nfs_mount, self.boot_path, | |
480 os.path.basename(self.initrd), self.image_path)) | |
481 utils.run(initrd_fetch_cmd) | |
482 finally: | |
483 cleanup(self.nfs_mount) | |
484 | |
485 | |
486 def setup(self): | |
487 """ | |
488 Configure the environment for unattended install. | |
489 | |
490 Uses an appropriate strategy according to each install model. | |
491 """ | |
492 logging.info("Starting unattended install setup") | |
493 display_attributes(self) | |
494 | |
495 if self.unattended_file and (self.floppy or self.cdrom_unattended): | |
496 self.setup_boot_disk() | |
497 if self.medium == "cdrom": | |
498 if self.kernel and self.initrd: | |
499 self.setup_cdrom() | |
500 elif self.medium == "url": | |
501 self.setup_url() | |
502 elif self.medium == "nfs": | |
503 self.setup_nfs() | |
504 else: | |
505 raise ValueError("Unexpected installation method %s" % | |
506 self.medium) | |
507 | |
508 | |
509 class HugePageConfig(object): | 9 class HugePageConfig(object): |
510 def __init__(self, params): | 10 def __init__(self, params): |
511 """ | 11 """ |
512 Gets environment variable values and calculates the target number | 12 Gets environment variable values and calculates the target number |
513 of huge memory pages. | 13 of huge memory pages. |
514 | 14 |
515 @param params: Dict like object containing parameters for the test. | 15 @param params: Dict like object containing parameters for the test. |
516 """ | 16 """ |
517 self.vms = len(params.objects("vms")) | 17 self.vms = len(params.objects("vms")) |
518 self.mem = int(params.get("mem")) | 18 self.mem = int(params.get("mem")) |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
598 | 98 |
599 @error.context_aware | 99 @error.context_aware |
600 def cleanup(self): | 100 def cleanup(self): |
601 error.context("trying to dealocate hugepage memory") | 101 error.context("trying to dealocate hugepage memory") |
602 try: | 102 try: |
603 utils.system("umount %s" % self.hugepage_path) | 103 utils.system("umount %s" % self.hugepage_path) |
604 except error.CmdError: | 104 except error.CmdError: |
605 return | 105 return |
606 utils.system("echo 0 > %s" % self.kernel_hp_file) | 106 utils.system("echo 0 > %s" % self.kernel_hp_file) |
607 logging.debug("Hugepage memory successfuly dealocated") | 107 logging.debug("Hugepage memory successfuly dealocated") |
608 | |
609 | |
610 class EnospcConfig(object): | |
611 """ | |
612 Performs setup for the test enospc. This is a borg class, similar to a | |
613 singleton. The idea is to keep state in memory for when we call cleanup() | |
614 on postprocessing. | |
615 """ | |
616 __shared_state = {} | |
617 def __init__(self, test, params): | |
618 self.__dict__ = self.__shared_state | |
619 root_dir = test.bindir | |
620 self.tmpdir = test.tmpdir | |
621 self.qemu_img_binary = params.get('qemu_img_binary') | |
622 if not os.path.isfile(self.qemu_img_binary): | |
623 self.qemu_img_binary = os.path.join(root_dir, | |
624 self.qemu_img_binary) | |
625 self.raw_file_path = os.path.join(self.tmpdir, 'enospc.raw') | |
626 # Here we're trying to choose fairly explanatory names so it's less | |
627 # likely that we run in conflict with other devices in the system | |
628 self.vgtest_name = params.get("vgtest_name") | |
629 self.lvtest_name = params.get("lvtest_name") | |
630 self.lvtest_device = "/dev/%s/%s" % (self.vgtest_name, self.lvtest_name) | |
631 image_dir = os.path.dirname(params.get("image_name")) | |
632 self.qcow_file_path = os.path.join(image_dir, 'enospc.qcow2') | |
633 try: | |
634 getattr(self, 'loopback') | |
635 except AttributeError: | |
636 self.loopback = '' | |
637 | |
638 | |
639 @error.context_aware | |
640 def setup(self): | |
641 logging.debug("Starting enospc setup") | |
642 error.context("performing enospc setup") | |
643 display_attributes(self) | |
644 # Double check if there aren't any leftovers | |
645 self.cleanup() | |
646 try: | |
647 utils.run("%s create -f raw %s 10G" % | |
648 (self.qemu_img_binary, self.raw_file_path)) | |
649 # Associate a loopback device with the raw file. | |
650 # Subject to race conditions, that's why try here to associate | |
651 # it with the raw file as quickly as possible | |
652 l_result = utils.run("losetup -f") | |
653 utils.run("losetup -f %s" % self.raw_file_path) | |
654 self.loopback = l_result.stdout.strip() | |
655 # Add the loopback device configured to the list of pvs | |
656 # recognized by LVM | |
657 utils.run("pvcreate %s" % self.loopback) | |
658 utils.run("vgcreate %s %s" % (self.vgtest_name, self.loopback)) | |
659 # Create an lv inside the vg with starting size of 200M | |
660 utils.run("lvcreate -L 200M -n %s %s" % | |
661 (self.lvtest_name, self.vgtest_name)) | |
662 # Create a 10GB qcow2 image in the logical volume | |
663 utils.run("%s create -f qcow2 %s 10G" % | |
664 (self.qemu_img_binary, self.lvtest_device)) | |
665 # Let's symlink the logical volume with the image name that autotest | |
666 # expects this device to have | |
667 os.symlink(self.lvtest_device, self.qcow_file_path) | |
668 except Exception, e: | |
669 self.cleanup() | |
670 raise | |
671 | |
672 @error.context_aware | |
673 def cleanup(self): | |
674 error.context("performing enospc cleanup") | |
675 if os.path.isfile(self.lvtest_device): | |
676 utils.run("fuser -k %s" % self.lvtest_device) | |
677 time.sleep(2) | |
678 l_result = utils.run("lvdisplay") | |
679 # Let's remove all volumes inside the volume group created | |
680 if self.lvtest_name in l_result.stdout: | |
681 utils.run("lvremove -f %s" % self.lvtest_device) | |
682 # Now, removing the volume group itself | |
683 v_result = utils.run("vgdisplay") | |
684 if self.vgtest_name in v_result.stdout: | |
685 utils.run("vgremove -f %s" % self.vgtest_name) | |
686 # Now, if we can, let's remove the physical volume from lvm list | |
687 if self.loopback: | |
688 p_result = utils.run("pvdisplay") | |
689 if self.loopback in p_result.stdout: | |
690 utils.run("pvremove -f %s" % self.loopback) | |
691 l_result = utils.run('losetup -a') | |
692 if self.loopback and (self.loopback in l_result.stdout): | |
693 try: | |
694 utils.run("losetup -d %s" % self.loopback) | |
695 except error.CmdError: | |
696 logging.error("Failed to liberate loopback %s", self.loopback) | |
697 if os.path.islink(self.qcow_file_path): | |
698 os.remove(self.qcow_file_path) | |
699 if os.path.isfile(self.raw_file_path): | |
700 os.remove(self.raw_file_path) | |
OLD | NEW |