]>
git.proxmox.com Git - pve-storage.git/blob - PVE/API2/Storage/Content.pm
1 package PVE
::API2
::Storage
::Content
;
7 use PVE
::Cluster
qw(cfs_read_file);
10 use PVE
::Exception
qw(raise_param_exc);
11 use PVE
::RPCEnvironment
;
13 use PVE
::JSONSchema
qw(get_standard_option);
15 use base
qw(PVE::RESTHandler);
17 my @ctypes = qw(images vztmpl iso backup);
19 __PACKAGE__-
>register_method ({
23 description
=> "List storage content.",
25 check
=> ['perm', '/storage/{storage}', ['Datastore.Audit', 'Datastore.AllocateSpace'], any
=> 1],
30 additionalProperties
=> 0,
32 node
=> get_standard_option
('pve-node'),
33 storage
=> get_standard_option
('pve-storage-id'),
35 description
=> "Only list content of this type.",
36 type
=> 'string', format
=> 'pve-storage-content',
39 vmid
=> get_standard_option
41 description
=> "Only list images for this VM",
56 links
=> [ { rel
=> 'child', href
=> "{volid}" } ],
61 my $rpcenv = PVE
::RPCEnvironment
::get
();
63 my $authuser = $rpcenv->get_user();
65 my $cts = $param->{content
} ?
[ $param->{content
} ] : [ @ctypes ];
67 my $storeid = $param->{storage
};
69 my $cfg = cfs_read_file
("storage.cfg");
71 my $scfg = PVE
::Storage
::storage_config
($cfg, $storeid);
74 foreach my $ct (@$cts) {
76 if ($ct eq 'images' || defined($param->{vmid
})) {
77 $data = PVE
::Storage
::vdisk_list
($cfg, $storeid, $param->{vmid
});
78 } elsif ($ct eq 'iso') {
79 $data = PVE
::Storage
::template_list
($cfg, $storeid, 'iso');
80 } elsif ($ct eq 'vztmpl') {
81 $data = PVE
::Storage
::template_list
($cfg, $storeid, 'vztmpl');
82 } elsif ($ct eq 'backup') {
83 $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
86 next if !$data || !$data->{$storeid};
88 foreach my $item (@{$data->{$storeid}}) {
89 eval { $rpcenv->check_volume_access($authuser, $cfg, undef, $item->{volid
}); };
91 $item->{content
} = $ct;
99 __PACKAGE__-
>register_method ({
103 description
=> "Allocate disk images.",
105 check
=> ['perm', '/storage/{storage}', ['Datastore.AllocateSpace']],
110 additionalProperties
=> 0,
112 node
=> get_standard_option
('pve-node'),
113 storage
=> get_standard_option
('pve-storage-id'),
115 description
=> "The name of the file to create.",
118 vmid
=> get_standard_option
('pve-vmid', { description
=> "Specify owner VM" } ),
120 description
=> "Size in kilobyte (1024 bytes). Optional suffixes 'M' (megabyte, 1024K) and 'G' (gigabyte, 1024M)",
122 pattern
=> '\d+[MG]?',
126 enum
=> ['raw', 'qcow2'],
133 description
=> "Volume identifier",
139 my $storeid = $param->{storage
};
140 my $name = $param->{filename
};
141 my $sizestr = $param->{size
};
144 if ($sizestr =~ m/^\d+$/) {
146 } elsif ($sizestr =~ m/^(\d+)M$/) {
148 } elsif ($sizestr =~ m/^(\d+)G$/) {
149 $size = $1 * 1024 * 1024;
151 raise_param_exc
({ size
=> "unable to parse size '$sizestr'" });
154 # extract FORMAT from name
155 if ($name =~ m/\.(raw|qcow2)$/) {
158 raise_param_exc
({ format
=> "different storage formats ($param->{format} != $fmt)" })
159 if $param->{format
} && $param->{format
} ne $fmt;
161 $param->{format
} = $fmt;
164 my $cfg = cfs_read_file
('storage.cfg');
166 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $storeid, $param->{vmid
},
173 # we allow to pass volume names (without storage prefix) if the storage
174 # is specified as separate parameter.
175 my $real_volume_id = sub {
176 my ($storeid, $volume) = @_;
180 if ($volume =~ m/:/) {
182 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volume);
183 raise_param_exc
({ storage
=> "storage ID missmatch" })
184 if $storeid && $sid ne $storeid;
188 raise_param_exc
({ volume
=> $@}) if $@;
191 raise_param_exc
({ volume
=> "no storage speficied - incomplete volume ID" })
194 $volid = "$storeid:$volume";
197 return wantarray ?
($volid, $storeid) : $volid;
200 __PACKAGE__-
>register_method ({
204 description
=> "Get volume attributes",
206 description
=> "You need read access for the volume.",
212 additionalProperties
=> 0,
214 node
=> get_standard_option
('pve-node'),
215 storage
=> get_standard_option
('pve-storage-id', { optional
=> 1 }),
217 description
=> "Volume identifier",
222 returns
=> { type
=> 'object' },
226 my $rpcenv = PVE
::RPCEnvironment
::get
();
227 my $authuser = $rpcenv->get_user();
229 my ($volid, $storeid) = &$real_volume_id($param->{storage
}, $param->{volume
});
231 my $cfg = cfs_read_file
('storage.cfg');
233 $rpcenv->check_volume_access($authuser, $cfg, undef, $volid);
235 my $path = PVE
::Storage
::path
($cfg, $volid);
236 my ($size, $format, $used) = PVE
::Storage
::file_size_info
($path);
238 # fixme: return more attributes?
246 __PACKAGE__-
>register_method ({
250 description
=> "Delete volume",
252 description
=> "You need 'Datastore.Allocate' privilege on the storage ('Datastore.AllocateSpace' is not enough).",
258 additionalProperties
=> 0,
260 node
=> get_standard_option
('pve-node'),
261 storage
=> get_standard_option
('pve-storage-id', { optional
=> 1}),
263 description
=> "Volume identifier",
268 returns
=> { type
=> 'null' },
272 my $rpcenv = PVE
::RPCEnvironment
::get
();
273 my $authuser = $rpcenv->get_user();
275 my ($volid, $storeid) = &$real_volume_id($param->{storage
}, $param->{volume
});
277 $rpcenv->check($authuser, "/storage/$storeid", ['Datastore.Allocate']);
279 my $cfg = cfs_read_file
('storage.cfg');
281 PVE
::Storage
::vdisk_free
($cfg, $volid);
286 __PACKAGE__-
>register_method ({
290 description
=> "Copy a volume. This is experimental code - do not use.",
294 additionalProperties
=> 0,
296 node
=> get_standard_option
('pve-node'),
297 storage
=> get_standard_option
('pve-storage-id', { optional
=> 1}),
299 description
=> "Source volume identifier",
303 description
=> "Target volume identifier",
306 target_node
=> get_standard_option
('pve-node', {
307 description
=> "Target node. Default is local node.",
318 my $rpcenv = PVE
::RPCEnvironment
::get
();
320 my $user = $rpcenv->get_user();
322 my $target_node = $param->{target_node
} || PVE
::INotify
::nodename
();
324 # cd /nodes/localhost/storage/local/content
325 # pve:/> create local:103/vm-103-disk-1.raw -target local:103/vm-103-disk-2.raw
326 # pve:/> create 103/vm-103-disk-1.raw -target 103/vm-103-disk-3.raw
328 my $src_volid = &$real_volume_id($param->{storage
}, $param->{volume
});
329 my $dst_volid = &$real_volume_id($param->{storage
}, $param->{target
});
331 print "DEBUG: COPY $src_volid TO $dst_volid\n";
333 my $cfg = cfs_read_file
('storage.cfg');
335 # do all parameter checks first
337 # then do all short running task (to raise errors befor we go to background)
339 # then start the worker task
343 print "DEBUG: starting worker $upid\n";
345 my ($target_sid, $target_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
346 #my $target_ip = PVE::Cluster::remote_node_ip($target_node);
348 # you need to get this working (fails currently, because storage_migrate() uses
349 # ssh to connect to local host (which is not needed
350 PVE
::Storage
::storage_migrate
($cfg, $src_volid, $target_node, $target_sid, $target_volname);
352 print "DEBUG: end worker $upid\n";
356 return $rpcenv->fork_worker('imgcopy', undef, $user, $worker);