Skip to content

Commit

Permalink
force new snapshots on job run trigger
Browse files Browse the repository at this point in the history
  • Loading branch information
sonroyaalmerol committed Dec 7, 2024
1 parent 89ebd9d commit 990d735
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 3 deletions.
15 changes: 14 additions & 1 deletion internal/agent/sftp/sftp.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,19 @@ func handleRequests(ctx context.Context, requests <-chan *ssh.Request, sftpReque
case "ping":
sftpRequest <- false
req.Reply(true, []byte("pong"))
case "snapshot":
sftpRequest <- false
driveLetter := string(req.Payload[1:])
if driveLetter != "" {
_, err := snapshots.Snapshot(driveLetter, true)
if err != nil {
req.Reply(false, []byte(fmt.Sprintf("failed to initialize snapshot: %v", err)))
return
}
req.Reply(true, []byte("success"))
} else {
req.Reply(false, nil)
}
default:
sftpRequest <- false
req.Reply(false, nil)
Expand All @@ -143,7 +156,7 @@ func handleRequests(ctx context.Context, requests <-chan *ssh.Request, sftpReque
func handleSFTP(ctx context.Context, errChan chan string, channel ssh.Channel, driveLetter string) {
defer channel.Close()

snapshot, err := snapshots.Snapshot(driveLetter)
snapshot, err := snapshots.Snapshot(driveLetter, false)
if err != nil {
errChan <- fmt.Sprintf("failed to initialize snapshot: %v", err)
return
Expand Down
4 changes: 2 additions & 2 deletions internal/agent/snapshots/windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func getVSSFolder() (string, error) {
return configBasePath, nil
}

func Snapshot(driveLetter string) (*WinVSSSnapshot, error) {
func Snapshot(driveLetter string, forceNew bool) (*WinVSSSnapshot, error) {
knownSnaps := &KnownSnapshots{registry: "KnownSnaps"}
volName := filepath.VolumeName(fmt.Sprintf("%s:", driveLetter))

Expand All @@ -40,7 +40,7 @@ func Snapshot(driveLetter string) (*WinVSSSnapshot, error) {
snapshotPath := filepath.Join(vssFolder, driveLetter)
if knownSnap, err := knownSnaps.Get(snapshotPath); err == nil {
if _, err := vss.Get(snapshotPath); err == nil {
if time.Since(knownSnap.GetTimestamp()) < 15*time.Minute {
if time.Since(knownSnap.GetTimestamp()) < 15*time.Minute && !forceNew {
return knownSnap, nil
}
}
Expand Down
17 changes: 17 additions & 0 deletions internal/backend/backup/jobrun.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,23 @@ func RunBackup(job *store.Job, storeInstance *store.Store, waitChan chan struct{

_ = FixDatastore(job, storeInstance)

snapOk, err := storeInstance.AgentSnapshot(target)
if err != nil {
if agentMount != nil {
agentMount.Unmount()
}
cancel()
return nil, fmt.Errorf("RunBackup: agent snapshot error -> %w", err)
}

if !snapOk {
if agentMount != nil {
agentMount.Unmount()
}
cancel()
return nil, fmt.Errorf("RunBackup: agent snapshot error")
}

cmd := exec.Command("/usr/bin/proxmox-backup-client", cmdArgs...)
cmd.Env = os.Environ()
cmd.Env = append(cmd.Env, fmt.Sprintf("PBS_PASSWORD=%s", storeInstance.APIToken.Value))
Expand Down
62 changes: 62 additions & 0 deletions internal/store/snapshot.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//go:build linux

package store

import (
"fmt"
"os"
"path/filepath"
"strings"
"time"

"github.com/sonroyaalmerol/pbs-plus/internal/utils"
"golang.org/x/crypto/ssh"
)

func (storeInstance *Store) AgentSnapshot(agentTarget *Target) (bool, error) {
privKeyDir := filepath.Join(DbBasePath, "agent_keys")
privKeyFile := filepath.Join(privKeyDir, strings.ReplaceAll(fmt.Sprintf("%s.key", agentTarget.Name), " ", "-"))

pemBytes, err := os.ReadFile(privKeyFile)
if err != nil {
return false, fmt.Errorf("AgentSnapshot: error reading private key file -> %w", err)
}

signer, err := ssh.ParsePrivateKey(pemBytes)
if err != nil {
return false, fmt.Errorf("AgentSnapshot: error parsing private key -> %w", err)
}

agentPath := strings.TrimPrefix(agentTarget.Path, "agent://")
agentPathParts := strings.Split(agentPath, "/")
agentHost := agentPathParts[0]
agentDrive := agentPathParts[1]
agentDriveRune := []rune(agentDrive)[0]
agentPort, err := utils.DriveLetterPort(agentDriveRune)

sshConfig := &ssh.ClientConfig{
User: "proxmox",
Auth: []ssh.AuthMethod{ssh.PublicKeys(signer)},
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
Timeout: time.Second * 2,
}

client, err := ssh.Dial("tcp", fmt.Sprintf("%s:%s", agentHost, agentPort), sshConfig)
if err != nil {
return false, fmt.Errorf("AgentSnapshot: error dialing ssh client -> %w", err)
}
defer client.Close()

session, err := client.NewSession()
if err != nil {
return false, fmt.Errorf("AgentSnapshot: error creating new ssh session -> %w", err)
}
defer session.Close()

resp, err := session.SendRequest("snapshot", true, []byte(agentDrive))
if err != nil {
return false, fmt.Errorf("AgentSnapshot: error sending ping request -> %w", err)
}

return resp, nil
}

0 comments on commit 990d735

Please sign in to comment.