Skip to content

Commit 7fb6cb4

Browse files
authored
pick up Propolis 50cb28f5 (#5906)
Update to Propolis commit 50cb28f5 to obtain the following updates: ``` 50cb28f server: separate statuses of inbound and outbound migrations (#661) 61e1481 Don't return None from BlockData::block_for_req when attachment is paused (#711) 79e243b Build and clippy fixes for Rust 1.79 (#712) 3c0f998 Modernize fw_cfg emulation 7a65be9 Update and prune dependencies ``` 50cb28f5 changes the Propolis instance status and migration status APIs to report both inbound and outbound migration status. Update sled agent accordingly. Tests: `cargo nextest`, smoke test on a dev cluster.
1 parent 754fcd0 commit 7fb6cb4

File tree

5 files changed

+108
-77
lines changed

5 files changed

+108
-77
lines changed

Cargo.lock

+12-12
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+3-3
Original file line numberDiff line numberDiff line change
@@ -394,9 +394,9 @@ prettyplease = { version = "0.2.20", features = ["verbatim"] }
394394
proc-macro2 = "1.0"
395395
progenitor = { git = "https://github.com/oxidecomputer/progenitor", branch = "main" }
396396
progenitor-client = { git = "https://github.com/oxidecomputer/progenitor", branch = "main" }
397-
bhyve_api = { git = "https://github.com/oxidecomputer/propolis", rev = "6d7ed9a033babc054db9eff5b59dee978d2b0d76" }
398-
propolis-client = { git = "https://github.com/oxidecomputer/propolis", rev = "6d7ed9a033babc054db9eff5b59dee978d2b0d76" }
399-
propolis-mock-server = { git = "https://github.com/oxidecomputer/propolis", rev = "6d7ed9a033babc054db9eff5b59dee978d2b0d76" }
397+
bhyve_api = { git = "https://github.com/oxidecomputer/propolis", rev = "50cb28f586083fdb990e401bc6146e7dac9b2753" }
398+
propolis-client = { git = "https://github.com/oxidecomputer/propolis", rev = "50cb28f586083fdb990e401bc6146e7dac9b2753" }
399+
propolis-mock-server = { git = "https://github.com/oxidecomputer/propolis", rev = "50cb28f586083fdb990e401bc6146e7dac9b2753" }
400400
proptest = "1.4.0"
401401
quote = "1.0"
402402
rand = "0.8.5"

package-manifest.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -532,10 +532,10 @@ service_name = "propolis-server"
532532
only_for_targets.image = "standard"
533533
source.type = "prebuilt"
534534
source.repo = "propolis"
535-
source.commit = "6d7ed9a033babc054db9eff5b59dee978d2b0d76"
535+
source.commit = "50cb28f586083fdb990e401bc6146e7dac9b2753"
536536
# The SHA256 digest is automatically posted to:
537537
# https://buildomat.eng.oxide.computer/public/file/oxidecomputer/propolis/image/<commit>/propolis-server.sha256.txt
538-
source.sha256 = "f8f41b47bc00811fefe2ba75e0f6f8ab77765776c04021e0b31f09c3b21108a9"
538+
source.sha256 = "864e74222d3e617f1bd7b7ba8d0e5cc18134dca121fc4339369620d1419c5bb0"
539539
output.type = "zone"
540540

541541
[package.mg-ddm-gz]

sled-agent/src/common/instance.rs

+47-40
Original file line numberDiff line numberDiff line change
@@ -117,50 +117,57 @@ impl ObservedPropolisState {
117117
instance_runtime: &InstanceRuntimeState,
118118
propolis_state: &InstanceStateMonitorResponse,
119119
) -> Self {
120-
let migration_status =
121-
match (instance_runtime.migration_id, &propolis_state.migration) {
122-
// If the runtime state and Propolis state agree that there's
123-
// a migration in progress, and they agree on its ID, the
124-
// Propolis migration state determines the migration status.
125-
(Some(this_id), Some(propolis_migration))
126-
if this_id == propolis_migration.migration_id =>
127-
{
128-
match propolis_migration.state {
129-
PropolisMigrationState::Finish => {
130-
ObservedMigrationStatus::Succeeded
131-
}
132-
PropolisMigrationState::Error => {
133-
ObservedMigrationStatus::Failed
134-
}
135-
_ => ObservedMigrationStatus::InProgress,
136-
}
137-
}
138-
139-
// If both sides have a migration ID, but the IDs don't match,
140-
// assume the instance's migration ID is newer. This can happen
141-
// if Propolis was initialized via migration in and has not yet
142-
// been told to migrate out.
143-
(Some(_), Some(_)) => ObservedMigrationStatus::Pending,
144-
145-
// If only Propolis has a migration ID, assume it was from a
146-
// prior migration in and report that no migration is in
147-
// progress. This could be improved with propolis#508.
148-
(None, Some(_)) => ObservedMigrationStatus::NoMigration,
149-
150-
// A migration source's migration IDs get set before its
151-
// Propolis actually gets asked to migrate, so it's possible for
152-
// the runtime state to contain an ID while the Propolis has
153-
// none, in which case the migration is pending.
154-
(Some(_), None) => ObservedMigrationStatus::Pending,
155-
156-
// If neither side has a migration ID, then there's clearly no
157-
// migration.
158-
(None, None) => ObservedMigrationStatus::NoMigration,
120+
// If there's no migration currently registered with this sled, report
121+
// the current state and that no migration is currently in progress,
122+
// even if Propolis has some migration data to share. (This case arises
123+
// when Propolis returns state from a previous migration that sled agent
124+
// has already retired.)
125+
//
126+
// N.B. This needs to be read from the instance runtime state and not
127+
// the migration runtime state to ensure that, once a migration in
128+
// completes, the "completed" observation is reported to
129+
// `InstanceStates::apply_propolis_observation` exactly once.
130+
// Otherwise that routine will try to apply the "inbound migration
131+
// complete" instance state transition twice.
132+
let Some(migration_id) = instance_runtime.migration_id else {
133+
return Self {
134+
vmm_state: PropolisInstanceState(propolis_state.state),
135+
migration_status: ObservedMigrationStatus::NoMigration,
136+
time: Utc::now(),
159137
};
138+
};
139+
140+
// Sled agent believes a live migration may be in progress. See if
141+
// either of the Propolis migrations corresponds to it.
142+
let propolis_migration = match (
143+
&propolis_state.migration.migration_in,
144+
&propolis_state.migration.migration_out,
145+
) {
146+
(Some(inbound), _) if inbound.id == migration_id => inbound,
147+
(_, Some(outbound)) if outbound.id == migration_id => outbound,
148+
_ => {
149+
// Sled agent believes this instance should be migrating, but
150+
// Propolis isn't reporting a matching migration yet, so assume
151+
// the migration is still pending.
152+
return Self {
153+
vmm_state: PropolisInstanceState(propolis_state.state),
154+
migration_status: ObservedMigrationStatus::Pending,
155+
time: Utc::now(),
156+
};
157+
}
158+
};
160159

161160
Self {
162161
vmm_state: PropolisInstanceState(propolis_state.state),
163-
migration_status,
162+
migration_status: match propolis_migration.state {
163+
PropolisMigrationState::Finish => {
164+
ObservedMigrationStatus::Succeeded
165+
}
166+
PropolisMigrationState::Error => {
167+
ObservedMigrationStatus::Failed
168+
}
169+
_ => ObservedMigrationStatus::InProgress,
170+
},
164171
time: Utc::now(),
165172
}
166173
}

sled-agent/src/sim/instance.rs

+44-20
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ use omicron_common::api::internal::nexus::{
1919
InstanceRuntimeState, MigrationRole, SledInstanceState, VmmState,
2020
};
2121
use propolis_client::types::{
22-
InstanceMigrateStatusResponse as PropolisMigrateStatus,
22+
InstanceMigrateStatusResponse as PropolisMigrateResponse,
23+
InstanceMigrationStatus as PropolisMigrationStatus,
2324
InstanceState as PropolisInstanceState, InstanceStateMonitorResponse,
2425
};
2526
use std::collections::VecDeque;
@@ -32,7 +33,7 @@ use crate::common::instance::{Action as InstanceAction, InstanceStates};
3233
#[derive(Clone, Debug)]
3334
enum MonitorChange {
3435
PropolisState(PropolisInstanceState),
35-
MigrateStatus(PropolisMigrateStatus),
36+
MigrateStatus(PropolisMigrateResponse),
3637
}
3738

3839
/// A simulation of an Instance created by the external Oxide API.
@@ -70,10 +71,10 @@ impl SimInstanceInner {
7071
self.queue.push_back(MonitorChange::PropolisState(propolis_state));
7172
}
7273

73-
/// Pushes a Propolis migration status to the state change queue.
74-
fn queue_migration_status(
74+
/// Pushes a Propolis migration update to the state change queue.
75+
fn queue_migration_update(
7576
&mut self,
76-
migrate_status: PropolisMigrateStatus,
77+
migrate_status: PropolisMigrateResponse,
7778
) {
7879
self.queue.push_back(MonitorChange::MigrateStatus(migrate_status))
7980
}
@@ -92,22 +93,42 @@ impl SimInstanceInner {
9293
self
9394
)
9495
});
95-
self.queue_migration_status(PropolisMigrateStatus {
96-
migration_id,
97-
state: propolis_client::types::MigrationState::Sync,
98-
});
99-
self.queue_migration_status(PropolisMigrateStatus {
100-
migration_id,
101-
state: propolis_client::types::MigrationState::Finish,
102-
});
103-
104-
// The state we transition to after the migration completes will depend
105-
// on whether we are the source or destination.
96+
10697
match role {
98+
MigrationRole::Source => {
99+
self.queue_migration_update(PropolisMigrateResponse {
100+
migration_in: None,
101+
migration_out: Some(PropolisMigrationStatus {
102+
id: migration_id,
103+
state: propolis_client::types::MigrationState::Sync,
104+
}),
105+
});
106+
self.queue_migration_update(PropolisMigrateResponse {
107+
migration_in: None,
108+
migration_out: Some(PropolisMigrationStatus {
109+
id: migration_id,
110+
state: propolis_client::types::MigrationState::Finish,
111+
}),
112+
});
113+
self.queue_graceful_stop();
114+
}
107115
MigrationRole::Target => {
116+
self.queue_migration_update(PropolisMigrateResponse {
117+
migration_in: Some(PropolisMigrationStatus {
118+
id: migration_id,
119+
state: propolis_client::types::MigrationState::Sync,
120+
}),
121+
migration_out: None,
122+
});
123+
self.queue_migration_update(PropolisMigrateResponse {
124+
migration_in: Some(PropolisMigrationStatus {
125+
id: migration_id,
126+
state: propolis_client::types::MigrationState::Finish,
127+
}),
128+
migration_out: None,
129+
});
108130
self.queue_propolis_state(PropolisInstanceState::Running)
109131
}
110-
MigrationRole::Source => self.queue_graceful_stop(),
111132
}
112133
}
113134

@@ -252,12 +273,12 @@ impl SimInstanceInner {
252273
self.last_response.state = state;
253274
}
254275
MonitorChange::MigrateStatus(status) => {
255-
self.last_response.migration = Some(status);
276+
self.last_response.migration = status;
256277
}
257278
}
258279

259280
self.state.apply_propolis_observation(&ObservedPropolisState::new(
260-
&self.state.instance(),
281+
self.state.instance(),
261282
&self.last_response,
262283
))
263284
} else {
@@ -450,7 +471,10 @@ impl Simulatable for SimInstance {
450471
last_response: InstanceStateMonitorResponse {
451472
gen: 1,
452473
state: PropolisInstanceState::Starting,
453-
migration: None,
474+
migration: PropolisMigrateResponse {
475+
migration_in: None,
476+
migration_out: None,
477+
},
454478
},
455479
queue: VecDeque::new(),
456480
destroyed: false,

0 commit comments

Comments
 (0)