-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add initial version of hypervisor tooling (#18)
* deb: fix extraction of uncompressed data.tar In some debian packages the data.tar is not compressed and named only data.tar without any extension. * add initial version of hypervisor tooling Adds tooling to generated the hypervisor configuration (lua scripts) using a yaml configuration file and a yaml model of this configuration described in yaml and python. The reason for having the model "twice", is that the yaml definition of the model describes how the configuration is parsed into a python object model. The python model is required to do some postprocessing of the configuration, before jinja2 is used to generate the final configuration. The used hypervisor version can support additional features or require a different generated configuration. For that reason the configuration model can be extended by a configuration specialization bundled together with the hypervisor.
- Loading branch information
Showing
11 changed files
with
1,190 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
import argparse | ||
import logging | ||
import os | ||
from pathlib import Path | ||
|
||
import jinja2 | ||
import yaml | ||
|
||
from ebcl.common import init_logging, log_exception | ||
from ebcl.common.files import resolve_file | ||
|
||
from .schema_loader import BaseModel, FileReadProtocol, Schema, merge_dict | ||
|
||
|
||
class BaseResolver: | ||
""" | ||
Resolve bases defined in the yaml config. | ||
""" | ||
|
||
def load(self, config_file: str, conf_dir: str) -> dict: | ||
""" | ||
Load config_file and all of its bases. | ||
""" | ||
config = { | ||
"base": [config_file] | ||
} | ||
while config["base"]: | ||
base_name = config["base"].pop(0) | ||
base_path = resolve_file( | ||
file=base_name, relative_base_dir=conf_dir) | ||
old = config | ||
config = self._load_file(base_path) | ||
merge_dict(config, old) | ||
return config | ||
|
||
def _load_file(self, filename: str) -> dict: | ||
with open(filename, "r", encoding="utf-8") as f: | ||
return yaml.load(f, yaml.Loader) | ||
|
||
|
||
class HvFileGenerator: | ||
""" | ||
Hypervisor configuration file generator | ||
""" | ||
config: BaseModel | ||
schema: Schema | ||
output_path: Path | ||
|
||
def __init__(self, file: str, output_path: str, specialization: str | None = None) -> None: | ||
""" Parse the yaml config file. | ||
Args: | ||
config_file (Path): Path to the yaml config file. | ||
""" | ||
self.output_path = Path(output_path) | ||
|
||
""" Load yaml configuration. """ | ||
config_file = Path(file) | ||
|
||
config = BaseResolver().load(config_file.name, str(config_file.parent)) | ||
del config["base"] | ||
|
||
self.schema = Schema(specialization and Path(specialization) or None) | ||
self.config = self.schema.parse_config(config) | ||
|
||
def _render_template(self, outpath: Path, template: FileReadProtocol) -> None: | ||
"""Render a template to target""" | ||
template_obj = jinja2.Template(template.read_text("utf-8"), trim_blocks=True) | ||
|
||
with outpath.open("w", encoding="utf-8") as f: | ||
f.write(template_obj.render(config=self.config)) | ||
|
||
def create_files(self) -> None: | ||
""" | ||
Create three Files of HV | ||
init.ned, io.cfg and modules.list | ||
""" | ||
self.output_path.mkdir(exist_ok=True) | ||
|
||
for template in self.schema.templates: | ||
base, ext = os.path.splitext(template.name) | ||
if ext == ".j2": | ||
logging.info("Rendering %s", base) | ||
outpath = self.output_path / base | ||
self._render_template(outpath, template) | ||
else: | ||
logging.info("Creating %s", template) | ||
outpath = self.output_path / template.name | ||
outpath.write_text(template.read_text("utf-8")) | ||
|
||
|
||
@log_exception(call_exit=True) | ||
def main() -> None: | ||
""" Main entrypoint of EBcL hypervisor generator. """ | ||
init_logging() | ||
|
||
logging.info('\n===================\n' | ||
'EBcL Hypervisor Config File Generator\n' | ||
'===================\n') | ||
|
||
parser = argparse.ArgumentParser( | ||
description='Create the config files for the hypervisor') | ||
parser.add_argument('-s', '--specialization', type=str, | ||
help='Path to hypervisor specialization directory') | ||
parser.add_argument('config_file', type=str, | ||
help='Path to the YAML configuration file') | ||
parser.add_argument('output', type=str, | ||
help='Path to the output directory') | ||
args = parser.parse_args() | ||
|
||
generator = HvFileGenerator(args.config_file, args.output, args.specialization) | ||
generator.create_files() | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
local Res = Io.Res | ||
local Hw = Io.Hw | ||
|
||
local hw = Io.system_bus(); | ||
|
||
Io.Dt.add_children(hw, function() | ||
{% for vbus in config.vbus %} | ||
{% for dev in vbus.devices %} | ||
{{dev.name}} = Hw.Device(function() | ||
{% if dev.compatible %} | ||
compatible = {"{{dev.compatible}}"} | ||
{% endif %} | ||
{%for mmio in dev.mmios %} | ||
Resource.reg{{loop.index0}} = Res.mmio({{"0x%x"|format(mmio.address)}}, {{"0x%x"|format(mmio.address + mmio.size - 1)}}{% if mmio.cached %}, Io.Resource.F_cached_mem | Io.Resource.F_prefetchable{% endif %}) | ||
{% endfor %} | ||
{%for irq in dev.irqs %} | ||
Resource.irq{{loop.index0}} = Res.irq({{irq.irq + irq.offset}}, Io.Resource.Irq_type_{{irq.is_edge and "raising_edge" or "level_high"}}) | ||
{% endfor %} | ||
end) | ||
{% endfor %} | ||
{% endfor %} | ||
end) | ||
|
||
Io.add_vbusses({ | ||
{% for vbus in config.vbus %} | ||
{{vbus.name}} = Io.Vi.System_bus(function() | ||
{% for dev in vbus.devices %} | ||
{{dev.name}} = wrap(hw.{{dev.name}}) | ||
{% endfor %} | ||
end), | ||
{% endfor %} | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
{ | ||
"$schema": "https://json-schema.org/draft/2020-12/schema", | ||
"$id": "https://linux.elektrobit.com.com/model.schema.json", | ||
"title": "Hypervisor Configuration Model", | ||
"description": "Hypervisor configuration model", | ||
"type": "object", | ||
"additionalProperties": false, | ||
"default": {}, | ||
"properties": { | ||
"version": { | ||
"type": "integer" | ||
}, | ||
"classes": { | ||
"type": "object", | ||
"default": {}, | ||
"additionalProperties": { | ||
"type": "object", | ||
"additionalProperties": { | ||
"type": "object", | ||
"additionalProperties": false, | ||
"properties": { | ||
"type": {"type": "string"}, | ||
"default": {"type": ["string", "number", "boolean", "array"]}, | ||
"aggregate": { | ||
"enum": ["None", "list"], | ||
"default": "None" | ||
}, | ||
"optional": {"type": "boolean", "default": false}, | ||
"enum_values": {"type": "array", "items": {"type": "string"}} | ||
} | ||
} | ||
} | ||
}, | ||
"root": { | ||
"type": "string", | ||
"optional": false | ||
}, | ||
"templates": { | ||
"type": "array", | ||
"items": { | ||
"type": "string" | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
default-kernel fiasco -serial_esc | ||
|
||
entry hv-image | ||
roottask moe rom/init.ned | ||
|
||
module l4re | ||
module ned | ||
module cons | ||
module io | ||
{% if config.vms %} | ||
module uvmm | ||
{% endif %} | ||
{% if config.vio_block %} | ||
module virtio-block | ||
{% endif %} | ||
{% if config.vnets %} | ||
module l4vio_net_p2p | ||
{% endif %} | ||
|
||
module init.ned | ||
module io.cfg | ||
module system.lua | ||
|
||
{% for module in config.modules %} | ||
module {{module}} | ||
{% endfor %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
# yaml-language-server: $schema=model.schema.json | ||
|
||
version: 1 | ||
|
||
classes: | ||
HVConfig: | ||
vbus: | ||
type: VBus | ||
aggregate: list | ||
default: [] | ||
cons: | ||
type: Cons | ||
optional: true | ||
shms: | ||
type: SHM | ||
aggregate: list | ||
default: [] | ||
vms: | ||
type: VM | ||
aggregate: list | ||
default: [] | ||
|
||
VM: | ||
name: | ||
type: string | ||
kernel: | ||
type: string | ||
ram: | ||
type: integer | ||
cpus: | ||
type: integer | ||
cmdline: | ||
type: string | ||
default: "" | ||
initrd: | ||
type: string | ||
optional: true | ||
dtb: | ||
type: string | ||
vbus: | ||
type: string | ||
optional: true | ||
vmnets: | ||
type: string | ||
aggregate: list | ||
default: [] | ||
shms: | ||
type: string | ||
aggregate: list | ||
default: [] | ||
virtio_block: | ||
type: VirtioBlockNode | ||
optional: true | ||
vnets: | ||
type: string | ||
aggregate: list | ||
default: [] | ||
|
||
|
||
VirtioBlockNode: | ||
servers: | ||
type: string | ||
aggregate: list | ||
default: [] | ||
|
||
clients: | ||
type: string | ||
aggregate: list | ||
default: [] | ||
|
||
SHM: | ||
name: | ||
type: string | ||
size: | ||
type: integer | ||
address: | ||
type: integer | ||
optional: true | ||
|
||
Cons: | ||
default_vm: | ||
type: string | ||
optional: true | ||
|
||
VBus: | ||
name: | ||
type: string | ||
devices: | ||
type: Device | ||
aggregate: list | ||
|
||
Device: | ||
name: | ||
type: string | ||
compatible: | ||
type: string | ||
optional: true | ||
mmios: | ||
type: MMIO | ||
aggregate: list | ||
optional: true | ||
irqs: | ||
type: IRQ | ||
aggregate: list | ||
optional: true | ||
MMIO: | ||
address: | ||
type: integer | ||
size: | ||
type: integer | ||
cached: | ||
type: boolean | ||
default: false | ||
IRQ: | ||
irq: | ||
type: integer | ||
type: | ||
type: enum | ||
enum_values: | ||
- SGI | ||
- PPI | ||
- SPI | ||
default: SPI | ||
trigger: | ||
type: enum | ||
enum_values: | ||
- level_high | ||
- rising_edge | ||
|
||
root: HVConfig | ||
|
||
templates: | ||
- io.cfg.j2 | ||
- system.lua |
Oops, something went wrong.