From f0e2c835499b419f0171a1ae281c627e280a1aee Mon Sep 17 00:00:00 2001 From: Alfred Bratterud Date: Wed, 25 Jan 2017 23:09:46 +0100 Subject: [PATCH 1/5] boot: no cmake required for binaries, use verbose option, added json option, better defaults --- etc/boot | 75 +++++++++++++------- vmrunner/validate_vm.py | 63 +++++++++-------- vmrunner/vm.schema.json | 6 ++ vmrunner/vmrunner.py | 153 ++++++++++++++++++++++++++++------------ 4 files changed, 197 insertions(+), 100 deletions(-) diff --git a/etc/boot b/etc/boot index aa15728adc..19486f045f 100755 --- a/etc/boot +++ b/etc/boot @@ -18,6 +18,12 @@ if not os.path.isdir(INCLUDEOS_PREFIX + "/includeos"): print "Couldn't find IncludeOS installation. If you installed to a non-default location (e.g. not " + default_loc + ") please set the environment variable INCLUDEOS_PREFIX to point to this location." sys.exit(0) +# Location of vmrunner +sys.path.append(INCLUDEOS_PREFIX + "/includeos") + +from vmrunner.prettify import color + + # Argparse parser = argparse.ArgumentParser( description="IncludeOS vmrunner. Builds and runs an IncludeOS service") @@ -37,51 +43,68 @@ parser.add_argument("--create-bridge", dest="bridge", action="store_true", parser.add_argument("-g", "--grub", dest="grub", action="store_true", help="Create image with GRUB bootloader that will boot provided binary") -parser.add_argument('binary', action="store", type=str, - help="Filename of the IncludeOS service binary") +parser.add_argument("-j", "--config", dest="config", type = str, + help="Location of VM JSON config") + +parser.add_argument('vm_location', action="store", type = str, + help="Location of the IncludeOS service binary, image or source") parser.add_argument('vmargs', nargs='*', help="Arguments to pass on to the VM start / main") + args = parser.parse_args() -# Location of vmrunner -sys.path.append(INCLUDEOS_PREFIX + "/includeos") -from vmrunner.prettify import color +# Pretty printing from this command +nametag = "" +INFO = color.INFO(nametag) # Override VM output prepension color.VM_PREPEND = "" -# Pretty printing from this command -nametag = "" -INFO = color.INFO(nametag) +# in verbose mode we will set VERBOSE=1 for this environment +VERB = False +if (args.verbose): + os.environ["VERBOSE"] = "1" + VERB = True + print INFO, "VERBOSE mode set for environment" +# Avoid the verbose var to hang around next run +elif "VERBOSE" in os.environ: + del os.environ["VERBOSE"] + +# Note: importing vmrunner will make it start looking for VM's +# vmrunner also relies on the verbose env var to be set on initialization +from vmrunner import vmrunner + # We can boot either a binary without bootloader, or an image with bootloader allready attached has_bootloader = False -print INFO , "Args to pass to VM: ", args.vmargs +if VERB: print INFO , "Args to pass to VM: ", args.vmargs # path w/name of VM image to run -image_name = args.binary +image_name = args.vm_location # if the binary argument is a directory, go there immediately and # then initialize stuff ... -if (os.path.isdir(args.binary)): - image_name = os.path.abspath(args.binary) - print "Changing directory to: " + image_name - os.chdir(os.path.abspath(args.binary)) +if (os.path.isdir(args.vm_location)): + image_name = os.path.abspath(args.vm_location) + if VERB: print INFO, "Changing directory to " + image_name + os.chdir(os.path.abspath(args.vm_location)) -# in verbose mode we will just set VERBOSE=1 for this environment -if (args.verbose): - os.environ['VERBOSE'] = "1" -# Note: importing vmrunner will make it start looking for VM's -from vmrunner import vmrunner if len(vmrunner.vms) < 1: - print color.FAIL("No vm description files found - nothing to boot") + # This should never happen - there should always be a default + print color.FAIL("No vm object found in vmrunner - nothing to boot") exit(-1) -print color.INFO(nametag), len(vmrunner.vms), "VM initialized. Commencing build- and boot..." +if VERB: + print INFO, len(vmrunner.vms), "VM initialized. Commencing build- and boot..." + +config = None +if args.config: + config = os.path.abspath(args.config) + if VERB: print INFO, "Using config file", config -vm = vmrunner.vms[0] +vm = vmrunner.vm(config = config) # For multible JSON configs, find the one matching the provided image name for vm_ in vmrunner.vms: @@ -99,15 +122,15 @@ if (args.bridge): # If the binary name is a folder, such as ".", build the service if (os.path.isdir(image_name)): vm.cmake() - # also, set image name to + # also, set image name to image_name = open("binary.txt", 'r').read() # If the binary name has an extension (e.g. a '.'), assume it has a bootloader attached # NOTE: the idea is to support e.g. .vdi and virtualbox etc. in the future -elif ("." in args.binary): +elif ("." in args.vm_location): has_bootloader = True if (args.grub): - print INFO, "Creating GRUB image from ", args.binary + print INFO, "Creating GRUB image from ", args.vm_location subprocess.call(INCLUDEOS_PREFIX + "/includeos/scripts/grubify.sh " + image_name, shell=True) image_name = image_name + ".grub.img" has_bootloader = True @@ -116,6 +139,6 @@ if (args.grub): if (args.build): exit(0); if (not has_bootloader): - vm.boot(timeout = None, kernel_args=" ".join(args.vmargs), image_name = image_name) + vm.boot(timeout = None, multiboot = True, kernel_args = " ".join(args.vmargs), image_name = image_name) else: vm.boot(timeout = None, multiboot = False, kernel_args = None, image_name = image_name) diff --git a/vmrunner/validate_vm.py b/vmrunner/validate_vm.py index 5ea0f113c6..097e35a9f2 100755 --- a/vmrunner/validate_vm.py +++ b/vmrunner/validate_vm.py @@ -35,50 +35,53 @@ def set_defaults(validator, properties, instance, schema): validator = extend_with_default(Draft4Validator) package_path = os.path.dirname(os.path.realpath(__file__)) +default_schema = package_path + "/vm.schema.json" - -def load_schema(filename): +def load_schema(filename = default_schema): global vm_schema vm_schema = json.loads(open(filename).read()); + +#def load_from_json( + def validate_vm_spec(filename): + vm_spec = None - global valid_vms - vm_spec = None + # Load and parse as JSON + try: + vm_spec = json.loads(open(filename).read()) + except: + raise Exception("JSON load / parse Error for " + filename) - # Load and parse as JSON - try: - vm_spec = json.loads(open(filename).read()) - except: - raise Exception("JSON load / parse Error for " + filename) + if (not vm_schema): load_schema() - # Validate JSON according to schema - try: + # Validate JSON according to schema validator(vm_schema).validate(vm_spec) - except Exception as err: - raise Exception("JSON schema validation failed: " + err.message) - valid_vms.append(vm_spec) + return vm_spec, filename + +def load_config(path): + global valid_vms + global jsons -def has_required_stuff(path): + if (os.path.isfile(path)): + jsons = [path] - global jsons + if (os.path.isdir(path)): + jsons = glob.glob(path + "/*.json") + jsons.sort() - # Certain files are mandatory - required_files = [ "CMakeLists.txt"] - for file in required_files: - if not glob.glob(file): - raise Exception("missing " + file) + # JSON-files must conform to VM-schema + for json in jsons: + spec = validate_vm_spec(json) + try: + spec = validate_vm_spec(json) + valid_vms.append(spec) + except Exception as e: + pass + return valid_vms - # JSON-files must conform to VM-schema - jsons = glob.glob("*.json") - jsons.sort() - for json in jsons: - try: - validate_vm_spec(json) - except Exception as e: - pass def validate_path(path, verb = False): global verbose @@ -88,7 +91,7 @@ def validate_path(path, verb = False): load_schema(package_path + "/vm.schema.json") os.chdir(path) try: - has_required_stuff(path) + load_config(path) if verbose: print " \tPASS: ",os.getcwd() return True diff --git a/vmrunner/vm.schema.json b/vmrunner/vm.schema.json index 8471b8988e..f6f6ad3dfa 100644 --- a/vmrunner/vm.schema.json +++ b/vmrunner/vm.schema.json @@ -4,11 +4,17 @@ "type" : "object", "properties" : { + "description" : { + "description" : "A human-readable description of this config", + "type" : "string" + }, + "image" : { "description" : "A bootable virtual machine image", "type" : "string", "default" : "service.img" }, + "bios" : { "description" : "64k BIOS image", "type" : "string" diff --git a/vmrunner/vmrunner.py b/vmrunner/vmrunner.py index b9d3182b3e..7e049034ad 100644 --- a/vmrunner/vmrunner.py +++ b/vmrunner/vmrunner.py @@ -15,8 +15,6 @@ INCLUDEOS_HOME = None -nametag = "" - 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 @@ -27,6 +25,40 @@ package_path = os.path.dirname(os.path.realpath(__file__)) +default_config = {"description" : "Single virtio nic, otherwise hypervisor defaults", + "net" : [{"device" : "virtio", "backend" : "tap" }] } + + +nametag = "" +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): + print self.tag, + for arg in args: + print arg, + print + + def info_silent(self, args): + pass + +# Define verbose printing function "info", with multiple args +default_logger = Logger(INFO) +def info(*args): + default_logger.info(args) + + # The end-of-transmission character EOT = chr(4) @@ -119,9 +151,7 @@ def __init__(self, config): self._sudo = False # Pretty printing - self._nametag = "<" + type(self).__name__ + ">" - self.INFO = color.INFO(self._nametag) - + self.info = Logger(color.INFO("<" + type(self).__name__ + ">")) def name(self): return "Qemu" @@ -150,11 +180,11 @@ def kvm_present(self): command = "egrep -m 1 '^flags.*(vmx|svm)' /proc/cpuinfo" try: subprocess.check_output(command, shell = True) - print self.INFO, "KVM ON" + self.info("KVM ON") return True except Exception as err: - print self.INFO, "KVM OFF" + self.info("KVM OFF") return False # Start a process and preserve in- and output pipes @@ -172,7 +202,7 @@ def start_process(self, cmdlist): stdout = subprocess.PIPE, stderr = subprocess.PIPE, stdin = subprocess.PIPE) - print self.INFO, "Started process PID ",self._proc.pid + self.info("Started process PID ",self._proc.pid) return self._proc @@ -198,11 +228,11 @@ def boot(self, multiboot, kernel_args = "", image_name = None): kernel_args = ["-kernel", image_name, "-append", kernel_args] disk_args = [] - print self.INFO, "Booting", image_name, "directly without bootloader (multiboot / -kernel args)" + info ( "Booting", image_name, "directly without bootloader (multiboot / -kernel args)") else: kernel_args = [] disk_args = self.drive_arg(image_name, "ide") - print self.INFO, "Booting", image_name, "with a bootable disk image" + info ("Booting", image_name, "with a bootable disk image") if "bios" in self._config: kernel_args.extend(["-bios", self._config["bios"]]) @@ -235,8 +265,7 @@ def boot(self, multiboot, kernel_args = "", image_name = None): command += disk_args + net_args + mem_arg + vga_arg - print self.INFO, "command:" - print color.DATA(" ".join(command)) + info("Command:", " ".join(command)) try: self.start_process(command) @@ -258,17 +287,17 @@ def stop(self): if self._proc and self._proc.poll() == None : if not self._sudo: - print self.INFO,"Stopping child process (no sudo required)" + info ("Stopping child process (no sudo required)") self._proc.terminate() else: # Find and terminate all child processes, since parent is "sudo" parent = psutil.Process(self._proc.pid) children = parent.children() - print self.INFO, "Stopping", self._config["image"], "PID",self._proc.pid, "with", signal + info ("Stopping", self._config["image"], "PID",self._proc.pid, "with", signal) for child in children: - print self.INFO," + child process ", child.pid + info (" + child process ", child.pid) # The process might have gotten an exit status by now so check again to avoid negative exit if (not self._proc.poll()): @@ -312,18 +341,21 @@ def poll(self): # VM class class vm: - def __init__(self, config, hyper = qemu): + def __init__(self, config = None, hyper = qemu): + self._exit_status = 0 self._exit_msg = "" - self._config = config + self._config = load_single_config(config) self._on_success = lambda(line) : self.exit(exit_codes["SUCCESS"], nametag + " All tests passed") self._on_panic = self.panic self._on_timeout = self.timeout self._on_output = { "PANIC" : self._on_panic, "SUCCESS" : self._on_success } + + # Initialize hypervisor with config assert(issubclass(hyper, hypervisor)) - self._hyper = hyper(config) + self._hyper = hyper(self._config) self._timeout_after = None self._timer = None self._on_exit_success = lambda : None @@ -348,15 +380,15 @@ def poll(self): 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" + info("Exit called with status", self._exit_status, "(",get_exit_code_name(self._exit_status),")") + info("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" + info("Calling on_exit_success") return self._on_exit_success() # Print fail message and exit with appropriate code @@ -365,7 +397,7 @@ def exit(self, status, msg): # Default timeout event def timeout(self): - print color.INFO(""), "VM timed out" + if VERB: print color.INFO(""), "VM timed out" # Note: we have to stop the VM since the main thread is blocking on vm.readline #self.exit(exit_codes["TIMEOUT"], nametag + " Test timed out") @@ -376,7 +408,7 @@ def timeout(self): # Default panic event def panic(self, panic_line): panic_reason = self._hyper.readline() - print color.INFO(nametag), "VM signalled PANIC. Reading until EOT (", hex(ord(EOT)), ")" + info("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"): @@ -414,7 +446,7 @@ def writeline(self, line): # Make using GNU Make def make(self, params = []): - print color.INFO(nametag), "Building with 'make' (params=" + str(params) + ")" + print INFO, "Building with 'make' (params=" + str(params) + ")" make = ["make"] make.extend(params) cmd(make) @@ -422,7 +454,7 @@ def make(self, params = []): # Call cmake def cmake(self, args = []): - print color.INFO(nametag), "Building with cmake (%s)" % args + print INFO, "Building with cmake (%s)" % args # install dir: INSTDIR = os.getcwd() @@ -452,7 +484,7 @@ def cmake(self, args = []): # Clean cmake build folder def clean(self): - print color.INFO(nametag), "Cleaning cmake build folder" + print INFO, "Cleaning cmake build folder" subprocess.call(["rm","-rf","build"]) # Boot the VM and start reading output. This is the main event loop. @@ -464,7 +496,7 @@ def boot(self, timeout = 60, multiboot = True, kernel_args = "booted with vmrunn # Start the timeout thread if (timeout): - print color.INFO(nametag),"setting timeout to",timeout,"seconds" + info("setting timeout to",timeout,"seconds") self._timer = threading.Timer(timeout, self._on_timeout) self._timer.start() @@ -532,32 +564,65 @@ def boot(self, timeout = 60, multiboot = True, kernel_args = "booted with vmrunn # If everything went well we can return return self +# Load a single vm config. Fallback to default +def load_single_config(path = "."): + + config = default_config + description = None + + # If path is explicitly "None", try current dir + if not path: path = "." + + info("Loading config from", path) + try: + # Try loading the first valid config + config, path = validate_vm.load_config(path)[0] + info ("vm config loaded from", path, ":",) + except Exception as e: + info ("No JSON config found - using default:",) + + if config.has_key("description"): + description = config["description"] + else: + description = str(config) -print color.HEADER("IncludeOS vmrunner loading VM configs") + info('"',description,'"') -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(".") + return config -default_spec = {"image" : "service.img", - "net" : [{"device" : "virtio", "backend" : "tap" }] } # Provide a list of VM's with validated specs -vms = [] +# One unconfigured vm is created by default, which will try to load a config if booted +vms = [vm()] -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)) +def load_configs(config_path = "."): + global vms -else: - print color.WARNING(nametag), "No VM specification JSON found, trying default config" - vms.append(vm(default_spec)) + # 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 # Handler for SIGINT def handler(signum, frame): From c8cb2b4ce19bea63fe65a19d73ea1f077c3d37bf Mon Sep 17 00:00:00 2001 From: Alfred Bratterud Date: Wed, 25 Jan 2017 23:29:25 +0100 Subject: [PATCH 2/5] boot: added metavar to config arg --- etc/boot | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/etc/boot b/etc/boot index 19486f045f..1cfd322b97 100755 --- a/etc/boot +++ b/etc/boot @@ -43,8 +43,8 @@ parser.add_argument("--create-bridge", dest="bridge", action="store_true", parser.add_argument("-g", "--grub", dest="grub", action="store_true", help="Create image with GRUB bootloader that will boot provided binary") -parser.add_argument("-j", "--config", dest="config", type = str, - help="Location of VM JSON config") +parser.add_argument("-j", "--config", dest="config", type = str, metavar = "PATH", + help="Location of VM config file - JSON validated against a schema") parser.add_argument('vm_location', action="store", type = str, help="Location of the IncludeOS service binary, image or source") From 8e4194250699fd3a345645bc549f6a4bd910b97f Mon Sep 17 00:00:00 2001 From: Alfred Bratterud Date: Thu, 26 Jan 2017 17:05:03 +0100 Subject: [PATCH 3/5] test: separated validation of tests from vm config validation --- test/testrunner.py | 16 ++++++------ test/validate_all.py | 30 ---------------------- test/validate_tests.py | 56 +++++++++++++++++++++++++++++++++++++++++ vmrunner/validate_vm.py | 26 +++---------------- 4 files changed, 67 insertions(+), 61 deletions(-) delete mode 100755 test/validate_all.py create mode 100755 test/validate_tests.py diff --git a/test/testrunner.py b/test/testrunner.py index 663070a39c..4bcc383832 100755 --- a/test/testrunner.py +++ b/test/testrunner.py @@ -14,7 +14,7 @@ from vmrunner.prettify import color as pretty from vmrunner import validate_vm -import validate_all +import validate_tests startdir = os.getcwd() @@ -54,10 +54,7 @@ def print_skipped(tests): for test in tests: if test.skip_: print pretty.WARNING("* Skipping " + test.name_) - if "validate_vm" in test.skip_reason_: - validate_vm.validate_path(test.path_, verb = True) - else: - print " Reason: {0:40}".format(test.skip_reason_) + print "Reason: {0:40}".format(test.skip_reason_) class Test: @@ -179,9 +176,10 @@ def check_valid(self): self: Class function """ # Test 1 - if not validate_vm.validate_path(self.path_, verb = False): + valid, err = validate_tests.validate_test(self.path_, verb = False) + if not valid: self.skip_ = True - self.skip_reason_ = 'Failed validate_vm, missing files' + self.skip_reason_ = err return # Test 2 @@ -212,7 +210,7 @@ def stress_test(): print pretty.WARNING("Stress test skipped") return 0 - if (not validate_vm.validate_path("stress")): + if (not validate_tests.validate_test("stress")): raise Exception("Stress test failed validation") print pretty.HEADER("Starting stress test") @@ -383,7 +381,7 @@ def filter_tests(all_tests, arguments): or x.name_ in add_args ] # 2) Remove tests defined by the skip argument - print pretty.INFO("Tests to skip"), ", ".join(skip_args) + print pretty.INFO("Tests marked skip on command line"), ", ".join(skip_args) skipped_tests = [ x for x in tests_added if x.type_ in skip_args or x.category_ in skip_args diff --git a/test/validate_all.py b/test/validate_all.py deleted file mode 100755 index cb1cf1168e..0000000000 --- a/test/validate_all.py +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env python -import sys -sys.path.insert(0, ".") -sys.path.insert(0, "..") - -import subprocess -import os -from vmrunner import validate_vm -from vmrunner.prettify import color - -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 - -if __name__ == "__main__": - valid_tests(verb = True) diff --git a/test/validate_tests.py b/test/validate_tests.py new file mode 100755 index 0000000000..c6f4248968 --- /dev/null +++ b/test/validate_tests.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python +import sys +sys.path.insert(0, ".") +sys.path.insert(0, "..") + +import subprocess +import os +from vmrunner import validate_vm +from vmrunner.prettify import color + +# Verify if a given path is a valid integration test +def validate_test(path, verb = False): + + try: + # Load any valid configs in path + valid_configs = validate_vm.load_config(path) + if not valid_configs: + raise Exception("No valid JSON config in path") + + # Additional requirements for tests + required_files = ["CMakeLists.txt", "test.py"] + + for f in required_files: + if not os.path.isfile(path + "/" + f): + raise Exception("Required file " + f + " missing") + + if verb: + print " \tPASS: ",path + return True, "PASS" + + except Exception as err: + if verb: + print " \tFAIL: ", path, ": " , err.message + + return False, err.message + + +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 + passed, err = validate_test(path, verb) + if passed: + tests.append(path) + + return tests + +if __name__ == "__main__": + valid_tests(verb = True) diff --git a/vmrunner/validate_vm.py b/vmrunner/validate_vm.py index 097e35a9f2..96616bd043 100755 --- a/vmrunner/validate_vm.py +++ b/vmrunner/validate_vm.py @@ -42,8 +42,6 @@ def load_schema(filename = default_schema): vm_schema = json.loads(open(filename).read()); -#def load_from_json( - def validate_vm_spec(filename): vm_spec = None @@ -83,24 +81,8 @@ def load_config(path): return valid_vms -def validate_path(path, verb = False): - global verbose - verbose = verb - current_dir = os.getcwd() - if not vm_schema: - load_schema(package_path + "/vm.schema.json") - os.chdir(path) - try: - load_config(path) - if verbose: - print " \tPASS: ",os.getcwd() - return True - except Exception as err: - if verbose: - print " \tFAIL: unmet requirements in " + path, ": " , err.message - finally: - os.chdir(current_dir) - if __name__ == "__main__": - path = sys.argv[1] if len(sys.argv) > 1 else "." - validate_path(path) + path = sys.argv[1] if len(sys.argv) > 1 else "." + if not load_config(path): + print "No valid config found" + exit(-1) From 06c39ad18666e79984a49f99315fc502ed2f532b Mon Sep 17 00:00:00 2001 From: Alfred Bratterud Date: Thu, 26 Jan 2017 17:06:20 +0100 Subject: [PATCH 4/5] test: http test now runs server in separate thread --- test/net/integration/http/service.cpp | 3 +++ test/net/integration/http/test.py | 9 +++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/test/net/integration/http/service.cpp b/test/net/integration/http/service.cpp index 75f2d12db0..7c6c9371fe 100644 --- a/test/net/integration/http/service.cpp +++ b/test/net/integration/http/service.cpp @@ -48,6 +48,9 @@ void Service::ready() client_->send(std::move(req), {inet.gateway(), 9011}, [] (auto err, auto res) { + if (err) + printf("Error: %s \n", err.to_string().c_str()); + CHECKSERT(!err, "No error"); CHECKSERT(res->body() == "/testing", "Received body: \"/testing\""); printf("Response:\n%s\n", res->to_string().c_str()); diff --git a/test/net/integration/http/test.py b/test/net/integration/http/test.py index f83b095155..9cf35ac4f6 100755 --- a/test/net/integration/http/test.py +++ b/test/net/integration/http/test.py @@ -2,6 +2,7 @@ import sys import os +import thread includeos_src = os.environ.get('INCLUDEOS_SRC', os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__))).split('/test')[0]) @@ -23,7 +24,7 @@ def do_GET(s): s.wfile.write("%s" % s.path) -def Client_test(trigger_line): +def Client_test(): server_class = BaseHTTPServer.HTTPServer httpd = server_class((HOST, PORT), RequestHandler) global DO_SERVE @@ -32,11 +33,11 @@ def Client_test(trigger_line): DO_SERVE = False httpd.server_close() +# Start web server in a separate thread +thread.start_new_thread(Client_test, ()) + # Get an auto-created VM from the vmrunner vm = vmrunner.vms[0] -# Add custom event-handler -vm.on_output("Testing against local server", Client_test) - # Boot the VM, taking a timeout as parameter vm.cmake().boot(20).clean() From ad1c61f74d3474bc048c8419f89a6457f9d3a606 Mon Sep 17 00:00:00 2001 From: Alfred Bratterud Date: Thu, 26 Jan 2017 17:07:02 +0100 Subject: [PATCH 5/5] prettify: removed extra newline for warnings --- vmrunner/prettify.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vmrunner/prettify.py b/vmrunner/prettify.py index 5d34a61eb6..b53bf5333a 100644 --- a/vmrunner/prettify.py +++ b/vmrunner/prettify.py @@ -47,7 +47,7 @@ def code(fg = WHITE, bg = BLACK, style = NORMAL, fg_intensity = FG_NORMAL, bg_in @staticmethod def WARNING(string): - return color.C_WARNING + "[ WARNING ] " + string.rstrip() + color.C_ENDC + "\n" + return color.C_WARNING + "[ WARNING ] " + string.rstrip() + color.C_ENDC @staticmethod def FAIL(string):