4 # Copyright (c) 2018 Vojtech Horky
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions
11 # - Redistributions of source code must retain the above copyright
12 # notice, this list of conditions and the following disclaimer.
13 # - Redistributions in binary form must reproduce the above copyright
14 # notice, this list of conditions and the following disclaimer in the
15 # documentation and/or other materials provided with the distribution.
16 # - The name of the author may not be used to endorse or promote products
17 # derived from this software without specific prior written permission.
19 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 from htest
.vm
.controller
import VMManager
38 from htest
.vm
.qemu
import QemuVMController
39 from htest
.tasks
import *
41 args
= argparse
.ArgumentParser(
42 description
='Testing of HelenOS in VM',
43 formatter_class
=argparse
.RawDescriptionHelpFormatter
,
45 Typical invocation will use the following arguments:
47 --scenario scenario.yml
48 --arch amd64 # ia32, ppc32 etc.
49 --vterm-dump dump.txt # all text from main vterm
50 --last-screenshot shot.png # last VM screen
53 args
.add_argument('--headless',
57 help='Do not show any VM windows.'
59 args
.add_argument('--scenario',
60 metavar
='FILENAME.yml',
65 args
.add_argument('--arch',
66 metavar
='ARCHITECTURE',
69 help='Emulated architecture identification.'
71 args
.add_argument('--memory',
77 help='Amount of memory for the virtual machine.'
79 args
.add_argument('--image',
83 help='HelenOS boot image (e.g. ISO file).'
85 args
.add_argument('--disk',
90 help='Disk image (e.g. hdisk.img).'
92 args
.add_argument('--pass',
94 dest
='pass_thru_options',
97 help='Extra options to pass through to the emulator'
99 args
.add_argument('--vterm-dump',
100 metavar
='FILENAME.txt',
103 help='Where to store full vterm dump.'
105 args
.add_argument('--last-screenshot',
106 metavar
='FILENAME.png',
107 dest
='last_screenshot',
109 help='Where to store last screenshot.'
111 args
.add_argument('--debug',
115 help='Print debugging messages'
118 config
= args
.parse_args()
121 config
.logging_level
= logging
.DEBUG
123 config
.logging_level
= logging
.INFO
126 format
='[%(asctime)s %(name)-16s %(levelname)7s] %(message)s',
127 level
=config
.logging_level
130 logger
= logging
.getLogger('main')
132 with
open(config
.scenario
, 'r') as f
:
134 scenario
= yaml
.load(f
)
135 except yaml
.YAMLError
as ex
:
139 if config
.memory
< 8:
140 logger
.error("Specify at least 8MB of memory.")
144 for ctl
in [ QemuVMController
]:
145 if ctl
.is_supported(config
.architecture
):
148 if controller
is None:
149 logger
.error("Unsupported architecture {}.".format(config
.architecture
))
152 vmm
= VMManager(controller
, config
.architecture
, config
.boot_image
, config
.disk_image
, config
.memory
, config
.headless
, config
.pass_thru_options
)
155 for t
in scenario
['tasks']:
158 k
= list(set(t
.keys()) - set(['name', 'machine']))
160 raise Exception("Unknown task ({})!".format(k
))
168 raise Exception("Unknown task!")
169 task_classname
= 'ScenarioTask' + task_name
.title().replace('-', '_')
170 task_class
= globals()[task_classname
]
171 task_inst
= task_class(t
[task_name
])
172 if not ('machine' in t
):
174 machine
= vmm
.get(t
['machine'])
176 if t
['machine'] is None:
177 t
['machine'] = 'default'
178 logger
.debug("Creating new machine {}.".format(t
['machine']))
179 machine
= vmm
.create(t
['machine'])
180 task_inst
.set_machine(machine
)
181 scenario_tasks
.append(task_inst
)
185 for t
in scenario_tasks
:
187 print("Scenario passed.")
188 except Exception as ex
:
189 logger
.exception("Scenario aborted: {}".format(ex
))
190 print("Scenario aborted: {}".format(ex
))
193 vmm
.terminate(config
.vterm_dump
, config
.last_screenshot
)