Volt CLI: source-available under AGPSL v5.0

Complete infrastructure platform CLI:
- Container runtime (systemd-nspawn)
- VoltVisor VMs (Neutron Stardust / QEMU)
- Stellarium CAS (content-addressed storage)
- ORAS Registry
- GitOps integration
- Landlock LSM security
- Compose orchestration
- Mesh networking

Copyright (c) Armored Gates LLC. All rights reserved.
Licensed under AGPSL v5.0
This commit is contained in:
Karl Clinger
2026-03-21 00:30:23 -05:00
commit 0ebe75b2ca
155 changed files with 63317 additions and 0 deletions

301
pkg/storage/storage.go Normal file
View File

@@ -0,0 +1,301 @@
/*
Volt Storage - Git-attached persistent storage
Features:
- Git repositories for persistence
- Shared storage across VMs
- Copy-on-write overlays
- Snapshot/restore via git
- Multi-developer collaboration
*/
package storage
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"time"
)
// AttachedStorage represents storage attached to a VM
type AttachedStorage struct {
Name string
Source string // Host path or git URL
Target string // Mount point inside VM
Type string // git, bind, overlay
ReadOnly bool
GitBranch string
GitRemote string
}
// Manager handles storage operations
type Manager struct {
baseDir string
cacheDir string
overlayDir string
}
// NewManager creates a new storage manager
func NewManager(baseDir string) *Manager {
return &Manager{
baseDir: baseDir,
cacheDir: filepath.Join(baseDir, "cache"),
overlayDir: filepath.Join(baseDir, "overlays"),
}
}
// Setup initializes storage directories
func (m *Manager) Setup() error {
dirs := []string{m.baseDir, m.cacheDir, m.overlayDir}
for _, dir := range dirs {
if err := os.MkdirAll(dir, 0755); err != nil {
return fmt.Errorf("failed to create %s: %w", dir, err)
}
}
return nil
}
// AttachGit clones or updates a git repository for VM use
func (m *Manager) AttachGit(vmName string, gitURL string, branch string) (*AttachedStorage, error) {
// Determine local path for this repo
repoName := filepath.Base(strings.TrimSuffix(gitURL, ".git"))
localPath := filepath.Join(m.cacheDir, "git", repoName)
// Clone or fetch
if _, err := os.Stat(filepath.Join(localPath, ".git")); os.IsNotExist(err) {
// Clone
fmt.Printf("Cloning %s...\n", gitURL)
cmd := exec.Command("git", "clone", "--depth=1", "-b", branch, gitURL, localPath)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
return nil, fmt.Errorf("git clone failed: %w", err)
}
} else {
// Fetch latest
fmt.Printf("Fetching latest from %s...\n", gitURL)
cmd := exec.Command("git", "-C", localPath, "fetch", "--depth=1", "origin", branch)
cmd.Run() // Ignore errors for offline operation
cmd = exec.Command("git", "-C", localPath, "checkout", branch)
cmd.Run()
}
// Create overlay for this VM (copy-on-write)
overlayPath := filepath.Join(m.overlayDir, vmName, repoName)
upperDir := filepath.Join(overlayPath, "upper")
workDir := filepath.Join(overlayPath, "work")
mergedDir := filepath.Join(overlayPath, "merged")
for _, dir := range []string{upperDir, workDir, mergedDir} {
os.MkdirAll(dir, 0755)
}
// Mount overlay
mountCmd := exec.Command("mount", "-t", "overlay", "overlay",
"-o", fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", localPath, upperDir, workDir),
mergedDir)
if err := mountCmd.Run(); err != nil {
// Fallback: just use the local path directly
mergedDir = localPath
}
return &AttachedStorage{
Name: repoName,
Source: gitURL,
Target: filepath.Join("/mnt", repoName),
Type: "git",
GitBranch: branch,
GitRemote: "origin",
}, nil
}
// AttachBind creates a bind mount from host to VM
func (m *Manager) AttachBind(vmName, hostPath, vmPath string, readOnly bool) (*AttachedStorage, error) {
// Verify source exists
if _, err := os.Stat(hostPath); err != nil {
return nil, fmt.Errorf("source path does not exist: %s", hostPath)
}
return &AttachedStorage{
Name: filepath.Base(hostPath),
Source: hostPath,
Target: vmPath,
Type: "bind",
ReadOnly: readOnly,
}, nil
}
// CreateOverlay creates a copy-on-write overlay
func (m *Manager) CreateOverlay(vmName, basePath, vmPath string) (*AttachedStorage, error) {
overlayPath := filepath.Join(m.overlayDir, vmName, filepath.Base(basePath))
upperDir := filepath.Join(overlayPath, "upper")
workDir := filepath.Join(overlayPath, "work")
mergedDir := filepath.Join(overlayPath, "merged")
for _, dir := range []string{upperDir, workDir, mergedDir} {
if err := os.MkdirAll(dir, 0755); err != nil {
return nil, fmt.Errorf("failed to create overlay dir: %w", err)
}
}
return &AttachedStorage{
Name: filepath.Base(basePath),
Source: basePath,
Target: vmPath,
Type: "overlay",
}, nil
}
// Snapshot creates a git commit of VM changes
func (m *Manager) Snapshot(vmName, storageName, message string) error {
overlayPath := filepath.Join(m.overlayDir, vmName, storageName, "upper")
// Check if there are changes
if _, err := os.Stat(overlayPath); os.IsNotExist(err) {
return fmt.Errorf("no overlay found for %s/%s", vmName, storageName)
}
// Create snapshot directory
snapshotDir := filepath.Join(m.baseDir, "snapshots", vmName, storageName)
os.MkdirAll(snapshotDir, 0755)
// Initialize git if needed
gitDir := filepath.Join(snapshotDir, ".git")
if _, err := os.Stat(gitDir); os.IsNotExist(err) {
exec.Command("git", "-C", snapshotDir, "init").Run()
exec.Command("git", "-C", snapshotDir, "config", "user.email", "volt@localhost").Run()
exec.Command("git", "-C", snapshotDir, "config", "user.name", "Volt").Run()
}
// Copy changes to snapshot dir
exec.Command("rsync", "-a", "--delete", overlayPath+"/", snapshotDir+"/").Run()
// Commit
timestamp := time.Now().Format("2006-01-02 15:04:05")
if message == "" {
message = fmt.Sprintf("Snapshot at %s", timestamp)
}
exec.Command("git", "-C", snapshotDir, "add", "-A").Run()
exec.Command("git", "-C", snapshotDir, "commit", "-m", message).Run()
return nil
}
// Restore restores VM storage from a snapshot
func (m *Manager) Restore(vmName, storageName, commitHash string) error {
snapshotDir := filepath.Join(m.baseDir, "snapshots", vmName, storageName)
overlayUpper := filepath.Join(m.overlayDir, vmName, storageName, "upper")
// Checkout specific commit
if commitHash != "" {
exec.Command("git", "-C", snapshotDir, "checkout", commitHash).Run()
}
// Restore to overlay upper
os.RemoveAll(overlayUpper)
os.MkdirAll(overlayUpper, 0755)
exec.Command("rsync", "-a", snapshotDir+"/", overlayUpper+"/").Run()
return nil
}
// ListSnapshots returns available snapshots for a storage
func (m *Manager) ListSnapshots(vmName, storageName string) ([]Snapshot, error) {
snapshotDir := filepath.Join(m.baseDir, "snapshots", vmName, storageName)
// Get git log
out, err := exec.Command("git", "-C", snapshotDir, "log", "--oneline", "-20").Output()
if err != nil {
return nil, fmt.Errorf("failed to list snapshots: %w", err)
}
var snapshots []Snapshot
for _, line := range strings.Split(string(out), "\n") {
if line == "" {
continue
}
parts := strings.SplitN(line, " ", 2)
if len(parts) == 2 {
snapshots = append(snapshots, Snapshot{
Hash: parts[0],
Message: parts[1],
})
}
}
return snapshots, nil
}
// Unmount unmounts all storage for a VM
func (m *Manager) Unmount(vmName string) error {
vmOverlayDir := filepath.Join(m.overlayDir, vmName)
// Find and unmount all merged directories
entries, err := os.ReadDir(vmOverlayDir)
if err != nil {
return nil // Nothing to unmount
}
for _, entry := range entries {
if entry.IsDir() {
mergedDir := filepath.Join(vmOverlayDir, entry.Name(), "merged")
exec.Command("umount", mergedDir).Run()
}
}
return nil
}
// Cleanup removes all storage for a VM
func (m *Manager) Cleanup(vmName string) error {
m.Unmount(vmName)
// Remove overlay directory
overlayPath := filepath.Join(m.overlayDir, vmName)
os.RemoveAll(overlayPath)
// Keep snapshots (can be manually cleaned)
return nil
}
// Snapshot represents a storage snapshot
type Snapshot struct {
Hash string
Message string
Time time.Time
}
// MountEntry generates fstab entry for storage
func (s *AttachedStorage) MountEntry() string {
opts := "defaults"
if s.ReadOnly {
opts += ",ro"
}
switch s.Type {
case "bind":
return fmt.Sprintf("%s %s none bind,%s 0 0", s.Source, s.Target, opts)
case "overlay":
return fmt.Sprintf("overlay %s overlay %s 0 0", s.Target, opts)
default:
return fmt.Sprintf("%s %s auto %s 0 0", s.Source, s.Target, opts)
}
}
// SyncToRemote pushes changes to git remote
func (m *Manager) SyncToRemote(vmName, storageName string) error {
snapshotDir := filepath.Join(m.baseDir, "snapshots", vmName, storageName)
return exec.Command("git", "-C", snapshotDir, "push", "origin", "HEAD").Run()
}
// SyncFromRemote pulls changes from git remote
func (m *Manager) SyncFromRemote(vmName, storageName string) error {
snapshotDir := filepath.Join(m.baseDir, "snapshots", vmName, storageName)
return exec.Command("git", "-C", snapshotDir, "pull", "origin", "HEAD").Run()
}