-
Notifications
You must be signed in to change notification settings - Fork 134
feat(axvisor): axum management HTTP control plane with VM lifecycle API #1909
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
aptacc2421
wants to merge
42
commits into
rcore-os:dev
Choose a base branch
from
aptacc2421:feat/axvisor-pr1-axum-infra
base: dev
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
42 commits
Select commit
Hold shift + click to select a range
57b8bcd
feat(axvisor): VM start/stop 控制 API(axum 异步 stop + lifecycle 自测)
aptacc2421 40d0115
fix(axvisor): 控制测试 guest 改用 registry 预置镜像,CI 可复现
aptacc2421 5d04171
fix(axvisor): start-on-stopped 显式 409,stop 响应标注 async
aptacc2421 d061561
feat(net): 启用 ArceOS 网络栈、SMP=2 与 vCPU 核隔离
aptacc2421 0ae812d
feat(axvisor): 新增 axum 只读 HTTP 管理 API(GET /api/vms)
aptacc2421 ab1ca7c
fix(axvisor): explicit tower util feature and rename http::axum to se…
aptacc2421 36c84dc
test(axvm): add deterministic vCPU affinity mapping tests
aptacc2421 c044e2a
docs(axvisor): drop stale plan-doc reference from http-axum feature c…
aptacc2421 bc06093
docs(axvisor): 新增管理 HTTP 控制面 QEMU hostfwd + curl 操作指南
aptacc2421 9e3da81
docs(axvisor): 完善 HTTP 控制面 quickstart 可复现性与 NIC 排查
aptacc2421 fd8f719
feat(axvisor): 运行时 create/delete VM 控制 API(受限 create)
aptacc2421 cb58b92
fix(axvisor): dynamic 测试 fail_regex 补抓 control lifecycle FAILED
aptacc2421 7d4fca9
fix(axvm): vcpu_run 日志改用 host::cpu::current_id 避免裸 ax_hal 引用
aptacc2421 a29d45c
fix(axvisor): readonly HTTP 自测单哨兵 + x86_64 用例可发现
aptacc2421 5b6e3fc
feat(axvisor): QEMU hostfwd host→guest TCP 集成测试(http-axum-tcp)
aptacc2421 18dfb51
fix(axvisor): 移除误带入 PR1 的 web-ui 骨架并清理 host_probe 导入
aptacc2421 e71f62b
feat(axvisor): 管理 HTTP 控制面认证 + 默认 loopback 绑定 + 真实 TCP 拒绝访问回归
aptacc2421 b357c43
refactor(axvisor): 移除内核内 self-test,改用 host probe + fs Linux guest
aptacc2421 c763300
refactor(axbuild): host_http_probe 场景 Rust 代码改为 case 目录 probe.sh 脚本
aptacc2421 fd59db9
docs(axvisor): 将 HTTP 控制面 quickstart 文档移出仓库跟踪,保留本地副本
aptacc2421 9203a3b
test(axvisor): 归并 HTTP 测试目录为共享 wrapper 并按 fs 注册 Linux guest
aptacc2421 985d8be
chore(repo): rebase 后重新生成 Cargo.lock 补齐 axvisor 可选依赖
aptacc2421 cfbbc13
chore(axbuild): cargo fmt 修复 host probe 守卫与 qemu runner 排版
aptacc2421 1bb4a8d
feat(axvisor): bridge the guest L2 switch to a host NIC uplink
aptacc2421 34d46e4
merge upstream dev into axvisor-pr1-axum-infra
aptacc2421 c39a642
fix(axruntime): cfg-split net device collection to satisfy clippy
aptacc2421 aab2a56
refactor(axvisor): remove net-uplink from the HTTP control-plane PR
aptacc2421 46ff4b0
merge upstream dev into axvisor-pr1-axum-infra
aptacc2421 1e86e2d
refactor(axvisor): converge HTTP control-plane testing per review
aptacc2421 f4f03f5
chore(axbuild): rustfmt http_probe and case types
aptacc2421 6401567
fix(axbuild): preserve real serial failures over host probe verdict
aptacc2421 5f180f4
refactor(axbuild): drop probe SIGKILL, require QEMU + probe both pass
aptacc2421 dbf00f2
fix(axbuild): keep QMP quit connection open so QEMU exits after a probe
aptacc2421 00d7836
feat(axbuild): extend host probe to the full management-plane contract
aptacc2421 e83afba
refactor(axbuild): move HTTP probe config and guard to the axvisor layer
aptacc2421 9b9643c
test(axbuild): cover the axvisor host_http_probe toml parsing path
aptacc2421 428c4cd
fix(axvm): wait for vCPU entry before accepting request-stop
aptacc2421 061039f
chore(ci): retrigger CI run on branch head
aptacc2421 ca6849b
chore(ci): retrigger CI run on branch head (timer-stress flake)
aptacc2421 6754937
refactor(axbuild): move axvisor HTTP probe contract into the case asset
aptacc2421 182e514
fix(axvisor): retry probe request on boot-window read timeout
aptacc2421 4300010
chore(ci): retrigger CI run on branch head
aptacc2421 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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,63 @@ | ||
| //! Bearer-token access control for the management HTTP control plane. | ||
| //! | ||
| //! Mutating routes (`create`/`delete`/`start`/`stop`) require an | ||
| //! `Authorization: Bearer <token>` header matching the build-time token. The | ||
| //! token is baked into the image at | ||
| //! build time from the `[env] AXVM_HTTP_TOKEN` build-config variable — the same | ||
| //! `option_env!` mechanism `crate::shell::command::base` uses for `AX_ARCH`. | ||
| //! | ||
| //! The control plane is **deny-by-default**: if `AXVM_HTTP_TOKEN` is unset, | ||
| //! every protected route returns `401` and cannot be used. There is no | ||
| //! "fall back to allowing writes without a token" path — a build that forgets | ||
| //! the token fails its tests instead of silently exposing EL2 state changes. | ||
| //! Read-only routes (`GET`) are intentionally left open; they expose no state | ||
| //! mutation, and the default loopback bind (see [`crate::http::server`]) keeps | ||
| //! them off the management network unless an operator explicitly opts in. | ||
|
|
||
| use axum::{ | ||
| extract::FromRequestParts, | ||
| http::{ | ||
| StatusCode, | ||
| header::{AUTHORIZATION, HeaderValue}, | ||
| }, | ||
| }; | ||
|
|
||
| /// A request that carries a matching `Authorization: Bearer <token>` header. | ||
| /// | ||
| /// Attach as the first extractor on a mutating handler. Rejects the request | ||
| /// with `401 Unauthorized` when no token was baked into the image | ||
| /// (`AXVM_HTTP_TOKEN` unset) or the header is missing / does not match. | ||
| pub struct ApiToken; | ||
|
|
||
| impl ApiToken { | ||
| /// Whether the given header value carries the required bearer token. | ||
| fn header_matches(value: &HeaderValue) -> bool { | ||
| let Some(token) = option_env!("AXVM_HTTP_TOKEN") else { | ||
| return false; | ||
| }; | ||
| value.to_str().ok().is_some_and(|value| { | ||
| value | ||
| .strip_prefix("Bearer ") | ||
| .is_some_and(|rest| rest == token) | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| impl<S: Sync> FromRequestParts<S> for ApiToken { | ||
| type Rejection = StatusCode; | ||
|
|
||
| async fn from_request_parts( | ||
| parts: &mut axum::http::request::Parts, | ||
| _state: &S, | ||
| ) -> Result<Self, Self::Rejection> { | ||
| let authorized = parts | ||
| .headers | ||
| .get(AUTHORIZATION) | ||
| .is_some_and(Self::header_matches); | ||
| if authorized { | ||
| Ok(ApiToken) | ||
| } else { | ||
| Err(StatusCode::UNAUTHORIZED) | ||
| } | ||
| } | ||
| } |
This file contains hidden or 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,25 @@ | ||
| //! Management HTTP control plane. | ||
| //! | ||
| //! Served by an axum `Router` running on a tokio current-thread runtime | ||
| //! (see [`server`]). The VM list/detail and start/stop lifecycle routes live | ||
| //! in [`vm`]. JSON is built with `serde_json`. | ||
| //! | ||
| //! Security boundary: mutating routes require a build-time bearer token | ||
| //! ([`auth`]); the server binds `127.0.0.1:8080` by default and only binds | ||
| //! wider when `[env] AXVM_HTTP_BIND` opts in. See the per-module docs. | ||
| //! | ||
| //! This whole module is only compiled under the `http-axum` feature, which is | ||
| //! off by default. The hand-rolled HTTP/1.0 pilot was intentionally not | ||
| //! carried forward. | ||
|
|
||
| pub mod auth; | ||
| pub mod server; | ||
| pub mod vm; | ||
|
|
||
| /// Blocking entry point for the management HTTP server. | ||
| /// | ||
| /// Spawned on its own task (see `crate::main`); builds the tokio runtime and | ||
| /// serves until the hypervisor shuts down. | ||
| pub fn serve() { | ||
| server::serve(); | ||
| } |
This file contains hidden or 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,67 @@ | ||
| //! axum-based management HTTP server (`http-axum` feature). | ||
| //! | ||
| //! Runs an axum `Router` on a tokio current-thread runtime and serves the | ||
| //! management API. Routes and JSON fields mirror the hand-rolled pilot's API, | ||
| //! but dispatch and JSON construction are delegated to axum + serde_json. | ||
| //! | ||
| //! ```text | ||
| //! GET /api/vms → 200, JSON array (summary form) | ||
| //! GET /api/vms/{id} → 200, JSON detail (with vcpu_states) | 404 | ||
| //! POST /api/vms/create → 200 {"id":N} | 400 | 409 | 500 (body {"toml": "..."}) | ||
| //! DELETE /api/vms/{id} → 204 | 404 | 500 | ||
| //! POST /api/vms/{id}/start → 200 {"ok":true,"status":...} | 404 | 409 | 503 | ||
| //! POST /api/vms/{id}/stop → 200 {"ok":true,"status":...} | 404 | 409 | 503 | ||
| //! ``` | ||
| //! | ||
| //! Mutating routes (`create`/`delete`/`start`/`stop`) require | ||
| //! `Authorization: Bearer <token>` with the build-time `[env] AXVM_HTTP_TOKEN`; | ||
| //! see [`crate::http::auth`]. GET routes are open. The listener binds | ||
| //! [`bind_addr`], loopback by default. | ||
| //! | ||
| //! The tokio reactor is initialized with `enable_io()` only (no time driver), | ||
| //! which needs only epoll, so no `timerfd` syscall is required. | ||
|
|
||
| use axum::{Router, routing::get, routing::post}; | ||
|
|
||
| use crate::http::vm; | ||
|
|
||
| /// Assemble the management routes. | ||
| pub fn router() -> Router { | ||
| Router::new() | ||
| .route("/api/vms", get(vm::list_vms)) | ||
| .route("/api/vms/{id}", get(vm::vm_detail).delete(vm::vm_delete)) | ||
| .route("/api/vms/create", post(vm::vm_create)) | ||
| .route("/api/vms/{id}/start", post(vm::vm_start)) | ||
| .route("/api/vms/{id}/stop", post(vm::vm_stop)) | ||
| } | ||
|
|
||
| /// Bind address for the management HTTP server. | ||
| /// | ||
| /// Defaults to loopback (`127.0.0.1:8080`) so a stock `http-axum` build is not | ||
| /// reachable from the management network. Test/dev flows that need QEMU | ||
| /// hostfwd to reach the in-guest listener must opt in to all interfaces by | ||
| /// setting `[env] AXVM_HTTP_BIND = "0.0.0.0:8080"` in their build config; the | ||
| /// mutating routes still require the bearer token regardless of the bind. | ||
| fn bind_addr() -> &'static str { | ||
| option_env!("AXVM_HTTP_BIND").unwrap_or("127.0.0.1:8080") | ||
| } | ||
|
|
||
| /// Blocking serve: build a tokio current-thread runtime and hand it to axum. | ||
| /// | ||
| /// `main` spawns this on its own task via `std::thread::spawn(|| http::serve())`; | ||
| /// the runtime is built here. Only the IO driver is enabled — the epoll | ||
| /// reactor suffices for `axum::serve`; a time driver would need `timerfd`. | ||
| pub fn serve() { | ||
| let rt = tokio::runtime::Builder::new_current_thread() | ||
| .enable_io() | ||
| .build() | ||
| .expect("failed to build tokio runtime"); | ||
| rt.block_on(async { | ||
| let bind = bind_addr(); | ||
| let listener = tokio::net::TcpListener::bind(bind) | ||
| .await | ||
| .expect("failed to bind management HTTP server"); | ||
| info!("management HTTP server (axum) listening on {bind}"); | ||
| axum::serve(listener, router()).await.expect("server error"); | ||
| }); | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.