Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion src/cijoe/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,28 @@ def search_for_file(path: Path) -> Optional[Path]:


def create_combined_toml(configs: list[Path], path: Path):
def merge_dicts(a: dict, b: dict) -> dict:
"""
Recursively merge two dictionaries.
Values in `b` overwrite values in `a` unless both values are dicts.
"""
result = dict(a)

for key, value in b.items():
if (
key in result
and isinstance(result[key], dict)
and isinstance(value, dict)
):
result[key] = merge_dicts(result[key], value)
else:
result[key] = value

return result

combined_config: dict[str, Any] = {}
for config in configs:
combined_config |= dict_from_tomlfile(config)
combined_config = merge_dicts(combined_config, dict_from_tomlfile(config))

dict_to_tomlfile(combined_config, path)

Expand Down
2 changes: 2 additions & 0 deletions src/cijoe/core/templates/report-workflow.html.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,8 @@ function selectFilter(event) {
{% endif %}
</button>
<a href="{{ runlog["output_path"] }}" class="btn btn-primary bi bi-file-code">&nbsp;.output</a>
<button class="btn btn-primary bi bi-clipboard" type="button" onclick="navigator.clipboard.writeText('{{ runlog["state"]["cmd"].replace("'", "\\'") }}')">
</button>
<a href="{{ runlog["state_path"] }}" class="btn btn-primary bi bi-filetype-yml"></a>
</div>
</li>
Expand Down
59 changes: 59 additions & 0 deletions src/cijoe/qemu/scripts/guest_wait_for_ssh.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/usr/bin/env python3
"""
Wait for qemu guest SSH to be ready
===================================

Note: The script will not fail if the guest does not exist.
Note: This script does not itself start the qemu guest.

Retargetable: False
-------------------
"""
import logging as log
import time
from argparse import ArgumentParser


def add_args(parser: ArgumentParser):
parser.add_argument(
"--transport_name",
type=str,
default=None,
help="Name of the transport to be used. If none given, it uses the first defined transport in the config.",
)
parser.add_argument(
"--timeout",
type=int,
default=60,
help="Amount of seconds to wait for the qemu guest to terminate.",
)


def main(args, cijoe):
"""Wait for qemu guest to start"""

began = time.time()
while True:
enter = time.time()
try:
err, state = cijoe.run(
"echo 'It is alive!'",
transport_name=args.transport_name,
)
if not err and "It is alive!" in state.output():
break
except Exception:
# do nothing
...

now = time.time()
elapsed_iter = now - enter
elapsed_total = now - began

if elapsed_iter < 5.0:
time.sleep(5.0 - elapsed_iter)
if elapsed_total > args.timeout:
log.error(f"System did not come up within timeout({args.timeout}) seconds")
return False

return 0
6 changes: 6 additions & 0 deletions src/cijoe/qemu/workflows/example_workflow_guest_aarch64.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ steps:
with:
guest_name: generic-uefi-tcg-aarch64

- name: guest_wait_start
uses: qemu.guest_wait_for_ssh
with:
transport_name: qemu_guest
timeout: 120

- name: guest_check
run: |
hostname
Expand Down
6 changes: 6 additions & 0 deletions src/cijoe/qemu/workflows/example_workflow_guest_x86_64.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ steps:
with:
guest_name: generic-bios-kvm-x86_64

- name: guest_wait_start
uses: qemu.guest_wait_for_ssh
with:
transport_name: qemu_guest
timeout: 120

- name: guest_check
run: |
hostname
Expand Down
3 changes: 2 additions & 1 deletion src/cijoe/qemu/wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,8 @@ def start(self, daemonize=True, extra_args=[]):
"-blockdev",
f"qcow2,node-name=boot,file.driver=file,file.filename={self.boot_img}",
]
args += ["-device", "virtio-blk-pci,drive=boot"]
boot_driver = self.guest_config.get("boot_driver", "virtio-blk-pci")
args += ["-device", f"{boot_driver},drive=boot"]

# Process Management stuff
args += ["-pidfile", str(self.pid)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ write_files:

runcmd:
- systemctl restart ssh

- touch /etc/cloud/cloud-init.disabled

final_message: "The system is up, after $UPTIME seconds"
power_state:
mode: poweroff
Expand Down
Loading