aboutsummaryrefslogtreecommitdiff
path: root/bbot/agent/agent.cxx
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2021-03-16 20:21:59 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2021-03-26 20:00:31 +0300
commit2af2c4f092aa7efffe839ec615c06d22cf43cc3b (patch)
treee84676dbf273602fdf1f3541171df9dad7060daf /bbot/agent/agent.cxx
parent392c6003321047421467e07eac31e12875377ead (diff)
Add support for interactive builds
Diffstat (limited to 'bbot/agent/agent.cxx')
-rw-r--r--bbot/agent/agent.cxx80
1 files changed, 75 insertions, 5 deletions
diff --git a/bbot/agent/agent.cxx b/bbot/agent/agent.cxx
index 6c2e0d9..d85ecf5 100644
--- a/bbot/agent/agent.cxx
+++ b/bbot/agent/agent.cxx
@@ -8,6 +8,7 @@
#include <signal.h> // signal()
#include <stdlib.h> // rand_r()
#include <unistd.h> // sleep(), getuid(), fsync(), [f]stat()
+#include <ifaddrs.h> // getifaddrs(), freeifaddrs()
#include <sys/types.h> // stat
#include <sys/stat.h> // [f]stat()
#include <sys/file.h> // flock()
@@ -62,6 +63,7 @@ namespace bbot
uint16_t offset;
string hname;
+ string hip;
uid_t uid;
string uname;
}
@@ -179,7 +181,8 @@ bootstrap_machine (const dir_path& md,
mm,
obmm ? obmm->machine.mac : nullopt,
ops.bridge (),
- tftpd.port ()));
+ tftpd.port (),
+ false /* pub_vnc */));
{
// If we are terminating with an exception then force the machine down.
@@ -888,7 +891,8 @@ try
mm.machine,
mm.machine.mac,
ops.bridge (),
- tftpd.port ()));
+ tftpd.port (),
+ tm.interactive.has_value ()));
// Note: the machine handling logic is similar to bootstrap.
//
@@ -947,7 +951,9 @@ try
//
size_t to;
const size_t startup_to (120);
- const size_t build_to (ops.build_timeout ());
+ const size_t build_to (tm.interactive
+ ? ops.intactive_timeout ()
+ : ops.build_timeout ());
// Wait periodically making sure the machine is still alive.
//
@@ -1093,6 +1099,8 @@ try
uid = getuid ();
uname = getpwuid (uid)->pw_name;
+ // Obtain our hostname.
+ //
{
char buf[HOST_NAME_MAX + 1];
@@ -1103,6 +1111,44 @@ try
hname = buf;
}
+ // Obtain our IP address as a first discovered non-loopback IPv4 address.
+ //
+ // Note: Linux-specific implementation.
+ //
+ {
+ ifaddrs* i;
+ if (getifaddrs (&i) == -1)
+ fail << "unable to obtain IP addresses: "
+ << system_error (errno, std::generic_category ()); // Sanitize.
+
+ unique_ptr<ifaddrs, void (*)(ifaddrs*)> deleter (i, freeifaddrs);
+
+ for (; i != nullptr; i = i->ifa_next)
+ {
+ sockaddr* sa (i->ifa_addr);
+
+ if (sa != nullptr && // Configured.
+ (i->ifa_flags & IFF_LOOPBACK) == 0 && // Not a loopback interface.
+ (i->ifa_flags & IFF_UP) != 0 && // Up.
+ sa->sa_family == AF_INET) // Ignore IPv6 for now.
+ {
+ char buf[INET_ADDRSTRLEN]; // IPv4 address.
+ if (inet_ntop (AF_INET,
+ &reinterpret_cast<sockaddr_in*> (sa)->sin_addr,
+ buf,
+ sizeof (buf)) == nullptr)
+ fail << "unable to obtain IPv4 address: "
+ << system_error (errno, std::generic_category ()); // Sanitize.
+
+ hip = buf;
+ break;
+ }
+ }
+
+ if (hip.empty ())
+ fail << "no IPv4 address configured";
+ }
+
// On POSIX ignore SIGPIPE which is signaled to a pipe-writing process if
// the pipe reading end is closed. Note that by default this signal
// terminates a process. Also note that there is no way to disable this
@@ -1246,6 +1292,15 @@ try
return std::uniform_int_distribution<unsigned int> (50, 60) (g);
};
+ optional<interactive_mode> imode;
+ optional<string> ilogin;
+
+ if (ops.interactive () != interactive_mode::false_)
+ {
+ imode = ops.interactive ();
+ ilogin = machine_vnc (true /* public */);
+ }
+
for (unsigned int sleep (0);; ::sleep (sleep), sleep = 0)
{
bootstrapped_machines ms (enumerate_machines (ops.machines ()));
@@ -1256,6 +1311,8 @@ try
hname,
tc_name,
tc_ver,
+ imode,
+ ilogin,
fingerprint,
machine_header_manifests {}
};
@@ -1379,6 +1436,19 @@ try
continue;
}
+ // Make sure that the task interactivity matches the requested mode.
+ //
+ if (( t.interactive && !imode) ||
+ (!t.interactive && imode && *imode == interactive_mode::true_))
+ {
+ if (t.interactive)
+ error << "interactive task from " << u << ": " << *t.interactive;
+ else
+ error << "non-interactive task from " << u;
+
+ continue;
+ }
+
l2 ([&]{trace << "task for " << t.name << '/' << t.version << " "
<< "on " << t.machine << " "
<< "from " << u;});
@@ -1558,7 +1628,7 @@ namespace bbot
iface_addr (const string& i)
{
if (i.size () >= IFNAMSIZ)
- throw invalid_argument ("interface nama too long");
+ throw invalid_argument ("interface name too long");
auto_fd fd (socket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
@@ -1572,7 +1642,7 @@ namespace bbot
if (ioctl (fd.get (), SIOCGIFADDR, &ifr) == -1)
throw_system_error (errno);
- char buf[3 * 4 + 3 + 1]; // IPv4 address.
+ char buf[INET_ADDRSTRLEN]; // IPv4 address.
if (inet_ntop (AF_INET,
&reinterpret_cast<sockaddr_in*> (&ifr.ifr_addr)->sin_addr,
buf,