]>
Commit | Line | Data |
---|---|---|
b6cf0a66 DM |
1 | package PVE::API2::Storage::Scan; |
2 | ||
3 | use strict; | |
4 | use warnings; | |
5 | ||
6 | use PVE::SafeSyslog; | |
7 | use PVE::Storage; | |
6d64e9e0 | 8 | use PVE::Storage::LVMPlugin; |
b6cf0a66 DM |
9 | use HTTP::Status qw(:constants); |
10 | use PVE::JSONSchema qw(get_standard_option); | |
11 | ||
12 | use PVE::RESTHandler; | |
13 | ||
14 | use base qw(PVE::RESTHandler); | |
15 | ||
16 | __PACKAGE__->register_method ({ | |
17 | name => 'index', | |
18 | path => '', | |
19 | method => 'GET', | |
20 | description => "Index of available scan methods", | |
5f642f73 DM |
21 | permissions => { |
22 | user => 'all', | |
23 | }, | |
b6cf0a66 DM |
24 | parameters => { |
25 | additionalProperties => 0, | |
26 | properties => { | |
27 | node => get_standard_option('pve-node'), | |
28 | }, | |
29 | }, | |
30 | returns => { | |
31 | type => 'array', | |
32 | items => { | |
33 | type => "object", | |
34 | properties => { method => { type => 'string'} }, | |
35 | }, | |
36 | links => [ { rel => 'child', href => "{method}" } ], | |
37 | }, | |
38 | code => sub { | |
39 | my ($param) = @_; | |
40 | ||
41 | my $res = [ | |
42 | { method => 'lvm' }, | |
43 | { method => 'iscsi' }, | |
44 | { method => 'nfs' }, | |
3cf5e19e | 45 | { method => 'glusterfs' }, |
b6cf0a66 | 46 | { method => 'usb' }, |
584d97f6 | 47 | { method => 'zfs' }, |
b6cf0a66 DM |
48 | ]; |
49 | ||
50 | return $res; | |
51 | }}); | |
52 | ||
584d97f6 DM |
53 | __PACKAGE__->register_method ({ |
54 | name => 'zfsscan', | |
55 | path => 'zfs', | |
56 | method => 'GET', | |
57 | description => "Scan zfs pool list on local node.", | |
58 | protected => 1, | |
59 | proxyto => "node", | |
60 | permissions => { | |
61 | check => ['perm', '/storage', ['Datastore.Allocate']], | |
62 | }, | |
63 | parameters => { | |
64 | additionalProperties => 0, | |
65 | properties => { | |
66 | node => get_standard_option('pve-node'), | |
67 | }, | |
68 | }, | |
69 | returns => { | |
70 | type => 'array', | |
71 | items => { | |
72 | type => "object", | |
73 | properties => { | |
74 | pool => { type => 'string'}, | |
75 | }, | |
76 | }, | |
77 | }, | |
78 | code => sub { | |
79 | my ($param) = @_; | |
80 | ||
81 | return PVE::Storage::scan_zfs(); | |
82 | }}); | |
83 | ||
b6cf0a66 DM |
84 | __PACKAGE__->register_method ({ |
85 | name => 'nfsscan', | |
86 | path => 'nfs', | |
87 | method => 'GET', | |
88 | description => "Scan remote NFS server.", | |
89 | protected => 1, | |
90 | proxyto => "node", | |
5f642f73 DM |
91 | permissions => { |
92 | check => ['perm', '/storage', ['Datastore.Allocate']], | |
93 | }, | |
b6cf0a66 DM |
94 | parameters => { |
95 | additionalProperties => 0, | |
96 | properties => { | |
97 | node => get_standard_option('pve-node'), | |
98 | server => { type => 'string', format => 'pve-storage-server' }, | |
99 | }, | |
100 | }, | |
101 | returns => { | |
102 | type => 'array', | |
103 | items => { | |
104 | type => "object", | |
105 | properties => { | |
106 | path => { type => 'string'}, | |
107 | options => { type => 'string'}, | |
108 | }, | |
109 | }, | |
110 | }, | |
111 | code => sub { | |
112 | my ($param) = @_; | |
113 | ||
114 | my $server = $param->{server}; | |
115 | my $res = PVE::Storage::scan_nfs($server); | |
116 | ||
117 | my $data = []; | |
118 | foreach my $k (keys %$res) { | |
119 | push @$data, { path => $k, options => $res->{$k} }; | |
120 | } | |
121 | return $data; | |
122 | }}); | |
123 | ||
3cf5e19e DM |
124 | # Note: GlusterFS currently does not have an equivalent of showmount. |
125 | # As workaround, we simply use nfs showmount. | |
126 | # see http://www.gluster.org/category/volumes/ | |
127 | ||
128 | __PACKAGE__->register_method ({ | |
129 | name => 'glusterfsscan', | |
130 | path => 'glusterfs', | |
131 | method => 'GET', | |
132 | description => "Scan remote GlusterFS server.", | |
133 | protected => 1, | |
134 | proxyto => "node", | |
135 | permissions => { | |
136 | check => ['perm', '/storage', ['Datastore.Allocate']], | |
137 | }, | |
138 | parameters => { | |
139 | additionalProperties => 0, | |
140 | properties => { | |
141 | node => get_standard_option('pve-node'), | |
142 | server => { type => 'string', format => 'pve-storage-server' }, | |
143 | }, | |
144 | }, | |
145 | returns => { | |
146 | type => 'array', | |
147 | items => { | |
148 | type => "object", | |
149 | properties => { | |
150 | volname => { type => 'string'}, | |
151 | }, | |
152 | }, | |
153 | }, | |
154 | code => sub { | |
155 | my ($param) = @_; | |
156 | ||
157 | my $server = $param->{server}; | |
158 | my $res = PVE::Storage::scan_nfs($server); | |
159 | ||
160 | my $data = []; | |
161 | foreach my $path (keys %$res) { | |
162 | if ($path =~ m!^/([^\s/]+)$!) { | |
163 | push @$data, { volname => $1 }; | |
164 | } | |
165 | } | |
166 | return $data; | |
167 | }}); | |
168 | ||
b6cf0a66 DM |
169 | __PACKAGE__->register_method ({ |
170 | name => 'iscsiscan', | |
171 | path => 'iscsi', | |
172 | method => 'GET', | |
173 | description => "Scan remote iSCSI server.", | |
174 | protected => 1, | |
175 | proxyto => "node", | |
5f642f73 DM |
176 | permissions => { |
177 | check => ['perm', '/storage', ['Datastore.Allocate']], | |
178 | }, | |
b6cf0a66 DM |
179 | parameters => { |
180 | additionalProperties => 0, | |
181 | properties => { | |
182 | node => get_standard_option('pve-node'), | |
183 | portal => { type => 'string', format => 'pve-storage-portal-dns' }, | |
184 | }, | |
185 | }, | |
186 | returns => { | |
187 | type => 'array', | |
188 | items => { | |
189 | type => "object", | |
190 | properties => { | |
191 | target => { type => 'string'}, | |
192 | portal => { type => 'string'}, | |
193 | }, | |
194 | }, | |
195 | }, | |
196 | code => sub { | |
197 | my ($param) = @_; | |
198 | ||
199 | my $res = PVE::Storage::scan_iscsi($param->{portal}); | |
200 | ||
201 | my $data = []; | |
202 | foreach my $k (keys %$res) { | |
203 | push @$data, { target => $k, portal => join(',', @{$res->{$k}}) }; | |
204 | } | |
205 | ||
206 | return $data; | |
207 | }}); | |
208 | ||
209 | __PACKAGE__->register_method ({ | |
210 | name => 'lvmscan', | |
211 | path => 'lvm', | |
212 | method => 'GET', | |
213 | description => "List local LVM volume groups.", | |
214 | protected => 1, | |
215 | proxyto => "node", | |
5f642f73 DM |
216 | permissions => { |
217 | check => ['perm', '/storage', ['Datastore.Allocate']], | |
218 | }, | |
b6cf0a66 DM |
219 | parameters => { |
220 | additionalProperties => 0, | |
221 | properties => { | |
222 | node => get_standard_option('pve-node'), | |
223 | }, | |
224 | }, | |
225 | returns => { | |
226 | type => 'array', | |
227 | items => { | |
228 | type => "object", | |
229 | properties => { | |
230 | vg => { type => 'string'}, | |
231 | }, | |
232 | }, | |
233 | }, | |
234 | code => sub { | |
235 | my ($param) = @_; | |
236 | ||
6d64e9e0 | 237 | my $res = PVE::Storage::LVMPlugin::lvm_vgs(); |
b6cf0a66 DM |
238 | return PVE::RESTHandler::hash_to_array($res, 'vg'); |
239 | }}); | |
240 | ||
d0ea89e5 | 241 | __PACKAGE__->register_method ({ |
668f6d9f | 242 | name => 'lvmthinscan', |
d0ea89e5 DC |
243 | path => 'lvmthin', |
244 | method => 'GET', | |
245 | description => "List local LVM Thin Pools.", | |
246 | protected => 1, | |
247 | proxyto => "node", | |
248 | permissions => { | |
249 | check => ['perm', '/storage', ['Datastore.Allocate']], | |
250 | }, | |
251 | parameters => { | |
252 | additionalProperties => 0, | |
253 | properties => { | |
254 | node => get_standard_option('pve-node'), | |
255 | vg => { | |
256 | type => 'string', | |
257 | pattern => '[a-zA-Z0-9\.\+\_][a-zA-Z0-9\.\+\_\-]+', # see lvm(8) manpage | |
258 | maxLength => 100, | |
259 | }, | |
260 | }, | |
261 | }, | |
262 | returns => { | |
263 | type => 'array', | |
264 | items => { | |
265 | type => "object", | |
266 | properties => { | |
267 | lv => { type => 'string'}, | |
268 | }, | |
269 | }, | |
270 | }, | |
271 | code => sub { | |
272 | my ($param) = @_; | |
668f6d9f | 273 | |
d0ea89e5 DC |
274 | return PVE::Storage::LvmThinPlugin::list_thinpools($param->{vg}); |
275 | }}); | |
276 | ||
b6cf0a66 DM |
277 | __PACKAGE__->register_method ({ |
278 | name => 'usbscan', | |
279 | path => 'usb', | |
280 | method => 'GET', | |
281 | description => "List local USB devices.", | |
282 | protected => 1, | |
283 | proxyto => "node", | |
5f642f73 DM |
284 | permissions => { |
285 | check => ['perm', '/', ['Sys.Modify']], | |
286 | }, | |
b6cf0a66 DM |
287 | parameters => { |
288 | additionalProperties => 0, | |
289 | properties => { | |
290 | node => get_standard_option('pve-node'), | |
291 | }, | |
292 | }, | |
293 | returns => { | |
294 | type => 'array', | |
295 | items => { | |
296 | type => "object", | |
297 | properties => { | |
298 | busnum => { type => 'integer'}, | |
299 | devnum => { type => 'integer'}, | |
300 | port => { type => 'integer'}, | |
301 | usbpath => { type => 'string', optional => 1}, | |
302 | level => { type => 'integer'}, | |
303 | class => { type => 'integer'}, | |
304 | vendid => { type => 'string'}, | |
305 | prodid => { type => 'string'}, | |
306 | speed => { type => 'string'}, | |
307 | ||
308 | product => { type => 'string', optional => 1 }, | |
309 | serial => { type => 'string', optional => 1 }, | |
310 | manufacturer => { type => 'string', optional => 1 }, | |
311 | }, | |
312 | }, | |
313 | }, | |
314 | code => sub { | |
315 | my ($param) = @_; | |
316 | ||
317 | return PVE::Storage::scan_usb(); | |
318 | }}); | |
319 | ||
320 | 1; |