From f14ea31cbb07dd2f3a5e95af2ec0ed268a67e66b Mon Sep 17 00:00:00 2001 From: Utkarsh Mani Tripathi Date: Thu, 28 Nov 2019 13:36:49 +0530 Subject: [PATCH] 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) + } + } + }) + } +}