1 package PVE
::API2
::VZDump
;
5 use PVE
::Exception
qw(raise_param_exc);
6 use PVE
::Tools
qw(extract_param);
7 use PVE
::Cluster
qw(cfs_register_file cfs_read_file);
9 use PVE
::RPCEnvironment
;
10 use PVE
::AccessControl
;
11 use PVE
::JSONSchema
qw(get_standard_option);
16 use Data
::Dumper
; # fixme: remove
19 use base
qw(PVE::RESTHandler);
21 __PACKAGE__-
>register_method ({
25 description
=> "Create backup.",
27 description
=> "The user needs 'VM.Backup' permissions on any VM, and 'Datastore.AllocateSpace' on the backup storage. The 'maxfiles', 'tmpdir', 'dumpdir', 'script', 'bwlimit' and 'ionice' parameters are restricted to the 'root\@pam' user.",
33 additionalProperties
=> 0,
34 properties
=> PVE
::VZDump
::json_config_properties
({
37 description
=> "Write tar to stdout, not to a file.",
42 returns
=> { type
=> 'string' },
46 my $rpcenv = PVE
::RPCEnvironment
::get
();
48 my $user = $rpcenv->get_user();
50 my $nodename = PVE
::INotify
::nodename
();
52 if ($rpcenv->{type
} ne 'cli') {
53 raise_param_exc
({ node
=> "option is only allowed on the command line interface."})
54 if $param->{node
} && $param->{node
} ne $nodename;
56 raise_param_exc
({ stdout
=> "option is only allowed on the command line interface."})
60 foreach my $key (qw(maxfiles tmpdir dumpdir script bwlimit ionice)) {
61 raise_param_exc
({ $key => "Only root may set this option."})
62 if defined($param->{$key}) && ($user ne 'root@pam');
65 PVE
::VZDump
::verify_vzdump_parameters
($param, 1);
67 # silent exit if we run on wrong node
68 return 'OK' if $param->{node
} && $param->{node
} ne $nodename;
70 my $cmdline = PVE
::VZDump
::command_line
($param);
72 # convert string lists to arrays
74 @vmids = @{PVE
::API2Tools
::get_resource_pool_guest_members
($param->{pool
})};
76 @vmids = PVE
::Tools
::split_list
(extract_param
($param, 'vmid'));
80 PVE
::VZDump
::stop_running_backups
();
81 return 'OK' if !scalar(@vmids);
86 if (!$param->{node
} || $param->{node
} eq $nodename) {
87 my $vmlist = PVE
::Cluster
::get_vmlist
();
89 foreach my $vmid (@vmids) {
90 my $d = $vmlist->{ids
}->{$vmid};
91 if ($d && ($d->{node
} ne $nodename)) {
92 push @$skiplist, $vmid;
94 push @localvmids, $vmid;
98 # silent exit if specified VMs run on other nodes
99 return "OK" if !scalar(@vmids);
102 $param->{vmids
} = PVE
::VZDump
::check_vmids
(@vmids)
105 my @exclude = PVE
::Tools
::split_list
(extract_param
($param, 'exclude'));
106 $param->{exclude
} = PVE
::VZDump
::check_vmids
(@exclude);
108 # exclude-path list need to be 0 separated
109 if (defined($param->{'exclude-path'})) {
110 my @expaths = split(/\0/, $param->{'exclude-path'} || '');
111 $param->{'exclude-path'} = [ @expaths ];
114 if (defined($param->{mailto
})) {
115 my @mailto = PVE
::Tools
::split_list
(extract_param
($param, 'mailto'));
116 $param->{mailto
} = [ @mailto ];
119 die "you can only backup a single VM with option --stdout\n"
120 if $param->{stdout
} && scalar(@vmids) != 1;
122 $rpcenv->check($user, "/storage/$param->{storage}", [ 'Datastore.AllocateSpace' ])
123 if $param->{storage
};
128 $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
129 die "interrupted by signal\n";
132 my $vzdump = PVE
::VZDump-
>new($cmdline, $param, $skiplist);
135 $vzdump->getlock($upid); # only one process allowed
138 $vzdump->sendmail([], 0, $err);
142 if (defined($param->{ionice
})) {
143 if ($param->{ionice
} > 7) {
144 PVE
::VZDump
::run_command
(undef, "ionice -c3 -p $$");
146 PVE
::VZDump
::run_command
(undef, "ionice -c2 -n$param->{ionice} -p $$");
149 $vzdump->exec_backup($rpcenv, $user);
152 open STDOUT
, '>/dev/null' if $param->{quiet
} && !$param->{stdout
};
153 open STDERR
, '>/dev/null' if $param->{quiet
};
155 if ($rpcenv->{type
} eq 'cli') {
156 if ($param->{stdout
}) {
158 open my $saved_stdout, ">&STDOUT"
159 || die "can't dup STDOUT: $!\n";
161 open STDOUT
, '>&STDERR' ||
162 die "unable to redirect STDOUT: $!\n";
164 $param->{stdout
} = $saved_stdout;
169 $taskid = $vmids[0] if scalar(@vmids) == 1;
171 return $rpcenv->fork_worker('vzdump', $taskid, $user, $worker);
174 __PACKAGE__-
>register_method ({
175 name
=> 'extractconfig',
176 path
=> 'extractconfig',
178 description
=> "Extract configuration from vzdump backup archive.",
180 description
=> "The user needs 'VM.Backup' permissions on the backed up guest ID, and 'Datastore.AllocateSpace' on the backup storage.",
186 additionalProperties
=> 0,
188 node
=> get_standard_option
('pve-node'),
190 description
=> "Volume identifier",
192 completion
=> \
&PVE
::Storage
::complete_volume
,
196 returns
=> { type
=> 'string' },
200 my $volume = extract_param
($param, 'volume');
202 my $rpcenv = PVE
::RPCEnvironment
::get
();
203 my $authuser = $rpcenv->get_user();
205 my $storage_cfg = PVE
::Storage
::config
();
206 PVE
::Storage
::check_volume_access
($rpcenv, $authuser, $storage_cfg, undef, $volume);
208 return PVE
::Storage
::extract_vzdump_config
($storage_cfg, $volume);