Merge lp:~pawciobiel/testdrive/1297377-fix-kvm-img-not-found-report-error into lp:testdrive

Proposed by pawciobiel
Status: Merged
Merged at revision: 451
Proposed branch: lp:~pawciobiel/testdrive/1297377-fix-kvm-img-not-found-report-error
Merge into: lp:testdrive
Diff against target: 345 lines (+108/-56)
7 files modified
bin/testdrive (+14/-9)
bin/testdrive-gtk (+18/-13)
testdrive/virt/base.py (+16/-0)
testdrive/virt/kvm.py (+24/-10)
testdrive/virt/parallels.py (+12/-10)
testdrive/virt/virtualbox.py (+23/-13)
testdrivegtk/PreferencesTestdrivegtkDialog.py (+1/-1)
To merge this branch: bzr merge lp:~pawciobiel/testdrive/1297377-fix-kvm-img-not-found-report-error
Reviewer Review Type Date Requested Status
Andres Rodriguez Approve
Review via email: mp+234571@code.launchpad.net

Description of the change

merge fix for lp:1297377

* fix virt.kvm so it checks if qemu-img or kvm-img is installed
* check if qemu-utils is installed when user selected kvm
* tide up virt a bit so testdrive-gtk can notify user about errors

To post a comment you must log in.
Revision history for this message
Andres Rodriguez (andreserl) wrote :

lgtm!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'bin/testdrive'
--- bin/testdrive 2013-10-24 02:11:50 +0000
+++ bin/testdrive 2014-09-13 13:13:23 +0000
@@ -74,8 +74,12 @@
74 logger.error(_("\nERROR: Invalid input\n"))74 logger.error(_("\nERROR: Invalid input\n"))
75 continue75 continue
76 if choice == i:76 if choice == i:
77 url = raw_input(_("\nEnter an ISO URL to testdrive: "))77 try:
78 break78 url = raw_input(_("\nEnter an ISO URL to testdrive: "))
79 break
80 except KeyboardInterrupt:
81 print("\n")
82 exit(0)
79 elif choice in range(1, i):83 elif choice in range(1, i):
80 url = menu[choice-1]["url"]84 url = menu[choice-1]["url"]
81 td.ISO_PATH_HEADER = menu[choice-1]["cat"]85 td.ISO_PATH_HEADER = menu[choice-1]["cat"]
@@ -85,7 +89,7 @@
85 return(url)89 return(url)
8690
87def error(str):91def error(str):
88 logger.error(_("\n%s\n") % str)92 logger.error("\n%s\n" % str)
89 sys.exit(1)93 sys.exit(1)
9094
91def is_iso(file):95def is_iso(file):
@@ -401,14 +405,15 @@
401 logger.info(_("Validating Virtualization Method...."))405 logger.info(_("Validating Virtualization Method...."))
402 try:406 try:
403 virt.validate_virt()407 virt.validate_virt()
404 except:408 except Exception as exc:
405 error(_("Unable to validate Virtualization Method [%s]") % td.VIRT)409 error(_("Unable to validate Virtualization Method [%s] (%s)") % \
410 (td.VIRT, exc))
406411
407 logger.info(_("Setting up Virtual Machine..."))412 logger.info(_("Setting up Virtual Machine..."))
408 try:413 try:
409 virt.setup_virt()414 virt.setup_virt()
410 except:415 except Exception as exc:
411 error(_("Unable to setup Virtual Machine"))416 error(_("Unable to setup Virtual Machine (%s)") % exc)
412417
413 logger.info(_("Launching Virtual Machine..."))418 logger.info(_("Launching Virtual Machine..."))
414 try:419 try:
@@ -417,8 +422,8 @@
417 if td.VIRT == "kvm":422 if td.VIRT == "kvm":
418 logging.debug("%s:%s" % (time.strftime("%Y-%m-%d_%H:%M:%S"), cmd))423 logging.debug("%s:%s" % (time.strftime("%Y-%m-%d_%H:%M:%S"), cmd))
419 run_vm(cmd, td, cloud_curses)424 run_vm(cmd, td, cloud_curses)
420 except:425 except Exception as exc:
421 error(_("Unable to launch Virtual Machine"))426 error(_("Unable to launch Virtual Machine (%s)") % (exc))
422427
423 rm_disk = td.delete_image()428 rm_disk = td.delete_image()
424 if rm_disk:429 if rm_disk:
425430
=== modified file 'bin/testdrive-gtk'
--- bin/testdrive-gtk 2013-11-17 08:19:27 +0000
+++ bin/testdrive-gtk 2014-09-13 13:13:23 +0000
@@ -739,10 +739,9 @@
739 if self.td.VIRT == "virtualbox":739 if self.td.VIRT == "virtualbox":
740 logging.info(_("Using VirtualBox for virtual machine hosting..."))740 logging.info(_("Using VirtualBox for virtual machine hosting..."))
741 virt = virtualbox.VBox(self.td)741 virt = virtualbox.VBox(self.td)
742 if self.td.VIRT == "paralels":742 if self.td.VIRT == "parallels":
743 logging.info(_("Using Parallels Desktop for virtual machine hosting..."))743 logging.info(_("Using Parallels Desktop for virtual machine hosting..."))
744 virt = parallels.Parallels(self.td)744 virt = parallels.Parallels(self.td)
745
746 # Passing VIRT object to ISOLIST745 # Passing VIRT object to ISOLIST
747 ISOLIST[vm_id]["virt"] = virt746 ISOLIST[vm_id]["virt"] = virt
748 ISOLIST[vm_id]["virt_type"] = self.td.VIRT747 ISOLIST[vm_id]["virt_type"] = self.td.VIRT
@@ -924,20 +923,24 @@
924 self.p = None923 self.p = None
925924
926 def prepare_to_launch_vm(self):925 def prepare_to_launch_vm(self):
927 ###################################################################926 """Prepare the VM to launch and return launch command"""
928 ######## Prepare the VM to launch and return launch command #######927 try:
929 ###################################################################928 self.ovirt.validate_virt()
930 # TODO TODO TODO - Re-add validation929 self.ovirt.setup_virt()
931 self.ovirt.validate_virt()930 return self.ovirt.launch_virt()
932 self.ovirt.setup_virt()931 except Exception as exc:
933 return self.ovirt.launch_virt()932 text = _("Error preparing virtualization: %s") % (exc)
934
935 def run(self):
936 if self.virt == "virtualbox":
937 text = _(" Configuring Virtual Machine...")
938 self.status_label.set_markup("<b><i>%s</i></b>" % text)933 self.status_label.set_markup("<b><i>%s</i></b>" % text)
939 self.status_label.show()934 self.status_label.show()
935 logging.error("%s", exc, exc_info=1)
936
937 def run(self):
938 text = _(" Configuring Virtual Machine...")
939 self.status_label.set_markup("<b><i>%s</i></b>" % text)
940 self.status_label.show()
940 command = self.prepare_to_launch_vm()941 command = self.prepare_to_launch_vm()
942 if not command: return
943 logger.info("Running VM command %s", command)
941 cmd = command.split()944 cmd = command.split()
942 self.p = subprocess.Popen(cmd, stdout=subprocess.PIPE)945 self.p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
943 text = _(" Running Virtual Machine...")946 text = _(" Running Virtual Machine...")
@@ -948,6 +951,7 @@
948 while not self.stopthread.isSet():951 while not self.stopthread.isSet():
949 if self.p.poll() != None:952 if self.p.poll() != None:
950 self.status_label.set_markup("<i>%s</i>" % self.previous_text)953 self.status_label.set_markup("<i>%s</i>" % self.previous_text)
954 self.status_label.show()
951 self.p = None955 self.p = None
952 break956 break
953 time.sleep(0.1)957 time.sleep(0.1)
@@ -969,6 +973,7 @@
969 break973 break
970 time.sleep(2)974 time.sleep(2)
971975
976
972 def stop(self):977 def stop(self):
973 try:978 try:
974 if self.p.poll() is None:979 if self.p.poll() is None:
975980
=== added file 'testdrive/virt/base.py'
--- testdrive/virt/base.py 1970-01-01 00:00:00 +0000
+++ testdrive/virt/base.py 2014-09-13 13:13:23 +0000
@@ -0,0 +1,16 @@
1
2import os
3
4
5class VirtException(Exception):
6 pass
7
8
9class VirtBase(object):
10
11 def run(self, cmd):
12 return(os.system(cmd))
13
14 def run_or_die(self, cmd):
15 if self.run(cmd) != 0:
16 raise VirtException("Failed executing command: `%s`" % cmd)
017
=== modified file 'testdrive/virt/kvm.py'
--- testdrive/virt/kvm.py 2013-05-20 17:12:31 +0000
+++ testdrive/virt/kvm.py 2014-09-13 13:13:23 +0000
@@ -19,10 +19,15 @@
19# You should have received a copy of the GNU General Public License19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <http://www.gnu.org/licenses/>.20# along with this program. If not, see <http://www.gnu.org/licenses/>.
2121
22import sys
22import commands, os, uuid, logging23import commands, os, uuid, logging
2324
25from .base import VirtException
26
27
24logger = logging.getLogger("testdrive.virt.kvm")28logger = logging.getLogger("testdrive.virt.kvm")
2529
30
26class KVM:31class KVM:
2732
28 def __init__(self, td):33 def __init__(self, td):
@@ -45,19 +50,35 @@
45 def validate_virt(self):50 def validate_virt(self):
46 (status, output) = commands.getstatusoutput("kvm-ok")51 (status, output) = commands.getstatusoutput("kvm-ok")
47 if status != 0:52 if status != 0:
48 logger.info(output)53 logger.warn("kvm-ok failed: %s", output)
54 (status, output) = commands.getstatusoutput("dpkg -l qemu-utils")
55 if status != 0:
56 raise VirtException("Package qemu-utils is not installed.")
57
58 def get_kvm_img_path(self):
59 """Get kvm-img or qemu-img path and return it.
60
61 Fall back to deprecated kvm-img. It may appear to be better
62 to call just `which qemu-img kvm-img` but this way is cleaner.
63 """
64 for cmd in ['qemu-img', 'kvm-img']:
65 status, output = commands.getstatusoutput('which %s' % (cmd))
66 if status == 0 and output:
67 return output.strip()
68 raise VirtException("Can not find qemu-img nor kvm-img!")
4969
50 # Code to setup virtual machine70 # Code to setup virtual machine
51 def setup_virt(self):71 def setup_virt(self):
72 kvm_img = self.get_kvm_img_path()
52 if self.p == 'cloud-daily' or self.p == 'cloud-releases':73 if self.p == 'cloud-daily' or self.p == 'cloud-releases':
53 #path = "%s/%s" % (self.CACHE_ISO, self.PATH_TO_ISO.split(".tar.gz")[0].split("_")[-1])74 #path = "%s/%s" % (self.CACHE_ISO, self.PATH_TO_ISO.split(".tar.gz")[0].split("_")[-1])
54 path = "%s/%s" % (self.CACHE_ISO, os.path.basename(self.PATH_TO_ISO).split(".tar.gz")[0])75 path = "%s/%s" % (self.CACHE_ISO, os.path.basename(self.PATH_TO_ISO).split(".tar.gz")[0])
55 self.ORIG_DISK = "%s.img" % path76 self.ORIG_DISK = "%s.img" % path
56 self.FLOPPY_FILE = "%s-floppy" % path77 self.FLOPPY_FILE = "%s-floppy" % path
57 self.run_or_die("kvm-img create -f qcow2 -b %s %s" % (self.ORIG_DISK, self.DISK_FILE))78 self.run_or_die("%s create -f qcow2 -b %s %s" % (kvm_img, self.ORIG_DISK, self.DISK_FILE))
58 elif not os.path.exists(self.DISK_FILE) or self.is_disk_empty():79 elif not os.path.exists(self.DISK_FILE) or self.is_disk_empty():
59 logger.info("Creating disk image [%s]..." % self.DISK_FILE)80 logger.info("Creating disk image [%s]..." % self.DISK_FILE)
60 self.run_or_die("kvm-img create -f qcow2 %s %s" % (self.DISK_FILE, self.DISK_SIZE))81 self.run_or_die("%s create -f qcow2 %s %s" % (kvm_img, self.DISK_FILE, self.DISK_SIZE))
6182
62 # Code launch virtual machine83 # Code launch virtual machine
63 def launch_virt(self):84 def launch_virt(self):
@@ -68,10 +89,3 @@
68 else:89 else:
69 cmd = "qemu-system-x86_64 -uuid %s -m %s -smp %s -cdrom %s -drive file=%s,if=virtio,cache=writeback,index=0 %s" % (UUID, self.MEM, self.SMP, self.PATH_TO_ISO, self.DISK_FILE, self.KVM_ARGS)90 cmd = "qemu-system-x86_64 -uuid %s -m %s -smp %s -cdrom %s -drive file=%s,if=virtio,cache=writeback,index=0 %s" % (UUID, self.MEM, self.SMP, self.PATH_TO_ISO, self.DISK_FILE, self.KVM_ARGS)
70 return cmd91 return cmd
71
72 def run(self, cmd):
73 return(os.system(cmd))
74
75 def run_or_die(self, cmd):
76 if self.run(cmd) != 0:
77 logger.error("Command failed\n `%s`" % cmd)
7892
=== modified file 'testdrive/virt/parallels.py'
--- testdrive/virt/parallels.py 2012-04-21 02:05:42 +0000
+++ testdrive/virt/parallels.py 2014-09-13 13:13:23 +0000
@@ -19,9 +19,16 @@
19# You should have received a copy of the GNU General Public License19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <http://www.gnu.org/licenses/>.20# along with this program. If not, see <http://www.gnu.org/licenses/>.
2121
22import logging
22import commands, os, time23import commands, os, time
2324
24class Parallels:25from .base import VirtBase, VirtException
26
27
28logger = logging.getLogger(__name__)
29
30
31class Parallels(VirtBase):
2532
26 def __init__(self, td):33 def __init__(self, td):
27 self.HOME = td.HOME34 self.HOME = td.HOME
@@ -32,8 +39,11 @@
32 self.DISK_SIZE = td.DISK_SIZE39 self.DISK_SIZE = td.DISK_SIZE
33 self.VBOX_NAME = td.VBOX_NAME40 self.VBOX_NAME = td.VBOX_NAME
3441
35 # Code to validate if virtualization is installed/supported
36 def validate_virt(self):42 def validate_virt(self):
43 """validate if virtualization is installed/supported"""
44 if commands.getstatusoutput("which prlctl")[0] != 0:
45 raise VirtException("prlctl not found")
46
37 if commands.getstatusoutput("prlctl list %s | grep -qsv \"UUID\"" % self.VBOX_NAME)[0] == 0:47 if commands.getstatusoutput("prlctl list %s | grep -qsv \"UUID\"" % self.VBOX_NAME)[0] == 0:
38 self.run_or_die("prlctl delete %s" % self.VBOX_NAME)48 self.run_or_die("prlctl delete %s" % self.VBOX_NAME)
3949
@@ -55,11 +65,3 @@
55 # Loop as long as this VM is running65 # Loop as long as this VM is running
56 #while commands.getstatusoutput("prlctl list %s | grep -qs stopped" % self.td.VBOX_NAME)[0] != 0:66 #while commands.getstatusoutput("prlctl list %s | grep -qs stopped" % self.td.VBOX_NAME)[0] != 0:
57 # time.sleep(2)67 # time.sleep(2)
58
59 def run(self, cmd):
60 return(os.system(cmd))
61
62 def run_or_die(self, cmd):
63 if self.run(cmd) != 0:
64 #error("Command failed\n `%s`" % cmd)
65 print "Command failed\n `%s`" % cmd
6668
=== modified file 'testdrive/virt/virtualbox.py'
--- testdrive/virt/virtualbox.py 2013-10-28 19:55:24 +0000
+++ testdrive/virt/virtualbox.py 2014-09-13 13:13:23 +0000
@@ -21,9 +21,13 @@
2121
22import commands, os, time, logging22import commands, os, time, logging
2323
24from .base import VirtException, VirtBase
25
26
24logger = logging.getLogger("testdrive.virt.vbox")27logger = logging.getLogger("testdrive.virt.vbox")
2528
26class VBox:29
30class VBox(VirtBase):
2731
28 def __init__(self, td):32 def __init__(self, td):
29 self.vboxversion = None33 self.vboxversion = None
@@ -42,19 +46,32 @@
42 return True46 return True
43 return False47 return False
4448
49 def get_vboxversion(self):
50 status, verstr = commands.getstatusoutput("VBoxManage --version")
51 if status != 0:
52 raise VirtException("No VirtualBox found")
53 try:
54 self.vboxversion = (int(verstr.split(".")[0]),
55 int(verstr.split(".")[1]))
56 except (IndexError, ValueError) as exc:
57 raise VirtException("Can not extract version "
58 "[VBoxManage --version]")
59
60
45 # Code to validate if virtualization is installed/supported61 # Code to validate if virtualization is installed/supported
46 def validate_virt(self):62 def validate_virt(self):
47 # Determine which version of VirtualBox we have installed. What is returned is63 # Determine which version of VirtualBox we have installed. What is returned is
48 # typically a string such as '4.1.0r55467', lets assume that the command line64 # typically a string such as '4.1.0r55467', lets assume that the command line
49 # is consistent within 4.x.x versions extract this part of the65 # is consistent within 4.x.x versions extract this part of the
50 # version string for comparison later66 # version string for comparison later
51 self.vboxversion = commands.getoutput("VBoxManage --version")67 self.vboxversion = self.get_vboxversion()
52 self.vboxversion = ( int(self.vboxversion.split(".")[0]), int(self.vboxversion.split(".")[1]) )68 supported_versions = ((4,0), (4,1), (4,2), (4,3))
53 if self.vboxversion == (4,0) or self.vboxversion == (4,1) or self.vboxversion == (4,2) or self.vboxversion == (4,3):69 if self.vboxversion in supported_versions:
54 logger.info("VirtualBox %s.%s detected." % self.vboxversion)70 logger.info("VirtualBox %s.%s detected." % self.vboxversion)
55 else:71 else:
56 logger.error("ERROR: Unsupported version (%s.%s) of VirtualBox; please install v4.0 or newer." % self.vboxversion)72 err_text = ("Unsupported version (%s.%s) of VirtualBox; "
57 exit(0)73 "please install v4.0 or newer.") % self.vboxversion
74 raise VirtException(err_text)
5875
59 # Code to setup virtual machine76 # Code to setup virtual machine
60 def setup_virt(self):77 def setup_virt(self):
@@ -104,10 +121,3 @@
104 # Loop as long as this VM is running121 # Loop as long as this VM is running
105 #while commands.getstatusoutput("VBoxManage list runningvms | grep -qs %s" % self.td.VBOX_NAME)[0] == 0:122 #while commands.getstatusoutput("VBoxManage list runningvms | grep -qs %s" % self.td.VBOX_NAME)[0] == 0:
106 # time.sleep(2)123 # time.sleep(2)
107
108 def run(self, cmd):
109 return(os.system(cmd))
110
111 def run_or_die(self, cmd):
112 if self.run(cmd) != 0:
113 logger.error("Command failed\n `%s`" % cmd)
114124
=== modified file 'testdrivegtk/PreferencesTestdrivegtkDialog.py'
--- testdrivegtk/PreferencesTestdrivegtkDialog.py 2013-10-24 14:10:11 +0000
+++ testdrivegtk/PreferencesTestdrivegtkDialog.py 2014-09-13 13:13:23 +0000
@@ -481,7 +481,7 @@
481 path = "%s/%s" % (cache_path, file)481 path = "%s/%s" % (cache_path, file)
482 os.unlink(path)482 os.unlink(path)
483 except:483 except:
484 on_error_dlg(_("Unable to clean up files from [%s]") % cache_path)484 self.on_error_dlg(_("Unable to clean up files from [%s]") % cache_path)
485 485
486 def on_select_iso_image_repo(self, widget):486 def on_select_iso_image_repo(self, widget):
487 ##################################################################487 ##################################################################

Subscribers

People subscribed via source and target branches