From cee881a6e1605bfc17770bb8e7ef0d88da8fa44a Mon Sep 17 00:00:00 2001
From: Mike Hibler <hibler@cs.utah.edu>
Date: Sun, 7 Dec 2014 16:15:23 -0700
Subject: [PATCH] Add a little disk-based DB for tracking the last time events
 were sent.

This is analogous to what we do in bootinfo to ensure we don't fire off
excessive PXEBOOTING/BOOTING events. The DB file is in the new
/usr/testbed/db directory.
---
 GNUmakefile.in                          |  1 +
 dhcpd/dhcpd.conf.nobootinfo.template.in |  2 +-
 tbsetup/reportboot.in                   | 54 +++++++++++++++++++++++--
 3 files changed, 52 insertions(+), 5 deletions(-)

diff --git a/GNUmakefile.in b/GNUmakefile.in
index c2b476f4d8..e0bcac7e38 100644
--- a/GNUmakefile.in
+++ b/GNUmakefile.in
@@ -174,6 +174,7 @@ opsfs-install: ops-install fs-install
 	@echo "Combined ops/fs install done."
 
 install-mkdirs:
+	-mkdir -p $(INSTALL_TOPDIR)/db
 	-mkdir -p $(INSTALL_TOPDIR)/locks
 	-mkdir -p $(INSTALL_TOPDIR)/log
 	-mkdir -p $(INSTALL_TOPDIR)/log/mysql
diff --git a/dhcpd/dhcpd.conf.nobootinfo.template.in b/dhcpd/dhcpd.conf.nobootinfo.template.in
index 10cf73da19..350e8eaaa3 100644
--- a/dhcpd/dhcpd.conf.nobootinfo.template.in
+++ b/dhcpd/dhcpd.conf.nobootinfo.template.in
@@ -73,7 +73,7 @@ on commit {
 
     # If you want to send both events on the PXE contact, use this
     if (boot = "PXE") {
-	execute("@prefix@/sbin/reportboot", "-C", clip, clhw, boot);
+	execute("@prefix@/sbin/reportboot", "-bCD", clip, clhw, boot);
     }
 }
 
diff --git a/tbsetup/reportboot.in b/tbsetup/reportboot.in
index cd6e95c60d..b4e8633e33 100644
--- a/tbsetup/reportboot.in
+++ b/tbsetup/reportboot.in
@@ -34,18 +34,20 @@ use Sys::Syslog;
 
 sub usage()
 {
-    print "Usage: $0 [-bdC] IP MAC boot-type\n";
+    print "Usage: $0 [-bdCD] IP MAC boot-type\n";
     print("Options:\n");
     print(" -b      - Run in the background\n");
     print(" -d      - Turn on debugging\n");
     print(" -C      - Combine PXEBOOTING/BOOTING on the PXE event\n");
+    print(" -D      - Record event times in a DB to moderate send rate\n");
  
     exit(1);
 }
-my $optlist    = "bdC";
+my $optlist    = "bdCD";
 my $background = 0;
 my $debug      = 0;
 my $combined   = 0;
+my $usedb      = 0;
 
 #
 # Functions
@@ -61,6 +63,13 @@ my $TB       = "@prefix@";
 my $TBOPS    = "@TBOPSEMAIL@";
 my $EVPORT   = @BOSSEVENTPORT@;
 my $EVSERVER = "boss";
+my $EVDB     = "$TB/db/reportboot";
+
+#
+# Minimum time between events.
+# In bootinfo, this is 10 seconds!
+#
+my $EVMININT = 5;
 
 # Locals
 my $logfile  = "$TB/log/reportboot.log";
@@ -97,6 +106,9 @@ if (! getopts($optlist, \%options)) {
 if (defined($options{"C"})) {
     $combined = 1;
 }
+if (defined($options{"D"})) {
+    $usedb = 1;
+}
 if (defined($options{"b"})) {
     $background = 1;
 }
@@ -149,6 +161,41 @@ if (!$nodeid) {
     exit(0);
 }
 
+#
+# See if we need to send events.
+# We won't send more than one event per second.
+#
+if ($usedb) {
+    my %DB;
+    my $lasttime = 0;
+    my $now = time();
+    my $key = "$IP/$boottype";
+
+    if (!dbmopen(%DB, $EVDB, 0660)) {
+	logit("$nodeid: could not open $EVDB");
+	exit(1);
+    }
+
+    my $needone = 1;
+    if (defined($DB{$key})) {
+	$lasttime = $DB{$key};
+	# XXX watch for time going backward
+	if ($now >= $lasttime &&
+	    $now < ($lasttime + $EVMININT)) {
+	    $needone = 0;
+	}
+    }
+    if ($needone) {
+	$DB{$key} = $now;
+    }
+    dbmclose(%DB);
+
+    if (!$needone) {
+	logit("$nodeid: NOT sending BOOTING event (too soon)");
+	exit(0);
+    }
+}
+
 #
 # Combine reporting of PXEBOOTING and BOOTING on the PXE event, reporting
 # nothing on the OS event. Use this if you have problems with later
@@ -164,7 +211,7 @@ if ($combined) {
 	}
 	logit("$nodeid: sent PXEBOOTING and BOOTING events");
     } else {
-	logit("$nodeid: NOT sending BOOTING event");
+	logit("$nodeid: NOT sending BOOTING event (combo mode)");
     }
 } else {
     my $event = ($boottype eq "OS") ? "BOOTING" : "PXEBOOTING";
@@ -254,4 +301,3 @@ sub sendevent($$)
 
     return 0;
 }
-
-- 
GitLab