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.
		
		
		
		
		
			
		
			
				
					
					
						
							287 lines
						
					
					
						
							10 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							287 lines
						
					
					
						
							10 KiB
						
					
					
				| package maintenance | |
| 
 | |
| import ( | |
| 	"fmt" | |
| 	"time" | |
| 
 | |
| 	"github.com/seaweedfs/seaweedfs/weed/pb/worker_pb" | |
| ) | |
| 
 | |
| // MaintenanceConfigManager handles protobuf-based configuration | |
| type MaintenanceConfigManager struct { | |
| 	config *worker_pb.MaintenanceConfig | |
| } | |
| 
 | |
| // NewMaintenanceConfigManager creates a new config manager with defaults | |
| func NewMaintenanceConfigManager() *MaintenanceConfigManager { | |
| 	return &MaintenanceConfigManager{ | |
| 		config: DefaultMaintenanceConfigProto(), | |
| 	} | |
| } | |
| 
 | |
| // DefaultMaintenanceConfigProto returns default configuration as protobuf | |
| func DefaultMaintenanceConfigProto() *worker_pb.MaintenanceConfig { | |
| 	return &worker_pb.MaintenanceConfig{ | |
| 		Enabled:                true, | |
| 		ScanIntervalSeconds:    30 * 60,     // 30 minutes | |
| 		WorkerTimeoutSeconds:   5 * 60,      // 5 minutes | |
| 		TaskTimeoutSeconds:     2 * 60 * 60, // 2 hours | |
| 		RetryDelaySeconds:      15 * 60,     // 15 minutes | |
| 		MaxRetries:             3, | |
| 		CleanupIntervalSeconds: 24 * 60 * 60,     // 24 hours | |
| 		TaskRetentionSeconds:   7 * 24 * 60 * 60, // 7 days | |
| 		// Policy field will be populated dynamically from separate task configuration files | |
| 		Policy: nil, | |
| 	} | |
| } | |
| 
 | |
| // GetConfig returns the current configuration | |
| func (mcm *MaintenanceConfigManager) GetConfig() *worker_pb.MaintenanceConfig { | |
| 	return mcm.config | |
| } | |
| 
 | |
| // Type-safe configuration accessors | |
|  | |
| // GetVacuumConfig returns vacuum-specific configuration for a task type | |
| func (mcm *MaintenanceConfigManager) GetVacuumConfig(taskType string) *worker_pb.VacuumTaskConfig { | |
| 	if policy := mcm.getTaskPolicy(taskType); policy != nil { | |
| 		if vacuumConfig := policy.GetVacuumConfig(); vacuumConfig != nil { | |
| 			return vacuumConfig | |
| 		} | |
| 	} | |
| 	// Return defaults if not configured | |
| 	return &worker_pb.VacuumTaskConfig{ | |
| 		GarbageThreshold:   0.3, | |
| 		MinVolumeAgeHours:  24, | |
| 		MinIntervalSeconds: 7 * 24 * 60 * 60, // 7 days | |
| 	} | |
| } | |
| 
 | |
| // GetErasureCodingConfig returns EC-specific configuration for a task type | |
| func (mcm *MaintenanceConfigManager) GetErasureCodingConfig(taskType string) *worker_pb.ErasureCodingTaskConfig { | |
| 	if policy := mcm.getTaskPolicy(taskType); policy != nil { | |
| 		if ecConfig := policy.GetErasureCodingConfig(); ecConfig != nil { | |
| 			return ecConfig | |
| 		} | |
| 	} | |
| 	// Return defaults if not configured | |
| 	return &worker_pb.ErasureCodingTaskConfig{ | |
| 		FullnessRatio:    0.95, | |
| 		QuietForSeconds:  3600, | |
| 		MinVolumeSizeMb:  100, | |
| 		CollectionFilter: "", | |
| 	} | |
| } | |
| 
 | |
| // GetBalanceConfig returns balance-specific configuration for a task type | |
| func (mcm *MaintenanceConfigManager) GetBalanceConfig(taskType string) *worker_pb.BalanceTaskConfig { | |
| 	if policy := mcm.getTaskPolicy(taskType); policy != nil { | |
| 		if balanceConfig := policy.GetBalanceConfig(); balanceConfig != nil { | |
| 			return balanceConfig | |
| 		} | |
| 	} | |
| 	// Return defaults if not configured | |
| 	return &worker_pb.BalanceTaskConfig{ | |
| 		ImbalanceThreshold: 0.2, | |
| 		MinServerCount:     2, | |
| 	} | |
| } | |
| 
 | |
| // GetReplicationConfig returns replication-specific configuration for a task type | |
| func (mcm *MaintenanceConfigManager) GetReplicationConfig(taskType string) *worker_pb.ReplicationTaskConfig { | |
| 	if policy := mcm.getTaskPolicy(taskType); policy != nil { | |
| 		if replicationConfig := policy.GetReplicationConfig(); replicationConfig != nil { | |
| 			return replicationConfig | |
| 		} | |
| 	} | |
| 	// Return defaults if not configured | |
| 	return &worker_pb.ReplicationTaskConfig{ | |
| 		TargetReplicaCount: 2, | |
| 	} | |
| } | |
| 
 | |
| // Typed convenience methods for getting task configurations | |
|  | |
| // GetVacuumTaskConfigForType returns vacuum configuration for a specific task type | |
| func (mcm *MaintenanceConfigManager) GetVacuumTaskConfigForType(taskType string) *worker_pb.VacuumTaskConfig { | |
| 	return GetVacuumTaskConfig(mcm.config.Policy, MaintenanceTaskType(taskType)) | |
| } | |
| 
 | |
| // GetErasureCodingTaskConfigForType returns erasure coding configuration for a specific task type | |
| func (mcm *MaintenanceConfigManager) GetErasureCodingTaskConfigForType(taskType string) *worker_pb.ErasureCodingTaskConfig { | |
| 	return GetErasureCodingTaskConfig(mcm.config.Policy, MaintenanceTaskType(taskType)) | |
| } | |
| 
 | |
| // GetBalanceTaskConfigForType returns balance configuration for a specific task type | |
| func (mcm *MaintenanceConfigManager) GetBalanceTaskConfigForType(taskType string) *worker_pb.BalanceTaskConfig { | |
| 	return GetBalanceTaskConfig(mcm.config.Policy, MaintenanceTaskType(taskType)) | |
| } | |
| 
 | |
| // GetReplicationTaskConfigForType returns replication configuration for a specific task type | |
| func (mcm *MaintenanceConfigManager) GetReplicationTaskConfigForType(taskType string) *worker_pb.ReplicationTaskConfig { | |
| 	return GetReplicationTaskConfig(mcm.config.Policy, MaintenanceTaskType(taskType)) | |
| } | |
| 
 | |
| // Helper methods | |
|  | |
| func (mcm *MaintenanceConfigManager) getTaskPolicy(taskType string) *worker_pb.TaskPolicy { | |
| 	if mcm.config.Policy != nil && mcm.config.Policy.TaskPolicies != nil { | |
| 		return mcm.config.Policy.TaskPolicies[taskType] | |
| 	} | |
| 	return nil | |
| } | |
| 
 | |
| // IsTaskEnabled returns whether a task type is enabled | |
| func (mcm *MaintenanceConfigManager) IsTaskEnabled(taskType string) bool { | |
| 	if policy := mcm.getTaskPolicy(taskType); policy != nil { | |
| 		return policy.Enabled | |
| 	} | |
| 	return false | |
| } | |
| 
 | |
| // GetMaxConcurrent returns the max concurrent limit for a task type | |
| func (mcm *MaintenanceConfigManager) GetMaxConcurrent(taskType string) int32 { | |
| 	if policy := mcm.getTaskPolicy(taskType); policy != nil { | |
| 		return policy.MaxConcurrent | |
| 	} | |
| 	return 1 // Default | |
| } | |
| 
 | |
| // GetRepeatInterval returns the repeat interval for a task type in seconds | |
| func (mcm *MaintenanceConfigManager) GetRepeatInterval(taskType string) int32 { | |
| 	if policy := mcm.getTaskPolicy(taskType); policy != nil { | |
| 		return policy.RepeatIntervalSeconds | |
| 	} | |
| 	return mcm.config.Policy.DefaultRepeatIntervalSeconds | |
| } | |
| 
 | |
| // GetCheckInterval returns the check interval for a task type in seconds | |
| func (mcm *MaintenanceConfigManager) GetCheckInterval(taskType string) int32 { | |
| 	if policy := mcm.getTaskPolicy(taskType); policy != nil { | |
| 		return policy.CheckIntervalSeconds | |
| 	} | |
| 	return mcm.config.Policy.DefaultCheckIntervalSeconds | |
| } | |
| 
 | |
| // Duration accessor methods | |
|  | |
| // GetScanInterval returns the scan interval as a time.Duration | |
| func (mcm *MaintenanceConfigManager) GetScanInterval() time.Duration { | |
| 	return time.Duration(mcm.config.ScanIntervalSeconds) * time.Second | |
| } | |
| 
 | |
| // GetWorkerTimeout returns the worker timeout as a time.Duration | |
| func (mcm *MaintenanceConfigManager) GetWorkerTimeout() time.Duration { | |
| 	return time.Duration(mcm.config.WorkerTimeoutSeconds) * time.Second | |
| } | |
| 
 | |
| // GetTaskTimeout returns the task timeout as a time.Duration | |
| func (mcm *MaintenanceConfigManager) GetTaskTimeout() time.Duration { | |
| 	return time.Duration(mcm.config.TaskTimeoutSeconds) * time.Second | |
| } | |
| 
 | |
| // GetRetryDelay returns the retry delay as a time.Duration | |
| func (mcm *MaintenanceConfigManager) GetRetryDelay() time.Duration { | |
| 	return time.Duration(mcm.config.RetryDelaySeconds) * time.Second | |
| } | |
| 
 | |
| // GetCleanupInterval returns the cleanup interval as a time.Duration | |
| func (mcm *MaintenanceConfigManager) GetCleanupInterval() time.Duration { | |
| 	return time.Duration(mcm.config.CleanupIntervalSeconds) * time.Second | |
| } | |
| 
 | |
| // GetTaskRetention returns the task retention period as a time.Duration | |
| func (mcm *MaintenanceConfigManager) GetTaskRetention() time.Duration { | |
| 	return time.Duration(mcm.config.TaskRetentionSeconds) * time.Second | |
| } | |
| 
 | |
| // ValidateMaintenanceConfigWithSchema validates protobuf maintenance configuration using ConfigField rules | |
| func ValidateMaintenanceConfigWithSchema(config *worker_pb.MaintenanceConfig) error { | |
| 	if config == nil { | |
| 		return fmt.Errorf("configuration cannot be nil") | |
| 	} | |
| 
 | |
| 	// Get the schema to access field validation rules | |
| 	schema := GetMaintenanceConfigSchema() | |
| 
 | |
| 	// Validate each field individually using the ConfigField rules | |
| 	if err := validateFieldWithSchema(schema, "enabled", config.Enabled); err != nil { | |
| 		return err | |
| 	} | |
| 
 | |
| 	if err := validateFieldWithSchema(schema, "scan_interval_seconds", int(config.ScanIntervalSeconds)); err != nil { | |
| 		return err | |
| 	} | |
| 
 | |
| 	if err := validateFieldWithSchema(schema, "worker_timeout_seconds", int(config.WorkerTimeoutSeconds)); err != nil { | |
| 		return err | |
| 	} | |
| 
 | |
| 	if err := validateFieldWithSchema(schema, "task_timeout_seconds", int(config.TaskTimeoutSeconds)); err != nil { | |
| 		return err | |
| 	} | |
| 
 | |
| 	if err := validateFieldWithSchema(schema, "retry_delay_seconds", int(config.RetryDelaySeconds)); err != nil { | |
| 		return err | |
| 	} | |
| 
 | |
| 	if err := validateFieldWithSchema(schema, "max_retries", int(config.MaxRetries)); err != nil { | |
| 		return err | |
| 	} | |
| 
 | |
| 	if err := validateFieldWithSchema(schema, "cleanup_interval_seconds", int(config.CleanupIntervalSeconds)); err != nil { | |
| 		return err | |
| 	} | |
| 
 | |
| 	if err := validateFieldWithSchema(schema, "task_retention_seconds", int(config.TaskRetentionSeconds)); err != nil { | |
| 		return err | |
| 	} | |
| 
 | |
| 	// Validate policy fields if present | |
| 	if config.Policy != nil { | |
| 		// Note: These field names might need to be adjusted based on the actual schema | |
| 		if err := validatePolicyField("global_max_concurrent", int(config.Policy.GlobalMaxConcurrent)); err != nil { | |
| 			return err | |
| 		} | |
| 
 | |
| 		if err := validatePolicyField("default_repeat_interval_seconds", int(config.Policy.DefaultRepeatIntervalSeconds)); err != nil { | |
| 			return err | |
| 		} | |
| 
 | |
| 		if err := validatePolicyField("default_check_interval_seconds", int(config.Policy.DefaultCheckIntervalSeconds)); err != nil { | |
| 			return err | |
| 		} | |
| 	} | |
| 
 | |
| 	return nil | |
| } | |
| 
 | |
| // validateFieldWithSchema validates a single field using its ConfigField definition | |
| func validateFieldWithSchema(schema *MaintenanceConfigSchema, fieldName string, value interface{}) error { | |
| 	field := schema.GetFieldByName(fieldName) | |
| 	if field == nil { | |
| 		// Field not in schema, skip validation | |
| 		return nil | |
| 	} | |
| 
 | |
| 	return field.ValidateValue(value) | |
| } | |
| 
 | |
| // validatePolicyField validates policy fields (simplified validation for now) | |
| func validatePolicyField(fieldName string, value int) error { | |
| 	switch fieldName { | |
| 	case "global_max_concurrent": | |
| 		if value < 1 || value > 20 { | |
| 			return fmt.Errorf("Global Max Concurrent must be between 1 and 20, got %d", value) | |
| 		} | |
| 	case "default_repeat_interval": | |
| 		if value < 1 || value > 168 { | |
| 			return fmt.Errorf("Default Repeat Interval must be between 1 and 168 hours, got %d", value) | |
| 		} | |
| 	case "default_check_interval": | |
| 		if value < 1 || value > 168 { | |
| 			return fmt.Errorf("Default Check Interval must be between 1 and 168 hours, got %d", value) | |
| 		} | |
| 	} | |
| 	return nil | |
| }
 |