Skip to content

Commit

Permalink
incusd/instance/qemu: Add new agent share
Browse files Browse the repository at this point in the history
Signed-off-by: Stéphane Graber <stgraber@stgraber.org>
  • Loading branch information
stgraber committed Jan 24, 2024
1 parent 3486b8b commit 5218bed
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 29 deletions.
27 changes: 27 additions & 0 deletions internal/server/instance/drivers/agent-loader/incus-agent
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/bin/sh
PREFIX="/run/incus_agent"
mkdir -p "${PREFIX}/.mnt"

# Functions.
mount_virtiofs() {
mount -t virtiofs agent "${PREFIX}/.mnt" -o ro >/dev/null 2>&1
}

mount_9p() {
modprobe 9pnet_virtio >/dev/null 2>&1 || true
mount -t 9p agent "${PREFIX}/.mnt" -o ro,access=0,trans=virtio,size=1048576 >/dev/null 2>&1
}

# Mount the agent share.
mount_virtiofs || mount_9p || fail "Couldn't mount virtiofs or 9p, failing."

# Transfer the agent binary.
rm -f "${PREFIX}/incus-agent"
cp -a --no-preserve=ownership "${PREFIX}/.mnt/incus-agent.linux.$(uname -m)" "${PREFIX}/incus-agent"

# Unmount the temporary mount.
umount "${PREFIX}/.mnt"
rmdir "${PREFIX}/.mnt"

# Re-exec the agent.
exec "${PREFIX}/incus-agent" "$@"
89 changes: 60 additions & 29 deletions internal/server/instance/drivers/driver_qemu.go
Original file line number Diff line number Diff line change
Expand Up @@ -2606,46 +2606,59 @@ func (d *qemu) generateConfigShare() error {
return fmt.Errorf("Failed getting info for incus-agent source %q: %w", agentSrcPath, err)
}

agentInstallPath := filepath.Join(configDrivePath, "incus-agent")
agentNeedsInstall := true

if util.PathExists(agentInstallPath) {
agentInstallInfo, err := os.Stat(agentInstallPath)
if err != nil {
return fmt.Errorf("Failed getting info for existing incus-agent install %q: %w", agentInstallPath, err)
}

if agentInstallInfo.ModTime() == agentSrcInfo.ModTime() && agentInstallInfo.Size() == agentSrcInfo.Size() {
agentNeedsInstall = false
}
}

// Only install the agent into config drive if the existing one is different to the source one.
// Otherwise we would end up copying it again and this can cause unnecessary snapshot usage.
if agentNeedsInstall {
d.logger.Debug("Installing incus-agent", logger.Ctx{"srcPath": agentSrcPath, "installPath": agentInstallPath})
err = internalUtil.FileCopy(agentSrcPath, agentInstallPath)
if util.PathExists(os.Getenv("INCUS_AGENT_PATH")) {
// Install incus-agent script (loads from agent share).
fs, err := incusAgentLoader.ReadFile("agent-loader/incus-agent")
if err != nil {
return err
}

err = os.Chmod(agentInstallPath, 0500)
err = os.WriteFile(filepath.Join(configDrivePath, "incus-agent"), fs, 0700)
if err != nil {
return err
}
} else {
agentInstallPath := filepath.Join(configDrivePath, "incus-agent")
agentNeedsInstall := true

err = os.Chown(agentInstallPath, 0, 0)
if err != nil {
return err
if util.PathExists(agentInstallPath) {
agentInstallInfo, err := os.Stat(agentInstallPath)
if err != nil {
return fmt.Errorf("Failed getting info for existing incus-agent install %q: %w", agentInstallPath, err)
}

if agentInstallInfo.ModTime() == agentSrcInfo.ModTime() && agentInstallInfo.Size() == agentSrcInfo.Size() {
agentNeedsInstall = false
}
}

// Ensure we copy the source file's timestamps so they can be used for comparison later.
err = os.Chtimes(agentInstallPath, agentSrcInfo.ModTime(), agentSrcInfo.ModTime())
if err != nil {
return fmt.Errorf("Failed setting incus-agent timestamps: %w", err)
// Only install the agent into config drive if the existing one is different to the source one.
// Otherwise we would end up copying it again and this can cause unnecessary snapshot usage.
if agentNeedsInstall {
d.logger.Debug("Installing incus-agent", logger.Ctx{"srcPath": agentSrcPath, "installPath": agentInstallPath})
err = internalUtil.FileCopy(agentSrcPath, agentInstallPath)
if err != nil {
return err
}

err = os.Chmod(agentInstallPath, 0500)
if err != nil {
return err
}

err = os.Chown(agentInstallPath, 0, 0)
if err != nil {
return err
}

// Ensure we copy the source file's timestamps so they can be used for comparison later.
err = os.Chtimes(agentInstallPath, agentSrcInfo.ModTime(), agentSrcInfo.ModTime())
if err != nil {
return fmt.Errorf("Failed setting incus-agent timestamps: %w", err)
}
} else {
d.logger.Debug("Skipping incus-agent install as unchanged", logger.Ctx{"srcPath": agentSrcPath, "installPath": agentInstallPath})
}
} else {
d.logger.Debug("Skipping incus-agent install as unchanged", logger.Ctx{"srcPath": agentSrcPath, "installPath": agentInstallPath})
}

// Legacy support.
Expand Down Expand Up @@ -3163,6 +3176,24 @@ func (d *qemu) generateQemuConfigFile(cpuInfo *cpuTopology, mountInfo *storagePo

cfg = append(cfg, qemuDriveConfig(&driveConfig9pOpts)...)

// Pass in the agents if INCUS_AGENT_PATH is set.
if util.PathExists(os.Getenv("INCUS_AGENT_PATH")) {
devBus, devAddr, multi = bus.allocate(busFunctionGroup9p)
driveConfig9pOpts := qemuDriveConfigOpts{
dev: qemuDevOpts{
busName: bus.name,
devBus: devBus,
devAddr: devAddr,
multifunction: multi,
},
name: "agent",
protocol: "9p",
path: os.Getenv("INCUS_AGENT_PATH"),
}

cfg = append(cfg, qemuDriveConfig(&driveConfig9pOpts)...)
}

// If user has requested AMD SEV, check if supported and add to QEMU config.
if util.IsTrue(d.expandedConfig["security.sev"]) {
sevOpts, err := d.setupSEV(fdFiles)
Expand Down

0 comments on commit 5218bed

Please sign in to comment.