This repository has been archived by the owner on Mar 28, 2019. It is now read-only.
/
iscsi_node_administrator.go
99 lines (82 loc) · 3.08 KB
/
iscsi_node_administrator.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
package disks
import (
"fmt"
boshlog "github.com/cloudfoundry/bosh-utils/logger"
"strings"
"time"
)
type IscsiNodeAdministrator interface {
RunAttachmentCommands(scsiIQN string, scsiServer string,
scsiServerPort int64) (resolvedDevicePath string, err error)
}
const addCmd = "sudo iscsiadm -m node -o new -T %s -p %s:%d"
const loginCmd = "sudo iscsiadm -m node -T %s -p %s:%d -l"
const persistCmd = "sudo iscsiadm -m node -o update -T %s -n node.startup -v automatic"
const devicePath = "lsscsi -t | grep disk | grep %s | awk '{print $4}'"
type scsiCommand struct {
cmd string
maxAttempts int
delayBetweenAttempts time.Duration
resultHandler SSHCmdResultHandler
}
type remoteIscsiNodeAdministrator struct {
logger boshlog.Logger
cmdRunner SSHCmdRunner
resolvedDevicePath string
}
type IscsciNodeAdministratorFactory func(remoteUser string, remoteIP string, localIdentityFilePath string,
logger boshlog.Logger) IscsiNodeAdministrator
func NewRemoteIscsiNodeAdministrator(remoteUser string, remoteIP string,
localIdentityFilePath string, logger boshlog.Logger) IscsiNodeAdministrator {
return &remoteIscsiNodeAdministrator{
cmdRunner: NewSSHCmdRunner(remoteUser, remoteIP, localIdentityFilePath, logger),
logger: logger,
}
}
func (adm *remoteIscsiNodeAdministrator) RunAttachmentCommands(scsiIQN string, scsiServer string,
scsiServerPort int64) (string, error) {
if err := adm.cmdRunner.Connect(60, 1*time.Second); err != nil {
return "", err
}
adm.resetResolvedPath()
cmds := []scsiCommand{
{fmt.Sprintf(addCmd, scsiIQN, scsiServer, scsiServerPort), 4, 0 * time.Second, adm.defaultHandler},
{fmt.Sprintf(loginCmd, scsiIQN, scsiServer, scsiServerPort), 5, 2 * time.Second, adm.defaultHandler},
{fmt.Sprintf(persistCmd, scsiIQN), 1, 0 * time.Second, adm.defaultHandler},
{fmt.Sprintf(devicePath, scsiIQN), 1, 0 * time.Second, adm.devicePathReader},
}
for _, c := range cmds {
if err := adm.runCommand(c); err != nil {
adm.logger.Error(diskOperationsLogTag, "Failed to run command %s", c.cmd)
return "", err
}
}
return adm.LastResolvedPath(), nil
}
func (adm *remoteIscsiNodeAdministrator) runCommand(c scsiCommand) error {
return adm.cmdRunner.RunCommand(c.cmd, c.resultHandler, c.maxAttempts, c.delayBetweenAttempts)
}
func (adm *remoteIscsiNodeAdministrator) defaultHandler(stdout string,
stderr string) (retry bool, reasonToRetry string) {
return false, ""
}
func (adm *remoteIscsiNodeAdministrator) devicePathReader(stdout string,
stderr string) (retry bool, reasonToRetry string) {
if stdout == "" {
return true, "Device path unresolved"
}
if !strings.HasPrefix(stdout, "/dev/") {
return false, fmt.Sprintf("Unexpected output %s", stdout)
}
adm.setResolvedPath(strings.TrimSpace(strings.TrimSuffix(stdout, "\n")))
return false, ""
}
func (adm *remoteIscsiNodeAdministrator) resetResolvedPath() {
adm.resolvedDevicePath = ""
}
func (adm *remoteIscsiNodeAdministrator) LastResolvedPath() string {
return adm.resolvedDevicePath
}
func (adm *remoteIscsiNodeAdministrator) setResolvedPath(path string) {
adm.resolvedDevicePath = path
}