-
Notifications
You must be signed in to change notification settings - Fork 40
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
[nexus] improve external messages and make more available to clients #4573
Changes from 1 commit
6598065
610b007
fde90d6
3ae14c7
bad2f38
c9098ce
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -48,17 +48,17 @@ pub fn from_diesel(e: DieselError) -> external::Error { | |
if let Some(sentinel) = matches_sentinel(&e, &sentinels) { | ||
match sentinel { | ||
NOT_ENOUGH_DATASETS_SENTINEL => { | ||
return external::Error::unavail( | ||
return external::Error::unavail_external( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This one feels like the sort of thing I would not expect an operator to know about, let alone an end user. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've turned this and the other two below into a generic "Not enough disk space" message. |
||
"Not enough datasets to allocate disks", | ||
); | ||
} | ||
NOT_ENOUGH_ZPOOL_SPACE_SENTINEL => { | ||
return external::Error::unavail( | ||
return external::Error::unavail_external( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This one feels like a mix. Some of this seems useful to an operator but much of it (terms like "zpool" and "region") describes implementation details that feel like a bad UX to expose to operators and end users. |
||
"Not enough zpool space to allocate disks. There may not be enough disks with space for the requested region. You may also see this if your rack is in a degraded state, or you're running the default multi-rack topology configuration in a 1-sled development environment.", | ||
); | ||
} | ||
NOT_ENOUGH_UNIQUE_ZPOOLS_SENTINEL => { | ||
return external::Error::unavail( | ||
return external::Error::unavail_external( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similarly this feels like a call generator more than it's helpful. (I'm imagining a customer wondering "What's a zpool? Do I need more physical disks? Is it somehow allocating something from an API |
||
"Not enough unique zpools selected while allocating disks", | ||
); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -737,7 +737,7 @@ fn endpoint_for_authority( | |
let endpoint_config = config_rx.borrow(); | ||
let endpoints = endpoint_config.as_ref().ok_or_else(|| { | ||
error!(&log, "received request with no endpoints loaded"); | ||
Error::unavail("endpoints not loaded") | ||
Error::unavail_external("endpoints not loaded") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This feels confusing and unactionable for end users. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Made this internal-only. |
||
})?; | ||
|
||
// See if there's an endpoint for the requested name. If so, use it. | ||
|
@@ -810,6 +810,7 @@ mod test { | |
use nexus_types::identity::Resource; | ||
use omicron_common::api::external::Error; | ||
use omicron_common::api::external::IdentityMetadataCreateParams; | ||
use omicron_common::api::external::MessageVariant; | ||
use schemars::JsonSchema; | ||
use serde::Deserialize; | ||
use serde::Serialize; | ||
|
@@ -1532,9 +1533,15 @@ mod test { | |
let result = | ||
endpoint_for_authority(&log, &authority, rx_channel); | ||
match result { | ||
Err(Error::ServiceUnavailable { internal_message }) => { | ||
Err(Error::ServiceUnavailable { message }) => { | ||
assert_eq!(rx_label, "none"); | ||
assert_eq!(internal_message, "endpoints not loaded"); | ||
assert_eq!( | ||
message, | ||
MessageVariant::External { | ||
message: "endpoints not loaded".to_owned(), | ||
internal_context: String::new(), | ||
} | ||
); | ||
} | ||
Err(Error::InvalidRequest { message }) => { | ||
assert_eq!(rx_label, "empty"); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -362,7 +362,9 @@ impl super::Nexus { | |
} | ||
|
||
if instance.runtime().migration_id.is_some() { | ||
return Err(Error::unavail("instance is already migrating")); | ||
return Err(Error::unavail_external( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This feels like a 409 and not a 503. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed, turned this into a 409. |
||
"instance is already migrating", | ||
)); | ||
} | ||
|
||
// Kick off the migration saga | ||
|
@@ -1583,28 +1585,26 @@ impl super::Nexus { | |
| InstanceState::Starting | ||
| InstanceState::Stopping | ||
| InstanceState::Stopped | ||
| InstanceState::Failed => Err(Error::ServiceUnavailable { | ||
internal_message: format!( | ||
"cannot connect to serial console of instance in state \ | ||
{:?}", | ||
vmm.runtime.state.0 | ||
), | ||
}), | ||
InstanceState::Destroyed => Err(Error::ServiceUnavailable { | ||
internal_message: format!( | ||
| InstanceState::Failed => { | ||
Err(Error::unavail_external(format!( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This feels like some kind of 400, not a 503. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Turned this into a 400 and cleaned up the message. |
||
"cannot connect to serial console of instance in state \ | ||
{:?}", | ||
vmm.runtime.state.0 | ||
))) | ||
} | ||
InstanceState::Destroyed => { | ||
Err(Error::unavail_external(format!( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same -- 400 or 409, I'd think. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 400 as well. |
||
"cannot connect to serial console of instance in state \ | ||
{:?}", | ||
InstanceState::Stopped), | ||
}), | ||
InstanceState::Stopped))) | ||
} | ||
} | ||
} else { | ||
Err(Error::ServiceUnavailable { | ||
internal_message: format!( | ||
"instance is in state {:?} and has no active serial console \ | ||
Err(Error::unavail_external(format!( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 400 as well. |
||
"instance is in state {:?} and has no active serial console \ | ||
server", | ||
instance.runtime().nexus_state | ||
) | ||
}) | ||
instance.runtime().nexus_state | ||
))) | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -390,8 +390,8 @@ impl super::Nexus { | |
limit: std::num::NonZeroU32::new(1).unwrap(), | ||
}; | ||
let oxs = self.db_datastore.oximeter_list(&page_params).await?; | ||
let info = oxs.first().ok_or_else(|| Error::ServiceUnavailable { | ||
internal_message: String::from("no oximeter collectors available"), | ||
let info = oxs.first().ok_or_else(|| { | ||
Error::unavail_external("no oximeter collectors available") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think this makes sense for an external user, though I suspect this is only produced in calls to the internal API. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Reverted this change. |
||
})?; | ||
let address = | ||
SocketAddr::from((info.ip.ip(), info.port.try_into().unwrap())); | ||
|
@@ -403,7 +403,8 @@ impl super::Nexus { | |
fn map_oximeter_err(error: oximeter_db::Error) -> Error { | ||
match error { | ||
oximeter_db::Error::DatabaseUnavailable(_) => { | ||
Error::ServiceUnavailable { internal_message: error.to_string() } | ||
// XXX: should this be unavail_external? | ||
Error::unavail_internal(error.to_string()) | ||
} | ||
_ => Error::InternalError { internal_message: error.to_string() }, | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I would move the
:
back to the message in theServiceUnavailable
variant on line 57, in part to keep all those variants uniform, and in part so that if we ever, say,display_internal
into a log line we don't get the leading colon. This is pretty nitpicky, though, and I don't feel especially strongly about it, especially if there's a reason to do the formatting here that I've totally overlooked.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed this significantly, and followed this approach in the new version.