[lxc-devel] [lxd/master] Log expiry

stgraber on Github lxc-bot at linuxcontainers.org
Fri Apr 29 03:40:20 UTC 2016


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 301 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20160429/db7b5fdb/attachment.bin>
-------------- next part --------------
From 33ff3f65d329aabb2513e2c5214f7ffe4532e9c7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Thu, 28 Apr 2016 23:36:44 -0400
Subject: [PATCH 1/2] Do proper logfile expiry
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Closes #1966

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 lxd/container_lxc.go | 10 ++++++
 lxd/daemon.go        | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 109 insertions(+)

diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index 5ec9e8e..eb00220 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -1088,6 +1088,16 @@ func (c *containerLXC) startCommon() (string, error) {
 		delete(c.expandedConfig, k)
 	}
 
+	// Rotate the log file
+	logfile := c.LogFilePath()
+	if shared.PathExists(logfile) {
+		os.Remove(logfile + ".old")
+		err := os.Rename(logfile, logfile+".old")
+		if err != nil {
+			return "", err
+		}
+	}
+
 	// Generate the LXC config
 	configPath := filepath.Join(c.LogPath(), "lxc.conf")
 	err = c.c.SaveConfigFile(configPath)
diff --git a/lxd/daemon.go b/lxd/daemon.go
index 8a150cc..b7a2e4b 100644
--- a/lxd/daemon.go
+++ b/lxd/daemon.go
@@ -9,6 +9,7 @@ import (
 	"encoding/pem"
 	"fmt"
 	"io"
+	"io/ioutil"
 	"net"
 	"net/http"
 	"net/url"
@@ -749,6 +750,22 @@ func (d *Daemon) Init() error {
 		}
 	}
 
+	/* Log expiry */
+	go func() {
+		t := time.NewTicker(24 * time.Hour)
+		for {
+			shared.Debugf("Expiring log files")
+
+			err := d.ExpireLogs()
+			if err != nil {
+				shared.Log.Error("Failed to expire logs", log.Ctx{"err": err})
+			}
+
+			shared.Debugf("Done expiring log files")
+			<-t.C
+		}
+	}()
+
 	/* set the initial proxy function based on config values in the DB */
 	d.proxy = shared.ProxyFromConfig(
 		daemonConfig["core.proxy_https"].Get(),
@@ -1100,6 +1117,88 @@ func (d *Daemon) PasswordCheck(password string) error {
 	return nil
 }
 
+func (d *Daemon) ExpireLogs() error {
+	entries, err := ioutil.ReadDir(shared.LogPath())
+	if err != nil {
+		return err
+	}
+
+	result, err := dbContainersList(d.db, cTypeRegular)
+	if err != nil {
+		return err
+	}
+
+	newestFile := func(path string, dir os.FileInfo) time.Time {
+		newest := dir.ModTime()
+
+		entries, err := ioutil.ReadDir(path)
+		if err != nil {
+			return newest
+		}
+
+		for _, entry := range entries {
+			if entry.ModTime().After(newest) {
+				newest = entry.ModTime()
+			}
+		}
+
+		return newest
+	}
+
+	for _, entry := range entries {
+		// Check if the container still exists
+		if shared.StringInSlice(entry.Name(), result) {
+			// Remove any log file which wasn't modified in the past 48 hours
+			logs, err := ioutil.ReadDir(shared.LogPath(entry.Name()))
+			if err != nil {
+				return err
+			}
+
+			for _, logfile := range logs {
+				path := shared.LogPath(entry.Name(), logfile.Name())
+
+				// Always keep the LXC config
+				if logfile.Name() == "lxc.conf" {
+					continue
+				}
+
+				// Deal with directories (snapshots)
+				if logfile.IsDir() {
+					newest := newestFile(path, logfile)
+					if time.Since(newest).Hours() >= 48 {
+						os.RemoveAll(path)
+						if err != nil {
+							return err
+						}
+					}
+
+					continue
+				}
+
+				// Individual files
+				if time.Since(logfile.ModTime()).Hours() >= 48 {
+					err := os.Remove(path)
+					if err != nil {
+						return err
+					}
+				}
+			}
+		} else {
+			// Empty directory if unchanged in the past 24 hours
+			path := shared.LogPath(entry.Name())
+			newest := newestFile(path, entry)
+			if time.Since(newest).Hours() >= 24 {
+				err := os.RemoveAll(path)
+				if err != nil {
+					return err
+				}
+			}
+		}
+	}
+
+	return nil
+}
+
 type lxdHttpServer struct {
 	r *mux.Router
 	d *Daemon

From 6000b29693313efc7a4cfcbe7c983959375d9752 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Thu, 28 Apr 2016 23:39:45 -0400
Subject: [PATCH 2/2] Make logging a bit more consistent
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 lxd/images.go | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lxd/images.go b/lxd/images.go
index 1a78796..632b753 100644
--- a/lxd/images.go
+++ b/lxd/images.go
@@ -876,6 +876,8 @@ func autoUpdateImages(d *Daemon) {
 			shared.Log.Error("Error deleting image", log.Ctx{"err": err, "fp": fp})
 		}
 	}
+
+	shared.Debugf("Done updating images")
 }
 
 func pruneExpiredImages(d *Daemon) {


More information about the lxc-devel mailing list