mirror of
https://gitlab.com/veilid/veilid.git
synced 2025-02-04 08:55:37 -05:00
[skip ci] refactor and make multiple configs possible
This commit is contained in:
parent
9e7c41b635
commit
d83f09d058
@ -78,7 +78,11 @@ fn main() -> Result<(), String> {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let router_server = virtual_network::RouterServer::new(initial_config);
|
let router_server = virtual_network::RouterServer::new();
|
||||||
|
|
||||||
|
if let Err(e) = router_server.execute_config(initial_config) {
|
||||||
|
xxx continue here
|
||||||
|
}
|
||||||
|
|
||||||
let _ss_tcp = if !args.no_tcp {
|
let _ss_tcp = if !args.no_tcp {
|
||||||
Some(
|
Some(
|
||||||
|
@ -58,9 +58,9 @@ impl<T: fmt::Debug + Clone> AddressPool<T> {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn can_allocate_v6(&self, prefix: u8) -> MachineRegistryResult<bool> {
|
pub fn can_allocate_v6(&self, prefix: u8) -> GlobalStateManagerResult<bool> {
|
||||||
if prefix > 128 {
|
if prefix > 128 {
|
||||||
return Err(MachineRegistryError::InvalidPrefix);
|
return Err(GlobalStateManagerError::InvalidPrefix(prefix));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut srng = StableRng::new(0);
|
let mut srng = StableRng::new(0);
|
||||||
@ -68,9 +68,9 @@ impl<T: fmt::Debug + Clone> AddressPool<T> {
|
|||||||
Ok(opt_allocation.is_some())
|
Ok(opt_allocation.is_some())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn can_allocate_v4(&self, prefix: u8) -> MachineRegistryResult<bool> {
|
pub fn can_allocate_v4(&self, prefix: u8) -> GlobalStateManagerResult<bool> {
|
||||||
if prefix > 32 {
|
if prefix > 32 {
|
||||||
return Err(MachineRegistryError::InvalidPrefix);
|
return Err(GlobalStateManagerError::InvalidPrefix(prefix));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut srng = StableRng::new(0);
|
let mut srng = StableRng::new(0);
|
||||||
@ -82,15 +82,15 @@ impl<T: fmt::Debug + Clone> AddressPool<T> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
allocation: Ipv4Net,
|
allocation: Ipv4Net,
|
||||||
opt_tag: Option<T>,
|
opt_tag: Option<T>,
|
||||||
) -> MachineRegistryResult<()> {
|
) -> GlobalStateManagerResult<()> {
|
||||||
// Ensure the allocation is in our scope
|
// Ensure the allocation is in our scope
|
||||||
if !self.is_in_scope_v4(allocation) {
|
if !self.is_in_scope_v4(allocation) {
|
||||||
return Err(MachineRegistryError::NoAllocation);
|
return Err(GlobalStateManagerError::NoAllocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only reserve if it's not overlapping an allocation
|
// Only reserve if it's not overlapping an allocation
|
||||||
if !self.get_overlaps_v4(allocation).is_empty() {
|
if !self.get_overlaps_v4(allocation).is_empty() {
|
||||||
return Err(MachineRegistryError::NoAllocation);
|
return Err(GlobalStateManagerError::NoAllocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add to our allocated pool
|
// Add to our allocated pool
|
||||||
@ -104,15 +104,15 @@ impl<T: fmt::Debug + Clone> AddressPool<T> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
allocation: Ipv6Net,
|
allocation: Ipv6Net,
|
||||||
opt_tag: Option<T>,
|
opt_tag: Option<T>,
|
||||||
) -> MachineRegistryResult<()> {
|
) -> GlobalStateManagerResult<()> {
|
||||||
// Ensure the allocation is in our scope
|
// Ensure the allocation is in our scope
|
||||||
if !self.is_in_scope_v6(allocation) {
|
if !self.is_in_scope_v6(allocation) {
|
||||||
return Err(MachineRegistryError::NoAllocation);
|
return Err(GlobalStateManagerError::NoAllocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only reserve if it's not overlapping an allocation
|
// Only reserve if it's not overlapping an allocation
|
||||||
if !self.get_overlaps_v6(allocation).is_empty() {
|
if !self.get_overlaps_v6(allocation).is_empty() {
|
||||||
return Err(MachineRegistryError::NoAllocation);
|
return Err(GlobalStateManagerError::NoAllocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add to our allocated pool
|
// Add to our allocated pool
|
||||||
@ -149,9 +149,9 @@ impl<T: fmt::Debug + Clone> AddressPool<T> {
|
|||||||
srng: &mut StableRng,
|
srng: &mut StableRng,
|
||||||
prefix: u8,
|
prefix: u8,
|
||||||
tag: T,
|
tag: T,
|
||||||
) -> MachineRegistryResult<Option<Ipv4Net>> {
|
) -> GlobalStateManagerResult<Option<Ipv4Net>> {
|
||||||
if prefix > 32 {
|
if prefix > 32 {
|
||||||
return Err(MachineRegistryError::InvalidPrefix);
|
return Err(GlobalStateManagerError::InvalidPrefix(prefix));
|
||||||
}
|
}
|
||||||
|
|
||||||
let opt_allocation = self.find_random_allocation_v4(srng, prefix);
|
let opt_allocation = self.find_random_allocation_v4(srng, prefix);
|
||||||
@ -173,9 +173,9 @@ impl<T: fmt::Debug + Clone> AddressPool<T> {
|
|||||||
srng: &mut StableRng,
|
srng: &mut StableRng,
|
||||||
prefix: u8,
|
prefix: u8,
|
||||||
tag: T,
|
tag: T,
|
||||||
) -> MachineRegistryResult<Option<Ipv6Net>> {
|
) -> GlobalStateManagerResult<Option<Ipv6Net>> {
|
||||||
if prefix > 128 {
|
if prefix > 128 {
|
||||||
return Err(MachineRegistryError::InvalidPrefix);
|
return Err(GlobalStateManagerError::InvalidPrefix(prefix));
|
||||||
}
|
}
|
||||||
|
|
||||||
let opt_allocation = self.find_random_allocation_v6(srng, prefix);
|
let opt_allocation = self.find_random_allocation_v6(srng, prefix);
|
||||||
@ -195,13 +195,13 @@ impl<T: fmt::Debug + Clone> AddressPool<T> {
|
|||||||
pub fn release_allocation_v4(
|
pub fn release_allocation_v4(
|
||||||
&mut self,
|
&mut self,
|
||||||
allocation: Ipv4Net,
|
allocation: Ipv4Net,
|
||||||
) -> MachineRegistryResult<Option<T>> {
|
) -> GlobalStateManagerResult<Option<T>> {
|
||||||
let Some(pos) = self.allocated_v4.iter().position(|x| *x == allocation) else {
|
let Some(pos) = self.allocated_v4.iter().position(|x| *x == allocation) else {
|
||||||
return Err(MachineRegistryError::NoAllocation);
|
return Err(GlobalStateManagerError::NoAllocation);
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(opt_tag) = self.owner_tags_v4.remove(&allocation) else {
|
let Some(opt_tag) = self.owner_tags_v4.remove(&allocation) else {
|
||||||
return Err(MachineRegistryError::NoAllocation);
|
return Err(GlobalStateManagerError::NoAllocation);
|
||||||
};
|
};
|
||||||
|
|
||||||
self.allocated_v4.remove(pos);
|
self.allocated_v4.remove(pos);
|
||||||
@ -212,13 +212,13 @@ impl<T: fmt::Debug + Clone> AddressPool<T> {
|
|||||||
pub fn release_allocation_v6(
|
pub fn release_allocation_v6(
|
||||||
&mut self,
|
&mut self,
|
||||||
allocation: Ipv6Net,
|
allocation: Ipv6Net,
|
||||||
) -> MachineRegistryResult<Option<T>> {
|
) -> GlobalStateManagerResult<Option<T>> {
|
||||||
let Some(pos) = self.allocated_v6.iter().position(|x| *x == allocation) else {
|
let Some(pos) = self.allocated_v6.iter().position(|x| *x == allocation) else {
|
||||||
return Err(MachineRegistryError::NoAllocation);
|
return Err(GlobalStateManagerError::NoAllocation);
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(opt_tag) = self.owner_tags_v6.remove(&allocation) else {
|
let Some(opt_tag) = self.owner_tags_v6.remove(&allocation) else {
|
||||||
return Err(MachineRegistryError::NoAllocation);
|
return Err(GlobalStateManagerError::NoAllocation);
|
||||||
};
|
};
|
||||||
|
|
||||||
self.allocated_v4.remove(pos);
|
self.allocated_v4.remove(pos);
|
||||||
@ -264,7 +264,7 @@ impl<T: fmt::Debug + Clone> AddressPool<T> {
|
|||||||
pub fn clear_ipv4<F: FnMut(Ipv4Net, &T) -> bool>(
|
pub fn clear_ipv4<F: FnMut(Ipv4Net, &T) -> bool>(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut check: F,
|
mut check: F,
|
||||||
) -> MachineRegistryResult<()> {
|
) -> GlobalStateManagerResult<()> {
|
||||||
if !self.is_ipv4() {
|
if !self.is_ipv4() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
@ -272,7 +272,9 @@ impl<T: fmt::Debug + Clone> AddressPool<T> {
|
|||||||
IpNet::V4(ipv4_net) => check(ipv4_net, t),
|
IpNet::V4(ipv4_net) => check(ipv4_net, t),
|
||||||
IpNet::V6(_ipv6_net) => false,
|
IpNet::V6(_ipv6_net) => false,
|
||||||
}) {
|
}) {
|
||||||
return Err(MachineRegistryError::ResourceInUse);
|
return Err(GlobalStateManagerError::ResourceInUse(
|
||||||
|
"AddressPool-v4".to_owned(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
assert!(self.owner_tags_v4.is_empty(), "tags should be empty");
|
assert!(self.owner_tags_v4.is_empty(), "tags should be empty");
|
||||||
self.scope_v4.clear();
|
self.scope_v4.clear();
|
||||||
@ -284,7 +286,7 @@ impl<T: fmt::Debug + Clone> AddressPool<T> {
|
|||||||
pub fn clear_ipv6<F: FnMut(Ipv6Net, &T) -> bool>(
|
pub fn clear_ipv6<F: FnMut(Ipv6Net, &T) -> bool>(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut check: F,
|
mut check: F,
|
||||||
) -> MachineRegistryResult<()> {
|
) -> GlobalStateManagerResult<()> {
|
||||||
if !self.is_ipv6() {
|
if !self.is_ipv6() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
@ -292,7 +294,9 @@ impl<T: fmt::Debug + Clone> AddressPool<T> {
|
|||||||
IpNet::V4(_ipv4_net) => false,
|
IpNet::V4(_ipv4_net) => false,
|
||||||
IpNet::V6(ipv6_net) => check(ipv6_net, t),
|
IpNet::V6(ipv6_net) => check(ipv6_net, t),
|
||||||
}) {
|
}) {
|
||||||
return Err(MachineRegistryError::ResourceInUse);
|
return Err(GlobalStateManagerError::ResourceInUse(
|
||||||
|
"AddressPool-v6".to_owned(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
assert!(self.owner_tags_v6.is_empty(), "tags should be empty");
|
assert!(self.owner_tags_v6.is_empty(), "tags should be empty");
|
||||||
self.scope_v6.clear();
|
self.scope_v6.clear();
|
@ -1,73 +1,86 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(super) struct MachineRegistryInner {
|
pub(super) struct GlobalStateManagerInner {
|
||||||
unlocked_inner: Arc<MachineRegistryUnlockedInner>,
|
unlocked_inner: Arc<GlobalStateManagerUnlockedInner>,
|
||||||
srng: StableRng,
|
srng: StableRng,
|
||||||
|
models: imbl::HashMap<String, config::Model>,
|
||||||
|
allocations: imbl::HashMap<String, config::Allocation>,
|
||||||
allocated_machines: imbl::HashSet<MachineStateId>,
|
allocated_machines: imbl::HashSet<MachineStateId>,
|
||||||
profile_state_allocator: StateAllocator<ProfileState>,
|
profile_state_registry: StateRegistry<ProfileState>,
|
||||||
machine_state_allocator: StateAllocator<MachineState>,
|
machine_state_registry: StateRegistry<MachineState>,
|
||||||
template_state_allocator: StateAllocator<TemplateState>,
|
template_state_registry: StateRegistry<TemplateState>,
|
||||||
network_state_allocator: StateAllocator<NetworkState>,
|
network_state_registry: StateRegistry<NetworkState>,
|
||||||
blueprint_state_allocator: StateAllocator<BlueprintState>,
|
blueprint_state_registry: StateRegistry<BlueprintState>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MachineRegistryInner {
|
impl GlobalStateManagerInner {
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
/// Public Interface
|
/// Public Interface
|
||||||
|
|
||||||
pub fn new(unlocked_inner: Arc<MachineRegistryUnlockedInner>) -> Self {
|
pub fn new(unlocked_inner: Arc<GlobalStateManagerUnlockedInner>) -> Self {
|
||||||
let srng = StableRng::new(unlocked_inner.config.seed.unwrap_or_default());
|
GlobalStateManagerInner {
|
||||||
|
|
||||||
MachineRegistryInner {
|
|
||||||
unlocked_inner,
|
unlocked_inner,
|
||||||
srng,
|
srng: StableRng::new(0),
|
||||||
|
models: imbl::HashMap::new(),
|
||||||
|
allocations: imbl::HashMap::new(),
|
||||||
allocated_machines: imbl::HashSet::new(),
|
allocated_machines: imbl::HashSet::new(),
|
||||||
profile_state_allocator: StateAllocator::new(),
|
profile_state_registry: StateRegistry::new(),
|
||||||
machine_state_allocator: StateAllocator::new(),
|
machine_state_registry: StateRegistry::new(),
|
||||||
template_state_allocator: StateAllocator::new(),
|
template_state_registry: StateRegistry::new(),
|
||||||
network_state_allocator: StateAllocator::new(),
|
network_state_registry: StateRegistry::new(),
|
||||||
blueprint_state_allocator: StateAllocator::new(),
|
blueprint_state_registry: StateRegistry::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn srng(&mut self) -> &mut StableRng {
|
|
||||||
&mut self.srng
|
pub fn execute_config(&mut self, cfg: config::Config) -> GlobalStateManagerResult<()> {
|
||||||
}
|
// Create random number generator
|
||||||
pub fn config(&self) -> &config::Config {
|
if let Some(seed) = cfg.seed {
|
||||||
&self.unlocked_inner.config
|
self.srng = StableRng::new(seed);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn execute_config(&self, cfg: config::Config) -> MachineRegistryResult<()> {
|
// Import all allocation definitions
|
||||||
// Create all networks
|
for a in cfg.allocations {
|
||||||
|
if self.allocations.contains_key(&a.0) {
|
||||||
|
return Err(GlobalStateManagerError::DuplicateName(a.0));
|
||||||
|
}
|
||||||
|
self.allocations.insert(a.0, a.1);
|
||||||
|
}
|
||||||
|
|
||||||
// Create all blueprints
|
// Import all models
|
||||||
|
for m in cfg.models {
|
||||||
|
if self.models.contains_key(&m.0) {
|
||||||
|
return Err(GlobalStateManagerError::DuplicateName(m.0));
|
||||||
|
}
|
||||||
|
self.models.insert(m.0, m.1);
|
||||||
|
}
|
||||||
|
|
||||||
// Create all templates
|
// Create all profile states
|
||||||
|
|
||||||
// Create all machines
|
// Create all network states
|
||||||
|
|
||||||
|
// Create all blueprint states
|
||||||
|
|
||||||
|
// Create all template states
|
||||||
|
|
||||||
|
// Create all machine states
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn allocate(&mut self, profile: String) -> MachineRegistryResult<MachineId> {
|
pub fn allocate(&mut self, profile: String) -> GlobalStateManagerResult<MachineId> {
|
||||||
// Get profile definition
|
// Get current profile state
|
||||||
let Some(profile_def) = self.unlocked_inner.config.profiles.get(&profile) else {
|
let Some(profile_state_id) = self.profile_state_registry.get_state_id_by_name(&profile)
|
||||||
return Err(MachineRegistryError::ProfileNotFound);
|
else {
|
||||||
|
return Err(GlobalStateManagerError::ProfileNotFound(profile));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get current profile state, creating one if we have not yet started executing the profile
|
|
||||||
let profile_state_id = self
|
|
||||||
.profile_state_allocator
|
|
||||||
.get_or_create_by_name(profile, |id, name| {
|
|
||||||
ProfileState::new(id, name, profile_def.clone())
|
|
||||||
});
|
|
||||||
|
|
||||||
// Get the next instance from the definition
|
// Get the next instance from the definition
|
||||||
loop {
|
loop {
|
||||||
// Move to the next profile instance
|
// Move to the next profile instance
|
||||||
let mut profile_state = self.profile_states().get_state(profile_state_id)?;
|
let mut profile_state = self.profile_states().get_state(profile_state_id)?;
|
||||||
let Some(instance_def) = profile_state.next_instance() else {
|
let Some(instance_def) = profile_state.next_instance() else {
|
||||||
return Err(MachineRegistryError::ProfileComplete);
|
return Err(GlobalStateManagerError::ProfileComplete(profile));
|
||||||
};
|
};
|
||||||
self.profile_states_mut().set_state(profile_state);
|
self.profile_states_mut().set_state(profile_state);
|
||||||
|
|
||||||
@ -80,7 +93,7 @@ impl MachineRegistryInner {
|
|||||||
let Some(machine_state_id) =
|
let Some(machine_state_id) =
|
||||||
self.machine_states().get_state_id_by_name(name)
|
self.machine_states().get_state_id_by_name(name)
|
||||||
else {
|
else {
|
||||||
return Err(MachineRegistryError::MachineNotFound);
|
return Err(GlobalStateManagerError::MachineNotFound(name.clone()));
|
||||||
};
|
};
|
||||||
if self.allocated_machines.contains(&machine_state_id) {
|
if self.allocated_machines.contains(&machine_state_id) {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
@ -109,7 +122,7 @@ impl MachineRegistryInner {
|
|||||||
let Some(template_state_id) =
|
let Some(template_state_id) =
|
||||||
self.template_states().get_state_id_by_name(name)
|
self.template_states().get_state_id_by_name(name)
|
||||||
else {
|
else {
|
||||||
return Err(MachineRegistryError::TemplateNotFound);
|
return Err(GlobalStateManagerError::TemplateNotFound(name.clone()));
|
||||||
};
|
};
|
||||||
let template_state = self
|
let template_state = self
|
||||||
.template_states()
|
.template_states()
|
||||||
@ -143,7 +156,7 @@ impl MachineRegistryInner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn release(&mut self, machine_id: MachineId) -> MachineRegistryResult<()> {
|
pub fn release(&mut self, machine_id: MachineId) -> GlobalStateManagerResult<()> {
|
||||||
let id = StateId::<MachineState>::new(machine_id);
|
let id = StateId::<MachineState>::new(machine_id);
|
||||||
if self.allocated_machines.contains(&id) {
|
if self.allocated_machines.contains(&id) {
|
||||||
// Was a fixed machine, so we leave the machine state so it can
|
// Was a fixed machine, so we leave the machine state so it can
|
||||||
@ -162,36 +175,47 @@ impl MachineRegistryInner {
|
|||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
/// Private Implementation
|
/// Private Implementation
|
||||||
|
|
||||||
pub(super) fn profile_states(&self) -> &StateAllocator<ProfileState> {
|
pub(super) fn srng(&mut self) -> &mut StableRng {
|
||||||
&self.profile_state_allocator
|
&mut self.srng
|
||||||
}
|
|
||||||
pub(super) fn machine_states(&self) -> &StateAllocator<MachineState> {
|
|
||||||
&self.machine_state_allocator
|
|
||||||
}
|
|
||||||
pub(super) fn template_states(&self) -> &StateAllocator<TemplateState> {
|
|
||||||
&self.template_state_allocator
|
|
||||||
}
|
|
||||||
pub(super) fn network_states(&self) -> &StateAllocator<NetworkState> {
|
|
||||||
&self.network_state_allocator
|
|
||||||
}
|
|
||||||
pub(super) fn blueprint_states(&self) -> &StateAllocator<BlueprintState> {
|
|
||||||
&self.blueprint_state_allocator
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn profile_states_mut(&mut self) -> &mut StateAllocator<ProfileState> {
|
pub(super) fn models(&self) -> &imbl::HashMap<String, config::Model> {
|
||||||
&mut self.profile_state_allocator
|
&self.models
|
||||||
}
|
}
|
||||||
pub(super) fn machine_states_mut(&mut self) -> &mut StateAllocator<MachineState> {
|
pub(super) fn allocations(&self) -> &imbl::HashMap<String, config::Allocation> {
|
||||||
&mut self.machine_state_allocator
|
&self.allocations
|
||||||
}
|
}
|
||||||
pub(super) fn template_states_mut(&mut self) -> &mut StateAllocator<TemplateState> {
|
|
||||||
&mut self.template_state_allocator
|
pub(super) fn profile_states(&self) -> &StateRegistry<ProfileState> {
|
||||||
|
&self.profile_state_registry
|
||||||
}
|
}
|
||||||
pub(super) fn network_states_mut(&mut self) -> &mut StateAllocator<NetworkState> {
|
pub(super) fn machine_states(&self) -> &StateRegistry<MachineState> {
|
||||||
&mut self.network_state_allocator
|
&self.machine_state_registry
|
||||||
}
|
}
|
||||||
pub(super) fn blueprint_states_mut(&mut self) -> &mut StateAllocator<BlueprintState> {
|
pub(super) fn template_states(&self) -> &StateRegistry<TemplateState> {
|
||||||
&mut self.blueprint_state_allocator
|
&self.template_state_registry
|
||||||
|
}
|
||||||
|
pub(super) fn network_states(&self) -> &StateRegistry<NetworkState> {
|
||||||
|
&self.network_state_registry
|
||||||
|
}
|
||||||
|
pub(super) fn blueprint_states(&self) -> &StateRegistry<BlueprintState> {
|
||||||
|
&self.blueprint_state_registry
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn profile_states_mut(&mut self) -> &mut StateRegistry<ProfileState> {
|
||||||
|
&mut self.profile_state_registry
|
||||||
|
}
|
||||||
|
pub(super) fn machine_states_mut(&mut self) -> &mut StateRegistry<MachineState> {
|
||||||
|
&mut self.machine_state_registry
|
||||||
|
}
|
||||||
|
pub(super) fn template_states_mut(&mut self) -> &mut StateRegistry<TemplateState> {
|
||||||
|
&mut self.template_state_registry
|
||||||
|
}
|
||||||
|
pub(super) fn network_states_mut(&mut self) -> &mut StateRegistry<NetworkState> {
|
||||||
|
&mut self.network_state_registry
|
||||||
|
}
|
||||||
|
pub(super) fn blueprint_states_mut(&mut self) -> &mut StateRegistry<BlueprintState> {
|
||||||
|
&mut self.blueprint_state_registry
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub(super) fn get_or_create_machine_state(
|
// pub(super) fn get_or_create_machine_state(
|
@ -0,0 +1,117 @@
|
|||||||
|
mod address_pool;
|
||||||
|
mod global_state_manager_inner;
|
||||||
|
mod state;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
use address_pool::*;
|
||||||
|
use global_state_manager_inner::*;
|
||||||
|
use state::*;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Machine {}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct GlobalStateManagerUnlockedInner {}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, ThisError, PartialEq, Eq)]
|
||||||
|
pub enum GlobalStateManagerError {
|
||||||
|
#[error("Invalid id: {0}")]
|
||||||
|
InvalidId(u64),
|
||||||
|
#[error("Invalid name: {0}")]
|
||||||
|
InvalidName(String),
|
||||||
|
#[error("Invalid prefix: {0}")]
|
||||||
|
InvalidPrefix(u8),
|
||||||
|
#[error("Already attached")]
|
||||||
|
AlreadyAttached,
|
||||||
|
#[error("Not attached")]
|
||||||
|
NotAttached,
|
||||||
|
#[error("Duplicate name: {0}")]
|
||||||
|
DuplicateName(String),
|
||||||
|
#[error("Profile complete: {0}")]
|
||||||
|
ProfileComplete(String),
|
||||||
|
#[error("Template complete: {0}")]
|
||||||
|
TemplateComplete(String),
|
||||||
|
#[error("Network complete: {0}")]
|
||||||
|
NetworkComplete(String),
|
||||||
|
#[error("Blueprint complete: {0}")]
|
||||||
|
BlueprintComplete(String),
|
||||||
|
#[error("Profile not found: {0}")]
|
||||||
|
ProfileNotFound(String),
|
||||||
|
#[error("Machine not found: {0}")]
|
||||||
|
MachineNotFound(String),
|
||||||
|
#[error("Network not found: {0}")]
|
||||||
|
NetworkNotFound(String),
|
||||||
|
#[error("Template not found: {0}")]
|
||||||
|
TemplateNotFound(String),
|
||||||
|
#[error("Blueprint not found: {0}")]
|
||||||
|
BlueprintNotFound(String),
|
||||||
|
#[error("Model not found: {0}")]
|
||||||
|
ModelNotFound(String),
|
||||||
|
#[error("No default model")]
|
||||||
|
NoDefaultModel,
|
||||||
|
#[error("No default network")]
|
||||||
|
NoDefaultNetwork,
|
||||||
|
#[error("No allocation available")]
|
||||||
|
NoAllocation,
|
||||||
|
#[error("Resource in use: {0}")]
|
||||||
|
ResourceInUse(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type GlobalStateManagerResult<T> = Result<T, GlobalStateManagerError>;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct GlobalStateManager {
|
||||||
|
unlocked_inner: Arc<GlobalStateManagerUnlockedInner>,
|
||||||
|
inner: Arc<Mutex<GlobalStateManagerInner>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GlobalStateManager {
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
/// Public Interface
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let unlocked_inner = Arc::new(GlobalStateManagerUnlockedInner {});
|
||||||
|
Self {
|
||||||
|
inner: Arc::new(Mutex::new(GlobalStateManagerInner::new(
|
||||||
|
unlocked_inner.clone(),
|
||||||
|
))),
|
||||||
|
unlocked_inner,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn execute_config(&self, cfg: config::Config) -> GlobalStateManagerResult<()> {
|
||||||
|
let mut inner = self.inner.lock();
|
||||||
|
let saved_state = (*inner).clone();
|
||||||
|
match inner.execute_config(cfg) {
|
||||||
|
Ok(v) => Ok(v),
|
||||||
|
Err(e) => {
|
||||||
|
*inner = saved_state;
|
||||||
|
Err(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn allocate(&self, profile: String) -> GlobalStateManagerResult<MachineId> {
|
||||||
|
let mut inner = self.inner.lock();
|
||||||
|
let saved_state = (*inner).clone();
|
||||||
|
match inner.allocate(profile) {
|
||||||
|
Ok(v) => Ok(v),
|
||||||
|
Err(e) => {
|
||||||
|
*inner = saved_state;
|
||||||
|
Err(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn release(&self, machine_id: MachineId) -> GlobalStateManagerResult<()> {
|
||||||
|
let mut inner = self.inner.lock();
|
||||||
|
let saved_state = (*inner).clone();
|
||||||
|
match inner.release(machine_id) {
|
||||||
|
Ok(v) => Ok(v),
|
||||||
|
Err(e) => {
|
||||||
|
*inner = saved_state;
|
||||||
|
Err(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -69,7 +69,7 @@ pub struct BlueprintState {
|
|||||||
pub type BlueprintStateId = StateId<BlueprintState>;
|
pub type BlueprintStateId = StateId<BlueprintState>;
|
||||||
|
|
||||||
impl BlueprintState {
|
impl BlueprintState {
|
||||||
pub fn new(id: BlueprintStateId, name: String) -> MachineRegistryResult<BlueprintState> {
|
pub fn new(id: BlueprintStateId, name: String) -> GlobalStateManagerResult<BlueprintState> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
immutable: Arc::new(BlueprintStateImmutable { id, name }),
|
immutable: Arc::new(BlueprintStateImmutable { id, name }),
|
||||||
fields: Arc::new(BlueprintStateFields {
|
fields: Arc::new(BlueprintStateFields {
|
||||||
@ -165,18 +165,18 @@ impl BlueprintState {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_active(&self, machine_registry_inner: &mut MachineRegistryInner) -> bool {
|
pub fn is_active(&self, gsm_inner: &mut GlobalStateManagerInner) -> bool {
|
||||||
// Save a backup of the entire state
|
// Save a backup of the entire state
|
||||||
let backup = machine_registry_inner.clone();
|
let backup = gsm_inner.clone();
|
||||||
|
|
||||||
// Make a copy of this blueprint state
|
// Make a copy of this blueprint state
|
||||||
let mut current_state = self.clone();
|
let mut current_state = self.clone();
|
||||||
|
|
||||||
// See what would happen if we try to generate this blueprint
|
// See what would happen if we try to generate this blueprint
|
||||||
let ok = current_state.generate(machine_registry_inner).is_ok();
|
let ok = current_state.generate(gsm_inner).is_ok();
|
||||||
|
|
||||||
// Restore the backup
|
// Restore the backup
|
||||||
*machine_registry_inner = backup;
|
*gsm_inner = backup;
|
||||||
|
|
||||||
// Return if this worked or not
|
// Return if this worked or not
|
||||||
ok
|
ok
|
||||||
@ -184,20 +184,16 @@ impl BlueprintState {
|
|||||||
|
|
||||||
fn generate_model_inner(
|
fn generate_model_inner(
|
||||||
&mut self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
network_state: &mut NetworkState,
|
network_state: &mut NetworkState,
|
||||||
) -> MachineRegistryResult<()> {
|
) -> GlobalStateManagerResult<()> {
|
||||||
let model_name = match self.fields.model.as_ref() {
|
let Some(model_list) = self.fields.model.as_ref() else {
|
||||||
Some(models) => (**machine_registry_inner.srng().weighted_choice_ref(models)).clone(),
|
return Err(GlobalStateManagerError::NoDefaultModel);
|
||||||
None => machine_registry_inner
|
|
||||||
.config()
|
|
||||||
.default_model
|
|
||||||
.as_ref()
|
|
||||||
.ok_or(MachineRegistryError::NoDefaultModel)?
|
|
||||||
.clone(),
|
|
||||||
};
|
};
|
||||||
let Some(model) = machine_registry_inner.config().models.get(&model_name) else {
|
let model_name = (**gsm_inner.srng().weighted_choice_ref(model_list)).clone();
|
||||||
return Err(MachineRegistryError::ModelNotFound);
|
|
||||||
|
let Some(model) = gsm_inner.models().get(&model_name) else {
|
||||||
|
return Err(GlobalStateManagerError::ModelNotFound(model_name));
|
||||||
};
|
};
|
||||||
|
|
||||||
let params = NetworkStateModelParams {
|
let params = NetworkStateModelParams {
|
||||||
@ -212,13 +208,11 @@ impl BlueprintState {
|
|||||||
/// Network filter that ensures we can allocate an ipv4 gateway address on a network
|
/// Network filter that ensures we can allocate an ipv4 gateway address on a network
|
||||||
fn gateway_network_filter_v4(
|
fn gateway_network_filter_v4(
|
||||||
&self,
|
&self,
|
||||||
machine_registry_inner: &MachineRegistryInner,
|
gsm_inner: &GlobalStateManagerInner,
|
||||||
network_state_id: NetworkStateId,
|
network_state_id: NetworkStateId,
|
||||||
) -> MachineRegistryResult<bool> {
|
) -> GlobalStateManagerResult<bool> {
|
||||||
// Get the network state
|
// Get the network state
|
||||||
let network_state = machine_registry_inner
|
let network_state = gsm_inner.network_states().get_state(network_state_id)?;
|
||||||
.network_states()
|
|
||||||
.get_state(network_state_id)?;
|
|
||||||
|
|
||||||
// See if we can allocate on this network
|
// See if we can allocate on this network
|
||||||
let can_allocate = network_state.can_allocate_address_v4(None);
|
let can_allocate = network_state.can_allocate_address_v4(None);
|
||||||
@ -229,13 +223,11 @@ impl BlueprintState {
|
|||||||
/// Network filter that ensures we can allocate an ipv4 gateway address on a network
|
/// Network filter that ensures we can allocate an ipv4 gateway address on a network
|
||||||
fn gateway_network_filter_v6(
|
fn gateway_network_filter_v6(
|
||||||
&self,
|
&self,
|
||||||
machine_registry_inner: &MachineRegistryInner,
|
gsm_inner: &GlobalStateManagerInner,
|
||||||
network_state_id: NetworkStateId,
|
network_state_id: NetworkStateId,
|
||||||
) -> MachineRegistryResult<bool> {
|
) -> GlobalStateManagerResult<bool> {
|
||||||
// Get the network state
|
// Get the network state
|
||||||
let network_state = machine_registry_inner
|
let network_state = gsm_inner.network_states().get_state(network_state_id)?;
|
||||||
.network_states()
|
|
||||||
.get_state(network_state_id)?;
|
|
||||||
|
|
||||||
// See if we can allocate on this network
|
// See if we can allocate on this network
|
||||||
let can_allocate = network_state.can_allocate_address_v6(None);
|
let can_allocate = network_state.can_allocate_address_v6(None);
|
||||||
@ -245,19 +237,24 @@ impl BlueprintState {
|
|||||||
|
|
||||||
fn generate_ipv4_inner(
|
fn generate_ipv4_inner(
|
||||||
&mut self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
network_state: &mut NetworkState,
|
network_state: &mut NetworkState,
|
||||||
) -> MachineRegistryResult<()> {
|
) -> GlobalStateManagerResult<()> {
|
||||||
network_state.clear_ipv4(machine_registry_inner)?;
|
network_state.clear_ipv4(gsm_inner)?;
|
||||||
let Some(ipv4) = self.fields.ipv4.as_ref() else {
|
let Some(ipv4) = self.fields.ipv4.as_ref() else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get addresses for network
|
// Get addresses for network
|
||||||
let NetworkLocation { subnet, super_net } = ipv4
|
let Some(NetworkLocation { subnet, super_net }) = ipv4
|
||||||
.params
|
.params
|
||||||
.locations
|
.locations
|
||||||
.pick_v4(machine_registry_inner, &ipv4.params.prefix)?;
|
.pick_v4(gsm_inner, &ipv4.params.prefix)?
|
||||||
|
else {
|
||||||
|
return Err(GlobalStateManagerError::BlueprintComplete(
|
||||||
|
self.debug_name(),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
let params = NetworkStateIpv4Params {
|
let params = NetworkStateIpv4Params {
|
||||||
allocation: subnet,
|
allocation: subnet,
|
||||||
@ -266,35 +263,37 @@ impl BlueprintState {
|
|||||||
|
|
||||||
let gateway_params = match ipv4.gateway.as_ref() {
|
let gateway_params = match ipv4.gateway.as_ref() {
|
||||||
Some(v4gw) => {
|
Some(v4gw) => {
|
||||||
let translation = *machine_registry_inner
|
let translation = *gsm_inner
|
||||||
.srng()
|
.srng()
|
||||||
.weighted_choice_ref(&v4gw.params.translation);
|
.weighted_choice_ref(&v4gw.params.translation);
|
||||||
let upnp = machine_registry_inner
|
let upnp = gsm_inner.srng().probability_test(v4gw.params.upnp);
|
||||||
.srng()
|
|
||||||
.probability_test(v4gw.params.upnp);
|
|
||||||
|
|
||||||
let (external_network, external_address) = match v4gw.params.locations.as_ref() {
|
let (external_network, external_address) = match v4gw.params.locations.as_ref() {
|
||||||
Some(locations_list) => {
|
Some(locations_list) => {
|
||||||
// A external network location was specified, pick one
|
// A external network location was specified, pick one
|
||||||
// Get a network to generate the machine on
|
// Get a network to generate the machine on
|
||||||
let mut gateway_network_state = locations_list.pick(
|
let Some(mut gateway_network_state) = locations_list
|
||||||
machine_registry_inner,
|
.pick(gsm_inner, |gsm_inner, id| {
|
||||||
|machine_registry_inner, id| {
|
self.gateway_network_filter_v4(gsm_inner, id)
|
||||||
self.gateway_network_filter_v4(machine_registry_inner, id)
|
})?
|
||||||
},
|
else {
|
||||||
)?;
|
return Err(GlobalStateManagerError::BlueprintComplete(
|
||||||
|
self.debug_name(),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
let gateway_network_state_id = gateway_network_state.id();
|
let gateway_network_state_id = gateway_network_state.id();
|
||||||
|
|
||||||
// Allocate an external address on this network
|
// Allocate an external address on this network
|
||||||
let external_interface_address = gateway_network_state
|
let external_interface_address = gateway_network_state
|
||||||
.allocate_address_v4(
|
.allocate_address_v4(
|
||||||
machine_registry_inner,
|
gsm_inner,
|
||||||
OwnerTag::Gateway(network_state.id()),
|
OwnerTag::Gateway(network_state.id()),
|
||||||
None,
|
None,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Update the network state
|
// Update the network state
|
||||||
machine_registry_inner
|
gsm_inner
|
||||||
.network_states_mut()
|
.network_states_mut()
|
||||||
.set_state(gateway_network_state);
|
.set_state(gateway_network_state);
|
||||||
|
|
||||||
@ -321,25 +320,30 @@ impl BlueprintState {
|
|||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
network_state.set_ipv4(machine_registry_inner, params, gateway_params)?;
|
network_state.set_ipv4(gsm_inner, params, gateway_params)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_ipv6_inner(
|
fn generate_ipv6_inner(
|
||||||
&mut self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
network_state: &mut NetworkState,
|
network_state: &mut NetworkState,
|
||||||
) -> MachineRegistryResult<()> {
|
) -> GlobalStateManagerResult<()> {
|
||||||
network_state.clear_ipv6(machine_registry_inner)?;
|
network_state.clear_ipv6(gsm_inner)?;
|
||||||
let Some(ipv6) = self.fields.ipv6.as_ref() else {
|
let Some(ipv6) = self.fields.ipv6.as_ref() else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get addresses for network
|
// Get addresses for network
|
||||||
let NetworkLocation { subnet, super_net } = ipv6
|
let Some(NetworkLocation { subnet, super_net }) = ipv6
|
||||||
.params
|
.params
|
||||||
.locations
|
.locations
|
||||||
.pick_v6(machine_registry_inner, &ipv6.params.prefix)?;
|
.pick_v6(gsm_inner, &ipv6.params.prefix)?
|
||||||
|
else {
|
||||||
|
return Err(GlobalStateManagerError::BlueprintComplete(
|
||||||
|
self.debug_name(),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
let params = NetworkStateIpv6Params {
|
let params = NetworkStateIpv6Params {
|
||||||
allocation: subnet,
|
allocation: subnet,
|
||||||
@ -348,35 +352,37 @@ impl BlueprintState {
|
|||||||
|
|
||||||
let gateway_params = match ipv6.gateway.as_ref() {
|
let gateway_params = match ipv6.gateway.as_ref() {
|
||||||
Some(v6gw) => {
|
Some(v6gw) => {
|
||||||
let translation = *machine_registry_inner
|
let translation = *gsm_inner
|
||||||
.srng()
|
.srng()
|
||||||
.weighted_choice_ref(&v6gw.params.translation);
|
.weighted_choice_ref(&v6gw.params.translation);
|
||||||
let upnp = machine_registry_inner
|
let upnp = gsm_inner.srng().probability_test(v6gw.params.upnp);
|
||||||
.srng()
|
|
||||||
.probability_test(v6gw.params.upnp);
|
|
||||||
|
|
||||||
let (external_network, external_address) = match v6gw.params.locations.as_ref() {
|
let (external_network, external_address) = match v6gw.params.locations.as_ref() {
|
||||||
Some(locations_list) => {
|
Some(locations_list) => {
|
||||||
// A external network location was specified, pick one
|
// A external network location was specified, pick one
|
||||||
// Get a network to generate the machine on
|
// Get a network to generate the machine on
|
||||||
let mut gateway_network_state = locations_list.pick(
|
let Some(mut gateway_network_state) = locations_list
|
||||||
machine_registry_inner,
|
.pick(gsm_inner, |gsm_inner, id| {
|
||||||
|machine_registry_inner, id| {
|
self.gateway_network_filter_v6(gsm_inner, id)
|
||||||
self.gateway_network_filter_v6(machine_registry_inner, id)
|
})?
|
||||||
},
|
else {
|
||||||
)?;
|
return Err(GlobalStateManagerError::BlueprintComplete(
|
||||||
|
self.debug_name(),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
let gateway_network_state_id = gateway_network_state.id();
|
let gateway_network_state_id = gateway_network_state.id();
|
||||||
|
|
||||||
// Allocate an external address on this network
|
// Allocate an external address on this network
|
||||||
let external_interface_address = gateway_network_state
|
let external_interface_address = gateway_network_state
|
||||||
.allocate_address_v6(
|
.allocate_address_v6(
|
||||||
machine_registry_inner,
|
gsm_inner,
|
||||||
OwnerTag::Gateway(network_state.id()),
|
OwnerTag::Gateway(network_state.id()),
|
||||||
None,
|
None,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Update the network state
|
// Update the network state
|
||||||
machine_registry_inner
|
gsm_inner
|
||||||
.network_states_mut()
|
.network_states_mut()
|
||||||
.set_state(gateway_network_state);
|
.set_state(gateway_network_state);
|
||||||
|
|
||||||
@ -403,37 +409,39 @@ impl BlueprintState {
|
|||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
network_state.set_ipv6(machine_registry_inner, params, gateway_params)?;
|
network_state.set_ipv6(gsm_inner, params, gateway_params)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate(
|
pub fn generate(
|
||||||
&mut self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
) -> MachineRegistryResult<NetworkStateId> {
|
) -> GlobalStateManagerResult<NetworkStateId> {
|
||||||
// See if there's room for another network
|
// See if there's room for another network
|
||||||
if let Some(limit_network_count) = self.fields.limit_network_count {
|
if let Some(limit_network_count) = self.fields.limit_network_count {
|
||||||
if self.fields.networks.len() >= limit_network_count {
|
if self.fields.networks.len() >= limit_network_count {
|
||||||
return Err(MachineRegistryError::BlueprintComplete);
|
return Err(GlobalStateManagerError::BlueprintComplete(
|
||||||
|
self.debug_name(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate a network id
|
// Allocate a network id
|
||||||
let network_state_id = machine_registry_inner.network_states_mut().allocate_id();
|
let network_state_id = gsm_inner.network_states_mut().allocate_id();
|
||||||
|
|
||||||
// Create an anonymous network state
|
// Create an anonymous network state
|
||||||
let mut network_state =
|
let mut network_state =
|
||||||
NetworkState::new(network_state_id, None, NetworkOrigin::Blueprint(self.id()));
|
NetworkState::new(network_state_id, None, NetworkOrigin::Blueprint(self.id()));
|
||||||
|
|
||||||
if let Err(e) = (|| {
|
if let Err(e) = (|| {
|
||||||
self.generate_model_inner(machine_registry_inner, &mut network_state)?;
|
self.generate_model_inner(gsm_inner, &mut network_state)?;
|
||||||
self.generate_ipv4_inner(machine_registry_inner, &mut network_state)?;
|
self.generate_ipv4_inner(gsm_inner, &mut network_state)?;
|
||||||
self.generate_ipv6_inner(machine_registry_inner, &mut network_state)?;
|
self.generate_ipv6_inner(gsm_inner, &mut network_state)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})() {
|
})() {
|
||||||
// Release the network state and id if things failed to allocate
|
// Release the network state and id if things failed to allocate
|
||||||
network_state.release(machine_registry_inner);
|
network_state.release(gsm_inner);
|
||||||
machine_registry_inner
|
gsm_inner
|
||||||
.network_states_mut()
|
.network_states_mut()
|
||||||
.release_id(network_state_id)
|
.release_id(network_state_id)
|
||||||
.expect("must succeed");
|
.expect("must succeed");
|
||||||
@ -441,9 +449,7 @@ impl BlueprintState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Attach the state to the id
|
// Attach the state to the id
|
||||||
machine_registry_inner
|
gsm_inner.network_states_mut().attach_state(network_state)?;
|
||||||
.network_states_mut()
|
|
||||||
.attach_state(network_state)?;
|
|
||||||
|
|
||||||
// Record the newly instantiated network
|
// Record the newly instantiated network
|
||||||
let mut networks = self.fields.networks.clone();
|
let mut networks = self.fields.networks.clone();
|
||||||
@ -458,9 +464,9 @@ impl BlueprintState {
|
|||||||
Ok(network_state_id)
|
Ok(network_state_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn for_each_network_id<F, R>(&self, mut callback: F) -> MachineRegistryResult<Option<R>>
|
pub fn for_each_network_id<F, R>(&self, mut callback: F) -> GlobalStateManagerResult<Option<R>>
|
||||||
where
|
where
|
||||||
F: FnMut(NetworkStateId) -> MachineRegistryResult<Option<R>>,
|
F: FnMut(NetworkStateId) -> GlobalStateManagerResult<Option<R>>,
|
||||||
{
|
{
|
||||||
for network_id in &self.fields.networks {
|
for network_id in &self.fields.networks {
|
||||||
if let Some(res) = callback(*network_id)? {
|
if let Some(res) = callback(*network_id)? {
|
@ -20,24 +20,19 @@ pub enum MachineLocationsList {
|
|||||||
impl MachineLocationsList {
|
impl MachineLocationsList {
|
||||||
pub fn can_pick<F>(
|
pub fn can_pick<F>(
|
||||||
&self,
|
&self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
mut network_filter: F,
|
mut network_filter: F,
|
||||||
) -> MachineRegistryResult<bool>
|
) -> GlobalStateManagerResult<bool>
|
||||||
where
|
where
|
||||||
F: FnMut(&MachineRegistryInner, NetworkStateId) -> MachineRegistryResult<bool>,
|
F: FnMut(&GlobalStateManagerInner, NetworkStateId) -> GlobalStateManagerResult<bool>,
|
||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
MachineLocationsList::Networks { networks } => {
|
MachineLocationsList::Networks { networks } => {
|
||||||
// Filter the weighted list of networks to those that are still active and or not yet started
|
// Filter the weighted list of networks to those that are still active and or not yet started
|
||||||
if networks
|
if networks
|
||||||
.try_filter(|id| {
|
.try_filter(|id| {
|
||||||
let network_state =
|
let network_state = gsm_inner.network_states().get_state(*id)?;
|
||||||
machine_registry_inner.network_states().get_state(*id)?;
|
self.is_network_available(gsm_inner, network_state, &mut network_filter)
|
||||||
self.is_network_available(
|
|
||||||
machine_registry_inner,
|
|
||||||
network_state,
|
|
||||||
&mut network_filter,
|
|
||||||
)
|
|
||||||
})?
|
})?
|
||||||
.is_none()
|
.is_none()
|
||||||
{
|
{
|
||||||
@ -48,14 +43,9 @@ impl MachineLocationsList {
|
|||||||
// Filter the weighted list of blueprints to those that are still active or not yet started and can allocate
|
// Filter the weighted list of blueprints to those that are still active or not yet started and can allocate
|
||||||
if blueprints
|
if blueprints
|
||||||
.try_filter(|id| {
|
.try_filter(|id| {
|
||||||
let blueprint_state =
|
let blueprint_state = gsm_inner.blueprint_states().get_state(*id)?;
|
||||||
machine_registry_inner.blueprint_states().get_state(*id)?;
|
|
||||||
|
|
||||||
self.is_blueprint_available(
|
self.is_blueprint_available(gsm_inner, blueprint_state, &mut network_filter)
|
||||||
machine_registry_inner,
|
|
||||||
blueprint_state,
|
|
||||||
&mut network_filter,
|
|
||||||
)
|
|
||||||
.map(|x| x.is_some())
|
.map(|x| x.is_some())
|
||||||
})?
|
})?
|
||||||
.is_none()
|
.is_none()
|
||||||
@ -69,20 +59,20 @@ impl MachineLocationsList {
|
|||||||
|
|
||||||
pub fn pick<F>(
|
pub fn pick<F>(
|
||||||
&self,
|
&self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
mut network_filter: F,
|
mut network_filter: F,
|
||||||
) -> MachineRegistryResult<NetworkState>
|
) -> GlobalStateManagerResult<Option<NetworkState>>
|
||||||
where
|
where
|
||||||
F: FnMut(&MachineRegistryInner, NetworkStateId) -> MachineRegistryResult<bool>,
|
F: FnMut(&GlobalStateManagerInner, NetworkStateId) -> GlobalStateManagerResult<bool>,
|
||||||
{
|
{
|
||||||
// Get a network to generate the machine on
|
// Get a network to generate the machine on
|
||||||
let network_state = match self {
|
let network_state = match self {
|
||||||
MachineLocationsList::Networks { networks } => {
|
MachineLocationsList::Networks { networks } => {
|
||||||
// Filter the weighted list of networks to those that are still active and or not yet started
|
// Filter the weighted list of networks to those that are still active and or not yet started
|
||||||
let Some(available_networks) = networks.try_filter_map(|id| {
|
let Some(available_networks) = networks.try_filter_map(|id| {
|
||||||
let network_state = machine_registry_inner.network_states().get_state(*id)?;
|
let network_state = gsm_inner.network_states().get_state(*id)?;
|
||||||
if self.is_network_available(
|
if self.is_network_available(
|
||||||
machine_registry_inner,
|
gsm_inner,
|
||||||
network_state.clone(),
|
network_state.clone(),
|
||||||
&mut network_filter,
|
&mut network_filter,
|
||||||
)? {
|
)? {
|
||||||
@ -92,13 +82,11 @@ impl MachineLocationsList {
|
|||||||
}
|
}
|
||||||
})?
|
})?
|
||||||
else {
|
else {
|
||||||
return Err(MachineRegistryError::NetworkComplete);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Weighted choice of network now that we have a candidate list
|
// Weighted choice of network now that we have a candidate list
|
||||||
let network_state = machine_registry_inner
|
let network_state = gsm_inner.srng().weighted_choice(available_networks);
|
||||||
.srng()
|
|
||||||
.weighted_choice(available_networks);
|
|
||||||
|
|
||||||
// Return network state to use
|
// Return network state to use
|
||||||
network_state
|
network_state
|
||||||
@ -106,54 +94,42 @@ impl MachineLocationsList {
|
|||||||
MachineLocationsList::Blueprints { blueprints } => {
|
MachineLocationsList::Blueprints { blueprints } => {
|
||||||
// Filter the weighted list of blueprints to those that are still active or not yet started and can allocate
|
// Filter the weighted list of blueprints to those that are still active or not yet started and can allocate
|
||||||
let Some(available_blueprints) = blueprints.try_filter_map(|id| {
|
let Some(available_blueprints) = blueprints.try_filter_map(|id| {
|
||||||
let blueprint_state =
|
let blueprint_state = gsm_inner.blueprint_states().get_state(*id)?;
|
||||||
machine_registry_inner.blueprint_states().get_state(*id)?;
|
|
||||||
|
|
||||||
self.is_blueprint_available(
|
self.is_blueprint_available(gsm_inner, blueprint_state, &mut network_filter)
|
||||||
machine_registry_inner,
|
|
||||||
blueprint_state,
|
|
||||||
&mut network_filter,
|
|
||||||
)
|
|
||||||
})?
|
})?
|
||||||
else {
|
else {
|
||||||
return Err(MachineRegistryError::BlueprintComplete);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Weighted choice of blueprint now that we have a candidate list
|
// Weighted choice of blueprint now that we have a candidate list
|
||||||
match machine_registry_inner
|
match gsm_inner.srng().weighted_choice(available_blueprints) {
|
||||||
.srng()
|
|
||||||
.weighted_choice(available_blueprints)
|
|
||||||
{
|
|
||||||
BlueprintAvailability::Existing(network_state) => network_state,
|
BlueprintAvailability::Existing(network_state) => network_state,
|
||||||
BlueprintAvailability::Generate(mut blueprint_state) => {
|
BlueprintAvailability::Generate(mut blueprint_state) => {
|
||||||
// Generate network state from blueprint state
|
// Generate network state from blueprint state
|
||||||
let network_state_id = blueprint_state.generate(machine_registry_inner)?;
|
let network_state_id = blueprint_state.generate(gsm_inner)?;
|
||||||
|
|
||||||
// Update blueprint state
|
// Update blueprint state
|
||||||
machine_registry_inner
|
gsm_inner.blueprint_states_mut().set_state(blueprint_state);
|
||||||
.blueprint_states_mut()
|
|
||||||
.set_state(blueprint_state);
|
|
||||||
|
|
||||||
// Return network state
|
// Return network state
|
||||||
machine_registry_inner
|
gsm_inner.network_states().get_state(network_state_id)?
|
||||||
.network_states()
|
|
||||||
.get_state(network_state_id)?
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(network_state)
|
Ok(Some(network_state))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_network_available<F>(
|
fn is_network_available<F>(
|
||||||
&self,
|
&self,
|
||||||
machine_registry_inner: &MachineRegistryInner,
|
gsm_inner: &GlobalStateManagerInner,
|
||||||
network_state: NetworkState,
|
network_state: NetworkState,
|
||||||
mut network_filter: F,
|
mut network_filter: F,
|
||||||
) -> MachineRegistryResult<bool>
|
) -> GlobalStateManagerResult<bool>
|
||||||
where
|
where
|
||||||
F: FnMut(&MachineRegistryInner, NetworkStateId) -> MachineRegistryResult<bool>,
|
F: FnMut(&GlobalStateManagerInner, NetworkStateId) -> GlobalStateManagerResult<bool>,
|
||||||
{
|
{
|
||||||
// If the network is not active, it is not available
|
// If the network is not active, it is not available
|
||||||
if !network_state.is_active()? {
|
if !network_state.is_active()? {
|
||||||
@ -161,7 +137,7 @@ impl MachineLocationsList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check the network filter
|
// Check the network filter
|
||||||
if !network_filter(machine_registry_inner, network_state.id())? {
|
if !network_filter(gsm_inner, network_state.id())? {
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,23 +146,19 @@ impl MachineLocationsList {
|
|||||||
|
|
||||||
fn is_blueprint_available<F>(
|
fn is_blueprint_available<F>(
|
||||||
&self,
|
&self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
blueprint_state: BlueprintState,
|
blueprint_state: BlueprintState,
|
||||||
mut network_filter: F,
|
mut network_filter: F,
|
||||||
) -> MachineRegistryResult<Option<BlueprintAvailability>>
|
) -> GlobalStateManagerResult<Option<BlueprintAvailability>>
|
||||||
where
|
where
|
||||||
F: FnMut(&MachineRegistryInner, NetworkStateId) -> MachineRegistryResult<bool>,
|
F: FnMut(&GlobalStateManagerInner, NetworkStateId) -> GlobalStateManagerResult<bool>,
|
||||||
{
|
{
|
||||||
// See if the networks generated from this blueprint so far have availability
|
// See if the networks generated from this blueprint so far have availability
|
||||||
// in this template
|
// in this template
|
||||||
if let Some(available_network_state) = blueprint_state.for_each_network_id(|id| {
|
if let Some(available_network_state) = blueprint_state.for_each_network_id(|id| {
|
||||||
// Check the network's availability
|
// Check the network's availability
|
||||||
let network_state = machine_registry_inner.network_states().get_state(id)?;
|
let network_state = gsm_inner.network_states().get_state(id)?;
|
||||||
if self.is_network_available(
|
if self.is_network_available(gsm_inner, network_state.clone(), &mut network_filter)? {
|
||||||
machine_registry_inner,
|
|
||||||
network_state.clone(),
|
|
||||||
&mut network_filter,
|
|
||||||
)? {
|
|
||||||
// We found one
|
// We found one
|
||||||
return Ok(Some(network_state));
|
return Ok(Some(network_state));
|
||||||
}
|
}
|
||||||
@ -200,7 +172,7 @@ impl MachineLocationsList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If the blueprint is active, it is available because it can make a new network
|
// If the blueprint is active, it is available because it can make a new network
|
||||||
if blueprint_state.is_active(machine_registry_inner) {
|
if blueprint_state.is_active(gsm_inner) {
|
||||||
return Ok(Some(BlueprintAvailability::Generate(blueprint_state)));
|
return Ok(Some(BlueprintAvailability::Generate(blueprint_state)));
|
||||||
}
|
}
|
||||||
|
|
@ -60,17 +60,17 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn release(mut self, machine_registry_inner: &mut MachineRegistryInner) {
|
pub fn release(mut self, gsm_inner: &mut GlobalStateManagerInner) {
|
||||||
self.release_all_interfaces(machine_registry_inner)
|
self.release_all_interfaces(gsm_inner)
|
||||||
.expect("must succeed");
|
.expect("must succeed");
|
||||||
|
|
||||||
if let MachineOrigin::Template(generating_template) = self.immutable.origin {
|
if let MachineOrigin::Template(generating_template) = self.immutable.origin {
|
||||||
let mut template_state = machine_registry_inner
|
let mut template_state = gsm_inner
|
||||||
.template_states()
|
.template_states()
|
||||||
.get_state(generating_template)
|
.get_state(generating_template)
|
||||||
.expect("must exist");
|
.expect("must exist");
|
||||||
template_state.on_machine_released(self.id());
|
template_state.on_machine_released(self.id());
|
||||||
machine_registry_inner
|
gsm_inner
|
||||||
.template_states_mut()
|
.template_states_mut()
|
||||||
.set_state(template_state);
|
.set_state(template_state);
|
||||||
}
|
}
|
||||||
@ -105,12 +105,14 @@ impl MachineState {
|
|||||||
&mut self,
|
&mut self,
|
||||||
interface_name: Option<String>,
|
interface_name: Option<String>,
|
||||||
opt_interface_flags: Option<InterfaceFlags>,
|
opt_interface_flags: Option<InterfaceFlags>,
|
||||||
) -> MachineRegistryResult<Arc<String>> {
|
) -> GlobalStateManagerResult<Arc<String>> {
|
||||||
let interface_key = interface_name
|
let interface_key = interface_name
|
||||||
.map(Arc::new)
|
.map(Arc::new)
|
||||||
.unwrap_or_else(|| self.next_free_interface_key());
|
.unwrap_or_else(|| self.next_free_interface_key());
|
||||||
if self.fields.interfaces.contains_key(&interface_key) {
|
if self.fields.interfaces.contains_key(&interface_key) {
|
||||||
return Err(MachineRegistryError::DuplicateName);
|
return Err(GlobalStateManagerError::DuplicateName(
|
||||||
|
(*interface_key).clone(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
let flags = opt_interface_flags.unwrap_or(InterfaceFlags {
|
let flags = opt_interface_flags.unwrap_or(InterfaceFlags {
|
||||||
is_loopback: false,
|
is_loopback: false,
|
||||||
@ -146,35 +148,39 @@ impl MachineState {
|
|||||||
|
|
||||||
pub fn allocate_address_ipv4(
|
pub fn allocate_address_ipv4(
|
||||||
&mut self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
interface_name: &str,
|
interface_name: &str,
|
||||||
opt_address: Option<Ipv4Addr>,
|
opt_address: Option<Ipv4Addr>,
|
||||||
opt_address_flags: Option<AddressFlags>,
|
opt_address_flags: Option<AddressFlags>,
|
||||||
) -> MachineRegistryResult<Ifv4Addr> {
|
) -> GlobalStateManagerResult<Ifv4Addr> {
|
||||||
let interface_key = Arc::new(interface_name.to_string());
|
let interface_key = Arc::new(interface_name.to_string());
|
||||||
let Some(mut machine_state_interface) = self.fields.interfaces.get(&interface_key).cloned()
|
let Some(mut machine_state_interface) = self.fields.interfaces.get(&interface_key).cloned()
|
||||||
else {
|
else {
|
||||||
return Err(MachineRegistryError::InvalidName);
|
return Err(GlobalStateManagerError::InvalidName(
|
||||||
|
(*interface_key).clone(),
|
||||||
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get the network state
|
// Get the network state
|
||||||
let Some(network_id) = machine_state_interface.network_id else {
|
let Some(network_id) = machine_state_interface.network_id else {
|
||||||
return Err(MachineRegistryError::NetworkNotFound);
|
return Err(GlobalStateManagerError::NetworkNotFound(
|
||||||
|
(*interface_key).clone(),
|
||||||
|
));
|
||||||
};
|
};
|
||||||
let mut network_state = machine_registry_inner
|
let mut network_state = gsm_inner
|
||||||
.network_states()
|
.network_states()
|
||||||
.get_state(network_id)?;
|
.get_state(network_id)?;
|
||||||
|
|
||||||
// Allocate interface address
|
// Allocate interface address
|
||||||
let is_dynamic = opt_address.is_none();
|
let is_dynamic = opt_address.is_none();
|
||||||
let ifv4_addr = network_state.allocate_address_v4(
|
let ifv4_addr = network_state.allocate_address_v4(
|
||||||
machine_registry_inner,
|
gsm_inner,
|
||||||
OwnerTag::Machine(self.id()),
|
OwnerTag::Machine(self.id()),
|
||||||
opt_address,
|
opt_address,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Update the network state
|
// Update the network state
|
||||||
machine_registry_inner
|
gsm_inner
|
||||||
.network_states_mut()
|
.network_states_mut()
|
||||||
.set_state(network_state);
|
.set_state(network_state);
|
||||||
|
|
||||||
@ -212,34 +218,38 @@ impl MachineState {
|
|||||||
|
|
||||||
pub fn allocate_address_ipv6(
|
pub fn allocate_address_ipv6(
|
||||||
&mut self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
interface_name: &str,
|
interface_name: &str,
|
||||||
opt_address: Option<Ipv6Addr>,
|
opt_address: Option<Ipv6Addr>,
|
||||||
opt_address_flags: Option<AddressFlags>,
|
opt_address_flags: Option<AddressFlags>,
|
||||||
) -> MachineRegistryResult<Ifv6Addr> {
|
) -> GlobalStateManagerResult<Ifv6Addr> {
|
||||||
let interface_key = Arc::new(interface_name.to_string());
|
let interface_key = Arc::new(interface_name.to_string());
|
||||||
let Some(mut machine_state_interface) = self.fields.interfaces.get(&interface_key).cloned()
|
let Some(mut machine_state_interface) = self.fields.interfaces.get(&interface_key).cloned()
|
||||||
else {
|
else {
|
||||||
return Err(MachineRegistryError::InvalidName);
|
return Err(GlobalStateManagerError::InvalidName(
|
||||||
|
(*interface_key).clone(),
|
||||||
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get the network state
|
// Get the network state
|
||||||
let Some(network_id) = machine_state_interface.network_id else {
|
let Some(network_id) = machine_state_interface.network_id else {
|
||||||
return Err(MachineRegistryError::NetworkNotFound);
|
return Err(GlobalStateManagerError::NetworkNotFound(
|
||||||
|
(*interface_key).clone(),
|
||||||
|
));
|
||||||
};
|
};
|
||||||
let mut network_state = machine_registry_inner
|
let mut network_state = gsm_inner
|
||||||
.network_states()
|
.network_states()
|
||||||
.get_state(network_id)?;
|
.get_state(network_id)?;
|
||||||
|
|
||||||
// Allocate interface address
|
// Allocate interface address
|
||||||
let is_dynamic = opt_address.is_none();
|
let is_dynamic = opt_address.is_none();
|
||||||
let ifv6_addr = network_state.allocate_address_v6(
|
let ifv6_addr = network_state.allocate_address_v6(
|
||||||
machine_registry_inner,
|
gsm_inner,
|
||||||
OwnerTag::Machine(self.id()),
|
OwnerTag::Machine(self.id()),
|
||||||
opt_address,
|
opt_address,
|
||||||
)?;
|
)?;
|
||||||
// Update the network state
|
// Update the network state
|
||||||
machine_registry_inner
|
gsm_inner
|
||||||
.network_states_mut()
|
.network_states_mut()
|
||||||
.set_state(network_state);
|
.set_state(network_state);
|
||||||
|
|
||||||
@ -277,18 +287,20 @@ impl MachineState {
|
|||||||
|
|
||||||
pub fn attach_network(
|
pub fn attach_network(
|
||||||
&mut self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
interface_name: &str,
|
interface_name: &str,
|
||||||
network_id: NetworkStateId,
|
network_id: NetworkStateId,
|
||||||
) -> MachineRegistryResult<()> {
|
) -> GlobalStateManagerResult<()> {
|
||||||
let interface_key = Arc::new(interface_name.to_string());
|
let interface_key = Arc::new(interface_name.to_string());
|
||||||
let Some(mut machine_state_interface) = self.fields.interfaces.get(&interface_key).cloned()
|
let Some(mut machine_state_interface) = self.fields.interfaces.get(&interface_key).cloned()
|
||||||
else {
|
else {
|
||||||
return Err(MachineRegistryError::InvalidName);
|
return Err(GlobalStateManagerError::InvalidName(
|
||||||
|
(*interface_key).clone(),
|
||||||
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
if machine_state_interface.network_id.is_some() {
|
if machine_state_interface.network_id.is_some() {
|
||||||
Self::detach_network_inner(machine_registry_inner, &mut machine_state_interface)?;
|
Self::detach_network_inner(gsm_inner, &mut machine_state_interface)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
machine_state_interface.network_id = Some(network_id);
|
machine_state_interface.network_id = Some(network_id);
|
||||||
@ -310,16 +322,18 @@ impl MachineState {
|
|||||||
|
|
||||||
pub fn detach_network(
|
pub fn detach_network(
|
||||||
&mut self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
interface_name: &str,
|
interface_name: &str,
|
||||||
) -> MachineRegistryResult<()> {
|
) -> GlobalStateManagerResult<()> {
|
||||||
let interface_key = Arc::new(interface_name.to_string());
|
let interface_key = Arc::new(interface_name.to_string());
|
||||||
let Some(mut machine_state_interface) = self.fields.interfaces.get(&interface_key).cloned()
|
let Some(mut machine_state_interface) = self.fields.interfaces.get(&interface_key).cloned()
|
||||||
else {
|
else {
|
||||||
return Err(MachineRegistryError::InvalidName);
|
return Err(GlobalStateManagerError::InvalidName(
|
||||||
|
(*interface_key).clone(),
|
||||||
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
Self::detach_network_inner(machine_registry_inner, &mut machine_state_interface)?;
|
Self::detach_network_inner(gsm_inner, &mut machine_state_interface)?;
|
||||||
|
|
||||||
// Update interfaces map
|
// Update interfaces map
|
||||||
let interfaces = self
|
let interfaces = self
|
||||||
@ -339,7 +353,7 @@ impl MachineState {
|
|||||||
pub fn attached_network_interfaces(
|
pub fn attached_network_interfaces(
|
||||||
&self,
|
&self,
|
||||||
network_id: NetworkStateId,
|
network_id: NetworkStateId,
|
||||||
) -> MachineRegistryResult<Vec<Arc<String>>> {
|
) -> GlobalStateManagerResult<Vec<Arc<String>>> {
|
||||||
let mut out = Vec::new();
|
let mut out = Vec::new();
|
||||||
for intf in &self.fields.interfaces {
|
for intf in &self.fields.interfaces {
|
||||||
if intf.1.network_id == Some(network_id) {
|
if intf.1.network_id == Some(network_id) {
|
||||||
@ -351,22 +365,26 @@ impl MachineState {
|
|||||||
|
|
||||||
pub fn release_address(
|
pub fn release_address(
|
||||||
&mut self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
interface_name: &str,
|
interface_name: &str,
|
||||||
address: IpAddr,
|
address: IpAddr,
|
||||||
) -> MachineRegistryResult<()> {
|
) -> GlobalStateManagerResult<()> {
|
||||||
let interface_key = Arc::new(interface_name.to_owned());
|
let interface_key = Arc::new(interface_name.to_owned());
|
||||||
let Some(mut machine_state_interface) = self.fields.interfaces.get(&interface_key).cloned()
|
let Some(mut machine_state_interface) = self.fields.interfaces.get(&interface_key).cloned()
|
||||||
else {
|
else {
|
||||||
return Err(MachineRegistryError::InvalidName);
|
return Err(GlobalStateManagerError::InvalidName(
|
||||||
|
(*interface_key).clone(),
|
||||||
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(network_id) = machine_state_interface.network_id else {
|
let Some(network_id) = machine_state_interface.network_id else {
|
||||||
return Err(MachineRegistryError::NetworkNotFound);
|
return Err(GlobalStateManagerError::NetworkNotFound(
|
||||||
|
(*interface_key).clone(),
|
||||||
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get the network state
|
// Get the network state
|
||||||
let mut network_state = machine_registry_inner
|
let mut network_state = gsm_inner
|
||||||
.network_states()
|
.network_states()
|
||||||
.get_state(network_id)?;
|
.get_state(network_id)?;
|
||||||
|
|
||||||
@ -377,7 +395,7 @@ impl MachineState {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Update the network state
|
// Update the network state
|
||||||
machine_registry_inner
|
gsm_inner
|
||||||
.network_states_mut()
|
.network_states_mut()
|
||||||
.set_state(network_state);
|
.set_state(network_state);
|
||||||
|
|
||||||
@ -413,16 +431,18 @@ impl MachineState {
|
|||||||
|
|
||||||
pub fn release_all_addresses(
|
pub fn release_all_addresses(
|
||||||
&mut self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
interface_name: &str,
|
interface_name: &str,
|
||||||
) -> MachineRegistryResult<()> {
|
) -> GlobalStateManagerResult<()> {
|
||||||
let interface_key = Arc::new(interface_name.to_string());
|
let interface_key = Arc::new(interface_name.to_string());
|
||||||
let Some(mut machine_state_interface) = self.fields.interfaces.get(&interface_key).cloned()
|
let Some(mut machine_state_interface) = self.fields.interfaces.get(&interface_key).cloned()
|
||||||
else {
|
else {
|
||||||
return Err(MachineRegistryError::InvalidName);
|
return Err(GlobalStateManagerError::InvalidName(
|
||||||
|
(*interface_key).clone(),
|
||||||
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
Self::release_all_addresses_inner(machine_registry_inner, &mut machine_state_interface)?;
|
Self::release_all_addresses_inner(gsm_inner, &mut machine_state_interface)?;
|
||||||
|
|
||||||
// Update interfaces map
|
// Update interfaces map
|
||||||
let interfaces = self
|
let interfaces = self
|
||||||
@ -442,24 +462,24 @@ impl MachineState {
|
|||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
fn detach_network_inner(
|
fn detach_network_inner(
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
machine_state_interface: &mut MachineStateInterface,
|
machine_state_interface: &mut MachineStateInterface,
|
||||||
) -> MachineRegistryResult<()> {
|
) -> GlobalStateManagerResult<()> {
|
||||||
Self::release_all_addresses_inner(machine_registry_inner, machine_state_interface)?;
|
Self::release_all_addresses_inner(gsm_inner, machine_state_interface)?;
|
||||||
machine_state_interface.network_id = None;
|
machine_state_interface.network_id = None;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn release_all_addresses_inner(
|
fn release_all_addresses_inner(
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
machine_state_interface: &mut MachineStateInterface,
|
machine_state_interface: &mut MachineStateInterface,
|
||||||
) -> MachineRegistryResult<()> {
|
) -> GlobalStateManagerResult<()> {
|
||||||
let Some(network_id) = machine_state_interface.network_id else {
|
let Some(network_id) = machine_state_interface.network_id else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get the network state
|
// Get the network state
|
||||||
let mut network_state = machine_registry_inner
|
let mut network_state = gsm_inner
|
||||||
.network_states()
|
.network_states()
|
||||||
.get_state(network_id)?;
|
.get_state(network_id)?;
|
||||||
|
|
||||||
@ -472,7 +492,7 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update the network state
|
// Update the network state
|
||||||
machine_registry_inner
|
gsm_inner
|
||||||
.network_states_mut()
|
.network_states_mut()
|
||||||
.set_state(network_state);
|
.set_state(network_state);
|
||||||
|
|
||||||
@ -488,16 +508,18 @@ impl MachineState {
|
|||||||
|
|
||||||
pub fn release_interface(
|
pub fn release_interface(
|
||||||
&mut self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
interface_name: &str,
|
interface_name: &str,
|
||||||
) -> MachineRegistryResult<()> {
|
) -> GlobalStateManagerResult<()> {
|
||||||
let interface_key = Arc::new(interface_name.to_string());
|
let interface_key = Arc::new(interface_name.to_string());
|
||||||
let Some(mut machine_state_interface) = self.fields.interfaces.get(&interface_key).cloned()
|
let Some(mut machine_state_interface) = self.fields.interfaces.get(&interface_key).cloned()
|
||||||
else {
|
else {
|
||||||
return Err(MachineRegistryError::InvalidName);
|
return Err(GlobalStateManagerError::InvalidName(
|
||||||
|
(*interface_key).clone(),
|
||||||
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
Self::detach_network_inner(machine_registry_inner, &mut machine_state_interface)?;
|
Self::detach_network_inner(gsm_inner, &mut machine_state_interface)?;
|
||||||
|
|
||||||
// Update interfaces map
|
// Update interfaces map
|
||||||
let interfaces = self.fields.interfaces.without(&interface_key);
|
let interfaces = self.fields.interfaces.without(&interface_key);
|
||||||
@ -513,8 +535,8 @@ impl MachineState {
|
|||||||
|
|
||||||
pub fn release_all_interfaces(
|
pub fn release_all_interfaces(
|
||||||
&mut self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
) -> MachineRegistryResult<()> {
|
) -> GlobalStateManagerResult<()> {
|
||||||
let interface_names: Vec<String> = self
|
let interface_names: Vec<String> = self
|
||||||
.fields
|
.fields
|
||||||
.interfaces
|
.interfaces
|
||||||
@ -526,10 +548,12 @@ impl MachineState {
|
|||||||
let Some(mut machine_state_interface) =
|
let Some(mut machine_state_interface) =
|
||||||
self.fields.interfaces.get(&interface_key).cloned()
|
self.fields.interfaces.get(&interface_key).cloned()
|
||||||
else {
|
else {
|
||||||
return Err(MachineRegistryError::InvalidName);
|
return Err(GlobalStateManagerError::InvalidName(
|
||||||
|
(*interface_key).clone(),
|
||||||
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
Self::detach_network_inner(machine_registry_inner, &mut machine_state_interface)?;
|
Self::detach_network_inner(gsm_inner, &mut machine_state_interface)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update fields
|
// Update fields
|
@ -4,7 +4,7 @@ mod machine_state;
|
|||||||
mod network_locations_list;
|
mod network_locations_list;
|
||||||
mod network_state;
|
mod network_state;
|
||||||
mod profile_state;
|
mod profile_state;
|
||||||
mod state_allocator;
|
mod state_registry;
|
||||||
mod template_state;
|
mod template_state;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -15,5 +15,5 @@ pub use machine_state::*;
|
|||||||
pub use network_locations_list::*;
|
pub use network_locations_list::*;
|
||||||
pub use network_state::*;
|
pub use network_state::*;
|
||||||
pub use profile_state::*;
|
pub use profile_state::*;
|
||||||
pub use state_allocator::*;
|
pub use state_registry::*;
|
||||||
pub use template_state::*;
|
pub use template_state::*;
|
@ -20,9 +20,9 @@ pub struct NetworkLocation<T> {
|
|||||||
impl NetworkLocationsList {
|
impl NetworkLocationsList {
|
||||||
pub fn pick_v4(
|
pub fn pick_v4(
|
||||||
&self,
|
&self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
prefix: &WeightedList<u8>,
|
prefix: &WeightedList<u8>,
|
||||||
) -> MachineRegistryResult<NetworkLocation<Ipv4Net>> {
|
) -> GlobalStateManagerResult<Option<NetworkLocation<Ipv4Net>>> {
|
||||||
// Get maximum prefix
|
// Get maximum prefix
|
||||||
let max_prefix = prefix
|
let max_prefix = prefix
|
||||||
.iter()
|
.iter()
|
||||||
@ -36,9 +36,8 @@ impl NetworkLocationsList {
|
|||||||
// Get allocations which have subnets that would fit
|
// Get allocations which have subnets that would fit
|
||||||
// our maximum requested prefix
|
// our maximum requested prefix
|
||||||
let Some(alloc_subnets) = allocations.try_filter_map(|allocation_name| {
|
let Some(alloc_subnets) = allocations.try_filter_map(|allocation_name| {
|
||||||
let allocation = machine_registry_inner
|
let allocation = gsm_inner
|
||||||
.config()
|
.allocations()
|
||||||
.allocations
|
|
||||||
.get(allocation_name)
|
.get(allocation_name)
|
||||||
.expect("must exist");
|
.expect("must exist");
|
||||||
Ok(allocation
|
Ok(allocation
|
||||||
@ -48,48 +47,42 @@ impl NetworkLocationsList {
|
|||||||
.and_then(|subnet| subnet.filter(|p| p.prefix_len() <= max_prefix)))
|
.and_then(|subnet| subnet.filter(|p| p.prefix_len() <= max_prefix)))
|
||||||
})?
|
})?
|
||||||
else {
|
else {
|
||||||
return Err(MachineRegistryError::NoAllocation);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Pick an allocation
|
// Pick an allocation
|
||||||
let subnets = machine_registry_inner
|
let subnets = gsm_inner.srng().weighted_choice_ref(&alloc_subnets);
|
||||||
.srng()
|
|
||||||
.weighted_choice_ref(&alloc_subnets);
|
|
||||||
|
|
||||||
// Pick a subnet
|
// Pick a subnet
|
||||||
let net = *machine_registry_inner.srng().weighted_choice_ref(subnets);
|
let net = *gsm_inner.srng().weighted_choice_ref(subnets);
|
||||||
|
|
||||||
// Pick a prefix length that would fit in the subnet
|
// Pick a prefix length that would fit in the subnet
|
||||||
let opt_subnet = prefix
|
let opt_subnet = prefix
|
||||||
.filter(|p| *p >= net.prefix_len())
|
.filter(|p| *p >= net.prefix_len())
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|wl| {
|
.map(|wl| {
|
||||||
let subnet_prefix = *machine_registry_inner.srng().weighted_choice_ref(wl);
|
let subnet_prefix = *gsm_inner.srng().weighted_choice_ref(wl);
|
||||||
|
|
||||||
// Use an address pool temporarily to pick a subnet
|
// Use an address pool temporarily to pick a subnet
|
||||||
let mut address_pool = AddressPool::<()>::new();
|
let mut address_pool = AddressPool::<()>::new();
|
||||||
address_pool.add_scope_v4(net);
|
address_pool.add_scope_v4(net);
|
||||||
address_pool.allocate_random_v4(
|
address_pool.allocate_random_v4(gsm_inner.srng(), subnet_prefix, ())
|
||||||
machine_registry_inner.srng(),
|
|
||||||
subnet_prefix,
|
|
||||||
(),
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
.transpose()?
|
.transpose()?
|
||||||
.flatten();
|
.flatten();
|
||||||
let Some(subnet) = opt_subnet else {
|
let Some(subnet) = opt_subnet else {
|
||||||
return Err(MachineRegistryError::NoAllocation);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
Ok(NetworkLocation {
|
Ok(Some(NetworkLocation {
|
||||||
subnet,
|
subnet,
|
||||||
super_net: None,
|
super_net: None,
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
NetworkLocationsList::Networks { networks } => {
|
NetworkLocationsList::Networks { networks } => {
|
||||||
// Get networks which have subnets that would fit
|
// Get networks which have subnets that would fit
|
||||||
// our maximum requested prefix
|
// our maximum requested prefix
|
||||||
let Some(available_networks) = networks.try_filter(|network_id| {
|
let Some(available_networks) = networks.try_filter(|network_id| {
|
||||||
let super_network_state = machine_registry_inner
|
let super_network_state = gsm_inner
|
||||||
.network_states()
|
.network_states()
|
||||||
.get_state(*network_id)
|
.get_state(*network_id)
|
||||||
.expect("must exist");
|
.expect("must exist");
|
||||||
@ -97,14 +90,12 @@ impl NetworkLocationsList {
|
|||||||
Ok(super_network_state.can_allocate_subnet_v4(None, max_prefix))
|
Ok(super_network_state.can_allocate_subnet_v4(None, max_prefix))
|
||||||
})?
|
})?
|
||||||
else {
|
else {
|
||||||
return Err(MachineRegistryError::NoAllocation);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Pick a network
|
// Pick a network
|
||||||
let super_network_id = *machine_registry_inner
|
let super_network_id = *gsm_inner.srng().weighted_choice_ref(&available_networks);
|
||||||
.srng()
|
let mut super_network_state = gsm_inner
|
||||||
.weighted_choice_ref(&available_networks);
|
|
||||||
let mut super_network_state = machine_registry_inner
|
|
||||||
.network_states()
|
.network_states()
|
||||||
.get_state(super_network_id)
|
.get_state(super_network_id)
|
||||||
.expect("must exist");
|
.expect("must exist");
|
||||||
@ -114,11 +105,11 @@ impl NetworkLocationsList {
|
|||||||
.filter(|p| super_network_state.can_allocate_subnet_v4(None, *p))
|
.filter(|p| super_network_state.can_allocate_subnet_v4(None, *p))
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|wl| {
|
.map(|wl| {
|
||||||
let subnet_prefix = *machine_registry_inner.srng().weighted_choice_ref(wl);
|
let subnet_prefix = *gsm_inner.srng().weighted_choice_ref(wl);
|
||||||
|
|
||||||
// Allocate subnet from this network
|
// Allocate subnet from this network
|
||||||
super_network_state.allocate_subnet_v4(
|
super_network_state.allocate_subnet_v4(
|
||||||
machine_registry_inner,
|
gsm_inner,
|
||||||
OwnerTag::Network(super_network_state.id()),
|
OwnerTag::Network(super_network_state.id()),
|
||||||
None,
|
None,
|
||||||
subnet_prefix,
|
subnet_prefix,
|
||||||
@ -126,27 +117,27 @@ impl NetworkLocationsList {
|
|||||||
})
|
})
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
let Some(subnet) = opt_subnet else {
|
let Some(subnet) = opt_subnet else {
|
||||||
return Err(MachineRegistryError::NoAllocation);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Update network state
|
// Update network state
|
||||||
machine_registry_inner
|
gsm_inner
|
||||||
.network_states_mut()
|
.network_states_mut()
|
||||||
.set_state(super_network_state);
|
.set_state(super_network_state);
|
||||||
|
|
||||||
Ok(NetworkLocation {
|
Ok(Some(NetworkLocation {
|
||||||
subnet,
|
subnet,
|
||||||
super_net: Some(super_network_id),
|
super_net: Some(super_network_id),
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pick_v6(
|
pub fn pick_v6(
|
||||||
&self,
|
&self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
prefix: &WeightedList<u8>,
|
prefix: &WeightedList<u8>,
|
||||||
) -> MachineRegistryResult<NetworkLocation<Ipv6Net>> {
|
) -> GlobalStateManagerResult<Option<NetworkLocation<Ipv6Net>>> {
|
||||||
// Get maximum prefix
|
// Get maximum prefix
|
||||||
let max_prefix = prefix
|
let max_prefix = prefix
|
||||||
.iter()
|
.iter()
|
||||||
@ -160,9 +151,8 @@ impl NetworkLocationsList {
|
|||||||
// Get allocations which have subnets that would fit
|
// Get allocations which have subnets that would fit
|
||||||
// our maximum requested prefix
|
// our maximum requested prefix
|
||||||
let Some(alloc_subnets) = allocations.try_filter_map(|allocation_name| {
|
let Some(alloc_subnets) = allocations.try_filter_map(|allocation_name| {
|
||||||
let allocation = machine_registry_inner
|
let allocation = gsm_inner
|
||||||
.config()
|
.allocations()
|
||||||
.allocations
|
|
||||||
.get(allocation_name)
|
.get(allocation_name)
|
||||||
.expect("must exist");
|
.expect("must exist");
|
||||||
Ok(allocation
|
Ok(allocation
|
||||||
@ -172,48 +162,42 @@ impl NetworkLocationsList {
|
|||||||
.and_then(|subnet| subnet.filter(|p| p.prefix_len() <= max_prefix)))
|
.and_then(|subnet| subnet.filter(|p| p.prefix_len() <= max_prefix)))
|
||||||
})?
|
})?
|
||||||
else {
|
else {
|
||||||
return Err(MachineRegistryError::NoAllocation);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Pick an allocation
|
// Pick an allocation
|
||||||
let subnets = machine_registry_inner
|
let subnets = gsm_inner.srng().weighted_choice_ref(&alloc_subnets);
|
||||||
.srng()
|
|
||||||
.weighted_choice_ref(&alloc_subnets);
|
|
||||||
|
|
||||||
// Pick a subnet
|
// Pick a subnet
|
||||||
let net = *machine_registry_inner.srng().weighted_choice_ref(subnets);
|
let net = *gsm_inner.srng().weighted_choice_ref(subnets);
|
||||||
|
|
||||||
// Pick a prefix length that would fit in the subnet
|
// Pick a prefix length that would fit in the subnet
|
||||||
let opt_subnet = prefix
|
let opt_subnet = prefix
|
||||||
.filter(|p| *p >= net.prefix_len())
|
.filter(|p| *p >= net.prefix_len())
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|wl| {
|
.map(|wl| {
|
||||||
let subnet_prefix = *machine_registry_inner.srng().weighted_choice_ref(wl);
|
let subnet_prefix = *gsm_inner.srng().weighted_choice_ref(wl);
|
||||||
|
|
||||||
// Use an address pool temporarily to pick a subnet
|
// Use an address pool temporarily to pick a subnet
|
||||||
let mut address_pool = AddressPool::<()>::new();
|
let mut address_pool = AddressPool::<()>::new();
|
||||||
address_pool.add_scope_v6(net);
|
address_pool.add_scope_v6(net);
|
||||||
address_pool.allocate_random_v6(
|
address_pool.allocate_random_v6(gsm_inner.srng(), subnet_prefix, ())
|
||||||
machine_registry_inner.srng(),
|
|
||||||
subnet_prefix,
|
|
||||||
(),
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
.transpose()?
|
.transpose()?
|
||||||
.flatten();
|
.flatten();
|
||||||
let Some(subnet) = opt_subnet else {
|
let Some(subnet) = opt_subnet else {
|
||||||
return Err(MachineRegistryError::NoAllocation);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
Ok(NetworkLocation {
|
Ok(Some(NetworkLocation {
|
||||||
subnet,
|
subnet,
|
||||||
super_net: None,
|
super_net: None,
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
NetworkLocationsList::Networks { networks } => {
|
NetworkLocationsList::Networks { networks } => {
|
||||||
// Get networks which have subnets that would fit
|
// Get networks which have subnets that would fit
|
||||||
// our maximum requested prefix
|
// our maximum requested prefix
|
||||||
let Some(available_networks) = networks.try_filter(|network_id| {
|
let Some(available_networks) = networks.try_filter(|network_id| {
|
||||||
let super_network_state = machine_registry_inner
|
let super_network_state = gsm_inner
|
||||||
.network_states()
|
.network_states()
|
||||||
.get_state(*network_id)
|
.get_state(*network_id)
|
||||||
.expect("must exist");
|
.expect("must exist");
|
||||||
@ -221,14 +205,12 @@ impl NetworkLocationsList {
|
|||||||
Ok(super_network_state.can_allocate_subnet_v6(None, max_prefix))
|
Ok(super_network_state.can_allocate_subnet_v6(None, max_prefix))
|
||||||
})?
|
})?
|
||||||
else {
|
else {
|
||||||
return Err(MachineRegistryError::NoAllocation);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Pick a network
|
// Pick a network
|
||||||
let super_network_id = *machine_registry_inner
|
let super_network_id = *gsm_inner.srng().weighted_choice_ref(&available_networks);
|
||||||
.srng()
|
let mut super_network_state = gsm_inner
|
||||||
.weighted_choice_ref(&available_networks);
|
|
||||||
let mut super_network_state = machine_registry_inner
|
|
||||||
.network_states()
|
.network_states()
|
||||||
.get_state(super_network_id)
|
.get_state(super_network_id)
|
||||||
.expect("must exist");
|
.expect("must exist");
|
||||||
@ -238,11 +220,11 @@ impl NetworkLocationsList {
|
|||||||
.filter(|p| super_network_state.can_allocate_subnet_v6(None, *p))
|
.filter(|p| super_network_state.can_allocate_subnet_v6(None, *p))
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|wl| {
|
.map(|wl| {
|
||||||
let subnet_prefix = *machine_registry_inner.srng().weighted_choice_ref(wl);
|
let subnet_prefix = *gsm_inner.srng().weighted_choice_ref(wl);
|
||||||
|
|
||||||
// Allocate subnet from this network
|
// Allocate subnet from this network
|
||||||
super_network_state.allocate_subnet_v6(
|
super_network_state.allocate_subnet_v6(
|
||||||
machine_registry_inner,
|
gsm_inner,
|
||||||
OwnerTag::Network(super_network_state.id()),
|
OwnerTag::Network(super_network_state.id()),
|
||||||
None,
|
None,
|
||||||
subnet_prefix,
|
subnet_prefix,
|
||||||
@ -250,18 +232,18 @@ impl NetworkLocationsList {
|
|||||||
})
|
})
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
let Some(subnet) = opt_subnet else {
|
let Some(subnet) = opt_subnet else {
|
||||||
return Err(MachineRegistryError::NoAllocation);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Update network state
|
// Update network state
|
||||||
machine_registry_inner
|
gsm_inner
|
||||||
.network_states_mut()
|
.network_states_mut()
|
||||||
.set_state(super_network_state);
|
.set_state(super_network_state);
|
||||||
|
|
||||||
Ok(NetworkLocation {
|
Ok(Some(NetworkLocation {
|
||||||
subnet,
|
subnet,
|
||||||
super_net: Some(super_network_id),
|
super_net: Some(super_network_id),
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -137,14 +137,14 @@ impl NetworkState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn release(self, machine_registry_inner: &mut MachineRegistryInner) {
|
pub fn release(self, gsm_inner: &mut GlobalStateManagerInner) {
|
||||||
if let NetworkOrigin::Blueprint(generating_blueprint) = self.immutable.origin {
|
if let NetworkOrigin::Blueprint(generating_blueprint) = self.immutable.origin {
|
||||||
let mut blueprint_state = machine_registry_inner
|
let mut blueprint_state = gsm_inner
|
||||||
.blueprint_states()
|
.blueprint_states()
|
||||||
.get_state(generating_blueprint)
|
.get_state(generating_blueprint)
|
||||||
.expect("must exist");
|
.expect("must exist");
|
||||||
blueprint_state.on_network_released(self.id());
|
blueprint_state.on_network_released(self.id());
|
||||||
machine_registry_inner
|
gsm_inner
|
||||||
.blueprint_states_mut()
|
.blueprint_states_mut()
|
||||||
.set_state(blueprint_state)
|
.set_state(blueprint_state)
|
||||||
}
|
}
|
||||||
@ -159,17 +159,21 @@ impl NetworkState {
|
|||||||
|
|
||||||
pub fn clear_ipv4(
|
pub fn clear_ipv4(
|
||||||
&mut self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
) -> MachineRegistryResult<()> {
|
) -> GlobalStateManagerResult<()> {
|
||||||
let Some(ipv4) = self.fields.ipv4.clone() else {
|
let Some(ipv4) = self.fields.ipv4.clone() else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut address_pool = self.fields.address_pool.clone();
|
let mut address_pool = self.fields.address_pool.clone();
|
||||||
address_pool.clear_ipv4(|_n, t| match t {
|
address_pool
|
||||||
|
.clear_ipv4(|_n, t| match t {
|
||||||
OwnerTag::Machine(_) => true,
|
OwnerTag::Machine(_) => true,
|
||||||
OwnerTag::Network(nsid) => *nsid != self.id(),
|
OwnerTag::Network(nsid) => *nsid != self.id(),
|
||||||
OwnerTag::Gateway(nsid) => *nsid != self.id(),
|
OwnerTag::Gateway(nsid) => *nsid != self.id(),
|
||||||
|
})
|
||||||
|
.map_err(|_| {
|
||||||
|
GlobalStateManagerError::ResourceInUse(format!("{}-v4", self.debug_name()))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// If we have a gateway, release its external address
|
// If we have a gateway, release its external address
|
||||||
@ -177,7 +181,7 @@ impl NetworkState {
|
|||||||
if let Some(gateway) = ipv4.gateway.as_ref() {
|
if let Some(gateway) = ipv4.gateway.as_ref() {
|
||||||
if gateway.params.external_network != self.id() {
|
if gateway.params.external_network != self.id() {
|
||||||
// Get the external network state
|
// Get the external network state
|
||||||
let mut external_network_state = machine_registry_inner
|
let mut external_network_state = gsm_inner
|
||||||
.network_states()
|
.network_states()
|
||||||
.get_state(gateway.params.external_network)
|
.get_state(gateway.params.external_network)
|
||||||
.expect("must succeed");
|
.expect("must succeed");
|
||||||
@ -188,7 +192,7 @@ impl NetworkState {
|
|||||||
.expect("must succeed");
|
.expect("must succeed");
|
||||||
|
|
||||||
// Update external network
|
// Update external network
|
||||||
machine_registry_inner
|
gsm_inner
|
||||||
.network_states_mut()
|
.network_states_mut()
|
||||||
.set_state(external_network_state);
|
.set_state(external_network_state);
|
||||||
}
|
}
|
||||||
@ -206,11 +210,11 @@ impl NetworkState {
|
|||||||
|
|
||||||
pub fn set_ipv4(
|
pub fn set_ipv4(
|
||||||
&mut self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
params: NetworkStateIpv4Params,
|
params: NetworkStateIpv4Params,
|
||||||
gateway_params: Option<NetworkStateIpv4GatewayParams>,
|
gateway_params: Option<NetworkStateIpv4GatewayParams>,
|
||||||
) -> MachineRegistryResult<()> {
|
) -> GlobalStateManagerResult<()> {
|
||||||
self.clear_ipv4(machine_registry_inner)?;
|
self.clear_ipv4(gsm_inner)?;
|
||||||
|
|
||||||
let mut address_pool = self.fields.address_pool.clone();
|
let mut address_pool = self.fields.address_pool.clone();
|
||||||
address_pool.add_scope_v4(params.allocation);
|
address_pool.add_scope_v4(params.allocation);
|
||||||
@ -227,12 +231,12 @@ impl NetworkState {
|
|||||||
internal_address
|
internal_address
|
||||||
} else {
|
} else {
|
||||||
let Some(internal_address) = address_pool.allocate_random_v4(
|
let Some(internal_address) = address_pool.allocate_random_v4(
|
||||||
machine_registry_inner.srng(),
|
gsm_inner.srng(),
|
||||||
32,
|
32,
|
||||||
OwnerTag::Gateway(self.id()),
|
OwnerTag::Gateway(self.id()),
|
||||||
)?
|
)?
|
||||||
else {
|
else {
|
||||||
return Err(MachineRegistryError::NoAllocation);
|
return Err(GlobalStateManagerError::NoAllocation);
|
||||||
};
|
};
|
||||||
internal_address.addr()
|
internal_address.addr()
|
||||||
};
|
};
|
||||||
@ -245,7 +249,7 @@ impl NetworkState {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Get the external network state
|
// Get the external network state
|
||||||
let mut external_network_state = machine_registry_inner
|
let mut external_network_state = gsm_inner
|
||||||
.network_states()
|
.network_states()
|
||||||
.get_state(gateway_params.external_network)
|
.get_state(gateway_params.external_network)
|
||||||
.expect("must succeed");
|
.expect("must succeed");
|
||||||
@ -256,7 +260,7 @@ impl NetworkState {
|
|||||||
// If the translation mode is 'none', then the external and internal
|
// If the translation mode is 'none', then the external and internal
|
||||||
// addresses must be the same
|
// addresses must be the same
|
||||||
external_network_state.allocate_address_v4(
|
external_network_state.allocate_address_v4(
|
||||||
machine_registry_inner,
|
gsm_inner,
|
||||||
OwnerTag::Gateway(self.id()),
|
OwnerTag::Gateway(self.id()),
|
||||||
Some(internal_address),
|
Some(internal_address),
|
||||||
)?
|
)?
|
||||||
@ -264,14 +268,14 @@ impl NetworkState {
|
|||||||
// Network translation means the internal and external addresses
|
// Network translation means the internal and external addresses
|
||||||
// will be different
|
// will be different
|
||||||
external_network_state.allocate_address_v4(
|
external_network_state.allocate_address_v4(
|
||||||
machine_registry_inner,
|
gsm_inner,
|
||||||
OwnerTag::Gateway(self.id()),
|
OwnerTag::Gateway(self.id()),
|
||||||
None,
|
None,
|
||||||
)?
|
)?
|
||||||
};
|
};
|
||||||
|
|
||||||
// Update external network
|
// Update external network
|
||||||
machine_registry_inner
|
gsm_inner
|
||||||
.network_states_mut()
|
.network_states_mut()
|
||||||
.set_state(external_network_state);
|
.set_state(external_network_state);
|
||||||
|
|
||||||
@ -299,17 +303,21 @@ impl NetworkState {
|
|||||||
|
|
||||||
pub fn clear_ipv6(
|
pub fn clear_ipv6(
|
||||||
&mut self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
) -> MachineRegistryResult<()> {
|
) -> GlobalStateManagerResult<()> {
|
||||||
let Some(ipv6) = self.fields.ipv6.clone() else {
|
let Some(ipv6) = self.fields.ipv6.clone() else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut address_pool = self.fields.address_pool.clone();
|
let mut address_pool = self.fields.address_pool.clone();
|
||||||
address_pool.clear_ipv6(|_n, t| match t {
|
address_pool
|
||||||
|
.clear_ipv6(|_n, t| match t {
|
||||||
OwnerTag::Machine(_) => true,
|
OwnerTag::Machine(_) => true,
|
||||||
OwnerTag::Network(nsid) => *nsid != self.id(),
|
OwnerTag::Network(nsid) => *nsid != self.id(),
|
||||||
OwnerTag::Gateway(nsid) => *nsid != self.id(),
|
OwnerTag::Gateway(nsid) => *nsid != self.id(),
|
||||||
|
})
|
||||||
|
.map_err(|_| {
|
||||||
|
GlobalStateManagerError::ResourceInUse(format!("{}-v6", self.debug_name()))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// If we have a gateway, release its external address
|
// If we have a gateway, release its external address
|
||||||
@ -317,7 +325,7 @@ impl NetworkState {
|
|||||||
if let Some(gateway) = ipv6.gateway.as_ref() {
|
if let Some(gateway) = ipv6.gateway.as_ref() {
|
||||||
if gateway.params.external_network != self.id() {
|
if gateway.params.external_network != self.id() {
|
||||||
// Get the external network state
|
// Get the external network state
|
||||||
let mut external_network_state = machine_registry_inner
|
let mut external_network_state = gsm_inner
|
||||||
.network_states()
|
.network_states()
|
||||||
.get_state(gateway.params.external_network)
|
.get_state(gateway.params.external_network)
|
||||||
.expect("must succeed");
|
.expect("must succeed");
|
||||||
@ -328,7 +336,7 @@ impl NetworkState {
|
|||||||
.expect("must succeed");
|
.expect("must succeed");
|
||||||
|
|
||||||
// Update external network
|
// Update external network
|
||||||
machine_registry_inner
|
gsm_inner
|
||||||
.network_states_mut()
|
.network_states_mut()
|
||||||
.set_state(external_network_state);
|
.set_state(external_network_state);
|
||||||
}
|
}
|
||||||
@ -345,11 +353,11 @@ impl NetworkState {
|
|||||||
}
|
}
|
||||||
pub fn set_ipv6(
|
pub fn set_ipv6(
|
||||||
&mut self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
params: NetworkStateIpv6Params,
|
params: NetworkStateIpv6Params,
|
||||||
gateway_params: Option<NetworkStateIpv6GatewayParams>,
|
gateway_params: Option<NetworkStateIpv6GatewayParams>,
|
||||||
) -> MachineRegistryResult<()> {
|
) -> GlobalStateManagerResult<()> {
|
||||||
self.clear_ipv6(machine_registry_inner)?;
|
self.clear_ipv6(gsm_inner)?;
|
||||||
|
|
||||||
let mut address_pool = self.fields.address_pool.clone();
|
let mut address_pool = self.fields.address_pool.clone();
|
||||||
address_pool.add_scope_v6(params.allocation);
|
address_pool.add_scope_v6(params.allocation);
|
||||||
@ -366,12 +374,12 @@ impl NetworkState {
|
|||||||
internal_address
|
internal_address
|
||||||
} else {
|
} else {
|
||||||
let Some(internal_address) = address_pool.allocate_random_v6(
|
let Some(internal_address) = address_pool.allocate_random_v6(
|
||||||
machine_registry_inner.srng(),
|
gsm_inner.srng(),
|
||||||
128,
|
128,
|
||||||
OwnerTag::Gateway(self.id()),
|
OwnerTag::Gateway(self.id()),
|
||||||
)?
|
)?
|
||||||
else {
|
else {
|
||||||
return Err(MachineRegistryError::NoAllocation);
|
return Err(GlobalStateManagerError::NoAllocation);
|
||||||
};
|
};
|
||||||
internal_address.addr()
|
internal_address.addr()
|
||||||
};
|
};
|
||||||
@ -384,7 +392,7 @@ impl NetworkState {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Get the external network state
|
// Get the external network state
|
||||||
let mut external_network_state = machine_registry_inner
|
let mut external_network_state = gsm_inner
|
||||||
.network_states()
|
.network_states()
|
||||||
.get_state(gateway_params.external_network)
|
.get_state(gateway_params.external_network)
|
||||||
.expect("must succeed");
|
.expect("must succeed");
|
||||||
@ -395,7 +403,7 @@ impl NetworkState {
|
|||||||
// If the translation mode is 'none', then the external and internal
|
// If the translation mode is 'none', then the external and internal
|
||||||
// addresses must be the same
|
// addresses must be the same
|
||||||
external_network_state.allocate_address_v6(
|
external_network_state.allocate_address_v6(
|
||||||
machine_registry_inner,
|
gsm_inner,
|
||||||
OwnerTag::Gateway(self.id()),
|
OwnerTag::Gateway(self.id()),
|
||||||
Some(internal_address),
|
Some(internal_address),
|
||||||
)?
|
)?
|
||||||
@ -403,14 +411,14 @@ impl NetworkState {
|
|||||||
// Network translation means the internal and external addresses
|
// Network translation means the internal and external addresses
|
||||||
// will be different
|
// will be different
|
||||||
external_network_state.allocate_address_v6(
|
external_network_state.allocate_address_v6(
|
||||||
machine_registry_inner,
|
gsm_inner,
|
||||||
OwnerTag::Gateway(self.id()),
|
OwnerTag::Gateway(self.id()),
|
||||||
None,
|
None,
|
||||||
)?
|
)?
|
||||||
};
|
};
|
||||||
|
|
||||||
// Update external network
|
// Update external network
|
||||||
machine_registry_inner
|
gsm_inner
|
||||||
.network_states_mut()
|
.network_states_mut()
|
||||||
.set_state(external_network_state);
|
.set_state(external_network_state);
|
||||||
|
|
||||||
@ -444,7 +452,7 @@ impl NetworkState {
|
|||||||
self.fields.ipv6.is_some()
|
self.fields.ipv6.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_active(&self) -> MachineRegistryResult<bool> {
|
pub fn is_active(&self) -> GlobalStateManagerResult<bool> {
|
||||||
let mut can_allocate = false;
|
let mut can_allocate = false;
|
||||||
|
|
||||||
if self.fields.ipv4.is_some() {
|
if self.fields.ipv4.is_some() {
|
||||||
@ -464,11 +472,11 @@ impl NetworkState {
|
|||||||
|
|
||||||
pub fn allocate_address_v4(
|
pub fn allocate_address_v4(
|
||||||
&mut self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
owner_tag: OwnerTag,
|
owner_tag: OwnerTag,
|
||||||
opt_address: Option<Ipv4Addr>,
|
opt_address: Option<Ipv4Addr>,
|
||||||
) -> MachineRegistryResult<Ifv4Addr> {
|
) -> GlobalStateManagerResult<Ifv4Addr> {
|
||||||
let net = self.allocate_subnet_v4(machine_registry_inner, owner_tag, opt_address, 32)?;
|
let net = self.allocate_subnet_v4(gsm_inner, owner_tag, opt_address, 32)?;
|
||||||
let ip = net.addr();
|
let ip = net.addr();
|
||||||
|
|
||||||
let ipv4 = self.fields.ipv4.as_ref().unwrap();
|
let ipv4 = self.fields.ipv4.as_ref().unwrap();
|
||||||
@ -490,13 +498,13 @@ impl NetworkState {
|
|||||||
|
|
||||||
pub fn allocate_subnet_v4(
|
pub fn allocate_subnet_v4(
|
||||||
&mut self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
owner_tag: OwnerTag,
|
owner_tag: OwnerTag,
|
||||||
opt_address: Option<Ipv4Addr>,
|
opt_address: Option<Ipv4Addr>,
|
||||||
prefix: u8,
|
prefix: u8,
|
||||||
) -> MachineRegistryResult<Ipv4Net> {
|
) -> GlobalStateManagerResult<Ipv4Net> {
|
||||||
if self.fields.ipv4.is_none() {
|
if self.fields.ipv4.is_none() {
|
||||||
return Err(MachineRegistryError::NoAllocation);
|
return Err(GlobalStateManagerError::NoAllocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
// See if we are requesting a specific address
|
// See if we are requesting a specific address
|
||||||
@ -510,12 +518,12 @@ impl NetworkState {
|
|||||||
} else {
|
} else {
|
||||||
// Get a random address if available
|
// Get a random address if available
|
||||||
let Some(allocation) = address_pool.allocate_random_v4(
|
let Some(allocation) = address_pool.allocate_random_v4(
|
||||||
machine_registry_inner.srng(),
|
gsm_inner.srng(),
|
||||||
prefix,
|
prefix,
|
||||||
owner_tag,
|
owner_tag,
|
||||||
)?
|
)?
|
||||||
else {
|
else {
|
||||||
return Err(MachineRegistryError::NoAllocation);
|
return Err(GlobalStateManagerError::NoAllocation);
|
||||||
};
|
};
|
||||||
allocation
|
allocation
|
||||||
};
|
};
|
||||||
@ -551,11 +559,14 @@ impl NetworkState {
|
|||||||
pub fn release_address_v4(
|
pub fn release_address_v4(
|
||||||
&mut self,
|
&mut self,
|
||||||
addr: Ipv4Addr,
|
addr: Ipv4Addr,
|
||||||
) -> MachineRegistryResult<Option<OwnerTag>> {
|
) -> GlobalStateManagerResult<Option<OwnerTag>> {
|
||||||
self.release_subnet_v4(Ipv4Net::new(addr, 32).expect("must succeed"))
|
self.release_subnet_v4(Ipv4Net::new(addr, 32).expect("must succeed"))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn release_subnet_v4(&mut self, net: Ipv4Net) -> MachineRegistryResult<Option<OwnerTag>> {
|
pub fn release_subnet_v4(
|
||||||
|
&mut self,
|
||||||
|
net: Ipv4Net,
|
||||||
|
) -> GlobalStateManagerResult<Option<OwnerTag>> {
|
||||||
let mut address_pool = self.fields.address_pool.clone();
|
let mut address_pool = self.fields.address_pool.clone();
|
||||||
let opt_tag = address_pool.release_allocation_v4(net)?;
|
let opt_tag = address_pool.release_allocation_v4(net)?;
|
||||||
|
|
||||||
@ -569,11 +580,11 @@ impl NetworkState {
|
|||||||
|
|
||||||
pub fn allocate_address_v6(
|
pub fn allocate_address_v6(
|
||||||
&mut self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
owner_tag: OwnerTag,
|
owner_tag: OwnerTag,
|
||||||
opt_address: Option<Ipv6Addr>,
|
opt_address: Option<Ipv6Addr>,
|
||||||
) -> MachineRegistryResult<Ifv6Addr> {
|
) -> GlobalStateManagerResult<Ifv6Addr> {
|
||||||
let net = self.allocate_subnet_v6(machine_registry_inner, owner_tag, opt_address, 128)?;
|
let net = self.allocate_subnet_v6(gsm_inner, owner_tag, opt_address, 128)?;
|
||||||
let ip = net.addr();
|
let ip = net.addr();
|
||||||
|
|
||||||
let ipv6 = self.fields.ipv6.as_ref().unwrap();
|
let ipv6 = self.fields.ipv6.as_ref().unwrap();
|
||||||
@ -595,13 +606,13 @@ impl NetworkState {
|
|||||||
|
|
||||||
pub fn allocate_subnet_v6(
|
pub fn allocate_subnet_v6(
|
||||||
&mut self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
owner_tag: OwnerTag,
|
owner_tag: OwnerTag,
|
||||||
opt_address: Option<Ipv6Addr>,
|
opt_address: Option<Ipv6Addr>,
|
||||||
prefix: u8,
|
prefix: u8,
|
||||||
) -> MachineRegistryResult<Ipv6Net> {
|
) -> GlobalStateManagerResult<Ipv6Net> {
|
||||||
if self.fields.ipv6.is_none() {
|
if self.fields.ipv6.is_none() {
|
||||||
return Err(MachineRegistryError::NoAllocation);
|
return Err(GlobalStateManagerError::NoAllocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
// See if we are requesting a specific address
|
// See if we are requesting a specific address
|
||||||
@ -615,12 +626,12 @@ impl NetworkState {
|
|||||||
} else {
|
} else {
|
||||||
// Get a random address if available
|
// Get a random address if available
|
||||||
let Some(allocation) = address_pool.allocate_random_v6(
|
let Some(allocation) = address_pool.allocate_random_v6(
|
||||||
machine_registry_inner.srng(),
|
gsm_inner.srng(),
|
||||||
prefix,
|
prefix,
|
||||||
owner_tag,
|
owner_tag,
|
||||||
)?
|
)?
|
||||||
else {
|
else {
|
||||||
return Err(MachineRegistryError::NoAllocation);
|
return Err(GlobalStateManagerError::NoAllocation);
|
||||||
};
|
};
|
||||||
allocation
|
allocation
|
||||||
};
|
};
|
||||||
@ -656,11 +667,14 @@ impl NetworkState {
|
|||||||
pub fn release_address_v6(
|
pub fn release_address_v6(
|
||||||
&mut self,
|
&mut self,
|
||||||
addr: Ipv6Addr,
|
addr: Ipv6Addr,
|
||||||
) -> MachineRegistryResult<Option<OwnerTag>> {
|
) -> GlobalStateManagerResult<Option<OwnerTag>> {
|
||||||
self.release_subnet_v6(Ipv6Net::new(addr, 128).expect("must succeed"))
|
self.release_subnet_v6(Ipv6Net::new(addr, 128).expect("must succeed"))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn release_subnet_v6(&mut self, net: Ipv6Net) -> MachineRegistryResult<Option<OwnerTag>> {
|
pub fn release_subnet_v6(
|
||||||
|
&mut self,
|
||||||
|
net: Ipv6Net,
|
||||||
|
) -> GlobalStateManagerResult<Option<OwnerTag>> {
|
||||||
let mut address_pool = self.fields.address_pool.clone();
|
let mut address_pool = self.fields.address_pool.clone();
|
||||||
let opt_tag = address_pool.release_allocation_v6(net)?;
|
let opt_tag = address_pool.release_allocation_v6(net)?;
|
||||||
|
|
@ -4,6 +4,10 @@ use std::marker::PhantomData;
|
|||||||
pub trait State: fmt::Debug + Clone {
|
pub trait State: fmt::Debug + Clone {
|
||||||
fn id(&self) -> StateId<Self>;
|
fn id(&self) -> StateId<Self>;
|
||||||
fn name(&self) -> Option<String>;
|
fn name(&self) -> Option<String>;
|
||||||
|
fn debug_name(&self) -> String {
|
||||||
|
self.name()
|
||||||
|
.unwrap_or_else(|| format!("<{}>", self.id().external_id()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type StateIdInternal = u64;
|
type StateIdInternal = u64;
|
||||||
@ -44,14 +48,14 @@ impl<S: State> core::hash::Hash for StateId<S> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct StateAllocator<S: State> {
|
pub struct StateRegistry<S: State> {
|
||||||
state_id_by_name: imbl::HashMap<Arc<String>, StateIdInternal>,
|
state_id_by_name: imbl::HashMap<Arc<String>, StateIdInternal>,
|
||||||
state_by_id: imbl::HashMap<StateIdInternal, Option<S>>,
|
state_by_id: imbl::HashMap<StateIdInternal, Option<S>>,
|
||||||
next_state_id: StateIdInternal,
|
next_state_id: StateIdInternal,
|
||||||
free_state_ids: imbl::Vector<StateIdInternal>,
|
free_state_ids: imbl::Vector<StateIdInternal>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: State> StateAllocator<S> {
|
impl<S: State> StateRegistry<S> {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
state_id_by_name: imbl::HashMap::new(),
|
state_id_by_name: imbl::HashMap::new(),
|
||||||
@ -90,10 +94,10 @@ impl<S: State> StateAllocator<S> {
|
|||||||
StateId(state_id, PhantomData {})
|
StateId(state_id, PhantomData {})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn release_id(&mut self, id: StateId<S>) -> MachineRegistryResult<()> {
|
pub fn release_id(&mut self, id: StateId<S>) -> GlobalStateManagerResult<()> {
|
||||||
// Remove id to state mapping
|
// Remove id to state mapping
|
||||||
let Some(old_opt_state) = self.state_by_id.remove(&id.0) else {
|
let Some(old_opt_state) = self.state_by_id.remove(&id.0) else {
|
||||||
return Err(MachineRegistryError::InvalidId);
|
return Err(GlobalStateManagerError::InvalidId(id.external_id()));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Release state if it is attached
|
// Release state if it is attached
|
||||||
@ -112,24 +116,24 @@ impl<S: State> StateAllocator<S> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn attach_state(&mut self, state: S) -> MachineRegistryResult<()> {
|
pub fn attach_state(&mut self, state: S) -> GlobalStateManagerResult<()> {
|
||||||
// Get the id from the state
|
// Get the id from the state
|
||||||
let id = state.id();
|
let id = state.id();
|
||||||
|
|
||||||
// Get the allocator slot
|
// Get the allocator slot
|
||||||
let Some(opt_state) = self.state_by_id.get_mut(&id.0) else {
|
let Some(opt_state) = self.state_by_id.get_mut(&id.0) else {
|
||||||
return Err(MachineRegistryError::InvalidId);
|
return Err(GlobalStateManagerError::InvalidId(id.external_id()));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Ensure the state slot isn't attached already
|
// Ensure the state slot isn't attached already
|
||||||
if opt_state.is_some() {
|
if opt_state.is_some() {
|
||||||
return Err(MachineRegistryError::AlreadyAttached);
|
return Err(GlobalStateManagerError::AlreadyAttached);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the name isn't duplicated
|
// Ensure the name isn't duplicated
|
||||||
if let Some(name) = state.name() {
|
if let Some(name) = state.name() {
|
||||||
if self.state_id_by_name.contains_key(&name) {
|
if self.state_id_by_name.contains_key(&name) {
|
||||||
return Err(MachineRegistryError::DuplicateName);
|
return Err(GlobalStateManagerError::DuplicateName(name));
|
||||||
}
|
}
|
||||||
// Register the named state
|
// Register the named state
|
||||||
self.state_id_by_name
|
self.state_id_by_name
|
||||||
@ -143,15 +147,15 @@ impl<S: State> StateAllocator<S> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn detach_state(&mut self, id: StateId<S>) -> MachineRegistryResult<S> {
|
pub fn detach_state(&mut self, id: StateId<S>) -> GlobalStateManagerResult<S> {
|
||||||
// Get the allocator slot
|
// Get the allocator slot
|
||||||
let Some(opt_state) = self.state_by_id.get_mut(&id.0) else {
|
let Some(opt_state) = self.state_by_id.get_mut(&id.0) else {
|
||||||
return Err(MachineRegistryError::InvalidId);
|
return Err(GlobalStateManagerError::InvalidId(id.external_id()));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Take the state out of the slot and ensure the state slot isn't detached already
|
// Take the state out of the slot and ensure the state slot isn't detached already
|
||||||
let Some(state) = opt_state.take() else {
|
let Some(state) = opt_state.take() else {
|
||||||
return Err(MachineRegistryError::NotAttached);
|
return Err(GlobalStateManagerError::NotAttached);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Release the name if it exists
|
// Release the name if it exists
|
||||||
@ -166,13 +170,13 @@ impl<S: State> StateAllocator<S> {
|
|||||||
Ok(state)
|
Ok(state)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_state(&self, id: StateId<S>) -> MachineRegistryResult<S> {
|
pub fn get_state(&self, id: StateId<S>) -> GlobalStateManagerResult<S> {
|
||||||
// Get the allocator slot
|
// Get the allocator slot
|
||||||
let Some(opt_state) = self.state_by_id.get(&id.0) else {
|
let Some(opt_state) = self.state_by_id.get(&id.0) else {
|
||||||
return Err(MachineRegistryError::InvalidId);
|
return Err(GlobalStateManagerError::InvalidId(id.external_id()));
|
||||||
};
|
};
|
||||||
let Some(state) = opt_state else {
|
let Some(state) = opt_state else {
|
||||||
return Err(MachineRegistryError::NotAttached);
|
return Err(GlobalStateManagerError::NotAttached);
|
||||||
};
|
};
|
||||||
Ok(state.clone())
|
Ok(state.clone())
|
||||||
}
|
}
|
||||||
@ -188,7 +192,7 @@ impl<S: State> StateAllocator<S> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: State> Default for StateAllocator<S> {
|
impl<S: State> Default for StateRegistry<S> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::new()
|
Self::new()
|
||||||
}
|
}
|
@ -106,25 +106,25 @@ impl TemplateState {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_active(&self, machine_registry_inner: &mut MachineRegistryInner) -> bool {
|
pub fn is_active(&self, gsm_inner: &mut GlobalStateManagerInner) -> bool {
|
||||||
// Save a backup of the entire state
|
// Save a backup of the entire state
|
||||||
let backup = machine_registry_inner.clone();
|
let backup = gsm_inner.clone();
|
||||||
|
|
||||||
// Make a copy of this template state
|
// Make a copy of this template state
|
||||||
let mut current_state = self.clone();
|
let mut current_state = self.clone();
|
||||||
|
|
||||||
// See what would happen if we try to generate this template
|
// See what would happen if we try to generate this template
|
||||||
let ok = current_state.generate(machine_registry_inner).is_ok();
|
let ok = current_state.generate(gsm_inner).is_ok();
|
||||||
|
|
||||||
// Restore the backup
|
// Restore the backup
|
||||||
*machine_registry_inner = backup;
|
*gsm_inner = backup;
|
||||||
|
|
||||||
// Return if this worked or not
|
// Return if this worked or not
|
||||||
ok
|
ok
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Network filter that keeps this template generation within per-network limits
|
/// Network filter that keeps this template generation within per-network limits
|
||||||
fn network_filter(&self, network_state_id: NetworkStateId) -> MachineRegistryResult<bool> {
|
fn network_filter(&self, network_state_id: NetworkStateId) -> GlobalStateManagerResult<bool> {
|
||||||
// Get the per network info
|
// Get the per network info
|
||||||
let Some(pni) = self.fields.machines_per_network.get(&network_state_id) else {
|
let Some(pni) = self.fields.machines_per_network.get(&network_state_id) else {
|
||||||
// If we haven't allocated anything in the network yet it is
|
// If we haven't allocated anything in the network yet it is
|
||||||
@ -144,26 +144,28 @@ impl TemplateState {
|
|||||||
|
|
||||||
pub fn generate(
|
pub fn generate(
|
||||||
&mut self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
gsm_inner: &mut GlobalStateManagerInner,
|
||||||
) -> MachineRegistryResult<MachineStateId> {
|
) -> GlobalStateManagerResult<MachineStateId> {
|
||||||
// See if we have reached our machine limit
|
// See if we have reached our machine limit
|
||||||
if let Some(limit_machine_count) = self.fields.limit_machine_count {
|
if let Some(limit_machine_count) = self.fields.limit_machine_count {
|
||||||
if self.fields.machines.len() < limit_machine_count {
|
if self.fields.machines.len() < limit_machine_count {
|
||||||
return Err(MachineRegistryError::TemplateComplete);
|
return Err(GlobalStateManagerError::TemplateComplete(self.debug_name()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If existing networks are all full, we'd have to allocate one, see if we'd be able to do that
|
// If existing networks are all full, we'd have to allocate one, see if we'd be able to do that
|
||||||
let Some(locations_list) = self.fields.locations_list.as_ref() else {
|
let Some(locations_list) = self.fields.locations_list.as_ref() else {
|
||||||
return Err(MachineRegistryError::TemplateComplete);
|
return Err(GlobalStateManagerError::TemplateComplete(self.debug_name()));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get a network to generate the machine on
|
// Get a network to generate the machine on
|
||||||
let network_state =
|
let Some(network_state) = locations_list.pick(gsm_inner, |_, x| self.network_filter(x))?
|
||||||
locations_list.pick(machine_registry_inner, |_, x| self.network_filter(x))?;
|
else {
|
||||||
|
return Err(GlobalStateManagerError::TemplateComplete(self.debug_name()));
|
||||||
|
};
|
||||||
|
|
||||||
// Allocate a machine id
|
// Allocate a machine id
|
||||||
let machine_state_id = machine_registry_inner.machine_states_mut().allocate_id();
|
let machine_state_id = gsm_inner.machine_states_mut().allocate_id();
|
||||||
|
|
||||||
// Create an anonymous machine state
|
// Create an anonymous machine state
|
||||||
let mut machine_state =
|
let mut machine_state =
|
||||||
@ -183,18 +185,18 @@ impl TemplateState {
|
|||||||
|
|
||||||
// Make the default route interface
|
// Make the default route interface
|
||||||
let vin0 = machine_state.allocate_interface(None, None)?;
|
let vin0 = machine_state.allocate_interface(None, None)?;
|
||||||
machine_state.attach_network(machine_registry_inner, &vin0, network_state.id())?;
|
machine_state.attach_network(gsm_inner, &vin0, network_state.id())?;
|
||||||
if network_state.is_ipv4() {
|
if network_state.is_ipv4() {
|
||||||
machine_state.allocate_address_ipv4(machine_registry_inner, &vin0, None, None)?;
|
machine_state.allocate_address_ipv4(gsm_inner, &vin0, None, None)?;
|
||||||
}
|
}
|
||||||
if network_state.is_ipv6() {
|
if network_state.is_ipv6() {
|
||||||
machine_state.allocate_address_ipv6(machine_registry_inner, &vin0, None, None)?;
|
machine_state.allocate_address_ipv6(gsm_inner, &vin0, None, None)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})() {
|
})() {
|
||||||
// Release the machine state and id if things failed to allocate
|
// Release the machine state and id if things failed to allocate
|
||||||
machine_state.release(machine_registry_inner);
|
machine_state.release(gsm_inner);
|
||||||
machine_registry_inner
|
gsm_inner
|
||||||
.machine_states_mut()
|
.machine_states_mut()
|
||||||
.release_id(machine_state_id)
|
.release_id(machine_state_id)
|
||||||
.expect("must succeed");
|
.expect("must succeed");
|
||||||
@ -202,7 +204,7 @@ impl TemplateState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Attach the state to the id
|
// Attach the state to the id
|
||||||
machine_registry_inner
|
gsm_inner
|
||||||
.machine_states_mut()
|
.machine_states_mut()
|
||||||
.attach_state(machine_state)
|
.attach_state(machine_state)
|
||||||
.expect("must succeed");
|
.expect("must succeed");
|
||||||
@ -217,7 +219,7 @@ impl TemplateState {
|
|||||||
.fields
|
.fields
|
||||||
.limit_machines_per_network
|
.limit_machines_per_network
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|wl| *machine_registry_inner.srng().weighted_choice_ref(wl));
|
.map(|wl| *gsm_inner.srng().weighted_choice_ref(wl));
|
||||||
PerNetworkInfo {
|
PerNetworkInfo {
|
||||||
limit_machine_count,
|
limit_machine_count,
|
||||||
machines: imbl::HashSet::new(),
|
machines: imbl::HashSet::new(),
|
@ -1,87 +0,0 @@
|
|||||||
mod address_pool;
|
|
||||||
mod machine_registry_inner;
|
|
||||||
mod state;
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
use address_pool::*;
|
|
||||||
use machine_registry_inner::*;
|
|
||||||
use state::*;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct Machine {}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct MachineRegistryUnlockedInner {
|
|
||||||
config: config::Config,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum MachineRegistryError {
|
|
||||||
InvalidId,
|
|
||||||
InvalidName,
|
|
||||||
InvalidPrefix,
|
|
||||||
AlreadyAttached,
|
|
||||||
NotAttached,
|
|
||||||
DuplicateName,
|
|
||||||
ProfileComplete,
|
|
||||||
TemplateComplete,
|
|
||||||
NetworkComplete,
|
|
||||||
BlueprintComplete,
|
|
||||||
ProfileNotFound,
|
|
||||||
MachineNotFound,
|
|
||||||
NetworkNotFound,
|
|
||||||
TemplateNotFound,
|
|
||||||
BlueprintNotFound,
|
|
||||||
ModelNotFound,
|
|
||||||
NoDefaultModel,
|
|
||||||
NoDefaultNetwork,
|
|
||||||
NoAllocation,
|
|
||||||
ResourceInUse,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type MachineRegistryResult<T> = Result<T, MachineRegistryError>;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct MachineRegistry {
|
|
||||||
inner: Arc<Mutex<MachineRegistryInner>>,
|
|
||||||
unlocked_inner: Arc<MachineRegistryUnlockedInner>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MachineRegistry {
|
|
||||||
///////////////////////////////////////////////////////////
|
|
||||||
/// Public Interface
|
|
||||||
pub fn new(config: config::Config) -> Self {
|
|
||||||
let unlocked_inner = Arc::new(MachineRegistryUnlockedInner { config });
|
|
||||||
Self {
|
|
||||||
inner: Arc::new(Mutex::new(MachineRegistryInner::new(
|
|
||||||
unlocked_inner.clone(),
|
|
||||||
))),
|
|
||||||
unlocked_inner,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn allocate(&self, profile: String) -> MachineRegistryResult<MachineId> {
|
|
||||||
let mut inner = self.inner.lock();
|
|
||||||
let saved_state = (*inner).clone();
|
|
||||||
match inner.allocate(profile) {
|
|
||||||
Ok(v) => Ok(v),
|
|
||||||
Err(e) => {
|
|
||||||
*inner = saved_state;
|
|
||||||
Err(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn release(&self, machine_id: MachineId) -> MachineRegistryResult<()> {
|
|
||||||
let mut inner = self.inner.lock();
|
|
||||||
let saved_state = (*inner).clone();
|
|
||||||
match inner.release(machine_id) {
|
|
||||||
Ok(v) => Ok(v),
|
|
||||||
Err(e) => {
|
|
||||||
*inner = saved_state;
|
|
||||||
Err(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,12 +1,12 @@
|
|||||||
pub mod config;
|
pub mod config;
|
||||||
mod machine_registry;
|
mod global_state_manager;
|
||||||
mod server_processor;
|
mod server_processor;
|
||||||
mod stable_rng;
|
mod stable_rng;
|
||||||
mod weighted_list;
|
mod weighted_list;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use machine_registry::*;
|
use global_state_manager::*;
|
||||||
use server_processor::*;
|
use server_processor::*;
|
||||||
use stable_rng::*;
|
use stable_rng::*;
|
||||||
use weighted_list::*;
|
use weighted_list::*;
|
||||||
@ -26,6 +26,8 @@ pub enum RouterServerError {
|
|||||||
SerializationError(postcard::Error),
|
SerializationError(postcard::Error),
|
||||||
#[error("IO Error: {0}")]
|
#[error("IO Error: {0}")]
|
||||||
IoError(io::ErrorKind),
|
IoError(io::ErrorKind),
|
||||||
|
#[error("State Error: {0}")]
|
||||||
|
StateError(global_state_manager::GlobalStateManagerError),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type RouterServerResult<T> = Result<T, RouterServerError>;
|
pub type RouterServerResult<T> = Result<T, RouterServerError>;
|
||||||
@ -40,10 +42,10 @@ enum RunLoopEvent {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct RouterServerUnlockedInner {
|
struct RouterServerUnlockedInner {
|
||||||
config: config::Config,
|
|
||||||
new_client_sender: flume::Sender<SendPinBoxFuture<RunLoopEvent>>,
|
new_client_sender: flume::Sender<SendPinBoxFuture<RunLoopEvent>>,
|
||||||
new_client_receiver: flume::Receiver<SendPinBoxFuture<RunLoopEvent>>,
|
new_client_receiver: flume::Receiver<SendPinBoxFuture<RunLoopEvent>>,
|
||||||
server_processor: ServerProcessor,
|
server_processor: ServerProcessor,
|
||||||
|
global_state_manager: GlobalStateManager,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -60,69 +62,44 @@ pub struct RouterServer {
|
|||||||
inner: Arc<Mutex<RouterServerInner>>,
|
inner: Arc<Mutex<RouterServerInner>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for RouterServer {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl RouterServer {
|
impl RouterServer {
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Public Interface
|
// Public Interface
|
||||||
|
|
||||||
/// Create a router server for virtual networking
|
/// Create a router server for virtual networking
|
||||||
pub fn new(config: config::Config) -> Self {
|
pub fn new() -> Self {
|
||||||
// Make a channel to receive new clients
|
// Make a channel to receive new clients
|
||||||
let (new_client_sender, new_client_receiver) = flume::unbounded();
|
let (new_client_sender, new_client_receiver) = flume::unbounded();
|
||||||
|
|
||||||
|
// Make a machine registry to manage state
|
||||||
|
let global_state_manager = GlobalStateManager::new();
|
||||||
|
|
||||||
// Make a server processor to handle messages
|
// Make a server processor to handle messages
|
||||||
let server_processor = ServerProcessor::new(config.clone());
|
let server_processor = ServerProcessor::new(global_state_manager.clone());
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
unlocked_inner: Arc::new(RouterServerUnlockedInner {
|
unlocked_inner: Arc::new(RouterServerUnlockedInner {
|
||||||
config,
|
|
||||||
new_client_sender,
|
new_client_sender,
|
||||||
new_client_receiver,
|
new_client_receiver,
|
||||||
server_processor,
|
server_processor,
|
||||||
|
global_state_manager,
|
||||||
}),
|
}),
|
||||||
inner: Arc::new(Mutex::new(RouterServerInner {})),
|
inner: Arc::new(Mutex::new(RouterServerInner {})),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn process_connection<R, W>(self, reader: R, writer: W) -> RunLoopEvent
|
/// Execute a config file on the global state manager
|
||||||
where
|
pub fn execute_config(&self, cfg: config::Config) -> RouterServerResult<()> {
|
||||||
R: AsyncRead + Send + Unpin,
|
|
||||||
W: AsyncWrite + Send + Unpin,
|
|
||||||
{
|
|
||||||
let framed_reader = FramedRead::new(reader, BytesCodec);
|
|
||||||
let framed_writer = FramedWrite::new(writer, BytesCodec);
|
|
||||||
|
|
||||||
let (outbound_sender, outbound_receiver) = flume::unbounded();
|
|
||||||
let outbound_fut = system_boxed(
|
|
||||||
outbound_receiver
|
|
||||||
.into_stream()
|
|
||||||
.map(|command| {
|
|
||||||
to_stdvec(&command)
|
|
||||||
.map_err(io::Error::other)
|
|
||||||
.map(Bytes::from)
|
|
||||||
})
|
|
||||||
.forward(framed_writer),
|
|
||||||
);
|
|
||||||
|
|
||||||
let inbound_fut = system_boxed(framed_reader.try_for_each(|x| async {
|
|
||||||
let x = x;
|
|
||||||
let cmd = from_bytes::<ServerProcessorCommand>(&x).map_err(io::Error::other)?;
|
|
||||||
|
|
||||||
self.unlocked_inner
|
self.unlocked_inner
|
||||||
.server_processor
|
.global_state_manager
|
||||||
.enqueue_command(cmd, outbound_sender.clone());
|
.execute_config(cfg)
|
||||||
|
.map_err(RouterServerError::StateError)
|
||||||
Ok(())
|
|
||||||
}));
|
|
||||||
|
|
||||||
let mut unord = FuturesUnordered::new();
|
|
||||||
unord.push(outbound_fut);
|
|
||||||
unord.push(inbound_fut);
|
|
||||||
|
|
||||||
if let Some(Err(e)) = unord.next().await {
|
|
||||||
error!("{}", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
RunLoopEvent::Done
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Accept RouterClient connections on a TCP socket
|
/// Accept RouterClient connections on a TCP socket
|
||||||
@ -329,4 +306,46 @@ impl RouterServer {
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Private Implementation
|
// Private Implementation
|
||||||
|
|
||||||
|
async fn process_connection<R, W>(self, reader: R, writer: W) -> RunLoopEvent
|
||||||
|
where
|
||||||
|
R: AsyncRead + Send + Unpin,
|
||||||
|
W: AsyncWrite + Send + Unpin,
|
||||||
|
{
|
||||||
|
let framed_reader = FramedRead::new(reader, BytesCodec);
|
||||||
|
let framed_writer = FramedWrite::new(writer, BytesCodec);
|
||||||
|
|
||||||
|
let (outbound_sender, outbound_receiver) = flume::unbounded();
|
||||||
|
let outbound_fut = system_boxed(
|
||||||
|
outbound_receiver
|
||||||
|
.into_stream()
|
||||||
|
.map(|command| {
|
||||||
|
to_stdvec(&command)
|
||||||
|
.map_err(io::Error::other)
|
||||||
|
.map(Bytes::from)
|
||||||
|
})
|
||||||
|
.forward(framed_writer),
|
||||||
|
);
|
||||||
|
|
||||||
|
let inbound_fut = system_boxed(framed_reader.try_for_each(|x| async {
|
||||||
|
let x = x;
|
||||||
|
let cmd = from_bytes::<ServerProcessorCommand>(&x).map_err(io::Error::other)?;
|
||||||
|
|
||||||
|
self.unlocked_inner
|
||||||
|
.server_processor
|
||||||
|
.enqueue_command(cmd, outbound_sender.clone());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}));
|
||||||
|
|
||||||
|
let mut unord = FuturesUnordered::new();
|
||||||
|
unord.push(outbound_fut);
|
||||||
|
unord.push(inbound_fut);
|
||||||
|
|
||||||
|
if let Some(Err(e)) = unord.next().await {
|
||||||
|
error!("{}", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
RunLoopEvent::Done
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,11 +12,9 @@ struct ServerProcessorInner {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct ServerProcessorUnlockedInner {
|
struct ServerProcessorUnlockedInner {
|
||||||
config: config::Config,
|
machine_registry: GlobalStateManager,
|
||||||
receiver: flume::Receiver<ServerProcessorCommandRecord>,
|
receiver: flume::Receiver<ServerProcessorCommandRecord>,
|
||||||
sender: flume::Sender<ServerProcessorCommandRecord>,
|
sender: flume::Sender<ServerProcessorCommandRecord>,
|
||||||
|
|
||||||
machine_registry: MachineRegistry,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -29,15 +27,14 @@ impl ServerProcessor {
|
|||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// Public Interface
|
// Public Interface
|
||||||
|
|
||||||
pub fn new(config: config::Config) -> Self {
|
pub fn new(machine_registry: GlobalStateManager) -> Self {
|
||||||
let (sender, receiver) = flume::unbounded();
|
let (sender, receiver) = flume::unbounded();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
unlocked_inner: Arc::new(ServerProcessorUnlockedInner {
|
unlocked_inner: Arc::new(ServerProcessorUnlockedInner {
|
||||||
config: config.clone(),
|
|
||||||
sender,
|
sender,
|
||||||
receiver,
|
receiver,
|
||||||
machine_registry: MachineRegistry::new(config),
|
machine_registry,
|
||||||
}),
|
}),
|
||||||
inner: Arc::new(Mutex::new(ServerProcessorInner {})),
|
inner: Arc::new(Mutex::new(ServerProcessorInner {})),
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user