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