1 package PMG
::API2
::Tasks
;
7 use File
::ReadBackwards
;
12 use PMG
::RESTEnvironment
;
13 use PVE
::JSONSchema
qw(get_standard_option);
15 use base
qw(PVE::RESTHandler);
17 __PACKAGE__-
>register_method({
21 description
=> "Read task list for one node (finished tasks).",
23 permissions
=> { check
=> [ 'admin', 'audit' ] },
25 additionalProperties
=> 0,
27 node
=> get_standard_option
('pve-node'),
49 description
=> 'Only list tasks of this type (e.g., aptupdate, saupdate).',
53 description
=> "Only list tasks since this UNIX epoch.",
58 description
=> "Only list tasks until this UNIX epoch.",
63 format
=> 'pve-task-status-type-list',
65 description
=> 'List of Task States that should be returned.',
74 upid
=> { type
=> 'string' },
77 links
=> [ { rel
=> 'child', href
=> "{upid}" } ],
82 my $restenv = PMG
::RESTEnvironment-
>get();
86 my $filename = "/var/log/pve/tasks/index";
88 my $node = $param->{node
};
89 my $start = $param->{start
} || 0;
90 my $limit = $param->{limit
} || 50;
91 my $userfilter = $param->{userfilter
};
92 my $typefilter = $param->{typefilter
};
93 my $since = $param->{since
};
94 my $until = $param->{until};
95 my $errors = $param->{errors
};
104 if (defined($param->{statusfilter
}) && !$errors) {
111 for my $filter (PVE
::Tools
::split_list
($param->{statusfilter
})) {
112 $statusfilter->{lc($filter)} = 1 ;
115 $statusfilter->{ok
} = 0;
121 my $parse_line = sub {
122 if ($line =~ m/^(\S+)(\s([0-9A-Za-z]{8})(\s(\S.*))?)?$/) {
126 if ((my $task = PVE
::Tools
::upid_decode
($upid, 1))) {
127 return if $userfilter && $task->{user
} !~ m/\Q$userfilter\E/i;
128 return if defined($since) && $task->{starttime
} < $since;
129 return if defined($until) && $task->{starttime
} > $until;
130 return if $typefilter && $task->{type
} ne $typefilter;
132 my $statustype = PVE
::Tools
::upid_normalize_status_type
($status);
133 return if !$statusfilter->{$statustype};
135 return if $count++ < $start;
136 return if $limit <= 0;
138 $task->{upid
} = $upid;
139 $task->{endtime
} = hex($endtime) if $endtime;
140 $task->{status
} = $status if $status;
147 if (my $bw = File
::ReadBackwards-
>new($filename)) {
148 while (defined ($line = $bw->readline)) {
153 if (my $bw = File
::ReadBackwards-
>new("$filename.1")) {
154 while (defined ($line = $bw->readline)) {
160 $restenv->set_result_attrib('total', $count);
165 __PACKAGE__-
>register_method({
166 name
=> 'upid_index',
169 description
=> '', # index helper
170 permissions
=> { check
=> [ 'admin', 'audit' ] },
172 additionalProperties
=> 0,
174 node
=> get_standard_option
('pve-node'),
175 upid
=> { type
=> 'string' },
184 links
=> [ { rel
=> 'child', href
=> "{name}" } ],
195 __PACKAGE__-
>register_method({
199 description
=> 'Stop a task.',
202 permissions
=> { check
=> [ 'admin' ] },
204 additionalProperties
=> 0,
206 node
=> get_standard_option
('pve-node'),
207 upid
=> { type
=> 'string' },
210 returns
=> { type
=> 'null' },
214 my ($task, $filename) = PVE
::Tools
::upid_decode
($param->{upid
}, 1);
215 raise_param_exc
({ upid
=> "unable to parse worker upid" }) if !$task;
216 raise_param_exc
({ upid
=> "no such task" }) if ! -f
$filename;
218 my $restenv = PMG
::RESTEnvironment-
>get();
219 PMG
::RESTEnvironment-
>check_worker($param->{upid
}, 1);
224 __PACKAGE__-
>register_method({
225 name
=> 'read_task_log',
226 path
=> '{upid}/log',
229 description
=> "Read task log.",
231 permissions
=> { check
=> [ 'admin', 'audit' ] },
233 additionalProperties
=> 0,
235 node
=> get_standard_option
('pve-node'),
236 upid
=> { type
=> 'string' },
241 description
=> "Start at this line when reading the tasklog",
247 description
=> "The amount of lines to read from the tasklog.",
252 description
=> "Whether the tasklog file should be downloaded. This parameter can't be used in conjunction with other parameters",
262 description
=> "Line number",
266 description
=> "Line text",
275 my ($task, $filename) = PVE
::Tools
::upid_decode
($param->{upid
}, 1);
276 raise_param_exc
({ upid
=> "unable to parse worker upid" }) if !$task;
278 my $restenv = PMG
::RESTEnvironment-
>get();
280 if ($param->{download
}) {
281 die "Parameter 'download' can't be used with other parameters\n"
282 if (defined($param->{start
}) || defined($param->{limit
}));
285 my $use_compression = ( -s
$filename ) > 1024;
287 # 1024 is a practical cutoff for the size distribution of our log files.
288 if ($use_compression) {
289 open($fh, "-|", "/usr/bin/gzip", "-c", "$filename")
290 or die "Could not create compressed file stream for file '$filename' - $!\n";
292 open($fh, '<', $filename) or die "Could not open file '$filename' - $!\n";
295 my $task_time = strftime
('%FT%TZ', gmtime($task->{starttime
}));
296 my $download_name = 'task-'.$task->{node
}.'-'.$task->{type
}.'-'.$task_time.'.log';
302 'content-encoding' => $use_compression ?
'gzip' : undef,
303 'content-type' => "text/plain",
304 'content-disposition' => "attachment; filename=\"".$download_name."\"",
308 my $start = $param->{start
} // 0;
309 my $limit = $param->{limit
} // 50;
311 my ($count, $lines) = PVE
::Tools
::dump_logfile
($filename, $start, $limit);
313 $restenv->set_result_attrib('total', $count);
320 my $exit_status_cache = {};
322 __PACKAGE__-
>register_method({
323 name
=> 'read_task_status',
324 path
=> '{upid}/status',
327 description
=> "Read task status.",
329 permissions
=> { check
=> [ 'admin', 'audit' ] },
331 additionalProperties
=> 0,
333 node
=> get_standard_option
('pve-node'),
334 upid
=> { type
=> 'string' },
344 type
=> 'string', enum
=> ['running', 'stopped'],
351 my ($task, $filename) = PVE
::Tools
::upid_decode
($param->{upid
}, 1);
352 raise_param_exc
({ upid
=> "unable to parse worker upid" }) if !$task;
353 raise_param_exc
({ upid
=> "no such task" }) if ! -f
$filename;
357 my $pstart = PVE
::ProcFSTools
::read_proc_starttime
($task->{pid
});
358 $task->{status
} = ($pstart && ($pstart == $task->{pstart
})) ?
359 'running' : 'stopped';
361 $task->{upid
} = $param->{upid
}; # include upid
363 if ($task->{status
} eq 'stopped') {
364 if (!defined($exit_status_cache->{$task->{upid
}})) {
365 $exit_status_cache->{$task->{upid
}} =
366 PVE
::Tools
::upid_read_status
($task->{upid
});
368 $task->{exitstatus
} = $exit_status_cache->{$task->{upid
}};