sio_mgr_test.go 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. /*
  2. Copyright 2017 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package scaleio
  14. import (
  15. "errors"
  16. "testing"
  17. "time"
  18. "k8s.io/kubernetes/pkg/util/mount"
  19. siotypes "github.com/codedellemc/goscaleio/types/v1"
  20. )
  21. var (
  22. fakeSdcID = "test-sdc-123456789"
  23. fakeVolumeName = "test-vol-0001"
  24. fakeVolumeID = "1234567890"
  25. fakeDev = "/dev/testABC"
  26. fakeConfig = map[string]string{
  27. confKey.gateway: "http://sio.gateway:1234",
  28. confKey.sslEnabled: "false",
  29. confKey.system: "scaleio",
  30. confKey.volumeName: "sio-0001",
  31. confKey.secretName: "sio-secret",
  32. confKey.username: "c2lvdXNlcgo=", // siouser
  33. confKey.password: "c2lvcGFzc3dvcmQK", // siopassword
  34. }
  35. )
  36. func newTestMgr(t *testing.T) *sioMgr {
  37. mgr, err := newSioMgr(fakeConfig, mount.NewFakeExec(nil))
  38. if err != nil {
  39. t.Error(err)
  40. }
  41. mgr.client = newFakeSio()
  42. return mgr
  43. }
  44. func TestMgrNew(t *testing.T) {
  45. mgr, err := newSioMgr(fakeConfig, mount.NewFakeExec(nil))
  46. if err != nil {
  47. t.Fatal(err)
  48. }
  49. if mgr.configData == nil {
  50. t.Fatal("configuration data not set")
  51. }
  52. if mgr.configData[confKey.volumeName] != "sio-0001" {
  53. t.Errorf("expecting %s, got %s", "sio-0001", mgr.configData[confKey.volumeName])
  54. }
  55. // check defaults
  56. if mgr.configData[confKey.protectionDomain] != "default" {
  57. t.Errorf("unexpected value for confData[protectionDomain] %s", mgr.configData[confKey.protectionDomain])
  58. }
  59. if mgr.configData[confKey.storagePool] != "default" {
  60. t.Errorf("unexpected value for confData[storagePool] %s", mgr.configData[confKey.storagePool])
  61. }
  62. if mgr.configData[confKey.storageMode] != "ThinProvisioned" {
  63. t.Errorf("unexpected value for confData[storageMode] %s", mgr.configData[confKey.storageMode])
  64. }
  65. }
  66. func TestMgrGetClient(t *testing.T) {
  67. mgr := newTestMgr(t)
  68. _, err := mgr.getClient()
  69. if err != nil {
  70. t.Fatal(err)
  71. }
  72. if mgr.client == nil {
  73. t.Fatal("mgr.client not set")
  74. }
  75. }
  76. func TestMgrCreateVolume(t *testing.T) {
  77. mgr := newTestMgr(t)
  78. vol, err := mgr.CreateVolume("test-vol-0001", 8*1024*1024)
  79. if err != nil {
  80. t.Fatal(err)
  81. }
  82. if vol.Name != "test-vol-0001" {
  83. t.Errorf("unexpected vol.Name %s", vol.Name)
  84. }
  85. }
  86. func TestMgrAttachVolume(t *testing.T) {
  87. mgr := newTestMgr(t)
  88. mgr.CreateVolume("test-vol-0001", 8*1024*1024)
  89. device, err := mgr.AttachVolume("test-vol-0001", false)
  90. if err != nil {
  91. t.Fatal(err)
  92. }
  93. if device != "/dev/testABC" {
  94. t.Errorf("unexpected value for mapped device %s", device)
  95. }
  96. }
  97. func TestMgrAttachVolume_AlreadyAttached(t *testing.T) {
  98. mgr := newTestMgr(t)
  99. mgr.CreateVolume("test-vol-0001", 8*1024*1024)
  100. mgr.AttachVolume("test-vol-0001", false)
  101. dev, err := mgr.AttachVolume("test-vol-0001", false)
  102. if err != nil {
  103. t.Fatalf("unexpected error: %v", err)
  104. }
  105. if dev != "/dev/testABC" {
  106. t.Errorf("unexpected value for mapped device %s", dev)
  107. }
  108. }
  109. func TestMgrAttachVolume_VolumeNotFoundError(t *testing.T) {
  110. mgr := newTestMgr(t)
  111. mgr.CreateVolume("test-vol-0001", 8*1024*1024)
  112. _, err := mgr.AttachVolume("test-vol-0002", false)
  113. if err == nil {
  114. t.Error("attachVolume should fail with volume not found error")
  115. }
  116. }
  117. func TestMgrAttachVolume_WaitForAttachError(t *testing.T) {
  118. mgr := newTestMgr(t)
  119. mgr.CreateVolume("test-vol-0001", 8*1024*1024)
  120. go func() {
  121. c := mgr.client.(*fakeSio)
  122. close(c.waitAttachCtrl)
  123. }()
  124. _, err := mgr.AttachVolume("test-vol-0001", false)
  125. if err == nil {
  126. t.Error("attachVolume should fail with attach timeout error")
  127. }
  128. }
  129. func TestMgrDetachVolume(t *testing.T) {
  130. mgr := newTestMgr(t)
  131. mgr.CreateVolume("test-vol-0001", 8*1024*1024)
  132. mgr.AttachVolume("test-vol-0001", false)
  133. if err := mgr.DetachVolume("test-vol-0001"); err != nil {
  134. t.Fatal(err)
  135. }
  136. fakeSio := mgr.client.(*fakeSio)
  137. if len(fakeSio.volume.MappedSdcInfo) != 0 {
  138. t.Errorf("expecting attached sdc to 0, got %d", len(fakeSio.volume.MappedSdcInfo))
  139. }
  140. if len(fakeSio.devs) != 0 {
  141. t.Errorf("expecting local devs to be 0, got %d", len(fakeSio.devs))
  142. }
  143. }
  144. func TestMgrDetachVolume_VolumeNotFound(t *testing.T) {
  145. mgr := newTestMgr(t)
  146. mgr.CreateVolume("test-vol-0001", 8*1024*1024)
  147. mgr.AttachVolume("test-vol-0001", false)
  148. err := mgr.DetachVolume("test-vol-0002")
  149. if err == nil {
  150. t.Fatal("expected a volume not found failure")
  151. }
  152. }
  153. func TestMgrDetachVolume_VolumeNotAttached(t *testing.T) {
  154. mgr := newTestMgr(t)
  155. mgr.CreateVolume("test-vol-0001", 8*1024*1024)
  156. err := mgr.DetachVolume("test-vol-0001")
  157. if err != nil {
  158. t.Fatal(err)
  159. }
  160. }
  161. func TestMgrDetachVolume_VolumeAlreadyDetached(t *testing.T) {
  162. mgr := newTestMgr(t)
  163. mgr.CreateVolume("test-vol-0001", 8*1024*1024)
  164. mgr.AttachVolume("test-vol-0001", false)
  165. mgr.DetachVolume("test-vol-0001")
  166. err := mgr.DetachVolume("test-vol-0001")
  167. if err != nil {
  168. t.Fatal("failed detaching a volume already detached")
  169. }
  170. }
  171. func TestMgrDetachVolume_WaitForDetachError(t *testing.T) {
  172. mgr := newTestMgr(t)
  173. mgr.CreateVolume("test-vol-0001", 8*1024*1024)
  174. mgr.AttachVolume("test-vol-0001", false)
  175. err := mgr.DetachVolume("test-vol-0001")
  176. if err != nil {
  177. t.Error("detachVolume failed")
  178. }
  179. }
  180. func TestMgrDeleteVolume(t *testing.T) {
  181. mgr := newTestMgr(t)
  182. mgr.CreateVolume("test-vol-0001", 8*1024*1024)
  183. err := mgr.DeleteVolume("test-vol-0001")
  184. if err != nil {
  185. t.Fatal(err)
  186. }
  187. sio := mgr.client.(*fakeSio)
  188. if sio.volume != nil {
  189. t.Errorf("volume not nil after delete operation")
  190. }
  191. }
  192. func TestMgrDeleteVolume_VolumeNotFound(t *testing.T) {
  193. mgr := newTestMgr(t)
  194. mgr.CreateVolume("test-vol-0001", 8*1024*1024)
  195. err := mgr.DeleteVolume("test-vol-0002")
  196. if err == nil {
  197. t.Fatal("expected volume not found error")
  198. }
  199. }
  200. // ************************************************************
  201. // Helper Test Types
  202. // ************************************************************
  203. type fakeSio struct {
  204. volume *siotypes.Volume
  205. waitAttachCtrl chan struct{}
  206. waitDetachCtrl chan struct{}
  207. devs map[string]string
  208. isMultiMap bool
  209. }
  210. func newFakeSio() *fakeSio {
  211. return &fakeSio{
  212. waitAttachCtrl: make(chan struct{}),
  213. waitDetachCtrl: make(chan struct{}),
  214. }
  215. }
  216. func (f *fakeSio) FindVolume(volumeName string) (*siotypes.Volume, error) {
  217. if f.volume == nil || f.volume.Name != volumeName {
  218. return nil, errors.New("volume not found")
  219. }
  220. return f.volume, nil
  221. }
  222. func (f *fakeSio) Volume(id sioVolumeID) (*siotypes.Volume, error) {
  223. if f.volume == nil || f.volume.ID != string(id) {
  224. return nil, errors.New("volume not found")
  225. }
  226. return f.volume, nil
  227. }
  228. func (f *fakeSio) CreateVolume(volName string, sizeGB int64) (*siotypes.Volume, error) {
  229. f.volume = &siotypes.Volume{
  230. ID: fakeVolumeID,
  231. Name: volName,
  232. SizeInKb: int(sizeGB),
  233. VolumeType: "test",
  234. }
  235. return f.volume, nil
  236. }
  237. func (f *fakeSio) AttachVolume(id sioVolumeID, multiMaps bool) error {
  238. f.isMultiMap = multiMaps
  239. _, err := f.Volume(id)
  240. if err != nil {
  241. return err
  242. }
  243. f.volume.MappedSdcInfo = []*siotypes.MappedSdcInfo{
  244. {SdcID: fakeSdcID},
  245. }
  246. return nil
  247. }
  248. func (f *fakeSio) DetachVolume(id sioVolumeID) error {
  249. if _, err := f.Volume(id); err != nil {
  250. return err
  251. }
  252. f.volume.MappedSdcInfo = nil
  253. delete(f.devs, f.volume.ID)
  254. return nil
  255. }
  256. func (f *fakeSio) DeleteVolume(id sioVolumeID) error {
  257. if _, err := f.Volume(id); err != nil {
  258. return err
  259. }
  260. f.volume = nil
  261. return nil
  262. }
  263. func (f *fakeSio) IID() (string, error) {
  264. return fakeSdcID, nil
  265. }
  266. func (f *fakeSio) Devs() (map[string]string, error) {
  267. if f.volume == nil {
  268. return nil, errors.New("volume not found")
  269. }
  270. f.devs = map[string]string{
  271. f.volume.ID: fakeDev,
  272. }
  273. return f.devs, nil
  274. }
  275. func (f *fakeSio) GetVolumeRefs(volID sioVolumeID) (int, error) {
  276. if f.volume == nil {
  277. return 0, nil
  278. }
  279. return 1, nil
  280. }
  281. func (f *fakeSio) WaitForAttachedDevice(token string) (string, error) {
  282. select {
  283. case <-time.After(500 * time.Millisecond):
  284. return fakeDev, nil
  285. case <-f.waitAttachCtrl:
  286. return "", errors.New("attached device timeout")
  287. }
  288. }
  289. func (f *fakeSio) WaitForDetachedDevice(token string) error {
  290. select {
  291. case <-time.After(500 * time.Millisecond):
  292. delete(f.devs, f.volume.ID)
  293. return nil
  294. case <-f.waitDetachCtrl:
  295. return errors.New("detach device timeout")
  296. }
  297. }