App-FuguVM
view release on metacpan or search on metacpan
lib/App/FuguVM/Proxy.pm view on Meta::CPAN
# ex:ts=8 sw=4:
# $OpenBSD$
#
# Copyright (c) 2024 Dick Olsson <hi@senzilla.io>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
use v5.36;
package App::FuguVM::Proxy;
our $VERSION = '0.2.0';
use Fugu::Log;
use Fugu::Proxy;
our @ISA = ('Fugu::Proxy');
# App::FuguVM::Proxy - the OpenBSD mirror policy over Fugu::Proxy.
#
# The generic proxy holds the serve loop, the cache and the metadata.
# This file holds only what is true of an OpenBSD mirror and of a QEMU
# guest: which URL is worth keeping, how to prune a release that is no
# longer in use, the address that the guest reaches the host by, and
# the port range.
# QEMU user-mode networking puts the host at this address. A guest
# that fetches through the proxy names it, and no other address
# reaches back out of the SLIRP network.
use constant HOST_GATEWAY => '10.0.2.2';
# $class->run_child($port, $cache_dir):
# The entry point of the spawned child. The child builds its own
# cache, warms the metadata, and serves until a SIGTERM.
#
# The spawn passes a fixed argument list, so the distfile cap
# reaches the child through the environment, which it inherits
# from fuguvm. An absent variable means 0, and 0 turns the
# distfile cache off.
sub run_child ( $class, $port, $cache_dir )
{
my $log = Fugu::Log->new( mode => 'stderr', level => 'debug' );
my $limit = $ENV{FUGUVM_DISTFILE_LIMIT} // 0;
$limit = 0 if $limit !~ /\A[0-9]+\z/;
my $self = bless {
cache => App::FuguVM::Proxy::Cache->new( $cache_dir, $limit ),
meta => Fugu::Proxy::Meta->new,
log => $log,
}, $class;
$log->info( 'Proxy starting on port %d', $port );
$log->info( 'Cache directory: %s', $cache_dir );
$self->warm;
return $self->serve($port);
}
# $self->guest_url:
# Return the proxy URL as the guest reaches it, through the QEMU
# gateway. The loopback address serves the same proxy, but a
# guest cannot reach it. The method returns undef while the
# proxy does not run: a port that a crash left behind is not a
# reachable proxy.
sub guest_url ($self)
{
return if !$self->is_running;
my $port = $self->port;
return if !defined $port;
return 'http://' . HOST_GATEWAY . ":$port";
}
package App::FuguVM::Proxy::Cache;
our $VERSION = '0.2.0';
use Fugu::Log;
use Fugu::Proxy;
our @ISA = ('Fugu::Proxy::Cache');
# App::FuguVM::Proxy::Cache - which parts of an OpenBSD mirror to keep.
#
# The patterns are the release tree, the packages, the syspatch sets,
# the source tarballs and the files that an installer reads. Every one
# of them is version-scoped, so nothing here outlives the release it
# belongs to. That is what makes prune safe.
#
# The distfile tree is the one exception: a distfile belongs to a
# port and not to a release, so no version scopes it and prune leaves
# it. The distfile cap of trim_distfiles is its bound instead, and
# the tree is cacheable only while the cap is above zero.
my @CACHEABLE = (
qr{/pub/OpenBSD/\d+\.\d+/\w+/.*\.(tgz|img|gz)$}, # File sets
qr{/pub/OpenBSD/syspatch/.*\.tgz$}, # Patches
qr{/pub/OpenBSD/\d+\.\d+/packages/\w+/.*\.tgz$}, # Packages
qr{/pub/OpenBSD/\d+\.\d+/\w+/SHA256(\.sig)?$}, # Checksums
qr{/pub/OpenBSD/\d+\.\d+/\w+/miniroot\d+\.img$}, # Miniroot images
( run in 1.883 second using v1.01-cache-2.11-cpan-5c0b1e786e0 )