Skip to content

Commit

Permalink
Fix snapshot policy for legacy clients
Browse files Browse the repository at this point in the history
For core <2.10, serve updates from snapshots as before (repo_view is
"unknown").

Only HTTP clients sending X-Repo-View header receive the repo view as
the new feature 6970 says (repo_view is "managed" or "latest").
  • Loading branch information
DavidePrincipi committed Jul 17, 2024
1 parent 3325cec commit f4f1f4e
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 55 deletions.
96 changes: 67 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,34 +74,6 @@ Services are:
- `fpm.service`
- `nginx.service`

## Commands

### `take-snapshot`

To create a snapshot manually run:

runagent -m porthos1 take-snapshot

As alternative start the equivalent Systemd service:

runagent -m porthos1 systemctl --user start snapshot

### `sync-head`

To synchronize the copy of NS8 repodata with its upstream manually run:

runagent -m porthos1 sync-head

As alternative start the equivalent Systemd service:

runagent -m porthos1 systemctl --user start sync-head

### Inspect the services status

Print the status of relevant Systemd units:

runagent -m porthos1 systemctl --user status fpm.service nginx.service snapshot.timer

## Environment variables

- `PORTHOS_RETENTION`, number of snapshots preserved under `/srv/porthos/webroot`
Expand Down Expand Up @@ -138,4 +110,70 @@ net.ipv4.tcp_mem = 42456 169824 679296
net.core.wmem_max = 16482304
net.core.rmem_max = 16482304
net.ipv4.tcp_rmem = 4096 16384 16482304
```
```

## Content policy

Web clients can send an optional `X-Repo-View` header, with value `latest`
or `managed`. Any other value is considered like `latest`, but this
behavior may change in the future.

Header codes:

- `A` Authenticated
- `U` Anonymous
- `M` Managed repo view
- `L` Latest repo view
- `X` X-Repo-View header not sent

Request types:

- `df` request for distfeed (like `repodata.json`)
- `rl` request for rockylinux mirror content

Response types:

- `L` content from latest snapshot (weekly updates)
- `S` content from a managed snapshot (from previous weeks)
- `H` content from distfeed head (updated multiple times per day)

The following table summarizes the response for every headers/request
combination.

| headers/request | df | rl |
|-----------------|----|----|
| AX | S | S |
| AM | S | S |
| AL | H | L |
| UM | H | L |
| UL | H | L |
| UX | L | L |


## Commands

### `take-snapshot`

To create a snapshot manually run:

runagent -m porthos1 take-snapshot

As alternative start the equivalent Systemd service:

runagent -m porthos1 systemctl --user start snapshot

### `sync-head`

To synchronize the copy of NS8 repodata with its upstream manually run:

runagent -m porthos1 sync-head

As alternative start the equivalent Systemd service:

runagent -m porthos1 systemctl --user start sync-head

### Inspect the services status

Print the status of relevant Systemd units:

runagent -m porthos1 systemctl --user status fpm.service nginx.service snapshot.timer
83 changes: 57 additions & 26 deletions imageroot/script/snapshot.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,45 +43,76 @@ function snapshot_age($snapshot) {
return $days_age;
}

function main() {
// Minimum age (days) expected by tiers
$tier_age = [3, 4, 5];

function serve_from_latest_snapshot() {
$lsnapshots = array_map('basename', glob('/srv/porthos/webroot/d20*'));
if (count($lsnapshots) == 0) {
return 'not-found'; // Nginx will fail the file and return 404 for us
}
sort($lsnapshots);
$snapshot = array_pop($lsnapshots);
return $snapshot;
}

function serve_from_snapshots() {
$lsnapshots = array_map('basename', glob('/srv/porthos/webroot/d20*'));
if (count($lsnapshots) == 0) {
http_response_code(404);
echo "Not found\n";
return 'not-found'; // Nginx will not find the file and return 404 for us
}
sort($lsnapshots);
$snapshot = array_pop($lsnapshots);
// Minimum age (days) expected by tiers
$tier_age = [3, 4, 5];
while($snapshot != NULL) {
$tier_id = system_tier($_SERVER['PHP_AUTH_USER']);
if (snapshot_age($snapshot) >= $tier_age[$tier_id]) {
break;
}
$snapshot = array_pop($lsnapshots);
}
return $snapshot;
}

$repo_view = isset($_SERVER['HTTP_X_REPO_VIEW']) ? $_SERVER['HTTP_X_REPO_VIEW'] : "latest";
function main() {
$repo_view = isset($_SERVER['HTTP_X_REPO_VIEW']) ? $_SERVER['HTTP_X_REPO_VIEW'] : "unknown";
$username = isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : "";
$password = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : "";

sort($lsnapshots);

if($repo_view == "managed" && $username && $password) {
// Access to managed updates for authenticated clients.
$snapshot = array_pop($lsnapshots);
while($snapshot != NULL) {
$tier_id = system_tier($username);
if (snapshot_age($snapshot) >= $tier_age[$tier_id]) {
break;
}
$snapshot = array_pop($lsnapshots);
$is_authenticated = ($username != "") && ($password != "");
$is_distfeed_request = substr($_SERVER['DOCUMENT_URI'], 0, 10) == "/distfeed/";

//
// This is the enumeration if input => output cases
//
// AX, AM => SS
// UX => LL
// AL, UL, UM => HL
//
// Where A=Authenticated, U=Not authenticated,
// X=no-view, M=managed view, L=latest view
// SS=from snapshots, LL=from latest,
// HL=distfeed from head, other content from latest
//

if($repo_view == "unknown") {
// Core <2.10 does not send the X-Repo-View header. We implement
// the initial update policy for backward compatibility.
if($is_authenticated) {
$prefix = serve_from_snapshots(); // AX => SS
} else {
$prefix = serve_from_latest_snapshot(); // UX => LL
}
} else if (substr($_SERVER['DOCUMENT_URI'], 0, 10) == "/distfeed/") {
// Access to latest metadata (distfeed) if client is not
// authenticated, or if the request comes from the user through
// the Software Center APIs.
$snapshot = 'head';
} else if($is_authenticated && $repo_view == "managed") {
// Automated nightly update job receive managed updates.
$prefix = serve_from_snapshots(); // AM => SS
} else if($is_distfeed_request) {
$prefix = 'head'; // AL, UL, UM => H.
} else {
// Access to latest DNF mirror contents.
$snapshot = array_pop($lsnapshots);
// AL, UL, UM => .L
$prefix = serve_from_latest_snapshot();
}

header('Cache-Control: private');
header('X-Accel-Redirect: /' . $snapshot . $_SERVER['DOCUMENT_URI']);
header('X-Accel-Redirect: /' . $prefix . $_SERVER['DOCUMENT_URI']);
}

// Run
Expand Down

0 comments on commit f4f1f4e

Please sign in to comment.