From 4a4ae927611a5939a45c8018a26cd639066e9fde Mon Sep 17 00:00:00 2001 From: Jeff Lane Date: Wed, 1 Feb 2017 12:50:07 -0500 Subject: First working version of LXD test --- bin/virtualization | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 131 insertions(+), 3 deletions(-) diff --git a/bin/virtualization b/bin/virtualization index ff11061..2b04aed 100755 --- a/bin/virtualization +++ b/bin/virtualization @@ -37,8 +37,11 @@ import signal from subprocess import ( Popen, PIPE, + STDOUT, + DEVNULL, CalledProcessError, check_output, + check_call, call ) import sys @@ -514,6 +517,123 @@ final_message: CERTIFICATION BOOT COMPLETE return status +class LXDTest(object): + + def __init__(self, template = None, rootfs = None): + self.rootfs_url = rootfs + self.template_url = template + self.rootfs_tarball = None + self.template_tarball = None + + def setup(self): + # Initialize LXD + result = True + logging.debug("Attempting to initialize LXD") + try: + check_output(['lxd'], universal_newlines=True, stderr=STDOUT) + except CalledProcessError as err: + logging.debug('LXD appears to be running') + logging.debug(err.output) + else: + try: + check_output(['lxd', 'init', '--auto'], stderr=DEVNULL) + except CalledProcessError as init_error: + logging.error('Unable to initialize LXD') + logging.error(init_error.output) + result = False + + # Retrieve and insert LXD images + if self.template_url is not None: + filename = urlparse(self.template_url).path.split('/')[-1] + self.template_tarball = self.download_images(self.template_url, + filename) + if not self.template_tarball: + logging.error("Unable to download {} from " + "{}".format(self.template_tarball, self.template_url)) + logging.error("Aborting") + result = False + + if self.rootfs_url is not None: + filename = urlparse(self.rootfs_url).path.split('/')[-1] + self.rootfs_tarball = self.download_images(self.rootfs_url, + filename) + if not self.rootfs_tarball: + logging.error("Unable to download {} from{}".format( + self.rootfs_tarball, self.rootfs_url)) + logging.error("Aborting") + result = False + + # Insert images + # TODO: + # * catch situation where image already exists + logging.debug("Importing images into LXD") + cmd = 'lxc image import {} rootfs {} --alias ubuntu'.format( + self.template_tarball, self.rootfs_tarball) + try: + check_output(shlex.split(cmd), universal_newlines=True) + except CalledProcessError as err: + logging.error("Failed to insert LXC images.") + logging.error(err.output) + result = False + + return result + + def download_images(self, url, filename): + """ + Downloads LXD files for same release as host machine + """ + logging.debug("Attempting download of {} from {}".format(filename, + url)) + try: + resp = urllib.request.urlretrieve(url, filename) + except (IOError, + Error, + urllib.error.HTTPError, + urllib.error.URLError) as exception: + logging.error("Failed download of image from %s: %s", + image_url, exception) + return False + + if not os.path.isfile(filename): + logging.warn("Can not find {}".format(filename)) + return False + + return filename + + def start(self): + """ + Creates a container and performs the test + """ + result = self.setup() + if not result: + logging.warn("One or more setup stages failed.") + + # Create container + try: + check_call(['lxc', 'launch', 'ubuntu', "testbed"]) + except CalledProcessError as err: + logging.error("Unable to launch container!") + logging.error(err) + return False + + cmd = "lxc exec testbed uptime" + try: + print(check_output(shlex.split(cmd), universal_newlines=True)) + except CalledProcessError as err: + logging.error("Failed to connect to container!") + logging.error(err) + return False + + print("PASS: Container was succssfully started and checked") + return True + +def test_lxd(args): + print("Executing LXD Test") + + lxd_test = LXDTest(args.template, args.rootfs) + + result = lxd_test.start() + sys.exit(result) def test_kvm(args): print("Executing KVM Test", file=sys.stderr) @@ -559,6 +679,11 @@ def main(): # Main cli options kvm_test_parser = subparsers.add_parser( 'kvm', help=("Run kvm virtualization test")) + lxd_test_parser = subparsers.add_parser( + 'lxd', help=("Run the LXD validation test")) + parser.add_argument('--debug', dest='log_level', + action="store_const", const=logging.DEBUG, + default=logging.INFO) # Sub test options kvm_test_parser.add_argument( @@ -568,11 +693,14 @@ def main(): kvm_test_parser.add_argument( '-l', '--log-file', default='virt_debug', help="Location for debugging output log. Defaults to %(default)s.") - kvm_test_parser.add_argument('--debug', dest='log_level', - action="store_const", const=logging.DEBUG, - default=logging.INFO) kvm_test_parser.set_defaults(func=test_kvm) + lxd_test_parser.add_argument( + '--template', type=str, default=None) + lxd_test_parser.add_argument( + '--rootfs', type=str, default=None) + lxd_test_parser.set_defaults(func=test_lxd) + args = parser.parse_args() try: -- cgit v1.2.3 From b5438a2892c36cc9f0a71817ff2c67ccc0abbb13 Mon Sep 17 00:00:00 2001 From: Jeff Lane Date: Thu, 9 Feb 2017 16:08:37 -0500 Subject: Working LXD test now present. --- bin/virtualization | 100 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 66 insertions(+), 34 deletions(-) diff --git a/bin/virtualization b/bin/virtualization index 2b04aed..0954691 100755 --- a/bin/virtualization +++ b/bin/virtualization @@ -529,48 +529,56 @@ class LXDTest(object): # Initialize LXD result = True logging.debug("Attempting to initialize LXD") + # TODO: Need a method to see if LXD is already initialized try: - check_output(['lxd'], universal_newlines=True, stderr=STDOUT) - except CalledProcessError as err: - logging.debug('LXD appears to be running') - logging.debug(err.output) - else: - try: - check_output(['lxd', 'init', '--auto'], stderr=DEVNULL) - except CalledProcessError as init_error: - logging.error('Unable to initialize LXD') - logging.error(init_error.output) - result = False + check_output(['lxd', 'init', '--auto'], stderr=DEVNULL) + except CalledProcessError as init_error: + logging.error('Unable to initialize LXD') + logging.debug(init_error.output) + result = False # Retrieve and insert LXD images + logging.debug("Downloading template.") if self.template_url is not None: - filename = urlparse(self.template_url).path.split('/')[-1] - self.template_tarball = self.download_images(self.template_url, - filename) - if not self.template_tarball: - logging.error("Unable to download {} from " - "{}".format(self.template_tarball, self.template_url)) - logging.error("Aborting") - result = False - + targetfile = urlparse(self.template_url).path.split('/')[-1] + filename = os.path.join('/tmp', targetfile) + if not os.path.isfile(filename): + self.template_tarball = self.download_images(self.template_url, + filename) + if not self.template_tarball: + logging.error("Unable to download {} from " + "{}".format(self.template_tarball, self.template_url)) + logging.error("Aborting") + result = False + else: + logging.debug("Template file {} already exists. " + "Skipping Download.".format(filename)) + self.template_tarball = filename + + logging.debug("Downloading rootfs.") if self.rootfs_url is not None: - filename = urlparse(self.rootfs_url).path.split('/')[-1] - self.rootfs_tarball = self.download_images(self.rootfs_url, + targetfile = urlparse(self.rootfs_url).path.split('/')[-1] + filename = os.path.join('/tmp', targetfile) + if not os.path.isfile(filename): + self.rootfs_tarball = self.download_images(self.rootfs_url, filename) - if not self.rootfs_tarball: - logging.error("Unable to download {} from{}".format( + if not self.rootfs_tarball: + logging.error("Unable to download {} from{}".format( self.rootfs_tarball, self.rootfs_url)) - logging.error("Aborting") - result = False + logging.error("Aborting") + result = False + else: + logging.debug("Template file {} already exists. " + "Skipping Download.".format(filename)) + self.rootfs_tarball = filename # Insert images - # TODO: - # * catch situation where image already exists + # TODO: check to see if ubuntu already exists logging.debug("Importing images into LXD") cmd = 'lxc image import {} rootfs {} --alias ubuntu'.format( self.template_tarball, self.rootfs_tarball) try: - check_output(shlex.split(cmd), universal_newlines=True) + check_output(shlex.split(cmd), stderr=STDOUT, universal_newlines=True) except CalledProcessError as err: logging.error("Failed to insert LXC images.") logging.error(err.output) @@ -600,6 +608,22 @@ class LXDTest(object): return filename + def cleanup(self): + # Clean up image + logging.debug('Cleaning up images and containers created during test') + try: + check_output(['lxc', 'image', 'delete', 'ubuntu'], stderr=STDOUT, universal_newlines=True) + except CalledProcessError as err: + logging.error('Unable to remove image from LXC image store. This may cause problems on re-runs') + logging.debug(err.output) + + # Clean up container + try: + check_output(['lxc', 'delete', 'testbed', '--force'], stderr=STDOUT, universal_newlines=True) + except CalledProcessError as err: + logging.error('Unable to destroy container. This may cause problems on re-runs') + logging.debug(err.output) + def start(self): """ Creates a container and performs the test @@ -609,22 +633,24 @@ class LXDTest(object): logging.warn("One or more setup stages failed.") # Create container + logging.debug("Launching container") try: - check_call(['lxc', 'launch', 'ubuntu', "testbed"]) + check_output(['lxc', 'launch', 'ubuntu', "testbed"], stderr=STDOUT, universal_newlines=True) except CalledProcessError as err: logging.error("Unable to launch container!") - logging.error(err) + logging.debug(err.output) return False + + time.sleep(60) cmd = "lxc exec testbed uptime" try: - print(check_output(shlex.split(cmd), universal_newlines=True)) + check_output(shlex.split(cmd), stderr=STDOUT, universal_newlines=True) except CalledProcessError as err: logging.error("Failed to connect to container!") - logging.error(err) + logging.debug(err.output) return False - print("PASS: Container was succssfully started and checked") return True def test_lxd(args): @@ -633,6 +659,12 @@ def test_lxd(args): lxd_test = LXDTest(args.template, args.rootfs) result = lxd_test.start() + lxd_test.cleanup() + if result: + print("PASS: Container was succssfully started and checked") + else: + print("FAIL: Container was not started and checked") + sys.exit(result) def test_kvm(args): -- cgit v1.2.3 From e58502d706daec15637a5f7b3baeb88c8ba09dd1 Mon Sep 17 00:00:00 2001 From: Jeff Lane Date: Fri, 10 Feb 2017 17:13:30 -0500 Subject: refactored lxd test code --- bin/virtualization | 109 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 62 insertions(+), 47 deletions(-) diff --git a/bin/virtualization b/bin/virtualization index 0954691..5c43cc5 100755 --- a/bin/virtualization +++ b/bin/virtualization @@ -23,6 +23,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . """ +import pdb from argparse import ArgumentParser import configparser from glob import glob @@ -517,6 +518,31 @@ final_message: CERTIFICATION BOOT COMPLETE return status +class RunCommand(object): + """ + Runs a command and can return all needed info: + * stdout + * stderr + * return code + * original command + + Convenince class to avoid the same repetitive code to run shell commands. + """ + + def __init__(self, cmd = None): + self.stdout = None + self.stderr = None + self.returncode = None + self.cmd = cmd + self.run(self.cmd) + + + def run(self,cmd): + proc = Popen(shlex.split(cmd), stdout=PIPE, stderr=PIPE, universal_newlines=True) + self.stdout, self.stderr = proc.communicate() + self.returncode = proc.returncode + + class LXDTest(object): def __init__(self, template = None, rootfs = None): @@ -524,24 +550,34 @@ class LXDTest(object): self.template_url = template self.rootfs_tarball = None self.template_tarball = None + self.name = 'testbed' + self.image_alias = 'ubuntu' + + def run_command(self, cmd): + task = RunCommand(cmd) + if task.returncode != 0: + logging.error('Command {} returnd a code of {}'.format(task.cmd, task.returncode)) + logging.error(' STDOUT: {}'.format(task.stdout)) + logging.error(' STDERR: {}'.format(task.stderr)) + return False + + return True def setup(self): # Initialize LXD result = True logging.debug("Attempting to initialize LXD") # TODO: Need a method to see if LXD is already initialized - try: - check_output(['lxd', 'init', '--auto'], stderr=DEVNULL) - except CalledProcessError as init_error: - logging.error('Unable to initialize LXD') - logging.debug(init_error.output) + if not self.run_command('lxd init --auto'): + logging.error('Error encounterd while initializing LXD') result = False - + # Retrieve and insert LXD images logging.debug("Downloading template.") if self.template_url is not None: - targetfile = urlparse(self.template_url).path.split('/')[-1] - filename = os.path.join('/tmp', targetfile) + filename = urlparse(self.template_url).path.split('/')[-1] + #targetfile = urlparse(self.template_url).path.split('/')[-1] + #filename = os.path.join('/tmp', targetfile) if not os.path.isfile(filename): self.template_tarball = self.download_images(self.template_url, filename) @@ -557,8 +593,9 @@ class LXDTest(object): logging.debug("Downloading rootfs.") if self.rootfs_url is not None: - targetfile = urlparse(self.rootfs_url).path.split('/')[-1] - filename = os.path.join('/tmp', targetfile) + filname = urlparse(self.rootfs_url).path.split('/')[-1] + #targetfile = urlparse(self.rootfs_url).path.split('/')[-1] + #filename = os.path.join('/tmp', targetfile) if not os.path.isfile(filename): self.rootfs_tarball = self.download_images(self.rootfs_url, filename) @@ -575,13 +612,10 @@ class LXDTest(object): # Insert images # TODO: check to see if ubuntu already exists logging.debug("Importing images into LXD") - cmd = 'lxc image import {} rootfs {} --alias ubuntu'.format( - self.template_tarball, self.rootfs_tarball) - try: - check_output(shlex.split(cmd), stderr=STDOUT, universal_newlines=True) - except CalledProcessError as err: - logging.error("Failed to insert LXC images.") - logging.error(err.output) + cmd = 'lxc image import {} rootfs {} --alias {}'.format( + self.template_tarball, self.rootfs_tarball, self.image_alias) + if not self.run_command(cmd): + logging.error('Error encountered while attempting to import images into LXD') result = False return result @@ -609,20 +643,12 @@ class LXDTest(object): return filename def cleanup(self): - # Clean up image + """ + Clean up test files an containers created + """ logging.debug('Cleaning up images and containers created during test') - try: - check_output(['lxc', 'image', 'delete', 'ubuntu'], stderr=STDOUT, universal_newlines=True) - except CalledProcessError as err: - logging.error('Unable to remove image from LXC image store. This may cause problems on re-runs') - logging.debug(err.output) - - # Clean up container - try: - check_output(['lxc', 'delete', 'testbed', '--force'], stderr=STDOUT, universal_newlines=True) - except CalledProcessError as err: - logging.error('Unable to destroy container. This may cause problems on re-runs') - logging.debug(err.output) + self.run_command('lxc image delete {}'.format(self.image_alias)) + self.run_command('lxc delete --force {}'.format(self.name)) def start(self): """ @@ -634,27 +660,16 @@ class LXDTest(object): # Create container logging.debug("Launching container") - try: - check_output(['lxc', 'launch', 'ubuntu', "testbed"], stderr=STDOUT, universal_newlines=True) - except CalledProcessError as err: - logging.error("Unable to launch container!") - logging.debug(err.output) + if not self.run_command('lxc launch {} {}'.format(self.image_alias,self.name)): return False - - time.sleep(60) - - cmd = "lxc exec testbed uptime" - try: - check_output(shlex.split(cmd), stderr=STDOUT, universal_newlines=True) - except CalledProcessError as err: - logging.error("Failed to connect to container!") - logging.debug(err.output) + cmd = "lxc exec {} dd if=/dev/urandom of=testdata.txt bs=1024 count=1000".format(self.name) + if not self.run_command(cmd): return False return True def test_lxd(args): - print("Executing LXD Test") + logging.debug("Executing LXD Test") lxd_test = LXDTest(args.template, args.rootfs) @@ -662,10 +677,10 @@ def test_lxd(args): lxd_test.cleanup() if result: print("PASS: Container was succssfully started and checked") + sys.exit(0) else: print("FAIL: Container was not started and checked") - - sys.exit(result) + sys.exit(1) def test_kvm(args): print("Executing KVM Test", file=sys.stderr) -- cgit v1.2.3 From f9b953a8f4039a9dfa0702649cee8bceba08df9a Mon Sep 17 00:00:00 2001 From: Jeff Lane Date: Fri, 10 Feb 2017 17:35:41 -0500 Subject: pep8 fixes --- bin/virtualization | 71 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 39 insertions(+), 32 deletions(-) diff --git a/bin/virtualization b/bin/virtualization index 5c43cc5..0551c4a 100755 --- a/bin/virtualization +++ b/bin/virtualization @@ -518,6 +518,7 @@ final_message: CERTIFICATION BOOT COMPLETE return status + class RunCommand(object): """ Runs a command and can return all needed info: @@ -527,25 +528,25 @@ class RunCommand(object): * original command Convenince class to avoid the same repetitive code to run shell commands. - """ + """ - def __init__(self, cmd = None): + def __init__(self, cmd=None): self.stdout = None self.stderr = None self.returncode = None self.cmd = cmd self.run(self.cmd) - - def run(self,cmd): - proc = Popen(shlex.split(cmd), stdout=PIPE, stderr=PIPE, universal_newlines=True) + def run(self, cmd): + proc = Popen(shlex.split(cmd), stdout=PIPE, stderr=PIPE, + universal_newlines=True) self.stdout, self.stderr = proc.communicate() - self.returncode = proc.returncode + self.returncode = proc.returncode class LXDTest(object): - def __init__(self, template = None, rootfs = None): + def __init__(self, template=None, rootfs=None): self.rootfs_url = rootfs self.template_url = template self.rootfs_tarball = None @@ -556,7 +557,8 @@ class LXDTest(object): def run_command(self, cmd): task = RunCommand(cmd) if task.returncode != 0: - logging.error('Command {} returnd a code of {}'.format(task.cmd, task.returncode)) + logging.error('Command {} returnd a code of {}'.format( + task.cmd, task.returncode)) logging.error(' STDOUT: {}'.format(task.stdout)) logging.error(' STDERR: {}'.format(task.stderr)) return False @@ -571,34 +573,33 @@ class LXDTest(object): if not self.run_command('lxd init --auto'): logging.error('Error encounterd while initializing LXD') result = False - + # Retrieve and insert LXD images logging.debug("Downloading template.") if self.template_url is not None: - filename = urlparse(self.template_url).path.split('/')[-1] - #targetfile = urlparse(self.template_url).path.split('/')[-1] - #filename = os.path.join('/tmp', targetfile) + targetfile = urlparse(self.template_url).path.split('/')[-1] + filename = os.path.join('/tmp', targetfile) if not os.path.isfile(filename): - self.template_tarball = self.download_images(self.template_url, + self.template_tarball = self.download_images(self.template_url, filename) - if not self.template_tarball: - logging.error("Unable to download {} from " - "{}".format(self.template_tarball, self.template_url)) - logging.error("Aborting") - result = False + if not self.template_tarball: + logging.error("Unable to download {} from " + "{}".format(self.template_tarball, + self.template_url)) + logging.error("Aborting") + result = False else: logging.debug("Template file {} already exists. " "Skipping Download.".format(filename)) self.template_tarball = filename - + logging.debug("Downloading rootfs.") if self.rootfs_url is not None: - filname = urlparse(self.rootfs_url).path.split('/')[-1] - #targetfile = urlparse(self.rootfs_url).path.split('/')[-1] - #filename = os.path.join('/tmp', targetfile) + targetfile = urlparse(self.rootfs_url).path.split('/')[-1] + filename = os.path.join('/tmp', targetfile) if not os.path.isfile(filename): self.rootfs_tarball = self.download_images(self.rootfs_url, - filename) + filename) if not self.rootfs_tarball: logging.error("Unable to download {} from{}".format( self.rootfs_tarball, self.rootfs_url)) @@ -613,18 +614,20 @@ class LXDTest(object): # TODO: check to see if ubuntu already exists logging.debug("Importing images into LXD") cmd = 'lxc image import {} rootfs {} --alias {}'.format( - self.template_tarball, self.rootfs_tarball, self.image_alias) + self.template_tarball, self.rootfs_tarball, + self.image_alias) if not self.run_command(cmd): - logging.error('Error encountered while attempting to import images into LXD') + logging.error('Error encountered while attempting to ' + 'import images into LXD') result = False - + return result def download_images(self, url, filename): """ Downloads LXD files for same release as host machine """ - logging.debug("Attempting download of {} from {}".format(filename, + logging.debug("Attempting download of {} from {}".format(filename, url)) try: resp = urllib.request.urlretrieve(url, filename) @@ -660,19 +663,22 @@ class LXDTest(object): # Create container logging.debug("Launching container") - if not self.run_command('lxc launch {} {}'.format(self.image_alias,self.name)): + if not self.run_command('lxc launch {} {}'.format(self.image_alias, + self.name)): return False - cmd = "lxc exec {} dd if=/dev/urandom of=testdata.txt bs=1024 count=1000".format(self.name) - if not self.run_command(cmd): + cmd = ("lxc exec {} dd if=/dev/urandom of=testdata.txt " + "bs=1024 count=1000".format(self.name)) + if not self.run_command(cmd): return False return True + def test_lxd(args): logging.debug("Executing LXD Test") - + lxd_test = LXDTest(args.template, args.rootfs) - + result = lxd_test.start() lxd_test.cleanup() if result: @@ -682,6 +688,7 @@ def test_lxd(args): print("FAIL: Container was not started and checked") sys.exit(1) + def test_kvm(args): print("Executing KVM Test", file=sys.stderr) -- cgit v1.2.3 From 22537dbaebf92cb15c2b7173f915e8bb1b3e0387 Mon Sep 17 00:00:00 2001 From: Jeff Lane Date: Fri, 10 Feb 2017 18:27:42 -0500 Subject: jobs/virtualization.txt.in: added lxd job --- jobs/virtualization.txt.in | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/jobs/virtualization.txt.in b/jobs/virtualization.txt.in index 919691b..4def608 100644 --- a/jobs/virtualization.txt.in +++ b/jobs/virtualization.txt.in @@ -14,3 +14,18 @@ _description: cloud image. _summary: Verify KVM guest boots + +plugin: shell +category_id: 2013.com.canonical.plainbox::virtualization +id: virtualization/verify_lxd +user: root +environ: LXD_TEMPLATE LXD_ROOTFS +estimated_duration: 30.0 +requires: + package.name == 'lxd-client' + package.name == 'lxd' +command: virtualization lxd --template $LXD_TEMPLATE --rootfs $LXD_ROOTFS +_description: + Verifies that an LXD container can be created and launched +_summary: + Verify LXD container launches -- cgit v1.2.3 From ac933b55d333d433dd41c19e6bf749aaccb1143f Mon Sep 17 00:00:00 2001 From: Jeff Lane Date: Sat, 11 Feb 2017 10:41:28 -0500 Subject: fixed regression in kvm test description caused by my changes for LXD tests --- jobs/virtualization.txt.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jobs/virtualization.txt.in b/jobs/virtualization.txt.in index 4def608..2a466af 100644 --- a/jobs/virtualization.txt.in +++ b/jobs/virtualization.txt.in @@ -8,7 +8,7 @@ requires: package.name == 'qemu-system' package.name == 'qemu-utils' virtualization.kvm == 'supported' -command: virtualization kvm --debug --log-file=$PLAINBOX_SESSION_SHARE/virt_debug +command: virtualization --debug kvm --log-file=$PLAINBOX_SESSION_SHARE/virt_debug _description: Verifies that a KVM guest can be created and booted using an Ubuntu Server cloud image. -- cgit v1.2.3 From a80a96028ad572d22cfb893700ff02970dfed4b2 Mon Sep 17 00:00:00 2001 From: Jeff Lane Date: Mon, 13 Feb 2017 19:18:43 -0500 Subject: Forgot to remove the import of pdb from debugging --- bin/virtualization | 1 - 1 file changed, 1 deletion(-) diff --git a/bin/virtualization b/bin/virtualization index 0551c4a..acb3c79 100755 --- a/bin/virtualization +++ b/bin/virtualization @@ -23,7 +23,6 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . """ -import pdb from argparse import ArgumentParser import configparser from glob import glob -- cgit v1.2.3 From 38847a8f5b6e6a5989e5ce399c6734df290aa09f Mon Sep 17 00:00:00 2001 From: Jeff Lane Date: Tue, 28 Mar 2017 15:00:50 -0400 Subject: More refinements to LXD tests LP: #1677003 --- bin/virtualization | 75 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 54 insertions(+), 21 deletions(-) diff --git a/bin/virtualization b/bin/virtualization index acb3c79..db70849 100755 --- a/bin/virtualization +++ b/bin/virtualization @@ -30,6 +30,7 @@ import os import re import logging import lsb_release +import platform import requests from requests.packages.urllib3.exceptions import NewConnectionError import shlex @@ -50,6 +51,7 @@ import tarfile import time import urllib.request from urllib.parse import urlparse +from uuid import uuid4 DEFAULT_TIMEOUT = 500 @@ -551,7 +553,9 @@ class LXDTest(object): self.rootfs_tarball = None self.template_tarball = None self.name = 'testbed' - self.image_alias = 'ubuntu' + self.image_alias = uuid4().hex + self.default_remote = "ubuntu:" + self.os_version = platform.linux_distribution()[1] def run_command(self, cmd): task = RunCommand(cmd) @@ -561,8 +565,15 @@ class LXDTest(object): logging.error(' STDOUT: {}'.format(task.stdout)) logging.error(' STDERR: {}'.format(task.stderr)) return False - - return True + else: + logging.debug('Command {}:'.format(task.cmd)) + if task.stdout != '': + logging.debug(' STDOUT: {}'.format(task.stdout)) + elif task.stderr != '': + logging.debug(' STDERR: {}'.format(task.stderr)) + else: + logging.debug(' Command returned no output') + return True def setup(self): # Initialize LXD @@ -570,12 +581,12 @@ class LXDTest(object): logging.debug("Attempting to initialize LXD") # TODO: Need a method to see if LXD is already initialized if not self.run_command('lxd init --auto'): - logging.error('Error encounterd while initializing LXD') + logging.debug('Error encounterd while initializing LXD') result = False # Retrieve and insert LXD images - logging.debug("Downloading template.") if self.template_url is not None: + logging.debug("Downloading template.") targetfile = urlparse(self.template_url).path.split('/')[-1] filename = os.path.join('/tmp', targetfile) if not os.path.isfile(filename): @@ -592,8 +603,8 @@ class LXDTest(object): "Skipping Download.".format(filename)) self.template_tarball = filename - logging.debug("Downloading rootfs.") if self.rootfs_url is not None: + logging.debug("Downloading rootfs.") targetfile = urlparse(self.rootfs_url).path.split('/')[-1] filename = os.path.join('/tmp', targetfile) if not os.path.isfile(filename): @@ -610,15 +621,24 @@ class LXDTest(object): self.rootfs_tarball = filename # Insert images - # TODO: check to see if ubuntu already exists - logging.debug("Importing images into LXD") - cmd = 'lxc image import {} rootfs {} --alias {}'.format( - self.template_tarball, self.rootfs_tarball, - self.image_alias) - if not self.run_command(cmd): - logging.error('Error encountered while attempting to ' - 'import images into LXD') - result = False + if result is True: + logging.debug("Importing images into LXD") + cmd = 'lxc image import {} rootfs {} --alias {}'.format( + self.template_tarball, self.rootfs_tarball, + self.image_alias) + if not self.run_command(cmd): + logging.error('Error encountered while attempting to ' + 'import images into LXD') + result = False + else: + logging.debug("No local image available, attempting to " + "import from default remote.") + cmd = 'lxc image copy {}{} local: --alias {}'.format( + self.default_remote, self.os_version, self.image_alias) + if not self.run_command(cmd): + loggging.error('Error encountered while attempting to ' + 'import images from default remote.') + result = False return result @@ -626,16 +646,21 @@ class LXDTest(object): """ Downloads LXD files for same release as host machine """ + # TODO: Clean this up to use a non-internet simplestream on MAAS server logging.debug("Attempting download of {} from {}".format(filename, url)) try: resp = urllib.request.urlretrieve(url, filename) except (IOError, - Error, + OSError, urllib.error.HTTPError, urllib.error.URLError) as exception: logging.error("Failed download of image from %s: %s", - image_url, exception) + url, exception) + return False + except ValueError as verr: + logging.error("Invalid URL %s" % url) + logging.error("%s" % verr) return False if not os.path.isfile(filename): @@ -665,10 +690,18 @@ class LXDTest(object): if not self.run_command('lxc launch {} {}'.format(self.image_alias, self.name)): return False + + logging.debug("Container listing:") + cmd = ("lxc list") + if not self.run_command(cmd): + return False + + logging.debug("Testing container") cmd = ("lxc exec {} dd if=/dev/urandom of=testdata.txt " "bs=1024 count=1000".format(self.name)) if not self.run_command(cmd): return False + return True @@ -764,12 +797,12 @@ def main(): # silence normal output from requests module logging.getLogger("requests").setLevel(logging.WARNING) - # to check if not len(sys.argv) > 1 - if len(vars(args)) == 0: + # Verify args + try: + args.func(args) + except AttributeError: parser.print_help() return False - args.func(args) - if __name__ == "__main__": main() -- cgit v1.2.3 From f832021568e9a6205baa6234a7dd7968ebfaadf5 Mon Sep 17 00:00:00 2001 From: Jeff Lane Date: Tue, 28 Mar 2017 15:01:50 -0400 Subject: PEP8 cleanup --- bin/virtualization | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bin/virtualization b/bin/virtualization index db70849..6091fe8 100755 --- a/bin/virtualization +++ b/bin/virtualization @@ -690,7 +690,7 @@ class LXDTest(object): if not self.run_command('lxc launch {} {}'.format(self.image_alias, self.name)): return False - + logging.debug("Container listing:") cmd = ("lxc list") if not self.run_command(cmd): @@ -701,7 +701,6 @@ class LXDTest(object): "bs=1024 count=1000".format(self.name)) if not self.run_command(cmd): return False - return True -- cgit v1.2.3