Skip to content

Commit 8773335

Browse files
committed
Throttle openQA jobs resources based on test parameters size
Define a priority malus for jobs resources exceeding given limit. Store the configuration in openqa.ini file 'prio_throttling_parameters', in the format therein described "PAR1=MAX1:MALUS1,PAR2=..:..,", to load the paramters details at server start. - Ticket poo#192952
1 parent 1e0c209 commit 8773335

File tree

5 files changed

+57
-1
lines changed

5 files changed

+57
-1
lines changed

etc/openqa/openqa.ini

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,13 @@ concurrent = 0
369369
## scheduled products without any jobs (e.g. due to errors) are not immediately
370370
## cleaned up.
371371
#scheduled_product_min_storage_duration = 34
372+
## Job resources throttling configuration:
373+
## a string of comma-separated jobs resources,
374+
## formatted like: "RES1=THR1:MAL1,RES2=THR2:MAL2,..."
375+
## where THR# is the maximum threshold of a RESOURCE# value,
376+
## and MAL# is a malus priority to multiply as many times as THR# increases:
377+
## PRIO1 = base + int(RESOURCE1/THR1)*MAL1
378+
#prio_throttling_parameters
372379

373380
[archiving]
374381
## Moves logs of jobs which are preserved during the cleanup because they are

lib/OpenQA/Schema/ResultSet/Jobs.pm

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,14 @@ sub latest_jobs ($self, $until = undef) {
101101
return @latest;
102102
}
103103

104+
sub load_throttling_config ($config_string) {
105+
# parse to hash "{ PAR1 => [THR1, MAL1], PAR2 => [THR2, MAL2], ...}"
106+
# the prio_throttling_parameters configuration string; see openqa.ini
107+
return unless ($config_string && $config_string =~ /=\d+:/);
108+
my %hash = map { my ($k, $v) = split /=/, $_, 2; uc($k) => [split(/:/, $v)] } split /,/, $config_string;
109+
return \%hash;
110+
}
111+
104112
sub create_from_settings ($self, $settings, $scheduled_product_id = undef) {
105113
my %settings = %$settings;
106114
my %new_job_args;
@@ -158,6 +166,21 @@ sub create_from_settings ($self, $settings, $scheduled_product_id = undef) {
158166
$new_job_args{priority} += $malus;
159167
}
160168
}
169+
my $throttling = OpenQA::App->singleton->config->{misc_limits}->{prio_throttling_parameters};
170+
$throttling = load_throttling_config($throttling);
171+
# apply resources throttling control
172+
if ($throttling && ref $throttling eq 'HASH') {
173+
for my $resource (keys %$throttling) {
174+
next if !defined $settings{$resource};
175+
my @limits = $throttling->{$resource};
176+
if ($settings{$resource} > $limits[0]) {
177+
my $malus = int($settings{$resource} / $limits[0]) * $limits[1];
178+
$debug_msg = sprintf 'Adding priority malus to newly created job (old: %d, malus: %s)',
179+
$new_job_args{priority}, $malus;
180+
$new_job_args{priority} += $malus;
181+
}
182+
}
183+
}
161184

162185
my $job = $self->create(\%new_job_args);
163186
log_debug(sprintf "(Job %d) $debug_msg", $job->id) if $debug_msg;

lib/OpenQA/Setup.pm

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ sub read_config ($app) {
243243
mcp_max_result_size => 500000,
244244
max_job_time_prio_scale => 100,
245245
scheduled_product_min_storage_duration => 34,
246+
prio_throttling_parameters => '',
246247
},
247248
archiving => {
248249
archive_preserved_important_jobs => 0,
@@ -293,6 +294,12 @@ sub read_config ($app) {
293294
if (my $minion_fail_job_blocklist = $config->{influxdb}->{ignored_failed_minion_jobs}) {
294295
$config->{influxdb}->{ignored_failed_minion_jobs} = [split(/\s+/, $minion_fail_job_blocklist)];
295296
}
297+
my $throttling = $config->{misc_limits}->{prio_throttling_parameters};
298+
if ($throttling && length $throttling) {
299+
$config->{misc_limits}->{prio_throttling_parameters} =~ s/\s+//g;
300+
die("Wrong formatting for 'prio_throttling_parameters' in openqa.ini")
301+
unless ($throttling =~ /^[A-Z_]+=\d+:\d+(?:,[A-Z_]+=\d+:\d+)*$/i);
302+
}
296303
my $results = delete $global_config->{parallel_children_collapsable_results};
297304
$global_config->{parallel_children_collapsable_results_sel}
298305
= ' .status' . join('', map { ":not(.result_$_)" } split(/\s+/, $results));

t/21-needles.t

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,9 @@ my %settings = (
4343
ISO => 'whatever.iso',
4444
MACHINE => 'alpha',
4545
ARCH => 'x86_64',
46+
MAX_JOB_TIME => '7600',
47+
_PRIORITY => 50,
4648
);
47-
4849
my $mock_utils = Test::MockModule->new('OpenQA::Utils');
4950
$mock_utils->redefine('run_cmd_with_log', 1);
5051
$mock_utils->redefine('run_cmd_with_log_return_error', 1);
@@ -54,6 +55,23 @@ my $schema = OpenQA::Test::Database->new->create;
5455
my $needledir_archlinux = 't/data/openqa/share/tests/archlinux/needles';
5556
my $needledir_fedora = 't/data/openqa/share/tests/fedora/needles';
5657
# create dummy job
58+
59+
my $mock_config = {
60+
misc_limits => {prio_throttling_parameters => '', max_job_time_prio_scale => 100},
61+
global => {worker_timeout => 900},
62+
'scm git' => {checkout_needles_sha => 'yes', allow_arbitrary_url_fetch => 'yes'}};
63+
my $mock_app = Test::MockModule->new('OpenQA::App');
64+
my $mock_log = Test::MockModule->new('Mojo::Log');
65+
$mock_log->redefine('error', sub { print STDERR $_[1] . "\n" });
66+
$mock_log->redefine('info', sub { print STDOUT $_[1] . "\n" });
67+
$mock_log->redefine('debug', sub { print STDOUT $_[1] . "\n" });
68+
my $mock_singleton = bless {config => $mock_config}, 'OpenQA::App';
69+
# Add config and log as methods
70+
no strict 'refs';
71+
*{'OpenQA::App::config'} = sub { return $_[0]->{config} };
72+
*{'OpenQA::App::log'} = sub { return bless {}, 'Mojo::Log' };
73+
use strict 'refs';
74+
$mock_app->redefine('singleton', sub { return $mock_singleton });
5775
my $job = $schema->resultset('Jobs')->create_from_settings(\%settings);
5876
# create dummy module
5977
$job->insert_module({name => 'a', category => 'a', script => 'a', flags => {}});

t/config.t

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ subtest 'Test configuration default modes' => sub {
193193
mcp_max_result_size => 500000,
194194
max_job_time_prio_scale => 100,
195195
scheduled_product_min_storage_duration => 34,
196+
prio_throttling_parameters => '',
196197
},
197198
archiving => {
198199
archive_preserved_important_jobs => 0,

0 commit comments

Comments
 (0)