Skip to content

Commit eb65c69

Browse files
Merge pull request #25 from DavidePrincipi/tier-id-calc-fix
Autoupdate policy implementation (beta6)
2 parents 4882811 + a4591ac commit eb65c69

File tree

7 files changed

+181
-23
lines changed

7 files changed

+181
-23
lines changed

porthos/README.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,41 @@ If `icat` field is not set, the `subscription.php` replies with 403 - forbidden.
140140
If `secret` field is not set, both `auth.php` and `subscription.php` reply with
141141
403 - forbidden, unless `$config['legacy_auth']` is enabled.
142142

143+
## Porthos repository autoupdate policy
144+
145+
When a client accesses the `autoupdate/` contents it is possible to
146+
differentiate what it can see, on a client `tier_id` and `version` basis.
147+
148+
The **default** policy is to return the repository state of the last monday, or
149+
the previous one, depending on the tier number. Custom policies can be
150+
configured by adding items to the `$config['autoupdate_policy']` array.
151+
152+
Example 1:
153+
154+
```php
155+
$config['autoupdate_policy'] = array(
156+
'7.6.1810/0' => 'head',
157+
'7.6.1810/*' => 'empty',
158+
);
159+
```
160+
161+
This setting says that clients of tier 0 requesting version 7.6.1810 can see the
162+
`head` repository state. Clients of other tiers (identified by `*`) always see
163+
an `empty` repository.
164+
165+
Example 2:
166+
167+
```php
168+
$config['autoupdate_policy'] = array(
169+
'7.6.1810/*' => 'default',
170+
'7.6.1810/2' => 'fixed/d20191030',
171+
);
172+
```
173+
174+
In this case clients of tier 2 see the repository state as it was on 2019-10-30.
175+
Other clients see the repository state according to the default policy (note
176+
that the corresponding line can be omitted because it already corresponds to the
177+
default policy).
143178

144179
## Repository management commands
145180

porthos/root/srv/porthos/script/auth.php

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,14 @@
5858
$valid_credentials = $valid_credentials && ($access['tier_id'] !== FALSE);
5959

6060
if($access['tier_id'] < 0) {
61-
$hash = 0;
61+
$hash = $config['tier_seed'] ?: 0;
6262
foreach(str_split($_SERVER['PHP_AUTH_USER']) as $c) {
6363
$hash += ord($c);
6464
}
65-
$hash = $hash % 256;
66-
if($hash < 26) { // 10%
65+
$hash = $hash % 10;
66+
if($hash < 1) { // 10%
6767
$tier_id = 0;
68-
} elseif($hash < 77) { // +20% = 30%
68+
} elseif($hash < 3) { // +20% = 30%
6969
$tier_id = 1;
7070
} else { // +70% = 100%
7171
$tier_id = 2;
@@ -78,7 +78,7 @@
7878
if($is_tier_request && $valid_credentials) {
7979
// Seeking a snapshot is a time-consuming op. Ensure we have valid
8080
// credentials before running it!
81-
$snapshot = lookup_snapshot($uri['full_path'], $tier_id, $config['week_size']);
81+
$snapshot = lookup_snapshot($uri['full_path'], $uri['version'], $tier_id);
8282
} else {
8383
$snapshot = 'head';
8484
}
@@ -108,4 +108,8 @@
108108
}
109109

110110
header('Cache-Control: private');
111-
return_file('/' . $snapshot . $uri['full_path']);
111+
if($snapshot == 'empty') {
112+
return_file('/empty/repodata/' . basename($uri['full_path']));
113+
} else {
114+
return_file('/' . $snapshot . $uri['full_path']);
115+
}

porthos/root/srv/porthos/script/config-porthos.php

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,20 @@
5656
// the PHP timezone for this application
5757
$config['timezone'] = 'UTC';
5858

59-
// stop_autoupdate (array)
60-
// forcibly stop autoupdate contents distribution for the listed versions.
61-
// The /empty repository is served instead.
62-
$config['stop_autoupdate'] = array();
59+
// autoupdate_policy (array)
60+
// Decide the content returned for a given version/tier_id combination.
61+
// Valid keys are, for instance "7.6.1810/2" "6.10/0" "7.7.1908/*" ...
62+
// Valid values are "head", "empty", "fixed/d20191104" (fixed snapshot name -
63+
// if the snapshot dir does not exist, "empty" is assumed) and "default"
64+
// (automatically selects the previous monday snapshot).
65+
$config['autoupdate_policy'] = array();
66+
67+
// snapshots_dir (string)
68+
// Filesystem directory path where snapshot directories are stored with
69+
// trailing slash.
70+
$config['snapshots_dir'] = '/srv/porthos/webroot/';
71+
72+
// tier_seed (int)
73+
// The system_id value is reduced to the integer range 0-9 plus the seed.
74+
// The resulting value is mapped to a tier_id
75+
$config['tier_seed'] = 0;

porthos/root/srv/porthos/script/lib.php

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,49 @@ function get_snapshot_timestamp($snapshot_name) {
7979
return mktime(0, 0, 0, $parts['month'], $parts['day'], $parts['year']);
8080
}
8181

82-
function lookup_snapshot($path, $tier_id = 0, $week_size = 5) {
83-
$root_path = "/srv/porthos/webroot/";
82+
function lookup_policy($version, $tier_id) {
83+
global $config;
84+
85+
$policy_map = $config['autoupdate_policy'] ?: array();
86+
$policy_key = $version . '/' . $tier_id;
87+
$poldef_key = $version . '/*';
88+
89+
if(isset($policy_map[$policy_key])) {
90+
$value = $policy_map[$policy_key];
91+
} elseif(isset($policy_map[$poldef_key])) {
92+
$value = $policy_map[$poldef_key];
93+
} else {
94+
$value = 'default';
95+
}
96+
97+
return $value;
98+
}
99+
100+
function lookup_fixed($path, $snapshot_start) {
101+
global $config;
102+
103+
$root_path = $config['snapshots_dir'] ?: "/srv/porthos/webroot/";
104+
$snapshots = array_map('basename', glob($root_path . "d20*"));
105+
106+
$start_key = array_search($snapshot_start, $snapshots);
107+
if( ! $start_key) {
108+
// the fixed snapshot does not exist: fall back to the empty repository.
109+
return 'empty';
110+
}
111+
$snapshots = array_slice($snapshots, $start_key);
112+
foreach($snapshots as $snapshot) {
113+
if(is_file($root_path . $snapshot . '/' . $path)) {
114+
return $snapshot;
115+
}
116+
}
117+
return 'head';
118+
}
119+
120+
function lookup_monday($path, $tier_id) {
121+
global $config;
122+
123+
$week_size = $config['week_size'] ?: 5;
124+
$root_path = $config['snapshots_dir'] ?: "/srv/porthos/webroot/";
84125
$snapshots = array_reverse(array_map('basename', glob($root_path . "d20*")));
85126
$last_snapshot_day_id = date('w', get_snapshot_timestamp($snapshots[0]));
86127
// $monday_offset formula:
@@ -93,4 +134,19 @@ function lookup_snapshot($path, $tier_id = 0, $week_size = 5) {
93134
}
94135
}
95136
return $i < 0 ? 'head' : $snapshots[$i];
96-
}
137+
}
138+
139+
function lookup_snapshot($path, $version, $tier_id) {
140+
global $config;
141+
142+
$policy_name = lookup_policy($version, $tier_id);
143+
if($policy_name == 'default') {
144+
return lookup_monday($path, $tier_id);
145+
} elseif(substr($policy_name, 0, 6) == 'fixed/') {
146+
return lookup_fixed($path, substr($policy_name, 6));
147+
} elseif($policy_name == 'empty') {
148+
return 'empty';
149+
} else {
150+
return 'head';
151+
}
152+
}

porthos/root/srv/porthos/script/mirrorlist.php

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,5 @@
5252
}
5353

5454
foreach($config['base_urls'] as $baseurl) {
55-
if($use_tier && in_array($version, $config['stop_autoupdate'])) {
56-
echo $baseurl . "empty\n";
57-
} else {
58-
echo $baseurl . $path . "${version}/${repo}/${arch}\n";
59-
}
55+
echo $baseurl . $path . "${version}/${repo}/${arch}\n";
6056
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
/*
4+
* Copyright (C) 2019 Nethesis S.r.l.
5+
* http://www.nethesis.it - nethserver@nethesis.it
6+
*
7+
* This script is part of Dartagnan.
8+
*
9+
* Dartagnan is free software: you can redistribute it and/or modify
10+
* it under the terms of the GNU Affero General Public License as published by
11+
* the Free Software Foundation, either version 3 of the License,
12+
* or any later version.
13+
*
14+
* Dartagnan is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
* GNU Affero General Public License for more details.
18+
*
19+
* You should have received a copy of the GNU Affero General Public License
20+
* along with Dartagnan. If not, see COPYING.
21+
*/
22+
23+
//
24+
// Test the automatic tier assignment procedure.
25+
//
26+
// 1. Read a list of system_id keys from standard input
27+
// 2. Print the system_id with resulting tier_id
28+
//
29+
30+
while($system_id = trim(fgets(STDIN))) {
31+
32+
$hash = 0;
33+
34+
foreach(str_split($system_id) as $c) {
35+
$hash += ord($c);
36+
}
37+
$hash = $hash % 10;
38+
if($hash < 1) { // 10%
39+
$tier_id = 0;
40+
} elseif($hash < 3) { // +20% = 30%
41+
$tier_id = 1;
42+
} else { // +70% = 100%
43+
$tier_id = 2;
44+
}
45+
46+
echo $system_id . ' ' . $tier_id . "\n";
47+
}

porthos/root/srv/porthos/script/calc-tierid.php renamed to porthos/root/srv/porthos/test/tier-hits.php

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@
2020
* along with Dartagnan. If not, see COPYING.
2121
*/
2222

23+
//
24+
// Test the automatic tier assignment procedure.
25+
//
26+
// 1. Read a list of system_id keys from standard input
27+
// 2. Print the tiers hit percentages
28+
//
29+
2330
$tier_hits = [0,0,0];
2431

2532
while($system_id = trim(fgets(STDIN))) {
@@ -29,10 +36,10 @@
2936
foreach(str_split($system_id) as $c) {
3037
$hash += ord($c);
3138
}
32-
$hash = $hash % 256;
33-
if($hash < 26) { // 10%
39+
$hash = $hash % 10;
40+
if($hash < 1) { // 10%
3441
$tier_id = 0;
35-
} elseif($hash < 77) { // +20% = 30%
42+
} elseif($hash < 3) { // +20% = 30%
3643
$tier_id = 1;
3744
} else { // +70% = 100%
3845
$tier_id = 2;
@@ -44,7 +51,7 @@
4451

4552
$total_hits = array_sum($tier_hits);
4653

47-
printf("Total: %d\n", $total_hits);
54+
printf("Total hits: %d\n", $total_hits);
4855
foreach($tier_hits as $tier_id => $hits) {
49-
printf("Tier %d, hits %4d - %.2f\n", $tier_id, $hits, 100*$hits/$total_hits);
56+
printf("- tier %d: %2.2f%% (%d)\n", $tier_id, 100*$hits/$total_hits, $hits);
5057
}

0 commit comments

Comments
 (0)