]>
git.proxmox.com Git - pve-storage.git/blob - PVE/API2/Storage/Status.pm
68f3d398c74abf725366674709542966a8980a27
1 package PVE
:: API2
:: Storage
:: Status
;
10 use PVE
:: Cluster
qw(cfs_read_file) ;
12 use PVE
:: API2
:: Storage
:: Content
;
14 use PVE
:: RPCEnvironment
;
15 use PVE
:: JSONSchema
qw(get_standard_option) ;
16 use PVE
:: Exception
qw(raise_param_exc) ;
18 use base
qw(PVE::RESTHandler) ;
20 __PACKAGE__-
> register_method ({
21 subclass
=> "PVE::API2::Storage::Content" ,
22 # set fragment delimiter (no subdirs) - we need that, because volume
23 # IDs may contain a slash '/'
24 fragmentDelimiter
=> '' ,
25 path
=> '{storage}/content' ,
28 __PACKAGE__-
> register_method ({
32 description
=> "Get status for all datastores." ,
36 additionalProperties
=> 0 ,
38 node
=> get_standard_option
( 'pve-node' ),
39 storage
=> get_standard_option
41 description
=> "Only list status for specified storage" ,
45 description
=> "Only list stores which support this content type." ,
46 type
=> 'string' , format
=> 'pve-storage-content' ,
55 properties
=> { storage
=> { type
=> 'string' } },
57 links
=> [ { rel
=> 'child' , href
=> "{storage}" } ],
62 my $cfg = cfs_read_file
( "storage.cfg" );
64 my $info = PVE
:: Storage
:: storage_info
( $cfg, $param ->{ content
});
66 if ( $param ->{ storage
}) {
67 my $data = $info ->{ $param ->{ storage
}};
69 raise_param_exc
({ storage
=> "No such storage." })
72 $data ->{ storage
} = $param ->{ storage
};
76 return PVE
:: RESTHandler
:: hash_to_array
( $info, 'storage' );
79 __PACKAGE__-
> register_method ({
85 additionalProperties
=> 0 ,
87 node
=> get_standard_option
( 'pve-node' ),
88 storage
=> get_standard_option
( 'pve-storage-id' ),
96 subdir
=> { type
=> 'string' },
99 links
=> [ { rel
=> 'child' , href
=> "{subdir}" } ],
105 { subdir
=> 'status' },
106 { subdir
=> 'content' },
107 { subdir
=> 'upload' },
109 { subdir
=> 'rrddata' },
115 __PACKAGE__-
> register_method ({
116 name
=> 'read_status' ,
117 path
=> '{storage}/status' ,
119 description
=> "Read storage status." ,
123 additionalProperties
=> 0 ,
125 node
=> get_standard_option
( 'pve-node' ),
126 storage
=> get_standard_option
( 'pve-storage-id' ),
136 my $cfg = cfs_read_file
( "storage.cfg" );
138 my $info = PVE
:: Storage
:: storage_info
( $cfg, $param ->{ content
});
140 my $data = $info ->{ $param ->{ storage
}};
142 raise_param_exc
({ storage
=> "No such storage." })
148 __PACKAGE__-
> register_method ({
150 path
=> '{storage}/rrd' ,
152 description
=> "Read storage RRD statistics (returns PNG)." ,
156 additionalProperties
=> 0 ,
158 node
=> get_standard_option
( 'pve-node' ),
159 storage
=> get_standard_option
( 'pve-storage-id' ),
161 description
=> "Specify the time frame you are interested in." ,
163 enum
=> [ 'hour' , 'day' , 'week' , 'month' , 'year' ],
166 description
=> "The list of datasources you want to display." ,
167 type
=> 'string' , format
=> 'pve-configid-list' ,
170 description
=> "The RRD consolidation function" ,
172 enum
=> [ 'AVERAGE' , 'MAX' ],
180 filename
=> { type
=> 'string' },
186 return PVE
:: Cluster
:: create_rrd_graph
(
187 "pve2-storage/ $param ->{node}/ $param ->{storage}" ,
188 $param ->{ timeframe
}, $param ->{ ds
}, $param ->{ cf
});
192 __PACKAGE__-
> register_method ({
194 path
=> '{storage}/rrddata' ,
196 description
=> "Read storage RRD statistics." ,
200 additionalProperties
=> 0 ,
202 node
=> get_standard_option
( 'pve-node' ),
203 storage
=> get_standard_option
( 'pve-storage-id' ),
205 description
=> "Specify the time frame you are interested in." ,
207 enum
=> [ 'hour' , 'day' , 'week' , 'month' , 'year' ],
210 description
=> "The RRD consolidation function" ,
212 enum
=> [ 'AVERAGE' , 'MAX' ],
227 return PVE
:: Cluster
:: create_rrd_data
(
228 "pve2-storage/ $param ->{node}/ $param ->{storage}" ,
229 $param ->{ timeframe
}, $param ->{ cf
});
232 __PACKAGE__-
> register_method ({
234 path
=> '{storage}/upload' ,
236 description
=> "Upload file." ,
239 additionalProperties
=> 0 ,
241 node
=> get_standard_option
( 'pve-node' ),
242 storage
=> get_standard_option
( 'pve-storage-id' ),
244 description
=> "Content type." ,
245 type
=> 'string' , format
=> 'pve-storage-content' ,
248 description
=> "The name of the file to create." ,
252 description
=> "The source file name. This parameter is usually set by the REST handler. You can only overwrite it when connecting to the trustet port on localhost." ,
258 returns
=> { type
=> "string" },
262 my $rpcenv = PVE
:: RPCEnvironment
:: get
();
264 my $user = $rpcenv -> get_user ();
266 my $cfg = cfs_read_file
( "storage.cfg" );
268 my $node = $param ->{ node
};
269 my $scfg = PVE
:: Storage
:: storage_check_enabled
( $cfg, $param ->{ storage
}, $node );
271 die "cant upload to storage type ' $scfg ->{type}'"
272 if !( $scfg ->{ type
} eq 'dir' || $scfg ->{ type
} eq 'nfs' );
274 my $content = $param ->{ content
};
276 my $tmpfilename = $param ->{ tmpfilename
};
277 die "missing temporary file name \n " if ! $tmpfilename ;
279 my $size = - s
$tmpfilename ;
280 die "temporary file ' $tmpfilename ' does not exists \n " if ! defined ( $size );
282 my $filename = $param ->{ filename
};
285 $filename =~ s/^.*[\/\\]/ /;
286 $filename =~ s/\s/_/g ;
290 if ( $content eq 'iso' ) {
291 if ( $filename !~ m![^/]+\.[Ii][Ss][Oo]$! ) {
292 raise_param_exc
({ filename
=> "missing '.iso' extension" });
294 $path = PVE
:: Storage
:: get_iso_dir
( $cfg, $param ->{ storage
});
295 } elsif ( $content eq 'vztmpl' ) {
296 if ( $filename !~ m![^/]+\.tar\.gz$! ) {
297 raise_param_exc
({ filename
=> "missing '.tar.gz' extension" });
299 $path = PVE
:: Storage
:: get_vztmpl_dir
( $cfg, $param ->{ storage
});
300 } elsif ( $content eq 'backup' ) {
301 if ( $filename !~ m!/([^/]+\.(tar|tgz))$! ) {
302 raise_param_exc
({ filename
=> "missing '.(tar|tgz)' extension" });
304 $path = PVE
:: Storage
:: get_backup_dir
( $cfg, $param ->{ storage
});
306 raise_param_exc
({ content
=> "upload content type ' $content ' not implemented" });
309 die "storage ' $param ->{storage}' does not support ' $content ' content \n "
310 if ! $scfg ->{ content
}->{ $content };
312 my $dest = " $path/$filename " ;
313 my $dirname = dirname
( $dest );
315 # we simply overwrite when destination when file already exists
318 if ( $node ne 'localhost' && $node ne PVE
:: INotify
:: nodename
()) {
319 my $remip = PVE
:: Cluster
:: remote_node_ip
( $node );
321 my @ssh_options = ( '-o' , 'BatchMode=yes' , '-c' , 'blowfish-cbc' );
323 my @remcmd = ( '/usr/bin/ssh' , @ssh_options, $remip );
326 # activate remote storage
327 PVE
:: Tools
:: run_command
([ @remcmd, '/usr/sbin/pvesm' , 'status' ,
328 '--storage' , $param ->{ storage
}]);
330 die "can't activate storage ' $param ->{storage}' on node ' $node ' \n " if $@ ;
332 PVE
:: Tools
:: run_command
([ @remcmd, '/bin/mkdir' , '-p' , $dirname ],
333 errmsg
=> "mkdir failed" );
335 $cmd = [ '/usr/bin/scp' , @ssh_options, $tmpfilename, " $remip : $dest " ];
337 PVE
:: Storage
:: activate_storage
( $cfg, $param ->{ storage
});
338 File
:: Path
:: make_path
( $dirname );
339 $cmd = [ 'cp' , $tmpfilename, $dest ];
345 print "starting file import from: $tmpfilename\n " ;
346 print "target node: $node\n " ;
347 print "target file: $dest\n " ;
348 print "file size is: $size\n " ;
349 print "command: " . join ( ' ' , @$cmd ) . " \n " ;
351 eval { PVE
:: Tools
:: run_command
( $cmd, errmsg
=> 'import failed' ); };
356 print "finished file import successfully \n " ;
359 return $rpcenv -> fork_worker ( 'imgcopy' , undef , $user, $worker );