* [pve-devel] [PATCH v2 container 1/2] Add module for reading state changes from monitor socket
@ 2020-09-08 11:58 Fabian Ebner
2020-09-08 11:58 ` [pve-devel] [PATCH v2 container 2/2] Improve feedback for startup Fabian Ebner
2020-09-09 19:09 ` [pve-devel] applied-series: [PATCH v2 container 1/2] Add module for reading state changes from monitor socket Thomas Lamprecht
0 siblings, 2 replies; 3+ messages in thread
From: Fabian Ebner @ 2020-09-08 11:58 UTC (permalink / raw)
To: pve-devel; +Cc: Wolfgang Bumiller
Will be used to monitor state changes on container startup.
Co-developed-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
---
New in v2.
I hard-coded the name of the abstract UNIX socket instead of
trying to re-implement lxc/monitor.c's lxc_monitor_sock_name
function. For us, is it true that the lxcpath is always '/varl/lib/lxc'?
Otherwise this won't always work.
src/PVE/LXC/Makefile | 1 +
src/PVE/LXC/Monitor.pm | 92 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 93 insertions(+)
create mode 100644 src/PVE/LXC/Monitor.pm
diff --git a/src/PVE/LXC/Makefile b/src/PVE/LXC/Makefile
index f4f4dc1..a190260 100644
--- a/src/PVE/LXC/Makefile
+++ b/src/PVE/LXC/Makefile
@@ -4,6 +4,7 @@ SOURCES= \
Config.pm \
Create.pm \
Migrate.pm \
+ Monitor.pm \
Setup.pm \
Tools.pm
diff --git a/src/PVE/LXC/Monitor.pm b/src/PVE/LXC/Monitor.pm
new file mode 100644
index 0000000..3a592b5
--- /dev/null
+++ b/src/PVE/LXC/Monitor.pm
@@ -0,0 +1,92 @@
+# LXC monitor socket
+
+package PVE::LXC::Monitor;
+
+use strict;
+use warnings;
+
+use IO::Socket::UNIX;
+use Socket qw(SOCK_STREAM);
+use POSIX qw(NAME_MAX);
+
+use constant {
+ STATE_STOPPED => 0,
+ STATE_STARTING => 1,
+ STATE_RUNNING => 2,
+ STATE_STOPPING => 3,
+ STATE_ABORTING => 4,
+ STATE_FREEZING => 5,
+ STATE_FROZEN => 6,
+ STATE_THAWED => 7,
+ MAX_STATE => 8,
+};
+
+my $LXC_MSG_SIZE = length(pack('I! Z'.(NAME_MAX+1).' x![I] I', 0, "", 0));
+# Unpack an lxc_msg struct.
+my sub _unpack_lxc_msg($) {
+ my ($packet) = @_;
+
+ # struct lxc_msg {
+ # lxc_msg_type_t type;
+ # char name[NAME_MAX+1];
+ # int value;
+ # };
+
+ my ($type, $name, $value) = unpack('I!Z'.(NAME_MAX+1).'I!', $packet);
+
+ if ($type == 0) {
+ $type = 'STATE';
+ } elsif ($type == 1) {
+ $type = 'PRIORITY';
+ } elsif ($type == 2) {
+ $type = 'EXITCODE';
+ } else {
+ warn "unsupported lxc message type $type received\n";
+ $type = undef;
+ }
+
+ return ($type, $name, $value);
+}
+
+# Opens the monitor socket
+#
+# Dies on errors
+sub get_monitor_socket {
+ my $socket = IO::Socket::UNIX->new(
+ Type => SOCK_STREAM(),
+ # assumes that lxcpath is '/var/lib/lxc', the hex part is a hash of the lxcpath
+ Peer => "\0lxc/ad055575fe28ddd5//var/lib/lxc",
+ );
+ if (!defined($socket)) {
+ die "failed to connect to monitor socket: $!\n";
+ }
+
+ return $socket;
+}
+
+# Read an lxc message from a socket.
+#
+# Returns undef on EOF
+# Otherwise returns a (type, vmid, value) tuple.
+#
+# The returned 'type' currently can be 'STATE', 'PRIORITY' or 'EXITSTATUS'.
+sub read_lxc_message($) {
+ my ($socket) = @_;
+
+ my $msg;
+ my $got = recv($socket, $msg, $LXC_MSG_SIZE, 0)
+ // die "failed to read from state socket: $!\n";
+
+ if (length($msg) == 0) {
+ return undef;
+ }
+
+ die "short read on state socket ($LXC_MSG_SIZE != ".length($msg).")\n"
+ if length($msg) != $LXC_MSG_SIZE;
+
+ my ($type, $name, $value) = _unpack_lxc_msg($msg);
+
+ return ($type, $name, $value);
+}
+
+1;
--
2.20.1
^ permalink raw reply [flat|nested] 3+ messages in thread
* [pve-devel] [PATCH v2 container 2/2] Improve feedback for startup
2020-09-08 11:58 [pve-devel] [PATCH v2 container 1/2] Add module for reading state changes from monitor socket Fabian Ebner
@ 2020-09-08 11:58 ` Fabian Ebner
2020-09-09 19:09 ` [pve-devel] applied-series: [PATCH v2 container 1/2] Add module for reading state changes from monitor socket Thomas Lamprecht
1 sibling, 0 replies; 3+ messages in thread
From: Fabian Ebner @ 2020-09-08 11:58 UTC (permalink / raw)
To: pve-devel
Since it was necessary to switch to 'Type=Simple' in the systemd
service, see 545d6f0a13ac2bf3a8d3f224c19c0e0def12116d,
'systemctl start' would not wait for the 'lxc-start' command anymore.
Thus every container start was reported as a success and the 'post-start'
hook would trigger immediately after the 'systemctl start' command.
Use the monitor socket to get the necessary information and detect
startup failure, and only run the 'post-start' hookscript after
the container is effectively running. If something goes wrong
with the monitor socket, for example if lxc-monitord is not running,
fall back to the old behavior.
Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
---
Changes from v1:
* use monitor socket directly instead of forking off an lxc-monitor process
* use run_with_timeout helper
* warn instead of die on unexpected message
src/PVE/LXC.pm | 40 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 39 insertions(+), 1 deletion(-)
diff --git a/src/PVE/LXC.pm b/src/PVE/LXC.pm
index db5b8ca..370adda 100644
--- a/src/PVE/LXC.pm
+++ b/src/PVE/LXC.pm
@@ -32,6 +32,7 @@ use PVE::LXC::Config;
use PVE::GuestHelpers qw(safe_string_ne safe_num_ne safe_boolean_ne);
use PVE::LXC::Tools;
use PVE::LXC::CGroup;
+use PVE::LXC::Monitor;
use Time::HiRes qw (gettimeofday);
my $have_sdn;
@@ -2191,10 +2192,47 @@ sub vm_start {
PVE::Storage::activate_volumes($storage_cfg, $vollist);
+ my $monitor_socket = eval { PVE::LXC::Monitor::get_monitor_socket(); };
+ warn $@ if $@;
+
+ my $monitor_state_change = sub {
+ die "no monitor socket" if !defined($monitor_socket);
+
+ while (1) {
+ my ($type, $name, $value) = PVE::LXC::Monitor::read_lxc_message($monitor_socket);
+
+ die "monitor socket EOF" if !defined($type);
+
+ next if $name ne "$vmid" || $type ne 'STATE';
+
+ if ($value eq PVE::LXC::Monitor::STATE_STARTING) {
+ alarm(0); # don't timeout after seeing the starting state
+ } elsif ($value eq PVE::LXC::Monitor::STATE_ABORTING ||
+ $value eq PVE::LXC::Monitor::STATE_STOPPING ||
+ $value eq PVE::LXC::Monitor::STATE_STOPPED) {
+ return 0;
+ } elsif ($value eq PVE::LXC::Monitor::STATE_RUNNING) {
+ return 1;
+ } else {
+ warn "unexpected message from monitor socket - " .
+ "type: '$type' - value: '$value'\n";
+ }
+ }
+ };
+
my $cmd = ['systemctl', 'start', "pve-container\@$vmid"];
PVE::GuestHelpers::exec_hookscript($conf, $vmid, 'pre-start', 1);
- eval { PVE::Tools::run_command($cmd); };
+ eval {
+ PVE::Tools::run_command($cmd);
+
+ my $success = eval { PVE::Tools::run_with_timeout(10, $monitor_state_change); };
+ if (my $err = $@) {
+ warn "problem with monitor socket: $err - continuing anyway\n";
+ } elsif (!$success) {
+ die "startup for container '$vmid' failed\n";
+ }
+ };
if (my $err = $@) {
unlink $skiplock_flag_fn;
die $err;
--
2.20.1
^ permalink raw reply [flat|nested] 3+ messages in thread
* [pve-devel] applied-series: [PATCH v2 container 1/2] Add module for reading state changes from monitor socket
2020-09-08 11:58 [pve-devel] [PATCH v2 container 1/2] Add module for reading state changes from monitor socket Fabian Ebner
2020-09-08 11:58 ` [pve-devel] [PATCH v2 container 2/2] Improve feedback for startup Fabian Ebner
@ 2020-09-09 19:09 ` Thomas Lamprecht
1 sibling, 0 replies; 3+ messages in thread
From: Thomas Lamprecht @ 2020-09-09 19:09 UTC (permalink / raw)
To: Proxmox VE development discussion, Fabian Ebner; +Cc: Wolfgang Bumiller
On 08.09.20 13:58, Fabian Ebner wrote:
> Will be used to monitor state changes on container startup.
>
> Co-developed-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
> Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
> ---
>
> New in v2.
>
> I hard-coded the name of the abstract UNIX socket instead of
> trying to re-implement lxc/monitor.c's lxc_monitor_sock_name
> function. For us, is it true that the lxcpath is always '/varl/lib/lxc'?
> Otherwise this won't always work.
>
> src/PVE/LXC/Makefile | 1 +
> src/PVE/LXC/Monitor.pm | 92 ++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 93 insertions(+)
> create mode 100644 src/PVE/LXC/Monitor.pm
>
>
applied series, thanks! Wolfgang may improve his variant, e.g., by patching lxc, to avoid
a runtime dependency on the lxc monitor, but until that works out this is 10000x times
better that the current status quo.
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2020-09-09 19:09 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-08 11:58 [pve-devel] [PATCH v2 container 1/2] Add module for reading state changes from monitor socket Fabian Ebner
2020-09-08 11:58 ` [pve-devel] [PATCH v2 container 2/2] Improve feedback for startup Fabian Ebner
2020-09-09 19:09 ` [pve-devel] applied-series: [PATCH v2 container 1/2] Add module for reading state changes from monitor socket Thomas Lamprecht
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox