Skip to content

Commit

Permalink
Merge pull request #163 from LRZ-BADW/server-cost
Browse files Browse the repository at this point in the history
Server Cost Endpoint
  • Loading branch information
gierens authored Feb 5, 2025
2 parents 68f5b19 + 6dd18d6 commit 5ebda2a
Show file tree
Hide file tree
Showing 28 changed files with 1,248 additions and 122 deletions.
5 changes: 5 additions & 0 deletions .spellcheck.dic
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,8 @@ user_budget_modify
{user_budget_id}
select_project_budgets_by_project_from_db
_not_found
Params
inits
server_consumption
server_cost
parallelize

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

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

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

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

30 changes: 30 additions & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ jzon = "0.12"
lrzcc-wire = { version = "1.5", path = "../wire" }
thiserror = "2.0"
chrono = { version = "0.4", features = ["serde"] }
strum = { version = "0.26", features = ["derive"] }
indexmap = "2.7"

[dependencies.sqlx]
version = "0.8"
Expand Down
22 changes: 22 additions & 0 deletions api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,25 @@
Partial Rust-rewrite of the API server application for the Openstack-based
LRZ Compute Cloud, [https://cc.lrz.de](https://cc.lrz.de), first and foremost the budgeting
system.

## Development

### Running the API server locally
```bash
scripts/init.sh
source admin-openrc.sh
source scripts/config_env.sh

# optional: insert database dump
scripts/enter_db.sh
source lrz_budgeting.sql
quit

RUST_LOG=info cargo run --bin lrzcc-api | bunyan
```

### Calling the local API server
```bash
source admin-openrc.sh
cargo run --bin lrzcc -- -u http://localhost:8000/api -r http://localhost:8000/api user me
```
40 changes: 40 additions & 0 deletions api/src/database/accounting/server_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,46 @@ pub async fn select_server_states_by_server_from_db(
Ok(rows)
}

#[tracing::instrument(
name = "select_user_class_by_server_from_db",
skip(transaction)
)]
pub async fn select_user_class_by_server_from_db(
transaction: &mut Transaction<'_, MySql>,
server_id: String,
) -> Result<Option<u64>, UnexpectedOnlyError> {
#[derive(FromRow)]
struct Row {
user_class: u64,
}
let query = sqlx::query!(
r#"
SELECT
p.user_class as user_class
FROM
accounting_serverstate as ss,
user_user as u,
user_project as p
WHERE
ss.user_id = u.id AND
u.project_id = p.id AND
ss.instance_id = ?
LIMIT 1
"#,
server_id
);
let user_class = transaction
.fetch_optional(query)
.await
.context("Failed to execute select query")?
.map(|r| {
Row::from_row(&r).context("Failed to convert row to user class")
})
.map_or(Ok(None), |r| r.map(Some))?
.map(|r| r.user_class);
Ok(user_class)
}

#[tracing::instrument(
name = "select_server_states_by_server_and_project_from_db",
skip(transaction)
Expand Down
50 changes: 50 additions & 0 deletions api/src/database/pricing/flavor_price.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ use sqlx::{Executor, FromRow, MySql, Transaction};

#[derive(FromRow)]
pub struct FlavorPriceRow {
#[sqlx(try_from = "i32")]
pub id: u32,
#[sqlx(try_from = "i32")]
pub flavor: u32,
pub flavor_name: String,
pub user_class: u32,
Expand Down Expand Up @@ -117,6 +119,54 @@ pub async fn select_all_flavor_prices_from_db(
Ok(rows)
}

#[tracing::instrument(
name = "select_flavor_prices_for_period_from_db",
skip(transaction)
)]
pub async fn select_flavor_prices_for_period_from_db(
transaction: &mut Transaction<'_, MySql>,
begin: DateTime<Utc>,
end: DateTime<Utc>,
) -> Result<Vec<FlavorPrice>, UnexpectedOnlyError> {
let query = sqlx::query!(
r#"
SELECT
p.id,
p.flavor_id as flavor,
f.name as flavor_name,
p.user_class as user_class,
p.unit_price as unit_price,
p.start_time as start_time
FROM
pricing_flavorprice as p,
resources_flavor as f
WHERE
p.flavor_id = f.id AND
p.start_time <= ?
"#,
end,
);
let rows = transaction
.fetch_all(query)
.await
.context("Failed to execute select query")?
.into_iter()
.map(|r| FlavorPriceRow::from_row(&r))
.collect::<Result<Vec<_>, _>>()
.context("Failed to convert row to flavor price")?
.into_iter()
.map(|row| FlavorPrice {
id: row.id,
flavor: row.flavor,
flavor_name: row.flavor_name,
user_class: row.user_class,
unit_price: row.unit_price,
start_time: row.start_time.fixed_offset(),
})
.collect();
Ok(rows)
}

pub struct NewFlavorPrice {
pub flavor_id: u64,
pub user_class: u32,
Expand Down
Loading

0 comments on commit 5ebda2a

Please sign in to comment.