Skip to content

Import maghemite mg-ddm service #1249

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 23, 2022
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
9 changes: 3 additions & 6 deletions deploy/src/bin/thing-flinger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -480,19 +480,16 @@ fn overlay_sled_agent(

// TODO do we need any escaping here? this will definitely break if any dir
// names have spaces
let dirs = sled_agent_dirs
.iter()
.map(|dir| format!(" --directories {}", dir.display()))
.collect::<String>();
let dirs = sled_agent_dirs.iter().map(|dir| format!(" {}", dir.display()));

let cmd = format!(
"sh -c 'for dir in {}; do mkdir -p $dir; done' && \
cd {} && \
cargo run {} --bin sled-agent-overlay-files -- {}",
dirs,
dirs.clone().collect::<String>(),
config.builder.omicron_path.to_string_lossy(),
config.release_arg(),
dirs
dirs.map(|dir| format!(" --directories {}", dir)).collect::<String>(),
);
ssh_exec(builder, &cmd, false)
}
Expand Down
11 changes: 11 additions & 0 deletions package-manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,14 @@ commit = "d2b8184d11d5d5f56424fe0bee13ca03d576604e"
# The SHA256 digest is automatically posted to:
# https://buildomat.eng.oxide.computer/public/file/oxidecomputer/propolis/image/<commit>/propolis-server.sha256.txt
sha256 = "b192fbaaee850e63adaf9f7fe5ff2054a9de338d70198b1d1670285057a047be"

[external_package.maghemite]
service_name = "mg-ddm"
zone = false
[external_package.maghemite.source]
type = "prebuilt"
repo = "maghemite"
commit = "2be097ddd1d3fd8e7f56bc0a4bfd696253b11454"
# The SHA256 digest is automatically posted to:
# https://buildomat.eng.oxide.computer/public/file/oxidecomputer/maghemite/image/<commit>/mg-ddm.sha256.txt
sha256 = "94218915ec6fed75dcc81d736bd5e9ef62c9eb651a67a943b297d94d6b390941"
20 changes: 14 additions & 6 deletions package/src/bin/omicron-package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,12 +330,16 @@ fn do_install(
uninstall_all_packages(config);
uninstall_all_omicron_zones()?;

// Extract and install the bootstrap service, which itself extracts and
// installs other services.
if let Some(package) = config.packages.get("omicron-sled-agent") {
let tar_path =
install_dir.join(format!("{}.tar", package.service_name));
let service_path = install_dir.join(&package.service_name);
// Extract all global zone services.
let global_zone_service_names = config
.packages
.values()
.chain(config.external_packages.values().map(|p| &p.package))
.filter_map(|p| if p.zone { None } else { Some(&p.service_name) });

for service_name in global_zone_service_names {
let tar_path = install_dir.join(format!("{}.tar", service_name));
let service_path = install_dir.join(service_name);
println!(
"Unpacking {} to {}",
tar_path.to_string_lossy(),
Expand All @@ -347,7 +351,11 @@ fn do_install(
std::fs::create_dir_all(&service_path)?;
let mut archive = tar::Archive::new(tar_file);
archive.unpack(&service_path)?;
}

// Install the bootstrap service, which itself extracts and
// installs other services.
if let Some(package) = config.packages.get("omicron-sled-agent") {
let manifest_path = install_dir
.join(&package.service_name)
.join("pkg")
Expand Down
60 changes: 60 additions & 0 deletions sled-agent/src/bootstrap/maghemite.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// 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/.

//! Starting the mg-ddm service.

use crate::illumos::addrobj::AddrObject;
use slog::Logger;
use thiserror::Error;

const SERVICE_FMRI: &str = "svc:/system/illumos/mg-ddm";
const MANIFEST_PATH: &str = "/opt/oxide/mg-ddm/pkg/ddm/manifest.xml";

#[derive(Debug, Error)]
pub enum Error {
#[error("Error configuring service: {0}")]
Config(#[from] smf::ConfigError),

#[error("Error administering service: {0}")]
Adm(#[from] smf::AdmError),

#[error("Error starting service: {0}")]
Join(#[from] tokio::task::JoinError),
}

pub async fn enable_mg_ddm_service(
log: Logger,
interface: AddrObject,
) -> Result<(), Error> {
tokio::task::spawn_blocking(|| {
enable_mg_ddm_service_blocking(log, interface)
})
.await?
}

fn enable_mg_ddm_service_blocking(
log: Logger,
interface: AddrObject,
) -> Result<(), Error> {
info!(log, "Importing mg-ddm service"; "path" => MANIFEST_PATH);
smf::Config::import().run(MANIFEST_PATH)?;

// TODO-cleanup mg-ddm supports multiple interfaces, but `smf` currently
// doesn't expose an equivalent of `svccfg addpropvalue`. If we need
// multiple interfaces we'll need to extend smf.
let interface = interface.to_string();
info!(log, "Setting mg-ddm interface"; "interface" => interface.as_str());
smf::Config::set_property(SERVICE_FMRI).run(smf::Property::new(
smf::PropertyName::new("config", "interfaces").unwrap(),
smf::PropertyValue::Astring(interface),
))?;
Comment on lines +43 to +51
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, this library is just a wrapper around the /usr/sbin/svccfg command - if it's too inflexible, it's totally okay to call out to that command manually.

(extending the library is also a viable option, as you suggested).


info!(log, "Enabling mg-ddm service");
smf::Adm::new()
.enable()
.temporary()
.run(smf::AdmSelection::ByPattern(&[SERVICE_FMRI]))?;

Ok(())
}
1 change: 1 addition & 0 deletions sled-agent/src/bootstrap/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub mod agent;
pub mod client;
pub mod config;
pub mod discovery;
mod maghemite;
pub mod multicast;
pub(crate) mod params;
pub(crate) mod rss_handle;
Expand Down
28 changes: 28 additions & 0 deletions sled-agent/src/bootstrap/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,14 @@ use super::params::RequestEnvelope;
use super::trust_quorum::ShareDistribution;
use super::views::Response;
use super::views::ResponseEnvelope;
use crate::bootstrap::maghemite;
use crate::config::Config as SledConfig;
use crate::illumos::addrobj::AddrObject;
use crate::illumos::dladm::VnicSource;
use crate::sp::AsyncReadWrite;
use crate::sp::SpHandle;
use crate::sp::SprocketsRole;
use crate::zone::Zones;
use slog::Drain;
use slog::Logger;
use std::net::Ipv6Addr;
Expand Down Expand Up @@ -63,6 +67,30 @@ impl Server {
debug!(log, "registered DTrace probes");
}

// Ensure we have a link-local inet6 address.
let link = sled_config
.get_link()
.map_err(|err| format!("Failed to find physical link: {err}"))?;

let mg_interface = AddrObject::new(link.name(), "linklocal")
.expect("unexpected failure creating AddrObject");
Zones::ensure_has_link_local_v6_address(None, &mg_interface).map_err(
|err| {
format!(
"Failed to ensure link-local address for {}: {}",
mg_interface, err
)
},
)?;

// Turn on the maghemite routing service.
// TODO-correctness Eventually we need mg-ddm to listen on multiple
// interfaces (link-local addresses of both NICs).
info!(log, "Starting mg-ddm service");
maghemite::enable_mg_ddm_service(log.clone(), mg_interface)
.await
.map_err(|err| format!("Failed to start mg-ddm: {err}"))?;

info!(log, "detecting (real or simulated) SP");
let sp = SpHandle::detect(
config.sp_config.as_ref().map(|c| &c.local_sp),
Expand Down