omni_orchestrator/schemas/v1/api/
storage.rs

1use crate::schemas::v1::db::queries::storage;
2use rocket::http::Status;
3use rocket::serde::json::{json, Json, Value};
4use rocket::{get, State};
5use sqlx::MySql;
6
7/// Query parameters for storage class listing
8#[derive(FromForm, Default, Debug)]
9pub struct StorageClassQuery {
10    pub storage_type: Option<String>,
11    pub volume_binding_mode: Option<String>,
12    pub allow_volume_expansion: Option<bool>,
13}
14
15/// Query parameters for storage volume listing
16#[derive(FromForm, Default, Debug)]
17pub struct StorageVolumeQuery {
18    pub app_id: Option<i64>,
19    pub storage_class_id: Option<i64>,
20    pub status: Option<String>,
21    pub node_id: Option<i64>,
22    pub persistence_level: Option<String>,
23    pub write_concern: Option<String>,
24    pub page: Option<i64>,
25    pub per_page: Option<i64>,
26}
27
28/// List all storage classes with optional filtering
29#[get("/storage/classes?<query..>")]
30pub async fn list_storage_classes(
31    pool: &State<sqlx::Pool<MySql>>,
32    query: StorageClassQuery,
33) -> Json<Value> {
34    let filter = storage::StorageClassFilter {
35        storage_type: query.storage_type,
36        volume_binding_mode: query.volume_binding_mode,
37        allow_volume_expansion: query.allow_volume_expansion,
38    };
39    
40    let storage_classes = storage::list_storage_classes(pool, filter)
41        .await
42        .expect("Failed to list storage classes");
43    
44    Json(json!({
45        "storage_classes": storage_classes
46    }))
47}
48
49/// Get a specific storage class by ID
50#[get("/storage/classes/<id>")]
51pub async fn get_storage_class(
52    pool: &State<sqlx::Pool<MySql>>,
53    id: i64,
54) -> Result<Json<Value>, Status> {
55    let storage_class = storage::get_storage_class_by_id(pool, id)
56        .await
57        .expect("Database error")
58        .ok_or(Status::NotFound)?;
59    
60    Ok(Json(json!({
61        "storage_class": storage_class
62    })))
63}
64
65/// List storage volumes with comprehensive filtering
66#[get("/storage/volumes?<query..>")]
67pub async fn list_storage_volumes(
68    pool: &State<sqlx::Pool<MySql>>,
69    query: StorageVolumeQuery,
70) -> Json<Value> {
71    let page = query.page.unwrap_or(0);
72    let per_page = query.per_page.unwrap_or(10);
73    
74    let filter = storage::StorageVolumeFilter {
75        app_id: query.app_id,
76        storage_class_id: query.storage_class_id,
77        status: query.status,
78        node_id: query.node_id,
79        persistence_level: query.persistence_level,
80        write_concern: query.write_concern,
81    };
82    
83    let storage_volumes = storage::list_storage_volumes(pool, filter.clone(), page, per_page)
84        .await
85        .expect("Failed to list storage volumes");
86    
87    let total_count = storage::count_storage_volumes_with_filter(pool, &filter)
88        .await
89        .expect("Failed to get total count of storage volumes");
90    
91    let total_pages = (total_count as f64 / per_page as f64).ceil() as i64;
92    
93    Json(json!({
94        "storage_volumes": storage_volumes,
95        "pagination": {
96            "page": page,
97            "per_page": per_page,
98            "total_count": total_count,
99            "total_pages": total_pages
100        }
101    }))
102}
103
104/// Get volumes by storage class
105#[get("/storage/classes/<id>/volumes?<page>&<per_page>")]
106pub async fn get_volumes_by_storage_class(
107    pool: &State<sqlx::Pool<MySql>>,
108    id: i64,
109    page: Option<i64>,
110    per_page: Option<i64>,
111) -> Result<Json<Value>, Status> {
112    // First check if storage class exists
113    storage::get_storage_class_by_id(pool, id)
114        .await
115        .expect("Database error")
116        .ok_or(Status::NotFound)?;
117    
118    let page = page.unwrap_or(0);
119    let per_page = per_page.unwrap_or(10);
120    
121    let volumes = storage::get_volumes_by_storage_class(pool, id, page, per_page)
122        .await
123        .expect("Failed to fetch volumes by storage class");
124    
125    let filter = storage::StorageVolumeFilter {
126        storage_class_id: Some(id),
127        ..Default::default()
128    };
129    
130    let total_count = storage::count_storage_volumes_with_filter(pool, &filter)
131        .await
132        .expect("Failed to count volumes");
133    
134    let total_pages = (total_count as f64 / per_page as f64).ceil() as i64;
135    
136    Ok(Json(json!({
137        "volumes": volumes,
138        "pagination": {
139            "page": page,
140            "per_page": per_page,
141            "total_count": total_count,
142            "total_pages": total_pages
143        }
144    })))
145}
146
147/// Get QoS policies
148#[get("/storage/qos-policies")]
149pub async fn list_qos_policies(
150    pool: &State<sqlx::Pool<MySql>>,
151) -> Json<Value> {
152    let policies = storage::list_storage_qos_policies(pool)
153        .await
154        .expect("Failed to fetch QoS policies");
155    
156    Json(json!({
157        "qos_policies": policies
158    }))
159}
160
161/// List volumes by write concern level
162#[get("/storage/write-concerns/<write_concern>/volumes?<page>&<per_page>")]
163pub async fn list_volumes_by_write_concern(
164    pool: &State<sqlx::Pool<MySql>>,
165    write_concern: String,
166    page: Option<i64>,
167    per_page: Option<i64>,
168) -> Json<Value> {
169    let page = page.unwrap_or(0);
170    let per_page = per_page.unwrap_or(10);
171    
172    let volumes = storage::get_volumes_by_write_concern(pool, write_concern.clone(), page, per_page)
173        .await
174        .expect("Failed to fetch volumes by write concern");
175    
176    let filter = storage::StorageVolumeFilter {
177        write_concern: Some(write_concern),
178        ..Default::default()
179    };
180    
181    let total_count = storage::count_storage_volumes_with_filter(pool, &filter)
182        .await
183        .expect("Failed to count volumes");
184    
185    let total_pages = (total_count as f64 / per_page as f64).ceil() as i64;
186    
187    Json(json!({
188        "volumes": volumes,
189        "pagination": {
190            "page": page,
191            "per_page": per_page,
192            "total_count": total_count,
193            "total_pages": total_pages
194        }
195    }))
196}
197
198/// List volumes by persistence level
199#[get("/storage/persistence-levels/<persistence_level>/volumes?<page>&<per_page>")]
200pub async fn list_volumes_by_persistence_level(
201    pool: &State<sqlx::Pool<MySql>>,
202    persistence_level: String,
203    page: Option<i64>,
204    per_page: Option<i64>,
205) -> Json<Value> {
206    let page = page.unwrap_or(0);
207    let per_page = per_page.unwrap_or(10);
208    
209    let volumes = storage::get_volumes_by_persistence_level(pool, persistence_level.clone(), page, per_page)
210        .await
211        .expect("Failed to fetch volumes by persistence level");
212    
213    let filter = storage::StorageVolumeFilter {
214        persistence_level: Some(persistence_level),
215        ..Default::default()
216    };
217    
218    let total_count = storage::count_storage_volumes_with_filter(pool, &filter)
219        .await
220        .expect("Failed to count volumes");
221    
222    let total_pages = (total_count as f64 / per_page as f64).ceil() as i64;
223    
224    Json(json!({
225        "volumes": volumes,
226        "pagination": {
227            "page": page,
228            "per_page": per_page,
229            "total_count": total_count,
230            "total_pages": total_pages
231        }
232    }))
233}
234
235/// Get storage volumes for a specific region, grouped by region, with pagination
236#[get("/storage/regions/<region_id>/volumes?<page>&<per_page>")]
237pub async fn get_volumes_for_region_route(
238    pool: &State<sqlx::Pool<MySql>>,
239    region_id: i64,
240    page: Option<i64>,
241    per_page: Option<i64>,
242) -> Result<Json<Value>, Status> {
243    let page = page.unwrap_or(0);
244    let per_page = per_page.unwrap_or(10);
245
246    let region_volumes = storage::get_volumes_for_region(pool, region_id, page, per_page)
247        .await
248        .map_err(|_| Status::InternalServerError)?;
249
250    let total_count = storage::count_volumes_for_region(pool, region_id)
251        .await
252        .map_err(|_| Status::InternalServerError)?;
253
254    let total_pages = (total_count as f64 / per_page as f64).ceil() as i64;
255
256    Ok(Json(json!({
257        "region": region_volumes.region,
258        "volumes": region_volumes.volumes,
259        "pagination": {
260            "page": page,
261            "per_page": per_page,
262            "total_count": total_count,
263            "total_pages": total_pages
264        }
265    })))
266}
267
268/// Get storage volumes for a specific provider, with pagination
269#[get("/storage/providers/<provider_id>/volumes?<page>&<per_page>")]
270pub async fn get_storage_volumes_for_provider(
271    pool: &State<sqlx::Pool<MySql>>,
272    provider_id: i64,
273    page: Option<i64>,
274    per_page: Option<i64>,
275) -> Result<Json<Value>, Status> {
276    let page = page.unwrap_or(0);
277    let per_page = per_page.unwrap_or(10);
278
279    let volumes = storage::get_volumes_for_provider(pool, provider_id, page, per_page)
280        .await
281        .map_err(|_| Status::InternalServerError)?;
282
283    let total_count = storage::count_volumes_for_provider(pool, provider_id)
284        .await
285        .map_err(|_| Status::InternalServerError)?;
286
287    let total_pages = (total_count as f64 / per_page as f64).ceil() as i64;
288
289    Ok(Json(json!({
290        "provider_id": provider_id,
291        "volumes": volumes,
292        "pagination": {
293            "page": page,
294            "per_page": per_page,
295            "total_count": total_count,
296            "total_pages": total_pages
297        }
298    })))
299}