package iscsi import ( "fmt" "os" "path/filepath" ) // AddLUN adds a LUN to a target func (s *Service) AddLUN(targetID string, lunNumber int, devicePath string, lunType string) error { s.logger.Info("Adding LUN to target", "target", targetID, "lun", lunNumber, "device", devicePath, "type", lunType) // Validate device exists if _, err := os.Stat(devicePath); err != nil { return fmt.Errorf("device not found: %s", devicePath) } // Validate LUN type if lunType != "disk" && lunType != "tape" { return fmt.Errorf("invalid LUN type: %s (must be 'disk' or 'tape')", lunType) } // For tape library: // LUN 0 = Media changer // LUN 1-8 = Tape drives if lunType == "tape" { if lunNumber == 0 { // Media changer devicePath = "/dev/sg0" // Default media changer } else if lunNumber >= 1 && lunNumber <= 8 { // Tape drive devicePath = fmt.Sprintf("/dev/nst%d", lunNumber-1) } else { return fmt.Errorf("invalid LUN number for tape: %d (must be 0-8)", lunNumber) } } // Update target configuration target, err := s.GetTarget(targetID) if err != nil { return err } // Check if LUN already exists for _, lun := range target.LUNs { if lun.Number == lunNumber { return fmt.Errorf("LUN %d already exists", lunNumber) } } // Add LUN target.LUNs = append(target.LUNs, LUN{ Number: lunNumber, Device: devicePath, Type: lunType, }) // Write updated config return s.writeSCSTConfig(target) } // RemoveLUN removes a LUN from a target func (s *Service) RemoveLUN(targetID string, lunNumber int) error { s.logger.Info("Removing LUN from target", "target", targetID, "lun", lunNumber) target, err := s.GetTarget(targetID) if err != nil { return err } // Find and remove LUN found := false newLUNs := []LUN{} for _, lun := range target.LUNs { if lun.Number != lunNumber { newLUNs = append(newLUNs, lun) } else { found = true } } if !found { return fmt.Errorf("LUN %d not found", lunNumber) } target.LUNs = newLUNs return s.writeSCSTConfig(target) } // MapRepositoryToLUN maps a disk repository to an iSCSI LUN func (s *Service) MapRepositoryToLUN(targetID string, repositoryPath string, lunNumber int) error { // Resolve repository path to device devicePath, err := filepath.EvalSymlinks(repositoryPath) if err != nil { return fmt.Errorf("failed to resolve repository path: %w", err) } return s.AddLUN(targetID, lunNumber, devicePath, "disk") }