mirror of
https://github.com/edera-dev/krata.git
synced 2025-08-02 21:00:55 +00:00
os: build bootable images
This commit is contained in:
parent
817509bcef
commit
4894bd9d1c
2
.dockerignore
Normal file
2
.dockerignore
Normal file
@ -0,0 +1,2 @@
|
||||
/target
|
||||
/kernel/linux-*
|
4
.github/workflows/kernel.yml
vendored
4
.github/workflows/kernel.yml
vendored
@ -13,4 +13,6 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- run: ./hack/ci/install-deps.sh
|
||||
- run: ./hack/kernel/build.sh -j5
|
||||
- run: ./hack/kernel/build.sh
|
||||
env:
|
||||
KRATA_KERNEL_BUILD_JOBS: "5"
|
||||
|
29
.github/workflows/nightly.yml
vendored
29
.github/workflows/nightly.yml
vendored
@ -16,17 +16,32 @@ jobs:
|
||||
- run: ./hack/dist/bundle.sh
|
||||
env:
|
||||
KRATA_KERNEL_BUILD_JOBS: "5"
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: krata-bundle-systemd-x86_64
|
||||
path: "target/dist/bundle-systemd.tgz"
|
||||
compression-level: 0
|
||||
- run: ./hack/dist/deb.sh
|
||||
env:
|
||||
KRATA_BUNDLE_SKIP_KERNEL_BUILD: "1"
|
||||
KRATA_KERNEL_BUILD_SKIP: "1"
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: krata-nightly-bundle-x86_64
|
||||
path: "target/dist/bundle.tgz"
|
||||
name: krata-debian-x86_64
|
||||
path: "target/dist/*_amd64.deb"
|
||||
compression-level: 0
|
||||
- run: ./hack/dist/apk.sh
|
||||
env:
|
||||
KRATA_KERNEL_BUILD_SKIP: "1"
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: krata-nightly-debian-x86_64
|
||||
path: "target/dist/*_amd64.deb"
|
||||
compression-level: 0
|
||||
|
||||
name: krata-alpine-x86_64
|
||||
path: "target/dist/*_amd64.apk"
|
||||
compression-level: 0
|
||||
- run: ./hack/os/build.sh
|
||||
env:
|
||||
KRATA_KERNEL_BUILD_SKIP: "1"
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: krata-os-x86_64
|
||||
path: "target/os/krata.qcow2"
|
||||
compression-level: 0
|
||||
|
@ -75,6 +75,8 @@ features = ["derive"]
|
||||
|
||||
[workspace.dependencies.reqwest]
|
||||
version = "0.11.24"
|
||||
default-features = false
|
||||
features = ["rustls-tls"]
|
||||
|
||||
[workspace.dependencies.sys-mount]
|
||||
version = "3.0.0"
|
||||
|
@ -60,7 +60,7 @@ impl RuntimeContext {
|
||||
image_cache_path.push("cache");
|
||||
fs::create_dir_all(&image_cache_path)?;
|
||||
|
||||
let xen = XenClient::open().await?;
|
||||
let xen = XenClient::open(0).await?;
|
||||
image_cache_path.push("image");
|
||||
fs::create_dir_all(&image_cache_path)?;
|
||||
let image_cache = ImageCache::new(&image_cache_path)?;
|
||||
|
@ -5,7 +5,7 @@ use xencall::XenCall;
|
||||
fn main() -> Result<()> {
|
||||
env_logger::init();
|
||||
|
||||
let call = XenCall::open()?;
|
||||
let call = XenCall::open(0)?;
|
||||
let domid = call.create_domain(CreateDomain::default())?;
|
||||
println!("created domain {}", domid);
|
||||
Ok(())
|
||||
|
@ -4,7 +4,7 @@ use xencall::XenCall;
|
||||
fn main() -> Result<()> {
|
||||
env_logger::init();
|
||||
|
||||
let call = XenCall::open()?;
|
||||
let call = XenCall::open(0)?;
|
||||
let info = call.get_domain_info(1)?;
|
||||
println!("{:?}", info);
|
||||
Ok(())
|
||||
|
@ -4,7 +4,7 @@ use xencall::XenCall;
|
||||
fn main() -> Result<()> {
|
||||
env_logger::init();
|
||||
|
||||
let call = XenCall::open()?;
|
||||
let call = XenCall::open(0)?;
|
||||
let context = call.get_vcpu_context(224, 0)?;
|
||||
println!("{:?}", context);
|
||||
Ok(())
|
||||
|
@ -4,7 +4,7 @@ use xencall::XenCall;
|
||||
fn main() -> Result<()> {
|
||||
env_logger::init();
|
||||
|
||||
let call = XenCall::open()?;
|
||||
let call = XenCall::open(0)?;
|
||||
let info = call.get_version_capabilities()?;
|
||||
println!("{:?}", info);
|
||||
Ok(())
|
||||
|
@ -2,9 +2,11 @@ use std::io;
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error("kernel error")]
|
||||
#[error("version of xen is not supported")]
|
||||
XenVersionUnsupported,
|
||||
#[error("kernel error: {0}")]
|
||||
Kernel(#[from] nix::errno::Errno),
|
||||
#[error("io issue encountered")]
|
||||
#[error("io issue encountered: {0}")]
|
||||
Io(#[from] io::Error),
|
||||
#[error("populate physmap failed")]
|
||||
PopulatePhysmapFailed,
|
||||
|
@ -3,22 +3,22 @@ pub mod sys;
|
||||
|
||||
use crate::error::{Error, Result};
|
||||
use crate::sys::{
|
||||
AddressSize, ArchDomainConfig, CreateDomain, DomCtl, DomCtlValue, DomCtlVcpuContext,
|
||||
EvtChnAllocUnbound, GetDomainInfo, GetPageFrameInfo3, Hypercall, HypercallInit, MaxMem,
|
||||
MaxVcpus, MemoryMap, MemoryReservation, MmapBatch, MmapResource, MmuExtOp, MultiCallEntry,
|
||||
VcpuGuestContext, VcpuGuestContextAny, XenCapabilitiesInfo, HYPERVISOR_DOMCTL,
|
||||
HYPERVISOR_EVENT_CHANNEL_OP, HYPERVISOR_MEMORY_OP, HYPERVISOR_MMUEXT_OP, HYPERVISOR_MULTICALL,
|
||||
HYPERVISOR_XEN_VERSION, XENVER_CAPABILITIES, XEN_DOMCTL_CREATEDOMAIN, XEN_DOMCTL_DESTROYDOMAIN,
|
||||
AddressSize, CreateDomain, DomCtl, DomCtlValue, DomCtlVcpuContext, EvtChnAllocUnbound,
|
||||
GetDomainInfo, GetPageFrameInfo3, Hypercall, HypercallInit, MaxMem, MaxVcpus, MemoryMap,
|
||||
MemoryReservation, MmapBatch, MmapResource, MmuExtOp, MultiCallEntry, VcpuGuestContext,
|
||||
VcpuGuestContextAny, XenCapabilitiesInfo, HYPERVISOR_DOMCTL, HYPERVISOR_EVENT_CHANNEL_OP,
|
||||
HYPERVISOR_MEMORY_OP, HYPERVISOR_MMUEXT_OP, HYPERVISOR_MULTICALL, HYPERVISOR_XEN_VERSION,
|
||||
XENVER_CAPABILITIES, XEN_DOMCTL_CREATEDOMAIN, XEN_DOMCTL_DESTROYDOMAIN,
|
||||
XEN_DOMCTL_GETDOMAININFO, XEN_DOMCTL_GETPAGEFRAMEINFO3, XEN_DOMCTL_GETVCPUCONTEXT,
|
||||
XEN_DOMCTL_HYPERCALL_INIT, XEN_DOMCTL_INTERFACE_VERSION, XEN_DOMCTL_MAX_MEM,
|
||||
XEN_DOMCTL_MAX_VCPUS, XEN_DOMCTL_PAUSEDOMAIN, XEN_DOMCTL_SETVCPUCONTEXT,
|
||||
XEN_DOMCTL_SET_ADDRESS_SIZE, XEN_DOMCTL_UNPAUSEDOMAIN, XEN_MEM_CLAIM_PAGES, XEN_MEM_MEMORY_MAP,
|
||||
XEN_MEM_POPULATE_PHYSMAP,
|
||||
XEN_DOMCTL_HYPERCALL_INIT, XEN_DOMCTL_MAX_MEM, XEN_DOMCTL_MAX_VCPUS, XEN_DOMCTL_PAUSEDOMAIN,
|
||||
XEN_DOMCTL_SETVCPUCONTEXT, XEN_DOMCTL_SET_ADDRESS_SIZE, XEN_DOMCTL_UNPAUSEDOMAIN,
|
||||
XEN_MEM_CLAIM_PAGES, XEN_MEM_MEMORY_MAP, XEN_MEM_POPULATE_PHYSMAP,
|
||||
};
|
||||
use libc::{c_int, mmap, usleep, MAP_FAILED, MAP_SHARED, PROT_READ, PROT_WRITE};
|
||||
use log::trace;
|
||||
use nix::errno::Errno;
|
||||
use std::ffi::{c_long, c_uint, c_ulong, c_void};
|
||||
use sys::{XEN_DOMCTL_MAX_INTERFACE_VERSION, XEN_DOMCTL_MIN_INTERFACE_VERSION};
|
||||
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::os::fd::AsRawFd;
|
||||
@ -27,15 +27,45 @@ use std::slice;
|
||||
|
||||
pub struct XenCall {
|
||||
pub handle: File,
|
||||
domctl_interface_version: u32,
|
||||
}
|
||||
|
||||
impl XenCall {
|
||||
pub fn open() -> Result<XenCall> {
|
||||
let file = OpenOptions::new()
|
||||
pub fn open(current_domid: u32) -> Result<XenCall> {
|
||||
let handle = OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.open("/dev/xen/privcmd")?;
|
||||
Ok(XenCall { handle: file })
|
||||
let domctl_interface_version =
|
||||
XenCall::detect_domctl_interface_version(&handle, current_domid)?;
|
||||
Ok(XenCall {
|
||||
handle,
|
||||
domctl_interface_version,
|
||||
})
|
||||
}
|
||||
|
||||
fn detect_domctl_interface_version(handle: &File, current_domid: u32) -> Result<u32> {
|
||||
for version in XEN_DOMCTL_MIN_INTERFACE_VERSION..XEN_DOMCTL_MAX_INTERFACE_VERSION + 1 {
|
||||
let mut domctl = DomCtl {
|
||||
cmd: XEN_DOMCTL_GETDOMAININFO,
|
||||
interface_version: version,
|
||||
domid: current_domid,
|
||||
value: DomCtlValue {
|
||||
get_domain_info: GetDomainInfo::default(),
|
||||
},
|
||||
};
|
||||
unsafe {
|
||||
let mut call = Hypercall {
|
||||
op: HYPERVISOR_DOMCTL,
|
||||
arg: [addr_of_mut!(domctl) as u64, 0, 0, 0, 0],
|
||||
};
|
||||
let result = sys::hypercall(handle.as_raw_fd(), &mut call).unwrap_or(-1);
|
||||
if result == 0 {
|
||||
return Ok(version);
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(Error::XenVersionUnsupported)
|
||||
}
|
||||
|
||||
pub fn mmap(&self, addr: u64, len: u64) -> Option<u64> {
|
||||
@ -275,32 +305,10 @@ impl XenCall {
|
||||
);
|
||||
let mut domctl = DomCtl {
|
||||
cmd: XEN_DOMCTL_GETDOMAININFO,
|
||||
interface_version: XEN_DOMCTL_INTERFACE_VERSION,
|
||||
interface_version: self.domctl_interface_version,
|
||||
domid,
|
||||
value: DomCtlValue {
|
||||
get_domain_info: GetDomainInfo {
|
||||
domid: 0,
|
||||
pad1: 0,
|
||||
flags: 0,
|
||||
total_pages: 0,
|
||||
max_pages: 0,
|
||||
outstanding_pages: 0,
|
||||
shr_pages: 0,
|
||||
paged_pages: 0,
|
||||
shared_info_frame: 0,
|
||||
cpu_time: 0,
|
||||
number_online_vcpus: 0,
|
||||
max_vcpu_id: 0,
|
||||
ssidref: 0,
|
||||
handle: [0; 16],
|
||||
cpupool: 0,
|
||||
gpaddr_bits: 0,
|
||||
pad2: [0; 7],
|
||||
arch: ArchDomainConfig {
|
||||
emulation_flags: 0,
|
||||
misc_flags: 0,
|
||||
},
|
||||
},
|
||||
get_domain_info: GetDomainInfo::default(),
|
||||
},
|
||||
};
|
||||
self.hypercall1(HYPERVISOR_DOMCTL, addr_of_mut!(domctl) as c_ulong)?;
|
||||
@ -315,7 +323,7 @@ impl XenCall {
|
||||
);
|
||||
let mut domctl = DomCtl {
|
||||
cmd: XEN_DOMCTL_CREATEDOMAIN,
|
||||
interface_version: XEN_DOMCTL_INTERFACE_VERSION,
|
||||
interface_version: self.domctl_interface_version,
|
||||
domid: 0,
|
||||
value: DomCtlValue { create_domain },
|
||||
};
|
||||
@ -331,7 +339,7 @@ impl XenCall {
|
||||
);
|
||||
let mut domctl = DomCtl {
|
||||
cmd: XEN_DOMCTL_PAUSEDOMAIN,
|
||||
interface_version: XEN_DOMCTL_INTERFACE_VERSION,
|
||||
interface_version: self.domctl_interface_version,
|
||||
domid,
|
||||
value: DomCtlValue { pad: [0; 128] },
|
||||
};
|
||||
@ -347,7 +355,7 @@ impl XenCall {
|
||||
);
|
||||
let mut domctl = DomCtl {
|
||||
cmd: XEN_DOMCTL_UNPAUSEDOMAIN,
|
||||
interface_version: XEN_DOMCTL_INTERFACE_VERSION,
|
||||
interface_version: self.domctl_interface_version,
|
||||
domid,
|
||||
value: DomCtlValue { pad: [0; 128] },
|
||||
};
|
||||
@ -364,7 +372,7 @@ impl XenCall {
|
||||
);
|
||||
let mut domctl = DomCtl {
|
||||
cmd: XEN_DOMCTL_MAX_MEM,
|
||||
interface_version: XEN_DOMCTL_INTERFACE_VERSION,
|
||||
interface_version: self.domctl_interface_version,
|
||||
domid,
|
||||
value: DomCtlValue {
|
||||
max_mem: MaxMem { max_memkb: memkb },
|
||||
@ -383,7 +391,7 @@ impl XenCall {
|
||||
);
|
||||
let mut domctl = DomCtl {
|
||||
cmd: XEN_DOMCTL_MAX_VCPUS,
|
||||
interface_version: XEN_DOMCTL_INTERFACE_VERSION,
|
||||
interface_version: self.domctl_interface_version,
|
||||
domid,
|
||||
value: DomCtlValue {
|
||||
max_cpus: MaxVcpus { max_vcpus },
|
||||
@ -402,7 +410,7 @@ impl XenCall {
|
||||
);
|
||||
let mut domctl = DomCtl {
|
||||
cmd: XEN_DOMCTL_SET_ADDRESS_SIZE,
|
||||
interface_version: XEN_DOMCTL_INTERFACE_VERSION,
|
||||
interface_version: self.domctl_interface_version,
|
||||
domid,
|
||||
value: DomCtlValue {
|
||||
address_size: AddressSize { size },
|
||||
@ -423,7 +431,7 @@ impl XenCall {
|
||||
};
|
||||
let mut domctl = DomCtl {
|
||||
cmd: XEN_DOMCTL_GETVCPUCONTEXT,
|
||||
interface_version: XEN_DOMCTL_INTERFACE_VERSION,
|
||||
interface_version: self.domctl_interface_version,
|
||||
domid,
|
||||
value: DomCtlValue {
|
||||
vcpu_context: DomCtlVcpuContext {
|
||||
@ -452,7 +460,7 @@ impl XenCall {
|
||||
let mut value = VcpuGuestContextAny { value: *context };
|
||||
let mut domctl = DomCtl {
|
||||
cmd: XEN_DOMCTL_SETVCPUCONTEXT,
|
||||
interface_version: XEN_DOMCTL_INTERFACE_VERSION,
|
||||
interface_version: self.domctl_interface_version,
|
||||
domid,
|
||||
value: DomCtlValue {
|
||||
vcpu_context: DomCtlVcpuContext {
|
||||
@ -469,7 +477,7 @@ impl XenCall {
|
||||
let mut buffer: Vec<u64> = frames.to_vec();
|
||||
let mut domctl = DomCtl {
|
||||
cmd: XEN_DOMCTL_GETPAGEFRAMEINFO3,
|
||||
interface_version: XEN_DOMCTL_INTERFACE_VERSION,
|
||||
interface_version: self.domctl_interface_version,
|
||||
domid,
|
||||
value: DomCtlValue {
|
||||
get_page_frame_info: GetPageFrameInfo3 {
|
||||
@ -497,7 +505,7 @@ impl XenCall {
|
||||
);
|
||||
let mut domctl = DomCtl {
|
||||
cmd: XEN_DOMCTL_HYPERCALL_INIT,
|
||||
interface_version: XEN_DOMCTL_INTERFACE_VERSION,
|
||||
interface_version: self.domctl_interface_version,
|
||||
domid,
|
||||
value: DomCtlValue {
|
||||
hypercall_init: HypercallInit { gmfn },
|
||||
@ -515,7 +523,7 @@ impl XenCall {
|
||||
);
|
||||
let mut domctl = DomCtl {
|
||||
cmd: XEN_DOMCTL_DESTROYDOMAIN,
|
||||
interface_version: XEN_DOMCTL_INTERFACE_VERSION,
|
||||
interface_version: self.domctl_interface_version,
|
||||
domid,
|
||||
value: DomCtlValue { pad: [0; 128] },
|
||||
};
|
||||
|
@ -280,7 +280,7 @@ impl Default for CreateDomain {
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Copy, Clone, Debug, Default)]
|
||||
pub struct GetDomainInfo {
|
||||
pub domid: u16,
|
||||
pub pad1: u16,
|
||||
@ -310,7 +310,7 @@ pub struct GetPageFrameInfo3 {
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Copy, Clone, Debug, Default)]
|
||||
pub struct ArchDomainConfig {
|
||||
pub emulation_flags: u32,
|
||||
pub misc_flags: u32,
|
||||
@ -334,7 +334,9 @@ pub struct HypercallInit {
|
||||
pub gmfn: u64,
|
||||
}
|
||||
|
||||
pub const XEN_DOMCTL_INTERFACE_VERSION: u32 = 0x00000015;
|
||||
pub const XEN_DOMCTL_MIN_INTERFACE_VERSION: u32 = 0x00000015;
|
||||
pub const XEN_DOMCTL_MAX_INTERFACE_VERSION: u32 = 0x00000016;
|
||||
|
||||
pub const SECINITSID_DOMU: u32 = 12;
|
||||
|
||||
#[repr(C)]
|
||||
|
@ -13,7 +13,7 @@ async fn main() -> Result<()> {
|
||||
}
|
||||
let kernel_image_path = args.get(1).expect("argument not specified");
|
||||
let initrd_path = args.get(2).expect("argument not specified");
|
||||
let mut client = XenClient::open().await?;
|
||||
let mut client = XenClient::open(0).await?;
|
||||
let config = DomainConfig {
|
||||
backend_domid: 0,
|
||||
name: "xenclient-test",
|
||||
|
@ -83,9 +83,9 @@ pub struct DomainConfig<'a> {
|
||||
}
|
||||
|
||||
impl XenClient {
|
||||
pub async fn open() -> Result<XenClient> {
|
||||
pub async fn open(current_domid: u32) -> Result<XenClient> {
|
||||
let store = XsdClient::open().await?;
|
||||
let call = XenCall::open()?;
|
||||
let call = XenCall::open(current_domid)?;
|
||||
Ok(XenClient { store, call })
|
||||
}
|
||||
|
||||
|
@ -4,5 +4,10 @@ set -e
|
||||
TOOLS_DIR="$(dirname "${0}")"
|
||||
RUST_TARGET="$("${TOOLS_DIR}/target.sh")"
|
||||
|
||||
if [ "${RUST_LIBC}" = "musl" ] && [ -f "/etc/alpine-release" ]
|
||||
then
|
||||
export RUSTFLAGS="-Ctarget-feature=-crt-static"
|
||||
fi
|
||||
|
||||
export CARGO_BUILD_TARGET="${RUST_TARGET}"
|
||||
exec cargo "${@}"
|
||||
|
@ -5,3 +5,4 @@ REAL_SCRIPT="$(realpath "${0}")"
|
||||
cd "$(dirname "${REAL_SCRIPT}")/../.."
|
||||
|
||||
find hack -type f -name '*.sh' -print0 | xargs -0 shellcheck -x
|
||||
find os/internal -type f -name '*.sh' -print0 | xargs -0 shellcheck -x
|
||||
|
25
hack/dist/apk.sh
vendored
Executable file
25
hack/dist/apk.sh
vendored
Executable file
@ -0,0 +1,25 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
# shellcheck source-path=SCRIPTDIR source=common.sh
|
||||
. "$(dirname "${0}")/common.sh"
|
||||
|
||||
export RUST_LIBC="musl"
|
||||
KRATA_SYSTAR_OPENRC=1 "${KRATA_DIR}/hack/dist/systar.sh"
|
||||
|
||||
KRATA_VERSION="$("${KRATA_DIR}/hack/dist/version.sh")"
|
||||
TARGET_ARCH="$("${KRATA_DIR}/hack/build/arch.sh")"
|
||||
|
||||
cd "${OUTPUT_DIR}"
|
||||
|
||||
rm -f "krata_${KRATA_VERSION}_${TARGET_ARCH}.apk"
|
||||
|
||||
fpm -s tar -t apk \
|
||||
--name krata \
|
||||
--license agpl3 \
|
||||
--version "${KRATA_VERSION}" \
|
||||
--architecture "${TARGET_ARCH}" \
|
||||
--description "Krata Hypervisor" \
|
||||
--url "https://krata.dev" \
|
||||
--maintainer "Edera Team <contact@edera.dev>" \
|
||||
"${OUTPUT_DIR}/system-openrc.tgz"
|
4
hack/dist/bundle.sh
vendored
4
hack/dist/bundle.sh
vendored
@ -9,7 +9,7 @@ then
|
||||
KRATA_KERNEL_BUILD_JOBS="2"
|
||||
fi
|
||||
|
||||
BUNDLE_TAR="${OUTPUT_DIR}/bundle.tgz"
|
||||
BUNDLE_TAR="${OUTPUT_DIR}/bundle-systemd.tgz"
|
||||
rm -f "${BUNDLE_TAR}"
|
||||
BUNDLE_DIR="$(mktemp -d /tmp/krata-bundle.XXXXXXXXXXXXX)"
|
||||
BUNDLE_DIR="${BUNDLE_DIR}/krata"
|
||||
@ -21,7 +21,7 @@ do
|
||||
cp "${KRATA_DIR}/target/${RUST_TARGET}/release/${X}" "${BUNDLE_DIR}/${X}"
|
||||
done
|
||||
./hack/initrd/build.sh
|
||||
if [ "${KRATA_BUNDLE_SKIP_KERNEL_BUILD}" != "1" ]
|
||||
if [ "${KRATA_KERNEL_BUILD_SKIP}" != "1" ]
|
||||
then
|
||||
./hack/kernel/build.sh "-j${KRATA_KERNEL_BUILD_JOBS}"
|
||||
fi
|
||||
|
2
hack/dist/deb.sh
vendored
2
hack/dist/deb.sh
vendored
@ -27,4 +27,4 @@ fpm -s tar -t deb \
|
||||
--deb-systemd "${KRATA_DIR}/resources/systemd/kratanet.service" \
|
||||
--deb-systemd-enable \
|
||||
--deb-systemd-auto-start \
|
||||
"${OUTPUT_DIR}/system.tgz"
|
||||
"${OUTPUT_DIR}/system-systemd.tgz"
|
||||
|
23
hack/dist/systar.sh
vendored
23
hack/dist/systar.sh
vendored
@ -6,11 +6,17 @@ set -e
|
||||
|
||||
"${KRATA_DIR}/hack/dist/bundle.sh"
|
||||
|
||||
SYSTAR="${OUTPUT_DIR}/system.tgz"
|
||||
SYSTAR_VARIANT="systemd"
|
||||
if [ "${KRATA_SYSTAR_OPENRC}" = "1" ]
|
||||
then
|
||||
SYSTAR_VARIANT="openrc"
|
||||
fi
|
||||
|
||||
SYSTAR="${OUTPUT_DIR}/system-${SYSTAR_VARIANT}.tgz"
|
||||
rm -f "${SYSTAR}"
|
||||
SYSTAR_DIR="$(mktemp -d /tmp/krata-systar.XXXXXXXXXXXXX)"
|
||||
cd "${SYSTAR_DIR}"
|
||||
tar xf "${OUTPUT_DIR}/bundle.tgz"
|
||||
tar xf "${OUTPUT_DIR}/bundle-systemd.tgz"
|
||||
|
||||
mkdir sys
|
||||
cd sys
|
||||
@ -19,8 +25,17 @@ mkdir -p usr/bin usr/libexec
|
||||
mv ../krata/kratactl usr/bin
|
||||
mv ../krata/kratanet ../krata/kratad usr/libexec/
|
||||
|
||||
mkdir -p usr/lib/systemd/system
|
||||
mv ../krata/kratad.service ../krata/kratanet.service usr/lib/systemd/system/
|
||||
if [ "${SYSTAR_VARIANT}" = "openrc" ]
|
||||
then
|
||||
mkdir -p etc/init.d
|
||||
cp "${KRATA_DIR}/resources/openrc/kratad" etc/init.d/kratad
|
||||
cp "${KRATA_DIR}/resources/openrc/kratanet" etc/init.d/kratanet
|
||||
chmod +x etc/init.d/kratad
|
||||
chmod +x etc/init.d/kratanet
|
||||
else
|
||||
mkdir -p usr/lib/systemd/system
|
||||
mv ../krata/kratad.service ../krata/kratanet.service usr/lib/systemd/system/
|
||||
fi
|
||||
|
||||
mkdir -p usr/share/krata/guest
|
||||
mv ../krata/kernel ../krata/initrd usr/share/krata/guest
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
REAL_SCRIPT="$(realpath "${0}")"
|
||||
@ -16,5 +16,5 @@ cp "target/${RUST_TARGET}/release/krataguest" "${INITRD_DIR}/init"
|
||||
chmod +x "${INITRD_DIR}/init"
|
||||
cd "${INITRD_DIR}"
|
||||
mkdir -p "${KRATA_DIR}/target/initrd"
|
||||
find . | cpio -R 0:0 --reproducible -o -H newc --quiet > "${KRATA_DIR}/target/initrd/initrd"
|
||||
find . | cpio -R 0:0 --ignore-devno --renumber-inodes -o -H newc --quiet > "${KRATA_DIR}/target/initrd/initrd"
|
||||
rm -rf "${INITRD_DIR}"
|
||||
|
@ -12,6 +12,11 @@ cd "${KRATA_DIR}"
|
||||
. "${KERNEL_DIR}/config.sh"
|
||||
KERNEL_SRC="${KERNEL_DIR}/linux-${KERNEL_VERSION}"
|
||||
|
||||
if [ -z "${KRATA_KERNEL_BUILD_JOBS}" ]
|
||||
then
|
||||
KRATA_KERNEL_BUILD_JOBS="2"
|
||||
fi
|
||||
|
||||
if [ ! -f "${KERNEL_SRC}/Makefile" ]
|
||||
then
|
||||
rm -rf "${KERNEL_SRC}"
|
||||
@ -34,14 +39,14 @@ then
|
||||
fi
|
||||
|
||||
cp "${KERNEL_CONFIG_FILE}" "${KERNEL_SRC}/.config"
|
||||
make -C "${KERNEL_SRC}" ARCH="${TARGET_ARCH}" "${@}" olddefconfig
|
||||
make -C "${KERNEL_SRC}" ARCH="${TARGET_ARCH}" olddefconfig
|
||||
|
||||
if [ "${TARGET_ARCH}" = "x86_64" ]
|
||||
then
|
||||
make -C "${KERNEL_SRC}" ARCH="${TARGET_ARCH}" "${@}" bzImage
|
||||
make -C "${KERNEL_SRC}" ARCH="${TARGET_ARCH}" -j"${KRATA_KERNEL_BUILD_JOBS}" bzImage
|
||||
elif [ "${TARGET_ARCH}" = "arm64" ]
|
||||
then
|
||||
make -C "${KERNEL_SRC}" ARCH="${TARGET_ARCH}" "${@}" Image.gz
|
||||
make -C "${KERNEL_SRC}" ARCH="${TARGET_ARCH}" -j"${KRATA_KERNEL_BUILD_JOBS}" Image.gz
|
||||
fi
|
||||
|
||||
if [ "${TARGET_ARCH}" = "x86_64" ]
|
||||
|
95
hack/os/build.sh
Executable file
95
hack/os/build.sh
Executable file
@ -0,0 +1,95 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
REAL_SCRIPT="$(realpath "${0}")"
|
||||
cd "$(dirname "${REAL_SCRIPT}")/../.."
|
||||
|
||||
./hack/dist/apk.sh
|
||||
KRATA_VERSION="$(./hack/dist/version.sh)"
|
||||
TARGET_ARCH="$(./hack/build/arch.sh)"
|
||||
|
||||
TARGET_DIR="${PWD}/target"
|
||||
TARGET_OS_DIR="${TARGET_DIR}/os"
|
||||
mkdir -p "${TARGET_OS_DIR}"
|
||||
cp "${TARGET_DIR}/dist/krata_${KRATA_VERSION}_${TARGET_ARCH}.apk" "${TARGET_OS_DIR}/krata.apk"
|
||||
docker run --rm --privileged -v "${PWD}:/mnt" -it alpine:latest "/mnt/os/internal/stage1.sh"
|
||||
sudo chown "${USER}:${GROUP}" "${TARGET_OS_DIR}/rootfs.tgz"
|
||||
sudo modprobe nbd
|
||||
|
||||
NBD_DEVICE="$(find /dev -maxdepth 2 -name 'nbd[0-9]*' | while read -r DEVICE
|
||||
do
|
||||
if [ "$(sudo blockdev --getsize64 "${DEVICE}")" = "0" ]
|
||||
then
|
||||
echo "${DEVICE}"
|
||||
break
|
||||
fi
|
||||
done)"
|
||||
|
||||
if [ -z "${NBD_DEVICE}" ]
|
||||
then
|
||||
echo "ERROR: unable to allocate nbd device" > /dev/stderr
|
||||
exit 1
|
||||
fi
|
||||
|
||||
OS_IMAGE="${TARGET_OS_DIR}/krata.qcow2"
|
||||
EFI_PART="${NBD_DEVICE}p1"
|
||||
ROOT_PART="${NBD_DEVICE}p2"
|
||||
ROOT_DIR="${TARGET_OS_DIR}/root"
|
||||
EFI_DIR="${ROOT_DIR}/boot/efi"
|
||||
|
||||
cleanup() {
|
||||
trap '' EXIT HUP INT TERM
|
||||
sudo umount -R "${ROOT_DIR}" > /dev/null 2>&1 || true
|
||||
sudo umount "${EFI_PART}" > /dev/null 2>&1 || true
|
||||
sudo umount "${ROOT_PART}" > /dev/null 2>&1 || true
|
||||
sudo qemu-nbd --disconnect "${NBD_DEVICE}" > /dev/null 2>&1 || true
|
||||
sudo rm -rf "${ROOT_DIR}"
|
||||
}
|
||||
|
||||
rm -f "${OS_IMAGE}"
|
||||
qemu-img create -f qcow2 "${TARGET_OS_DIR}/krata.qcow2" "2G"
|
||||
|
||||
trap cleanup EXIT HUP INT TERM
|
||||
sudo qemu-nbd --connect="${NBD_DEVICE}" --cache=writeback -f qcow2 "${OS_IMAGE}"
|
||||
printf '%s\n' \
|
||||
'label: gpt' \
|
||||
'name=efi,type=U,size=128M,bootable' \
|
||||
'name=system,type=L' | sudo sfdisk "${NBD_DEVICE}"
|
||||
sudo mkfs.fat -F32 -n EFI "${EFI_PART}"
|
||||
sudo mkfs.ext4 -L root -E discard "${ROOT_PART}"
|
||||
|
||||
mkdir -p "${ROOT_DIR}"
|
||||
|
||||
sudo mount -t ext4 "${ROOT_PART}" "${ROOT_DIR}"
|
||||
sudo mkdir -p "${EFI_DIR}"
|
||||
sudo mount -t vfat "${EFI_PART}" "${EFI_DIR}"
|
||||
|
||||
sudo tar xf "${TARGET_OS_DIR}/rootfs.tar" -C "${ROOT_DIR}"
|
||||
ROOT_UUID="$(sudo blkid "${ROOT_PART}" | sed -En 's/.*\bUUID="([^"]+)".*/\1/p')"
|
||||
EFI_UUID="$(sudo blkid "${EFI_PART}" | sed -En 's/.*\bUUID="([^"]+)".*/\1/p')"
|
||||
echo "${ROOT_UUID}"
|
||||
|
||||
sudo mkdir -p "${ROOT_DIR}/proc" "${ROOT_DIR}/dev" "${ROOT_DIR}/sys"
|
||||
sudo mount -t proc none "${ROOT_DIR}/proc"
|
||||
sudo mount --bind /dev "${ROOT_DIR}/dev"
|
||||
sudo mount --make-private "${ROOT_DIR}/dev"
|
||||
sudo mount --bind /sys "${ROOT_DIR}/sys"
|
||||
sudo mount --make-private "${ROOT_DIR}/sys"
|
||||
|
||||
sudo cp "${PWD}/os/internal/stage2.sh" "${ROOT_DIR}/stage2.sh"
|
||||
echo "${ROOT_UUID}" | sudo tee "${ROOT_DIR}/root-uuid" > /dev/null
|
||||
sudo chroot "${ROOT_DIR}" /bin/sh -c "/stage2.sh"
|
||||
sudo rm -f "${ROOT_DIR}/stage2.sh"
|
||||
sudo rm -f "${ROOT_DIR}/root-uuid"
|
||||
|
||||
{
|
||||
echo "# krata fstab"
|
||||
echo "UUID=${ROOT_UUID} / ext4 relatime 0 1"
|
||||
echo "UUID=${EFI_UUID} / vfat rw,relatime,fmask=0133,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro 0 2"
|
||||
} | sudo tee "${ROOT_DIR}/etc/fstab" > /dev/null
|
||||
|
||||
cleanup
|
||||
|
||||
OS_SMALL_IMAGE="${TARGET_OS_DIR}/krata.small.qcow2"
|
||||
qemu-img convert -O qcow2 "${OS_IMAGE}" "${OS_SMALL_IMAGE}"
|
||||
mv -f "${OS_SMALL_IMAGE}" "${OS_IMAGE}"
|
80
os/internal/stage1.sh
Executable file
80
os/internal/stage1.sh
Executable file
@ -0,0 +1,80 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
apk add --update-cache alpine-base \
|
||||
linux-lts linux-firmware-none \
|
||||
mkinitfs dosfstools e2fsprogs \
|
||||
tzdata chrony
|
||||
|
||||
apk add --allow-untrusted /mnt/target/os/krata.apk
|
||||
|
||||
for SERVICE in kratad kratanet
|
||||
do
|
||||
rc-update add "${SERVICE}" default
|
||||
done
|
||||
|
||||
apk add xen xen-hypervisor
|
||||
|
||||
for SERVICE in xenconsoled xenstored
|
||||
do
|
||||
rc-update add "${SERVICE}" default
|
||||
done
|
||||
|
||||
for MODULE in xen-netblock xen-blkback tun tap
|
||||
do
|
||||
echo "${MODULE}" >> /etc/modules
|
||||
done
|
||||
|
||||
cat > /etc/network/interfaces <<-EOF
|
||||
auto eth0
|
||||
iface eth0 inet dhcp
|
||||
EOF
|
||||
|
||||
for SERVICE in networking chronyd
|
||||
do
|
||||
rc-update add "${SERVICE}" default
|
||||
done
|
||||
|
||||
for SERVICE in devfs dmesg mdev hwdrivers cgroups
|
||||
do
|
||||
rc-update add "${SERVICE}" sysinit
|
||||
done
|
||||
|
||||
for SERVICE in modules hwclock swap hostname sysctl bootmisc syslog seedrng
|
||||
do
|
||||
rc-update add "${SERVICE}" boot
|
||||
done
|
||||
|
||||
for SERVICE in killprocs savecache mount-ro
|
||||
do
|
||||
rc-update add "${SERVICE}" shutdown
|
||||
done
|
||||
|
||||
echo 'root:krata' | chpasswd
|
||||
echo 'krata' > /etc/hostname
|
||||
|
||||
{
|
||||
echo '# krata resolver configuration'
|
||||
echo 'nameserver 1.1.1.1'
|
||||
echo 'nameserver 1.0.0.1'
|
||||
echo 'nameserver 2606:4700:4700::1111'
|
||||
echo 'nameserver 2606:4700:4700::1001'
|
||||
} > /etc/resolv.conf
|
||||
|
||||
{
|
||||
echo 'Welcome to krataOS!'
|
||||
echo 'You may now login to the console to manage krata.'
|
||||
} > /etc/issue
|
||||
|
||||
echo > /etc/motd
|
||||
|
||||
ln -s /usr/share/zoneinfo/UTC /etc/localtime
|
||||
|
||||
rm -rf /var/cache/apk/*
|
||||
rm -rf /.dockerenv
|
||||
|
||||
cd /
|
||||
rm -f /mnt/target/os/rootfs.tar
|
||||
tar cf /mnt/target/os/rootfs.tar --numeric-owner \
|
||||
--exclude 'mnt/**' --exclude 'proc/**' \
|
||||
--exclude 'sys/**' --exclude 'dev/**' .
|
19
os/internal/stage2.sh
Executable file
19
os/internal/stage2.sh
Executable file
@ -0,0 +1,19 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
apk add --update-cache grub-efi
|
||||
grub-install --target=x86_64-efi --efi-directory=/boot/efi --no-nvram --skip-fs-probe --bootloader-id=BOOT
|
||||
mv /boot/efi/EFI/BOOT/grubx64.efi /boot/efi/EFI/BOOT/BOOTX64.efi
|
||||
|
||||
ROOT_UUID="$(cat /root-uuid)"
|
||||
|
||||
{
|
||||
echo 'GRUB_CMDLINE_XEN_DEFAULT="dom0_mem=1024M,max:1024M"'
|
||||
echo "GRUB_CMDLINE_LINUX_DEFAULT=\"quiet rootfstype=ext4 root=UUID=${ROOT_UUID} modules=ext4\""
|
||||
echo 'GRUB_DEFAULT="saved"'
|
||||
echo 'GRUB_SAVEDEFAULT="true"'
|
||||
} >> /etc/default/grub
|
||||
|
||||
grub-mkconfig -o /boot/grub/grub.cfg
|
||||
grub-set-default "$(grep ^menuentry /boot/grub/grub.cfg | grep Xen | cut -d \' -f 2 | head -1)"
|
||||
rm -rf /var/cache/apk/*
|
13
resources/openrc/kratad
Normal file
13
resources/openrc/kratad
Normal file
@ -0,0 +1,13 @@
|
||||
#!/sbin/openrc-run
|
||||
description="Krata Control Daemon"
|
||||
command="/usr/libexec/kratad"
|
||||
supervisor="supervise-daemon"
|
||||
output_log="/var/log/kratad.log"
|
||||
error_log="/var/log/kratad.err"
|
||||
|
||||
depend() {
|
||||
use xenconsoled
|
||||
use xenstored
|
||||
}
|
||||
|
||||
export RUST_LOG=info
|
12
resources/openrc/kratanet
Normal file
12
resources/openrc/kratanet
Normal file
@ -0,0 +1,12 @@
|
||||
#!/sbin/openrc-run
|
||||
description="Krata Networking Daemon"
|
||||
command="/usr/libexec/kratanet"
|
||||
supervisor="supervise-daemon"
|
||||
output_log="/var/log/kratanet.log"
|
||||
error_log="/var/log/kratanet.err"
|
||||
|
||||
depend() {
|
||||
use xenstored
|
||||
}
|
||||
|
||||
export RUST_LOG=info
|
@ -4,7 +4,6 @@ Description=Krata Control Daemon
|
||||
[Service]
|
||||
Restart=on-failure
|
||||
Type=simple
|
||||
ExecStartPre=/bin/mkdir -p /var/lib/krata
|
||||
ExecStart=/usr/libexec/kratad -l unix:///var/lib/krata/daemon.socket
|
||||
Environment=RUST_LOG=info
|
||||
User=root
|
||||
|
Loading…
Reference in New Issue
Block a user