From 41d2db1b63641d7d2cfc9db80e41e8437f6c96b3 Mon Sep 17 00:00:00 2001 From: "Carpenter, Adam (CORP)" Date: Thu, 13 Jan 2022 13:53:26 -0500 Subject: feat: support station busyout/release toggling via extension Introduces bulk station busyout/release toggle endpoints via the `simple_busy` extension. Bumps `angelsharkd` version. Feature is documented in README. Removes TODO in `simple_deprov` README. --- .../src/routes/extensions/simple_busy/README.md | 50 +++++++++++ .../src/routes/extensions/simple_busy/mod.rs | 98 ++++++++++++++++++++++ 2 files changed, 148 insertions(+) create mode 100644 angelsharkd/src/routes/extensions/simple_busy/README.md create mode 100644 angelsharkd/src/routes/extensions/simple_busy/mod.rs (limited to 'angelsharkd/src/routes/extensions/simple_busy') diff --git a/angelsharkd/src/routes/extensions/simple_busy/README.md b/angelsharkd/src/routes/extensions/simple_busy/README.md new file mode 100644 index 0000000..dd9ba2c --- /dev/null +++ b/angelsharkd/src/routes/extensions/simple_busy/README.md @@ -0,0 +1,50 @@ +# Daemon Extension `simple_busy` + +This extension implements simple extension busyout and release toggling. + +## Getting Started + +To enable this feature, compile `angelsharkd` with the `simple_busy` flag: + +```sh +cargo build --bin angelsharkd --features simple_busy ... +``` + +## `POST /extensions/service/busyout` Busy-out a station + +The request consists of one or more entries including the ACM and extension to +be operated on. + +```json +POST /extensions/service/toggle +[ + { + "acm": "01", + "ext": "17571230000" + } +] +``` + +The response is a typical `angelsharkd` OSSI reponse. + +```json +[ + { + "acm": "01", + "command": "busyout station 17571230000", + "error": "", + "fields": ["0001ff00", "0002ff00", "0005ff00", "0003ff00", "0004ff00"], + "datas": [["S075157", "DIG-IP-S", "17571230000", "ABORT", "1010"]] + } +] +``` + +## `POST /extensions/service/release` Release a station + +This endpoint works identically to the busyout endpoint, but the response will +indicate whether the station was released. + +## `POST /extensions/service/toggle` Busyout and then immediately release a station + +This endpoint runs two OSSI commands for busyout-ing and releasing the given +stations, respectively. diff --git a/angelsharkd/src/routes/extensions/simple_busy/mod.rs b/angelsharkd/src/routes/extensions/simple_busy/mod.rs new file mode 100644 index 0000000..23f05fd --- /dev/null +++ b/angelsharkd/src/routes/extensions/simple_busy/mod.rs @@ -0,0 +1,98 @@ +use crate::routes::dtos::{Error, Response}; +use libangelshark::{AcmRunner, Message, ParallelIterator}; +use log::error; +use serde::Deserialize; +use warp::{ + body::{content_length_limit, json}, + hyper::StatusCode, + path, post, reply, Filter, Rejection, Reply, +}; + +const SIXTEEN_K: u64 = 1024 * 16; + +pub fn busy_filter( + runner: AcmRunner, +) -> impl Filter + Clone { + post() + .and(path!("service" / "busyout" / ..)) + .and(content_length_limit(SIXTEEN_K)) + .and(json()) + .map(move |entries| queue_and_run(entries, "busyout", runner.to_owned())) +} + +pub fn release_filter( + runner: AcmRunner, +) -> impl Filter + Clone { + post() + .and(path!("service" / "release" / ..)) + .and(content_length_limit(SIXTEEN_K)) + .and(json()) + .map(move |entries| queue_and_run(entries, "release", runner.to_owned())) +} + +pub fn toggle_filter( + runner: AcmRunner, +) -> impl Filter + Clone { + post() + .and(path!("service" / "toggle" / ..)) + .and(content_length_limit(SIXTEEN_K)) + .and(json()) + .map(move |entries| queue_and_run(entries, "toggle", runner.to_owned())) +} + +fn queue_and_run(entries: Entries, command: &str, mut runner: AcmRunner) -> impl Reply { + for entry in entries.into_iter() { + if command == "toggle" { + runner.queue_input( + &entry.acm, + &Message::new(&format!("busyout station {}", entry.ext)), + ); + runner.queue_input( + &entry.acm, + &Message::new(&format!("release station {}", entry.ext)), + ); + } else { + runner.queue_input( + &entry.acm, + &Message::new(&format!("{} station {}", command, entry.ext)), + ); + } + } + + // generate output on runner + let output: Result>, _> = runner + .run() + .map(|(name, output)| -> Result, anyhow::Error> { + Ok(output? + .into_iter() + .filter_map(move |msg| { + (msg.command != "logoff").then(|| Response::from((name.to_owned(), msg))) + }) + .collect()) + }) + .collect(); + + // handle errors and package output as json + match output { + Err(e) => { + error!("busyout-release extension: {}", e); + reply::with_status( + reply::json(&Error { + reason: e.to_string(), + }), + StatusCode::INTERNAL_SERVER_ERROR, + ) + } + Ok(r) => reply::with_status( + reply::json(&r.into_iter().flatten().collect::>()), + StatusCode::OK, + ), + } +} + +type Entries = Vec; +#[derive(Debug, Deserialize)] +struct Entry { + acm: String, + ext: String, +} -- cgit v1.2.3