All checks were successful
Run Check Script / check (pull_request) Successful in -6s
420 lines
14 KiB
Rust
420 lines
14 KiB
Rust
use async_trait::async_trait;
|
|
use harmony_macros::ip;
|
|
use harmony_types::net::MacAddress;
|
|
use log::info;
|
|
|
|
use crate::executors::ExecutorError;
|
|
use crate::interpret::InterpretError;
|
|
use crate::interpret::Outcome;
|
|
|
|
use super::DHCPStaticEntry;
|
|
use super::DhcpServer;
|
|
use super::DnsRecord;
|
|
use super::DnsRecordType;
|
|
use super::DnsServer;
|
|
use super::Firewall;
|
|
use super::HttpServer;
|
|
use super::IpAddress;
|
|
use super::K8sclient;
|
|
use super::LoadBalancer;
|
|
use super::LoadBalancerService;
|
|
use super::LogicalHost;
|
|
use super::Router;
|
|
use super::TftpServer;
|
|
|
|
use super::Topology;
|
|
use super::Url;
|
|
use super::k8s::K8sClient;
|
|
use std::sync::Arc;
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct HAClusterTopology {
|
|
pub domain_name: String,
|
|
pub router: Arc<dyn Router>,
|
|
pub load_balancer: Arc<dyn LoadBalancer>,
|
|
pub firewall: Arc<dyn Firewall>,
|
|
pub dhcp_server: Arc<dyn DhcpServer>,
|
|
pub tftp_server: Arc<dyn TftpServer>,
|
|
pub http_server: Arc<dyn HttpServer>,
|
|
pub dns_server: Arc<dyn DnsServer>,
|
|
pub bootstrap_host: LogicalHost,
|
|
pub control_plane: Vec<LogicalHost>,
|
|
pub workers: Vec<LogicalHost>,
|
|
pub switch: Vec<LogicalHost>,
|
|
}
|
|
|
|
#[async_trait]
|
|
impl Topology for HAClusterTopology {
|
|
fn name(&self) -> &str {
|
|
"HAClusterTopology"
|
|
}
|
|
async fn ensure_ready(&self) -> Result<Outcome, InterpretError> {
|
|
todo!(
|
|
"ensure_ready, not entirely sure what it should do here, probably something like verify that the hosts are reachable and all services are up and ready."
|
|
)
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl K8sclient for HAClusterTopology {
|
|
async fn k8s_client(&self) -> Result<Arc<K8sClient>, String> {
|
|
Ok(Arc::new(
|
|
K8sClient::try_default().await.map_err(|e| e.to_string())?,
|
|
))
|
|
}
|
|
}
|
|
|
|
impl HAClusterTopology {
|
|
pub fn autoload() -> Self {
|
|
let dummy_infra = Arc::new(DummyInfra {});
|
|
let dummy_host = LogicalHost {
|
|
ip: ip!("0.0.0.0"),
|
|
name: "dummyhost".to_string(),
|
|
};
|
|
|
|
Self {
|
|
domain_name: "DummyTopology".to_string(),
|
|
router: dummy_infra.clone(),
|
|
load_balancer: dummy_infra.clone(),
|
|
firewall: dummy_infra.clone(),
|
|
dhcp_server: dummy_infra.clone(),
|
|
tftp_server: dummy_infra.clone(),
|
|
http_server: dummy_infra.clone(),
|
|
dns_server: dummy_infra.clone(),
|
|
bootstrap_host: dummy_host,
|
|
control_plane: vec![],
|
|
workers: vec![],
|
|
switch: vec![],
|
|
}
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl DnsServer for HAClusterTopology {
|
|
async fn register_dhcp_leases(&self, register: bool) -> Result<(), ExecutorError> {
|
|
self.dns_server.register_dhcp_leases(register).await
|
|
}
|
|
async fn register_hosts(&self, hosts: Vec<DnsRecord>) -> Result<(), ExecutorError> {
|
|
self.dns_server.register_hosts(hosts).await
|
|
}
|
|
fn remove_record(&self, name: &str, record_type: DnsRecordType) -> Result<(), ExecutorError> {
|
|
self.dns_server.remove_record(name, record_type)
|
|
}
|
|
async fn list_records(&self) -> Vec<DnsRecord> {
|
|
self.dns_server.list_records().await
|
|
}
|
|
fn get_ip(&self) -> IpAddress {
|
|
self.dns_server.get_ip()
|
|
}
|
|
fn get_host(&self) -> LogicalHost {
|
|
self.dns_server.get_host()
|
|
}
|
|
async fn commit_config(&self) -> Result<(), ExecutorError> {
|
|
self.dns_server.commit_config().await
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl LoadBalancer for HAClusterTopology {
|
|
fn get_ip(&self) -> IpAddress {
|
|
self.load_balancer.get_ip()
|
|
}
|
|
fn get_host(&self) -> LogicalHost {
|
|
self.load_balancer.get_host()
|
|
}
|
|
async fn add_service(&self, service: &LoadBalancerService) -> Result<(), ExecutorError> {
|
|
self.load_balancer.add_service(service).await
|
|
}
|
|
async fn remove_service(&self, service: &LoadBalancerService) -> Result<(), ExecutorError> {
|
|
self.load_balancer.remove_service(service).await
|
|
}
|
|
async fn list_services(&self) -> Vec<LoadBalancerService> {
|
|
self.load_balancer.list_services().await
|
|
}
|
|
async fn ensure_initialized(&self) -> Result<(), ExecutorError> {
|
|
self.load_balancer.ensure_initialized().await
|
|
}
|
|
async fn commit_config(&self) -> Result<(), ExecutorError> {
|
|
self.load_balancer.commit_config().await
|
|
}
|
|
async fn reload_restart(&self) -> Result<(), ExecutorError> {
|
|
self.load_balancer.reload_restart().await
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl DhcpServer for HAClusterTopology {
|
|
async fn add_static_mapping(&self, entry: &DHCPStaticEntry) -> Result<(), ExecutorError> {
|
|
self.dhcp_server.add_static_mapping(entry).await
|
|
}
|
|
async fn remove_static_mapping(&self, mac: &MacAddress) -> Result<(), ExecutorError> {
|
|
self.dhcp_server.remove_static_mapping(mac).await
|
|
}
|
|
async fn list_static_mappings(&self) -> Vec<(MacAddress, IpAddress)> {
|
|
self.dhcp_server.list_static_mappings().await
|
|
}
|
|
async fn set_next_server(&self, ip: IpAddress) -> Result<(), ExecutorError> {
|
|
self.dhcp_server.set_next_server(ip).await
|
|
}
|
|
async fn set_boot_filename(&self, boot_filename: &str) -> Result<(), ExecutorError> {
|
|
self.dhcp_server.set_boot_filename(boot_filename).await
|
|
}
|
|
fn get_ip(&self) -> IpAddress {
|
|
self.dhcp_server.get_ip()
|
|
}
|
|
fn get_host(&self) -> LogicalHost {
|
|
self.dhcp_server.get_host()
|
|
}
|
|
async fn commit_config(&self) -> Result<(), ExecutorError> {
|
|
self.dhcp_server.commit_config().await
|
|
}
|
|
|
|
async fn set_filename(&self, filename: &str) -> Result<(), ExecutorError> {
|
|
self.dhcp_server.set_filename(filename).await
|
|
}
|
|
async fn set_filename64(&self, filename64: &str) -> Result<(), ExecutorError> {
|
|
self.dhcp_server.set_filename64(filename64).await
|
|
}
|
|
async fn set_filenameipxe(&self, filenameipxe: &str) -> Result<(), ExecutorError> {
|
|
self.dhcp_server.set_filenameipxe(filenameipxe).await
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl TftpServer for HAClusterTopology {
|
|
async fn serve_files(&self, url: &Url) -> Result<(), ExecutorError> {
|
|
self.tftp_server.serve_files(url).await
|
|
}
|
|
fn get_ip(&self) -> IpAddress {
|
|
self.tftp_server.get_ip()
|
|
}
|
|
|
|
async fn set_ip(&self, ip: IpAddress) -> Result<(), ExecutorError> {
|
|
self.tftp_server.set_ip(ip).await
|
|
}
|
|
async fn ensure_initialized(&self) -> Result<(), ExecutorError> {
|
|
self.tftp_server.ensure_initialized().await
|
|
}
|
|
async fn commit_config(&self) -> Result<(), ExecutorError> {
|
|
self.tftp_server.commit_config().await
|
|
}
|
|
async fn reload_restart(&self) -> Result<(), ExecutorError> {
|
|
self.tftp_server.reload_restart().await
|
|
}
|
|
}
|
|
|
|
impl Router for HAClusterTopology {
|
|
fn get_gateway(&self) -> super::IpAddress {
|
|
self.router.get_gateway()
|
|
}
|
|
fn get_cidr(&self) -> cidr::Ipv4Cidr {
|
|
self.router.get_cidr()
|
|
}
|
|
fn get_host(&self) -> LogicalHost {
|
|
self.router.get_host()
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl HttpServer for HAClusterTopology {
|
|
async fn serve_files(&self, url: &Url) -> Result<(), ExecutorError> {
|
|
self.http_server.serve_files(url).await
|
|
}
|
|
|
|
fn get_ip(&self) -> IpAddress {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
async fn ensure_initialized(&self) -> Result<(), ExecutorError> {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
async fn commit_config(&self) -> Result<(), ExecutorError> {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
async fn reload_restart(&self) -> Result<(), ExecutorError> {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct DummyInfra;
|
|
|
|
#[async_trait]
|
|
impl Topology for DummyInfra {
|
|
fn name(&self) -> &str {
|
|
todo!()
|
|
}
|
|
|
|
async fn ensure_ready(&self) -> Result<Outcome, InterpretError> {
|
|
let dummy_msg = "This is a dummy infrastructure that does nothing";
|
|
info!("{dummy_msg}");
|
|
Ok(Outcome::success(dummy_msg.to_string()))
|
|
}
|
|
}
|
|
|
|
const UNIMPLEMENTED_DUMMY_INFRA: &str = "This is a dummy infrastructure, no operation is supported";
|
|
|
|
impl Router for DummyInfra {
|
|
fn get_gateway(&self) -> super::IpAddress {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
fn get_cidr(&self) -> cidr::Ipv4Cidr {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
fn get_host(&self) -> LogicalHost {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
}
|
|
|
|
impl Firewall for DummyInfra {
|
|
fn add_rule(
|
|
&mut self,
|
|
_rule: super::FirewallRule,
|
|
) -> Result<(), crate::executors::ExecutorError> {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
fn remove_rule(&mut self, _rule_id: &str) -> Result<(), crate::executors::ExecutorError> {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
fn list_rules(&self) -> Vec<super::FirewallRule> {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
fn get_ip(&self) -> super::IpAddress {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
fn get_host(&self) -> LogicalHost {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl DhcpServer for DummyInfra {
|
|
async fn add_static_mapping(&self, _entry: &DHCPStaticEntry) -> Result<(), ExecutorError> {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
async fn remove_static_mapping(&self, _mac: &MacAddress) -> Result<(), ExecutorError> {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
async fn list_static_mappings(&self) -> Vec<(MacAddress, IpAddress)> {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
async fn set_next_server(&self, _ip: IpAddress) -> Result<(), ExecutorError> {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
async fn set_boot_filename(&self, _boot_filename: &str) -> Result<(), ExecutorError> {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
async fn set_filename(&self, _filename: &str) -> Result<(), ExecutorError> {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
async fn set_filename64(&self, _filename: &str) -> Result<(), ExecutorError> {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
async fn set_filenameipxe(&self, _filenameipxe: &str) -> Result<(), ExecutorError> {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
fn get_ip(&self) -> IpAddress {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
fn get_host(&self) -> LogicalHost {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
async fn commit_config(&self) -> Result<(), ExecutorError> {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl LoadBalancer for DummyInfra {
|
|
fn get_ip(&self) -> IpAddress {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
fn get_host(&self) -> LogicalHost {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
async fn add_service(&self, _service: &LoadBalancerService) -> Result<(), ExecutorError> {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
async fn remove_service(&self, _service: &LoadBalancerService) -> Result<(), ExecutorError> {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
async fn list_services(&self) -> Vec<LoadBalancerService> {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
async fn ensure_initialized(&self) -> Result<(), ExecutorError> {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
async fn commit_config(&self) -> Result<(), ExecutorError> {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
async fn reload_restart(&self) -> Result<(), ExecutorError> {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl TftpServer for DummyInfra {
|
|
async fn serve_files(&self, _url: &Url) -> Result<(), ExecutorError> {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
fn get_ip(&self) -> IpAddress {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
|
|
async fn set_ip(&self, _ip: IpAddress) -> Result<(), ExecutorError> {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
async fn ensure_initialized(&self) -> Result<(), ExecutorError> {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
async fn commit_config(&self) -> Result<(), ExecutorError> {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
async fn reload_restart(&self) -> Result<(), ExecutorError> {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl HttpServer for DummyInfra {
|
|
async fn serve_files(&self, _url: &Url) -> Result<(), ExecutorError> {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
fn get_ip(&self) -> IpAddress {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
async fn ensure_initialized(&self) -> Result<(), ExecutorError> {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
async fn commit_config(&self) -> Result<(), ExecutorError> {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
async fn reload_restart(&self) -> Result<(), ExecutorError> {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl DnsServer for DummyInfra {
|
|
async fn register_dhcp_leases(&self, _register: bool) -> Result<(), ExecutorError> {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
async fn register_hosts(&self, _hosts: Vec<DnsRecord>) -> Result<(), ExecutorError> {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
fn remove_record(&self, _name: &str, _record_type: DnsRecordType) -> Result<(), ExecutorError> {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
async fn list_records(&self) -> Vec<DnsRecord> {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
fn get_ip(&self) -> IpAddress {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
fn get_host(&self) -> LogicalHost {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
async fn commit_config(&self) -> Result<(), ExecutorError> {
|
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
}
|
|
}
|