omni_orchestrator/schemas/v1/api/
storage.rs

1use std::sync::Arc;
2use crate::DatabaseManager;
3use crate::schemas::v1::db::queries::storage;
4use rocket::http::Status;
5use rocket::serde::json::{json, Json, Value};
6use rocket::{get, State};
7use crate::schemas::v1::db::queries::{self as db};
8
9/// Query parameters for storage class listing
10#[derive(FromForm, Default, Debug)]
11pub struct StorageClassQuery {
12    pub storage_type: Option<String>,
13    pub volume_binding_mode: Option<String>,
14    pub allow_volume_expansion: Option<bool>,
15}
16
17/// Query parameters for storage volume listing
18#[derive(FromForm, Default, Debug)]
19pub struct StorageVolumeQuery {
20    pub app_id: Option<i64>,
21    pub storage_class_id: Option<i64>,
22    pub status: Option<String>,
23    pub node_id: Option<i64>,
24    pub persistence_level: Option<String>,
25    pub write_concern: Option<String>,
26    pub page: Option<i64>,
27    pub per_page: Option<i64>,
28}
29
30/// List all storage classes with optional filtering
31#[get("/platform/<platform_id>/storage/classes?<query..>")]
32pub async fn list_storage_classes(
33    platform_id: i64,
34    query: StorageClassQuery,
35    db_manager: &State<Arc<DatabaseManager>>,
36) -> Result<Json<Value>, (Status, Json<Value>)> {
37    // Get platform information
38    let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
39        Ok(platform) => platform,
40        Err(_) => {
41            return Err((
42                Status::NotFound,
43                Json(json!({
44                    "error": "Platform not found",
45                    "message": format!("Platform with ID {} does not exist", platform_id)
46                }))
47            ));
48        }
49    };
50
51    // Get platform-specific database pool
52    let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
53        Ok(pool) => pool,
54        Err(_) => {
55            return Err((
56                Status::InternalServerError,
57                Json(json!({
58                    "error": "Database error",
59                    "message": "Failed to connect to platform database"
60                }))
61            ));
62        }
63    };
64    
65    let filter = storage::StorageClassFilter {
66        storage_type: query.storage_type,
67        volume_binding_mode: query.volume_binding_mode,
68        allow_volume_expansion: query.allow_volume_expansion,
69    };
70    
71    match storage::list_storage_classes(&pool, filter).await {
72        Ok(storage_classes) => Ok(Json(json!({
73            "storage_classes": storage_classes
74        }))),
75        Err(_) => Err((
76            Status::InternalServerError,
77            Json(json!({
78                "error": "Database error",
79                "message": "Failed to list storage classes"
80            }))
81        )),
82    }
83}
84
85/// Get a specific storage class by ID
86#[get("/platform/<platform_id>/storage/classes/<id>")]
87pub async fn get_storage_class(
88    platform_id: i64,
89    id: i64,
90    db_manager: &State<Arc<DatabaseManager>>,
91) -> Result<Json<Value>, (Status, Json<Value>)> {
92    // Get platform information
93    let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
94        Ok(platform) => platform,
95        Err(_) => {
96            return Err((
97                Status::NotFound,
98                Json(json!({
99                    "error": "Platform not found",
100                    "message": format!("Platform with ID {} does not exist", platform_id)
101                }))
102            ));
103        }
104    };
105
106    // Get platform-specific database pool
107    let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
108        Ok(pool) => pool,
109        Err(_) => {
110            return Err((
111                Status::InternalServerError,
112                Json(json!({
113                    "error": "Database error",
114                    "message": "Failed to connect to platform database"
115                }))
116            ));
117        }
118    };
119    
120    match storage::get_storage_class_by_id(&pool, id).await {
121        Ok(Some(storage_class)) => Ok(Json(json!({
122            "storage_class": storage_class
123        }))),
124        Ok(None) => Err((
125            Status::NotFound,
126            Json(json!({
127                "error": "Not found",
128                "message": format!("Storage class with ID {} does not exist", id)
129            }))
130        )),
131        Err(_) => Err((
132            Status::InternalServerError,
133            Json(json!({
134                "error": "Database error",
135                "message": "Failed to get storage class"
136            }))
137        )),
138    }
139}
140
141/// List storage volumes with comprehensive filtering
142#[get("/platform/<platform_id>/storage/volumes?<query..>")]
143pub async fn list_storage_volumes(
144    platform_id: i64,
145    query: StorageVolumeQuery,
146    db_manager: &State<Arc<DatabaseManager>>,
147) -> Result<Json<Value>, (Status, Json<Value>)> {
148    // Get platform information
149    let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
150        Ok(platform) => platform,
151        Err(_) => {
152            return Err((
153                Status::NotFound,
154                Json(json!({
155                    "error": "Platform not found",
156                    "message": format!("Platform with ID {} does not exist", platform_id)
157                }))
158            ));
159        }
160    };
161
162    // Get platform-specific database pool
163    let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
164        Ok(pool) => pool,
165        Err(_) => {
166            return Err((
167                Status::InternalServerError,
168                Json(json!({
169                    "error": "Database error",
170                    "message": "Failed to connect to platform database"
171                }))
172            ));
173        }
174    };
175    
176    let page = query.page.unwrap_or(0);
177    let per_page = query.per_page.unwrap_or(10);
178    
179    let filter = storage::StorageVolumeFilter {
180        app_id: query.app_id,
181        storage_class_id: query.storage_class_id,
182        status: query.status,
183        node_id: query.node_id,
184        persistence_level: query.persistence_level,
185        write_concern: query.write_concern,
186    };
187    
188    let storage_volumes = match storage::list_storage_volumes(&pool, filter.clone(), page, per_page).await {
189        Ok(volumes) => volumes,
190        Err(_) => {
191            return Err((
192                Status::InternalServerError,
193                Json(json!({
194                    "error": "Database error",
195                    "message": "Failed to list storage volumes"
196                }))
197            ));
198        }
199    };
200    
201    let total_count = match storage::count_storage_volumes_with_filter(&pool, &filter).await {
202        Ok(count) => count,
203        Err(_) => {
204            return Err((
205                Status::InternalServerError,
206                Json(json!({
207                    "error": "Database error",
208                    "message": "Failed to count storage volumes"
209                }))
210            ));
211        }
212    };
213    
214    let total_pages = (total_count as f64 / per_page as f64).ceil() as i64;
215    
216    Ok(Json(json!({
217        "storage_volumes": storage_volumes,
218        "pagination": {
219            "page": page,
220            "per_page": per_page,
221            "total_count": total_count,
222            "total_pages": total_pages
223        }
224    })))
225}
226
227/// Get volumes by storage class
228#[get("/platform/<platform_id>/storage/classes/<id>/volumes?<page>&<per_page>")]
229pub async fn get_volumes_by_storage_class(
230    platform_id: i64,
231    id: i64,
232    page: Option<i64>,
233    per_page: Option<i64>,
234    db_manager: &State<Arc<DatabaseManager>>,
235) -> Result<Json<Value>, (Status, Json<Value>)> {
236    // Get platform information
237    let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
238        Ok(platform) => platform,
239        Err(_) => {
240            return Err((
241                Status::NotFound,
242                Json(json!({
243                    "error": "Platform not found",
244                    "message": format!("Platform with ID {} does not exist", platform_id)
245                }))
246            ));
247        }
248    };
249
250    // Get platform-specific database pool
251    let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
252        Ok(pool) => pool,
253        Err(_) => {
254            return Err((
255                Status::InternalServerError,
256                Json(json!({
257                    "error": "Database error",
258                    "message": "Failed to connect to platform database"
259                }))
260            ));
261        }
262    };
263    
264    // First check if storage class exists
265    match storage::get_storage_class_by_id(&pool, id).await {
266        Ok(Some(_)) => {},
267        Ok(None) => {
268            return Err((
269                Status::NotFound,
270                Json(json!({
271                    "error": "Not found",
272                    "message": format!("Storage class with ID {} does not exist", id)
273                }))
274            ));
275        },
276        Err(_) => {
277            return Err((
278                Status::InternalServerError,
279                Json(json!({
280                    "error": "Database error",
281                    "message": "Failed to verify storage class existence"
282                }))
283            ));
284        }
285    };
286    
287    let page = page.unwrap_or(0);
288    let per_page = per_page.unwrap_or(10);
289    
290    let volumes = match storage::get_volumes_by_storage_class(&pool, id, page, per_page).await {
291        Ok(volumes) => volumes,
292        Err(_) => {
293            return Err((
294                Status::InternalServerError,
295                Json(json!({
296                    "error": "Database error",
297                    "message": "Failed to fetch volumes by storage class"
298                }))
299            ));
300        }
301    };
302    
303    let filter = storage::StorageVolumeFilter {
304        storage_class_id: Some(id),
305        ..Default::default()
306    };
307    
308    let total_count = match storage::count_storage_volumes_with_filter(&pool, &filter).await {
309        Ok(count) => count,
310        Err(_) => {
311            return Err((
312                Status::InternalServerError,
313                Json(json!({
314                    "error": "Database error",
315                    "message": "Failed to count volumes"
316                }))
317            ));
318        }
319    };
320    
321    let total_pages = (total_count as f64 / per_page as f64).ceil() as i64;
322    
323    Ok(Json(json!({
324        "volumes": volumes,
325        "pagination": {
326            "page": page,
327            "per_page": per_page,
328            "total_count": total_count,
329            "total_pages": total_pages
330        }
331    })))
332}
333
334/// Get QoS policies
335#[get("/platform/<platform_id>/storage/qos-policies")]
336pub async fn list_qos_policies(
337    platform_id: i64,
338    db_manager: &State<Arc<DatabaseManager>>,
339) -> Result<Json<Value>, (Status, Json<Value>)> {
340    // Get platform information
341    let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
342        Ok(platform) => platform,
343        Err(_) => {
344            return Err((
345                Status::NotFound,
346                Json(json!({
347                    "error": "Platform not found",
348                    "message": format!("Platform with ID {} does not exist", platform_id)
349                }))
350            ));
351        }
352    };
353
354    // Get platform-specific database pool
355    let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
356        Ok(pool) => pool,
357        Err(_) => {
358            return Err((
359                Status::InternalServerError,
360                Json(json!({
361                    "error": "Database error",
362                    "message": "Failed to connect to platform database"
363                }))
364            ));
365        }
366    };
367    
368    match storage::list_storage_qos_policies(&pool).await {
369        Ok(policies) => Ok(Json(json!({
370            "qos_policies": policies
371        }))),
372        Err(_) => Err((
373            Status::InternalServerError,
374            Json(json!({
375                "error": "Database error",
376                "message": "Failed to fetch QoS policies"
377            }))
378        )),
379    }
380}
381
382/// List volumes by write concern level
383#[get("/platform/<platform_id>/storage/write-concerns/<write_concern>/volumes?<page>&<per_page>")]
384pub async fn list_volumes_by_write_concern(
385    platform_id: i64,
386    write_concern: String,
387    page: Option<i64>,
388    per_page: Option<i64>,
389    db_manager: &State<Arc<DatabaseManager>>,
390) -> Result<Json<Value>, (Status, Json<Value>)> {
391    // Get platform information
392    let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
393        Ok(platform) => platform,
394        Err(_) => {
395            return Err((
396                Status::NotFound,
397                Json(json!({
398                    "error": "Platform not found",
399                    "message": format!("Platform with ID {} does not exist", platform_id)
400                }))
401            ));
402        }
403    };
404
405    // Get platform-specific database pool
406    let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
407        Ok(pool) => pool,
408        Err(_) => {
409            return Err((
410                Status::InternalServerError,
411                Json(json!({
412                    "error": "Database error",
413                    "message": "Failed to connect to platform database"
414                }))
415            ));
416        }
417    };
418    
419    let page = page.unwrap_or(0);
420    let per_page = per_page.unwrap_or(10);
421    
422    let volumes = match storage::get_volumes_by_write_concern(&pool, write_concern.clone(), page, per_page).await {
423        Ok(volumes) => volumes,
424        Err(_) => {
425            return Err((
426                Status::InternalServerError,
427                Json(json!({
428                    "error": "Database error",
429                    "message": "Failed to fetch volumes by write concern"
430                }))
431            ));
432        }
433    };
434    
435    let filter = storage::StorageVolumeFilter {
436        write_concern: Some(write_concern),
437        ..Default::default()
438    };
439    
440    let total_count = match storage::count_storage_volumes_with_filter(&pool, &filter).await {
441        Ok(count) => count,
442        Err(_) => {
443            return Err((
444                Status::InternalServerError,
445                Json(json!({
446                    "error": "Database error",
447                    "message": "Failed to count volumes"
448                }))
449            ));
450        }
451    };
452    
453    let total_pages = (total_count as f64 / per_page as f64).ceil() as i64;
454    
455    Ok(Json(json!({
456        "volumes": volumes,
457        "pagination": {
458            "page": page,
459            "per_page": per_page,
460            "total_count": total_count,
461            "total_pages": total_pages
462        }
463    })))
464}
465
466/// List volumes by persistence level
467#[get("/platform/<platform_id>/storage/persistence-levels/<persistence_level>/volumes?<page>&<per_page>")]
468pub async fn list_volumes_by_persistence_level(
469    platform_id: i64,
470    persistence_level: String,
471    page: Option<i64>,
472    per_page: Option<i64>,
473    db_manager: &State<Arc<DatabaseManager>>,
474) -> Result<Json<Value>, (Status, Json<Value>)> {
475    // Get platform information
476    let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
477        Ok(platform) => platform,
478        Err(_) => {
479            return Err((
480                Status::NotFound,
481                Json(json!({
482                    "error": "Platform not found",
483                    "message": format!("Platform with ID {} does not exist", platform_id)
484                }))
485            ));
486        }
487    };
488
489    // Get platform-specific database pool
490    let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
491        Ok(pool) => pool,
492        Err(_) => {
493            return Err((
494                Status::InternalServerError,
495                Json(json!({
496                    "error": "Database error",
497                    "message": "Failed to connect to platform database"
498                }))
499            ));
500        }
501    };
502    
503    let page = page.unwrap_or(0);
504    let per_page = per_page.unwrap_or(10);
505    
506    let volumes = match storage::get_volumes_by_persistence_level(&pool, persistence_level.clone(), page, per_page).await {
507        Ok(volumes) => volumes,
508        Err(_) => {
509            return Err((
510                Status::InternalServerError,
511                Json(json!({
512                    "error": "Database error",
513                    "message": "Failed to fetch volumes by persistence level"
514                }))
515            ));
516        }
517    };
518    
519    let filter = storage::StorageVolumeFilter {
520        persistence_level: Some(persistence_level),
521        ..Default::default()
522    };
523    
524    let total_count = match storage::count_storage_volumes_with_filter(&pool, &filter).await {
525        Ok(count) => count,
526        Err(_) => {
527            return Err((
528                Status::InternalServerError,
529                Json(json!({
530                    "error": "Database error",
531                    "message": "Failed to count volumes"
532                }))
533            ));
534        }
535    };
536    
537    let total_pages = (total_count as f64 / per_page as f64).ceil() as i64;
538    
539    Ok(Json(json!({
540        "volumes": volumes,
541        "pagination": {
542            "page": page,
543            "per_page": per_page,
544            "total_count": total_count,
545            "total_pages": total_pages
546        }
547    })))
548}
549
550/// Get storage volumes for a specific region, grouped by region, with pagination
551#[get("/platform/<platform_id>/storage/regions/<region_id>/volumes?<page>&<per_page>")]
552pub async fn get_volumes_for_region_route(
553    platform_id: i64,
554    region_id: i64,
555    page: Option<i64>,
556    per_page: Option<i64>,
557    db_manager: &State<Arc<DatabaseManager>>,
558) -> Result<Json<Value>, (Status, Json<Value>)> {
559    // Get platform information
560    let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
561        Ok(platform) => platform,
562        Err(_) => {
563            return Err((
564                Status::NotFound,
565                Json(json!({
566                    "error": "Platform not found",
567                    "message": format!("Platform with ID {} does not exist", platform_id)
568                }))
569            ));
570        }
571    };
572
573    // Get platform-specific database pool
574    let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
575        Ok(pool) => pool,
576        Err(_) => {
577            return Err((
578                Status::InternalServerError,
579                Json(json!({
580                    "error": "Database error",
581                    "message": "Failed to connect to platform database"
582                }))
583            ));
584        }
585    };
586    
587    let page = page.unwrap_or(0);
588    let per_page = per_page.unwrap_or(10);
589
590    let region_volumes = match storage::get_volumes_for_region(&pool, region_id, page, per_page).await {
591        Ok(volumes) => volumes,
592        Err(_) => {
593            return Err((
594                Status::InternalServerError,
595                Json(json!({
596                    "error": "Database error",
597                    "message": "Failed to fetch volumes for region"
598                }))
599            ));
600        }
601    };
602
603    let total_count = match storage::count_volumes_for_region(&pool, region_id).await {
604        Ok(count) => count,
605        Err(_) => {
606            return Err((
607                Status::InternalServerError,
608                Json(json!({
609                    "error": "Database error",
610                    "message": "Failed to count volumes for region"
611                }))
612            ));
613        }
614    };
615
616    let total_pages = (total_count as f64 / per_page as f64).ceil() as i64;
617
618    Ok(Json(json!({
619        "region": region_volumes.region,
620        "volumes": region_volumes.volumes,
621        "pagination": {
622            "page": page,
623            "per_page": per_page,
624            "total_count": total_count,
625            "total_pages": total_pages
626        }
627    })))
628}
629
630/// Get storage volumes for a specific provider, with pagination
631#[get("/platform/<platform_id>/storage/providers/<provider_id>/volumes?<page>&<per_page>")]
632pub async fn get_storage_volumes_for_provider(
633    platform_id: i64,
634    provider_id: i64,
635    page: Option<i64>,
636    per_page: Option<i64>,
637    db_manager: &State<Arc<DatabaseManager>>,
638) -> Result<Json<Value>, (Status, Json<Value>)> {
639    // Get platform information
640    let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
641        Ok(platform) => platform,
642        Err(_) => {
643            return Err((
644                Status::NotFound,
645                Json(json!({
646                    "error": "Platform not found",
647                    "message": format!("Platform with ID {} does not exist", platform_id)
648                }))
649            ));
650        }
651    };
652
653    // Get platform-specific database pool
654    let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
655        Ok(pool) => pool,
656        Err(_) => {
657            return Err((
658                Status::InternalServerError,
659                Json(json!({
660                    "error": "Database error",
661                    "message": "Failed to connect to platform database"
662                }))
663            ));
664        }
665    };
666    
667    let page = page.unwrap_or(0);
668    let per_page = per_page.unwrap_or(10);
669
670    let volumes = match storage::get_volumes_for_provider(&pool, provider_id, page, per_page).await {
671        Ok(volumes) => volumes,
672        Err(_) => {
673            return Err((
674                Status::InternalServerError,
675                Json(json!({
676                    "error": "Database error",
677                    "message": "Failed to fetch volumes for provider"
678                }))
679            ));
680        }
681    };
682
683    let total_count = match storage::count_volumes_for_provider(&pool, provider_id).await {
684        Ok(count) => count,
685        Err(_) => {
686            return Err((
687                Status::InternalServerError,
688                Json(json!({
689                    "error": "Database error",
690                    "message": "Failed to count volumes for provider"
691                }))
692            ));
693        }
694    };
695
696    let total_pages = (total_count as f64 / per_page as f64).ceil() as i64;
697
698    Ok(Json(json!({
699        "provider_id": provider_id,
700        "volumes": volumes,
701        "pagination": {
702            "page": page,
703            "per_page": per_page,
704            "total_count": total_count,
705            "total_pages": total_pages
706        }
707    })))
708}