Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions gateway/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,7 @@ serde_json = "1.0"
sp-sim = { path = "../sp-sim" }
subprocess = "0.2.9"
tokio-tungstenite = "0.17"

[[bin]]
name = "mgs"
doc = false
8 changes: 0 additions & 8 deletions gateway/examples/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@
# Oxide API: example configuration file
#

# Identifier for this instance of MGS
id = "8afcb12d-f625-4df9-bdf2-f495c3bbd323"

[switch]
# which vsc port is connected to our local sidecar SP (i.e., the SP that acts as
# our contact to the ignition controller)
Expand Down Expand Up @@ -79,11 +76,6 @@ bulk_request_max_millis = 60_000
bulk_request_page_millis = 1_000
bulk_request_retain_grace_period_millis = 10_000

[dropshot]
# IP address and TCP port on which to listen for the external API
bind_address = "127.0.0.1:12222"
request_body_max_bytes = 134217728 # 128 MiB

[log]
# Show log messages of this level and more severe
level = "debug"
Expand Down
51 changes: 0 additions & 51 deletions gateway/src/bin/gateway.rs

This file was deleted.

58 changes: 58 additions & 0 deletions gateway/src/bin/mgs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

//! Executable program to run gateway, the management gateway service

use clap::Parser;
use omicron_common::cmd::{fatal, CmdError};
use omicron_gateway::{run_openapi, run_server, Config, MgsArguments};
use std::net::SocketAddrV6;
use std::path::PathBuf;
use uuid::Uuid;

#[derive(Debug, Parser)]
#[clap(name = "gateway", about = "See README.adoc for more information")]
enum Args {
/// Print the external OpenAPI Spec document and exit
Openapi,

/// Start an MGS server
Run {
#[clap(name = "CONFIG_FILE_PATH", action)]
config_file_path: PathBuf,

#[clap(short, long, action)]
id: Uuid,

#[clap(short, long, action)]
address: SocketAddrV6,
},
}

#[tokio::main]
async fn main() {
if let Err(cmd_error) = do_run().await {
fatal(cmd_error);
}
}

async fn do_run() -> Result<(), CmdError> {
let args = Args::parse();

match args {
Args::Openapi => run_openapi().map_err(CmdError::Failure),
Args::Run { config_file_path, id, address } => {
let config = Config::from_file(&config_file_path).map_err(|e| {
CmdError::Failure(format!(
"failed to parse {}: {}",
config_file_path.display(),
e
))
})?;

let args = MgsArguments { id, address };
run_server(config, args).await.map_err(CmdError::Failure)
}
}
}
6 changes: 1 addition & 5 deletions gateway/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
//! Interfaces for parsing configuration files and working with a gateway server
//! configuration

use dropshot::{ConfigDropshot, ConfigLogging};
use dropshot::ConfigLogging;
use gateway_sp_comms::SwitchConfig;
use serde::{Deserialize, Serialize};
use std::path::Path;
Expand Down Expand Up @@ -36,12 +36,8 @@ pub struct Timeouts {
/// Configuration for a gateway server
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct Config {
/// Identifier for this instance of MGS
pub id: uuid::Uuid,
/// Various timeouts
pub timeouts: Timeouts,
/// Dropshot configuration for API server
pub dropshot: ConfigDropshot,
/// Configuration of the management switch.
pub switch: SwitchConfig,
/// Server-wide logging configuration.
Expand Down
37 changes: 31 additions & 6 deletions gateway/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,19 @@ pub mod http_entrypoints; // TODO pub only for testing - is this right?
pub use config::Config;
pub use context::ServerContext;

use slog::{debug, error, info, o, warn, Logger};
use dropshot::ConfigDropshot;
use slog::debug;
use slog::error;
use slog::info;
use slog::o;
use slog::warn;
use slog::Logger;
use std::net::SocketAddr;
use std::net::SocketAddrV6;
use std::sync::Arc;
use uuid::Uuid;

/// Run the OpenAPI generator for the API, which emits the OpenAPI spec
/// Run the OpenAPI generator for the API; which emits the OpenAPI spec
/// to stdout.
pub fn run_openapi() -> Result<(), String> {
http_entrypoints::api()
Expand All @@ -29,6 +37,11 @@ pub fn run_openapi() -> Result<(), String> {
.map_err(|e| e.to_string())
}

pub struct MgsArguments {
pub id: Uuid,
pub address: SocketAddrV6,
}

pub struct Server {
/// shared state used by API request handlers
pub apictx: Arc<ServerContext>,
Expand All @@ -40,10 +53,11 @@ impl Server {
/// Start a gateway server.
pub async fn start(
config: Config,
args: MgsArguments,
_rack_id: Uuid,
log: &Logger,
) -> Result<Server, String> {
let log = log.new(o!("name" => config.id.to_string()));
let log = log.new(o!("name" => args.id.to_string()));
info!(log, "setting up gateway server");

match gateway_sp_comms::register_probes() {
Expand All @@ -59,8 +73,16 @@ impl Server {
format!("initializing server context: {}", error)
})?;

let dropshot = ConfigDropshot {
bind_address: SocketAddr::V6(args.address),
// We need to be able to accept the largest single update blob we
// expect to be given, which at the moment is probably a host phase
// 1 image? (32 MiB raw, plus overhead for HTTP encoding)
request_body_max_bytes: 128 << 20,
..Default::default()
};
let http_server_starter = dropshot::HttpServerStarter::new(
&config.dropshot,
&dropshot,
http_entrypoints::api(),
Arc::clone(&apictx),
&log.new(o!("component" => "dropshot")),
Expand Down Expand Up @@ -92,7 +114,10 @@ impl Server {
}

/// Run an instance of the [Server].
pub async fn run_server(config: Config) -> Result<(), String> {
pub async fn run_server(
config: Config,
args: MgsArguments,
) -> Result<(), String> {
use slog::Drain;
let (drain, registration) = slog_dtrace::with_drain(
config
Expand All @@ -109,7 +134,7 @@ pub async fn run_server(config: Config) -> Result<(), String> {
debug!(log, "registered DTrace probes");
}
let rack_id = Uuid::new_v4();
let server = Server::start(config, rack_id, &log).await?;
let server = Server::start(config, args, rack_id, &log).await?;
// server.register_as_producer().await;
server.wait_for_finish().await
}
13 changes: 0 additions & 13 deletions gateway/tests/config.test.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@
# Oxide API: example configuration file
#

# Identifier for this instance of MGS
# NOTE: The test suite always overrides this.
id = "8afcb12d-f625-4df9-bdf2-f495c3bbd323"

[switch]
# which vsc port is connected to our local sidecar SP (i.e., the SP that acts as
# our contact to the ignition controller)
Expand Down Expand Up @@ -87,15 +83,6 @@ bulk_request_max_millis = 40_000
bulk_request_page_millis = 2_000
bulk_request_retain_grace_period_millis = 10_000

#
# NOTE: for the test suite, the port MUST be 0 (in order to bind to any
# available port) because the test suite will be running many servers
# concurrently.
#
[dropshot]
bind_address = "127.0.0.1:0"
request_body_max_bytes = 1048576

#
# NOTE: for the test suite, if mode = "file", the file path MUST be the sentinel
# string "UNUSED". The actual path will be generated by the test suite for each
Expand Down
16 changes: 7 additions & 9 deletions gateway/tests/integration_tests/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,19 @@ use omicron_test_utils::dev::test_cmds::{
use openapiv3::OpenAPI;
use subprocess::Exec;

// name of gateway executable
const CMD_GATEWAY: &str = env!("CARGO_BIN_EXE_gateway");
// name of mgs executable
const CMD_MGS: &str = env!("CARGO_BIN_EXE_mgs");

fn path_to_gateway() -> PathBuf {
path_to_executable(CMD_GATEWAY)
fn path_to_mgs() -> PathBuf {
path_to_executable(CMD_MGS)
}

#[test]
fn test_gateway_openapi_sled() {
let exec = Exec::cmd(path_to_gateway())
.arg("--openapi")
.arg("examples/config.toml");
fn test_mgs_openapi_sled() {
let exec = Exec::cmd(path_to_mgs()).arg("openapi");
let (exit_status, stdout_text, stderr_text) = run_command(exec);
assert_exit_code(exit_status, EXIT_SUCCESS, &stderr_text);
assert_contents("tests/output/cmd-gateway-openapi-stderr", &stderr_text);
assert_contents("tests/output/cmd-mgs-openapi-stderr", &stderr_text);

let spec: OpenAPI = serde_json::from_str(&stdout_text)
.expect("stdout was not valid OpenAPI");
Expand Down
20 changes: 14 additions & 6 deletions gateway/tests/integration_tests/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use dropshot::test_util::ClientTestContext;
use dropshot::test_util::LogContext;
use gateway_messages::SpPort;
use gateway_sp_comms::SpType;
use omicron_gateway::MgsArguments;
use omicron_test_utils::dev::poll;
use omicron_test_utils::dev::poll::CondCheckError;
use slog::o;
Expand Down Expand Up @@ -40,10 +41,9 @@ impl GatewayTestContext {

pub fn load_test_config() -> (omicron_gateway::Config, sp_sim::Config) {
let server_config_file_path = Path::new("tests/config.test.toml");
let mut server_config =
let server_config =
omicron_gateway::Config::from_file(server_config_file_path)
.expect("failed to load config.test.toml");
server_config.id = Uuid::new_v4();

let sp_sim_config_file_path = Path::new("tests/sp_sim_config.test.toml");
let sp_sim_config = sp_sim::Config::from_file(sp_sim_config_file_path)
Expand Down Expand Up @@ -120,10 +120,18 @@ pub async fn test_setup_with_config(
// Start gateway server
let rack_id = Uuid::parse_str(RACK_UUID).unwrap();

let server =
omicron_gateway::Server::start(server_config.clone(), rack_id, log)
.await
.unwrap();
let args = MgsArguments {
id: Uuid::new_v4(),
address: "[::1]:0".parse().unwrap(),
};
let server = omicron_gateway::Server::start(
server_config.clone(),
args,
rack_id,
log,
)
.await
.unwrap();

// Build a list of all SPs defined in our config
let mut all_sp_ids = Vec::new();
Expand Down
9 changes: 9 additions & 0 deletions package-manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,15 @@ zone = true
from = "smf/internal-dns"
to = "/var/svc/manifest/site/internal-dns"

[package.omicron-gateway]
rust.binary_names = ["mgs"]
rust.release = true
service_name = "mgs"
zone = true
[[package.omicron-gateway.paths]]
from = "smf/mgs"
to = "/var/svc/manifest/site/mgs"

# Packages not built within Omicron, but which must be imported.

# Refer to
Expand Down
Loading