summaryrefslogtreecommitdiff
diff options
authorUbuntu <ubuntu@cert-jenkins-slave-1-201406-15260.maas>2022-05-17 22:00:49 +0000
committerUbuntu <ubuntu@cert-jenkins-slave-1-201406-15260.maas>2022-05-17 22:00:49 +0000
commit92397e7e41c752b4c2332dbd5c4d8308812a6b7b (patch)
treeba3c473e1eb3f6e3896e1cfaaa9c1ec2778fd696
parent6f10dd7b0a530c084c526c081cf34fc77ff69ef9 (diff)
parentfaab708e7c854365f88754c38be1e8cb99e6119f (diff)
Merge #420282 from ~mreed8855/plainbox-provider-checkbox:lxd-vm-virtualization_2
Adding a test to start and verify virtual machines using lxd. This is replacing the older MP https://code.launchpad.net/~mreed8855/plainbox-provider-checkbox/+git/plainbox-provider-checkbox/+merge/416851 This is related to the following MP: https://code.launchpad.net/~mreed8855/plainbox-provider-certification-server/+git/plainbox-provider-certification-server/+merge/420291
-rwxr-xr-xbin/virtualization.py214
-rw-r--r--units/virtualization/jobs.pxu14
-rw-r--r--units/virtualization/test-plan.pxu4
3 files changed, 230 insertions, 2 deletions
diff --git a/bin/virtualization.py b/bin/virtualization.py
index a3794de..75144e1 100755
--- a/bin/virtualization.py
+++ b/bin/virtualization.py
@@ -865,6 +865,211 @@ class LXDTest(object):
return True
+class LXDTest_vm(object):
+
+ def __init__(self, template=None, image=None):
+ self.image_url = image
+ self.template_url = template
+ self.image_tarball = None
+ self.template_tarball = None
+ self.name = 'testbed'
+ self.image_alias = uuid4().hex
+ self.default_remote = "ubuntu:"
+ self.os_version = get_release_to_test()
+
+ 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
+ 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
+ result = True
+ 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.debug('Error encounterd while initializing LXD')
+ result = False
+
+ # Retrieve and insert LXD images
+ 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):
+ 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
+
+ if self.image_url is not None:
+ logging.debug("Downloading image.")
+ targetfile = urlparse(self.image_url).path.split('/')[-1]
+ filename = os.path.join('/tmp', targetfile)
+ if not os.path.isfile(filename):
+ self.image_tarball = self.download_images(self.image_url,
+ filename)
+ if not self.image_tarball:
+ logging.error("Unable to download {} from{}".format(
+ self.image_tarball, self.image_url))
+ logging.error("Aborting")
+ result = False
+ else:
+ logging.debug("Template file {} already exists. "
+ "Skipping Download.".format(filename))
+ self.image_tarball = filename
+
+ # Insert images
+ if self.template_url is not None and self.image_url is not None:
+ logging.debug("Importing images into LXD")
+ cmd = 'lxc image import {} {} --alias {}'.format(
+ self.template_tarball, self.image_tarball,
+ self.image_alias)
+ result = self.run_command(cmd)
+ if not result:
+ 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
+ """
+ # TODO: Clean this up to use a non-internet simplestream on MAAS server
+ logging.debug("Attempting download of {} from {}".format(filename,
+ url))
+ try:
+ urllib.request.urlretrieve(url, filename)
+ except (IOError,
+ OSError,
+ urllib.error.HTTPError,
+ urllib.error.URLError) as exception:
+ logging.error("Failed download of image from %s: %s",
+ 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):
+ logging.warn("Can not find {}".format(filename))
+ return False
+
+ return filename
+
+ def cleanup(self):
+ """
+ Clean up test files an Virtual Machines created
+ """
+ logging.debug('Cleaning up images and VMs created during test')
+ self.run_command('lxc image delete {}'.format(self.image_alias))
+ self.run_command('lxc delete --force {}'.format(self.name))
+
+ def start_vm(self):
+ """
+ Creates an lxd virtutal machine and performs the test
+ """
+ wait_interval = 5
+ test_interval = 300
+
+ result = self.setup()
+ if not result:
+ logging.error("One or more setup stages failed.")
+ return False
+
+ # Create Virtual Machine
+ logging.debug("Launching Virtual Machine")
+ if not self.image_url and not self.template_url:
+ logging.debug("No local image available, attempting to "
+ "import from default remote.")
+ cmd = ('lxc init {}{} {} --vm '.format(
+ self.default_remote, self.os_version, self.name))
+ else:
+ cmd = ('lxc init {} {} --vm'.format(self.image_alias, self.name))
+
+ if not self.run_command(cmd):
+ return False
+
+ logging.debug("Start VM:")
+ cmd = ("lxc start {} ".format(self.name))
+ if not self.run_command(cmd):
+ return False
+
+ logging.debug("Virtual Machine listing:")
+ cmd = ("lxc list")
+ if not self.run_command(cmd):
+ return False
+
+ logging.debug("Wait for vm to boot")
+ check_vm = 0
+ while check_vm < test_interval:
+ time.sleep(wait_interval)
+ cmd = ("lxc exec {} -- lsb_release -a".format(self.name))
+ if self.run_command(cmd):
+ print("Vm started and booted succefully")
+ return True
+ else:
+ logging.debug("Re-verify VM booted")
+ check_vm = check_vm + wait_interval
+
+ logging.debug("testing vm failed")
+ if check_vm == test_interval:
+ return False
+
+
+def test_lxd_vm(args):
+ logging.debug("Executing LXD VM Test")
+
+ template = None
+ image = None
+
+ # First in priority are environment variables.
+ if 'LXD_TEMPLATE' in os.environ:
+ template = os.environ['LXD_TEMPLATE']
+ if 'KVM_IMAGE' in os.environ:
+ image = os.environ['KVM_IMAGE']
+
+ # Finally, highest-priority are command line arguments.
+ if args.template:
+ template = args.template
+ if args.image:
+ image = args.image
+
+ lxd_test = LXDTest_vm(template, image)
+
+ result = lxd_test.start_vm()
+ lxd_test.cleanup()
+ if result:
+ print("PASS: Virtual Machine was succssfully started and checked")
+ sys.exit(0)
+ else:
+ print("FAIL: Virtual Machine was not started and checked")
+ sys.exit(1)
+
+
def test_uvtkvm(args):
logging.debug("Executing UVT KVM Test")
# if args.image is not set and UVT_IMAGE_OR_SOURCE does not exist, a key
@@ -965,6 +1170,8 @@ def main():
'uvt', help=("Run uvt kvm virtualization test"))
lxd_test_parser = subparsers.add_parser(
'lxd', help=("Run the LXD validation test"))
+ lxd_test_vm_parser = subparsers.add_parser(
+ 'lxdvm', help=("Run the LXD VM validation test"))
parser.add_argument('--debug', dest='log_level',
action="store_const", const=logging.DEBUG,
default=logging.INFO)
@@ -990,6 +1197,13 @@ def main():
'--rootfs', type=str, default=None)
lxd_test_parser.set_defaults(func=test_lxd)
+ # Sub test options
+ lxd_test_vm_parser.add_argument(
+ '--template', type=str, default=None)
+ lxd_test_vm_parser.add_argument(
+ '--image', type=str, default=None)
+ lxd_test_vm_parser.set_defaults(func=test_lxd_vm)
+
args = parser.parse_args()
try:
diff --git a/units/virtualization/jobs.pxu b/units/virtualization/jobs.pxu
index 2b903c7..54fb496 100644
--- a/units/virtualization/jobs.pxu
+++ b/units/virtualization/jobs.pxu
@@ -19,6 +19,20 @@ _summary:
plugin: shell
category_id: com.canonical.plainbox::virtualization
+id: virtualization/verify_lxd_vm
+environ: LXD_TEMPLATE KVM_IMAGE
+estimated_duration: 60.0
+requires:
+ executable.name == 'lxc'
+ package.name == 'lxd' or snap.name == 'lxd'
+command: virtualization.py --debug lxdvm
+_description:
+ Verifies that an LXD Virtual Machine can be created and launched
+_summary:
+ Verify LXD Virtual Machine launches
+
+plugin: shell
+category_id: com.canonical.plainbox::virtualization
id: virtualization/verify_lxd
environ: LXD_TEMPLATE LXD_ROOTFS
estimated_duration: 30.0
diff --git a/units/virtualization/test-plan.pxu b/units/virtualization/test-plan.pxu
index 16f4c73..aae210f 100644
--- a/units/virtualization/test-plan.pxu
+++ b/units/virtualization/test-plan.pxu
@@ -15,5 +15,5 @@ id: virtualization-automated
unit: test plan
_name: Automated virtualization tests
include:
- virtualization/kvm_check_vm
- virtualization/verify_lxd \ No newline at end of file
+ virtualization/verify_lxd
+ virtualization/verify_lxd_vm