mirror of
https://gitlab.com/veilid/veilid.git
synced 2025-01-26 22:37:05 -05:00
[skip ci] checkpoint
This commit is contained in:
parent
c361dce995
commit
10534b5bb7
@ -1,7 +1,7 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
/// Locations where a machine can be instantiated
|
/// Locations where a machine can be instantiated
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum MachineLocationsList {
|
pub enum MachineLocationsList {
|
||||||
Networks {
|
Networks {
|
||||||
networks: WeightedList<NetworkStateId>,
|
networks: WeightedList<NetworkStateId>,
|
||||||
|
@ -156,25 +156,26 @@ impl NetworkState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear_ipv4(
|
pub fn clear_ipv4(
|
||||||
&self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
machine_registry_inner: &mut MachineRegistryInner,
|
||||||
) -> MachineRegistryResult<()> {
|
) -> MachineRegistryResult<()> {
|
||||||
let Some(ipv4) = inner.ipv4.as_mut() else {
|
let Some(ipv4) = self.fields.ipv4.clone() else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
inner.address_pool.clear_ipv4(|_n, t| match t {
|
let mut address_pool = self.fields.address_pool.clone();
|
||||||
|
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(),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// If we have a gateway, release its external address
|
// If we have a gateway, release its external address
|
||||||
// if it belongs to a different network
|
// if it belongs to a different network
|
||||||
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 external_network_state = machine_registry_inner
|
let mut external_network_state = machine_registry_inner
|
||||||
.network_states()
|
.network_states()
|
||||||
.get_state(gateway.params.external_network)
|
.get_state(gateway.params.external_network)
|
||||||
.expect("must succeed");
|
.expect("must succeed");
|
||||||
@ -183,35 +184,47 @@ impl NetworkState {
|
|||||||
external_network_state
|
external_network_state
|
||||||
.release_address_v4(gateway.external_interface_address.ip)
|
.release_address_v4(gateway.external_interface_address.ip)
|
||||||
.expect("must succeed");
|
.expect("must succeed");
|
||||||
|
|
||||||
|
// Update external network
|
||||||
|
machine_registry_inner
|
||||||
|
.network_states_mut()
|
||||||
|
.set_state(external_network_state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inner.ipv4 = None;
|
// Update fields
|
||||||
|
self.fields = Arc::new(NetworkStateFields {
|
||||||
|
ipv4: None,
|
||||||
|
address_pool,
|
||||||
|
..(*self.fields).clone()
|
||||||
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_ipv4(
|
pub fn set_ipv4(
|
||||||
&self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
machine_registry_inner: &mut MachineRegistryInner,
|
||||||
params: NetworkStateIpv4Params,
|
params: NetworkStateIpv4Params,
|
||||||
gateway_params: Option<NetworkStateIpv4GatewayParams>,
|
gateway_params: Option<NetworkStateIpv4GatewayParams>,
|
||||||
) -> MachineRegistryResult<()> {
|
) -> MachineRegistryResult<()> {
|
||||||
Self::clear_ipv4_inner(self.id(), &mut *inner, machine_registry_inner)?;
|
self.clear_ipv4(machine_registry_inner)?;
|
||||||
|
|
||||||
inner.address_pool.add_scope_v4(params.allocation);
|
let mut address_pool = self.fields.address_pool.clone();
|
||||||
|
address_pool.add_scope_v4(params.allocation);
|
||||||
|
|
||||||
let gateway = match gateway_params {
|
let gateway = match gateway_params {
|
||||||
Some(gateway_params) => {
|
Some(gateway_params) => {
|
||||||
// Allocate or reserve an internal network address for the gateway
|
// Allocate or reserve an internal network address for the gateway
|
||||||
let internal_address =
|
let internal_address =
|
||||||
if let Some(internal_address) = gateway_params.internal_address {
|
if let Some(internal_address) = gateway_params.internal_address {
|
||||||
inner.address_pool.reserve_allocation_v4(
|
address_pool.reserve_allocation_v4(
|
||||||
Ipv4Net::new(internal_address, 32).expect("must succeed"),
|
Ipv4Net::new(internal_address, 32).expect("must succeed"),
|
||||||
Some(OwnerTag::Gateway(self.id())),
|
Some(OwnerTag::Gateway(self.id())),
|
||||||
)?;
|
)?;
|
||||||
internal_address
|
internal_address
|
||||||
} else {
|
} else {
|
||||||
let Some(internal_address) = inner.address_pool.allocate_random_v4(
|
let Some(internal_address) = address_pool.allocate_random_v4(
|
||||||
machine_registry_inner.srng(),
|
machine_registry_inner.srng(),
|
||||||
32,
|
32,
|
||||||
OwnerTag::Gateway(self.id()),
|
OwnerTag::Gateway(self.id()),
|
||||||
@ -230,7 +243,7 @@ impl NetworkState {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Get the external network state
|
// Get the external network state
|
||||||
let external_network_state = machine_registry_inner
|
let mut external_network_state = machine_registry_inner
|
||||||
.network_states()
|
.network_states()
|
||||||
.get_state(gateway_params.external_network)
|
.get_state(gateway_params.external_network)
|
||||||
.expect("must succeed");
|
.expect("must succeed");
|
||||||
@ -255,6 +268,11 @@ impl NetworkState {
|
|||||||
)?
|
)?
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Update external network
|
||||||
|
machine_registry_inner
|
||||||
|
.network_states_mut()
|
||||||
|
.set_state(external_network_state);
|
||||||
|
|
||||||
// Return the gateway state
|
// Return the gateway state
|
||||||
Some(NetworkStateIpv4Gateway {
|
Some(NetworkStateIpv4Gateway {
|
||||||
params: gateway_params,
|
params: gateway_params,
|
||||||
@ -267,38 +285,85 @@ impl NetworkState {
|
|||||||
|
|
||||||
let ipv4 = NetworkStateIpv4 { params, gateway };
|
let ipv4 = NetworkStateIpv4 { params, gateway };
|
||||||
|
|
||||||
inner.ipv4 = Some(ipv4);
|
// Update fields
|
||||||
|
self.fields = Arc::new(NetworkStateFields {
|
||||||
|
ipv4: Some(ipv4),
|
||||||
|
address_pool,
|
||||||
|
..(*self.fields).clone()
|
||||||
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear_ipv6(
|
pub fn clear_ipv6(
|
||||||
&self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
machine_registry_inner: &mut MachineRegistryInner,
|
||||||
) -> MachineRegistryResult<()> {
|
) -> MachineRegistryResult<()> {
|
||||||
Self::clear_ipv6_inner(self.id(), &mut *inner, machine_registry_inner)
|
let Some(ipv6) = self.fields.ipv6.clone() else {
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut address_pool = self.fields.address_pool.clone();
|
||||||
|
address_pool.clear_ipv6(|_n, t| match t {
|
||||||
|
OwnerTag::Machine(_) => true,
|
||||||
|
OwnerTag::Network(nsid) => *nsid != self.id(),
|
||||||
|
OwnerTag::Gateway(nsid) => *nsid != self.id(),
|
||||||
|
})?;
|
||||||
|
|
||||||
|
// If we have a gateway, release its external address
|
||||||
|
// if it belongs to a different network
|
||||||
|
if let Some(gateway) = ipv6.gateway.as_ref() {
|
||||||
|
if gateway.params.external_network != self.id() {
|
||||||
|
// Get the external network state
|
||||||
|
let mut external_network_state = machine_registry_inner
|
||||||
|
.network_states()
|
||||||
|
.get_state(gateway.params.external_network)
|
||||||
|
.expect("must succeed");
|
||||||
|
|
||||||
|
// Release external address
|
||||||
|
external_network_state
|
||||||
|
.release_address_v6(gateway.external_interface_address.ip)
|
||||||
|
.expect("must succeed");
|
||||||
|
|
||||||
|
// Update external network
|
||||||
|
machine_registry_inner
|
||||||
|
.network_states_mut()
|
||||||
|
.set_state(external_network_state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update fields
|
||||||
|
self.fields = Arc::new(NetworkStateFields {
|
||||||
|
ipv6: None,
|
||||||
|
address_pool,
|
||||||
|
..(*self.fields).clone()
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
pub fn set_ipv6(
|
pub fn set_ipv6(
|
||||||
&self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
machine_registry_inner: &mut MachineRegistryInner,
|
||||||
params: NetworkStateIpv6Params,
|
params: NetworkStateIpv6Params,
|
||||||
gateway_params: Option<NetworkStateIpv6GatewayParams>,
|
gateway_params: Option<NetworkStateIpv6GatewayParams>,
|
||||||
) -> MachineRegistryResult<()> {
|
) -> MachineRegistryResult<()> {
|
||||||
Self::clear_ipv6_inner(self.id(), &mut *inner, machine_registry_inner)?;
|
self.clear_ipv6(machine_registry_inner)?;
|
||||||
|
|
||||||
inner.address_pool.add_scope_v6(params.allocation);
|
let mut address_pool = self.fields.address_pool.clone();
|
||||||
|
address_pool.add_scope_v6(params.allocation);
|
||||||
|
|
||||||
let gateway = match gateway_params {
|
let gateway = match gateway_params {
|
||||||
Some(gateway_params) => {
|
Some(gateway_params) => {
|
||||||
// Allocate or reserve an internal network address for the gateway
|
// Allocate or reserve an internal network address for the gateway
|
||||||
let internal_address =
|
let internal_address =
|
||||||
if let Some(internal_address) = gateway_params.internal_address {
|
if let Some(internal_address) = gateway_params.internal_address {
|
||||||
inner.address_pool.reserve_allocation_v6(
|
address_pool.reserve_allocation_v6(
|
||||||
Ipv6Net::new(internal_address, 128).expect("must succeed"),
|
Ipv6Net::new(internal_address, 128).expect("must succeed"),
|
||||||
Some(OwnerTag::Gateway(self.id())),
|
Some(OwnerTag::Gateway(self.id())),
|
||||||
)?;
|
)?;
|
||||||
internal_address
|
internal_address
|
||||||
} else {
|
} else {
|
||||||
let Some(internal_address) = inner.address_pool.allocate_random_v6(
|
let Some(internal_address) = address_pool.allocate_random_v6(
|
||||||
machine_registry_inner.srng(),
|
machine_registry_inner.srng(),
|
||||||
128,
|
128,
|
||||||
OwnerTag::Gateway(self.id()),
|
OwnerTag::Gateway(self.id()),
|
||||||
@ -317,7 +382,7 @@ impl NetworkState {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Get the external network state
|
// Get the external network state
|
||||||
let external_network_state = machine_registry_inner
|
let mut external_network_state = machine_registry_inner
|
||||||
.network_states()
|
.network_states()
|
||||||
.get_state(gateway_params.external_network)
|
.get_state(gateway_params.external_network)
|
||||||
.expect("must succeed");
|
.expect("must succeed");
|
||||||
@ -342,6 +407,11 @@ impl NetworkState {
|
|||||||
)?
|
)?
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Update external network
|
||||||
|
machine_registry_inner
|
||||||
|
.network_states_mut()
|
||||||
|
.set_state(external_network_state);
|
||||||
|
|
||||||
// Return the gateway state
|
// Return the gateway state
|
||||||
Some(NetworkStateIpv6Gateway {
|
Some(NetworkStateIpv6Gateway {
|
||||||
params: gateway_params,
|
params: gateway_params,
|
||||||
@ -354,30 +424,36 @@ impl NetworkState {
|
|||||||
|
|
||||||
let ipv6 = NetworkStateIpv6 { params, gateway };
|
let ipv6 = NetworkStateIpv6 { params, gateway };
|
||||||
|
|
||||||
inner.ipv6 = Some(ipv6);
|
// Update fields
|
||||||
|
self.fields = Arc::new(NetworkStateFields {
|
||||||
|
ipv6: Some(ipv6),
|
||||||
|
address_pool,
|
||||||
|
..(*self.fields).clone()
|
||||||
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_ipv4(&self) -> bool {
|
pub fn is_ipv4(&self) -> bool {
|
||||||
self.fields.lock().ipv4.is_some()
|
self.fields.ipv4.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_ipv6(&self) -> bool {
|
pub fn is_ipv6(&self) -> bool {
|
||||||
self.fields.lock().ipv6.is_some()
|
self.fields.ipv6.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_active(&self) -> MachineRegistryResult<bool> {
|
pub fn is_active(&self) -> MachineRegistryResult<bool> {
|
||||||
let mut can_allocate = false;
|
let mut can_allocate = false;
|
||||||
|
|
||||||
if inner.ipv4.is_some() {
|
if self.fields.ipv4.is_some() {
|
||||||
//
|
//
|
||||||
if !inner.address_pool.can_allocate_v4(32)? {
|
if !self.fields.address_pool.can_allocate_v4(32)? {
|
||||||
can_allocate = false;
|
can_allocate = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if inner.ipv6.is_some() {
|
if self.fields.ipv6.is_some() {
|
||||||
//
|
//
|
||||||
if !inner.address_pool.can_allocate_v6(128)? {
|
if !self.fields.address_pool.can_allocate_v6(128)? {
|
||||||
can_allocate = false;
|
can_allocate = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -390,61 +466,103 @@ impl NetworkState {
|
|||||||
owner_tag: OwnerTag,
|
owner_tag: OwnerTag,
|
||||||
opt_address: Option<Ipv4Addr>,
|
opt_address: Option<Ipv4Addr>,
|
||||||
) -> MachineRegistryResult<Ifv4Addr> {
|
) -> MachineRegistryResult<Ifv4Addr> {
|
||||||
let mut inner = self.fields.lock();
|
let net = self.allocate_subnet_v4(machine_registry_inner, owner_tag, opt_address, 32)?;
|
||||||
|
|
||||||
let net = Self::allocate_net_v4_inner(
|
|
||||||
&mut *inner,
|
|
||||||
machine_registry_inner,
|
|
||||||
owner_tag,
|
|
||||||
opt_address,
|
|
||||||
32,
|
|
||||||
)?;
|
|
||||||
let ip = net.addr();
|
let ip = net.addr();
|
||||||
|
|
||||||
|
let ipv4 = self.fields.ipv4.as_ref().unwrap();
|
||||||
|
let netmask = ipv4.params.allocation.netmask();
|
||||||
|
let broadcast = ipv4.params.allocation.broadcast();
|
||||||
|
|
||||||
let ifaddr = Ifv4Addr {
|
let ifaddr = Ifv4Addr {
|
||||||
ip,
|
ip,
|
||||||
netmask: inner.ipv4.as_ref().unwrap().params.allocation.netmask(),
|
netmask,
|
||||||
broadcast: Some(inner.ipv4.as_ref().unwrap().params.allocation.broadcast()),
|
broadcast: Some(broadcast),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(ifaddr)
|
Ok(ifaddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn can_allocate_address_v4(&self, opt_address: Option<Ipv4Addr>) -> bool {
|
pub fn can_allocate_address_v4(&self, opt_address: Option<Ipv4Addr>) -> bool {
|
||||||
Self::can_allocate_net_v4_inner(&*inner, opt_address, 32)
|
self.can_allocate_subnet_v4(opt_address, 32)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn allocate_subnet_v4(
|
pub fn allocate_subnet_v4(
|
||||||
&self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
machine_registry_inner: &mut MachineRegistryInner,
|
||||||
owner_tag: OwnerTag,
|
owner_tag: OwnerTag,
|
||||||
opt_address: Option<Ipv4Addr>,
|
opt_address: Option<Ipv4Addr>,
|
||||||
prefix: u8,
|
prefix: u8,
|
||||||
) -> MachineRegistryResult<Ipv4Net> {
|
) -> MachineRegistryResult<Ipv4Net> {
|
||||||
let net = Self::allocate_net_v4_inner(
|
if self.fields.ipv4.is_none() {
|
||||||
&mut *inner,
|
return Err(MachineRegistryError::NoAllocation);
|
||||||
machine_registry_inner,
|
}
|
||||||
owner_tag,
|
|
||||||
opt_address,
|
// See if we are requesting a specific address
|
||||||
|
let mut address_pool = self.fields.address_pool.clone();
|
||||||
|
|
||||||
|
let net = if let Some(address) = opt_address {
|
||||||
|
// Get the net form for this address
|
||||||
|
let net = Ipv4Net::new(address, prefix).expect("must succeed");
|
||||||
|
address_pool.reserve_allocation_v4(net, Some(owner_tag))?;
|
||||||
|
net
|
||||||
|
} else {
|
||||||
|
// Get a random address if available
|
||||||
|
let Some(allocation) = address_pool.allocate_random_v4(
|
||||||
|
machine_registry_inner.srng(),
|
||||||
prefix,
|
prefix,
|
||||||
)?;
|
owner_tag,
|
||||||
|
)?
|
||||||
|
else {
|
||||||
|
return Err(MachineRegistryError::NoAllocation);
|
||||||
|
};
|
||||||
|
allocation
|
||||||
|
};
|
||||||
|
|
||||||
|
// Update fields
|
||||||
|
self.fields = Arc::new(NetworkStateFields {
|
||||||
|
address_pool,
|
||||||
|
..(*self.fields).clone()
|
||||||
|
});
|
||||||
|
|
||||||
Ok(net)
|
Ok(net)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn can_allocate_subnet_v4(&self, opt_address: Option<Ipv4Addr>, prefix: u8) -> bool {
|
pub fn can_allocate_subnet_v4(&self, opt_address: Option<Ipv4Addr>, prefix: u8) -> bool {
|
||||||
Self::can_allocate_net_v4_inner(&*inner, opt_address, prefix)
|
if self.fields.ipv4.is_none() {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// See if we are requesting a specific address
|
||||||
|
if let Some(address) = opt_address {
|
||||||
|
// Get the net form for this address
|
||||||
|
let net = Ipv4Net::new(address, prefix).expect("must succeed");
|
||||||
|
self.fields.address_pool.get_overlaps_v4(net).is_empty()
|
||||||
|
} else {
|
||||||
|
// Get a random address if available
|
||||||
|
self.fields
|
||||||
|
.address_pool
|
||||||
|
.can_allocate_v4(prefix)
|
||||||
|
.unwrap_or(false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn release_address_v4(
|
pub fn release_address_v4(
|
||||||
&mut self,
|
&mut self,
|
||||||
addr: Ipv4Addr,
|
addr: Ipv4Addr,
|
||||||
) -> MachineRegistryResult<Option<OwnerTag>> {
|
) -> MachineRegistryResult<Option<OwnerTag>> {
|
||||||
Self::release_subnet_v4_inner(&mut *inner, 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) -> MachineRegistryResult<Option<OwnerTag>> {
|
||||||
Self::release_subnet_v4_inner(&mut *inner, net)
|
let mut address_pool = self.fields.address_pool.clone();
|
||||||
|
let opt_tag = address_pool.release_allocation_v4(net)?;
|
||||||
|
|
||||||
|
// Update fields
|
||||||
|
self.fields = Arc::new(NetworkStateFields {
|
||||||
|
address_pool,
|
||||||
|
..(*self.fields).clone()
|
||||||
|
});
|
||||||
|
Ok(opt_tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn allocate_address_v6(
|
pub fn allocate_address_v6(
|
||||||
@ -453,157 +571,69 @@ impl NetworkState {
|
|||||||
owner_tag: OwnerTag,
|
owner_tag: OwnerTag,
|
||||||
opt_address: Option<Ipv6Addr>,
|
opt_address: Option<Ipv6Addr>,
|
||||||
) -> MachineRegistryResult<Ifv6Addr> {
|
) -> MachineRegistryResult<Ifv6Addr> {
|
||||||
let net = Self::allocate_net_v6_inner(
|
let net = self.allocate_subnet_v6(machine_registry_inner, owner_tag, opt_address, 128)?;
|
||||||
&mut *inner,
|
|
||||||
machine_registry_inner,
|
|
||||||
owner_tag,
|
|
||||||
opt_address,
|
|
||||||
128,
|
|
||||||
)?;
|
|
||||||
let ip = net.addr();
|
let ip = net.addr();
|
||||||
|
|
||||||
|
let ipv6 = self.fields.ipv6.as_ref().unwrap();
|
||||||
|
let netmask = ipv6.params.allocation.netmask();
|
||||||
|
let broadcast = ipv6.params.allocation.broadcast();
|
||||||
|
|
||||||
let ifaddr = Ifv6Addr {
|
let ifaddr = Ifv6Addr {
|
||||||
ip,
|
ip,
|
||||||
netmask: inner.ipv6.as_ref().unwrap().params.allocation.netmask(),
|
netmask,
|
||||||
broadcast: Some(inner.ipv6.as_ref().unwrap().params.allocation.broadcast()),
|
broadcast: Some(broadcast),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(ifaddr)
|
Ok(ifaddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn can_allocate_address_v6(&self, opt_address: Option<Ipv6Addr>) -> bool {
|
pub fn can_allocate_address_v6(&self, opt_address: Option<Ipv6Addr>) -> bool {
|
||||||
Self::can_allocate_net_v6_inner(&*inner, opt_address, 128)
|
self.can_allocate_subnet_v6(opt_address, 128)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn allocate_subnet_v6(
|
pub fn allocate_subnet_v6(
|
||||||
&self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
machine_registry_inner: &mut MachineRegistryInner,
|
||||||
owner_tag: OwnerTag,
|
owner_tag: OwnerTag,
|
||||||
opt_address: Option<Ipv6Addr>,
|
opt_address: Option<Ipv6Addr>,
|
||||||
prefix: u8,
|
prefix: u8,
|
||||||
) -> MachineRegistryResult<Ipv6Net> {
|
) -> MachineRegistryResult<Ipv6Net> {
|
||||||
let net = Self::allocate_net_v6_inner(
|
if self.fields.ipv6.is_none() {
|
||||||
&mut *inner,
|
return Err(MachineRegistryError::NoAllocation);
|
||||||
machine_registry_inner,
|
}
|
||||||
owner_tag,
|
|
||||||
opt_address,
|
// See if we are requesting a specific address
|
||||||
|
let mut address_pool = self.fields.address_pool.clone();
|
||||||
|
|
||||||
|
let net = if let Some(address) = opt_address {
|
||||||
|
// Get the net form for this address
|
||||||
|
let net = Ipv6Net::new(address, prefix).expect("must succeed");
|
||||||
|
address_pool.reserve_allocation_v6(net, Some(owner_tag))?;
|
||||||
|
net
|
||||||
|
} else {
|
||||||
|
// Get a random address if available
|
||||||
|
let Some(allocation) = address_pool.allocate_random_v6(
|
||||||
|
machine_registry_inner.srng(),
|
||||||
prefix,
|
prefix,
|
||||||
)?;
|
owner_tag,
|
||||||
|
)?
|
||||||
|
else {
|
||||||
|
return Err(MachineRegistryError::NoAllocation);
|
||||||
|
};
|
||||||
|
allocation
|
||||||
|
};
|
||||||
|
|
||||||
|
// Update fields
|
||||||
|
self.fields = Arc::new(NetworkStateFields {
|
||||||
|
address_pool,
|
||||||
|
..(*self.fields).clone()
|
||||||
|
});
|
||||||
|
|
||||||
Ok(net)
|
Ok(net)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn can_allocate_subnet_v6(&self, opt_address: Option<Ipv6Addr>, prefix: u8) -> bool {
|
pub fn can_allocate_subnet_v6(&self, opt_address: Option<Ipv6Addr>, prefix: u8) -> bool {
|
||||||
Self::can_allocate_net_v6_inner(&*inner, opt_address, prefix)
|
if self.fields.ipv6.is_none() {
|
||||||
}
|
|
||||||
|
|
||||||
pub fn release_address_v6(&self, addr: Ipv6Addr) -> MachineRegistryResult<Option<OwnerTag>> {
|
|
||||||
Self::release_subnet_v6_inner(&mut *inner, Ipv6Net::new(addr, 128).expect("must succeed"))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn release_subnet_v6(&self, net: Ipv6Net) -> MachineRegistryResult<Option<OwnerTag>> {
|
|
||||||
Self::release_subnet_v6_inner(&mut *inner, net)
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
fn clear_ipv6_inner(
|
|
||||||
self_id: NetworkStateId,
|
|
||||||
inner: &mut NetworkStateFields,
|
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
|
||||||
) -> MachineRegistryResult<()> {
|
|
||||||
let Some(ipv6) = inner.ipv6.as_mut() else {
|
|
||||||
return Ok(());
|
|
||||||
};
|
|
||||||
|
|
||||||
inner.address_pool.clear_ipv6(|_n, t| match t {
|
|
||||||
OwnerTag::Machine(_) => true,
|
|
||||||
OwnerTag::Network(nsid) => *nsid != self_id,
|
|
||||||
OwnerTag::Gateway(nsid) => *nsid != self_id,
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// If we have a gateway, release its external address
|
|
||||||
// if it belongs to a different network
|
|
||||||
if let Some(gateway) = ipv6.gateway.as_ref() {
|
|
||||||
if gateway.params.external_network != self_id {
|
|
||||||
// Get the external network state
|
|
||||||
let external_network_state = machine_registry_inner
|
|
||||||
.network_states()
|
|
||||||
.get_state(gateway.params.external_network)
|
|
||||||
.expect("must succeed");
|
|
||||||
|
|
||||||
// Release external address
|
|
||||||
external_network_state
|
|
||||||
.release_address_v6(gateway.external_interface_address.ip)
|
|
||||||
.expect("must succeed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inner.ipv6 = None;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn allocate_net_v4_inner(
|
|
||||||
inner: &mut NetworkStateFields,
|
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
|
||||||
owner_tag: OwnerTag,
|
|
||||||
opt_address: Option<Ipv4Addr>,
|
|
||||||
prefix: u8,
|
|
||||||
) -> MachineRegistryResult<Ipv4Net> {
|
|
||||||
let Some(_network_state_ipv4) = &mut inner.ipv4 else {
|
|
||||||
return Err(MachineRegistryError::NoAllocation);
|
|
||||||
};
|
|
||||||
|
|
||||||
// See if we are requesting a specific address
|
|
||||||
let net = if let Some(address) = opt_address {
|
|
||||||
// Get the net form for this address
|
|
||||||
let net = Ipv4Net::new(address, prefix).expect("must succeed");
|
|
||||||
inner
|
|
||||||
.address_pool
|
|
||||||
.reserve_allocation_v4(net, Some(owner_tag))?;
|
|
||||||
net
|
|
||||||
} else {
|
|
||||||
// Get a random address if available
|
|
||||||
let Some(allocation) = inner.address_pool.allocate_random_v4(
|
|
||||||
machine_registry_inner.srng(),
|
|
||||||
prefix,
|
|
||||||
owner_tag,
|
|
||||||
)?
|
|
||||||
else {
|
|
||||||
return Err(MachineRegistryError::NoAllocation);
|
|
||||||
};
|
|
||||||
allocation
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(net)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn can_allocate_net_v4_inner(
|
|
||||||
inner: &NetworkStateFields,
|
|
||||||
opt_address: Option<Ipv4Addr>,
|
|
||||||
prefix: u8,
|
|
||||||
) -> bool {
|
|
||||||
let Some(_network_state_ipv4) = &inner.ipv4 else {
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
// See if we are requesting a specific address
|
|
||||||
if let Some(address) = opt_address {
|
|
||||||
// Get the net form for this address
|
|
||||||
let net = Ipv4Net::new(address, prefix).expect("must succeed");
|
|
||||||
inner.address_pool.get_overlaps_v4(net).is_empty()
|
|
||||||
} else {
|
|
||||||
// Get a random address if available
|
|
||||||
inner.address_pool.can_allocate_v4(prefix).unwrap_or(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn can_allocate_net_v6_inner(
|
|
||||||
inner: &NetworkStateFields,
|
|
||||||
opt_address: Option<Ipv6Addr>,
|
|
||||||
prefix: u8,
|
|
||||||
) -> bool {
|
|
||||||
let Some(_network_state_ipv6) = &inner.ipv6 else {
|
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -611,96 +641,33 @@ impl NetworkState {
|
|||||||
if let Some(address) = opt_address {
|
if let Some(address) = opt_address {
|
||||||
// Get the net form for this address
|
// Get the net form for this address
|
||||||
let net = Ipv6Net::new(address, prefix).expect("must succeed");
|
let net = Ipv6Net::new(address, prefix).expect("must succeed");
|
||||||
inner.address_pool.get_overlaps_v6(net).is_empty()
|
self.fields.address_pool.get_overlaps_v6(net).is_empty()
|
||||||
} else {
|
} else {
|
||||||
// Get a random address if available
|
// Get a random address if available
|
||||||
inner.address_pool.can_allocate_v6(prefix).unwrap_or(false)
|
self.fields
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn allocate_net_v6_inner(
|
|
||||||
inner: &mut NetworkStateFields,
|
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
|
||||||
owner_tag: OwnerTag,
|
|
||||||
opt_address: Option<Ipv6Addr>,
|
|
||||||
prefix: u8,
|
|
||||||
) -> MachineRegistryResult<Ipv6Net> {
|
|
||||||
let Some(_network_state_ipv6) = &mut inner.ipv6 else {
|
|
||||||
return Err(MachineRegistryError::NoAllocation);
|
|
||||||
};
|
|
||||||
|
|
||||||
// See if we are requesting a specific address
|
|
||||||
let net = if let Some(address) = opt_address {
|
|
||||||
// Get the net form for this address
|
|
||||||
let net = Ipv6Net::new(address, prefix).expect("must succeed");
|
|
||||||
inner
|
|
||||||
.address_pool
|
.address_pool
|
||||||
.reserve_allocation_v6(net, Some(owner_tag))?;
|
.can_allocate_v6(prefix)
|
||||||
net
|
.unwrap_or(false)
|
||||||
} else {
|
}
|
||||||
// Get a random address if available
|
|
||||||
let Some(allocation) = inner.address_pool.allocate_random_v6(
|
|
||||||
machine_registry_inner.srng(),
|
|
||||||
prefix,
|
|
||||||
owner_tag,
|
|
||||||
)?
|
|
||||||
else {
|
|
||||||
return Err(MachineRegistryError::NoAllocation);
|
|
||||||
};
|
|
||||||
allocation
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(net)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn release_subnet_v4_inner(
|
pub fn release_address_v6(
|
||||||
inner: &mut NetworkStateFields,
|
&mut self,
|
||||||
net: Ipv4Net,
|
addr: Ipv6Addr,
|
||||||
) -> MachineRegistryResult<Option<OwnerTag>> {
|
) -> MachineRegistryResult<Option<OwnerTag>> {
|
||||||
inner.address_pool.release_allocation_v4(net)
|
self.release_subnet_v6(Ipv6Net::new(addr, 128).expect("must succeed"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn release_subnet_v6_inner(
|
pub fn release_subnet_v6(&mut self, net: Ipv6Net) -> MachineRegistryResult<Option<OwnerTag>> {
|
||||||
inner: &mut NetworkStateFields,
|
let mut address_pool = self.fields.address_pool.clone();
|
||||||
net: Ipv6Net,
|
let opt_tag = address_pool.release_allocation_v6(net)?;
|
||||||
) -> MachineRegistryResult<Option<OwnerTag>> {
|
|
||||||
inner.address_pool.release_allocation_v6(net)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn release_all_addresses<I: Iterator<Item = IpAddr>>(
|
// Update fields
|
||||||
&self,
|
self.fields = Arc::new(NetworkStateFields {
|
||||||
addrs: I,
|
address_pool,
|
||||||
) -> MachineRegistryResult<()> {
|
..(*self.fields).clone()
|
||||||
let mut ok = true;
|
});
|
||||||
for addr in addrs {
|
Ok(opt_tag)
|
||||||
match addr {
|
|
||||||
IpAddr::V4(ipv4_addr) => {
|
|
||||||
if Self::release_subnet_v4_inner(
|
|
||||||
&mut *inner,
|
|
||||||
Ipv4Net::new(ipv4_addr, 32).expect("must succeed"),
|
|
||||||
)
|
|
||||||
.is_err()
|
|
||||||
{
|
|
||||||
ok = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
IpAddr::V6(ipv6_addr) => {
|
|
||||||
if Self::release_subnet_v6_inner(
|
|
||||||
&mut *inner,
|
|
||||||
Ipv6Net::new(ipv6_addr, 128).expect("must succeed"),
|
|
||||||
)
|
|
||||||
.is_err()
|
|
||||||
{
|
|
||||||
ok = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ok {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(MachineRegistryError::NoAllocation)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct TemplateStateUnlockedInner {
|
struct TemplateStateImmutable {
|
||||||
id: TemplateStateId,
|
id: TemplateStateId,
|
||||||
name: String,
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
struct PerNetworkInfo {
|
struct PerNetworkInfo {
|
||||||
limit_machine_count: Option<usize>,
|
limit_machine_count: Option<usize>,
|
||||||
machines: HashSet<MachineStateId>,
|
machines: imbl::HashSet<MachineStateId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -18,20 +18,20 @@ enum BlueprintAvailability {
|
|||||||
Generate(BlueprintState),
|
Generate(BlueprintState),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
struct TemplateStateInner {
|
struct TemplateStateFields {
|
||||||
limit_machine_count: Option<usize>,
|
limit_machine_count: Option<usize>,
|
||||||
limit_machines_per_network: Option<WeightedList<usize>>,
|
limit_machines_per_network: Option<WeightedList<usize>>,
|
||||||
locations_list: Option<MachineLocationsList>,
|
locations_list: Option<MachineLocationsList>,
|
||||||
machines: HashSet<MachineStateId>,
|
machines: imbl::HashSet<MachineStateId>,
|
||||||
machines_per_network: HashMap<NetworkStateId, PerNetworkInfo>,
|
machines_per_network: imbl::HashMap<NetworkStateId, PerNetworkInfo>,
|
||||||
disable_capabilities: Vec<String>,
|
disable_capabilities: imbl::Vector<Arc<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct TemplateState {
|
pub struct TemplateState {
|
||||||
unlocked_inner: Arc<TemplateStateUnlockedInner>,
|
immutable: Arc<TemplateStateImmutable>,
|
||||||
inner: Arc<Mutex<TemplateStateInner>>,
|
fields: Arc<TemplateStateFields>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type TemplateStateId = StateId<TemplateState>;
|
pub type TemplateStateId = StateId<TemplateState>;
|
||||||
@ -39,61 +39,85 @@ pub type TemplateStateId = StateId<TemplateState>;
|
|||||||
impl TemplateState {
|
impl TemplateState {
|
||||||
pub fn new(id: TemplateStateId, name: String) -> Self {
|
pub fn new(id: TemplateStateId, name: String) -> Self {
|
||||||
Self {
|
Self {
|
||||||
unlocked_inner: Arc::new(TemplateStateUnlockedInner { id, name }),
|
immutable: Arc::new(TemplateStateImmutable { id, name }),
|
||||||
inner: Arc::new(Mutex::new(TemplateStateInner {
|
fields: Arc::new(TemplateStateFields {
|
||||||
limit_machine_count: None,
|
limit_machine_count: None,
|
||||||
limit_machines_per_network: None,
|
limit_machines_per_network: None,
|
||||||
locations_list: None,
|
locations_list: None,
|
||||||
machines: HashSet::new(),
|
machines: imbl::HashSet::new(),
|
||||||
machines_per_network: HashMap::new(),
|
machines_per_network: imbl::HashMap::new(),
|
||||||
disable_capabilities: Vec::new(),
|
disable_capabilities: imbl::Vector::new(),
|
||||||
})),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_disable_capabilities(&self, disable_capabilities: Vec<String>) {
|
pub fn set_disable_capabilities(&mut self, disable_capabilities: Vec<String>) {
|
||||||
let mut inner = self.inner.lock();
|
let disable_capabilities =
|
||||||
inner.disable_capabilities = disable_capabilities;
|
imbl::Vector::from_iter(disable_capabilities.into_iter().map(Arc::new));
|
||||||
|
// Update fields
|
||||||
|
self.fields = Arc::new(TemplateStateFields {
|
||||||
|
disable_capabilities,
|
||||||
|
..(*self.fields).clone()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_networks_list(&self, networks: WeightedList<NetworkStateId>) {
|
pub fn set_networks_list(&mut self, networks: WeightedList<NetworkStateId>) {
|
||||||
let mut inner = self.inner.lock();
|
let locations_list = Some(MachineLocationsList::Networks { networks });
|
||||||
inner.locations_list = Some(MachineLocationsList::Networks { networks })
|
|
||||||
|
// Update fields
|
||||||
|
self.fields = Arc::new(TemplateStateFields {
|
||||||
|
locations_list,
|
||||||
|
..(*self.fields).clone()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_blueprints_list(&self, blueprints: WeightedList<BlueprintStateId>) {
|
pub fn set_blueprints_list(mut self, blueprints: WeightedList<BlueprintStateId>) {
|
||||||
let mut inner = self.inner.lock();
|
let locations_list = Some(MachineLocationsList::Blueprints { blueprints });
|
||||||
inner.locations_list = Some(MachineLocationsList::Blueprints { blueprints })
|
|
||||||
|
// Update fields
|
||||||
|
self.fields = Arc::new(TemplateStateFields {
|
||||||
|
locations_list,
|
||||||
|
..(*self.fields).clone()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear_locations_list(&self) {
|
pub fn clear_locations_list(&mut self) {
|
||||||
let mut inner = self.inner.lock();
|
let locations_list = None;
|
||||||
inner.locations_list = None;
|
|
||||||
|
// Update fields
|
||||||
|
self.fields = Arc::new(TemplateStateFields {
|
||||||
|
locations_list,
|
||||||
|
..(*self.fields).clone()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_limit_machine_count(&self, limit_machine_count: Option<usize>) {
|
pub fn set_limit_machine_count(&mut self, limit_machine_count: Option<usize>) {
|
||||||
let mut inner = self.inner.lock();
|
// Update fields
|
||||||
inner.limit_machine_count = limit_machine_count;
|
self.fields = Arc::new(TemplateStateFields {
|
||||||
|
limit_machine_count,
|
||||||
|
..(*self.fields).clone()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_limit_machines_per_network(
|
pub fn set_limit_machines_per_network(
|
||||||
&self,
|
&mut self,
|
||||||
limit_machines_per_network: Option<WeightedList<usize>>,
|
limit_machines_per_network: Option<WeightedList<usize>>,
|
||||||
) {
|
) {
|
||||||
let mut inner = self.inner.lock();
|
// Update fields
|
||||||
inner.limit_machines_per_network = limit_machines_per_network;
|
self.fields = Arc::new(TemplateStateFields {
|
||||||
|
limit_machines_per_network,
|
||||||
|
..(*self.fields).clone()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_network_available_inner(
|
fn is_network_available(&self, network_state: NetworkState) -> MachineRegistryResult<bool> {
|
||||||
inner: &TemplateStateInner,
|
|
||||||
network_state: NetworkState,
|
|
||||||
) -> MachineRegistryResult<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()? {
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the per network info
|
// Get the per network info
|
||||||
let Some(pni) = inner.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
|
||||||
// by definition available
|
// by definition available
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
@ -110,8 +134,8 @@ impl TemplateState {
|
|||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_blueprint_available_inner(
|
fn is_blueprint_available(
|
||||||
inner: &TemplateStateInner,
|
&self,
|
||||||
machine_registry_inner: &MachineRegistryInner,
|
machine_registry_inner: &MachineRegistryInner,
|
||||||
blueprint_state: BlueprintState,
|
blueprint_state: BlueprintState,
|
||||||
) -> MachineRegistryResult<Option<BlueprintAvailability>> {
|
) -> MachineRegistryResult<Option<BlueprintAvailability>> {
|
||||||
@ -120,7 +144,7 @@ impl TemplateState {
|
|||||||
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 = machine_registry_inner.network_states().get_state(id)?;
|
||||||
if Self::is_network_available_inner(inner, network_state.clone())? {
|
if self.is_network_available(network_state.clone())? {
|
||||||
// We found one
|
// We found one
|
||||||
return Ok(Some(network_state));
|
return Ok(Some(network_state));
|
||||||
}
|
}
|
||||||
@ -145,16 +169,14 @@ impl TemplateState {
|
|||||||
&self,
|
&self,
|
||||||
machine_registry_inner: &MachineRegistryInner,
|
machine_registry_inner: &MachineRegistryInner,
|
||||||
) -> MachineRegistryResult<bool> {
|
) -> MachineRegistryResult<bool> {
|
||||||
let inner = self.inner.lock();
|
|
||||||
|
|
||||||
// See if we have reached our machine limit
|
// See if we have reached our machine limit
|
||||||
if let Some(limit_machine_count) = inner.limit_machine_count {
|
if let Some(limit_machine_count) = self.fields.limit_machine_count {
|
||||||
if inner.machines.len() >= limit_machine_count {
|
if self.fields.machines.len() >= limit_machine_count {
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(locations_list) = inner.locations_list.as_ref() else {
|
let Some(locations_list) = self.fields.locations_list.as_ref() else {
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -165,7 +187,7 @@ impl TemplateState {
|
|||||||
.try_filter(|id| {
|
.try_filter(|id| {
|
||||||
let network_state =
|
let network_state =
|
||||||
machine_registry_inner.network_states().get_state(*id)?;
|
machine_registry_inner.network_states().get_state(*id)?;
|
||||||
Self::is_network_available_inner(&*inner, network_state)
|
self.is_network_available(network_state)
|
||||||
})?
|
})?
|
||||||
.is_none()
|
.is_none()
|
||||||
{
|
{
|
||||||
@ -179,11 +201,7 @@ impl TemplateState {
|
|||||||
let blueprint_state =
|
let blueprint_state =
|
||||||
machine_registry_inner.blueprint_states().get_state(*id)?;
|
machine_registry_inner.blueprint_states().get_state(*id)?;
|
||||||
|
|
||||||
Self::is_blueprint_available_inner(
|
self.is_blueprint_available(machine_registry_inner, blueprint_state)
|
||||||
&*inner,
|
|
||||||
machine_registry_inner,
|
|
||||||
blueprint_state,
|
|
||||||
)
|
|
||||||
.map(|x| x.is_some())
|
.map(|x| x.is_some())
|
||||||
})?
|
})?
|
||||||
.is_none()
|
.is_none()
|
||||||
@ -200,17 +218,15 @@ impl TemplateState {
|
|||||||
&mut self,
|
&mut self,
|
||||||
machine_registry_inner: &mut MachineRegistryInner,
|
machine_registry_inner: &mut MachineRegistryInner,
|
||||||
) -> MachineRegistryResult<MachineStateId> {
|
) -> MachineRegistryResult<MachineStateId> {
|
||||||
let mut inner = self.inner.lock();
|
|
||||||
|
|
||||||
// See if we have reached our machine limit
|
// See if we have reached our machine limit
|
||||||
if let Some(limit_machine_count) = inner.limit_machine_count {
|
if let Some(limit_machine_count) = self.fields.limit_machine_count {
|
||||||
if inner.machines.len() < limit_machine_count.try_into().unwrap_or(usize::MAX) {
|
if self.fields.machines.len() < limit_machine_count.try_into().unwrap_or(usize::MAX) {
|
||||||
return Err(MachineRegistryError::TemplateComplete);
|
return Err(MachineRegistryError::TemplateComplete);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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) = inner.locations_list.as_ref() else {
|
let Some(locations_list) = self.fields.locations_list.as_ref() else {
|
||||||
return Err(MachineRegistryError::TemplateComplete);
|
return Err(MachineRegistryError::TemplateComplete);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -220,7 +236,7 @@ impl TemplateState {
|
|||||||
// 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 = machine_registry_inner.network_states().get_state(*id)?;
|
||||||
if Self::is_network_available_inner(&*inner, network_state.clone())? {
|
if self.is_network_available(network_state.clone())? {
|
||||||
Ok(Some(network_state))
|
Ok(Some(network_state))
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
@ -244,11 +260,7 @@ impl TemplateState {
|
|||||||
let blueprint_state =
|
let blueprint_state =
|
||||||
machine_registry_inner.blueprint_states().get_state(*id)?;
|
machine_registry_inner.blueprint_states().get_state(*id)?;
|
||||||
|
|
||||||
Self::is_blueprint_available_inner(
|
self.is_blueprint_available(machine_registry_inner, blueprint_state)
|
||||||
&*inner,
|
|
||||||
machine_registry_inner,
|
|
||||||
blueprint_state,
|
|
||||||
)
|
|
||||||
})?
|
})?
|
||||||
else {
|
else {
|
||||||
return Err(MachineRegistryError::BlueprintComplete);
|
return Err(MachineRegistryError::BlueprintComplete);
|
||||||
@ -270,6 +282,8 @@ impl TemplateState {
|
|||||||
// Allocate a machine id
|
// Allocate a machine id
|
||||||
let machine_state_id = machine_registry_inner.machine_states_mut().allocate_id();
|
let machine_state_id = machine_registry_inner.machine_states_mut().allocate_id();
|
||||||
|
|
||||||
|
xxx continue here
|
||||||
|
|
||||||
// Create an anonymous machine state
|
// Create an anonymous machine state
|
||||||
let machine_state = MachineState::new(machine_state_id, None);
|
let machine_state = MachineState::new(machine_state_id, None);
|
||||||
|
|
||||||
@ -309,8 +323,12 @@ impl TemplateState {
|
|||||||
.machines_per_network
|
.machines_per_network
|
||||||
.entry(network_state.id())
|
.entry(network_state.id())
|
||||||
.or_insert_with(|| {
|
.or_insert_with(|| {
|
||||||
let limit_machine_count = limit_machines_per_network
|
let limit_machine_count = limit_machines_per_network.map(|wl| {
|
||||||
.map(|wl| machine_registry_inner.srng().weighted_choice_ref(&wl).clone());
|
machine_registry_inner
|
||||||
|
.srng()
|
||||||
|
.weighted_choice_ref(&wl)
|
||||||
|
.clone()
|
||||||
|
});
|
||||||
PerNetworkInfo {
|
PerNetworkInfo {
|
||||||
limit_machine_count,
|
limit_machine_count,
|
||||||
machines: HashSet::new(),
|
machines: HashSet::new(),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user