BAMS initial project structure
This commit is contained in:
222
backend/internal/services/iscsi/service.go
Normal file
222
backend/internal/services/iscsi/service.go
Normal file
@@ -0,0 +1,222 @@
|
||||
package iscsi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/bams/backend/internal/config"
|
||||
"github.com/bams/backend/internal/logger"
|
||||
)
|
||||
|
||||
type Target struct {
|
||||
ID string `json:"id"`
|
||||
IQN string `json:"iqn"`
|
||||
Portals []string `json:"portals"`
|
||||
Initiators []string `json:"initiators"`
|
||||
LUNs []LUN `json:"luns"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
type LUN struct {
|
||||
Number int `json:"number"`
|
||||
Device string `json:"device"`
|
||||
Type string `json:"type"` // "disk" or "tape"
|
||||
}
|
||||
|
||||
type Session struct {
|
||||
TargetIQN string `json:"target_iqn"`
|
||||
InitiatorIQN string `json:"initiator_iqn"`
|
||||
IP string `json:"ip"`
|
||||
State string `json:"state"`
|
||||
}
|
||||
|
||||
type Service struct {
|
||||
config *config.Config
|
||||
logger *logger.Logger
|
||||
}
|
||||
|
||||
func NewService(cfg *config.Config, log *logger.Logger) *Service {
|
||||
return &Service{
|
||||
config: cfg,
|
||||
logger: log,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) ListTargets() ([]*Target, error) {
|
||||
s.logger.Debug("Listing iSCSI targets")
|
||||
|
||||
// Read SCST configuration
|
||||
targets := []*Target{}
|
||||
|
||||
// Parse SCST config file
|
||||
if _, err := os.Stat(s.config.SCSTConfig); err == nil {
|
||||
data, err := os.ReadFile(s.config.SCSTConfig)
|
||||
if err == nil {
|
||||
targets = s.parseSCSTConfig(string(data))
|
||||
}
|
||||
}
|
||||
|
||||
return targets, nil
|
||||
}
|
||||
|
||||
func (s *Service) GetTarget(id string) (*Target, error) {
|
||||
targets, err := s.ListTargets()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, target := range targets {
|
||||
if target.ID == id || target.IQN == id {
|
||||
return target, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("target not found: %s", id)
|
||||
}
|
||||
|
||||
func (s *Service) CreateTarget(iqn string, portals, initiators []string) (*Target, error) {
|
||||
s.logger.Info("Creating iSCSI target", "iqn", iqn)
|
||||
|
||||
target := &Target{
|
||||
ID: iqn,
|
||||
IQN: iqn,
|
||||
Portals: portals,
|
||||
Initiators: initiators,
|
||||
LUNs: []LUN{},
|
||||
Status: "pending",
|
||||
}
|
||||
|
||||
// Write to SCST config
|
||||
if err := s.writeSCSTConfig(target); err != nil {
|
||||
return nil, fmt.Errorf("failed to write SCST config: %w", err)
|
||||
}
|
||||
|
||||
return target, nil
|
||||
}
|
||||
|
||||
func (s *Service) UpdateTarget(id string, portals, initiators []string) (*Target, error) {
|
||||
target, err := s.GetTarget(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
target.Portals = portals
|
||||
target.Initiators = initiators
|
||||
|
||||
if err := s.writeSCSTConfig(target); err != nil {
|
||||
return nil, fmt.Errorf("failed to update SCST config: %w", err)
|
||||
}
|
||||
|
||||
return target, nil
|
||||
}
|
||||
|
||||
func (s *Service) DeleteTarget(id string) error {
|
||||
s.logger.Info("Deleting iSCSI target", "id", id)
|
||||
|
||||
// Remove from SCST config
|
||||
// TODO: Implement actual deletion
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) ApplyTarget(id string) error {
|
||||
s.logger.Info("Applying iSCSI target configuration", "id", id)
|
||||
|
||||
// Reload SCST configuration
|
||||
cmd := exec.Command("scstadmin", "-config", s.config.SCSTConfig)
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to apply SCST config", "error", string(output))
|
||||
return fmt.Errorf("failed to apply SCST config: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) ListSessions() ([]*Session, error) {
|
||||
s.logger.Debug("Listing iSCSI sessions")
|
||||
|
||||
sessions := []*Session{}
|
||||
|
||||
// Query SCST for active sessions
|
||||
cmd := exec.Command("scstadmin", "-list_sessions")
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err == nil {
|
||||
sessions = s.parseSCSTSessions(string(output))
|
||||
}
|
||||
|
||||
return sessions, nil
|
||||
}
|
||||
|
||||
func (s *Service) parseSCSTConfig(data string) []*Target {
|
||||
targets := []*Target{}
|
||||
// Simplified parsing - real implementation would parse SCST config format
|
||||
lines := strings.Split(data, "\n")
|
||||
currentTarget := &Target{}
|
||||
|
||||
for _, line := range lines {
|
||||
line = strings.TrimSpace(line)
|
||||
if strings.HasPrefix(line, "TARGET") {
|
||||
if currentTarget.IQN != "" {
|
||||
targets = append(targets, currentTarget)
|
||||
}
|
||||
currentTarget = &Target{
|
||||
IQN: strings.Fields(line)[1],
|
||||
ID: strings.Fields(line)[1],
|
||||
Portals: []string{},
|
||||
Initiators: []string{},
|
||||
LUNs: []LUN{},
|
||||
Status: "active",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if currentTarget.IQN != "" {
|
||||
targets = append(targets, currentTarget)
|
||||
}
|
||||
|
||||
return targets
|
||||
}
|
||||
|
||||
func (s *Service) parseSCSTSessions(data string) []*Session {
|
||||
sessions := []*Session{}
|
||||
// Parse SCST session output
|
||||
lines := strings.Split(data, "\n")
|
||||
|
||||
for _, line := range lines {
|
||||
if strings.Contains(line, "session") {
|
||||
// Parse session information
|
||||
session := &Session{
|
||||
State: "active",
|
||||
}
|
||||
sessions = append(sessions, session)
|
||||
}
|
||||
}
|
||||
|
||||
return sessions
|
||||
}
|
||||
|
||||
func (s *Service) writeSCSTConfig(target *Target) error {
|
||||
// Generate SCST configuration
|
||||
config := fmt.Sprintf(`TARGET %s {
|
||||
enabled 1
|
||||
`, target.IQN)
|
||||
|
||||
for _, portal := range target.Portals {
|
||||
config += fmt.Sprintf(" portal %s {\n", portal)
|
||||
config += " enabled 1\n"
|
||||
config += " }\n"
|
||||
}
|
||||
|
||||
for _, initiator := range target.Initiators {
|
||||
config += fmt.Sprintf(" initiator %s {\n", initiator)
|
||||
config += " enabled 1\n"
|
||||
config += " }\n"
|
||||
}
|
||||
|
||||
config += "}\n"
|
||||
|
||||
// Append to config file (simplified - real implementation would merge properly)
|
||||
return os.WriteFile(s.config.SCSTConfig, []byte(config), 0644)
|
||||
}
|
||||
Reference in New Issue
Block a user