mirror of
https://gitlab.com/veilid/veilid.git
synced 2025-03-30 17:48:03 -04:00
machine state work
This commit is contained in:
parent
693b9d185b
commit
3cb880c0bf
@ -139,7 +139,7 @@ impl MachineRegistryInner {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
break Ok(machine_state_id.0);
|
break Ok(machine_state_id.external_id());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,60 +1,69 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||||
struct MachineStateInner {
|
pub enum MachineOrigin {
|
||||||
/// The template generating this machine
|
InitialConfig,
|
||||||
generating_template: Option<TemplateStateId>,
|
Direct,
|
||||||
|
Template(TemplateStateId),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct MachineStateFields {
|
||||||
/// The current network interfaces definition
|
/// The current network interfaces definition
|
||||||
interfaces: HashMap<String, MachineStateInterface>,
|
interfaces: imbl::HashMap<Arc<String>, MachineStateInterface>,
|
||||||
/// Capabilities to disable on this machine
|
/// Capabilities to disable on this machine
|
||||||
disable_capabilities: Vec<String>,
|
disable_capabilities: imbl::Vector<String>,
|
||||||
/// If this machine is a bootstrap
|
/// If this machine is a bootstrap
|
||||||
bootstrap: bool,
|
bootstrap: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct MachineStateInterface {
|
pub struct MachineStateInterface {
|
||||||
/// The network this interface belongs to
|
/// The network this interface belongs to
|
||||||
pub network_id: Option<NetworkStateId>,
|
pub network_id: Option<NetworkStateId>,
|
||||||
/// The veilid NetworkInterface state
|
/// The veilid NetworkInterface state
|
||||||
pub network_interface: NetworkInterface,
|
pub network_interface: Arc<NetworkInterface>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct MachineStateUnlockedInner {
|
struct MachineStateImmutable {
|
||||||
/// The id of this machine
|
/// The id of this machine
|
||||||
id: MachineStateId,
|
id: MachineStateId,
|
||||||
/// The name of this machine if it is named
|
/// The name of this machine if it is named
|
||||||
opt_name: Option<String>,
|
opt_name: Option<String>,
|
||||||
|
/// Where this machine came for housekeeping purposes
|
||||||
|
origin: MachineOrigin,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct MachineState {
|
pub struct MachineState {
|
||||||
xxx convert to immutable state
|
immutable: Arc<MachineStateImmutable>,
|
||||||
unlocked_inner: Arc<MachineStateUnlockedInner>,
|
fields: Arc<MachineStateFields>,
|
||||||
inner: Arc<Mutex<MachineStateInner>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type MachineStateId = StateId<MachineState>;
|
pub type MachineStateId = StateId<MachineState>;
|
||||||
|
|
||||||
impl MachineState {
|
impl MachineState {
|
||||||
pub fn new(id: MachineStateId, opt_name: Option<String>) -> Self {
|
pub fn new(id: MachineStateId, opt_name: Option<String>, origin: MachineOrigin) -> Self {
|
||||||
// Create a localhost interface for this machine
|
// Create a localhost interface for this machine
|
||||||
Self {
|
Self {
|
||||||
unlocked_inner: Arc::new(MachineStateUnlockedInner { id, opt_name }),
|
immutable: Arc::new(MachineStateImmutable {
|
||||||
inner: Arc::new(Mutex::new(MachineStateInner {
|
id,
|
||||||
generating_template: None,
|
opt_name,
|
||||||
interfaces: HashMap::new(),
|
origin,
|
||||||
disable_capabilities: Vec::new(),
|
}),
|
||||||
|
fields: Arc::new(MachineStateFields {
|
||||||
|
interfaces: imbl::HashMap::new(),
|
||||||
|
disable_capabilities: imbl::Vector::new(),
|
||||||
bootstrap: false,
|
bootstrap: false,
|
||||||
})),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn release(&self, machine_registry_inner: &mut MachineRegistryInner) {
|
pub fn release(mut self, machine_registry_inner: &mut MachineRegistryInner) {
|
||||||
self.release_all_interfaces(machine_registry_inner);
|
self.release_all_interfaces(machine_registry_inner);
|
||||||
let inner = self.inner.lock();
|
|
||||||
if let Some(generating_template) = inner.generating_template {
|
if let MachineOrigin::Template(generating_template) = self.immutable.origin {
|
||||||
let template_state = machine_registry_inner
|
let template_state = machine_registry_inner
|
||||||
.template_states_mut()
|
.template_states_mut()
|
||||||
.get_state(generating_template)
|
.get_state(generating_template)
|
||||||
@ -63,44 +72,40 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn external_id(&self) -> MachineId {
|
pub fn set_disable_capabilities(&mut self, disable_capabilities: Vec<String>) {
|
||||||
self.unlocked_inner.id.0
|
self.fields = Arc::new(MachineStateFields {
|
||||||
|
disable_capabilities: disable_capabilities.into(),
|
||||||
|
..(*self.fields).clone()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_generating_template(&self, generating_template: TemplateStateId) {
|
pub fn set_bootstrap(&mut self, bootstrap: bool) {
|
||||||
let mut inner = self.inner.lock();
|
self.fields = Arc::new(MachineStateFields {
|
||||||
inner.generating_template = Some(generating_template);
|
bootstrap,
|
||||||
|
..(*self.fields).clone()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_disable_capabilities(&self, disable_capabilities: Vec<String>) {
|
fn next_free_interface_key(&self) -> Arc<String> {
|
||||||
let mut inner = self.inner.lock();
|
|
||||||
inner.disable_capabilities = disable_capabilities;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_bootstrap(&self, bootstrap: bool) {
|
|
||||||
let mut inner = self.inner.lock();
|
|
||||||
inner.bootstrap = bootstrap
|
|
||||||
}
|
|
||||||
|
|
||||||
fn next_free_interface_name_inner(inner: &MachineStateInner) -> String {
|
|
||||||
let mut inum = 0usize;
|
let mut inum = 0usize;
|
||||||
loop {
|
loop {
|
||||||
let name = format!("vin{}", inum);
|
let name = format!("vin{}", inum);
|
||||||
if !inner.interfaces.contains_key(&name) {
|
if !self.fields.interfaces.contains_key(&name) {
|
||||||
return name;
|
return Arc::new(name);
|
||||||
}
|
}
|
||||||
inum += 1;
|
inum += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn allocate_interface(
|
pub fn allocate_interface(
|
||||||
&self,
|
&mut self,
|
||||||
opt_name: Option<String>,
|
interface_name: Option<String>,
|
||||||
opt_interface_flags: Option<InterfaceFlags>,
|
opt_interface_flags: Option<InterfaceFlags>,
|
||||||
) -> MachineRegistryResult<String> {
|
) -> MachineRegistryResult<Arc<String>> {
|
||||||
let mut inner = self.inner.lock();
|
let interface_key = interface_name
|
||||||
let name = opt_name.unwrap_or_else(|| Self::next_free_interface_name_inner(&*inner));
|
.map(Arc::new)
|
||||||
if inner.interfaces.contains_key(&name) {
|
.unwrap_or_else(|| self.next_free_interface_key());
|
||||||
|
if self.fields.interfaces.contains_key(&interface_key) {
|
||||||
return Err(MachineRegistryError::DuplicateName);
|
return Err(MachineRegistryError::DuplicateName);
|
||||||
}
|
}
|
||||||
let flags = opt_interface_flags.unwrap_or_else(|| InterfaceFlags {
|
let flags = opt_interface_flags.unwrap_or_else(|| InterfaceFlags {
|
||||||
@ -109,44 +114,50 @@ impl MachineState {
|
|||||||
is_point_to_point: false,
|
is_point_to_point: false,
|
||||||
has_default_route: true,
|
has_default_route: true,
|
||||||
});
|
});
|
||||||
inner.interfaces.insert(
|
let interfaces = self.fields.interfaces.update(
|
||||||
name.clone(),
|
interface_key.clone(),
|
||||||
MachineStateInterface {
|
MachineStateInterface {
|
||||||
network_id: None,
|
network_id: None,
|
||||||
network_interface: NetworkInterface {
|
network_interface: Arc::new(NetworkInterface {
|
||||||
name: name.clone(),
|
name: (*interface_key).clone(),
|
||||||
flags,
|
flags,
|
||||||
addrs: Vec::new(),
|
addrs: Vec::new(),
|
||||||
},
|
}),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(name)
|
self.fields = Arc::new(MachineStateFields {
|
||||||
|
interfaces,
|
||||||
|
..(*self.fields).clone()
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(interface_key)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn interfaces(&self) -> Vec<String> {
|
pub fn interfaces(&self) -> Vec<Arc<String>> {
|
||||||
let mut intfs: Vec<String> = self.inner.lock().interfaces.keys().cloned().collect();
|
let mut intfs: Vec<_> = self.fields.interfaces.keys().cloned().collect();
|
||||||
intfs.sort();
|
intfs.sort();
|
||||||
intfs
|
intfs
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn allocate_address_ipv4(
|
pub fn allocate_address_ipv4(
|
||||||
&self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
machine_registry_inner: &mut MachineRegistryInner,
|
||||||
interface: &str,
|
interface_name: &str,
|
||||||
opt_address: Option<Ipv4Addr>,
|
opt_address: Option<Ipv4Addr>,
|
||||||
opt_address_flags: Option<AddressFlags>,
|
opt_address_flags: Option<AddressFlags>,
|
||||||
) -> MachineRegistryResult<Ifv4Addr> {
|
) -> MachineRegistryResult<Ifv4Addr> {
|
||||||
let mut inner = self.inner.lock();
|
let interface_key = Arc::new(interface_name.to_string());
|
||||||
let Some(intf) = inner.interfaces.get_mut(interface) else {
|
let Some(mut machine_state_interface) = self.fields.interfaces.get(&interface_key).cloned()
|
||||||
|
else {
|
||||||
return Err(MachineRegistryError::InvalidName);
|
return Err(MachineRegistryError::InvalidName);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get the network state
|
// Get the network state
|
||||||
let Some(network_id) = intf.network_id else {
|
let Some(network_id) = machine_state_interface.network_id else {
|
||||||
return Err(MachineRegistryError::NetworkNotFound);
|
return Err(MachineRegistryError::NetworkNotFound);
|
||||||
};
|
};
|
||||||
let network_state = machine_registry_inner
|
let mut network_state = machine_registry_inner
|
||||||
.network_states()
|
.network_states()
|
||||||
.get_state(network_id)?;
|
.get_state(network_id)?;
|
||||||
|
|
||||||
@ -158,6 +169,11 @@ impl MachineState {
|
|||||||
opt_address,
|
opt_address,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
// Update the network state
|
||||||
|
machine_registry_inner
|
||||||
|
.network_states_mut()
|
||||||
|
.set_state(network_state);
|
||||||
|
|
||||||
// Get address flags
|
// Get address flags
|
||||||
let flags = opt_address_flags.unwrap_or_else(|| AddressFlags {
|
let flags = opt_address_flags.unwrap_or_else(|| AddressFlags {
|
||||||
is_dynamic,
|
is_dynamic,
|
||||||
@ -165,31 +181,49 @@ impl MachineState {
|
|||||||
is_preferred: true,
|
is_preferred: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
intf.network_interface.addrs.push(InterfaceAddress {
|
// Update interface addresses
|
||||||
|
let mut new_intf = (*machine_state_interface.network_interface).clone();
|
||||||
|
new_intf.addrs.push(InterfaceAddress {
|
||||||
if_addr: IfAddr::V4(ifv4_addr.clone()),
|
if_addr: IfAddr::V4(ifv4_addr.clone()),
|
||||||
flags,
|
flags,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Update interface
|
||||||
|
machine_state_interface.network_interface = Arc::new(new_intf);
|
||||||
|
|
||||||
|
// Update interfaces map
|
||||||
|
let interfaces = self
|
||||||
|
.fields
|
||||||
|
.interfaces
|
||||||
|
.update(interface_key, machine_state_interface);
|
||||||
|
|
||||||
|
// Update fields
|
||||||
|
self.fields = Arc::new(MachineStateFields {
|
||||||
|
interfaces,
|
||||||
|
..(*self.fields).clone()
|
||||||
|
});
|
||||||
|
|
||||||
Ok(ifv4_addr)
|
Ok(ifv4_addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn allocate_address_ipv6(
|
pub fn allocate_address_ipv6(
|
||||||
&self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
machine_registry_inner: &mut MachineRegistryInner,
|
||||||
interface: &str,
|
interface_name: &str,
|
||||||
opt_address: Option<Ipv6Addr>,
|
opt_address: Option<Ipv6Addr>,
|
||||||
opt_address_flags: Option<AddressFlags>,
|
opt_address_flags: Option<AddressFlags>,
|
||||||
) -> MachineRegistryResult<Ifv6Addr> {
|
) -> MachineRegistryResult<Ifv6Addr> {
|
||||||
let mut inner = self.inner.lock();
|
let interface_key = Arc::new(interface_name.to_string());
|
||||||
let Some(intf) = inner.interfaces.get_mut(interface) else {
|
let Some(mut machine_state_interface) = self.fields.interfaces.get(&interface_key).cloned()
|
||||||
|
else {
|
||||||
return Err(MachineRegistryError::InvalidName);
|
return Err(MachineRegistryError::InvalidName);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get the network state
|
// Get the network state
|
||||||
let Some(network_id) = intf.network_id else {
|
let Some(network_id) = machine_state_interface.network_id else {
|
||||||
return Err(MachineRegistryError::NetworkNotFound);
|
return Err(MachineRegistryError::NetworkNotFound);
|
||||||
};
|
};
|
||||||
let network_state = machine_registry_inner
|
let mut network_state = machine_registry_inner
|
||||||
.network_states()
|
.network_states()
|
||||||
.get_state(network_id)?;
|
.get_state(network_id)?;
|
||||||
|
|
||||||
@ -200,6 +234,10 @@ impl MachineState {
|
|||||||
OwnerTag::Machine(self.id()),
|
OwnerTag::Machine(self.id()),
|
||||||
opt_address,
|
opt_address,
|
||||||
)?;
|
)?;
|
||||||
|
// Update the network state
|
||||||
|
machine_registry_inner
|
||||||
|
.network_states_mut()
|
||||||
|
.set_state(network_state);
|
||||||
|
|
||||||
// Get address flags
|
// Get address flags
|
||||||
let flags = opt_address_flags.unwrap_or_else(|| AddressFlags {
|
let flags = opt_address_flags.unwrap_or_else(|| AddressFlags {
|
||||||
@ -208,48 +246,98 @@ impl MachineState {
|
|||||||
is_preferred: true,
|
is_preferred: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
intf.network_interface.addrs.push(InterfaceAddress {
|
// Update interface addresses
|
||||||
|
let mut new_intf = (*machine_state_interface.network_interface).clone();
|
||||||
|
new_intf.addrs.push(InterfaceAddress {
|
||||||
if_addr: IfAddr::V6(ifv6_addr.clone()),
|
if_addr: IfAddr::V6(ifv6_addr.clone()),
|
||||||
flags,
|
flags,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Update interface
|
||||||
|
machine_state_interface.network_interface = Arc::new(new_intf);
|
||||||
|
|
||||||
|
// Update interfaces map
|
||||||
|
let interfaces = self
|
||||||
|
.fields
|
||||||
|
.interfaces
|
||||||
|
.update(interface_key, machine_state_interface);
|
||||||
|
|
||||||
|
// Update fields
|
||||||
|
self.fields = Arc::new(MachineStateFields {
|
||||||
|
interfaces,
|
||||||
|
..(*self.fields).clone()
|
||||||
|
});
|
||||||
|
|
||||||
Ok(ifv6_addr)
|
Ok(ifv6_addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn attach_network(
|
pub fn attach_network(
|
||||||
&self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
machine_registry_inner: &mut MachineRegistryInner,
|
||||||
interface: &str,
|
interface_name: &str,
|
||||||
network_id: NetworkStateId,
|
network_id: NetworkStateId,
|
||||||
) -> MachineRegistryResult<()> {
|
) -> MachineRegistryResult<()> {
|
||||||
let mut inner = self.inner.lock();
|
let interface_key = Arc::new(interface_name.to_string());
|
||||||
let Some(intf) = inner.interfaces.get_mut(interface) else {
|
let Some(mut machine_state_interface) = self.fields.interfaces.get(&interface_key).cloned()
|
||||||
|
else {
|
||||||
return Err(MachineRegistryError::InvalidName);
|
return Err(MachineRegistryError::InvalidName);
|
||||||
};
|
};
|
||||||
if intf.network_id.is_some() {
|
|
||||||
self.detach_network(machine_registry_inner, interface);
|
if machine_state_interface.network_id.is_some() {
|
||||||
|
Self::detach_network_inner(machine_registry_inner, &mut machine_state_interface)?;
|
||||||
}
|
}
|
||||||
intf.network_id = Some(network_id);
|
|
||||||
|
machine_state_interface.network_id = Some(network_id);
|
||||||
|
|
||||||
|
// Update interfaces map
|
||||||
|
let interfaces = self
|
||||||
|
.fields
|
||||||
|
.interfaces
|
||||||
|
.update(interface_key, machine_state_interface);
|
||||||
|
|
||||||
|
// Update fields
|
||||||
|
self.fields = Arc::new(MachineStateFields {
|
||||||
|
interfaces,
|
||||||
|
..(*self.fields).clone()
|
||||||
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn detach_network(
|
pub fn detach_network(
|
||||||
&self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
machine_registry_inner: &mut MachineRegistryInner,
|
||||||
interface: &str,
|
interface_name: &str,
|
||||||
) -> MachineRegistryResult<()> {
|
) -> MachineRegistryResult<()> {
|
||||||
let mut inner = self.inner.lock();
|
let interface_key = Arc::new(interface_name.to_string());
|
||||||
Self::detach_network_inner(&mut *inner, machine_registry_inner, interface)
|
let Some(mut machine_state_interface) = self.fields.interfaces.get(&interface_key).cloned()
|
||||||
|
else {
|
||||||
|
return Err(MachineRegistryError::InvalidName);
|
||||||
|
};
|
||||||
|
|
||||||
|
Self::detach_network_inner(machine_registry_inner, &mut machine_state_interface)?;
|
||||||
|
|
||||||
|
// Update interfaces map
|
||||||
|
let interfaces = self
|
||||||
|
.fields
|
||||||
|
.interfaces
|
||||||
|
.update(interface_key, machine_state_interface);
|
||||||
|
|
||||||
|
// Update fields
|
||||||
|
self.fields = Arc::new(MachineStateFields {
|
||||||
|
interfaces,
|
||||||
|
..(*self.fields).clone()
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn attached_network_interfaces(
|
pub fn attached_network_interfaces(
|
||||||
&self,
|
&self,
|
||||||
network_id: NetworkStateId,
|
network_id: NetworkStateId,
|
||||||
) -> MachineRegistryResult<Vec<String>> {
|
) -> MachineRegistryResult<Vec<Arc<String>>> {
|
||||||
let mut out = Vec::new();
|
let mut out = Vec::new();
|
||||||
let inner = self.inner.lock();
|
for intf in &self.fields.interfaces {
|
||||||
for intf in &inner.interfaces {
|
|
||||||
if intf.1.network_id == Some(network_id) {
|
if intf.1.network_id == Some(network_id) {
|
||||||
out.push(intf.0.clone());
|
out.push(intf.0.clone());
|
||||||
}
|
}
|
||||||
@ -258,22 +346,23 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn release_address(
|
pub fn release_address(
|
||||||
&self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
machine_registry_inner: &mut MachineRegistryInner,
|
||||||
interface: &str,
|
interface_name: &str,
|
||||||
address: IpAddr,
|
address: IpAddr,
|
||||||
) -> MachineRegistryResult<()> {
|
) -> MachineRegistryResult<()> {
|
||||||
let mut inner = self.inner.lock();
|
let interface_key = Arc::new(interface_name.to_owned());
|
||||||
let Some(intf) = inner.interfaces.get_mut(interface) else {
|
let Some(mut machine_state_interface) = self.fields.interfaces.get(&interface_key).cloned()
|
||||||
|
else {
|
||||||
return Err(MachineRegistryError::InvalidName);
|
return Err(MachineRegistryError::InvalidName);
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(network_id) = intf.network_id else {
|
let Some(network_id) = machine_state_interface.network_id else {
|
||||||
return Err(MachineRegistryError::NetworkNotFound);
|
return Err(MachineRegistryError::NetworkNotFound);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get the network state
|
// Get the network state
|
||||||
let network_state = machine_registry_inner
|
let mut network_state = machine_registry_inner
|
||||||
.network_states()
|
.network_states()
|
||||||
.get_state(network_id)?;
|
.get_state(network_id)?;
|
||||||
|
|
||||||
@ -283,92 +372,168 @@ impl MachineState {
|
|||||||
IpAddr::V6(ipv6_addr) => network_state.release_address_v6(ipv6_addr)?,
|
IpAddr::V6(ipv6_addr) => network_state.release_address_v6(ipv6_addr)?,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Update the network state
|
||||||
|
machine_registry_inner
|
||||||
|
.network_states_mut()
|
||||||
|
.set_state(network_state);
|
||||||
|
|
||||||
// Remove the address from the interface
|
// Remove the address from the interface
|
||||||
intf.network_interface
|
let addrs: Vec<_> = machine_state_interface
|
||||||
|
.network_interface
|
||||||
.addrs
|
.addrs
|
||||||
.retain(|x| x.if_addr().ip() != address);
|
.iter()
|
||||||
|
.filter(|x| x.if_addr().ip() != address)
|
||||||
|
.cloned()
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
// Update network interface
|
||||||
|
machine_state_interface.network_interface = Arc::new(NetworkInterface {
|
||||||
|
addrs,
|
||||||
|
..(*machine_state_interface.network_interface).clone()
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update interfaces map
|
||||||
|
let interfaces = self
|
||||||
|
.fields
|
||||||
|
.interfaces
|
||||||
|
.update(interface_key, machine_state_interface);
|
||||||
|
|
||||||
|
// Update fields
|
||||||
|
self.fields = Arc::new(MachineStateFields {
|
||||||
|
interfaces,
|
||||||
|
..(*self.fields).clone()
|
||||||
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn release_all_addresses(
|
pub fn release_all_addresses(
|
||||||
&self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
machine_registry_inner: &mut MachineRegistryInner,
|
||||||
interface: &str,
|
interface_name: &str,
|
||||||
) -> MachineRegistryResult<()> {
|
) -> MachineRegistryResult<()> {
|
||||||
let mut inner = self.inner.lock();
|
let interface_key = Arc::new(interface_name.to_string());
|
||||||
Self::release_all_addresses_inner(&mut *inner, machine_registry_inner, interface)
|
let Some(mut machine_state_interface) = self.fields.interfaces.get(&interface_key).cloned()
|
||||||
}
|
else {
|
||||||
|
|
||||||
fn detach_network_inner(
|
|
||||||
inner: &mut MachineStateInner,
|
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
|
||||||
interface: &str,
|
|
||||||
) -> MachineRegistryResult<()> {
|
|
||||||
Self::release_all_addresses_inner(inner, machine_registry_inner, interface)?;
|
|
||||||
let Some(intf) = inner.interfaces.get_mut(interface) else {
|
|
||||||
return Err(MachineRegistryError::InvalidName);
|
return Err(MachineRegistryError::InvalidName);
|
||||||
};
|
};
|
||||||
intf.network_id = None;
|
|
||||||
|
Self::release_all_addresses_inner(machine_registry_inner, &mut machine_state_interface)?;
|
||||||
|
|
||||||
|
// Update interfaces map
|
||||||
|
let interfaces = self
|
||||||
|
.fields
|
||||||
|
.interfaces
|
||||||
|
.update(interface_key, machine_state_interface);
|
||||||
|
|
||||||
|
// Update fields
|
||||||
|
self.fields = Arc::new(MachineStateFields {
|
||||||
|
interfaces,
|
||||||
|
..(*self.fields).clone()
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
fn detach_network_inner(
|
||||||
|
machine_registry_inner: &mut MachineRegistryInner,
|
||||||
|
machine_state_interface: &mut MachineStateInterface,
|
||||||
|
) -> MachineRegistryResult<()> {
|
||||||
|
Self::release_all_addresses_inner(machine_registry_inner, machine_state_interface)?;
|
||||||
|
machine_state_interface.network_id = None;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn release_all_addresses_inner(
|
fn release_all_addresses_inner(
|
||||||
inner: &mut MachineStateInner,
|
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
machine_registry_inner: &mut MachineRegistryInner,
|
||||||
interface: &str,
|
machine_state_interface: &mut MachineStateInterface,
|
||||||
) -> MachineRegistryResult<()> {
|
) -> MachineRegistryResult<()> {
|
||||||
let Some(intf) = inner.interfaces.get_mut(interface) else {
|
let Some(network_id) = machine_state_interface.network_id else {
|
||||||
return Err(MachineRegistryError::InvalidName);
|
|
||||||
};
|
|
||||||
|
|
||||||
let Some(network_id) = intf.network_id else {
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get the network state
|
// Get the network state
|
||||||
let network_state = machine_registry_inner
|
let mut network_state = machine_registry_inner
|
||||||
.network_states()
|
.network_states()
|
||||||
.get_state(network_id)?;
|
.get_state(network_id)?;
|
||||||
|
|
||||||
// Release the addresses from the network
|
// Release the addresses from the network
|
||||||
for addr in &intf.network_interface.addrs {
|
for addr in &machine_state_interface.network_interface.addrs {
|
||||||
match addr.if_addr.ip() {
|
match addr.if_addr.ip() {
|
||||||
IpAddr::V4(ipv4_addr) => network_state.release_address_v4(ipv4_addr)?,
|
IpAddr::V4(ipv4_addr) => network_state.release_address_v4(ipv4_addr)?,
|
||||||
IpAddr::V6(ipv6_addr) => network_state.release_address_v6(ipv6_addr)?,
|
IpAddr::V6(ipv6_addr) => network_state.release_address_v6(ipv6_addr)?,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the network state
|
||||||
|
machine_registry_inner
|
||||||
|
.network_states_mut()
|
||||||
|
.set_state(network_state);
|
||||||
|
|
||||||
// Remove the addresses from the interface
|
// Remove the addresses from the interface
|
||||||
intf.network_interface.addrs.clear();
|
let mut new_intf = (*machine_state_interface.network_interface).clone();
|
||||||
|
new_intf.addrs.clear();
|
||||||
|
|
||||||
|
// Update interface
|
||||||
|
machine_state_interface.network_interface = Arc::new(new_intf);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn release_interface(
|
pub fn release_interface(
|
||||||
&self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
machine_registry_inner: &mut MachineRegistryInner,
|
||||||
interface: &str,
|
interface_name: &str,
|
||||||
) -> MachineRegistryResult<()> {
|
) -> MachineRegistryResult<()> {
|
||||||
let mut inner = self.inner.lock();
|
let interface_key = Arc::new(interface_name.to_string());
|
||||||
Self::detach_network_inner(&mut *inner, machine_registry_inner, interface)?;
|
let Some(mut machine_state_interface) = self.fields.interfaces.get(&interface_key).cloned()
|
||||||
inner
|
else {
|
||||||
.interfaces
|
return Err(MachineRegistryError::InvalidName);
|
||||||
.remove(interface)
|
};
|
||||||
.expect("interface must exist");
|
|
||||||
|
Self::detach_network_inner(machine_registry_inner, &mut machine_state_interface)?;
|
||||||
|
|
||||||
|
// Update interfaces map
|
||||||
|
let interfaces = self.fields.interfaces.without(&interface_key);
|
||||||
|
|
||||||
|
// Update fields
|
||||||
|
self.fields = Arc::new(MachineStateFields {
|
||||||
|
interfaces,
|
||||||
|
..(*self.fields).clone()
|
||||||
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn release_all_interfaces(
|
pub fn release_all_interfaces(
|
||||||
&self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
machine_registry_inner: &mut MachineRegistryInner,
|
||||||
) -> MachineRegistryResult<()> {
|
) -> MachineRegistryResult<()> {
|
||||||
let mut inner = self.inner.lock();
|
let interface_names: Vec<String> = self
|
||||||
let interfaces: Vec<String> = inner.interfaces.keys().cloned().collect();
|
.fields
|
||||||
for interface in interfaces {
|
.interfaces
|
||||||
Self::release_all_addresses_inner(&mut *inner, machine_registry_inner, &interface)?;
|
.keys()
|
||||||
|
.map(|x| (**x).clone())
|
||||||
|
.collect();
|
||||||
|
for interface_name in interface_names {
|
||||||
|
let interface_key = Arc::new(interface_name);
|
||||||
|
let Some(mut machine_state_interface) =
|
||||||
|
self.fields.interfaces.get(&interface_key).cloned()
|
||||||
|
else {
|
||||||
|
return Err(MachineRegistryError::InvalidName);
|
||||||
|
};
|
||||||
|
|
||||||
|
Self::detach_network_inner(machine_registry_inner, &mut machine_state_interface)?;
|
||||||
}
|
}
|
||||||
inner.interfaces.clear();
|
|
||||||
|
// Update fields
|
||||||
|
self.fields = Arc::new(MachineStateFields {
|
||||||
|
interfaces: imbl::HashMap::new(),
|
||||||
|
..(*self.fields).clone()
|
||||||
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -467,10 +632,10 @@ impl MachineState {
|
|||||||
|
|
||||||
impl State for MachineState {
|
impl State for MachineState {
|
||||||
fn id(&self) -> StateId<Self> {
|
fn id(&self) -> StateId<Self> {
|
||||||
self.unlocked_inner.id.clone()
|
self.immutable.id.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn name(&self) -> Option<String> {
|
fn name(&self) -> Option<String> {
|
||||||
self.unlocked_inner.opt_name.clone()
|
self.immutable.opt_name.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -148,18 +148,11 @@ impl NetworkState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_model(
|
pub fn set_model(&mut self, params: NetworkStateModelParams) {
|
||||||
self,
|
self.fields = Arc::new(NetworkStateFields {
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
model: NetworkStateModel { params },
|
||||||
params: NetworkStateModelParams,
|
..(*self.fields).clone()
|
||||||
) -> Self {
|
});
|
||||||
Self {
|
|
||||||
fields: Arc::new(NetworkStateFields {
|
|
||||||
model: NetworkStateModel { params },
|
|
||||||
..(*self.fields).clone()
|
|
||||||
}),
|
|
||||||
..self.clone()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear_ipv4(
|
pub fn clear_ipv4(
|
||||||
@ -365,10 +358,6 @@ impl NetworkState {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_generating_blueprint(&self, generating_blueprint: BlueprintStateId) {
|
|
||||||
inner.generating_blueprint = Some(generating_blueprint);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_ipv4(&self) -> bool {
|
pub fn is_ipv4(&self) -> bool {
|
||||||
self.fields.lock().ipv4.is_some()
|
self.fields.lock().ipv4.is_some()
|
||||||
}
|
}
|
||||||
@ -396,7 +385,7 @@ impl NetworkState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn allocate_address_v4(
|
pub fn allocate_address_v4(
|
||||||
&self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
machine_registry_inner: &mut MachineRegistryInner,
|
||||||
owner_tag: OwnerTag,
|
owner_tag: OwnerTag,
|
||||||
opt_address: Option<Ipv4Addr>,
|
opt_address: Option<Ipv4Addr>,
|
||||||
@ -447,16 +436,19 @@ impl NetworkState {
|
|||||||
Self::can_allocate_net_v4_inner(&*inner, opt_address, prefix)
|
Self::can_allocate_net_v4_inner(&*inner, opt_address, prefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn release_address_v4(&self, addr: Ipv4Addr) -> MachineRegistryResult<Option<OwnerTag>> {
|
pub fn release_address_v4(
|
||||||
|
&mut self,
|
||||||
|
addr: Ipv4Addr,
|
||||||
|
) -> MachineRegistryResult<Option<OwnerTag>> {
|
||||||
Self::release_subnet_v4_inner(&mut *inner, Ipv4Net::new(addr, 32).expect("must succeed"))
|
Self::release_subnet_v4_inner(&mut *inner, Ipv4Net::new(addr, 32).expect("must succeed"))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn release_subnet_v4(&self, net: Ipv4Net) -> MachineRegistryResult<Option<OwnerTag>> {
|
pub fn release_subnet_v4(&mut self, net: Ipv4Net) -> MachineRegistryResult<Option<OwnerTag>> {
|
||||||
Self::release_subnet_v4_inner(&mut *inner, net)
|
Self::release_subnet_v4_inner(&mut *inner, net)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn allocate_address_v6(
|
pub fn allocate_address_v6(
|
||||||
&self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
machine_registry_inner: &mut MachineRegistryInner,
|
||||||
owner_tag: OwnerTag,
|
owner_tag: OwnerTag,
|
||||||
opt_address: Option<Ipv6Addr>,
|
opt_address: Option<Ipv6Addr>,
|
||||||
|
@ -14,6 +14,10 @@ impl<S: State> StateId<S> {
|
|||||||
pub fn new(external_id: u64) -> Self {
|
pub fn new(external_id: u64) -> Self {
|
||||||
Self(external_id, PhantomData {})
|
Self(external_id, PhantomData {})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn external_id(&self) -> u64 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: State> Copy for StateId<S> {}
|
impl<S: State> Copy for StateId<S> {}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user