Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
42 changes: 38 additions & 4 deletions mgmtd/src/bee_msg/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,10 +195,46 @@ async fn update_node(msg: RegisterNode, ctx: &Context) -> Result<NodeId> {
}
}

let new_alias_or_reg_token = String::from_utf8(msg.node_alias)?;

let (node, is_new) = if let Some(node) = node {
// Existing node, update data
db::node::update(tx, node.uid, msg.port, machine_uuid)?;

// If the updated node is a meta node, check if its corresponding target has a
// registration token
if msg.node_type == NodeType::Meta {
let stored_reg_token: Option<String> = tx.query_row(
sql!("SELECT reg_token FROM meta_targets WHERE node_id = ?1"),
[node.num_id()],
|row| row.get(0),
)?;

if let Some(ref t) = stored_reg_token
&& t != &new_alias_or_reg_token
{
bail!(
"Meta node {} has already been registered and its \
registration token ({}) does not match the stored token ({})",
node,
new_alias_or_reg_token,
t
);
} else if stored_reg_token.is_none() {
tx.execute(
sql!(
"UPDATE targets SET reg_token = ?1
WHERE node_id = ?2 AND node_type = ?3"
),
rusqlite::params![
new_alias_or_reg_token,
node.num_id(),
NodeType::Meta.sql_variant()
],
)?;
}
}

(node, false)
} else {
// New node, do additional checks and insert data
Expand All @@ -216,9 +252,7 @@ async fn update_node(msg: RegisterNode, ctx: &Context) -> Result<NodeId> {
// updated to no longer start with a number, thus it is unlikely this
// would happen unless BeeGFS 8 was mounted by a BeeGFS 7 client.

let new_alias = String::from_utf8(msg.node_alias)
.ok()
.and_then(|s| Alias::try_from(s).ok());
let new_alias = Alias::try_from(new_alias_or_reg_token.clone()).ok();

if new_alias.is_none() {
log::warn!(
Expand Down Expand Up @@ -246,7 +280,7 @@ client version < 8.0)"
);
};

db::target::insert_meta(tx, target_id, None)?;
db::target::insert_meta(tx, target_id, Some(&new_alias_or_reg_token))?;
}

(node, true)
Expand Down
28 changes: 22 additions & 6 deletions mgmtd/src/bee_msg/target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,33 @@ impl HandleWithResponse for RegisterTarget {
let (id, is_new) = ctx
.db
.write_tx(move |tx| {
let reg_token = str::from_utf8(&self.reg_token)?;

// Do not do anything if the target already exists
if let Some(id) = try_resolve_num_id(
tx,
EntityType::Target,
NodeType::Storage,
self.target_id.into(),
)? {
let stored_reg_token: Option<String> = tx.query_row(
sql!(
"SELECT reg_token FROM targets
WHERE target_id = ?1 AND node_type = ?2"
),
rusqlite::params![id.num_id(), NodeType::Storage.sql_variant()],
|row| row.get(0),
)?;

if let Some(st) = stored_reg_token
&& st != reg_token
{
bail!(
"Storage target {id} has already been registered and its \
registration token ({reg_token}) does not match the stored token ({st})"
);
}

return Ok((id.num_id().try_into()?, false));
}

Expand All @@ -142,11 +162,7 @@ impl HandleWithResponse for RegisterTarget {
}

Ok((
db::target::insert_storage(
tx,
self.target_id,
Some(format!("target_{}", std::str::from_utf8(&self.alias)?).try_into()?),
)?,
db::target::insert_storage(tx, self.target_id, Some(reg_token))?,
true,
))
})
Expand All @@ -155,7 +171,7 @@ impl HandleWithResponse for RegisterTarget {
if is_new {
log::info!("Registered new storage target with Id {id}");
} else {
log::debug!("Re-registered existing storage target with Id {id}");
log::debug!("Re-registered existing storage target with Id {id}",);
}

Ok(RegisterTargetResp { id })
Expand Down
9 changes: 2 additions & 7 deletions mgmtd/src/db/import_v7.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,8 @@ fn meta_nodes(tx: &Transaction, f: &Path) -> Result<(NodeId, bool)> {
"{num_id} is not a valid numeric meta node/target id (must be between 1 and 65535)",
);
};
target::insert(
tx,
target_id,
None,
NodeTypeServer::Meta,
Some(target_id.into()),
)?;

target::insert_meta(tx, target_id, None)?;
}

if root_id == 0 {
Expand Down
1 change: 1 addition & 0 deletions mgmtd/src/db/schema/4.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE targets ADD COLUMN reg_token TEXT;
55 changes: 19 additions & 36 deletions mgmtd/src/db/target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,22 +40,18 @@ pub(crate) fn validate_ids(
pub(crate) fn insert_meta(
tx: &Transaction,
target_id: TargetId,
alias: Option<Alias>,
reg_token: Option<&str>,
) -> Result<()> {
let target_id = if target_id == 0 {
misc::find_new_id(tx, "targets", "target_id", NodeType::Meta, 1..=0xFFFF)?
} else if try_resolve_num_id(tx, EntityType::Target, NodeType::Meta, target_id.into())?
.is_some()
{
bail!(TypedError::value_exists("numeric target id", target_id));
} else {
target_id
};

insert(
tx,
target_id,
alias,
reg_token,
NodeTypeServer::Meta,
Some(target_id.into()),
)?;
Expand All @@ -78,45 +74,36 @@ pub(crate) fn insert_meta(
pub(crate) fn insert_storage(
tx: &Transaction,
target_id: TargetId,
alias: Option<Alias>,
reg_token: Option<&str>,
) -> Result<TargetId> {
let target_id = if target_id == 0 {
misc::find_new_id(tx, "targets", "target_id", NodeType::Storage, 1..=0xFFFF)?
} else if try_resolve_num_id(tx, EntityType::Target, NodeType::Storage, target_id.into())?
.is_some()
{
return Ok(target_id);
} else {
target_id
};

insert(tx, target_id, alias, NodeTypeServer::Storage, None)?;
insert(tx, target_id, reg_token, NodeTypeServer::Storage, None)?;

Ok(target_id)
}

pub(crate) fn insert(
fn insert(
tx: &Transaction,
target_id: TargetId,
alias: Option<Alias>,
reg_token: Option<&str>,
node_type: NodeTypeServer,
// This is optional because storage targets come "unmapped"
node_id: Option<NodeId>,
) -> Result<()> {
anyhow::ensure!(target_id > 0, "A target id must be > 0");

let alias = if let Some(alias) = alias {
alias
} else {
format!("target_{}_{}", node_type.user_str(), target_id).try_into()?
};

let alias = format!("target_{}_{target_id}", node_type.user_str()).try_into()?;
let new_uid = entity::insert(tx, EntityType::Target, &alias)?;

tx.execute(
sql!(
"INSERT INTO targets (target_uid, node_type, target_id, node_id, pool_id)
VALUES (?1, ?2, ?3, ?4, ?5)"
"INSERT INTO targets (target_uid, node_type, target_id, node_id, pool_id, reg_token)
VALUES (?1, ?2, ?3, ?4, ?5, ?6)"
),
params![
new_uid,
Expand All @@ -127,7 +114,8 @@ pub(crate) fn insert(
Some(1)
} else {
None
}
},
reg_token
],
)?;

Expand Down Expand Up @@ -287,11 +275,10 @@ mod test {
#[test]
fn set_get_meta() {
with_test_data(|tx| {
super::insert_meta(tx, 1, Some("existing_meta_target".try_into().unwrap()))
.unwrap_err();
super::insert_meta(tx, 99, Some("new_meta_target".try_into().unwrap())).unwrap();
// existing alias
super::insert_meta(tx, 99, Some("new_meta_target".try_into().unwrap())).unwrap_err();
super::insert_meta(tx, 1, None).unwrap_err();
super::insert_meta(tx, 99, None).unwrap();
// existing id
super::insert_meta(tx, 99, None).unwrap_err();

let targets: i64 = tx
.query_row(sql!("SELECT COUNT(*) FROM meta_targets"), [], |row| {
Expand All @@ -306,15 +293,11 @@ mod test {
#[test]
fn set_get_storage_and_map() {
with_test_data(|tx| {
let new_target_id =
super::insert_storage(tx, 0, Some("new_storage_target".try_into().unwrap()))
.unwrap();
super::insert_storage(tx, 1000, Some("new_storage_target_2".try_into().unwrap()))
.unwrap();
let new_target_id = super::insert_storage(tx, 0, Some("new_storage_target")).unwrap();
super::insert_storage(tx, 1000, Some("new_storage_target_2")).unwrap();

// existing alias
super::insert_storage(tx, 0, Some("new_storage_target".try_into().unwrap()))
.unwrap_err();
// existing id
super::insert_storage(tx, 1000, Some("new_storage_target")).unwrap_err();

super::update_storage_node_mappings(tx, &[new_target_id, 1000], 1).unwrap();

Expand Down
2 changes: 1 addition & 1 deletion shared/src/bee_msg/target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ impl Deserializable for TargetReachabilityState {
#[derive(Clone, Debug, Default, PartialEq, Eq, BeeSerde)]
pub struct RegisterTarget {
#[bee_serde(as = CStr<0>)]
pub alias: Vec<u8>,
pub reg_token: Vec<u8>,
pub target_id: TargetId,
}

Expand Down
Loading