first commit

This commit is contained in:
2026-04-17 11:56:39 +07:00
commit 2a79993f43
506 changed files with 342249 additions and 0 deletions
+212
View File
@@ -0,0 +1,212 @@
package nfs
import (
"fmt"
"os"
"os/exec"
"sync"
"time"
"github.com/sirupsen/logrus"
)
// Manager управляет NFS монтированием
type Manager struct {
mu sync.RWMutex
enabled bool
server string
exportPath string
mountPoint string
options string
mounted bool
mountTime time.Time
}
var (
// DefaultManager - глобальный менеджер NFS
DefaultManager *Manager
initOnce sync.Once
)
// Config конфигурация NFS
type Config struct {
Enabled bool
Server string
ExportPath string
MountPoint string
Options string
}
// Init инициализирует глобальный менеджер NFS
func Init(cfg Config) {
initOnce.Do(func() {
DefaultManager = &Manager{
enabled: cfg.Enabled,
server: cfg.Server,
exportPath: cfg.ExportPath,
mountPoint: cfg.MountPoint,
options: cfg.Options,
mounted: false,
}
if cfg.Enabled {
logrus.Infof("NFS manager initialized: %s:%s -> %s",
cfg.Server, cfg.ExportPath, cfg.MountPoint)
} else {
logrus.Info("NFS manager initialized but disabled")
}
})
}
// IsEnabled возвращает статус включения NFS
func (m *Manager) IsEnabled() bool {
m.mu.RLock()
defer m.mu.RUnlock()
return m.enabled
}
// IsMounted проверяет, смонтирован ли NFS
func (m *Manager) IsMounted() bool {
m.mu.RLock()
defer m.mu.RUnlock()
if !m.mounted {
return false
}
// Проверяем актуальность монтирования через filesystem
return checkMountPoint(m.mountPoint)
}
// Mount монтирует NFS share
func (m *Manager) Mount() error {
m.mu.Lock()
defer m.mu.Unlock()
if !m.enabled {
logrus.Debug("NFS mounting skipped: disabled")
return nil
}
// Проверяем, уже ли смонтировано
if checkMountPoint(m.mountPoint) {
logrus.Debugf("NFS already mounted at %s", m.mountPoint)
m.mounted = true
m.mountTime = time.Now()
return nil
}
logrus.Infof("Attempting to mount NFS: %s:%s -> %s",
m.server, m.exportPath, m.mountPoint)
// Создаем точку монтирования если не существует
if err := os.MkdirAll(m.mountPoint, 0755); err != nil {
logrus.Errorf("Failed to create mount point %s: %v", m.mountPoint, err)
return fmt.Errorf("failed to create mount point: %w", err)
}
// Формируем опции монтирования
mountOptions := m.options
if mountOptions == "" {
mountOptions = "rw,vers=4.1,timeo=50,retrans=2"
}
// Выполняем команду mount
cmd := exec.Command("mount", "-t", "nfs",
fmt.Sprintf("%s:%s", m.server, m.exportPath),
m.mountPoint,
"-o", mountOptions)
output, err := cmd.CombinedOutput()
if err != nil {
logrus.Errorf("Failed to mount NFS: %v, output: %s", err, string(output))
m.mounted = false
return fmt.Errorf("failed to mount NFS: %w, output: %s", err, string(output))
}
m.mounted = true
m.mountTime = time.Now()
logrus.Infof("NFS mounted successfully: %s:%s -> %s",
m.server, m.exportPath, m.mountPoint)
return nil
}
// Unmount размонтирует NFS share
func (m *Manager) Unmount() error {
m.mu.Lock()
defer m.mu.Unlock()
if !m.enabled {
logrus.Debug("NFS unmounting skipped: disabled")
return nil
}
logrus.Infof("Unmounting NFS from %s", m.mountPoint)
cmd := exec.Command("umount", m.mountPoint)
output, err := cmd.CombinedOutput()
if err != nil {
logrus.Errorf("Failed to unmount NFS: %v, output: %s", err, string(output))
return fmt.Errorf("failed to unmount NFS: %w, output: %s", err, string(output))
}
m.mounted = false
logrus.Infof("NFS unmounted successfully from %s", m.mountPoint)
return nil
}
// CheckHealth проверяет доступность NFS mount point
func (m *Manager) CheckHealth() error {
m.mu.RLock()
defer m.mu.RUnlock()
if !m.enabled {
return nil
}
return checkMountPointWithDetails(m.mountPoint)
}
// Remount пытается перемонтировать NFS если он размонтирован
func (m *Manager) Remount() error {
if !m.IsMounted() {
logrus.Warn("NFS not mounted, attempting remount...")
return m.Mount()
}
return nil
}
// GetMountPoint возвращает точку монтирования
func (m *Manager) GetMountPoint() string {
m.mu.RLock()
defer m.mu.RUnlock()
return m.mountPoint
}
// checkMountPoint проверяет, смонтирована ли точка
func checkMountPoint(mountPoint string) bool {
// Проверяем через statfs (на Linux)
// Если точка смонтирована, то она будет иметь другой device ID чем родитель
cmd := exec.Command("mountpoint", "-q", mountPoint)
err := cmd.Run()
return err == nil
}
// checkMountPointWithDetails проверяет с логированием
func checkMountPointWithDetails(mountPoint string) error {
if !checkMountPoint(mountPoint) {
return fmt.Errorf("mount point %s is not mounted", mountPoint)
}
return nil
}
// EnsureMounted гарантирует что NFS смонтирован, монтирует если нужно
func EnsureMounted() error {
if DefaultManager == nil {
logrus.Debug("NFS manager not initialized")
return nil
}
return DefaultManager.Remount()
}