Skip to content

Commit

Permalink
chore: add start and stop commands
Browse files Browse the repository at this point in the history
Add commands for start and stop together
with their logic for the netgen CLI.

Signed-off-by: Paul Wekesa <paul1tw1@gmail.com>
  • Loading branch information
Paul-weqe committed Jan 3, 2025
1 parent 4096ad2 commit a98f997
Show file tree
Hide file tree
Showing 8 changed files with 305 additions and 50 deletions.
129 changes: 129 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,5 @@ enum-as-inner = "0.6.1"
ipnetwork = "0.20.0"
rand = "0.8.5"
clap = {version="4.5.23", features = ["default", "cargo"]}
futures-util = "0.3.31"
sysinfo = "0.33.1"
111 changes: 85 additions & 26 deletions src/bin/netgen.rs
Original file line number Diff line number Diff line change
@@ -1,39 +1,106 @@
#![feature(let_chains)]
use netgen::plugins::Config;
use netgen::topology::Topology;
use netgen::PLUGIN_PIDS_FILE;
use netgen::{error::Error, Result};

use std::fs::File;
use std::fs::OpenOptions;
use std::io::BufRead;

use clap::{command, Arg};
use clap::{command, Arg, ArgMatches};
use sysinfo::{Pid, System};

#[tokio::main]
async fn main() -> Result<()> {
let matches = command!("netgen")
.arg(
Arg::new("Config File")
.short('c')
.long("config")
.value_name("yaml-file")
.help("the file with plugin configs"),
let app_match = command!("netgen")
.subcommand(
command!("start")
.args(config_args())
.about("starts the netgen setup"),
)
.arg(
Arg::new("Topo File")
.short('t')
.long("topo")
.value_name("yaml-file")
.help("file with the topology"),
.subcommand(
command!("stop")
.args(config_args())
.about("stops the running netgen setup"),
)
.get_matches();
let config = match matches.get_one::<String>("Config File") {

match app_match.subcommand() {
Some(("start", start_args)) => {
let mut topology = parse_config_args(start_args)?;

// If the file exists, then the topology is currently running
if File::open(PLUGIN_PIDS_FILE).is_ok() {
return Err(Error::GeneralError(String::from("topology is currently running. Consider running 'netgen stop -t my-topo.yml' before starting again")));
}

File::create(PLUGIN_PIDS_FILE).unwrap();

// "powers on" all the devices and sets up all the required links
topology.power_on().await?;

// Runs the plugins in the routers.
// and initiates their startup-config (if present)
topology.run().await?;
}
Some(("stop", stop_args)) => {
let mut topology = parse_config_args(stop_args)?;

// Turns off all the nodes
// as a result also deletes any dangling veth link
topology.power_off().await;

// Kills all the running plugin PIDs
if let Ok(file) = OpenOptions::new().read(true).open(PLUGIN_PIDS_FILE) {
let reader = std::io::BufReader::new(file);
let system = System::new_all();

for line in reader.lines() {
if let Ok(line) = line
&& let Ok(pid) = line.parse::<u32>()
&& let Some(process) = system.process(Pid::from_u32(pid))
{
process.kill();
}
}
}

// Delete the PID file.
let _ = std::fs::remove_file(PLUGIN_PIDS_FILE);
}
_ => {
// Probably "help"
}
}
Ok(())
}

fn config_args() -> Vec<Arg> {
vec![
Arg::new("Config File")
.short('c')
.long("config")
.value_name("yaml-file")
.help("the file with plugin configs"),
Arg::new("Topo File")
.short('t')
.long("topo")
.value_name("yaml-file")
.help("file with the topology"),
]
}

fn parse_config_args(config_args: &ArgMatches) -> Result<Topology> {
let config = match config_args.get_one::<String>("Config File") {
Some(config_file) => {
let mut config_file = File::open(config_file).unwrap();
Config::from_yaml_file(Some(&mut config_file))?
}
None => Config::from_yaml_file(None)?,
};

let topo_file = match matches.get_one::<String>("Topo File") {
let topo_file = match config_args.get_one::<String>("Topo File") {
Some(topo_file) => topo_file,
None => {
return Err(Error::GeneralError(String::from(
Expand All @@ -43,14 +110,6 @@ async fn main() -> Result<()> {
};

let mut topo_file = File::open(topo_file).unwrap();
let mut topology = Topology::from_yaml_file(&mut topo_file, config).unwrap();

// "powers on" all the devices and sets up all the required links
topology.power_on().await?;

// runs the plugins in the routers.
// and initiates their startup-config (if present)
topology.run().await?;

Ok(())
let topology = Topology::from_yaml_file(&mut topo_file, config.clone()).unwrap();
Ok(topology)
}
Loading

0 comments on commit a98f997

Please sign in to comment.