]> git.proxmox.com Git - pve-storage.git/blob - PVE/API2/Disks.pm
Diskmanage: also include partitions with get_disks if flag is set
[pve-storage.git] / PVE / API2 / Disks.pm
1 package PVE::API2::Disks;
2
3 use strict;
4 use warnings;
5
6 use HTTP::Status qw(:constants);
7
8 use PVE::Diskmanage;
9 use PVE::JSONSchema qw(get_standard_option);
10 use PVE::SafeSyslog;
11
12 use PVE::API2::Disks::Directory;
13 use PVE::API2::Disks::LVM;
14 use PVE::API2::Disks::LVMThin;
15 use PVE::API2::Disks::ZFS;
16
17 use PVE::RESTHandler;
18 use base qw(PVE::RESTHandler);
19
20 __PACKAGE__->register_method ({
21 subclass => "PVE::API2::Disks::LVM",
22 path => 'lvm',
23 });
24
25 __PACKAGE__->register_method ({
26 subclass => "PVE::API2::Disks::LVMThin",
27 path => 'lvmthin',
28 });
29
30 __PACKAGE__->register_method ({
31 subclass => "PVE::API2::Disks::Directory",
32 path => 'directory',
33 });
34
35 __PACKAGE__->register_method ({
36 subclass => "PVE::API2::Disks::ZFS",
37 path => 'zfs',
38 });
39
40 __PACKAGE__->register_method ({
41 name => 'index',
42 path => '',
43 method => 'GET',
44 proxyto => 'node',
45 permissions => { user => 'all' },
46 description => "Node index.",
47 parameters => {
48 additionalProperties => 0,
49 properties => {
50 node => get_standard_option('pve-node'),
51 },
52 },
53 returns => {
54 type => 'array',
55 items => {
56 type => "object",
57 properties => {},
58 },
59 links => [ { rel => 'child', href => "{name}" } ],
60 },
61 code => sub {
62 my ($param) = @_;
63
64 my $result = [
65 { name => 'list' },
66 { name => 'initgpt' },
67 { name => 'smart' },
68 { name => 'lvm' },
69 { name => 'lvmthin' },
70 { name => 'directory' },
71 { name => 'zfs' },
72 ];
73
74 return $result;
75 }});
76
77 __PACKAGE__->register_method ({
78 name => 'list',
79 path => 'list',
80 method => 'GET',
81 description => "List local disks.",
82 protected => 1,
83 proxyto => 'node',
84 permissions => {
85 check => ['perm', '/', ['Sys.Audit', 'Datastore.Audit'], any => 1],
86 },
87 parameters => {
88 additionalProperties => 0,
89 properties => {
90 node => get_standard_option('pve-node'),
91 'include-partitions' => {
92 description => "Also include partitions.",
93 type => 'boolean',
94 optional => 1,
95 default => 0,
96 },
97 skipsmart => {
98 description => "Skip smart checks.",
99 type => 'boolean',
100 optional => 1,
101 default => 0,
102 },
103 type => {
104 description => "Only list specific types of disks.",
105 type => 'string',
106 enum => ['unused', 'journal_disks'],
107 optional => 1,
108 },
109 },
110 },
111 returns => {
112 type => 'array',
113 items => {
114 type => 'object',
115 properties => {
116 devpath => {
117 type => 'string',
118 description => 'The device path',
119 },
120 used => { type => 'string', optional => 1 },
121 gpt => { type => 'boolean' },
122 size => { type => 'integer'},
123 osdid => { type => 'integer'},
124 vendor => { type => 'string', optional => 1 },
125 model => { type => 'string', optional => 1 },
126 serial => { type => 'string', optional => 1 },
127 wwn => { type => 'string', optional => 1},
128 health => { type => 'string', optional => 1},
129 parent => {
130 type => 'string',
131 description => 'For partitions only. The device path of ' .
132 'the disk the partition resides on.',
133 optional => 1
134 },
135 },
136 },
137 },
138 code => sub {
139 my ($param) = @_;
140
141 my $skipsmart = $param->{skipsmart} // 0;
142 my $include_partitions = $param->{'include-partitions'} // 0;
143
144 my $disks = PVE::Diskmanage::get_disks(
145 undef,
146 $skipsmart,
147 $include_partitions
148 );
149
150 my $type = $param->{type} // '';
151 my $result = [];
152
153 foreach my $disk (sort keys %$disks) {
154 my $entry = $disks->{$disk};
155 if ($type eq 'journal_disks') {
156 next if $entry->{osdid} >= 0;
157 if (my $usage = $entry->{used}) {
158 next if !($usage eq 'partitions' && $entry->{gpt}
159 || $usage eq 'LVM');
160 }
161 } elsif ($type eq 'unused') {
162 next if $entry->{used};
163 } elsif ($type ne '') {
164 die "internal error"; # should not happen
165 }
166 push @$result, $entry;
167 }
168 return $result;
169 }});
170
171 __PACKAGE__->register_method ({
172 name => 'smart',
173 path => 'smart',
174 method => 'GET',
175 description => "Get SMART Health of a disk.",
176 protected => 1,
177 proxyto => "node",
178 permissions => {
179 check => ['perm', '/', ['Sys.Audit', 'Datastore.Audit'], any => 1],
180 },
181 parameters => {
182 additionalProperties => 0,
183 properties => {
184 node => get_standard_option('pve-node'),
185 disk => {
186 type => 'string',
187 pattern => '^/dev/[a-zA-Z0-9\/]+$',
188 description => "Block device name",
189 },
190 healthonly => {
191 type => 'boolean',
192 description => "If true returns only the health status",
193 optional => 1,
194 },
195 },
196 },
197 returns => {
198 type => 'object',
199 properties => {
200 health => { type => 'string' },
201 type => { type => 'string', optional => 1 },
202 attributes => { type => 'array', optional => 1},
203 text => { type => 'string', optional => 1 },
204 },
205 },
206 code => sub {
207 my ($param) = @_;
208
209 my $disk = PVE::Diskmanage::verify_blockdev_path($param->{disk});
210
211 my $result = PVE::Diskmanage::get_smart_data($disk, $param->{healthonly});
212
213 $result->{health} = 'UNKNOWN' if !defined $result->{health};
214 $result = { health => $result->{health} } if $param->{healthonly};
215
216 return $result;
217 }});
218
219 __PACKAGE__->register_method ({
220 name => 'initgpt',
221 path => 'initgpt',
222 method => 'POST',
223 description => "Initialize Disk with GPT",
224 protected => 1,
225 proxyto => "node",
226 permissions => {
227 check => ['perm', '/', ['Sys.Modify']],
228 },
229 parameters => {
230 additionalProperties => 0,
231 properties => {
232 node => get_standard_option('pve-node'),
233 disk => {
234 type => 'string',
235 description => "Block device name",
236 pattern => '^/dev/[a-zA-Z0-9\/]+$',
237 },
238 uuid => {
239 type => 'string',
240 description => 'UUID for the GPT table',
241 pattern => '[a-fA-F0-9\-]+',
242 maxLength => 36,
243 optional => 1,
244 },
245 },
246 },
247 returns => { type => 'string' },
248 code => sub {
249 my ($param) = @_;
250
251 my $disk = PVE::Diskmanage::verify_blockdev_path($param->{disk});
252
253 my $rpcenv = PVE::RPCEnvironment::get();
254
255 my $authuser = $rpcenv->get_user();
256
257 die "disk $disk already in use\n" if PVE::Diskmanage::disk_is_used($disk);
258 my $worker = sub {
259 PVE::Diskmanage::init_disk($disk, $param->{uuid});
260 };
261
262 my $diskid = $disk;
263 $diskid =~ s|^.*/||; # remove all up to the last slash
264 return $rpcenv->fork_worker('diskinit', $diskid, $authuser, $worker);
265 }});
266
267 1;