mirror of
https://github.com/michael-yuji/xc.git
synced 2026-03-17 22:35:43 +01:00
allow container to be reference by jid
This commit is contained in:
@@ -25,12 +25,14 @@
|
||||
use ipcidr::IpCidr;
|
||||
use std::io::Write;
|
||||
use std::net::IpAddr;
|
||||
use std::process::Command;
|
||||
use std::process::{Command, Stdio};
|
||||
|
||||
pub const PFCTL_CMD: &str = crate::env_or_default!("XC_PFCTL_CMD", "/sbin/pfctl");
|
||||
|
||||
pub fn is_pf_enabled() -> Result<bool, std::io::Error> {
|
||||
Command::new(PFCTL_CMD)
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.arg("-s")
|
||||
.arg("Running")
|
||||
.status()
|
||||
|
||||
@@ -189,7 +189,7 @@ impl Container {
|
||||
} else {
|
||||
proto = proto.param("vnet", Value::Int(1));
|
||||
for alloc in self.ip_alloc.iter() {
|
||||
if let Some(network) = &alloc.network {
|
||||
if let Some(_network) = &alloc.network {
|
||||
let (epair_a, epair_b) = undo.create_epair()?;
|
||||
undo.iface_up(epair_a.to_owned())?;
|
||||
undo.iface_up(epair_b.to_owned())?;
|
||||
|
||||
@@ -101,6 +101,20 @@ impl InstantiateBlueprint {
|
||||
ipc::packet::codec::Maybe::Some(x) => Some(EventFdNotify::from_fd(x.as_raw_fd())),
|
||||
};
|
||||
|
||||
for (name, env_spec) in config.envs.iter() {
|
||||
if env_spec.required && !request.envs.contains_key(&name.to_string()) {
|
||||
let extra_info = env_spec
|
||||
.description
|
||||
.as_ref()
|
||||
.map(|d| format!(" - {d}"))
|
||||
.unwrap_or_default();
|
||||
precondition_failure!(
|
||||
ENOENT,
|
||||
"missing required environment variable: {name}{extra_info}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let Some(entry_point) = config.entry_points.get(&request.entry_point) else {
|
||||
precondition_failure!(ENOENT, "requested entry point not found: {}", request.entry_point);
|
||||
};
|
||||
|
||||
@@ -213,6 +213,15 @@ async fn instantiate(
|
||||
// let id = Uuid::new_v4().to_string();
|
||||
let id = gen_id();
|
||||
|
||||
if request
|
||||
.name
|
||||
.as_ref()
|
||||
.and_then(|n| n.parse::<isize>().ok())
|
||||
.is_some()
|
||||
{
|
||||
return ipc_err(EINVAL, "container name cannot be integer literal");
|
||||
}
|
||||
|
||||
let row = {
|
||||
let ctx = context.read().await;
|
||||
let dlctx = ctx.image_manager.read().await;
|
||||
@@ -526,27 +535,28 @@ async fn show_container(
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct DestroyContainerRequest {
|
||||
pub struct KillContainerRequest {
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct DestroyContainerResponse {}
|
||||
pub struct KillContainerResponse {}
|
||||
|
||||
#[ipc_method(method = "destroy_container")]
|
||||
async fn destroy_container(
|
||||
#[ipc_method(method = "kill_container")]
|
||||
async fn kill_container(
|
||||
context: Arc<RwLock<ServerContext>>,
|
||||
local_context: &mut ConnectionContext<Variables>,
|
||||
request: DestroyContainerRequest,
|
||||
) -> GenericResult<DestroyContainerResponse> {
|
||||
request: KillContainerRequest,
|
||||
) -> GenericResult<KillContainerResponse> {
|
||||
let mut context = context.write().await;
|
||||
if let Some(id) = context.alias_map.get(&request.name).cloned() {
|
||||
_ = context.terminate(&id).await;
|
||||
Ok(DestroyContainerResponse {})
|
||||
Ok(KillContainerResponse {})
|
||||
} else {
|
||||
enoent(format!("no such container: {}", request.name).as_str())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct DoRdr {
|
||||
pub name: String,
|
||||
@@ -564,6 +574,25 @@ async fn rdr_container(
|
||||
Ok(request)
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct ContainerRdrList {
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[ipc_method(method = "list_site_rdr")]
|
||||
async fn list_site_rdr(
|
||||
context: Arc<RwLock<ServerContext>>,
|
||||
local_context: &mut ConnectionContext<Variables>,
|
||||
request: ContainerRdrList,
|
||||
) -> GenericResult<Vec<PortRedirection>> {
|
||||
let context = context.read().await;
|
||||
if let Some(id) = context.alias_map.get(&request.name) {
|
||||
Ok(context.port_forward_table.all_rules_with_id(id))
|
||||
} else {
|
||||
enoent(format!("no such container: {}", request.name).as_str())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(FromPacket)]
|
||||
pub struct FdImport {
|
||||
pub fd: Fd,
|
||||
@@ -695,17 +724,17 @@ async fn commit_container(
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct ReplaceMetaRequest {
|
||||
pub struct SetConfigRequest {
|
||||
pub name: String,
|
||||
pub tag: String,
|
||||
pub meta: xc::models::jail_image::JailConfig,
|
||||
pub config: xc::models::jail_image::JailConfig,
|
||||
}
|
||||
|
||||
#[ipc_method(method = "replace_meta")]
|
||||
async fn replace_meta(
|
||||
context: Arc<RwLock<ServerContext>>,
|
||||
local_context: &mut ConnectionContext<Variables>,
|
||||
request: ReplaceMetaRequest,
|
||||
request: SetConfigRequest,
|
||||
) -> GenericResult<xc::models::jail_image::JailImage> {
|
||||
let ctx = context.read().await;
|
||||
let dlctx = ctx.image_manager.read().await;
|
||||
@@ -714,7 +743,7 @@ async fn replace_meta(
|
||||
.await
|
||||
.unwrap();
|
||||
let mut manifest = record.manifest;
|
||||
manifest.set_config(&request.meta);
|
||||
manifest.set_config(&request.config);
|
||||
dlctx
|
||||
.register_and_tag_manifest(&request.name, &request.tag, &manifest)
|
||||
.await
|
||||
@@ -860,7 +889,7 @@ pub(crate) async fn register_to_service(
|
||||
service.register(create_network).await;
|
||||
service.register(list_networks).await;
|
||||
service.register(show_container).await;
|
||||
service.register(destroy_container).await;
|
||||
service.register(kill_container).await;
|
||||
service.register(list_containers).await;
|
||||
service.register(login_registry).await;
|
||||
service.register(commit_container).await;
|
||||
|
||||
@@ -31,6 +31,7 @@ mod port;
|
||||
mod registry;
|
||||
mod site;
|
||||
mod task;
|
||||
mod util;
|
||||
|
||||
pub mod ipc;
|
||||
use config_manager::ConfigManager;
|
||||
|
||||
@@ -29,6 +29,7 @@ use std::ffi::OsString;
|
||||
use std::os::fd::RawFd;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::watch::Receiver;
|
||||
use tracing::info;
|
||||
use xc::config::XcConfig;
|
||||
use xc::container::effect::UndoStack;
|
||||
use xc::container::{Container, ContainerManifest};
|
||||
@@ -110,7 +111,6 @@ impl Site {
|
||||
|
||||
pub fn kill_conatiner(&mut self) -> anyhow::Result<()> {
|
||||
use freebsd::nix::sys::event::{kevent_ts, EventFilter, EventFlag, FilterFlag, KEvent};
|
||||
use tracing::error;
|
||||
let event = KEvent::new(
|
||||
2,
|
||||
EventFilter::EVFILT_USER,
|
||||
@@ -119,7 +119,7 @@ impl Site {
|
||||
0 as freebsd::libc::intptr_t,
|
||||
0 as freebsd::libc::intptr_t,
|
||||
);
|
||||
error!("killing container");
|
||||
info!("killing container");
|
||||
_ = kevent_ts(self.ctl_channel.unwrap(), &[event], &mut [], None);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
104
xcd/src/util.rs
Normal file
104
xcd/src/util.rs
Normal file
@@ -0,0 +1,104 @@
|
||||
// Copyright (c) 2023 Yan Ka, Chiu.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions, and the following disclaimer,
|
||||
// without modification, immediately at the beginning of the file.
|
||||
// 2. The name of the author may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
// SUCH DAMAGE.
|
||||
use std::borrow::Borrow;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::hash::Hash;
|
||||
|
||||
pub struct TwoWayMap<K, V> {
|
||||
reverse_map: HashMap<V, HashSet<K>>,
|
||||
main_map: HashMap<K, V>,
|
||||
}
|
||||
|
||||
impl<K, V> Default for TwoWayMap<K, V> {
|
||||
fn default() -> TwoWayMap<K, V> {
|
||||
TwoWayMap {
|
||||
reverse_map: HashMap::new(),
|
||||
main_map: HashMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Clone + Hash + Eq, V: Clone + Hash + Eq> TwoWayMap<K, V> {
|
||||
pub fn new() -> TwoWayMap<K, V> {
|
||||
TwoWayMap {
|
||||
reverse_map: HashMap::new(),
|
||||
main_map: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, key: K, value: V) {
|
||||
self.main_map.insert(key.clone(), value.clone());
|
||||
match self.reverse_map.get_mut(&value) {
|
||||
Some(vec) => {
|
||||
vec.insert(key);
|
||||
}
|
||||
None => {
|
||||
self.reverse_map
|
||||
.insert(value.clone(), HashSet::from_iter([key]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get<Q: Eq + Hash + ?Sized>(&self, key: &Q) -> Option<&V>
|
||||
where
|
||||
K: Borrow<Q>,
|
||||
{
|
||||
self.main_map.get(key)
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn contains_key<Q: Eq + Hash + ?Sized>(&self, key: &Q) -> Option<&V>
|
||||
where
|
||||
K: Borrow<Q>,
|
||||
{
|
||||
self.main_map.get(key)
|
||||
}
|
||||
|
||||
pub fn remove_all_referenced<Q>(&mut self, value: &Q) -> Option<HashSet<K>>
|
||||
where
|
||||
V: Borrow<Q>,
|
||||
Q: Eq + Hash + ?Sized,
|
||||
{
|
||||
let keys = self.reverse_map.remove(value)?;
|
||||
for key in keys.iter() {
|
||||
self.main_map.remove(key);
|
||||
}
|
||||
Some(keys)
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn remove<Q>(&mut self, key: &Q) -> Option<V>
|
||||
where
|
||||
K: Borrow<Q>,
|
||||
Q: Eq + Hash + ?Sized,
|
||||
{
|
||||
let value = self.main_map.remove(key);
|
||||
if let Some(value) = &value {
|
||||
if let Some(keys) = self.reverse_map.get_mut(value) {
|
||||
keys.remove(key);
|
||||
}
|
||||
}
|
||||
value
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user