Skip to content
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

[sled agent] Create and use self-assembling zones for storage zones #1902

Merged
merged 35 commits into from
Apr 21, 2023
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
29bbfc2
[package] Destroy datasets as a part of uninstallation
smklein Oct 30, 2022
ef533ae
[sled agent] Add SMF profile builder
smklein Oct 31, 2022
9bae2a9
crdb uses a method script
smklein Oct 31, 2022
2bf35ca
CRDB is booting the 'new' way
smklein Nov 1, 2022
774b86e
Self-assembling clickhouse
smklein Nov 1, 2022
eaea77b
self-assembling crucible
smklein Nov 1, 2022
8d30fc9
formatting
smklein Nov 1, 2022
afb19c5
Merge branch 'main' into uninstall-zfs
smklein Nov 1, 2022
626fdad
Fix typo
smklein Nov 1, 2022
8940321
Merge branch 'uninstall-zfs' into self-assembling-zones
smklein Nov 1, 2022
0274225
Merge branch 'main' into self-assembling-zones
smklein Nov 1, 2022
75a1e8c
Merge branch 'main' into self-assembling-zones
smklein Nov 2, 2022
e6f016c
Merge branch 'main' into self-assembling-zones
smklein Nov 10, 2022
792d312
Merge branch 'main' into self-assembling-zones
smklein Nov 14, 2022
7d1a2a5
Merge branch 'main' into self-assembling-zones
smklein Mar 7, 2023
a679a4b
fix mismerge
smklein Mar 7, 2023
7948af7
Merge branch 'main' into self-assembling-zones
smklein Apr 19, 2023
58f77f6
lock
smklein Apr 19, 2023
fedd4c0
Updates for CruciblePantry
smklein Apr 19, 2023
a10617d
Bump revs for crucibles
smklein Apr 20, 2023
c3c4f52
Remove single_instance
smklein Apr 20, 2023
d80b632
convert to oxide/service name where possible
smklein Apr 20, 2023
3d22b05
review feedback
smklein Apr 20, 2023
b5a9ec9
More method script cleanup
smklein Apr 20, 2023
a62d759
Rename to ServiceInstanceBuilder
smklein Apr 20, 2023
efc139b
Split instance from service
smklein Apr 20, 2023
f1ddb57
package manifest
smklein Apr 20, 2023
8b6648b
fmt
smklein Apr 20, 2023
89377fc
Let me see the propolis log
smklein Apr 20, 2023
23977fd
Merge branch 'main' into self-assembling-zones
smklein Apr 20, 2023
26bcf31
Update manifest
smklein Apr 20, 2023
bbff097
Start CRDB in background so the start task transitions it to 'online'
smklein Apr 20, 2023
dca16bc
Merge branch 'main' into self-assembling-zones
smklein Apr 20, 2023
e9229bf
Fix Clickhouse manifests
smklein Apr 20, 2023
be30a16
Update crucible
smklein Apr 21, 2023
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
291 changes: 198 additions & 93 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package-manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,10 @@ service_name = "crucible"
# 3. Use source.type = "manual" instead of "prebuilt"
source.type = "prebuilt"
source.repo = "crucible"
source.commit = "144d8dafa41715e00b08a5929cc62140ff0eb561"
source.commit = "5aa4e86eccb2763ef23e03dfccbe5b55c006a367"
# The SHA256 digest is automatically posted to:
# https://buildomat.eng.oxide.computer/public/file/oxidecomputer/crucible/image/<commit>/crucible.sha256.txt
source.sha256 = "2de086b0ba27efc638c88ff46a6d110236c2db92499266eccbd2a3ec28acc693"
source.sha256 = "f9949062f8a06f43dc0002d3c82a174ccafac84a4666b625bfff914d37643641"
output.type = "zone"

# Refer to
Expand Down
1 change: 1 addition & 0 deletions sled-agent/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ mockall = "0.11"
omicron-test-utils = { path = "../test-utils" }
openapi-lint = { git = "https://github.com/oxidecomputer/openapi-lint", branch = "main" }
openapiv3 = "1.0"
pretty_assertions = "1.3.0"
serial_test = "0.9"
subprocess = "0.2.9"
slog-async = "2.6"
Expand Down
8 changes: 8 additions & 0 deletions sled-agent/src/illumos/running_zone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,14 @@ impl InstalledZone {
zone_name
}

pub fn get_control_vnic_name(&self) -> &str {
self.control_vnic.name()
}

pub fn name(&self) -> &str {
&self.name
}

#[allow(clippy::too_many_arguments)]
pub async fn install(
log: &Logger,
Expand Down
1 change: 1 addition & 0 deletions sled-agent/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ mod instance_manager;
mod nexus;
mod opte;
pub mod params;
mod profile;
pub mod rack_setup;
mod serial;
pub mod server;
Expand Down
254 changes: 254 additions & 0 deletions sled-agent/src/profile.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
// 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/.

//! Utilities to build SMF profiles.

use std::fmt::{Display, Error, Formatter};

pub struct ProfileBuilder {
name: String,
services: Vec<ServiceBuilder>,
}

impl ProfileBuilder {
pub fn new(name: &str) -> Self {
Self { name: name.to_string(), services: vec![] }
}

pub fn add_service(mut self, service: ServiceBuilder) -> Self {
self.services.push(service);
self
}
}

impl Display for ProfileBuilder {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
write!(
f,
r#"<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<service_bundle type="profile" name="{name}">
"#,
name = self.name
)?;
for service in &self.services {
write!(f, "{}", service)?;
}
write!(f, "</service_bundle>")?;

Ok(())
}
}

pub struct ServiceBuilder {
name: String,
property_groups: Vec<PropertyGroupBuilder>,
}

impl ServiceBuilder {
pub fn new(name: &str) -> Self {
Self { name: name.to_string(), property_groups: vec![] }
}

pub fn add_property_group(
mut self,
property_group: PropertyGroupBuilder,
) -> Self {
self.property_groups.push(property_group);
self
}
}

impl Display for ServiceBuilder {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
write!(
f,
r#" <service version="1" type="service" name="{name}">
<instance enabled="true" name="default">
smklein marked this conversation as resolved.
Show resolved Hide resolved
"#,
name = self.name
)?;

for property_group in &self.property_groups {
write!(f, "{}", property_group)?;
}

write!(
f,
r#" </instance>
</service>
"#
)?;

Ok(())
}
}

pub struct PropertyGroupBuilder {
name: String,
properties: Vec<Property>,
}

impl PropertyGroupBuilder {
pub fn new(name: &str) -> Self {
Self { name: name.to_string(), properties: vec![] }
}

pub fn add_property(mut self, name: &str, ty: &str, value: &str) -> Self {
self.properties.push(Property {
name: name.to_string(),
ty: ty.to_string(),
value: value.to_string(),
});
self
}
}

impl Display for PropertyGroupBuilder {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
write!(
f,
r#" <property_group type="application" name="{name}">
"#,
name = self.name
)?;
for property in &self.properties {
write!(f, "{}", property)?;
}
write!(
f,
r#" </property_group>
"#
)?;
Ok(())
}
}

pub struct Property {
name: String,
ty: String,
value: String,
}

impl Display for Property {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
write!(
f,
r#" <propval type="{ty}" name="{name}" value="{value}"/>
"#,
name = self.name,
ty = self.ty,
value = self.value
)?;
Ok(())
}
}

#[cfg(test)]
mod tests {
use super::*;
use pretty_assertions::assert_eq;

#[test]
fn empty_profile() {
let builder = ProfileBuilder::new("myprofile");
assert_eq!(
format!("{}", builder),
r#"<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<service_bundle type="profile" name="myprofile">
</service_bundle>"#,
);
}

#[test]
fn test_service() {
let builder = ProfileBuilder::new("myprofile")
.add_service(ServiceBuilder::new("myservice"));
assert_eq!(
format!("{}", builder),
r#"<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<service_bundle type="profile" name="myprofile">
<service version="1" type="service" name="myservice">
<instance enabled="true" name="default">
</instance>
</service>
</service_bundle>"#,
);
}

#[test]
fn test_property_group() {
let builder = ProfileBuilder::new("myprofile").add_service(
ServiceBuilder::new("myservice")
.add_property_group(PropertyGroupBuilder::new("mypg")),
);
assert_eq!(
format!("{}", builder),
r#"<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<service_bundle type="profile" name="myprofile">
<service version="1" type="service" name="myservice">
<instance enabled="true" name="default">
<property_group type="application" name="mypg">
</property_group>
</instance>
</service>
</service_bundle>"#,
);
}

#[test]
fn test_property() {
let builder = ProfileBuilder::new("myprofile").add_service(
ServiceBuilder::new("myservice").add_property_group(
PropertyGroupBuilder::new("mypg")
.add_property("prop", "type", "value"),
),
);
assert_eq!(
format!("{}", builder),
r#"<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<service_bundle type="profile" name="myprofile">
<service version="1" type="service" name="myservice">
<instance enabled="true" name="default">
<property_group type="application" name="mypg">
<propval type="type" name="prop" value="value"/>
</property_group>
</instance>
</service>
</service_bundle>"#,
);
}

#[test]
fn test_multiple() {
let builder = ProfileBuilder::new("myprofile").add_service(
ServiceBuilder::new("myservice")
.add_property_group(
PropertyGroupBuilder::new("mypg")
.add_property("prop", "type", "value")
.add_property("prop2", "type", "value2"),
)
.add_property_group(
PropertyGroupBuilder::new("mypg2")
.add_property("prop3", "type", "value3"),
),
);
assert_eq!(
format!("{}", builder),
r#"<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<service_bundle type="profile" name="myprofile">
<service version="1" type="service" name="myservice">
<instance enabled="true" name="default">
<property_group type="application" name="mypg">
<propval type="type" name="prop" value="value"/>
<propval type="type" name="prop2" value="value2"/>
</property_group>
<property_group type="application" name="mypg2">
<propval type="type" name="prop3" value="value3"/>
</property_group>
</instance>
</service>
</service_bundle>"#,
);
}
}
Loading