]> git.proxmox.com Git - pve-storage.git/blame - PVE/API2/Storage/Content.pm
only list iscsi when enabled (content == images)
[pve-storage.git] / PVE / API2 / Storage / Content.pm
CommitLineData
b6cf0a66
DM
1package PVE::API2::Storage::Content;
2
3use strict;
4use warnings;
5
6use PVE::SafeSyslog;
7use PVE::Cluster qw(cfs_read_file);
8use PVE::Storage;
9use PVE::INotify;
10use PVE::Exception qw(raise_param_exc);
11use PVE::RPCEnvironment;
12use PVE::RESTHandler;
13use PVE::JSONSchema qw(get_standard_option);
14
15use base qw(PVE::RESTHandler);
16
17my @ctypes = qw(images vztmpl iso backup);
18
19__PACKAGE__->register_method ({
20 name => 'index',
21 path => '',
22 method => 'GET',
23 description => "List storage content.",
5f642f73
DM
24 permissions => {
25 check => ['perm', '/storage/{storage}', ['Datastore.Audit', 'Datastore.AllocateSpace'], any => 1],
26 },
b6cf0a66
DM
27 protected => 1,
28 proxyto => 'node',
29 parameters => {
30 additionalProperties => 0,
31 properties => {
32 node => get_standard_option('pve-node'),
33 storage => get_standard_option('pve-storage-id'),
34 content => {
35 description => "Only list content of this type.",
36 type => 'string', format => 'pve-storage-content',
37 optional => 1,
38 },
39 vmid => get_standard_option
40 ('pve-vmid', {
41 description => "Only list images for this VM",
42 optional => 1,
43 }),
44 },
45 },
46 returns => {
47 type => 'array',
48 items => {
49 type => "object",
50 properties => {
51 volid => {
52 type => 'string'
53 }
54 },
55 },
56 links => [ { rel => 'child', href => "{volid}" } ],
57 },
58 code => sub {
59 my ($param) = @_;
60
61 my $cts = $param->{content} ? [ $param->{content} ] : [ @ctypes ];
62
63 my $storeid = $param->{storage};
64
65 my $cfg = cfs_read_file("storage.cfg");
66
67 my $scfg = PVE::Storage::storage_config ($cfg, $storeid);
68
69 my $res = [];
70 foreach my $ct (@$cts) {
71 my $data;
568de3d1 72 if ($ct eq 'images' || defined($param->{vmid})) {
b6cf0a66
DM
73 $data = PVE::Storage::vdisk_list ($cfg, $storeid, $param->{vmid});
74 } elsif ($ct eq 'iso') {
568de3d1 75 $data = PVE::Storage::template_list ($cfg, $storeid, 'iso');
b6cf0a66 76 } elsif ($ct eq 'vztmpl') {
568de3d1 77 $data = PVE::Storage::template_list ($cfg, $storeid, 'vztmpl');
b6cf0a66 78 } elsif ($ct eq 'backup') {
568de3d1 79 $data = PVE::Storage::template_list ($cfg, $storeid, 'backup');
b6cf0a66
DM
80 }
81
82 next if !$data || !$data->{$storeid};
83
84 foreach my $item (@{$data->{$storeid}}) {
87191fbe 85 $item->{content} = $ct;
b6cf0a66
DM
86 push @$res, $item;
87 }
88 }
89
90 return $res;
91 }});
92
93__PACKAGE__->register_method ({
94 name => 'create',
95 path => '',
96 method => 'POST',
97 description => "Allocate disk images.",
5f642f73
DM
98 permissions => {
99 check => ['perm', '/storage/{storage}', ['Datastore.AllocateSpace']],
100 },
b6cf0a66
DM
101 protected => 1,
102 proxyto => 'node',
103 parameters => {
104 additionalProperties => 0,
105 properties => {
106 node => get_standard_option('pve-node'),
107 storage => get_standard_option('pve-storage-id'),
108 filename => {
03f03009 109 description => "The name of the file to create.",
b6cf0a66
DM
110 type => 'string',
111 },
112 vmid => get_standard_option('pve-vmid', { description => "Specify owner VM" } ),
113 size => {
114 description => "Size in kilobyte (1024 bytes). Optional suffixes 'M' (megabyte, 1024K) and 'G' (gigabyte, 1024M)",
115 type => 'string',
116 pattern => '\d+[MG]?',
117 },
118 'format' => {
119 type => 'string',
120 enum => ['raw', 'qcow2'],
121 requires => 'size',
122 optional => 1,
123 },
124 },
125 },
126 returns => {
127 description => "Volume identifier",
128 type => 'string',
129 },
130 code => sub {
131 my ($param) = @_;
132
133 my $storeid = $param->{storage};
134 my $name = $param->{filename};
135 my $sizestr = $param->{size};
136
137 my $size;
138 if ($sizestr =~ m/^\d+$/) {
139 $size = $sizestr;
140 } elsif ($sizestr =~ m/^(\d+)M$/) {
141 $size = $1 * 1024;
142 } elsif ($sizestr =~ m/^(\d+)G$/) {
143 $size = $1 * 1024 * 1024;
144 } else {
145 raise_param_exc({ size => "unable to parse size '$sizestr'" });
146 }
147
148 # extract FORMAT from name
149 if ($name =~ m/\.(raw|qcow2)$/) {
150 my $fmt = $1;
151
152 raise_param_exc({ format => "different storage formats ($param->{format} != $fmt)" })
153 if $param->{format} && $param->{format} ne $fmt;
154
155 $param->{format} = $fmt;
156 }
157
158 my $cfg = cfs_read_file('storage.cfg');
159
160 my $volid = PVE::Storage::vdisk_alloc ($cfg, $storeid, $param->{vmid},
161 $param->{format},
162 $name, $size);
163
164 return $volid;
165 }});
166
167# we allow to pass volume names (without storage prefix) if the storage
168# is specified as separate parameter.
169my $real_volume_id = sub {
170 my ($storeid, $volume) = @_;
171
172 my $volid;
173
174 if ($volume =~ m/:/) {
175 eval {
176 my ($sid, $volname) = PVE::Storage::parse_volume_id ($volume);
177 raise_param_exc({ storage => "storage ID missmatch" })
178 if $storeid && $sid ne $storeid;
179 $volid = $volume;
180 };
181 raise_param_exc({ volume => $@}) if $@;
182
183 } else {
184 raise_param_exc({ volume => "no storage speficied - incomplete volume ID" })
185 if !$storeid;
186
187 $volid = "$storeid:$volume";
188 }
189
190 return $volid;
191};
192
193__PACKAGE__->register_method ({
194 name => 'info',
195 path => '{volume}',
196 method => 'GET',
197 description => "Get volume attributes",
5f642f73
DM
198 permissions => {
199 check => ['perm', '/storage/{storage}', ['Datastore.Audit', 'Datastore.AllocateSpace'], any => 1],
200 },
b6cf0a66
DM
201 protected => 1,
202 proxyto => 'node',
203 parameters => {
204 additionalProperties => 0,
205 properties => {
206 node => get_standard_option('pve-node'),
207 storage => get_standard_option('pve-storage-id', { optional => 1 }),
208 volume => {
209 description => "Volume identifier",
210 type => 'string',
211 },
212 },
213 },
214 returns => { type => 'object' },
215 code => sub {
216 my ($param) = @_;
217
218 my $volid = &$real_volume_id($param->{storage}, $param->{volume});
219
220 my $cfg = cfs_read_file('storage.cfg');
221
222 my $path = PVE::Storage::path($cfg, $volid);
223 my ($size, $format, $used) = PVE::Storage::file_size_info ($path);
224
225 # fixme: return more attributes?
226 return {
227 path => $path,
228 size => $size,
229 used => $used,
230 };
231 }});
232
233__PACKAGE__->register_method ({
234 name => 'delete',
235 path => '{volume}',
236 method => 'DELETE',
237 description => "Delete volume",
5f642f73
DM
238 permissions => {
239 check => ['perm', '/storage/{storage}', ['Datastore.AllocateSpace']],
240 },
b6cf0a66
DM
241 protected => 1,
242 proxyto => 'node',
243 parameters => {
244 additionalProperties => 0,
245 properties => {
246 node => get_standard_option('pve-node'),
247 storage => get_standard_option('pve-storage-id', { optional => 1}),
248 volume => {
249 description => "Volume identifier",
250 type => 'string',
251 },
252 },
253 },
254 returns => { type => 'null' },
255 code => sub {
256 my ($param) = @_;
257
258 my $volid = &$real_volume_id($param->{storage}, $param->{volume});
259
260 my $cfg = cfs_read_file('storage.cfg');
261
262 PVE::Storage::vdisk_free ($cfg, $volid);
263
264 return undef;
265 }});
266
883eeea6
DM
267__PACKAGE__->register_method ({
268 name => 'copy',
269 path => '{volume}',
270 method => 'POST',
5f642f73 271 description => "Copy a volume. This is experimental code - do not use.",
883eeea6
DM
272 protected => 1,
273 proxyto => 'node',
274 parameters => {
275 additionalProperties => 0,
276 properties => {
277 node => get_standard_option('pve-node'),
278 storage => get_standard_option('pve-storage-id', { optional => 1}),
279 volume => {
280 description => "Source volume identifier",
281 type => 'string',
282 },
283 target => {
284 description => "Target volume identifier",
285 type => 'string',
286 },
287 target_node => get_standard_option('pve-node', {
288 description => "Target node. Default is local node.",
289 optional => 1,
290 }),
291 },
292 },
293 returns => {
294 type => 'string',
295 },
296 code => sub {
297 my ($param) = @_;
298
299 my $rpcenv = PVE::RPCEnvironment::get();
300
301 my $user = $rpcenv->get_user();
302
303 my $target_node = $param->{target_node} || PVE::INotify::nodename();
304 # pvesh examples
305 # cd /nodes/localhost/storage/local/content
306 # pve:/> create local:103/vm-103-disk-1.raw -target local:103/vm-103-disk-2.raw
307 # pve:/> create 103/vm-103-disk-1.raw -target 103/vm-103-disk-3.raw
308
309 my $src_volid = &$real_volume_id($param->{storage}, $param->{volume});
310 my $dst_volid = &$real_volume_id($param->{storage}, $param->{target});
311
312 print "DEBUG: COPY $src_volid TO $dst_volid\n";
313
314 my $cfg = cfs_read_file('storage.cfg');
315
316 # do all parameter checks first
317
318 # then do all short running task (to raise errors befor we go to background)
319
320 # then start the worker task
321 my $worker = sub {
322 my $upid = shift;
323
324 print "DEBUG: starting worker $upid\n";
325
326 my ($target_sid, $target_volname) = PVE::Storage::parse_volume_id($dst_volid);
327 #my $target_ip = PVE::Cluster::remote_node_ip($target_node);
328
329 # you need to get this working (fails currently, because storage_migrate() uses
330 # ssh to connect to local host (which is not needed
331 PVE::Storage::storage_migrate($cfg, $src_volid, $target_node, $target_sid, $target_volname);
332
333 print "DEBUG: end worker $upid\n";
334
335 };
336
337 return $rpcenv->fork_worker('imgcopy', undef, $user, $worker);
338 }});
339
b6cf0a66 3401;