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
2 changes: 1 addition & 1 deletion Cargo.lock

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

1 change: 1 addition & 0 deletions illumos-utils/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ oxlog.workspace = true
oxnet.workspace = true
schemars.workspace = true
serde.workspace = true
sled-agent-types.workspace = true
slog.workspace = true
slog-async.workspace = true
slog-term.workspace = true
Expand Down
44 changes: 44 additions & 0 deletions illumos-utils/src/opte/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,22 @@ pub struct AttachedSubnet {
pub kind: AttachedSubnetKind,
}

impl From<sled_agent_types::attached_subnet::AttachedSubnet>
for AttachedSubnet
{
fn from(value: sled_agent_types::attached_subnet::AttachedSubnet) -> Self {
Self { cidr: net_to_cidr(value.subnet), kind: value.kind.into() }
}
}

impl From<AttachedSubnet>
for sled_agent_types::attached_subnet::AttachedSubnet
{
fn from(value: AttachedSubnet) -> Self {
Self { subnet: cidr_to_net(value.cidr), kind: value.kind.into() }
}
}

/// The kind of subnet that is attached.
#[derive(Clone, Copy, Debug)]
pub enum AttachedSubnetKind {
Expand All @@ -180,6 +196,34 @@ pub enum AttachedSubnetKind {
External,
}

impl From<sled_agent_types::attached_subnet::AttachedSubnetKind>
for AttachedSubnetKind
{
fn from(
value: sled_agent_types::attached_subnet::AttachedSubnetKind,
) -> Self {
match value {
sled_agent_types::attached_subnet::AttachedSubnetKind::Vpc => {
Self::Vpc
}
sled_agent_types::attached_subnet::AttachedSubnetKind::External => {
Self::External
}
}
}
}

impl From<AttachedSubnetKind>
for sled_agent_types::attached_subnet::AttachedSubnetKind
{
fn from(value: AttachedSubnetKind) -> Self {
match value {
AttachedSubnetKind::Vpc => Self::Vpc,
AttachedSubnetKind::External => Self::External,
}
}
}

/// A set of removed / added attached subnets in an OPTE API call.
///
/// This is used to ensure we keep our in-memory state in sync with whatever we
Expand Down
22 changes: 2 additions & 20 deletions illumos-utils/src/running_zone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -720,23 +720,6 @@ impl InstalledZone {
/// The path to the zone's root filesystem (i.e., `/`), within zonepath.
pub const ROOT_FS_PATH: &'static str = "root";

/// Returns the name of a zone, based on the base zone name plus any unique
/// identifying info.
///
/// The zone name is based on:
/// - A unique Oxide prefix ("oxz_")
/// - The name of the zone type being hosted (e.g., "nexus")
/// - An optional, zone-unique UUID
///
/// This results in a zone name which is distinct across different zpools,
/// but stable and predictable across reboots.
pub fn get_zone_name(
zone_type: &str,
unique_name: Option<OmicronZoneUuid>,
) -> String {
crate::zone::zone_name(zone_type, unique_name)
}

/// Get the name of the bootstrap VNIC in the zone, if any.
pub fn get_bootstrap_vnic_name(&self) -> Option<&str> {
self.bootstrap_vnic.as_ref().map(|link| link.name())
Expand Down Expand Up @@ -992,7 +975,7 @@ impl<'a> ZoneBuilder<'a> {
let temp_dir = fake_cfg.temp_dir;
(|| {
let zone_type = self.zone_type?;
let full_zone_name = InstalledZone::get_zone_name(
let full_zone_name = crate::zone::zone_name(
zone_type,
self.unique_name,
);
Expand Down Expand Up @@ -1058,8 +1041,7 @@ impl<'a> ZoneBuilder<'a> {
err,
})?;

let full_zone_name =
InstalledZone::get_zone_name(zone_type, unique_name);
let full_zone_name = crate::zone::zone_name(zone_type, unique_name);

// Look for the image within `file_source.search_paths`, in order.
let zone_image_path = file_source
Expand Down
82 changes: 11 additions & 71 deletions illumos-utils/src/svcs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ use chrono::Utc;
use schemars::JsonSchema;
use serde::Deserialize;
use serde::Serialize;
use sled_agent_types::inventory::Svc;
use sled_agent_types::inventory::SvcState;
use sled_agent_types::inventory::SvcsEnabledNotOnline;
use slog::Logger;
use slog::{error, info};
use std::fmt::Display;
#[cfg(target_os = "illumos")]
use tokio::process::Command;

Expand Down Expand Up @@ -61,6 +63,13 @@ pub struct SvcsResult {
pub time_of_status: DateTime<Utc>,
}

impl From<SvcsResult> for SvcsEnabledNotOnline {
fn from(value: SvcsResult) -> Self {
let SvcsResult { services, errors, time_of_status } = value;
Self { services, errors, time_of_status }
}
}

impl SvcsResult {
pub fn new() -> Self {
Self { services: vec![], errors: vec![], time_of_status: Utc::now() }
Expand Down Expand Up @@ -89,7 +98,7 @@ impl SvcsResult {

if let Some(svc_state) = svc.next() {
// Only parse services that are in a known SMF service state.
let state = SvcState::from(svc_state.to_string());
let state = SvcState::from(svc_state);
match &state {
SvcState::Maintenance
| SvcState::Degraded
Expand Down Expand Up @@ -165,75 +174,6 @@ impl SvcsResult {
}
}

/// Each service instance is always in a well-defined state based on its
/// dependencies, the results of the execution of its methods, and its potential
/// contracts events. See <https://illumos.org/man/7/smf> for more information.
#[derive(
Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize, JsonSchema,
)]
#[serde(rename_all = "snake_case")]
pub enum SvcState {
/// Initial state for all service instances.
Uninitialized,
/// The instance is enabled, but not yet running or available to run.
Offline,
/// The instance is enabled and running or is available to run.
Online,
/// The instance is enabled and running or available to run. It is, however,
/// functioning at a limited capacity in comparison to normal operation.
Degraded,
/// The instance is enabled, but not able to run.
Maintenance,
/// The instance is disabled.
Disabled,
/// Represents a legacy instance that is not managed by the service
/// management facility.
LegacyRun,
/// We were unable to determine the state of the service instance.
Unknown,
}

impl From<String> for SvcState {
fn from(value: String) -> Self {
match value.as_str() {
"uninitialized" => SvcState::Uninitialized,
"offline" => SvcState::Offline,
"online" => SvcState::Online,
"degraded" => SvcState::Degraded,
"maintenance" => SvcState::Maintenance,
"disabled" => SvcState::Disabled,
"legacy_run" => SvcState::LegacyRun,
_ => SvcState::Unknown,
}
}
}

impl Display for SvcState {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let state = match self {
SvcState::Uninitialized => "uninitialized",
SvcState::Offline => "offline",
SvcState::Online => "online",
SvcState::Degraded => "degraded",
SvcState::Maintenance => "maintenance",
SvcState::Disabled => "disabled",
SvcState::LegacyRun => "legacy_run",
SvcState::Unknown => "unknown",
};

write!(f, "{state}")
}
}

#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
/// Information about an SMF service that is enabled but not running
pub struct Svc {
fmri: String,
zone: String,
state: SvcState,
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
15 changes: 15 additions & 0 deletions illumos-utils/src/zfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use omicron_common::disk::DiskIdentity;
use omicron_common::disk::SharedDatasetConfig;
use omicron_uuid_kinds::DatasetUuid;
use rustix::fd::AsRawFd;
use sled_agent_types::inventory::InventoryDataset;
use slog_error_chain::SlogInlineError;
use std::collections::BTreeMap;
use std::fmt;
Expand Down Expand Up @@ -592,6 +593,20 @@ impl TryFrom<&DatasetProperties> for SharedDatasetConfig {
}
}

impl From<DatasetProperties> for InventoryDataset {
fn from(props: DatasetProperties) -> Self {
Self {
id: props.id,
name: props.name,
available: props.avail,
used: props.used,
quota: props.quota,
reservation: props.reservation,
compression: props.compression,
}
}
}

impl DatasetProperties {
/// Parses dataset properties, assuming that the caller is providing the
/// output of the following command as stdout:
Expand Down
30 changes: 30 additions & 0 deletions illumos-utils/src/zone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use anyhow::anyhow;
use camino::Utf8Path;
use ipnetwork::IpNetwork;
use ipnetwork::IpNetworkError;
use sled_agent_types::inventory::OmicronZoneConfig;
use slog::Logger;
use slog::info;
use std::net::{IpAddr, Ipv6Addr};
Expand All @@ -33,6 +34,16 @@ pub const ROUTE: &str = "/usr/sbin/route";
pub const ZONE_PREFIX: &str = "oxz_";
pub const PROPOLIS_ZONE_PREFIX: &str = "oxz_propolis-server_";

/// Returns the name of a zone, based on the base zone name plus any unique
/// identifying info.
///
/// The zone name is based on:
/// - A unique Oxide prefix ("oxz_")
/// - The name of the zone type being hosted (e.g., "nexus")
/// - An optional, zone-unique UUID
///
/// This results in a zone name which is distinct across different zpools,
/// but stable and predictable across reboots.
pub fn zone_name(prefix: &str, id: Option<OmicronZoneUuid>) -> String {
if let Some(id) = id {
format!("{ZONE_PREFIX}{}_{}", prefix, id)
Expand All @@ -41,6 +52,25 @@ pub fn zone_name(prefix: &str, id: Option<OmicronZoneUuid>) -> String {
}
}

pub trait OmicronZoneConfigExt {
/// Returns the name of a zone, based on the zone type plus its unique ID.
///
/// The zone name is based on:
/// - A unique Oxide prefix ("oxz_")
/// - The zone type being hosted (e.g., "nexus")
/// - The zone's ID.
///
/// This results in a zone name which is distinct across different zpools,
/// but stable and predictable across reboots.
fn zone_name(&self) -> String;
}

impl OmicronZoneConfigExt for OmicronZoneConfig {
fn zone_name(&self) -> String {
zone_name(self.zone_type.kind().zone_prefix(), Some(self.id))
}
}

#[derive(thiserror::Error, Debug)]
enum Error {
#[error("Zone execution error")]
Expand Down
Loading
Loading