]> git.proxmox.com Git - proxmox-backup.git/blob - src/api2/node/disks.rs
api: disks: indentation fixup
[proxmox-backup.git] / src / api2 / node / disks.rs
1 use anyhow::{bail, Error};
2 use serde_json::{json, Value};
3
4 use proxmox::api::{api, Permission, RpcEnvironment, RpcEnvironmentType};
5 use proxmox::api::router::{Router, SubdirMap};
6 use proxmox::{sortable, identity};
7 use proxmox::{list_subdirs_api_method};
8
9 use crate::config::acl::{PRIV_SYS_AUDIT, PRIV_SYS_MODIFY};
10 use crate::tools::disks::{
11 DiskUsageInfo, DiskUsageType, DiskManage, SmartData,
12 get_disks, get_smart_data, get_disk_usage_info, inititialize_gpt_disk,
13 };
14 use crate::server::WorkerTask;
15
16 use crate::api2::types::{UPID_SCHEMA, NODE_SCHEMA, BLOCKDEVICE_NAME_SCHEMA};
17
18 pub mod directory;
19 pub mod zfs;
20
21 #[api(
22 protected: true,
23 input: {
24 properties: {
25 node: {
26 schema: NODE_SCHEMA,
27 },
28 skipsmart: {
29 description: "Skip smart checks.",
30 type: bool,
31 optional: true,
32 default: false,
33 },
34 "usage-type": {
35 type: DiskUsageType,
36 optional: true,
37 },
38 },
39 },
40 returns: {
41 description: "Local disk list.",
42 type: Array,
43 items: {
44 type: DiskUsageInfo,
45 },
46 },
47 access: {
48 permission: &Permission::Privilege(&["system", "disks"], PRIV_SYS_AUDIT, false),
49 },
50 )]
51 /// List local disks
52 pub fn list_disks(
53 skipsmart: bool,
54 usage_type: Option<DiskUsageType>,
55 ) -> Result<Vec<DiskUsageInfo>, Error> {
56
57 let mut list = Vec::new();
58
59 for (_, info) in get_disks(None, skipsmart)? {
60 if let Some(ref usage_type) = usage_type {
61 if info.used == *usage_type {
62 list.push(info);
63 }
64 } else {
65 list.push(info);
66 }
67 }
68
69 Ok(list)
70 }
71
72 #[api(
73 protected: true,
74 input: {
75 properties: {
76 node: {
77 schema: NODE_SCHEMA,
78 },
79 disk: {
80 schema: BLOCKDEVICE_NAME_SCHEMA,
81 },
82 healthonly: {
83 description: "If true returns only the health status.",
84 type: bool,
85 optional: true,
86 },
87 },
88 },
89 returns: {
90 type: SmartData,
91 },
92 access: {
93 permission: &Permission::Privilege(&["system", "disks"], PRIV_SYS_AUDIT, false),
94 },
95 )]
96 /// Get SMART attributes and health of a disk.
97 pub fn smart_status(
98 disk: String,
99 healthonly: Option<bool>,
100 ) -> Result<SmartData, Error> {
101
102 let healthonly = healthonly.unwrap_or(false);
103
104 let manager = DiskManage::new();
105 let disk = manager.disk_by_name(&disk)?;
106 get_smart_data(&disk, healthonly)
107 }
108
109 #[api(
110 protected: true,
111 input: {
112 properties: {
113 node: {
114 schema: NODE_SCHEMA,
115 },
116 disk: {
117 schema: BLOCKDEVICE_NAME_SCHEMA,
118 },
119 uuid: {
120 description: "UUID for the GPT table.",
121 type: String,
122 optional: true,
123 max_length: 36,
124 },
125 },
126 },
127 returns: {
128 schema: UPID_SCHEMA,
129 },
130 access: {
131 permission: &Permission::Privilege(&["system", "disks"], PRIV_SYS_MODIFY, false),
132 },
133 )]
134 /// Initialize empty Disk with GPT
135 pub fn initialize_disk(
136 disk: String,
137 uuid: Option<String>,
138 rpcenv: &mut dyn RpcEnvironment,
139 ) -> Result<Value, Error> {
140
141 let to_stdout = if rpcenv.env_type() == RpcEnvironmentType::CLI { true } else { false };
142
143 let username = rpcenv.get_user().unwrap();
144
145 let info = get_disk_usage_info(&disk, true)?;
146
147 if info.used != DiskUsageType::Unused {
148 bail!("disk '{}' is already in use.", disk);
149 }
150
151 let upid_str = WorkerTask::new_thread(
152 "diskinit", Some(disk.clone()), &username.clone(), to_stdout, move |worker|
153 {
154 worker.log(format!("initialize disk {}", disk));
155
156 let disk_manager = DiskManage::new();
157 let disk_info = disk_manager.disk_by_name(&disk)?;
158
159 inititialize_gpt_disk(&disk_info, uuid.as_deref())?;
160
161 Ok(())
162 })?;
163
164 Ok(json!(upid_str))
165 }
166
167 #[sortable]
168 const SUBDIRS: SubdirMap = &sorted!([
169 // ("lvm", &lvm::ROUTER),
170 ("directory", &directory::ROUTER),
171 ("zfs", &zfs::ROUTER),
172 (
173 "initgpt", &Router::new()
174 .post(&API_METHOD_INITIALIZE_DISK)
175 ),
176 (
177 "list", &Router::new()
178 .get(&API_METHOD_LIST_DISKS)
179 ),
180 (
181 "smart", &Router::new()
182 .get(&API_METHOD_SMART_STATUS)
183 ),
184 ]);
185
186 pub const ROUTER: Router = Router::new()
187 .get(&list_subdirs_api_method!(SUBDIRS))
188 .subdirs(SUBDIRS);