mirror of
https://git.proxmox.com/git/proxmox-perl-rs
synced 2025-08-14 00:10:21 +00:00
pve-rs: add resource scheduling module
backed by the proxmox-resource-scheduling crate. Initially to be used by the HA manager to allow it basing its decision where to start a new or recovered service on static usage information rather than just counting. Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
This commit is contained in:
parent
9488180f9e
commit
887c0e2074
1
Makefile
1
Makefile
@ -56,6 +56,7 @@ gen:
|
|||||||
perl ./scripts/genpackage.pl PVE \
|
perl ./scripts/genpackage.pl PVE \
|
||||||
PVE::RS::APT::Repositories \
|
PVE::RS::APT::Repositories \
|
||||||
PVE::RS::OpenId \
|
PVE::RS::OpenId \
|
||||||
|
PVE::RS::ResourceScheduling::Static \
|
||||||
PVE::RS::TFA
|
PVE::RS::TFA
|
||||||
perl ./scripts/genpackage.pl PMG \
|
perl ./scripts/genpackage.pl PMG \
|
||||||
PMG::RS::APT::Repositories \
|
PMG::RS::APT::Repositories \
|
||||||
|
@ -33,6 +33,7 @@ perlmod = { version = "0.13", features = [ "exporter" ] }
|
|||||||
proxmox-apt = "0.9"
|
proxmox-apt = "0.9"
|
||||||
proxmox-http = { version = "0.7", features = ["client-sync", "client-trait"] }
|
proxmox-http = { version = "0.7", features = ["client-sync", "client-trait"] }
|
||||||
proxmox-openid = "0.9.5"
|
proxmox-openid = "0.9.5"
|
||||||
|
proxmox-resource-scheduling = "0.1"
|
||||||
proxmox-subscription = "0.3"
|
proxmox-subscription = "0.3"
|
||||||
proxmox-sys = "0.4"
|
proxmox-sys = "0.4"
|
||||||
proxmox-tfa = { version = "2.1", features = ["api"] }
|
proxmox-tfa = { version = "2.1", features = ["api"] }
|
||||||
|
@ -5,4 +5,5 @@ pub mod common;
|
|||||||
|
|
||||||
pub mod apt;
|
pub mod apt;
|
||||||
pub mod openid;
|
pub mod openid;
|
||||||
|
pub mod resource_scheduling;
|
||||||
pub mod tfa;
|
pub mod tfa;
|
||||||
|
1
pve-rs/src/resource_scheduling/mod.rs
Normal file
1
pve-rs/src/resource_scheduling/mod.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub mod r#static;
|
116
pve-rs/src/resource_scheduling/static.rs
Normal file
116
pve-rs/src/resource_scheduling/static.rs
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
#[perlmod::package(name = "PVE::RS::ResourceScheduling::Static", lib = "pve_rs")]
|
||||||
|
mod export {
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
use anyhow::{bail, Error};
|
||||||
|
|
||||||
|
use perlmod::Value;
|
||||||
|
use proxmox_resource_scheduling::pve_static::{StaticNodeUsage, StaticServiceUsage};
|
||||||
|
|
||||||
|
perlmod::declare_magic!(Box<Scheduler> : &Scheduler as "PVE::RS::ResourceScheduling::Static");
|
||||||
|
|
||||||
|
struct Usage {
|
||||||
|
nodes: HashMap<String, StaticNodeUsage>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Scheduler {
|
||||||
|
inner: Mutex<Usage>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[export(raw_return)]
|
||||||
|
fn new(#[raw] class: Value) -> Result<Value, Error> {
|
||||||
|
let inner = Usage {
|
||||||
|
nodes: HashMap::new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(perlmod::instantiate_magic!(
|
||||||
|
&class, MAGIC => Box::new(Scheduler { inner: Mutex::new(inner) })
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[export]
|
||||||
|
fn add_node(
|
||||||
|
#[try_from_ref] this: &Scheduler,
|
||||||
|
nodename: String,
|
||||||
|
maxcpu: usize,
|
||||||
|
maxmem: usize,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let mut usage = this.inner.lock().unwrap();
|
||||||
|
|
||||||
|
if usage.nodes.contains_key(&nodename) {
|
||||||
|
bail!("node {} already added", nodename);
|
||||||
|
}
|
||||||
|
|
||||||
|
let node = StaticNodeUsage {
|
||||||
|
name: nodename.clone(),
|
||||||
|
cpu: 0.0,
|
||||||
|
maxcpu,
|
||||||
|
mem: 0,
|
||||||
|
maxmem,
|
||||||
|
};
|
||||||
|
|
||||||
|
usage.nodes.insert(nodename, node);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[export]
|
||||||
|
fn remove_node(#[try_from_ref] this: &Scheduler, nodename: &str) {
|
||||||
|
let mut usage = this.inner.lock().unwrap();
|
||||||
|
|
||||||
|
usage.nodes.remove(nodename);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[export]
|
||||||
|
fn list_nodes(#[try_from_ref] this: &Scheduler) -> Vec<String> {
|
||||||
|
let usage = this.inner.lock().unwrap();
|
||||||
|
|
||||||
|
usage
|
||||||
|
.nodes
|
||||||
|
.keys()
|
||||||
|
.map(|nodename| nodename.to_string())
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[export]
|
||||||
|
fn contains_node(#[try_from_ref] this: &Scheduler, nodename: &str) -> bool {
|
||||||
|
let usage = this.inner.lock().unwrap();
|
||||||
|
|
||||||
|
usage.nodes.contains_key(nodename)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add usage of `service` to the node's usage.
|
||||||
|
#[export]
|
||||||
|
fn add_service_usage_to_node(
|
||||||
|
#[try_from_ref] this: &Scheduler,
|
||||||
|
nodename: &str,
|
||||||
|
service: StaticServiceUsage,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let mut usage = this.inner.lock().unwrap();
|
||||||
|
|
||||||
|
match usage.nodes.get_mut(nodename) {
|
||||||
|
Some(node) => {
|
||||||
|
node.add_service_usage(&service);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
None => bail!("node '{}' not present in usage hashmap", nodename),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Scores all previously added nodes for starting a `service` on. Scoring is done according to
|
||||||
|
/// the static memory and CPU usages of the nodes as if the service would already be running on
|
||||||
|
/// each.
|
||||||
|
///
|
||||||
|
/// Returns a vector of (nodename, score) pairs. Scores are between 0.0 and 1.0 and a higher
|
||||||
|
/// score is better.
|
||||||
|
#[export]
|
||||||
|
fn score_nodes_to_start_service(
|
||||||
|
#[try_from_ref] this: &Scheduler,
|
||||||
|
service: StaticServiceUsage,
|
||||||
|
) -> Result<Vec<(String, f64)>, Error> {
|
||||||
|
let usage = this.inner.lock().unwrap();
|
||||||
|
let nodes = usage.nodes.values().collect::<Vec<&StaticNodeUsage>>();
|
||||||
|
|
||||||
|
proxmox_resource_scheduling::pve_static::score_nodes_to_start_service(&nodes, &service)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user