Files
synology-csi/pkg/driver/initiator.go
2021-08-31 10:18:35 +08:00

163 lines
3.3 KiB
Go

// Copyright 2021 Synology Inc.
package driver
import (
"errors"
"fmt"
"strings"
log "github.com/sirupsen/logrus"
utilexec "k8s.io/utils/exec"
)
type initiatorDriver struct {
chapUser string
chapPassword string
}
const (
ISCSIPort = 3260
)
func iscsiadm(cmdArgs ...string) utilexec.Cmd {
executor := utilexec.New()
return executor.Command("iscsiadm", cmdArgs...)
}
func iscsiadm_session() string {
cmd := iscsiadm("-m", "session")
out, err := cmd.CombinedOutput()
if err != nil {
exitErr, ok := err.(utilexec.ExitError)
if ok && exitErr.ExitStatus() == 21 { // iscsiadm: No active sessions
log.Info("No active iscsi session found.")
} else {
log.Errorf("Failed to run iscsiadm session: %v", err)
}
return ""
}
return string(out)
}
func iscsiadm_discovery(ip string) error {
cmd := iscsiadm(
"-m", "discoverydb",
"--type", "sendtargets",
"--portal", ip,
"--discover")
out, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("%s (%v)", string(out), err)
}
return nil
}
func iscsiadm_login(iqn, portal string) error {
cmd := iscsiadm(
"-m", "node",
"--targetname", iqn,
"--portal", portal,
"--login")
out, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("%s (%v)", string(out), err)
}
return nil
}
func iscsiadm_logout(iqn string) error {
cmd := iscsiadm(
"-m", "node",
"--targetname", iqn,
"--logout")
if _, err := cmd.CombinedOutput(); err != nil {
return err
}
return nil
}
func iscsiadm_rescan(iqn string) error {
cmd := iscsiadm(
"-m", "node",
"--targetname", iqn,
"-R")
if _, err := cmd.CombinedOutput(); err != nil {
return err
}
return nil
}
func hasSession(targetIqn string) bool{
sessions := iscsiadm_session();
for _, line := range strings.Split(sessions, "\n") {
if strings.Contains(line, targetIqn) {
return true
}
}
return false
}
func (d *initiatorDriver) login(targetIqn string, ip string) error{
portal := fmt.Sprintf("%s:%d", ip, ISCSIPort)
if (hasSession(targetIqn)) {
log.Infof("Session[%s] already exists.", targetIqn)
return nil
}
if err := iscsiadm_discovery(ip); err != nil {
log.Errorf("Failed in discovery of the target: %v", err)
return err
}
if err := iscsiadm_login(targetIqn, portal); err != nil {
log.Errorf("Failed in login of the target: %v", err)
return err
}
log.Infof("Login target portal [%s], iqn [%s].", portal, targetIqn)
return nil
}
func (d *initiatorDriver) logout(targetIqn string, ip string) error{
if (!hasSession(targetIqn)) {
log.Infof("Session[%s] doesn't exist.", targetIqn)
return nil
}
portal := fmt.Sprintf("%s:%d", ip, ISCSIPort)
if err := iscsiadm_logout(targetIqn); err != nil {
log.Errorf("Failed in logout of the target.\nTarget [%s], Portal [%s], Err[%v]",
targetIqn, portal, err)
return err
}
log.Infof("Logout target portal [%s], iqn [%s].", portal, targetIqn)
return nil
}
func (d *initiatorDriver) rescan(targetIqn string) error{
if (!hasSession(targetIqn)) {
msg := fmt.Sprintf("Session[%s] doesn't exist.", targetIqn)
log.Error(msg)
return errors.New(msg)
}
if err := iscsiadm_rescan(targetIqn); err != nil {
log.Errorf("Failed in rescan of the target.\nTarget [%s], Err[%v]",
targetIqn, err)
return err
}
log.Infof("Rescan target iqn [%s].", targetIqn)
return nil
}