Skip to content

Commit 4429162

Browse files
authored
Retrying compartmentless containers (#1608)
* changes in internal event handling * fixing namespace tests compilation * rustfmt + PR suggestions * suggestions from PR, removing unnused vector * removing unnecessary create uuid * reverting Cargo.lock * suggestions from PR
1 parent 604d90d commit 4429162

File tree

11 files changed

+294
-138
lines changed

11 files changed

+294
-138
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/admin.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ async fn handle_jemalloc_pprof_heapgen(
436436
.expect("builder with known status code should not fail"))
437437
}
438438

439-
#[cfg(not(feature = "jemalloc"))]
439+
#[cfg(all(target_os = "linux", not(feature = "jemalloc")))]
440440
async fn handle_jemalloc_pprof_heapgen(
441441
_req: Request<Incoming>,
442442
) -> anyhow::Result<Response<Full<Bytes>>> {

src/inpod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ pub enum Error {
2424
ProtocolError(String),
2525
#[error("announce error: {0}")]
2626
AnnounceError(String),
27+
#[error("namespace error: {0}")]
28+
NamespaceError(String),
2729
}
2830

2931
#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize)]

src/inpod/windows.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ mod workloadmanager;
3434
#[cfg(any(test, feature = "testing"))]
3535
pub mod test_helpers;
3636

37-
38-
#[derive(Debug)]
37+
#[derive(Debug, Clone)]
3938
pub struct WorkloadData {
4039
workload_uid: WorkloadUid,
4140
workload_info: Option<WorkloadInfo>,

src/inpod/windows/admin.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use std::sync::RwLock;
2424
#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
2525
pub enum State {
2626
Pending,
27+
WaitingCompartment,
2728
Up,
2829
}
2930

@@ -63,6 +64,7 @@ pub struct WorkloadManagerAdminHandler {
6364
impl WorkloadManagerAdminHandler {
6465
pub fn proxy_pending(
6566
&self,
67+
workload_state: State,
6668
uid: &crate::inpod::WorkloadUid,
6769
workload_info: &WorkloadInfo,
6870
) {
@@ -71,13 +73,13 @@ impl WorkloadManagerAdminHandler {
7173
// don't increment count here, as it is only for up and down. see comment in count.
7274
match state.get_mut(uid) {
7375
Some(key) => {
74-
key.state = State::Pending;
76+
key.state = workload_state;
7577
}
7678
None => {
7779
state.insert(
7880
uid.clone(),
7981
ProxyState {
80-
state: State::Pending,
82+
state: workload_state,
8183
connections: None,
8284
count: 0,
8385
info: workload_info.clone(),

src/inpod/windows/config.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
16-
1715
use crate::inpod::windows::namespace::InpodNamespace;
1816
use crate::proxy::DefaultSocketFactory;
1917
use crate::{config, socket};
@@ -68,8 +66,8 @@ impl InPodSocketFactory {
6866
fn from_cfg(inner: DefaultSocketFactory, _: &InPodConfig, netns: InpodNamespace) -> Self {
6967
Self::new(inner, netns)
7068
}
71-
fn new(inner: DefaultSocketFactory,netns: InpodNamespace) -> Self {
72-
Self {inner, netns }
69+
fn new(inner: DefaultSocketFactory, netns: InpodNamespace) -> Self {
70+
Self { inner, netns }
7371
}
7472

7573
fn run_in_ns<S, F: FnOnce() -> std::io::Result<S>>(&self, f: F) -> std::io::Result<S> {
@@ -96,7 +94,7 @@ impl crate::proxy::SocketFactory for InPodSocketFactory {
9694
}
9795

9896
fn tcp_bind(&self, addr: std::net::SocketAddr) -> std::io::Result<socket::Listener> {
99-
let std_sock = self.configure( || std::net::TcpListener::bind(addr))?;
97+
let std_sock = self.configure(|| std::net::TcpListener::bind(addr))?;
10098
std_sock.set_nonblocking(true)?;
10199
tokio::net::TcpListener::from_std(std_sock).map(socket::Listener::new)
102100
}

src/inpod/windows/namespace.rs

Lines changed: 33 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,16 @@
1-
use std::sync::Arc;
21
use tracing::warn;
32
use windows::Win32::NetworkManagement::IpHelper::{
43
GetCurrentThreadCompartmentId, SetCurrentThreadCompartmentId,
54
};
65

76
#[derive(Debug, Clone, Eq, Hash, PartialEq)]
8-
pub struct Namespace {
9-
pub id: u32,
10-
pub guid: String,
11-
}
12-
13-
#[derive(Clone, Debug)]
147
pub struct InpodNamespace {
15-
inner: Arc<NetnsInner>,
16-
}
17-
18-
#[derive(Debug, Eq, PartialEq)]
19-
struct NetnsInner {
20-
current_namespace: u32,
21-
workload_namespace: Namespace,
8+
// On Windows every network namespace is based
9+
// on a network compartment ID. This is the reference
10+
// we need when we want to create sockets inside
11+
// a network namespace or change IP stack configuration.
12+
pub compartment_id: u32,
13+
pub namespace_guid: String,
2214
}
2315

2416
impl InpodNamespace {
@@ -32,56 +24,50 @@ impl InpodNamespace {
3224
}
3325

3426
pub fn capable() -> std::io::Result<()> {
35-
// set the netns to our current netns. This is intended to be a no-op,
36-
// and meant to be used as a test, so we can fail early if we can't set the netns
37-
let curr_namespace = Self::current()?;
38-
setns(curr_namespace)
27+
// Set the network compartment to the host compartment. This is intended to be a no-op,
28+
// and meant to be used as a test, so we can fail early if we can't set the netns.
29+
set_compartment(1)
3930
}
4031

41-
pub fn new(cur_namespace: u32, workload_namespace: String) -> std::io::Result<Self> {
32+
pub fn new(workload_namespace: String) -> std::io::Result<Self> {
4233
let ns = hcn::get_namespace(&workload_namespace);
4334
match ns {
4435
Err(e) => {
4536
warn!("Failed to get namespace: {}", e);
4637
Err(std::io::Error::last_os_error())
4738
}
4839
Ok(ns) => Ok(InpodNamespace {
49-
inner: Arc::new(NetnsInner {
50-
current_namespace: cur_namespace,
51-
workload_namespace: Namespace {
52-
id: ns
53-
.namespace_id
54-
.expect("There must always be a namespace id"),
55-
guid: ns.id,
56-
},
57-
}),
40+
compartment_id: ns
41+
.namespace_id
42+
// Compartment ID 0 means undefined compartment ID.
43+
// At the moment the JSON serialization ommits the field
44+
// if it is set to 0. This happens when the compartment
45+
// for the container is not yet available.
46+
.unwrap_or(0),
47+
namespace_guid: ns.id,
5848
}),
5949
}
6050
}
6151

62-
pub fn workload_namespace(&self) -> u32 {
63-
self.inner.workload_namespace.id
64-
}
65-
66-
// Useful for logging / debugging
67-
pub fn workload_namespace_guid(&self) -> String {
68-
self.inner.workload_namespace.guid.clone()
69-
}
70-
7152
pub fn run<F, T>(&self, f: F) -> std::io::Result<T>
7253
where
7354
F: FnOnce() -> T,
7455
{
75-
setns(self.inner.workload_namespace.id)?;
56+
set_compartment(self.compartment_id)?;
7657
let ret = f();
77-
setns(self.inner.current_namespace).expect("this must never fail");
58+
// The Windows API defines the network compartment ID 1 as the
59+
// comapartment backing up the host network namespace.
60+
set_compartment(1).expect("failed to switch to host namespace");
7861
Ok(ret)
7962
}
8063
}
8164

82-
// hop into a namespace
83-
fn setns(namespace: u32) -> std::io::Result<()> {
84-
let error = unsafe { SetCurrentThreadCompartmentId(namespace) };
65+
// Hop into a network compartment
66+
fn set_compartment(compartment_id: u32) -> std::io::Result<()> {
67+
if compartment_id == 0 {
68+
return Err(std::io::Error::other("undefined compartment ID"));
69+
}
70+
let error = unsafe { SetCurrentThreadCompartmentId(compartment_id) };
8571
if error.0 != 0 {
8672
return Err(std::io::Error::from_raw_os_error(error.0 as i32));
8773
}
@@ -90,13 +76,13 @@ fn setns(namespace: u32) -> std::io::Result<()> {
9076

9177
#[cfg(test)]
9278
mod tests {
93-
use hcn::schema::HostComputeQuery;
9479
use hcn::api;
80+
use hcn::schema::HostComputeQuery;
9581
use windows::core::GUID;
9682

9783
use super::*;
9884

99-
fn new_namespace() -> Namespace {
85+
fn new_namespace() -> InpodNamespace {
10086
let api_namespace = hcn::schema::HostComputeNamespace::default();
10187

10288
let api_namespace = serde_json::to_string(&api_namespace).unwrap();
@@ -111,9 +97,9 @@ mod tests {
11197
let api_namespace: hcn::schema::HostComputeNamespace =
11298
serde_json::from_str(&api_namespace).unwrap();
11399

114-
Namespace {
115-
id: api_namespace.namespace_id.unwrap(),
116-
guid: api_namespace.id,
100+
InpodNamespace {
101+
compartment_id: api_namespace.namespace_id.unwrap(),
102+
namespace_guid: api_namespace.id,
117103
}
118104
}
119105

src/inpod/windows/protocol.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
use crate::drain::DrainWatcher;
2-
use crate::inpod::windows::{WorkloadData, WorkloadMessage, WorkloadUid};
32
use crate::inpod::istio::zds::{
4-
self, workload_request::Payload, Ack, Version, WorkloadRequest, WorkloadResponse, ZdsHello,
3+
self, Ack, Version, WorkloadRequest, WorkloadResponse, ZdsHello, workload_request::Payload,
54
};
5+
use crate::inpod::windows::{WorkloadData, WorkloadMessage, WorkloadUid};
66
use prost::Message;
7-
use tracing::info;
87
use std::io::{IoSlice, IoSliceMut};
98
use tokio::net::windows::named_pipe::*;
10-
9+
use tracing::info;
1110

1211
pub struct WorkloadStreamProcessor {
1312
client: NamedPipeClient,

0 commit comments

Comments
 (0)