summaryrefslogtreecommitdiff
path: root/bin/virtualization
diff options
Diffstat (limited to 'bin/virtualization')
-rwxr-xr-xbin/virtualization144
1 files changed, 93 insertions, 51 deletions
diff --git a/bin/virtualization b/bin/virtualization
index f32c7ce..fe59656 100755
--- a/bin/virtualization
+++ b/bin/virtualization
@@ -44,13 +44,11 @@ import tempfile
import tarfile
import time
import urllib.request
+from urllib.parse import urlparse
DEFAULT_TIMEOUT = 500
-class XENTest(object):
- pass
-
# The "TAR" type is a tarball that contains both
# a disk image and a kernel binary. This is useful
# on architectures that don't (yet) have a bootloader
@@ -88,7 +86,7 @@ QEMU_ARCH_CONFIG = {
},
'amd64': {
'cloudimg_type': CLOUD_IMAGE_TYPE_DISK,
- 'cloudimg_arch': 'i386',
+ 'cloudimg_arch': 'amd64',
'qemu_bin': 'qemu-system-x86_64',
'qemu_disk_type': QEMU_DISK_TYPE_VIRTIO,
'qemu_extra_args': [
@@ -110,7 +108,19 @@ QEMU_ARCH_CONFIG = {
'qemu_bin': 'qemu-system-ppc64',
'qemu_disk_type': QEMU_DISK_TYPE_VIRTIO,
'qemu_extra_args': [
- '-machine', 'pseries',
+ '-enable-kvm',
+ '-machine', 'pseries,usb=off',
+ '-cpu', 'POWER8',
+ ],
+ },
+ 's390x': {
+ 'cloudimg_type': CLOUD_IMAGE_TYPE_DISK,
+ 'cloudimg_arch': 's390x',
+ 'qemu_bin': 'qemu-system-s390x',
+ 'qemu_disk_type': QEMU_DISK_TYPE_VIRTIO,
+ 'qemu_extra_args': [
+ '-enable-kvm',
+ '-machine', 's390-ccw-virtio-2.5',
],
},
}
@@ -124,7 +134,7 @@ class QemuRunner(object):
# Parameters common to all architectures
self.params = [
self.config['qemu_bin'],
- "-m", "256",
+ "-m", "1024",
"-display", "none",
"-nographic",
"-net", "nic",
@@ -133,11 +143,8 @@ class QemuRunner(object):
# If arch is arm64, add the machine type for gicv3, or default to old
# type
if self.arch == 'arm64':
- if glob("/sys/firmware/devicetree/base/interrupt-controller@*/compatible"):
- self.config['qemu_extra_args'].extend(
- ['-machine', 'virt,gic_version=3'])
- else:
- self.config['qemu_extra_args'].extend(['-machine', 'virt'])
+ (self.config['qemu_extra_args'].
+ extend(['-machine', 'virt,gic_version=host']))
# Add any architecture-specific parameters
if 'qemu_extra_args' in self.config:
self.params = self.params + self.config['qemu_extra_args']
@@ -191,35 +198,68 @@ class KVMTest(object):
self.arch = check_output(['dpkg', '--print-architecture'],
universal_newlines=True).strip()
self.qemu_config = QEMU_ARCH_CONFIG[self.arch]
+ self.release = lsb_release.get_lsb_information()["CODENAME"]
- def download_image(self):
+ def url_to_path(self, image_path):
"""
- Downloads Cloud image for same release as host machine
+ Test the provided image path to determine if it's a URL or or a simple
+ file path
+ """
+ url = urlparse(image_path)
+ if url.scheme == '' or url.scheme == 'file':
+ # Gives us path wheter we specify a filesystem path or a file URL
+ logging.debug("Cloud image exists locally at %s" % url.path)
+ return url.path
+ elif url.scheme == 'http' or url.scheme == 'ftp':
+ # Gives us the stuff needed to build the URL to download the image
+ return self.download_image(image_path)
+
+ def construct_cloud_filename(self):
+ """
+ Build a URL for official Ubuntu images hosted either at
+ cloud-images.ubuntu.com or on a maas server hosting a mirror of
+ cloud-images.ubuntu.com
"""
-
- # Check Ubuntu release info. Example {quantal, precise}
- release = lsb_release.get_lsb_information()["CODENAME"]
-
- # Construct URL
- cloud_url = "http://cloud-images.ubuntu.com"
-
if self.qemu_config['cloudimg_type'] == CLOUD_IMAGE_TYPE_TAR:
cloud_iso = "%s-server-cloudimg-%s.tar.gz" % (
- release, self.qemu_config['cloudimg_arch'])
+ self.release, self.qemu_config['cloudimg_arch'])
elif self.qemu_config['cloudimg_type'] == CLOUD_IMAGE_TYPE_DISK:
cloud_iso = "%s-server-cloudimg-%s-disk1.img" % (
- release, self.qemu_config['cloudimg_arch'])
+ self.release, self.qemu_config['cloudimg_arch'])
else:
logging.error("Unknown cloud image type")
- return False
- image_url = "/".join((
- cloud_url, release, "current", cloud_iso))
+ sys.exit(1)
+ return cloud_iso
+ def download_image(self, image_url=None):
+ """
+ Downloads Cloud image for same release as host machine
+ """
+ if image_url is None:
+ # If we have not specified a URL to get our images from, default
+ # to ubuntu.com
+ cloud_url = "http://cloud-images.ubuntu.com"
+ cloud_iso = self.construct_cloud_filename()
+ full_url = "/".join((
+ cloud_url, self.release, "current", cloud_iso))
+ else:
+ url = urlparse(image_url)
+ if url.path.endswith('/') or url.path == '':
+ # If we have a relative URL (MAAS server mirror)
+ cloud_url = image_url
+ cloud_iso = self.construct_cloud_filename()
+ full_url = "/".join((
+ cloud_url, cloud_iso))
+ else:
+ # Assume anything else is an absolute URL to a remote server
+ cloud_iso = url.path.split('/')[-1]
+ cloud_url = "{}://{}".format(url.scheme, url.netloc)
+ full_url = image_url
logging.debug("Downloading {}, from {}".format(cloud_iso, cloud_url))
# Attempt download
try:
- resp = urllib.request.urlretrieve(image_url, cloud_iso)
+ resp = urllib.request.urlretrieve(full_url, cloud_iso)
except (IOError,
OSError,
urllib.error.HTTPError,
@@ -324,6 +364,22 @@ final_message: CERTIFICATION BOOT COMPLETE
logging.exception("Cloud data disk creation failed")
def start(self):
+ if self.arch == 'arm64':
+ # lp:1548539 - For arm64, we need to make sure we're using qemu
+ # later than 2.0.0 to enable gic_version functionality
+ logging.debug('Checking QEMU version for arm64 arch')
+ cmd = 'apt-cache policy qemu-system-arm | grep Installed'
+ installed_version = (check_output(['/bin/bash', '-c', cmd]).
+ decode().split(':', 1)[1].strip())
+
+ cmd = ('dpkg --compare-versions \"2.0.0\" \"lt\" \"{}\"'
+ .format(installed_version))
+ retcode = call(['/bin/bash', '-c', cmd])
+ if retcode != 0:
+ logging.error('arm64 needs qemu-system version later than '
+ '2.0.0')
+ return 1
+
logging.debug('Starting KVM Test')
status = 1
# Create temp directory:
@@ -337,6 +393,10 @@ final_message: CERTIFICATION BOOT COMPLETE
logging.debug('No image specified, downloading one now.')
# Download cloud image
self.image = self.download_image()
+ else:
+ logging.debug('Cloud image location specified: %s.' %
+ self.image)
+ self.image = self.url_to_path(self.image)
if self.image and os.path.isfile(self.image):
@@ -385,34 +445,10 @@ final_message: CERTIFICATION BOOT COMPLETE
def test_kvm(args):
print("Executing KVM Test", file=sys.stderr)
- DEFAULT_CFG = "/etc/checkbox.d/virtualization.cfg"
image = ""
timeout = ""
- # Configuration data can come from three sources.
- # Lowest priority is the config file.
- config_file = DEFAULT_CFG
- config = configparser.SafeConfigParser()
-
- try:
- config.readfp(open(config_file))
- except IOError:
- logging.warn("No config file found")
- else:
- try:
- timeout = config.getfloat("KVM", "timeout")
- except ValueError:
- logging.warning('Invalid or Empty timeout in config file. '
- 'Falling back to default')
- except configparser.NoSectionError as e:
- logging.exception(e)
-
- try:
- image = config.get("KVM", "image")
- except configparser.NoSectionError:
- logging.exception('Invalid or Empty image in config file.')
-
- # Next in priority are environment variables.
+ # First in priority are environment variables.
if 'KVM_TIMEOUT' in os.environ:
try:
timeout = float(os.environ['KVM_TIMEOUT'])
@@ -431,7 +467,13 @@ def test_kvm(args):
image = args.image
kvm_test = KVMTest(image, timeout, args.log_file)
+ # If arch is ppc64el, disable smt
+ if kvm_test.arch == 'ppc64el':
+ os.system("/usr/sbin/ppc64_cpu --smt=off")
result = kvm_test.start()
+ # If arch is ppc64el, re-enable smt
+ if kvm_test.arch == 'ppc64el':
+ os.system("/usr/sbin/ppc64_cpu --smt=on")
sys.exit(result)