Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 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 common/src/api/external/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3571,7 +3571,7 @@ pub enum ImportExportPolicy {
/// will fail to parse if the key is not present. The JSON Schema in the
/// OpenAPI definition will also reflect that the field is required. See
/// <https://github.com/serde-rs/serde/issues/2753>.
#[derive(Clone, Debug, Serialize)]
#[derive(Clone, Debug, Serialize, PartialEq, Eq)]
pub struct Nullable<T>(pub Option<T>);

impl<T> From<Option<T>> for Nullable<T> {
Expand Down
12 changes: 0 additions & 12 deletions nexus/db-model/src/target_release.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use super::{Generation, impl_enum_type};
use crate::typed_uuid::DbTypedUuid;
use chrono::{DateTime, Utc};
use nexus_db_schema::schema::target_release;
use nexus_types::external_api::views;
use omicron_uuid_kinds::TufRepoKind;

impl_enum_type!(
Expand Down Expand Up @@ -60,15 +59,4 @@ impl TargetRelease {
tuf_repo_id: Some(tuf_repo_id),
}
}

pub fn into_external(
&self,
release_source: views::TargetReleaseSource,
) -> views::TargetRelease {
views::TargetRelease {
generation: (&self.generation.0).into(),
time_requested: self.time_requested,
release_source,
}
}
}
48 changes: 1 addition & 47 deletions nexus/db-queries/src/db/datastore/target_release.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,14 @@
use super::DataStore;
use crate::authz;
use crate::context::OpContext;
use crate::db::model::{
Generation, SemverVersion, TargetRelease, TargetReleaseSource,
};
use crate::db::model::{Generation, TargetRelease};
use async_bb8_diesel::AsyncRunQueryDsl as _;
use diesel::insert_into;
use diesel::prelude::*;
use diesel::sql_types;
use nexus_db_errors::{ErrorHandler, public_error_from_diesel};
use nexus_db_schema::enums::TargetReleaseSourceEnum;
use nexus_db_schema::schema::target_release::dsl;
use nexus_types::external_api::views;
use omicron_common::api::external::{CreateResult, Error, LookupResult};
use omicron_uuid_kinds::TufRepoUuid;
use std::collections::BTreeSet;
Expand Down Expand Up @@ -181,49 +178,6 @@ impl DataStore {
}
}

/// Convert a model-level target release to an external view.
/// This method lives here because we have to look up the version
/// corresponding to the TUF repo.
pub async fn target_release_view(
&self,
opctx: &OpContext,
target_release: &TargetRelease,
) -> LookupResult<views::TargetRelease> {
opctx
.authorize(authz::Action::Read, &authz::TARGET_RELEASE_CONFIG)
.await?;
let conn = self.pool_connection_authorized(opctx).await?;
let release_source = match target_release.release_source {
TargetReleaseSource::Unspecified => {
views::TargetReleaseSource::Unspecified
}
TargetReleaseSource::SystemVersion => {
use nexus_db_schema::schema::tuf_repo;
if let Some(tuf_repo_id) = target_release.tuf_repo_id {
views::TargetReleaseSource::SystemVersion {
version: tuf_repo::table
.select(tuf_repo::system_version)
.filter(tuf_repo::id.eq(tuf_repo_id))
.first_async::<SemverVersion>(&*conn)
.await
.map_err(|e| {
public_error_from_diesel(
e,
ErrorHandler::Server,
)
})?
.into(),
}
} else {
return Err(Error::internal_error(
"missing TUF repo ID for specified system version",
));
}
}
};
Ok(target_release.into_external(release_source))
}

/// Lists the most recent N distinct target releases
pub async fn target_release_fetch_recent_distinct(
&self,
Expand Down
26 changes: 24 additions & 2 deletions nexus/db-queries/src/db/datastore/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ use nexus_db_errors::OptionalError;
use nexus_db_errors::{ErrorHandler, public_error_from_diesel};
use nexus_db_lookup::DbConnection;
use nexus_db_model::{
ArtifactHash, TargetRelease, TufArtifact, TufRepo, TufRepoDescription,
TufTrustRoot, to_db_typed_uuid,
ArtifactHash, DbTypedUuid, TargetRelease, TufArtifact, TufRepo,
TufRepoDescription, TufTrustRoot, to_db_typed_uuid,
};
use omicron_common::api::external::{
self, CreateResult, DataPageParams, DeleteResult, Generation,
Expand Down Expand Up @@ -180,6 +180,28 @@ impl DataStore {
Ok(TufRepoDescription { repo, artifacts })
}

/// Given a TUF repo ID, get its version. We could use `tuf_repo_get_by_id`,
/// but that makes an additional query for the artifacts that we don't need
/// in the code that uses this method.
pub async fn tuf_repo_get_version(
&self,
opctx: &OpContext,
tuf_repo_id: &DbTypedUuid<TufRepoKind>,
) -> LookupResult<semver::Version> {
opctx
.authorize(authz::Action::Read, &authz::TARGET_RELEASE_CONFIG)
.await?;
let conn = self.pool_connection_authorized(opctx).await?;
use nexus_db_schema::schema::tuf_repo;
tuf_repo::table
.select(tuf_repo::system_version)
.filter(tuf_repo::id.eq(tuf_repo_id.into_untyped_uuid()))
.first_async::<SemverVersion>(&*conn)
.await
.map(|v| v.0)
.map_err(|e| public_error_from_diesel(e, ErrorHandler::Server))
}

/// Returns the list of all TUF repo artifacts known to the system.
pub async fn tuf_list_repos(
&self,
Expand Down
2 changes: 1 addition & 1 deletion nexus/external-api/output/nexus_tags.txt
Original file line number Diff line number Diff line change
Expand Up @@ -298,12 +298,12 @@ API operations found with tag "system/update"
OPERATION ID METHOD URL PATH
system_update_get_repository GET /v1/system/update/repository/{system_version}
system_update_put_repository PUT /v1/system/update/repository
system_update_status GET /v1/system/update/status
system_update_trust_root_create POST /v1/system/update/trust-roots
system_update_trust_root_delete DELETE /v1/system/update/trust-roots/{trust_root_id}
system_update_trust_root_list GET /v1/system/update/trust-roots
system_update_trust_root_view GET /v1/system/update/trust-roots/{trust_root_id}
target_release_update PUT /v1/system/update/target-release
target_release_view GET /v1/system/update/target-release

API operations found with tag "tokens"
OPERATION ID METHOD URL PATH
Expand Down
35 changes: 17 additions & 18 deletions nexus/external-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3041,36 +3041,35 @@ pub trait NexusExternalApi {
path_params: Path<params::TufTrustRootPath>,
) -> Result<HttpResponseDeleted, HttpError>;

/// Get the current target release of the rack's system software
/// Set target release
///
/// This may not correspond to the actual software running on the rack
/// at the time of request; it is instead the release that the rack
/// reconfigurator should be moving towards as a goal state. After some
/// number of planning and execution phases, the software running on the
/// rack should eventually correspond to the release described here.
/// Set the current target release of the rack's system software. The rack
/// reconfigurator will treat the software specified here as a goal state
/// for the rack's software, and attempt to asynchronously update to that
/// release. Use the update status endpoint to view the current target
/// release.
#[endpoint {
method = GET,
method = PUT,
path = "/v1/system/update/target-release",
tags = ["system/update"],
}]
async fn target_release_view(
async fn target_release_update(
rqctx: RequestContext<Self::Context>,
) -> Result<HttpResponseOk<views::TargetRelease>, HttpError>;
params: TypedBody<params::SetTargetReleaseParams>,
) -> Result<HttpResponseUpdatedNoContent, HttpError>;

/// Set the current target release of the rack's system software
/// Fetch system update status
///
/// The rack reconfigurator will treat the software specified here as
/// a goal state for the rack's software, and attempt to asynchronously
/// update to that release.
/// Returns information about the current target release and the
/// progress of system software updates.
#[endpoint {
method = PUT,
path = "/v1/system/update/target-release",
method = GET,
path = "/v1/system/update/status",
tags = ["system/update"],
}]
async fn target_release_update(
async fn system_update_status(
rqctx: RequestContext<Self::Context>,
params: TypedBody<params::SetTargetReleaseParams>,
) -> Result<HttpResponseCreated<views::TargetRelease>, HttpError>;
) -> Result<HttpResponseOk<views::UpdateStatus>, HttpError>;

// Silo users

Expand Down
6 changes: 6 additions & 0 deletions nexus/src/app/quiesce.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,12 @@ impl NexusQuiesceHandle {
self.state.borrow().clone()
}

pub fn latest_blueprint(
&self,
) -> Option<Arc<(BlueprintTarget, Blueprint)>> {
self.latest_blueprint.borrow().clone()
}

pub fn set_quiescing(&self, quiescing: bool) {
let new_state = if quiescing {
let time_requested = Utc::now();
Expand Down
Loading
Loading