From e73507f4613c6b05cefd44a009c5eabc32b96b7b Mon Sep 17 00:00:00 2001 From: Utkarsh Mani Tripathi Date: Thu, 28 Nov 2019 13:16:09 +0530 Subject: [PATCH 1/4] add target to install dependency Signed-off-by: Utkarsh Mani Tripathi --- .travis.yml | 5 ++++- Makefile | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 433234e..c9e2596 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,9 +26,11 @@ before_script: - ceph status - sudo apt-get install -y libcunit1 libcunit1-doc libcunit1-dev - sudo apt-get install -y open-iscsi + - go get -u github.com/golang/dep/cmd/dep script: - cd ${TRAVIS_BUILD_DIR} + - make deps # Try a build without cgo first - make build-nocgo - make clean @@ -39,7 +41,7 @@ script: - dd if=/dev/zero of=/var/tmp/disk.img bs=1024 count=102400 - mkdir ${HOME}/.gotgt - echo ${TGT_CFG} > ${HOME}/.gotgt/config.json - - ./_output/cmd/bin/gotgt daemon --log debug 1>/dev/null 2>&1 & + - ./_output/cmd/bin/gotgt daemon --log debug 1>log.txt 2>&1 & # libiscsi test - mkdir ${HOME}/libiscsi - git clone https://github.com/gostor/libiscsi ${HOME}/libiscsi @@ -98,4 +100,5 @@ script: - sudo mkdir -p /var/tmp/test - sudo mount /dev/sdb1 /var/tmp/test - sudo ls -lh /var/tmp/test/ + - cat log.txt diff --git a/Makefile b/Makefile index 00f0995..0be7f94 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,9 @@ BIN_DIR=_output/cmd/bin all: init build +deps: + dep ensure + build: init go build -o ${BIN_DIR}/gotgt gotgt.go From f14ea31cbb07dd2f3a5e95af2ec0ed268a67e66b Mon Sep 17 00:00:00 2001 From: Utkarsh Mani Tripathi Date: Thu, 28 Nov 2019 13:36:49 +0530 Subject: [PATCH 2/4] add unit test to test behaviour on start stop Signed-off-by: Utkarsh Mani Tripathi --- .travis.yml | 4 +- mock/remote.go | 204 ++++++++++++++++++++++++++++++++++++++++++++ mock/remote_test.go | 53 ++++++++++++ 3 files changed, 259 insertions(+), 2 deletions(-) create mode 100644 mock/remote.go create mode 100644 mock/remote_test.go diff --git a/.travis.yml b/.travis.yml index c9e2596..189c821 100644 --- a/.travis.yml +++ b/.travis.yml @@ -38,10 +38,11 @@ script: - make - hack/verify-gofmt.sh - go test -v ./pkg/... + - go test -v ./mock/... - dd if=/dev/zero of=/var/tmp/disk.img bs=1024 count=102400 - mkdir ${HOME}/.gotgt - echo ${TGT_CFG} > ${HOME}/.gotgt/config.json - - ./_output/cmd/bin/gotgt daemon --log debug 1>log.txt 2>&1 & + - ./_output/cmd/bin/gotgt daemon --log debug 1>/dev/null 2>&1 & # libiscsi test - mkdir ${HOME}/libiscsi - git clone https://github.com/gostor/libiscsi ${HOME}/libiscsi @@ -100,5 +101,4 @@ script: - sudo mkdir -p /var/tmp/test - sudo mount /dev/sdb1 /var/tmp/test - sudo ls -lh /var/tmp/test/ - - cat log.txt diff --git a/mock/remote.go b/mock/remote.go new file mode 100644 index 0000000..95fc898 --- /dev/null +++ b/mock/remote.go @@ -0,0 +1,204 @@ +package mock + +import ( + "encoding/binary" + "fmt" + "net" + "os" + "time" + + uuid "github.com/satori/go.uuid" + "github.com/sirupsen/logrus" + + "github.com/gostor/gotgt/pkg/api" + "github.com/gostor/gotgt/pkg/config" /* init lib */ + "github.com/gostor/gotgt/pkg/port/iscsit" + "github.com/gostor/gotgt/pkg/scsi" + _ "github.com/gostor/gotgt/pkg/scsi/backingstore" /* init lib */ + "github.com/gostor/gotgt/pkg/scsi/backingstore/remote" +) + +type remoteBs struct { + Volume string + Size int64 + SectorSize int + + isUp bool + rw api.RemoteBackingStore + + tgtName string + lhbsName string + clusterIP string + cfg *config.Config + targetDriver scsi.SCSITargetDriver + stats scsi.Stats +} + +func (r *remoteBs) ReadAt(data []byte, size int64) (int, error) { + return 0, nil +} + +func (r *remoteBs) WriteAt(data []byte, size int64) (int, error) { + return 0, nil +} + +func (r *remoteBs) Sync() (int, error) { + return 0, nil +} + +func (r *remoteBs) Unmap(bs int64, size int64) (int, error) { + return 0, nil +} + +func initializeSCSITarget(size int64) { + iscsit.EnableStats = true + scsi.SCSIVendorID = "OPENEBS" + scsi.SCSIProductID = "JIVA" + scsi.SCSIID = "iqn.2016-09.com.jiva.openebs:iscsi-tgt" + scsi.EnableORWrite16 = false + scsi.EnablePersistentReservation = false + scsi.EnableMultipath = false + remote.Size = uint64(size) +} + +// Startup starts iscsi target server +func (r *remoteBs) Startup(name string, frontendIP string, clusterIP string, size, sectorSize int64) error { + initializeSCSITarget(size) + + if frontendIP == "" { + host, _ := os.Hostname() + addrs, _ := net.LookupIP(host) + for _, addr := range addrs { + if ipv4 := addr.To4(); ipv4 != nil { + frontendIP = ipv4.String() + if frontendIP == "127.0.0.1" { + continue + } + break + } + } + } + + r.tgtName = "iqn.2016-09.com.openebs.jiva:" + name + r.lhbsName = "RemBs:" + name + r.cfg = &config.Config{ + Storages: []config.BackendStorage{ + { + DeviceID: 1000, + Path: r.lhbsName, + Online: true, + }, + }, + ISCSIPortals: []config.ISCSIPortalInfo{ + { + ID: 0, + Portal: frontendIP + ":3260", + }, + }, + ISCSITargets: map[string]config.ISCSITarget{ + r.tgtName: { + TPGTs: map[string][]uint64{ + "1": {0}, + }, + LUNs: map[string]uint64{ + "1": uint64(1000), + }, + }, + }, + } + + r.Volume = name + r.Size = size + r.SectorSize = int(sectorSize) + r.rw = r + r.clusterIP = clusterIP + logrus.Info("Start SCSI target") + if err := r.startScsiTarget(r.cfg); err != nil { + return err + } + + r.isUp = true + + return nil +} + +// Shutdown stop scsi target +func (r *remoteBs) Shutdown() error { + if r.Volume != "" { + r.Volume = "" + } + + if err := r.stopScsiTarget(); err != nil { + return fmt.Errorf("Failed to stop scsi target, err: %v", err) + } + r.isUp = false + + return nil +} + +// State provides info whether scsi target is up or down +func (r *remoteBs) State() string { + if r.isUp { + return "Up" + } + return "Down" +} + +// Stats get target stats from the scsi target +func (r *remoteBs) Stats() scsi.Stats { + if !r.isUp { + return scsi.Stats{} + } + return r.targetDriver.Stats() +} + +// Resize is called to resize the volume +func (r *remoteBs) Resize(size uint64) error { + if !r.isUp { + return fmt.Errorf("Volume is not up") + } + return r.targetDriver.Resize(size) +} + +func (r *remoteBs) startScsiTarget(cfg *config.Config) error { + var err error + id := uuid.NewV4() + uid := binary.BigEndian.Uint64(id[:8]) + err = scsi.InitSCSILUMapEx(&config.BackendStorage{ + DeviceID: uid, + Path: "RemBs:" + r.tgtName, + Online: true, + BlockShift: 9, + ThinProvisioning: true, + }, + r.tgtName, uint64(0), r.rw) + if err != nil { + return err + } + scsiTarget := scsi.NewSCSITargetService() + r.targetDriver, err = scsi.NewTargetDriver("iscsi", scsiTarget) + if err != nil { + logrus.Errorf("iscsi target driver error") + return err + } + r.targetDriver.NewTarget(r.tgtName, cfg) + //r.targetDriver.SetClusterIP(r.clusterIP) + go r.targetDriver.Run() + // Wait here so that listener get started + time.Sleep(1 * time.Second) + + logrus.Infof("SCSI device created") + return nil +} + +func (r *remoteBs) stopScsiTarget() error { + if r.targetDriver == nil { + return nil + } + logrus.Infof("Stopping target %v ...", r.tgtName) + if err := r.targetDriver.Close(); err != nil { + return err + } + logrus.Infof("Target %v stopped", r.tgtName) + return nil +} diff --git a/mock/remote_test.go b/mock/remote_test.go new file mode 100644 index 0000000..6499dae --- /dev/null +++ b/mock/remote_test.go @@ -0,0 +1,53 @@ +package mock + +import ( + "log" + "testing" +) + +func TestStartStop(t *testing.T) { + cases := map[string]struct { + count int + shutdownAgain bool + expectErr bool + }{ + "TargetStartStop": { + count: 3, + expectErr: false, + }, + "TargetStop": { + count: 1, + expectErr: true, + shutdownAgain: true, + }, + } + + for name, tt := range cases { + t.Run(name, func(t *testing.T) { + for i := 0; i < tt.count; i++ { + bs := &remoteBs{} + err := bs.Startup("store1", "", "127.0.0.1", 2147483648, 512) + if err != nil { + log.Fatal("Failed to initialize tgt, err: ", err) + } + + expectErr := false + err = bs.Shutdown() + if err != nil { + expectErr = true + } + + if tt.shutdownAgain { + err = bs.Shutdown() + if err != nil { + expectErr = true + } + } + + if tt.expectErr != expectErr { + t.Fatalf("Startup test failed, err: %v", err) + } + } + }) + } +} From 901974d8c457777d8de6a8ee95f4da5f1100f7f8 Mon Sep 17 00:00:00 2001 From: Utkarsh Mani Tripathi Date: Thu, 28 Nov 2019 13:55:36 +0530 Subject: [PATCH 3/4] remove conn.close Signed-off-by: Utkarsh Mani Tripathi --- pkg/port/iscsit/iscsid.go | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/port/iscsit/iscsid.go b/pkg/port/iscsit/iscsid.go index 24c0619..b8cbfd8 100644 --- a/pkg/port/iscsit/iscsid.go +++ b/pkg/port/iscsit/iscsid.go @@ -203,7 +203,6 @@ func (s *ISCSITargetDriver) Run() error { if err, ok := err.(net.Error); ok { if !err.Temporary() { log.Warning("Closing connection with initiator...") - conn.Close() break } } From 77d9428ea397c82f32702527504e05fd005860b6 Mon Sep 17 00:00:00 2001 From: Utkarsh Mani Tripathi Date: Thu, 28 Nov 2019 14:14:29 +0530 Subject: [PATCH 4/4] address review comments Signed-off-by: Utkarsh Mani Tripathi --- mock/remote.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/mock/remote.go b/mock/remote.go index 95fc898..2483fae 100644 --- a/mock/remote.go +++ b/mock/remote.go @@ -52,9 +52,6 @@ func (r *remoteBs) Unmap(bs int64, size int64) (int, error) { func initializeSCSITarget(size int64) { iscsit.EnableStats = true - scsi.SCSIVendorID = "OPENEBS" - scsi.SCSIProductID = "JIVA" - scsi.SCSIID = "iqn.2016-09.com.jiva.openebs:iscsi-tgt" scsi.EnableORWrite16 = false scsi.EnablePersistentReservation = false scsi.EnableMultipath = false @@ -79,7 +76,7 @@ func (r *remoteBs) Startup(name string, frontendIP string, clusterIP string, siz } } - r.tgtName = "iqn.2016-09.com.openebs.jiva:" + name + r.tgtName = "iqn.2016-09.com.gotgt.gostor:" + name r.lhbsName = "RemBs:" + name r.cfg = &config.Config{ Storages: []config.BackendStorage{