patches and low-level development discussion
 help / color / mirror / code / Atom feed
becbe5c9523b2966bf850019f6104fb7c9d3ba99 blob 3618 bytes (raw)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
 
// SPDX-License-Identifier: EUPL-1.2
// SPDX-FileCopyrightText: 2022 Alyssa Ross <hi@alyssa.is>

mod ch;
mod modprobe;
mod net;

use std::env::{args, current_dir};
use std::ffi::{CString, OsString};
use std::io::{self, ErrorKind};
use std::os::unix::prelude::*;
use std::path::PathBuf;
use std::process::{exit, Command};

use modprobe::modprobe;
use net::{format_mac, net_setup, NetConfig};

macro_rules! errx {
    ($code:expr, $fmt:expr $(,$args:expr)*) => ({
        let argv0_option = args().next();
        let argv0 = argv0_option.as_ref().map(String::as_str).unwrap_or("start-vm");
        eprintln!(concat!("{}: ", $fmt), argv0 $(,$args)*);
        exit($code);
    })
}

macro_rules! err {
    ($code:expr, $fmt:expr $(,$args:expr)*) =>
        (|e| errx!($code, concat!($fmt, ": {}") $(,$args)*, e))
}

fn main() {
    modprobe(&["kvm-intel"]).unwrap_or_else(err!(1, "modprobe kvm-intel"));

    let mut command = Command::new("s6-notifyoncheck");
    command.args(&["-dc", "test -S env/cloud-hypervisor.sock"]);
    command.arg("cloud-hypervisor");
    command.args(&["--api-socket", "env/cloud-hypervisor.sock"]);
    command.args(&["--cmdline", "console=ttyS0 root=/dev/vda"]);
    command.args(&["--memory", "size=128M"]);
    command.args(&["--console", "pty"]);

    let dir = current_dir()
        .unwrap_or_else(err!(1, "getting current directory"))
        .into_os_string()
        .into_vec();
    let dir = PathBuf::from(OsString::from_vec(dir));

    let vm_name = dir
        .file_name()
        .unwrap_or_else(|| errx!(1, "current directory has no name"));

    let mut net_providers_dir = PathBuf::new();
    net_providers_dir.push("/ext/svc/data");
    net_providers_dir.push(vm_name);
    net_providers_dir.push("providers/net");

    match net_providers_dir.read_dir() {
        Ok(entries) => {
            for r in entries {
                let entry = r
                    .unwrap_or_else(err!(1, "examining directory entry"))
                    .file_name();

                // Safe because prov is the name of a directory entry, so
                // con't contain a null byte.
                let provider_name = unsafe { CString::from_vec_unchecked(entry.into_vec()) };

                // Safe because we pass a valid pointer and check the result.
                let NetConfig { fd, mac } = unsafe { net_setup(provider_name.as_ptr()) };
                if fd == -1 {
                    let e = io::Error::last_os_error();
                    errx!(1, "setting up networking failed: {}", e);
                }

                command
                    .arg("--net")
                    .arg(format!("fd={},mac={}", fd, format_mac(&mac)));

                // TODO: to support multiple net providers, we'll need
                // a better naming scheme for tap and bridge devices.
                break;
            }
        }
        Err(e) if e.kind() == ErrorKind::NotFound => {}
        Err(e) => errx!(1, "reading directory {:?}: {}", net_providers_dir, e),
    }

    command.arg("--kernel").arg({
        let mut kernel = OsString::from("/ext/svc/data/");
        kernel.push(&vm_name);
        kernel.push("/vmlinux");
        kernel
    });

    command.arg("--disk").arg({
        let mut disk = OsString::from("path=/ext/svc/data/");
        disk.push(&vm_name);
        disk.push("/rootfs.ext4,readonly=on");
        disk
    });

    command.arg("--serial").arg({
        let mut serial = OsString::from("file=/run/");
        serial.push(&vm_name);
        serial.push(".log");
        serial
    });

    errx!(1, "failed to exec: {}", command.exec());
}
debug log:

solving becbe5c ...
found becbe5c in https://spectrum-os.org/git/spectrum

Code repositories for project(s) associated with this public inbox

	https://spectrum-os.org/git/crosvm
	https://spectrum-os.org/git/doc
	https://spectrum-os.org/git/mktuntap
	https://spectrum-os.org/git/nixpkgs
	https://spectrum-os.org/git/spectrum
	https://spectrum-os.org/git/ucspi-vsock
	https://spectrum-os.org/git/www

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).