image_test.go 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. /*
  2. Copyright 2016 The Rook Authors. All rights reserved.
  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 client
  14. import (
  15. "fmt"
  16. "testing"
  17. "time"
  18. "strings"
  19. "github.com/pkg/errors"
  20. "github.com/rook/rook/pkg/clusterd"
  21. exectest "github.com/rook/rook/pkg/util/exec/test"
  22. "github.com/stretchr/testify/assert"
  23. )
  24. const (
  25. sizeMB = 1048576 // 1 MB
  26. )
  27. func TestCreateImage(t *testing.T) {
  28. executor := &exectest.MockExecutor{}
  29. context := &clusterd.Context{Executor: executor}
  30. // mock an error during the create image call. rbd tool returns error information to the output stream,
  31. // separate from the error object, so verify that information also makes it back to us (because it is useful).
  32. executor.MockExecuteCommandWithOutput = func(command string, args ...string) (string, error) {
  33. switch {
  34. case command == "rbd" && args[0] == "create":
  35. return "mocked detailed ceph error output stream", errors.New("some mocked error")
  36. }
  37. return "", errors.Errorf("unexpected ceph command %q", args)
  38. }
  39. clusterInfo := AdminTestClusterInfo("mycluster")
  40. _, err := CreateImage(context, clusterInfo, "image1", "pool1", "", uint64(sizeMB)) // 1MB
  41. assert.NotNil(t, err)
  42. assert.True(t, strings.Contains(err.Error(), "mocked detailed ceph error output stream"))
  43. // rbd tool interprets sizes as MB, so anything smaller than that should get rounded up to the minimum
  44. // (except for 0, that's OK)
  45. createCalled := false
  46. expectedSizeArg := ""
  47. executor.MockExecuteCommandWithOutput = func(command string, args ...string) (string, error) {
  48. switch {
  49. case command == "rbd" && args[0] == "create":
  50. createCalled = true
  51. assert.Equal(t, expectedSizeArg, args[3])
  52. return "", nil
  53. case command == "rbd" && args[0] == "info":
  54. assert.Equal(t, "pool1/image1", args[1])
  55. return `{"name":"image1","size":1048576,"objects":1,"order":20,"object_size":1048576,"block_name_prefix":"pool1_data.229226b8b4567",` +
  56. `"format":2,"features":["layering"],"op_features":[],"flags":[],"create_timestamp":"Fri Oct 5 19:46:20 2018"}`, nil
  57. }
  58. return "", errors.Errorf("unexpected ceph command %q", args)
  59. }
  60. // 0 byte --> 0 MB
  61. expectedSizeArg = "0"
  62. image, err := CreateImage(context, clusterInfo, "image1", "pool1", "", uint64(0))
  63. assert.Nil(t, err)
  64. assert.NotNil(t, image)
  65. assert.True(t, createCalled)
  66. createCalled = false
  67. // 1 byte --> 1 MB
  68. expectedSizeArg = "1"
  69. image, err = CreateImage(context, clusterInfo, "image1", "pool1", "", uint64(1))
  70. assert.Nil(t, err)
  71. assert.NotNil(t, image)
  72. assert.True(t, createCalled)
  73. createCalled = false
  74. // (1 MB - 1 byte) --> 1 MB
  75. expectedSizeArg = "1"
  76. image, err = CreateImage(context, clusterInfo, "image1", "pool1", "", uint64(sizeMB-1))
  77. assert.Nil(t, err)
  78. assert.NotNil(t, image)
  79. assert.True(t, createCalled)
  80. createCalled = false
  81. // 1 MB
  82. expectedSizeArg = "1"
  83. image, err = CreateImage(context, clusterInfo, "image1", "pool1", "", uint64(sizeMB))
  84. assert.Nil(t, err)
  85. assert.NotNil(t, image)
  86. assert.True(t, createCalled)
  87. assert.Equal(t, "image1", image.Name)
  88. assert.Equal(t, uint64(sizeMB), image.Size)
  89. createCalled = false
  90. // (1 MB + 1 byte) --> 2 MB
  91. expectedSizeArg = "2"
  92. image, err = CreateImage(context, clusterInfo, "image1", "pool1", "", uint64(sizeMB+1))
  93. assert.Nil(t, err)
  94. assert.NotNil(t, image)
  95. assert.True(t, createCalled)
  96. createCalled = false
  97. // (2 MB - 1 byte) --> 2 MB
  98. expectedSizeArg = "2"
  99. image, err = CreateImage(context, clusterInfo, "image1", "pool1", "", uint64(sizeMB*2-1))
  100. assert.Nil(t, err)
  101. assert.NotNil(t, image)
  102. assert.True(t, createCalled)
  103. createCalled = false
  104. // 2 MB
  105. expectedSizeArg = "2"
  106. image, err = CreateImage(context, clusterInfo, "image1", "pool1", "", uint64(sizeMB*2))
  107. assert.Nil(t, err)
  108. assert.NotNil(t, image)
  109. assert.True(t, createCalled)
  110. createCalled = false
  111. // (2 MB + 1 byte) --> 3MB
  112. expectedSizeArg = "3"
  113. image, err = CreateImage(context, clusterInfo, "image1", "pool1", "", uint64(sizeMB*2+1))
  114. assert.Nil(t, err)
  115. assert.NotNil(t, image)
  116. assert.True(t, createCalled)
  117. createCalled = false
  118. // Pool with data pool
  119. expectedSizeArg = "1"
  120. image, err = CreateImage(context, clusterInfo, "image1", "pool1", "datapool1", uint64(sizeMB))
  121. assert.Nil(t, err)
  122. assert.NotNil(t, image)
  123. assert.True(t, createCalled)
  124. createCalled = false
  125. }
  126. func TestExpandImage(t *testing.T) {
  127. executor := &exectest.MockExecutor{}
  128. context := &clusterd.Context{Executor: executor}
  129. executor.MockExecuteCommandWithTimeout = func(timeout time.Duration, command string, args ...string) (string, error) {
  130. switch {
  131. case args[1] != "kube/some-image":
  132. return "", errors.Errorf("no image %s", args[1])
  133. case command == "rbd" && args[0] == "resize":
  134. return "everything is okay", nil
  135. }
  136. return "", errors.Errorf("unexpected ceph command %q", args)
  137. }
  138. clusterInfo := AdminTestClusterInfo("mycluster")
  139. err := ExpandImage(context, clusterInfo, "error-name", "kube", "mon1,mon2,mon3", "/tmp/keyring", 1000000)
  140. assert.Error(t, err)
  141. err = ExpandImage(context, clusterInfo, "some-image", "kube", "mon1,mon2,mon3", "/tmp/keyring", 1000000)
  142. assert.NoError(t, err)
  143. }
  144. func TestListImageLogLevelInfo(t *testing.T) {
  145. executor := &exectest.MockExecutor{}
  146. context := &clusterd.Context{Executor: executor}
  147. var images []CephBlockImage
  148. var err error
  149. listCalled := false
  150. emptyListResult := false
  151. executor.MockExecuteCommandWithOutput = func(command string, args ...string) (string, error) {
  152. switch {
  153. case command == "rbd" && args[0] == "ls" && args[1] == "-l":
  154. listCalled = true
  155. if emptyListResult {
  156. return `[]`, nil
  157. } else {
  158. return `[{"image":"image1","size":1048576,"format":2},{"image":"image2","size":2048576,"format":2},{"image":"image3","size":3048576,"format":2}]`, nil
  159. }
  160. }
  161. return "", errors.Errorf("unexpected ceph command %q", args)
  162. }
  163. clusterInfo := AdminTestClusterInfo("mycluster")
  164. images, err = ListImages(context, clusterInfo, "pool1")
  165. assert.Nil(t, err)
  166. assert.NotNil(t, images)
  167. assert.True(t, len(images) == 3)
  168. assert.True(t, listCalled)
  169. listCalled = false
  170. emptyListResult = true
  171. images, err = ListImages(context, clusterInfo, "pool1")
  172. assert.Nil(t, err)
  173. assert.NotNil(t, images)
  174. assert.True(t, len(images) == 0)
  175. assert.True(t, listCalled)
  176. listCalled = false
  177. }
  178. func TestListImageLogLevelDebug(t *testing.T) {
  179. executor := &exectest.MockExecutor{}
  180. context := &clusterd.Context{Executor: executor}
  181. var images []CephBlockImage
  182. var err error
  183. libradosDebugOut := `2017-08-24 19:42:10.693348 7fd64513e0c0 1 librados: starting msgr at -
  184. 2017-08-24 19:42:10.693372 7fd64513e0c0 1 librados: starting objecter
  185. 2017-08-24 19:42:10.784686 7fd64513e0c0 1 librados: setting wanted keys
  186. 2017-08-24 19:42:10.784688 7fd64513e0c0 1 librados: calling monclient init
  187. 2017-08-24 19:42:10.789337 7fd64513e0c0 1 librados: init done
  188. 2017-08-24 19:42:10.789354 7fd64513e0c0 10 librados: wait_for_osdmap waiting
  189. 2017-08-24 19:42:10.790039 7fd64513e0c0 10 librados: wait_for_osdmap done waiting
  190. 2017-08-24 19:42:10.790079 7fd64513e0c0 10 librados: read oid=rbd_directory nspace=
  191. 2017-08-24 19:42:10.792235 7fd64513e0c0 10 librados: Objecter returned from read r=0
  192. 2017-08-24 19:42:10.792307 7fd64513e0c0 10 librados: call oid=rbd_directory nspace=
  193. 2017-08-24 19:42:10.793495 7fd64513e0c0 10 librados: Objecter returned from call r=0
  194. 2017-08-24 19:42:11.684960 7fd621ffb700 10 librados: set snap write context: seq = 0 and snaps = []
  195. 2017-08-24 19:42:11.884609 7fd621ffb700 10 librados: set snap write context: seq = 0 and snaps = []
  196. 2017-08-24 19:42:11.884628 7fd621ffb700 10 librados: set snap write context: seq = 0 and snaps = []
  197. 2017-08-24 19:42:11.985068 7fd621ffb700 10 librados: set snap write context: seq = 0 and snaps = []
  198. 2017-08-24 19:42:11.985084 7fd621ffb700 10 librados: set snap write context: seq = 0 and snaps = []
  199. 2017-08-24 19:42:11.986275 7fd621ffb700 10 librados: set snap write context: seq = 0 and snaps = []
  200. 2017-08-24 19:42:11.986339 7fd621ffb700 10 librados: set snap write context: seq = 0 and snaps = []
  201. 2017-08-24 19:42:11.986498 7fd621ffb700 10 librados: set snap write context: seq = 0 and snaps = []
  202. 2017-08-24 19:42:11.987363 7fd621ffb700 10 librados: set snap write context: seq = 0 and snaps = []
  203. 2017-08-24 19:42:11.988165 7fd621ffb700 10 librados: set snap write context: seq = 0 and snaps = []
  204. 2017-08-24 19:42:12.385448 7fd621ffb700 10 librados: set snap write context: seq = 0 and snaps = []
  205. 2017-08-24 19:42:12.386804 7fd621ffb700 10 librados: set snap write context: seq = 0 and snaps = []
  206. 2017-08-24 19:42:12.386877 7fd621ffb700 10 librados: set snap write context: seq = 0 and snaps = []
  207. `
  208. listCalled := false
  209. emptyListResult := false
  210. executor.MockExecuteCommandWithOutput = func(command string, args ...string) (string, error) {
  211. switch {
  212. case command == "rbd" && args[0] == "ls" && args[1] == "-l":
  213. listCalled = true
  214. if emptyListResult {
  215. return fmt.Sprintf(`%s[]`, libradosDebugOut), nil
  216. } else {
  217. return fmt.Sprintf(`%s[{"image":"image1","size":1048576,"format":2},{"image":"image2","size":2048576,"format":2},{"image":"image3","size":3048576,"format":2}]`, libradosDebugOut), nil
  218. }
  219. }
  220. return "", errors.Errorf("unexpected ceph command %q", args)
  221. }
  222. clusterInfo := AdminTestClusterInfo("mycluster")
  223. images, err = ListImages(context, clusterInfo, "pool1")
  224. assert.Nil(t, err)
  225. assert.NotNil(t, images)
  226. assert.True(t, len(images) == 3)
  227. assert.True(t, listCalled)
  228. listCalled = false
  229. emptyListResult = true
  230. images, err = ListImages(context, clusterInfo, "pool1")
  231. assert.Nil(t, err)
  232. assert.NotNil(t, images)
  233. assert.True(t, len(images) == 0)
  234. assert.True(t, listCalled)
  235. listCalled = false
  236. }