From f345349a74d0af33faa286751cf05812f9e161e4 Mon Sep 17 00:00:00 2001 From: Gabriel Mougard Date: Wed, 23 Oct 2024 11:53:02 +0200 Subject: [PATCH] lxd/network/acl: Allow 'ovnParseLogEntry' to read a log input using an external timestamp When reading a log file, the logtime (timestamp of the log entry) is part of the entry but when we read a syslog, the logtime is not contained in the log entry fields and need to be parsed and converted. We added two local functions to cope with these two usages: * 'parseLogTimeFromFields' * 'parseLogTimeFromTimestamp' (used when the OVN deployment is part of MicroOVN and we need to read the syslog) Signed-off-by: Gabriel Mougard --- lxd/network/acl/acl_ovn.go | 35 +++++++++++++++++++++++++++----- lxd/network/acl/driver_common.go | 2 +- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/lxd/network/acl/acl_ovn.go b/lxd/network/acl/acl_ovn.go index 0a3b19b22f7e..e5b846a351fc 100644 --- a/lxd/network/acl/acl_ovn.go +++ b/lxd/network/acl/acl_ovn.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "net" + "strconv" "strings" "time" @@ -1042,7 +1043,23 @@ type ovnLogEntry struct { } // ovnParseLogEntry takes a log line and expected ACL prefix and returns a re-formated log entry if matching. -func ovnParseLogEntry(input string, prefix string) string { +// The 'timestamp' string is in microseconds format. If empty, the timestamp is extracted from the log entry. +func ovnParseLogEntry(input string, timestamp string, prefix string) string { + parseLogTimeFromFields := func(fields []string) (time.Time, error) { + return time.Parse(time.RFC3339, fields[0]) + } + + parseLogTimeFromTimestamp := func(timestamp string) (time.Time, error) { + tsInt, err := strconv.ParseInt(timestamp, 10, 64) + if err != nil { + return time.Time{}, fmt.Errorf("Failed to parse timestamp: %w", err) + } + + // The provided timestamp is in microseconds and need to be converted to nanoseconds. + tsNs := tsInt * 1000 + return time.Unix(0, tsNs).UTC(), nil + } + fields := strings.Split(input, "|") // Skip unknown formatting. @@ -1071,10 +1088,18 @@ func ovnParseLogEntry(input string, prefix string) string { return "" } - // Parse the timestamp. - logTime, err := time.Parse(time.RFC3339, fields[0]) - if err != nil { - return "" + var logTime time.Time + var err error + if timestamp == "" { + logTime, err = parseLogTimeFromFields(fields) + if err != nil { + return "" + } + } else { + logTime, err = parseLogTimeFromTimestamp(timestamp) + if err != nil { + return "" + } } // Get the protocol. diff --git a/lxd/network/acl/driver_common.go b/lxd/network/acl/driver_common.go index 9d863a3c29a0..332da23aad13 100644 --- a/lxd/network/acl/driver_common.go +++ b/lxd/network/acl/driver_common.go @@ -767,7 +767,7 @@ func (d *common) GetLog(clientType request.ClientType) (string, error) { logEntries := []string{} scanner := bufio.NewScanner(logFile) for scanner.Scan() { - logEntry := ovnParseLogEntry(scanner.Text(), fmt.Sprintf("lxd_acl%d-", d.id)) + logEntry := ovnParseLogEntry(scanner.Text(), "", fmt.Sprintf("lxd_acl%d-", d.id)) if logEntry == "" { continue }