You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

270 lines
7.8 KiB

package dash
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"time"
"github.com/seaweedfs/seaweedfs/weed/glog"
)
const (
// Configuration file names
MaintenanceConfigFile = "maintenance.json"
AdminConfigFile = "admin.json"
ConfigDirPermissions = 0755
ConfigFilePermissions = 0644
)
// ConfigPersistence handles saving and loading configuration files
type ConfigPersistence struct {
dataDir string
}
// NewConfigPersistence creates a new configuration persistence manager
func NewConfigPersistence(dataDir string) *ConfigPersistence {
return &ConfigPersistence{
dataDir: dataDir,
}
}
// SaveMaintenanceConfig saves maintenance configuration to JSON file
func (cp *ConfigPersistence) SaveMaintenanceConfig(config *MaintenanceConfig) error {
if cp.dataDir == "" {
return fmt.Errorf("no data directory specified, cannot save configuration")
}
configPath := filepath.Join(cp.dataDir, MaintenanceConfigFile)
// Create directory if it doesn't exist
if err := os.MkdirAll(cp.dataDir, ConfigDirPermissions); err != nil {
return fmt.Errorf("failed to create config directory: %v", err)
}
// Marshal configuration to JSON
configData, err := json.MarshalIndent(config, "", " ")
if err != nil {
return fmt.Errorf("failed to marshal maintenance config: %v", err)
}
// Write to file
if err := os.WriteFile(configPath, configData, ConfigFilePermissions); err != nil {
return fmt.Errorf("failed to write maintenance config file: %v", err)
}
glog.V(1).Infof("Saved maintenance configuration to %s", configPath)
return nil
}
// LoadMaintenanceConfig loads maintenance configuration from JSON file
func (cp *ConfigPersistence) LoadMaintenanceConfig() (*MaintenanceConfig, error) {
if cp.dataDir == "" {
glog.V(1).Infof("No data directory specified, using default maintenance configuration")
return DefaultMaintenanceConfig(), nil
}
configPath := filepath.Join(cp.dataDir, MaintenanceConfigFile)
// Check if file exists
if _, err := os.Stat(configPath); os.IsNotExist(err) {
glog.V(1).Infof("Maintenance config file does not exist, using defaults: %s", configPath)
return DefaultMaintenanceConfig(), nil
}
// Read file
configData, err := os.ReadFile(configPath)
if err != nil {
return nil, fmt.Errorf("failed to read maintenance config file: %v", err)
}
// Unmarshal JSON
var config MaintenanceConfig
if err := json.Unmarshal(configData, &config); err != nil {
return nil, fmt.Errorf("failed to unmarshal maintenance config: %v", err)
}
glog.V(1).Infof("Loaded maintenance configuration from %s", configPath)
return &config, nil
}
// SaveAdminConfig saves general admin configuration to JSON file
func (cp *ConfigPersistence) SaveAdminConfig(config map[string]interface{}) error {
if cp.dataDir == "" {
return fmt.Errorf("no data directory specified, cannot save configuration")
}
configPath := filepath.Join(cp.dataDir, AdminConfigFile)
// Create directory if it doesn't exist
if err := os.MkdirAll(cp.dataDir, ConfigDirPermissions); err != nil {
return fmt.Errorf("failed to create config directory: %v", err)
}
// Marshal configuration to JSON
configData, err := json.MarshalIndent(config, "", " ")
if err != nil {
return fmt.Errorf("failed to marshal admin config: %v", err)
}
// Write to file
if err := os.WriteFile(configPath, configData, ConfigFilePermissions); err != nil {
return fmt.Errorf("failed to write admin config file: %v", err)
}
glog.V(1).Infof("Saved admin configuration to %s", configPath)
return nil
}
// LoadAdminConfig loads general admin configuration from JSON file
func (cp *ConfigPersistence) LoadAdminConfig() (map[string]interface{}, error) {
if cp.dataDir == "" {
glog.V(1).Infof("No data directory specified, using default admin configuration")
return make(map[string]interface{}), nil
}
configPath := filepath.Join(cp.dataDir, AdminConfigFile)
// Check if file exists
if _, err := os.Stat(configPath); os.IsNotExist(err) {
glog.V(1).Infof("Admin config file does not exist, using defaults: %s", configPath)
return make(map[string]interface{}), nil
}
// Read file
configData, err := os.ReadFile(configPath)
if err != nil {
return nil, fmt.Errorf("failed to read admin config file: %v", err)
}
// Unmarshal JSON
var config map[string]interface{}
if err := json.Unmarshal(configData, &config); err != nil {
return nil, fmt.Errorf("failed to unmarshal admin config: %v", err)
}
glog.V(1).Infof("Loaded admin configuration from %s", configPath)
return config, nil
}
// GetConfigPath returns the path to a configuration file
func (cp *ConfigPersistence) GetConfigPath(filename string) string {
if cp.dataDir == "" {
return ""
}
return filepath.Join(cp.dataDir, filename)
}
// ListConfigFiles returns all configuration files in the data directory
func (cp *ConfigPersistence) ListConfigFiles() ([]string, error) {
if cp.dataDir == "" {
return nil, fmt.Errorf("no data directory specified")
}
files, err := os.ReadDir(cp.dataDir)
if err != nil {
return nil, fmt.Errorf("failed to read config directory: %v", err)
}
var configFiles []string
for _, file := range files {
if !file.IsDir() && filepath.Ext(file.Name()) == ".json" {
configFiles = append(configFiles, file.Name())
}
}
return configFiles, nil
}
// BackupConfig creates a backup of a configuration file
func (cp *ConfigPersistence) BackupConfig(filename string) error {
if cp.dataDir == "" {
return fmt.Errorf("no data directory specified")
}
configPath := filepath.Join(cp.dataDir, filename)
if _, err := os.Stat(configPath); os.IsNotExist(err) {
return fmt.Errorf("config file does not exist: %s", filename)
}
// Create backup filename with timestamp
timestamp := time.Now().Format("2006-01-02_15-04-05")
backupName := fmt.Sprintf("%s.backup_%s", filename, timestamp)
backupPath := filepath.Join(cp.dataDir, backupName)
// Copy file
configData, err := os.ReadFile(configPath)
if err != nil {
return fmt.Errorf("failed to read config file: %v", err)
}
if err := os.WriteFile(backupPath, configData, ConfigFilePermissions); err != nil {
return fmt.Errorf("failed to create backup: %v", err)
}
glog.V(1).Infof("Created backup of %s as %s", filename, backupName)
return nil
}
// RestoreConfig restores a configuration file from a backup
func (cp *ConfigPersistence) RestoreConfig(filename, backupName string) error {
if cp.dataDir == "" {
return fmt.Errorf("no data directory specified")
}
backupPath := filepath.Join(cp.dataDir, backupName)
if _, err := os.Stat(backupPath); os.IsNotExist(err) {
return fmt.Errorf("backup file does not exist: %s", backupName)
}
// Read backup file
backupData, err := os.ReadFile(backupPath)
if err != nil {
return fmt.Errorf("failed to read backup file: %v", err)
}
// Write to config file
configPath := filepath.Join(cp.dataDir, filename)
if err := os.WriteFile(configPath, backupData, ConfigFilePermissions); err != nil {
return fmt.Errorf("failed to restore config: %v", err)
}
glog.V(1).Infof("Restored %s from backup %s", filename, backupName)
return nil
}
// GetDataDir returns the data directory path
func (cp *ConfigPersistence) GetDataDir() string {
return cp.dataDir
}
// IsConfigured returns true if a data directory is configured
func (cp *ConfigPersistence) IsConfigured() bool {
return cp.dataDir != ""
}
// GetConfigInfo returns information about the configuration storage
func (cp *ConfigPersistence) GetConfigInfo() map[string]interface{} {
info := map[string]interface{}{
"data_dir_configured": cp.IsConfigured(),
"data_dir": cp.dataDir,
}
if cp.IsConfigured() {
// Check if data directory exists
if _, err := os.Stat(cp.dataDir); err == nil {
info["data_dir_exists"] = true
// List config files
configFiles, err := cp.ListConfigFiles()
if err == nil {
info["config_files"] = configFiles
}
} else {
info["data_dir_exists"] = false
}
}
return info
}