]>
git.proxmox.com Git - pve-storage.git/blob - PVE/API2/Storage/Content.pm
1 package PVE
:: API2
:: Storage
:: Content
;
11 use PVE
:: Exception
qw(raise_param_exc) ;
12 use PVE
:: RPCEnvironment
;
14 use PVE
:: JSONSchema
qw(get_standard_option) ;
16 use base
qw(PVE::RESTHandler) ;
18 __PACKAGE__-
> register_method ({
22 description
=> "List storage content." ,
24 check
=> [ 'perm' , '/storage/{storage}' , [ 'Datastore.Audit' , 'Datastore.AllocateSpace' ], any
=> 1 ],
29 additionalProperties
=> 0 ,
31 node
=> get_standard_option
( 'pve-node' ),
32 storage
=> get_standard_option
( 'pve-storage-id' , {
33 completion
=> \
& PVE
:: Storage
:: complete_storage_enabled
,
36 description
=> "Only list content of this type." ,
37 type
=> 'string' , format
=> 'pve-storage-content' ,
39 completion
=> \
& PVE
:: Storage
:: complete_content_type
,
41 vmid
=> get_standard_option
( 'pve-vmid' , {
42 description
=> "Only list images for this VM" ,
44 completion
=> \
& PVE
:: Cluster
:: complete_vmid
,
54 description
=> "Volume identifier." ,
58 description
=> "Associated Owner VMID." ,
63 description
=> "Volume identifier of parent (for linked cloned)." ,
68 description
=> "Format identifier ('raw', 'qcow2', 'subvol', 'iso', 'tgz' ...)" ,
72 description
=> "Volume size in bytes." ,
77 description
=> "Used space. Please note that most storage plugins " .
78 "does not report anything useful here." ,
85 links
=> [ { rel
=> 'child' , href
=> "{volid}" } ],
90 my $rpcenv = PVE
:: RPCEnvironment
:: get
();
92 my $authuser = $rpcenv -> get_user ();
94 my $storeid = $param ->{ storage
};
96 my $cfg = PVE
:: Storage
:: config
();
98 my $vollist = PVE
:: Storage
:: volume_list
( $cfg, $storeid, $param ->{ vmid
}, $param ->{ content
});
101 foreach my $item ( @$vollist ) {
102 eval { PVE
:: Storage
:: check_volume_access
( $rpcenv, $authuser, $cfg, undef , $item ->{ volid
}); };
110 __PACKAGE__-
> register_method ({
114 description
=> "Allocate disk images." ,
116 check
=> [ 'perm' , '/storage/{storage}' , [ 'Datastore.AllocateSpace' ]],
121 additionalProperties
=> 0 ,
123 node
=> get_standard_option
( 'pve-node' ),
124 storage
=> get_standard_option
( 'pve-storage-id' , {
125 completion
=> \
& PVE
:: Storage
:: complete_storage_enabled
,
128 description
=> "The name of the file to create." ,
131 vmid
=> get_standard_option
( 'pve-vmid' , {
132 description
=> "Specify owner VM" ,
133 completion
=> \
& PVE
:: Cluster
:: complete_vmid
,
136 description
=> "Size in kilobyte (1024 bytes). Optional suffixes 'M' (megabyte, 1024K) and 'G' (gigabyte, 1024M)" ,
138 pattern
=> '\d+[MG]?' ,
142 enum
=> [ 'raw' , 'qcow2' , 'subvol' ],
149 description
=> "Volume identifier" ,
155 my $storeid = $param ->{ storage
};
156 my $name = $param ->{ filename
};
157 my $sizestr = $param ->{ size
};
160 if ( $sizestr =~ m/^\d+$/ ) {
162 } elsif ( $sizestr =~ m/^(\d+)M$/ ) {
164 } elsif ( $sizestr =~ m/^(\d+)G$/ ) {
165 $size = $1 * 1024 * 1024 ;
167 raise_param_exc
({ size
=> "unable to parse size ' $sizestr '" });
170 # extract FORMAT from name
171 if ( $name =~ m/\.(raw|qcow2|vmdk)$/ ) {
174 raise_param_exc
({ format
=> "different storage formats ( $param ->{format} != $fmt )" })
175 if $param ->{ format
} && $param ->{ format
} ne $fmt ;
177 $param ->{ format
} = $fmt ;
180 my $cfg = PVE
:: Storage
:: config
();
182 my $volid = PVE
:: Storage
:: vdisk_alloc
( $cfg, $storeid, $param ->{ vmid
},
189 # we allow to pass volume names (without storage prefix) if the storage
190 # is specified as separate parameter.
191 my $real_volume_id = sub {
192 my ( $storeid, $volume ) = @_ ;
196 if ( $volume =~ m/:/ ) {
198 my ( $sid, $volname ) = PVE
:: Storage
:: parse_volume_id
( $volume );
199 die "storage ID missmatch ( $sid != $storeid ) \n "
200 if $storeid && $sid ne $storeid ;
204 raise_param_exc
({ volume
=> $@ }) if $@ ;
207 raise_param_exc
({ volume
=> "no storage speficied - incomplete volume ID" })
210 $volid = " $storeid : $volume " ;
213 return wantarray ?
( $volid, $storeid ) : $volid ;
216 __PACKAGE__-
> register_method ({
220 description
=> "Get volume attributes" ,
222 description
=> "You need read access for the volume." ,
228 additionalProperties
=> 0 ,
230 node
=> get_standard_option
( 'pve-node' ),
231 storage
=> get_standard_option
( 'pve-storage-id' , { optional
=> 1 }),
233 description
=> "Volume identifier" ,
238 returns
=> { type
=> 'object' },
242 my $rpcenv = PVE
:: RPCEnvironment
:: get
();
243 my $authuser = $rpcenv -> get_user ();
245 my ( $volid, $storeid ) = & $real_volume_id ( $param ->{ storage
}, $param ->{ volume
});
247 my $cfg = PVE
:: Storage
:: config
();
249 PVE
:: Storage
:: check_volume_access
( $rpcenv, $authuser, $cfg, undef , $volid );
251 my $path = PVE
:: Storage
:: path
( $cfg, $volid );
252 my ( $size, $format, $used, $parent ) = PVE
:: Storage
:: file_size_info
( $path );
253 die "file_size_info on ' $volid ' failed \n " if !( $format && $size );
255 # fixme: return more attributes?
264 __PACKAGE__-
> register_method ({
268 description
=> "Delete volume" ,
270 description
=> "You need 'Datastore.Allocate' privilege on the storage (or 'Datastore.AllocateSpace' for backup volumes if you have VM.Backup privilege on the VM)." ,
276 additionalProperties
=> 0 ,
278 node
=> get_standard_option
( 'pve-node' ),
279 storage
=> get_standard_option
( 'pve-storage-id' , {
281 completion
=> \
& PVE
:: Storage
:: complete_storage
,
284 description
=> "Volume identifier" ,
286 completion
=> \
& PVE
:: Storage
:: complete_volume
,
290 returns
=> { type
=> 'null' },
294 my $rpcenv = PVE
:: RPCEnvironment
:: get
();
295 my $authuser = $rpcenv -> get_user ();
297 my $cfg = PVE
:: Storage
:: config
();
299 my ( $volid, $storeid ) = & $real_volume_id ( $param ->{ storage
}, $param ->{ volume
});
301 my ( $path, $ownervm, $vtype ) = PVE
:: Storage
:: path
( $cfg, $volid );
302 if ( $vtype eq 'backup' && $ownervm ) {
303 $rpcenv -> check ( $authuser, "/storage/ $storeid " , [ 'Datastore.AllocateSpace' ]);
304 $rpcenv -> check ( $authuser, "/vms/ $ownervm " , [ 'VM.Backup' ]);
306 $rpcenv -> check ( $authuser, "/storage/ $storeid " , [ 'Datastore.Allocate' ]);
309 PVE
:: Storage
:: vdisk_free
( $cfg, $volid );
311 if ( $vtype eq 'backup'
312 && $path =~ /(.*\/ vzdump-\w
+- \d
+- \d
{ 4 } _\d
{ 2 } _\d
{ 2 }- \d
{ 2 } _\d
{ 2 } _\d
{ 2 })[^ \
/]+$/ ) {
313 my $logpath = " $1 .log" ;
314 # try to cleanup our backup log file too, if still exisiting, #318
315 unlink ( $logpath ) if - e
$logpath ;
321 __PACKAGE__-
> register_method ({
325 description
=> "Copy a volume. This is experimental code - do not use." ,
329 additionalProperties
=> 0 ,
331 node
=> get_standard_option
( 'pve-node' ),
332 storage
=> get_standard_option
( 'pve-storage-id' , { optional
=> 1 }),
334 description
=> "Source volume identifier" ,
338 description
=> "Target volume identifier" ,
341 target_node
=> get_standard_option
( 'pve-node' , {
342 description
=> "Target node. Default is local node." ,
353 my $rpcenv = PVE
:: RPCEnvironment
:: get
();
355 my $user = $rpcenv -> get_user ();
357 my $target_node = $param ->{ target_node
} || PVE
:: INotify
:: nodename
();
359 # cd /nodes/localhost/storage/local/content
360 # pve:/> create local:103/vm-103-disk-1.raw -target local:103/vm-103-disk-2.raw
361 # pve:/> create 103/vm-103-disk-1.raw -target 103/vm-103-disk-3.raw
363 my $src_volid = & $real_volume_id ( $param ->{ storage
}, $param ->{ volume
});
364 my $dst_volid = & $real_volume_id ( $param ->{ storage
}, $param ->{ target
});
366 print "DEBUG: COPY $src_volid TO $dst_volid\n " ;
368 my $cfg = PVE
:: Storage
:: config
();
370 # do all parameter checks first
372 # then do all short running task (to raise errors befor we go to background)
374 # then start the worker task
378 print "DEBUG: starting worker $upid\n " ;
380 my ( $target_sid, $target_volname ) = PVE
:: Storage
:: parse_volume_id
( $dst_volid );
381 #my $target_ip = PVE::Cluster::remote_node_ip($target_node);
383 # you need to get this working (fails currently, because storage_migrate() uses
384 # ssh to connect to local host (which is not needed
385 my $sshinfo = PVE
:: Cluster
:: get_ssh_info
( $target_node );
386 PVE
:: Storage
:: storage_migrate
( $cfg, $src_volid, $sshinfo, $target_sid, $target_volname );
388 print "DEBUG: end worker $upid\n " ;
392 return $rpcenv -> fork_worker ( 'imgcopy' , undef , $user, $worker );