Example #1
0
  def boot(self, timeout = None, multiboot = True, kernel_args = "booted with vmrunner"):

    # Check for sudo access, needed for tap network devices and the KVM module
    if os.getuid() is not 0:
        print color.FAIL("Call the script with sudo access")
        sys.exit(1)

    # Start the timeout thread
    if (timeout):
      self._timer = threading.Timer(timeout, self._on_timeout)
      self._timer.start()

    # Boot via hypervisor
    try:
      self._hyper.boot(multiboot, kernel_args + "/" + self._hyper.name())
    except Exception as err:
      print color.WARNING("Exception raised while booting ")
      if (timeout): self._timer.cancel()
      raise err

    # Start analyzing output
    while self._hyper.poll() == None and not self._exit_status:
      line = self._hyper.readline()
      print color.SUBPROC("<VM> "+line.rstrip())
      # Look for event-triggers
      for pattern, func in self._on_output.iteritems():
        if re.search(pattern, line):
          try:
            res = func()
          except Exception as err:
            print color.WARNING("Exception raised in event callback: ")
            print_exception()
            res = False
            self.stop().wait()

          #NOTE: It can be 'None' without problem
          if res == False:
            self._exit_status = exit_codes["OUTSIDE_FAIL"]
            self.exit(self._exit_status, color.FAIL(nametag + " VM-external test failed"))

    # Now we either have an exit status from timer thread, or an exit status
    # from the subprocess, or the VM was powered off by the external test.
    # If the process didn't exit we need to stop it.
    if (self.poll() == None):
      self.stop()

    self.wait()

    if self._exit_status:
      print color.WARNING(nametag + "Found non-zero exit status but process didn't end. ")
      print color.FAIL(nametag + "Tests failed or program error")
      print color.INFO(nametag),"Done running VM. Exit status: ", self._exit_status
      sys.exit(self._exit_status)
    else:
      print color.SUCCESS(nametag + " VM exited with 0 exit status.")
      print color.INFO(nametag), "Subprocess finished. Exiting with ", self._hyper.poll()
      sys.exit(self._hyper.poll())

    raise Exception("Unexpected termination")
Example #2
0
def handler(signum, frame):
    print color.WARNING("Process interrupted - stopping vms")
    for vm in vms:
        try:
            vm.exit(exit_codes["ABORT"], "Process terminated by user")
        except Exception as e:
            print color.WARNING("Forced shutdown caused exception: "), e
            raise e
Example #3
0
def integration_tests():
    """
    Loops over all valid tests as defined by ./validate_all.py. Runs them one by one and gives an update of the statuses at the end.
    """
    global test_count
    valid = valid_tests()
    if not valid:
      print pretty.WARNING("Integration tests skipped")
      return 0

    test_count += len(valid)
    print pretty.HEADER("Starting " + str(len(valid)) + " integration test(s)")
    processes = []

    fail_count = 0
    for path in valid:
        processes.append(Test(path, clean = args.clean).start())

    # Collect test results
    print pretty.HEADER("Collecting integration test results")

    for p in processes:
      fail_count += 1 if p.wait_status() else 0

    # Exit early if any tests failed
    if fail_count and args.fail:
      print pretty.FAIL(str(fail_count) + "integration tests failed")
      sys.exit(fail_count)

    return fail_count
Example #4
0
def load_configs(config_path="."):
    global vms

    # Clear out the default unconfigured vm
    if (not vms[0]._config):
        vms = []

    print color.HEADER("IncludeOS vmrunner loading VM configs")

    schema_path = package_path + "/vm.schema.json"

    print INFO, "Validating JSON according to schema ", schema_path

    validate_vm.load_schema(schema_path)
    validate_vm.load_configs(config_path)

    if validate_vm.valid_vms:
        print INFO, "Loaded VM specification(s) from JSON"
        for spec in validate_vm.valid_vms:
            print INFO, "Found VM spec: "
            print color.DATA(spec.__str__())
            vms.append(vm(spec))

    else:
        print color.WARNING(
            nametag), "No VM specification JSON found, trying default config"
        vms.append(vm(default_config))

    return vms
Example #5
0
    def start_process(self, cmdlist):

        if cmdlist[0] == "sudo":  # and have_sudo():
            print color.WARNING("Running with sudo")
            self._sudo = True

        # Start a subprocess
        self._proc = subprocess.Popen(cmdlist,
                                      stdout=subprocess.PIPE,
                                      stderr=subprocess.PIPE,
                                      stdin=subprocess.PIPE)

        return self._proc
Example #6
0
def unit_tests():
  """Perform unit tests"""
  global test_count
  test_count += 1
  if ("unit" in args.skip):
    print pretty.WARNING("Unit tests skipped")
    return 0
  print pretty.HEADER("Building and running unit tests")
  build_status = Test(".", name="Unit test build", command=["make"], clean = args.clean).start().wait_status()
  unit_status = Test(".", name="Unit tests", command = ["./test.lest"]).start().wait_status()

  if (build_status or unit_status) and args.fail:
    print pretty.FAIL("Unit tests failed")
    sys.exit(max(build_status, unit_status))

  return max(build_status, unit_status)
Example #7
0
    def trigger_event(self, line):
        # Find any callback triggered by this line
        for pattern, func in self._on_output.iteritems():
            if re.search(pattern, line):
                try:
                    # Call it
                    res = func(line)
                except Exception as err:
                    print color.WARNING("Exception raised in event callback: ")
                    print_exception()
                    res = False
                    self.stop()

                # NOTE: Result can be 'None' without problem
                if res == False:
                    self._exit_status = exit_codes["CALLBACK_FAILED"]
                    self.exit(self._exit_status, " Event-triggered test failed")
def valid_tests(verb=False):
    tests = []

    dirs = os.walk('.').next()[1]
    for directory in dirs:
        subdirs = os.walk(directory).next()[1]
        if "integration" in subdirs:
            subdirs = os.walk(directory + "/integration").next()[1]
            if subdirs:
                for d in subdirs:
                    path = directory + "/integration/" + d
                    if validate_test.validate_path(path, verb):
                        tests.append(path)
                    else:
                        print color.WARNING("Validator: " + path +
                                            " failed validation")

    return tests
Example #9
0
def examples_working():
  global test_count
  if ("examples" in args.skip):
    print pretty.WARNING("Examples test skipped")
    return 0

  examples_dir = '../examples'
  dirs = os.walk(examples_dir).next()[1]
  print pretty.HEADER("Building " + str(len(dirs)) + " examples")
  test_count += len(dirs)
  fail_count = 0
  for directory in dirs:
    example = examples_dir + "/" + directory
    print "Building Example ", example
    build = Test(example, command = ["make"], name = directory + " build").start().wait_status()
    run = 0 #TODO: Make a 'test' folder for each example, containing test.py, vm.json etc.
    fail_count += 1 if build or run else 0
  return fail_count
Example #10
0
def stress_test():
  """Perform stresstest"""
  global test_count
  test_count += 1
  if ("stress" in args.skip):
    print pretty.WARNING("Stress test skipped")
    return 0

  if (not validate_test.validate_path("stress")):
    raise Exception("Stress test failed validation")

  print pretty.HEADER("Starting stress test")
  stress = Test("stress", clean = args.clean).start()

  if (stress and args.fail):
    print pretty.FAIL("Stress test failed")
    sys.exit(stress)

  return 1 if stress.wait_status() else 0
Example #11
0
def misc_working():
    global test_count
    if ("misc" in args.skip):
        print pretty.WARNING("Misc test skipped")
        return 0

    misc_dir = 'misc'
    dirs = os.walk(misc_dir).next()[1]
    dirs.sort()
    print pretty.HEADER("Building " + str(len(dirs)) + " misc")
    test_count += len(dirs)
    fail_count = 0
    for directory in dirs:
        misc = misc_dir + "/" + directory
        print "Building misc ", misc
        build = Test(misc, command=['./test.sh'],
                     name=directory).start().wait_status()
        run = 0  #TODO: Make a 'test' folder for each miscellanous test, containing test.py, vm.json etc.
        fail_count += 1 if build or run else 0
    return fail_count
Example #12
0
import re
import linecache
import traceback
import validate_vm
import signal
import psutil
from shutil import copyfile

from prettify import color

INCLUDEOS_HOME = None

if "INCLUDEOS_PREFIX" not in os.environ:
    def_home = "/usr/local"
    print color.WARNING(
        "WARNING:"
    ), "Environment variable INCLUDEOS_PREFIX is not set. Trying default", def_home
    if not os.path.isdir(def_home):
        raise Exception("Couldn't find INCLUDEOS_PREFIX")
    INCLUDEOS_HOME = def_home
else:
    INCLUDEOS_HOME = os.environ['INCLUDEOS_PREFIX']

package_path = os.path.dirname(os.path.realpath(__file__))

default_config = INCLUDEOS_HOME + "/includeos/vmrunner/vm.default.json"

default_json = "./vm.json"

chainloader = INCLUDEOS_HOME + "/includeos/chainloader"
Example #13
0
    def boot(self,
             timeout=60,
             multiboot=True,
             kernel_args="booted with vmrunner",
             image_name=None):

        # This might be a reboot
        self._exit_status = None
        self._timeout_after = timeout

        # Start the timeout thread
        if (timeout):
            info("setting timeout to", timeout, "seconds")
            self._timer = threading.Timer(timeout, self._on_timeout)
            self._timer.start()

        # Boot via hypervisor
        try:
            self._hyper.boot(multiboot, kernel_args, image_name)
        except Exception as err:
            print color.WARNING("Exception raised while booting: ")
            print_exception()
            if (timeout): self._timer.cancel()
            self.exit(exit_codes["BOOT_FAILED"], str(err))

        # Start analyzing output
        while self._hyper.poll() == None and not self._exit_status:

            try:
                line = self._hyper.readline()
            except Exception as e:
                print color.WARNING(
                    "Exception thrown while waiting for vm output")
                break

            if line:
                # Special case for end-of-transmission
                if line == EOT:
                    if not self._exit_status:
                        self._exit_status = exit_codes["VM_EOT"]
                    break
                if line.startswith(
                        "     [ Kernel ] service exited with status"):
                    self._exit_status = int(line.split(" ")[-1].rstrip())
                    self._exit_msg = "Service exited"
                    break
                else:
                    print color.VM(line.rstrip())

            else:
                pass
                # TODO: Add event-trigger for EOF?

            for pattern, func in self._on_output.iteritems():
                if re.search(pattern, line):
                    try:
                        res = func(line)
                    except Exception as err:
                        print color.WARNING(
                            "Exception raised in event callback: ")
                        print_exception()
                        res = False
                        self.stop()

                    # NOTE: It can be 'None' without problem
                    if res == False:
                        self._exit_status = exit_codes["CALLBACK_FAILED"]
                        self.exit(self._exit_status,
                                  " Event-triggered test failed")

        # If the VM process didn't exit by now we need to stop it.
        if (self.poll() == None):
            self.stop()

        # We might have an exit status, e.g. set by a callback noticing something wrong with VM output
        if self._exit_status:
            self.exit(self._exit_status, self._exit_msg)

        # Process might have ended prematurely
        elif self.poll():
            self.exit(self._hyper.poll(), self._hyper.get_error_messages())

        # If everything went well we can return
        return self
Example #14
0
def handler(signum, frame):
    print color.WARNING("Process interrupted")
    thread.interrupt_main()
    thread.exit()
Example #15
0
import time
import re
import linecache
import traceback
import validate_test
import signal

from prettify import color

INCLUDEOS_HOME = None

nametag = "<VMRunner>"

if "INCLUDEOS_HOME" not in os.environ:
    print color.WARNING(
        "WARNING:"
    ), "Environment varialble INCLUDEOS_HOME is not set. Trying default"
    def_home = os.environ["HOME"] + "/IncludeOS_install"
    if not os.path.isdir(def_home):
        raise Exception("Couldn't find INCLUDEOS_HOME")
    INCLUDEOS_HOME = def_home
else:
    INCLUDEOS_HOME = os.environ['INCLUDEOS_HOME']

# Exit codes used by this program
exit_codes = {
    "SUCCESS": 0,
    "PROGRAM_FAILURE": 1,
    "TIMEOUT": 66,
    "VM_FAIL": 67,
    "OUTSIDE_FAIL": 68
Example #16
0
    def boot(self,
             timeout=60,
             multiboot=True,
             debug=False,
             kernel_args="booted with vmrunner",
             image_name=None):
        info("VM boot, timeout: ", timeout, "multiboot: ", multiboot,
             "Kernel_args: ", kernel_args, "image_name: ", image_name)
        # This might be a reboot
        self._exit_status = None
        self._exit_complete = False
        self._timeout_after = timeout

        # Start the timeout thread
        if (timeout):
            info("setting timeout to", timeout, "seconds")
            self._timer = threading.Timer(timeout, self._on_timeout)
            self._timer.start()

        # Boot via hypervisor
        try:
            self._hyper.boot(multiboot, debug, kernel_args, image_name)
        except Exception as err:
            print color.WARNING("Exception raised while booting: ")
            print_exception()
            if (timeout): self._timer.cancel()
            self.exit(exit_codes["BOOT_FAILED"], str(err))

        # Start analyzing output
        while self._exit_status == None and self.poll() == None:

            try:
                line = self._hyper.readline()
            except Exception as e:
                print color.WARNING(
                    "Exception thrown while waiting for vm output")
                break

            if line and self.find_exit_status(line) == None:
                print color.VM(line.rstrip())
                self.trigger_event(line)

            # Empty line - should only happen if process exited
            else:
                pass

        # VM Done
        info("Event loop done. Exit status:", self._exit_status, "poll:",
             self.poll())

        # If the VM process didn't exit by now we need to stop it.
        if (self.poll() == None):
            self.stop()

        # Process may have ended without EOT / exit message being read yet
        # possibly normal vm shutdown
        if self.poll() != None:

            info("No poll - getting final output")
            try:
                data, err = self._hyper.get_final_output()

                # Print stderr if exit status wasnt 0
                if err and self.poll() != 0:
                    print color.WARNING("Stderr: \n" + err)

                # Parse the last output from vm
                lines = data.split("\n")
                for line in lines:
                    print color.VM(line)
                    self.find_exit_status(line)
                    # Note: keep going. Might find panic after service exit

            except Exception as e:
                pass

        # We should now have an exit status, either from a callback or VM EOT / exit msg.
        if self._exit_status != None:
            info("VM has exit status. Exiting.")
            self.exit(self._exit_status, self._exit_msg)
        else:
            self.exit(self._hyper.poll(), "process exited")

        # If everything went well we can return
        return self
Example #17
0
    def boot(self, multiboot, debug=False, kernel_args="", image_name=None):
        self._stopped = False

        info("Booting with multiboot:", multiboot, "kernel_args: ",
             kernel_args, "image_name:", image_name)

        # Resolve if kvm is present
        self._kvm_present = self.kvm_present()

        # Use provided image name if set, otherwise try to find it in json-config
        if not image_name:
            if not "image" in self._config:
                raise Exception(
                    "No image name provided, neither as param or in config file"
                )
            image_name = self._config["image"]

        self._image_name = image_name

        disk_args = []

        debug_args = []
        if debug:
            debug_args = ["-s"]

        # multiboot - e.g. boot with '-kernel' and no bootloader
        if multiboot:

            # TODO: Remove .img-extension from vm.json in tests to avoid this hack
            if (image_name.endswith(".img")):
                image_name = image_name.split(".")[0]

            if not kernel_args: kernel_args = "\"\""

            info("File magic: ", file_type(image_name))

            if is_Elf64(image_name):
                info("Found 64-bit ELF, need chainloader")
                print "Looking for chainloader: "
                print "Found", chainloader, "Type: ", file_type(chainloader)
                if not is_Elf32(chainloader):
                    print color.WARNING(
                        "Chainloader doesn't seem to be a 32-bit ELF executable"
                    )
                kernel_args = [
                    "-kernel", chainloader, "-append", kernel_args, "-initrd",
                    image_name + " " + kernel_args
                ]
            elif is_Elf32(image_name):
                info("Found 32-bit elf, trying direct boot")
                kernel_args = ["-kernel", image_name, "-append", kernel_args]
            else:
                print color.WARNING(
                    "Provided kernel is neither 64-bit or 32-bit ELF executable."
                )
                kernel_args = ["-kernel", image_name, "-append", kernel_args]

            info("Booting", image_name,
                 "directly without bootloader (multiboot / -kernel args)")
        else:
            kernel_args = []
            image_in_config = False

            # If the provided image name is also defined in vm.json, use vm.json
            if "drives" in self._config:
                for disk in self._config["drives"]:
                    if disk["file"] == image_name:
                        image_in_config = True
                if not image_in_config:
                    info("Provided image", image_name,
                         "not found in config. Appending.")
                    self._config["drives"].insert(
                        0, {
                            "file": image_name,
                            "type": "ide",
                            "format": "raw",
                            "media": "disk"
                        })
            else:
                self._config["drives"] = [{
                    "file": image_name,
                    "type": "ide",
                    "format": "raw",
                    "media": "disk"
                }]

            info("Booting", image_name, "with a bootable disk image")

        if "drives" in self._config:
            for disk in self._config["drives"]:
                disk_args += self.drive_arg(disk["file"], disk["type"],
                                            disk["format"], disk["media"])

        mod_args = []
        if "modules" in self._config:
            mod_args += self.mod_args(self._config["modules"])

        if "bios" in self._config:
            kernel_args.extend(["-bios", self._config["bios"]])

        if "uuid" in self._config:
            kernel_args.extend(["--uuid", str(self._config["uuid"])])

        if "smp" in self._config:
            kernel_args.extend(["-smp", str(self._config["smp"])])

        if "cpu" in self._config:
            cpu = self._config["cpu"]
            cpu_str = cpu["model"]
            if "features" in cpu:
                cpu_str += ",+" + ",+".join(cpu["features"])
            kernel_args.extend(["-cpu", cpu_str])

        net_args = []
        i = 0
        if "net" in self._config:
            for net in self._config["net"]:
                mac = net["mac"] if "mac" in net else None
                bridge = net["bridge"] if "bridge" in net else None
                scripts = net["scripts"] if "scripts" in net else None
                net_args += self.net_arg(net["backend"], net["device"],
                                         "net" + str(i), mac, bridge, scripts)
                i += 1

        mem_arg = []
        if "mem" in self._config:
            mem_arg = ["-m", str(self._config["mem"])]

        vga_arg = ["-nographic"]
        if "vga" in self._config:
            vga_arg = ["-vga", str(self._config["vga"])]

        trace_arg = []
        if "trace" in self._config:
            trace_arg = ["-trace", "events=" + str(self._config["trace"])]

        pci_arg = []
        if "vfio" in self._config:
            pci_arg = ["-device", "vfio-pci,host=" + self._config["vfio"]]

        # custom qemu binary/location
        qemu_binary = "qemu-system-x86_64"
        if "qemu" in self._config:
            qemu_binary = self._config["qemu"]

        # TODO: sudo is only required for tap networking and kvm. Check for those.
        command = ["sudo", qemu_binary]
        if self._kvm_present: command.extend(["--enable-kvm"])

        command += kernel_args
        command += disk_args + debug_args + net_args + mem_arg + mod_args
        command += vga_arg + trace_arg + pci_arg

        #command_str = " ".join(command)
        #command_str.encode('ascii','ignore')
        #command = command_str.split(" ")

        info("Command:", " ".join(command))

        try:
            self.start_process(command)
            self.info("Started process PID ", self._proc.pid)
        except Exception as e:
            print self.INFO, "Starting subprocess threw exception:", e
            raise e
Example #18
0
def print_skipped(name, reason):
  print pretty.WARNING("* Skipping " + name)
  print "  Reason: {0:40}".format(reason)
Example #19
0
def print_skipped(tests):
    for test in tests:
        if test.skip_:
            print pretty.WARNING("* Skipping " + test.name_)
            print "  Reason: {0:40}".format(test.skip_reason_)
Example #20
0
import re
import linecache
import traceback
import validate_vm
import signal
import psutil

from prettify import color

INCLUDEOS_HOME = None

nametag = "<VMRunner>"

if "INCLUDEOS_PREFIX" not in os.environ:
    def_home = "/usr/local"
    print color.WARNING("WARNING:"), "Environment varialble INCLUDEOS_PREFIX is not set. Trying default", def_home
    if not os.path.isdir(def_home): raise Exception("Couldn't find INCLUDEOS_PREFIX")
    INCLUDEOS_HOME= def_home
else:
    INCLUDEOS_HOME = os.environ['INCLUDEOS_PREFIX']

package_path = os.path.dirname(os.path.realpath(__file__))

# The end-of-transmission character
EOT = chr(4)

# Exit codes used by this program
exit_codes = {"SUCCESS" : 0,
              "PROGRAM_FAILURE" : 1,
              "TIMEOUT" : 66,
              "VM_PANIC" : 67,