From b60953583358da8a3ec0443d4c276508f3e83b29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= Date: Tue, 23 Jan 2024 15:48:52 -0500 Subject: [PATCH 01/15] internal/util: Re-order path functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stéphane Graber --- internal/util/paths.go | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/internal/util/paths.go b/internal/util/paths.go index 3cb5ed5057..c5a28e1b0e 100644 --- a/internal/util/paths.go +++ b/internal/util/paths.go @@ -5,19 +5,6 @@ import ( "path/filepath" ) -// VarPath returns the provided path elements joined by a slash and -// appended to the end of $INCUS_DIR, which defaults to /var/lib/incus. -func VarPath(path ...string) string { - varDir := os.Getenv("INCUS_DIR") - if varDir == "" { - varDir = "/var/lib/incus" - } - - items := []string{varDir} - items = append(items, path...) - return filepath.Join(items...) -} - // CachePath returns the directory that Incus should its cache under. If INCUS_DIR is // set, this path is $INCUS_DIR/cache, otherwise it is /var/cache/incus. func CachePath(path ...string) string { @@ -46,6 +33,19 @@ func LogPath(path ...string) string { return filepath.Join(items...) } +// VarPath returns the provided path elements joined by a slash and +// appended to the end of $INCUS_DIR, which defaults to /var/lib/incus. +func VarPath(path ...string) string { + varDir := os.Getenv("INCUS_DIR") + if varDir == "" { + varDir = "/var/lib/incus" + } + + items := []string{varDir} + items = append(items, path...) + return filepath.Join(items...) +} + // IsDir returns true if the given path is a directory. func IsDir(name string) bool { stat, err := os.Stat(name) From b3b6770a25e9f3d39fdb14b390ebd7a4eaa48ebd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= Date: Tue, 23 Jan 2024 15:51:10 -0500 Subject: [PATCH 02/15] internal/util: Add RunPath MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stéphane Graber --- internal/util/paths.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/internal/util/paths.go b/internal/util/paths.go index c5a28e1b0e..ea52263806 100644 --- a/internal/util/paths.go +++ b/internal/util/paths.go @@ -33,6 +33,20 @@ func LogPath(path ...string) string { return filepath.Join(items...) } +// RunPath returns the directory that Incus should put runtime data under. +// If INCUS_DIR is set, this path is $INCUS_DIR/run, otherwise it is /run/incus. +func RunPath(path ...string) string { + varDir := os.Getenv("INCUS_DIR") + runDir := "/run/incus" + if varDir != "" { + runDir = filepath.Join(varDir, "run") + } + + items := []string{runDir} + items = append(items, path...) + return filepath.Join(items...) +} + // VarPath returns the provided path elements joined by a slash and // appended to the end of $INCUS_DIR, which defaults to /var/lib/incus. func VarPath(path ...string) string { From 83dae792867c8a47edf537e4564ce1a8c670ec61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= Date: Tue, 23 Jan 2024 16:06:00 -0500 Subject: [PATCH 03/15] incusd/sys: Add runtime directory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stéphane Graber --- internal/server/sys/fs.go | 1 + internal/server/sys/os.go | 4 +++- internal/server/sys/testing.go | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/internal/server/sys/fs.go b/internal/server/sys/fs.go index 83296ecc89..ccf31852c6 100644 --- a/internal/server/sys/fs.go +++ b/internal/server/sys/fs.go @@ -49,6 +49,7 @@ func (s *OS) initDirs() error { {filepath.Join(s.VarDir, "images"), 0700}, {s.LogDir, 0700}, {filepath.Join(s.VarDir, "networks"), 0711}, + {s.RunDir, 0700}, {filepath.Join(s.VarDir, "security"), 0700}, {filepath.Join(s.VarDir, "security", "apparmor"), 0700}, {filepath.Join(s.VarDir, "security", "apparmor", "cache"), 0700}, diff --git a/internal/server/sys/os.go b/internal/server/sys/os.go index 30838c1cf0..c140a0203b 100644 --- a/internal/server/sys/os.go +++ b/internal/server/sys/os.go @@ -43,6 +43,7 @@ type OS struct { // Directories CacheDir string // Cache directory (e.g. /var/cache/incus/). LogDir string // Log directory (e.g. /var/log/incus/). + RunDir string // Runtime directory (e.g. /run/incus/). VarDir string // Data directory (e.g. /var/lib/incus/). // Daemon environment @@ -101,9 +102,10 @@ type OS struct { // DefaultOS returns a fresh uninitialized OS instance with default values. func DefaultOS() *OS { newOS := &OS{ - VarDir: internalUtil.VarPath(), CacheDir: internalUtil.CachePath(), LogDir: internalUtil.LogPath(), + RunDir: internalUtil.RunPath(), + VarDir: internalUtil.VarPath(), } newOS.InotifyWatch.Fd = -1 diff --git a/internal/server/sys/testing.go b/internal/server/sys/testing.go index e68e97f9c4..c9705b863e 100644 --- a/internal/server/sys/testing.go +++ b/internal/server/sys/testing.go @@ -29,6 +29,7 @@ func NewTestOS(t *testing.T) (*OS, func()) { VarDir: dir, CacheDir: filepath.Join(dir, "cache"), LogDir: filepath.Join(dir, "log"), + RunDir: filepath.Join(dir, "run"), } _, err = os.Init() From 4328b52427bea3342c3e52969d396b407bfbe9fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= Date: Tue, 23 Jan 2024 16:07:59 -0500 Subject: [PATCH 04/15] incusd/seccomp: Move seccomp.socket to /run MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stéphane Graber --- cmd/incusd/daemon.go | 4 ++-- internal/server/instance/drivers/driver_lxc.go | 2 +- internal/server/seccomp/seccomp.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/incusd/daemon.go b/cmd/incusd/daemon.go index 7b9d109d7b..2a4e31e99f 100644 --- a/cmd/incusd/daemon.go +++ b/cmd/incusd/daemon.go @@ -1521,7 +1521,7 @@ func (d *Daemon) init() error { // Setup seccomp handler if d.os.SeccompListener { - seccompServer, err := seccomp.NewSeccompServer(d.State(), internalUtil.VarPath("seccomp.socket"), func(pid int32, state *state.State) (seccomp.Instance, error) { + seccompServer, err := seccomp.NewSeccompServer(d.State(), internalUtil.RunPath("seccomp.socket"), func(pid int32, state *state.State) (seccomp.Instance, error) { return findContainerForPid(pid, state) }) if err != nil { @@ -1529,7 +1529,7 @@ func (d *Daemon) init() error { } d.seccomp = seccompServer - logger.Info("Started seccomp handler", logger.Ctx{"path": internalUtil.VarPath("seccomp.socket")}) + logger.Info("Started seccomp handler", logger.Ctx{"path": internalUtil.RunPath("seccomp.socket")}) } // Read the trusted certificates diff --git a/internal/server/instance/drivers/driver_lxc.go b/internal/server/instance/drivers/driver_lxc.go index 9aff84eccb..2fbbb61ff4 100644 --- a/internal/server/instance/drivers/driver_lxc.go +++ b/internal/server/instance/drivers/driver_lxc.go @@ -1017,7 +1017,7 @@ func (d *lxc) initLXC(config bool) (*liblxc.Container, error) { // System requirement errors are handled during policy generation instead of here ok, err := seccomp.InstanceNeedsIntercept(d.state, d) if err == nil && ok { - err = lxcSetConfigItem(cc, "lxc.seccomp.notify.proxy", fmt.Sprintf("unix:%s", internalUtil.VarPath("seccomp.socket"))) + err = lxcSetConfigItem(cc, "lxc.seccomp.notify.proxy", fmt.Sprintf("unix:%s", internalUtil.RunPath("seccomp.socket"))) if err != nil { return nil, err } diff --git a/internal/server/seccomp/seccomp.go b/internal/server/seccomp/seccomp.go index 6755dd98d9..95bdc4d24d 100644 --- a/internal/server/seccomp/seccomp.go +++ b/internal/server/seccomp/seccomp.go @@ -2403,7 +2403,7 @@ func lxcSupportSeccompNotify(state *state.State) error { return fmt.Errorf("Failed to load seccomp notify test container") } - err = c.SetConfigItem("lxc.seccomp.notify.proxy", fmt.Sprintf("unix:%s", internalUtil.VarPath("seccomp.socket"))) + err = c.SetConfigItem("lxc.seccomp.notify.proxy", fmt.Sprintf("unix:%s", internalUtil.RunPath("seccomp.socket"))) if err != nil { return fmt.Errorf("LXC doesn't support notify proxy: %w", err) } From df64cc171084e5c0cab0deecd72b5d8be289f128 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= Date: Tue, 23 Jan 2024 16:14:01 -0500 Subject: [PATCH 05/15] incusd/instance_logs: Drop conf files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stéphane Graber --- cmd/incusd/instance_logs.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/cmd/incusd/instance_logs.go b/cmd/incusd/instance_logs.go index a99a7cf838..663a6e3bf9 100644 --- a/cmd/incusd/instance_logs.go +++ b/cmd/incusd/instance_logs.go @@ -94,7 +94,6 @@ var instanceExecOutputsCmd = APIEndpoint{ // type: string // example: |- // [ -// "/1.0/instances/foo/logs/lxc.conf", // "/1.0/instances/foo/logs/lxc.log" // ] // "403": @@ -670,9 +669,7 @@ func validLogFileName(fname string) bool { * to deal with any escaping or whatever. */ return fname == "lxc.log" || - fname == "lxc.conf" || fname == "qemu.log" || - fname == "qemu.conf" || strings.HasPrefix(fname, "migration_") || strings.HasPrefix(fname, "snapshot_") } From bb304da317be6451712b050c001247a2c65b275f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= Date: Tue, 23 Jan 2024 16:15:19 -0500 Subject: [PATCH 06/15] doc/rest-api: Refresh swagger YAML MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stéphane Graber --- doc/rest-api.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/rest-api.yaml b/doc/rest-api.yaml index e251d8bb9a..5ffedfb770 100644 --- a/doc/rest-api.yaml +++ b/doc/rest-api.yaml @@ -9055,7 +9055,6 @@ paths: description: List of endpoints example: |- [ - "/1.0/instances/foo/logs/lxc.conf", "/1.0/instances/foo/logs/lxc.log" ] items: From aa4008611eeed52cb93d72d34c49a2e7cdd05725 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= Date: Tue, 23 Jan 2024 16:19:22 -0500 Subject: [PATCH 07/15] incusd/instance/common: Add RunPath MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stéphane Graber --- internal/server/instance/drivers/driver_common.go | 6 ++++++ internal/server/instance/instance_interface.go | 1 + 2 files changed, 7 insertions(+) diff --git a/internal/server/instance/drivers/driver_common.go b/internal/server/instance/drivers/driver_common.go index fca1eaa962..5086d7815a 100644 --- a/internal/server/instance/drivers/driver_common.go +++ b/internal/server/instance/drivers/driver_common.go @@ -386,6 +386,12 @@ func (d *common) LogPath() string { return internalUtil.LogPath(name) } +// RunPath returns the instance's runtime path. +func (d *common) RunPath() string { + name := project.Instance(d.project.Name, d.name) + return internalUtil.RunPath(name) +} + // Path returns the instance's path. func (d *common) Path() string { return storagePools.InstancePath(d.dbType, d.project.Name, d.name, d.isSnapshot) diff --git a/internal/server/instance/instance_interface.go b/internal/server/instance/instance_interface.go index 8dc4b1c01d..d2c467119f 100644 --- a/internal/server/instance/instance_interface.go +++ b/internal/server/instance/instance_interface.go @@ -150,6 +150,7 @@ type Instance interface { LogFilePath() string ConsoleBufferLogPath() string LogPath() string + RunPath() string DevicesPath() string // Storage. From 6686c96dd329e72c36769935d8aaa729c3bf24d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= Date: Tue, 23 Jan 2024 16:19:40 -0500 Subject: [PATCH 08/15] incusd/instance/lxc: Move lxc.conf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stéphane Graber --- internal/server/instance/drivers/driver_lxc.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/internal/server/instance/drivers/driver_lxc.go b/internal/server/instance/drivers/driver_lxc.go index 2fbbb61ff4..83730be9e8 100644 --- a/internal/server/instance/drivers/driver_lxc.go +++ b/internal/server/instance/drivers/driver_lxc.go @@ -2285,7 +2285,7 @@ func (d *lxc) startCommon() (string, []func() error, error) { } // Generate the LXC config - configPath := filepath.Join(d.LogPath(), "lxc.conf") + configPath := filepath.Join(d.RunPath(), "lxc.conf") err = cc.SaveConfigFile(configPath) if err != nil { _ = os.Remove(configPath) @@ -6985,7 +6985,7 @@ func (d *lxc) Console(protocol string) (*os.File, chan error, error) { "forkconsole", project.Instance(d.Project().Name, d.Name()), d.state.OS.LxcPath, - filepath.Join(d.LogPath(), "lxc.conf"), + filepath.Join(d.RunPath(), "lxc.conf"), "tty=0", "escape=-1"} @@ -7063,7 +7063,7 @@ func (d *lxc) ConsoleLog(opts liblxc.ConsoleLogOptions) (string, error) { // Exec executes a command inside the instance. func (d *lxc) Exec(req api.InstanceExecPost, stdin *os.File, stdout *os.File, stderr *os.File) (instance.Cmd, error) { // Generate the LXC config if missing. - configPath := filepath.Join(d.LogPath(), "lxc.conf") + configPath := filepath.Join(d.RunPath(), "lxc.conf") if !util.PathExists(configPath) { cc, err := d.initLXC(true) if err != nil { @@ -7100,7 +7100,7 @@ func (d *lxc) Exec(req api.InstanceExecPost, stdin *os.File, stdout *os.File, st "forkexec", cname, d.state.OS.LxcPath, - filepath.Join(d.LogPath(), "lxc.conf"), + filepath.Join(d.RunPath(), "lxc.conf"), req.Cwd, fmt.Sprintf("%d", req.User), fmt.Sprintf("%d", req.Group), @@ -7592,7 +7592,7 @@ func (d *lxc) insertMountGo(source, target, fstype string, flags int, mntnsPID i func (d *lxc) insertMountLXC(source, target, fstype string, flags int) error { cname := project.Instance(d.Project().Name, d.Name()) - configPath := filepath.Join(d.LogPath(), "lxc.conf") + configPath := filepath.Join(d.RunPath(), "lxc.conf") if fstype == "" { fstype = "none" } @@ -7688,7 +7688,7 @@ func (d *lxc) removeMount(mount string) error { } if d.state.OS.LXCFeatures["mount_injection_file"] { - configPath := filepath.Join(d.LogPath(), "lxc.conf") + configPath := filepath.Join(d.RunPath(), "lxc.conf") cname := project.Instance(d.Project().Name, d.Name()) if !strings.HasPrefix(mount, "/") { From 3dc11ec5b9d203301105ce553ab10aaa38a7d07a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= Date: Tue, 23 Jan 2024 16:19:51 -0500 Subject: [PATCH 09/15] incusd/instance/qemu: Move qemu.conf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stéphane Graber --- internal/server/instance/drivers/driver_qemu.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/server/instance/drivers/driver_qemu.go b/internal/server/instance/drivers/driver_qemu.go index 90183f99d3..d4edf318af 100644 --- a/internal/server/instance/drivers/driver_qemu.go +++ b/internal/server/instance/drivers/driver_qemu.go @@ -3435,7 +3435,7 @@ func (d *qemu) generateQemuConfigFile(cpuInfo *cpuTopology, mountInfo *storagePo cfg = qemuRawCfgOverride(cfg, d.expandedConfig) // Write the config file to disk. sb := qemuStringifyCfg(cfg...) - configPath := filepath.Join(d.LogPath(), "qemu.conf") + configPath := filepath.Join(d.RunPath(), "qemu.conf") return configPath, monHooks, os.WriteFile(configPath, []byte(sb.String()), 0640) } From 1d3c2f86709f6e283f9083f1c1bcfd04332a7210 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= Date: Tue, 23 Jan 2024 16:20:03 -0500 Subject: [PATCH 10/15] doc: Update qemu.conf path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stéphane Graber --- doc/reference/instance_options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/reference/instance_options.md b/doc/reference/instance_options.md index 94d6dae24a..cc87cf84aa 100644 --- a/doc/reference/instance_options.md +++ b/doc/reference/instance_options.md @@ -255,7 +255,7 @@ Therefore, you should avoid setting any of these keys. For VM instances, Incus configures QEMU through a configuration file that is passed to QEMU with the `-readconfig` command-line option. This configuration file is generated for each instance before boot. -It can be found at `/var/log/incus//qemu.conf`. +It can be found at `/run/incus//qemu.conf`. The default configuration works fine for Incus' most common use case: modern UEFI guests with VirtIO devices. In some situations, however, you might need to override the generated configuration. From a154030f04b87ee86142a6e99a2a3e998346750f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= Date: Tue, 23 Jan 2024 16:35:14 -0500 Subject: [PATCH 11/15] incusd/apparmor: Add runtime directory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stéphane Graber --- internal/server/apparmor/instance.go | 2 ++ internal/server/apparmor/instance_qemu.go | 1 + 2 files changed, 3 insertions(+) diff --git a/internal/server/apparmor/instance.go b/internal/server/apparmor/instance.go index 4e2f2a2c22..6e4bb30feb 100644 --- a/internal/server/apparmor/instance.go +++ b/internal/server/apparmor/instance.go @@ -23,6 +23,7 @@ type instance interface { ExpandedConfig() map[string]string Type() instancetype.Type LogPath() string + RunPath() string Path() string DevicesPath() string } @@ -211,6 +212,7 @@ func instanceProfile(sysOS *sys.OS, inst instance, extraBinaries []string) (stri "extra_binaries": extraBinaries, "libraryPath": strings.Split(os.Getenv("LD_LIBRARY_PATH"), ":"), "logPath": inst.LogPath(), + "runPath": inst.RunPath(), "name": InstanceProfileName(inst), "path": path, "raw": rawContent, diff --git a/internal/server/apparmor/instance_qemu.go b/internal/server/apparmor/instance_qemu.go index ac9dad5c01..b66d0b682c 100644 --- a/internal/server/apparmor/instance_qemu.go +++ b/internal/server/apparmor/instance_qemu.go @@ -63,6 +63,7 @@ profile "{{ .name }}" flags=(attach_disconnected,mediate_deleted) { # Instance specific paths {{ .logPath }}/** rwk, + {{ .runPath }}/** rwk, {{ .path }}/** rwk, {{ .devicesPath }}/** rwk, From 70f999bea429251d9eaeaca92e74e80770644e07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= Date: Tue, 23 Jan 2024 16:35:46 -0500 Subject: [PATCH 12/15] incusd/instance/utils: Cleanup runtime path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stéphane Graber --- internal/server/instance/instance_utils.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/server/instance/instance_utils.go b/internal/server/instance/instance_utils.go index ebf28202df..c6b60055c5 100644 --- a/internal/server/instance/instance_utils.go +++ b/internal/server/instance/instance_utils.go @@ -1010,6 +1010,7 @@ func CreateInternal(s *state.State, args db.InstanceArgs, clearLogDir bool) (Ins // Wipe any existing log for this instance name. if clearLogDir { _ = os.RemoveAll(inst.LogPath()) + _ = os.RemoveAll(inst.RunPath()) } cleanup = revert.Clone().Fail From 9e4d05675a7964ef91f0bf31f30c3c725782ad6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= Date: Tue, 23 Jan 2024 16:36:00 -0500 Subject: [PATCH 13/15] incusd/instance/lxc: Move files to runtime path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stéphane Graber --- .../server/instance/drivers/driver_lxc.go | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/internal/server/instance/drivers/driver_lxc.go b/internal/server/instance/drivers/driver_lxc.go index 83730be9e8..779c8b488f 100644 --- a/internal/server/instance/drivers/driver_lxc.go +++ b/internal/server/instance/drivers/driver_lxc.go @@ -2052,6 +2052,11 @@ func (d *lxc) startCommon() (string, []func() error, error) { return "", nil, err } + err = os.MkdirAll(d.RunPath(), 0700) + if err != nil { + return "", nil, err + } + err = os.MkdirAll(d.DevicesPath(), 0711) if err != nil { return "", nil, err @@ -3962,6 +3967,16 @@ func (d *lxc) Rename(newName string, applyTemplateTrigger bool) error { } } + // Rename the runtime path. + newFullName = project.Instance(d.Project().Name, d.Name()) + _ = os.RemoveAll(internalUtil.RunPath(newFullName)) + if util.PathExists(d.RunPath()) { + err := os.Rename(d.RunPath(), internalUtil.RunPath(newFullName)) + if err != nil { + d.logger.Error("Failed renaming instance", ctxMap) + return fmt.Errorf("Failed renaming instance: %w", err) + } + } revert := revert.New() defer revert.Fail() @@ -6709,13 +6724,13 @@ func (d *lxc) FileSFTPConn() (net.Conn, error) { defer spawnUnlock() // Create any missing directories in case the instance has never been started before. - err = os.MkdirAll(d.LogPath(), 0700) + err = os.MkdirAll(d.RunPath(), 0700) if err != nil { return nil, err } // Trickery to handle paths > 108 chars. - dirFile, err := os.Open(d.LogPath()) + dirFile, err := os.Open(d.RunPath()) if err != nil { return nil, err } @@ -6728,7 +6743,7 @@ func (d *lxc) FileSFTPConn() (net.Conn, error) { } // Attempt to connect on existing socket. - forkfilePath := filepath.Join(d.LogPath(), "forkfile.sock") + forkfilePath := filepath.Join(d.RunPath(), "forkfile.sock") forkfileConn, err := net.DialUnix("unix", nil, forkfileAddr) if err == nil { // Found an existing server. @@ -6871,7 +6886,7 @@ func (d *lxc) FileSFTPConn() (net.Conn, error) { } // Write PID file. - pidFile := filepath.Join(d.LogPath(), "forkfile.pid") + pidFile := filepath.Join(d.RunPath(), "forkfile.pid") err = os.WriteFile(pidFile, []byte(fmt.Sprintf("%d\n", forkfile.Process.Pid)), 0600) if err != nil { chReady <- fmt.Errorf("Failed to write forkfile PID: %w", err) @@ -6951,7 +6966,7 @@ func (d *lxc) stopForkfile(force bool) { unlock() }() - content, err := os.ReadFile(filepath.Join(d.LogPath(), "forkfile.pid")) + content, err := os.ReadFile(filepath.Join(d.RunPath(), "forkfile.pid")) if err != nil { return } From e51f2ef9341e996fa731340ccfd7d67d8008ba8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= Date: Tue, 23 Jan 2024 16:36:08 -0500 Subject: [PATCH 14/15] incusd/instance/qemu: Move files to runtime path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stéphane Graber --- .../server/instance/drivers/driver_qemu.go | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/internal/server/instance/drivers/driver_qemu.go b/internal/server/instance/drivers/driver_qemu.go index d4edf318af..d187d0769d 100644 --- a/internal/server/instance/drivers/driver_qemu.go +++ b/internal/server/instance/drivers/driver_qemu.go @@ -582,8 +582,8 @@ func (d *qemu) configDriveMountPathClear() error { // configVirtiofsdPaths returns the path for the socket and PID file to use with config drive virtiofsd process. func (d *qemu) configVirtiofsdPaths() (string, string) { - sockPath := filepath.Join(d.LogPath(), "virtio-fs.config.sock") - pidPath := filepath.Join(d.LogPath(), "virtiofsd.pid") + sockPath := filepath.Join(d.RunPath(), "virtio-fs.config.sock") + pidPath := filepath.Join(d.RunPath(), "virtiofsd.pid") return sockPath, pidPath } @@ -1226,6 +1226,12 @@ func (d *qemu) start(stateful bool, op *operationlock.InstanceOperation) error { return err } + err = os.MkdirAll(d.RunPath(), 0700) + if err != nil { + op.Done(err) + return err + } + err = os.MkdirAll(d.DevicesPath(), 0711) if err != nil { op.Done(err) @@ -2546,7 +2552,7 @@ func (d *qemu) deviceDetachNIC(deviceName string) error { } func (d *qemu) monitorPath() string { - return filepath.Join(d.LogPath(), "qemu.monitor") + return filepath.Join(d.RunPath(), "qemu.monitor") } func (d *qemu) nvramPath() string { @@ -2554,11 +2560,11 @@ func (d *qemu) nvramPath() string { } func (d *qemu) consolePath() string { - return filepath.Join(d.LogPath(), "qemu.console") + return filepath.Join(d.RunPath(), "qemu.console") } func (d *qemu) spicePath() string { - return filepath.Join(d.LogPath(), "qemu.spice") + return filepath.Join(d.RunPath(), "qemu.spice") } func (d *qemu) spiceCmdlineConfig() string { @@ -4589,7 +4595,7 @@ func (d *qemu) addVmgenDeviceConfig(cfg *[]cfgSection, guid string) error { // pidFilePath returns the path where the qemu process should write its PID. func (d *qemu) pidFilePath() string { - return filepath.Join(d.LogPath(), "qemu.pid") + return filepath.Join(d.RunPath(), "qemu.pid") } // pid gets the PID of the running qemu process. Returns 0 if PID file or process not found, and -1 if err non-nil. @@ -5100,6 +5106,17 @@ func (d *qemu) Rename(newName string, applyTemplateTrigger bool) error { } } + // Rename the runtime path. + newFullName = project.Instance(d.Project().Name, d.Name()) + _ = os.RemoveAll(internalUtil.RunPath(newFullName)) + if util.PathExists(d.RunPath()) { + err := os.Rename(d.RunPath(), internalUtil.RunPath(newFullName)) + if err != nil { + d.logger.Error("Failed renaming instance", ctxMap) + return err + } + } + revert := revert.New() defer revert.Fail() From e766a6059a89def82b49293d805e14bb896ef7d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= Date: Tue, 23 Jan 2024 17:20:14 -0500 Subject: [PATCH 15/15] incusd/patches: Move files to runtime directory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stéphane Graber --- cmd/incusd/patches.go | 58 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/cmd/incusd/patches.go b/cmd/incusd/patches.go index 52ee481c3e..dd33619951 100644 --- a/cmd/incusd/patches.go +++ b/cmd/incusd/patches.go @@ -17,6 +17,7 @@ import ( "github.com/lxc/incus/internal/server/db" dbCluster "github.com/lxc/incus/internal/server/db/cluster" "github.com/lxc/incus/internal/server/db/query" + "github.com/lxc/incus/internal/server/instance" "github.com/lxc/incus/internal/server/instance/instancetype" "github.com/lxc/incus/internal/server/network" "github.com/lxc/incus/internal/server/node" @@ -81,6 +82,7 @@ var patches = []patch{ {name: "snapshots_rename", stage: patchPreDaemonStorage, run: patchSnapshotsRename}, {name: "storage_zfs_unset_invalid_block_settings", stage: patchPostDaemonStorage, run: patchStorageZfsUnsetInvalidBlockSettings}, {name: "storage_zfs_unset_invalid_block_settings_v2", stage: patchPostDaemonStorage, run: patchStorageZfsUnsetInvalidBlockSettingsV2}, + {name: "runtime_directory", stage: patchPostDaemonStorage, run: patchRuntimeDirectory}, } type patch struct { @@ -1186,4 +1188,60 @@ func patchStorageZfsUnsetInvalidBlockSettingsV2(_ string, d *Daemon) error { return nil } +func patchRuntimeDirectory(name string, d *Daemon) error { + s := d.State() + + // Get the list of local instances. + instances, err := instance.LoadNodeAll(s, instancetype.Any) + if err != nil { + return fmt.Errorf("Failed loading local instances: %w", err) + } + + for _, inst := range instances { + if !util.PathExists(inst.LogPath()) { + continue + } + + err = os.MkdirAll(inst.RunPath(), 0700) + if err != nil && !os.IsExist(err) { + return fmt.Errorf("Failed to create runtime directory for %q in project %q: %w", inst.Name(), inst.Project(), err) + } + + files, err := os.ReadDir(inst.LogPath()) + if err != nil { + return fmt.Errorf("Failed to list log files for %q in project %q: %w", inst.Name(), inst.Project(), err) + } + + for _, fi := range files { + name := fi.Name() + + // Keep actual log files where they are. + if strings.HasSuffix(name, ".log") || strings.HasSuffix(name, ".log.old") || strings.HasSuffix(name, ".gz") { + continue + } + + info, err := fi.Info() + if err != nil { + return fmt.Errorf("Failed getting file info on %q for instance %q in project %q: %w", name, inst.Name(), inst.Project(), err) + } + + if info.Mode().IsRegular() { + // Relocate the file. + _, err := subprocess.RunCommand("mv", filepath.Join(inst.LogPath(), name), inst.RunPath()) + if err != nil { + return fmt.Errorf("Failed to relocate runtime file %q for instance %q in project %q: %w", name, inst.Name(), inst.Project(), err) + } + } else { + // For pipes and sockets, we need to use a symlink to avoid breaking the listener. + err := os.Symlink(filepath.Join(inst.LogPath(), name), filepath.Join(inst.RunPath(), name)) + if err != nil { + return fmt.Errorf("Failed to symlink runtime file %q for instance %q in project %q: %w", name, inst.Name(), inst.Project(), err) + } + } + } + } + + return nil +} + // Patches end here