Skip to content

Commit

Permalink
lxd/network/acl: If the OVN chassis is in MicroOVN, read the ACL logs…
Browse files Browse the repository at this point in the history
… from syslogs

If the OVN controller is deployed as part of MicroOVN, it means that the `ovn-chassis` snap connection hook
between LXD and MicroOVN has been fired and that a symlink like:

`/run/openvswitch -> /var/snap/lxd/<ID>/microovn/...`

exists. Otherwise, there might still be a symlink but not with that target prefix. That's how we detect the ovn chassis
connection without introducing a new plug / slot between LXD and MicroOVN.

Then, if this case is detected, we check the status of the systemd unit 'snap.microovn.chassis.service' (the one containing the OVN controller in its sd journal)
If it is loaded and active, we read the last 1000 ACL log entries in the journal and return them.

Signed-off-by: Gabriel Mougard <[email protected]>
  • Loading branch information
gabrielmougard committed Dec 2, 2024
1 parent 28a1c70 commit bcf1ae4
Showing 1 changed file with 37 additions and 22 deletions.
59 changes: 37 additions & 22 deletions lxd/network/acl/driver_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -751,33 +751,48 @@ func (d *common) Delete() error {
// GetLog gets the ACL log.
func (d *common) GetLog(clientType request.ClientType) (string, error) {
// ACLs aren't specific to a particular network type but the log only works with OVN.
logPath := shared.HostPath("/var/log/ovn/ovn-controller.log")
if !shared.PathExists(logPath) {
return "", fmt.Errorf("Only OVN log entries may be retrieved at this time")
}
var logEntries []string
var err error
prefix := fmt.Sprintf("lxd_acl%d-", d.id)
// First, check if we can resolve the /run/openvswitch symlink to determine if OVN is in use.
// This is used in case of a MicroOVN deployment is interfaced with LXD.
targetPath, err := os.Readlink("/run/openvswitch")
if err == nil && strings.HasSuffix(targetPath, "/microovn/chassis/switch") {
logEntries, err = ovnParseLogEntriesFromJournald("snap.microovn.chassis.service", prefix)
if err != nil {
return "", fmt.Errorf("Failed to get OVN log entries from syslog: %v\n", err)
}
} else {
// Else, if the /run/openvswitch symlink doesn't exist (which might be the case for a non-snap installation of LXD),
// then try to read the OVN controller log file directly.
logEntries = []string{}
logPath := shared.HostPath("/var/log/ovn/ovn-controller.log")
if !shared.PathExists(logPath) {
return "", fmt.Errorf("Only OVN log entries may be retrieved at this time")
}

// Open the log file.
logFile, err := os.Open(logPath)
if err != nil {
return "", fmt.Errorf("Couldn't open OVN log file: %w", err)
}
// Open the log file.
logFile, err := os.Open(logPath)
if err != nil {
return "", fmt.Errorf("Couldn't open OVN log file: %w", err)
}

defer func() { _ = logFile.Close() }()
defer func() { _ = logFile.Close() }()

logEntries := []string{}
scanner := bufio.NewScanner(logFile)
for scanner.Scan() {
logEntry := ovnParseLogEntry(scanner.Text(), fmt.Sprintf("lxd_acl%d-", d.id))
if logEntry == "" {
continue
}
scanner := bufio.NewScanner(logFile)
for scanner.Scan() {
logEntry := ovnParseLogEntry(scanner.Text(), "", prefix)
if logEntry == "" {
continue
}

logEntries = append(logEntries, logEntry)
}
logEntries = append(logEntries, logEntry)
}

err = scanner.Err()
if err != nil {
return "", fmt.Errorf("Failed to read OVN log file: %w", err)
err = scanner.Err()
if err != nil {
return "", fmt.Errorf("Failed to read OVN log file: %w", err)
}
}

// Aggregates the entries from the rest of the cluster.
Expand Down

0 comments on commit bcf1ae4

Please sign in to comment.