Skip to content

Commit

Permalink
plumb probes into API and DB
Browse files Browse the repository at this point in the history
  • Loading branch information
rcgoodfellow committed Nov 30, 2023
1 parent a04f5e3 commit 1aa5cfd
Show file tree
Hide file tree
Showing 17 changed files with 755 additions and 4 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

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

9 changes: 9 additions & 0 deletions common/src/api/external/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2604,6 +2604,15 @@ pub struct BgpImportedRouteIpv4 {
pub switch: SwitchLocation,
}

#[derive(
Clone, Debug, Deserialize, JsonSchema, Serialize, PartialEq, ObjectIdentity,
)]
pub struct Probe {
#[serde(flatten)]
pub identity: IdentityMetadata,
pub sled: Uuid,
}

#[cfg(test)]
mod test {
use serde::Deserialize;
Expand Down
2 changes: 2 additions & 0 deletions nexus/db-model/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ mod network_interface;
mod oximeter_info;
mod physical_disk;
mod physical_disk_kind;
mod probe;
mod producer_endpoint;
mod project;
mod semver_version;
Expand Down Expand Up @@ -137,6 +138,7 @@ pub use network_interface::*;
pub use oximeter_info::*;
pub use physical_disk::*;
pub use physical_disk_kind::*;
pub use probe::*;
pub use producer_endpoint::*;
pub use project::*;
pub use rack::*;
Expand Down
48 changes: 48 additions & 0 deletions nexus/db-model/src/probe.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use crate::schema::probe;
use db_macros::Resource;
use nexus_types::external_api::params;
use nexus_types::identity::Resource;
use omicron_common::api::external;
use omicron_common::api::external::IdentityMetadataCreateParams;
use serde::Deserialize;
use serde::Serialize;
use uuid::Uuid;

#[derive(
Queryable,
Insertable,
Selectable,
Clone,
Debug,
Resource,
Serialize,
Deserialize,
)]
#[diesel(table_name = probe)]
pub struct Probe {
#[diesel(embed)]
pub identity: ProbeIdentity,

pub sled: Uuid,
}

impl From<&params::ProbeCreate> for Probe {
fn from(p: &params::ProbeCreate) -> Self {
Self {
identity: ProbeIdentity::new(
Uuid::new_v4(),
IdentityMetadataCreateParams {
name: p.identity.name.clone(),
description: p.identity.description.clone(),
},
),
sled: p.sled,
}
}
}

impl Into<external::Probe> for Probe {
fn into(self) -> external::Probe {
external::Probe { identity: self.identity().clone(), sled: self.sled }
}
}
14 changes: 13 additions & 1 deletion nexus/db-model/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1296,12 +1296,24 @@ table! {
}
}

table! {
probe (id) {
id -> Uuid,
name -> Text,
description -> Text,
time_created -> Timestamptz,
time_modified -> Timestamptz,
time_deleted -> Nullable<Timestamptz>,
sled -> Uuid,
}
}

/// The version of the database schema this particular version of Nexus was
/// built against.
///
/// This should be updated whenever the schema is changed. For more details,
/// refer to: schema/crdb/README.adoc
pub const SCHEMA_VERSION: SemverVersion = SemverVersion::new(17, 0, 0);
pub const SCHEMA_VERSION: SemverVersion = SemverVersion::new(18, 0, 0);

allow_tables_to_appear_in_same_query!(
system_update,
Expand Down
1 change: 1 addition & 0 deletions nexus/db-queries/src/db/datastore/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ mod ipv4_nat_entry;
mod network_interface;
mod oximeter;
mod physical_disk;
mod probe;
mod project;
mod rack;
mod region;
Expand Down
135 changes: 135 additions & 0 deletions nexus/db-queries/src/db/datastore/probe.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
use crate::context::OpContext;
use crate::db;
use crate::db::error::public_error_from_diesel;
use crate::db::error::ErrorHandler;
use crate::db::model::Name;
use crate::db::pagination::paginated;
use async_bb8_diesel::AsyncRunQueryDsl;
use chrono::Utc;
use diesel::{ExpressionMethods, QueryDsl, SelectableHelper};
use nexus_db_model::Probe;
use nexus_types::external_api::params;
use omicron_common::api::external::http_pagination::PaginatedBy;
use omicron_common::api::external::CreateResult;
use omicron_common::api::external::DeleteResult;
use omicron_common::api::external::ListResultVec;
use omicron_common::api::external::LookupResult;
use omicron_common::api::external::NameOrId;
use ref_cast::RefCast;
use uuid::Uuid;

impl super::DataStore {
pub async fn probe_list(
&self,
opctx: &OpContext,
pagparams: &PaginatedBy<'_>,
) -> ListResultVec<Probe> {
use db::schema::probe::dsl;

let pool = self.pool_connection_authorized(opctx).await?;

match pagparams {
PaginatedBy::Id(pagparams) => {
paginated(dsl::probe, dsl::id, &pagparams)
}
PaginatedBy::Name(pagparams) => paginated(
dsl::probe,
dsl::name,
&pagparams.map_name(|n| Name::ref_cast(n)),
),
}
.filter(dsl::time_deleted.is_null())
.select(Probe::as_select())
.load_async(&*pool)
.await
.map_err(|e| public_error_from_diesel(e, ErrorHandler::Server))
}

pub async fn probe_get(
&self,
opctx: &OpContext,
name_or_id: &NameOrId,
) -> LookupResult<Probe> {
use db::schema::probe;
use db::schema::probe::dsl;
let pool = self.pool_connection_authorized(opctx).await?;

let name_or_id = name_or_id.clone();

let probe = match name_or_id {
NameOrId::Name(name) => dsl::probe
.filter(probe::name.eq(name.to_string()))
.filter(probe::time_deleted.is_null())
.select(Probe::as_select())
.limit(1)
.first_async::<Probe>(&*pool)
.await
.map_err(|e| public_error_from_diesel(e, ErrorHandler::Server)),
NameOrId::Id(id) => dsl::probe
.filter(probe::id.eq(id))
.select(Probe::as_select())
.limit(1)
.first_async::<Probe>(&*pool)
.await
.map_err(|e| public_error_from_diesel(e, ErrorHandler::Server)),
}?;

Ok(probe)
}

pub async fn probe_create(
&self,
opctx: &OpContext,
new_probe: &params::ProbeCreate,
) -> CreateResult<Probe> {
use db::schema::probe::dsl;
let pool = self.pool_connection_authorized(opctx).await?;

let probe = Probe::from(new_probe);

let result = diesel::insert_into(dsl::probe)
.values(probe.clone())
.returning(Probe::as_returning())
.get_result_async(&*pool)
.await
.map_err(|e| public_error_from_diesel(e, ErrorHandler::Server))?;

Ok(result)
}

pub async fn probe_delete(
&self,
opctx: &OpContext,
name_or_id: &NameOrId,
) -> DeleteResult {
use db::schema::probe;
use db::schema::probe::dsl;
let pool = self.pool_connection_authorized(opctx).await?;

let name_or_id = name_or_id.clone();

//TODO in transaction
let id = match name_or_id {
NameOrId::Name(name) => dsl::probe
.filter(probe::name.eq(name.to_string()))
.filter(probe::time_deleted.is_null())
.select(probe::id)
.limit(1)
.first_async::<Uuid>(&*pool)
.await
.map_err(|e| {
public_error_from_diesel(e, ErrorHandler::Server)
})?,
NameOrId::Id(id) => id,
};

diesel::update(dsl::probe)
.filter(dsl::id.eq(id))
.set(dsl::time_deleted.eq(Utc::now()))
.execute_async(&*pool)
.await
.map_err(|e| public_error_from_diesel(e, ErrorHandler::Server))?;

Ok(())
}
}
1 change: 1 addition & 0 deletions nexus/src/app/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ mod ip_pool;
mod metrics;
mod network_interface;
mod oximeter;
mod probe;
mod project;
mod rack;
pub(crate) mod saga;
Expand Down
41 changes: 41 additions & 0 deletions nexus/src/app/probe.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use nexus_db_model::Probe;
use nexus_db_queries::context::OpContext;
use nexus_types::external_api::params;
use omicron_common::api::external::{
http_pagination::PaginatedBy, CreateResult, DeleteResult, ListResultVec,
LookupResult, NameOrId,
};

impl super::Nexus {
pub(crate) async fn probe_list(
&self,
opctx: &OpContext,
pagparams: &PaginatedBy<'_>,
) -> ListResultVec<Probe> {
self.db_datastore.probe_list(opctx, pagparams).await
}

pub(crate) async fn probe_get(
&self,
opctx: &OpContext,
name_or_id: NameOrId,
) -> LookupResult<Probe> {
self.db_datastore.probe_get(opctx, &name_or_id).await
}

pub(crate) async fn probe_create(
&self,
opctx: &OpContext,
new_probe_params: &params::ProbeCreate,
) -> CreateResult<Probe> {
self.db_datastore.probe_create(opctx, new_probe_params).await
}

pub(crate) async fn probe_delete(
&self,
opctx: &OpContext,
name_or_id: NameOrId,
) -> DeleteResult {
self.db_datastore.probe_delete(opctx, &name_or_id).await
}
}
Loading

0 comments on commit 1aa5cfd

Please sign in to comment.