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 kvm_present(self):
        command = "egrep -m 1 '^flags.*(vmx|svm)' /proc/cpuinfo"
        try:
            subprocess.check_output(command, shell=True)
            print color.INFO("<qemu>"), "KVM ON"
            return True

        except Exception as err:
            print color.INFO("<qemu>"), "KVM OFF"
            return False
Example #3
0
    def timeout(self):
        if VERB: print color.INFO("<timeout>"), "VM timed out"

        # Note: we have to stop the VM since the main thread is blocking on vm.readline
        self._exit_status = exit_codes["TIMEOUT"]
        self._exit_msg = "vmrunner timed out after " + str(self._timeout_after) + " seconds"
        self._hyper.stop().wait()
Example #4
0
 def make(self, params = []):
   print color.INFO(nametag), "Building test service with 'make' (params=" + str(params) + ")"
   make = ["make"]
   make.extend(params)
   res = subprocess.check_output(make)
   print color.SUBPROC(res)
   return self
Example #5
0
    def cmake(self, args = []):
        print color.INFO(nametag), "Building with cmake (%s)" % args
        # install dir:
        INSTDIR = os.getcwd()

        # create build directory
        try:
            os.makedirs("build")
        except OSError as err:
            if err.errno!=17: # Errno 17: File exists
                self.exit(exit_codes["BUILD_FAIL"], "could not create build directory")

        # go into build directory
        # NOTE: The test gets run from here
        os.chdir("build")

        # build with prefix = original path
        cmake = ["cmake", "..", "-DCMAKE_INSTALL_PREFIX:PATH=" + INSTDIR]
        cmake.extend(args)

        try:
            cmd(cmake)

            # if everything went well, build with make and install
            return self.make()
        except Exception as e:
            print "Excetption while building: ", e
            self.exit(exit_codes["BUILD_FAIL"], "building with cmake failed")
Example #6
0
 def stop(self):
   if hasattr(self, "_proc") and self._proc.poll() == None :
     print color.INFO(self._nametag),"Stopping", self._config["image"], "PID",self._proc.pid
     # Kill
     subprocess.check_call(["kill", "-SIGTERM", str(self._proc.pid)])
     # Wait for termination (avoids the need to reset the terminal)
     self._proc.wait()
   return self
Example #7
0
  def wait_status(self):

    self.print_start()

    # Start and wait for the process
    self.output_ = self.proc_.communicate()

    if self.proc_.returncode == 0:
      print pretty.PASS_INLINE()
    else:
      print pretty.FAIL_INLINE()
      print pretty.INFO("Process stdout")
      print pretty.DATA(self.output_[0])
      print pretty.INFO("Process stderr")
      print pretty.DATA(self.output_[1])

    return self.proc_.returncode
Example #8
0
    def exit(self, status, msg):
        self._exit_status = status
        self.stop()
        print color.INFO(nametag),"Exit called with status", self._exit_status, "(",get_exit_code_name(self._exit_status),")"
        print color.INFO(nametag),"Calling on_exit"
        # Change back to test source
        os.chdir(self._root)
        self._on_exit()
        if status == 0:
            # Print success message and return to caller
            print color.SUCCESS(msg)
            print color.INFO(nametag),"Calling on_exit_success"
            return self._on_exit_success()

        # Print fail message and exit with appropriate code
        print color.EXIT_ERROR(get_exit_code_name(status), msg)
        sys.exit(status)
Example #9
0
    def __init__(self, config):
        super(qemu, self).__init__(config)
        self._proc = None
        self._stopped = False
        self._sudo = False
        self._image_name = self._config if "image" in self._config else self.name() + " vm"

        # Pretty printing
        self.info = Logger(color.INFO("<" + type(self).__name__ + ">"))
Example #10
0
    def __init__(self, config):
        super(qemu, self).__init__(config)
        self._proc = None
        self._stopped = False
        self._sudo = False

        # Pretty printing
        self._nametag = "<" + type(self).__name__ + ">"
        self.INFO = color.INFO(self._nametag)
Example #11
0
    def panic(self, panic_line):
        panic_reason = self._hyper.readline()
        print color.INFO(nametag), "VM signalled PANIC. Reading until EOT (", hex(ord(EOT)), ")"
        print color.VM(panic_reason),
        remaining_output = self._hyper.read_until_EOT()
        for line in remaining_output.split("\n"):
            print color.VM(line)

        self.exit(exit_codes["VM_PANIC"], panic_reason)
Example #12
0
    def boot(self, multiboot, kernel_args):
        self._nametag = "<" + type(self).__name__ + ">"
        print color.INFO(self._nametag), "booting", self._config["image"]

        # multiboot
        if multiboot:
            print color.INFO(
                self._nametag), "Booting with multiboot (-kernel args)"
            kernel_args = [
                "-kernel", self._config["image"].split(".")[0], "-append",
                kernel_args
            ]
        else:
            kernel_args = []

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

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

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

        command = ["qemu-system-x86_64"]
        if self.kvm_present(): command.append("--enable-kvm")

        command += kernel_args

        command += ["-nographic"] + disk_args + net_args + mem_arg

        print color.INFO(self._nametag), "command:"
        print color.DATA(command.__str__())

        self._proc = start_process(command)
Example #13
0
    def stop(self):
        # Check for sudo access, needed for qemu commands
        if os.getuid() is not 0:
            print color.FAIL("Call the script with sudo access")
            sys.exit(1)

        print color.INFO(nametag), "Stopping VM..."
        self._hyper.stop()
        if hasattr(self, "_timer") and self._timer:
            self._timer.cancel()
        return self
Example #14
0
def start_process(popen_param_list):
  # Start a subprocess
  proc = subprocess.Popen(popen_param_list,
                          stdout = subprocess.PIPE,
                          stderr = subprocess.PIPE,
                          stdin = subprocess.PIPE)

  # After half a second it should be started, otherwise throw
  time.sleep(0.5)
  if (proc.poll()):
    data, err = proc.communicate()
    raise Exception(color.C_FAILED+"Process exited. ERROR: " + err.__str__() + " " + data + color.C_ENDC);

  print color.INFO(nametag), "Started process PID ",proc.pid
  return proc
Example #15
0
  def __init__(self, path, clean = False, command = ['sudo', '-E', 'python', 'test.py'], name = None):

    self.command_ = command
    self.proc_ = None
    self.path_ = path
    self.output_ = None

    if (name == None):
      self.name_ = path
    else:
      self.name_ = name

    print pretty.INFO("Test"), "starting", self.name_

    if clean:
      subprocess.check_output(["make","clean"])
      print pretty.C_GRAY + "\t Cleaned, now start... ", pretty.C_ENDC
Example #16
0
def integration_tests(tests):
    """ Function that runs the tests that are passed to it.
    Filters out any invalid tests before running

    Arguments:
        tests: List containing test objects to be run

    Returns:
        integer: Number of tests that failed
    """

    # Only run the valid tests
    tests = [ x for x in tests if not x.skip_ and x.type_ == 'integration' ]

    # Print info before starting to run
    print pretty.HEADER("Starting " + str(len(tests)) + " integration test(s)")
    for test in tests:
        print pretty.INFO("Test"), "starting", test.name_

    processes = []
    fail_count = 0
    global test_count
    test_count += len(tests)

    # Start running tests in parallell
    for test in tests:
        processes.append(test.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 #17
0
 def make(self, params = []):
     print color.INFO(nametag), "Building with 'make' (params=" + str(params) + ")"
     make = ["make"]
     make.extend(params)
     cmd(make)
     return self
Example #18
0
        # 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


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

schema_path = package_path + "/vm.schema.json"
print color.INFO(nametag), "Validating JSON according to schema ",schema_path
validate_vm.load_schema(schema_path)
validate_vm.has_required_stuff(".")

default_spec = {"image" : "service.img"}

# Provide a list of VM's with validated specs
vms = []

if validate_vm.valid_vms:
    print color.INFO(nametag), "Loaded VM specification(s) from JSON"
    for spec in validate_vm.valid_vms:
        print color.INFO(nametag), "Found VM spec: "
        print color.DATA(spec.__str__())
        vms.append(vm(spec))
Example #19
0
 def clean(self):
     print color.INFO(nametag), "Cleaning cmake build folder"
     subprocess.call(["rm","-rf","build"])
Example #20
0
 def wait(self):
     print color.INFO(self._nametag), "Waiting for process to terminate"
     self._proc.wait()
Example #21
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):
            print color.INFO(nametag),"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 ")
            if (timeout): self._timer.cancel()
            self.exit(exit_codes["CALLBACK_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 #22
0
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"

# Provide a list of VM's with validated specs
# (One default vm added at the end)
vms = []

panic_signature = "\\x15\\x07\\t\*\*\*\* PANIC \*\*\*\*"
nametag = "<VMRunner>"
INFO = color.INFO(nametag)
VERB = bool(os.environ["VERBOSE"]) if "VERBOSE" in os.environ else False


class Logger:
    def __init__(self, tag):
        self.tag = tag
        if (VERB):
            self.info = self.info_verb
        else:
            self.info = self.info_silent

    def __call__(self, *args):
        self.info(args)

    def info_verb(self, args):
Example #23
0
        if hasattr(self, "_timer") and self._timer:
            self._timer.cancel()
        return self

    def wait(self):
        if hasattr(self, "_timer") and self._timer:
            self._timer.join()
        self._hyper.wait()
        return self._exit_status

    def poll(self):
        return self._hyper.poll()


print color.HEADER("IncludeOS vmrunner initializing tests")
print color.INFO(nametag), "Validating test service"
validate_test.load_schema(
    os.environ.get(
        "INCLUDEOS_SRC",
        os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(
            __file__))).split('/test')[0]) + "/test/vm.schema.json")
validate_test.has_required_stuff(".")

default_spec = {"image": "test.img"}

# Provide a list of VM's with validated specs
vms = []

if validate_test.valid_vms:
    print
    print color.INFO(nametag), "Loaded VM specification(s) from JSON"