ports/infrastructure/lib/DPB/Host.pm

171 lines
4 KiB
Perl

# ex:ts=8 sw=4:
# $OpenBSD: Host.pm,v 1.16 2023/05/06 05:20:31 espie Exp $
#
# Copyright (c) 2010-2013 Marc Espie <espie@openbsd.org>
#
# 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;
# we have unique objects for hosts, so we can put properties in there.
# synopsis
# $host = DPB::Host->new('name', $prop);
# then it can be used to obtain a shell to run things
# ... and also the core class responsible for forking
# so the full run is usually
# $core = $host->shellclass->new($host);
# attach job to core (a job is a list of tasks)
# $core->task->run;
# where task knows how to fork, and then it uses
# $core->host->shell to execute commands
# there is a registry of hosts accessible by name:
# DPB::Host->retrieve(name)
# a host specific for fetching
# DPB::Host->fetch_host($prop)
# a quick way to run shitz before full initialization
# DPB::Host::Localhost->getshell($state)
# (this will make use of default_prop/chroot in state
# if already setup)
# actually, the cores are created through host->new_init_core
# which will start up the initialization for each core
# and the finalization code will clone and register actual cores
package DPB::Host;
my $hosts = {};
sub shell($self)
{
# XXX create a lazy shell so host registration already occurred
$self->{shell} //= $self->shellclass->new($self);
return $self->{shell};
}
sub create($class, $name, $prop)
{
return bless {host => $name, prop => $prop }, $class;
}
sub new($class, $name, $prop = undef)
{
if ($class->name_is_localhost($name)) {
$class = "DPB::Host::Localhost";
$name = 'localhost';
} else {
require DPB::Core::Distant;
$class = "DPB::Host::Distant";
$prop->{socket} = "/tmp/ssh-$name-$prop->{master_pid}";
}
$hosts->{$name} //= $class->create($name, $prop);
return $hosts->{$name};
}
sub retrieve($class, $name)
{
if ($class->name_is_localhost($name)) {
return $hosts->{localhost};
} else {
return $hosts->{$name};
}
}
sub fetch_host($class, $prop)
{
$hosts->{FETCH} //= DPB::Host::Localhost->create('localhost', $prop);
return $hosts->{FETCH};
}
sub new_init_core($self)
{
return $self->coreclass->new_noreg($self);
}
sub coreclass($)
{
return "DPB::Core";
}
sub name($self)
{
return $self->{host};
}
sub fullname($self)
{
my $name = $self->name;
if (defined $self->{prop}->{jobs}) {
$name .= "/$self->{prop}->{jobs}";
}
return $name;
}
sub name_is_localhost($class, $host)
{
if ($host eq "localhost" or $host eq DPB::Core::Local->hostname) {
return 1;
} else {
return 0;
}
}
package DPB::Host::Localhost;
our @ISA = qw(DPB::Host);
sub create($class, $name, $prop)
{
$prop->{iamroot} = $< == 0;
$prop->{build_user}->enforce_local
if defined $prop->{build_user};
return $class->SUPER::create('localhost', $prop);
}
sub is_localhost($)
{
return 1;
}
sub is_alive($)
{
return 1;
}
sub shellclass($self)
{
if ($self->{prop}{iamroot}) {
return "DPB::Shell::Local::Root";
} elsif ($self->{prop}{chroot}) {
return "DPB::Shell::Local::Chroot";
} else {
return "DPB::Shell::Local";
}
}
# XXX this is a "quicky" local shell before we set up hosts properly
sub getshell($class, $state)
{
my $prop;
if ($state->{default_prop}) {
$prop = $state->{default_prop};
} else {
$prop = {};
if ($state->{chroot}) {
$prop->{chroot} = $state->{chroot};
}
}
my $h = $class->create('localhost', $prop);
return $h->shellclass->new($h);
}
1;