crush_test.go 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  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. "github.com/pkg/errors"
  18. "github.com/rook/rook/pkg/clusterd"
  19. exectest "github.com/rook/rook/pkg/util/exec/test"
  20. "github.com/stretchr/testify/assert"
  21. )
  22. const testCrushMap = `{
  23. "devices": [
  24. {
  25. "id": 0,
  26. "name": "osd.0",
  27. "class": "hdd"
  28. }
  29. ],
  30. "types": [
  31. {
  32. "type_id": 0,
  33. "name": "osd"
  34. },
  35. {
  36. "type_id": 1,
  37. "name": "host"
  38. },
  39. {
  40. "type_id": 2,
  41. "name": "chassis"
  42. },
  43. {
  44. "type_id": 3,
  45. "name": "rack"
  46. },
  47. {
  48. "type_id": 4,
  49. "name": "row"
  50. },
  51. {
  52. "type_id": 5,
  53. "name": "pdu"
  54. },
  55. {
  56. "type_id": 6,
  57. "name": "pod"
  58. },
  59. {
  60. "type_id": 7,
  61. "name": "room"
  62. },
  63. {
  64. "type_id": 8,
  65. "name": "datacenter"
  66. },
  67. {
  68. "type_id": 9,
  69. "name": "region"
  70. },
  71. {
  72. "type_id": 10,
  73. "name": "root"
  74. }
  75. ],
  76. "buckets": [
  77. {
  78. "id": -1,
  79. "name": "default",
  80. "type_id": 10,
  81. "type_name": "root",
  82. "weight": 1028,
  83. "alg": "straw",
  84. "hash": "rjenkins1",
  85. "items": [
  86. {
  87. "id": -3,
  88. "weight": 1028,
  89. "pos": 0
  90. }
  91. ]
  92. },
  93. {
  94. "id": -2,
  95. "name": "default~hdd",
  96. "type_id": 10,
  97. "type_name": "root",
  98. "weight": 1028,
  99. "alg": "straw",
  100. "hash": "rjenkins1",
  101. "items": [
  102. {
  103. "id": -4,
  104. "weight": 1028,
  105. "pos": 0
  106. }
  107. ]
  108. },
  109. {
  110. "id": -3,
  111. "name": "minikube",
  112. "type_id": 1,
  113. "type_name": "host",
  114. "weight": 1028,
  115. "alg": "straw",
  116. "hash": "rjenkins1",
  117. "items": [
  118. {
  119. "id": 0,
  120. "weight": 1028,
  121. "pos": 0
  122. }
  123. ]
  124. },
  125. {
  126. "id": -4,
  127. "name": "minikube~hdd",
  128. "type_id": 1,
  129. "type_name": "host",
  130. "weight": 1028,
  131. "alg": "straw",
  132. "hash": "rjenkins1",
  133. "items": [
  134. {
  135. "id": 0,
  136. "weight": 1028,
  137. "pos": 0
  138. }
  139. ]
  140. }
  141. ],
  142. "rules": [
  143. {
  144. "rule_id": 0,
  145. "rule_name": "replicated_ruleset",
  146. "ruleset": 0,
  147. "type": 1,
  148. "min_size": 1,
  149. "max_size": 10,
  150. "steps": [
  151. {
  152. "op": "take",
  153. "item": -1,
  154. "item_name": "default"
  155. },
  156. {
  157. "op": "chooseleaf_firstn",
  158. "num": 0,
  159. "type": "host"
  160. },
  161. {
  162. "op": "emit"
  163. }
  164. ]
  165. },
  166. {
  167. "rule_id": 1,
  168. "rule_name": "hybrid_ruleset",
  169. "ruleset": 1,
  170. "type": 1,
  171. "min_size": 1,
  172. "max_size": 10,
  173. "steps": [
  174. {
  175. "op": "take",
  176. "item": -2,
  177. "item_name": "default~hdd"
  178. },
  179. {
  180. "op": "chooseleaf_firstn",
  181. "num": 1,
  182. "type": "host"
  183. },
  184. {
  185. "op": "emit"
  186. },
  187. {
  188. "op": "take",
  189. "item": -2,
  190. "item_name": "default~ssd"
  191. },
  192. {
  193. "op": "chooseleaf_firstn",
  194. "num": 0,
  195. "type": "host"
  196. },
  197. {
  198. "op": "emit"
  199. }
  200. ]
  201. },
  202. {
  203. "rule_id": 1,
  204. "rule_name": "my-store.rgw.buckets.data",
  205. "ruleset": 1,
  206. "type": 3,
  207. "min_size": 3,
  208. "max_size": 3,
  209. "steps": [
  210. {
  211. "op": "set_chooseleaf_tries",
  212. "num": 5
  213. },
  214. {
  215. "op": "set_choose_tries",
  216. "num": 100
  217. },
  218. {
  219. "op": "take",
  220. "item": -1,
  221. "item_name": "default"
  222. },
  223. {
  224. "op": "chooseleaf_indep",
  225. "num": 0,
  226. "type": "host"
  227. },
  228. {
  229. "op": "emit"
  230. }
  231. ]
  232. }
  233. ],
  234. "tunables": {
  235. "choose_local_tries": 0,
  236. "choose_local_fallback_tries": 0,
  237. "choose_total_tries": 50,
  238. "chooseleaf_descend_once": 1,
  239. "chooseleaf_vary_r": 1,
  240. "chooseleaf_stable": 0,
  241. "straw_calc_version": 1,
  242. "allowed_bucket_algs": 22,
  243. "profile": "firefly",
  244. "optimal_tunables": 0,
  245. "legacy_tunables": 0,
  246. "minimum_required_version": "firefly",
  247. "require_feature_tunables": 1,
  248. "require_feature_tunables2": 1,
  249. "has_v2_rules": 1,
  250. "require_feature_tunables3": 1,
  251. "has_v3_rules": 0,
  252. "has_v4_buckets": 0,
  253. "require_feature_tunables5": 0,
  254. "has_v5_rules": 0
  255. },
  256. "choose_args": {}
  257. }
  258. `
  259. func TestGetCrushMap(t *testing.T) {
  260. executor := &exectest.MockExecutor{}
  261. executor.MockExecuteCommandWithOutput = func(command string, args ...string) (string, error) {
  262. logger.Infof("Command: %s %v", command, args)
  263. if args[1] == "crush" && args[2] == "dump" {
  264. return testCrushMap, nil
  265. }
  266. return "", errors.Errorf("unexpected ceph command '%v'", args)
  267. }
  268. crush, err := GetCrushMap(&clusterd.Context{Executor: executor}, AdminTestClusterInfo("mycluster"))
  269. assert.Nil(t, err)
  270. assert.Equal(t, 11, len(crush.Types))
  271. assert.Equal(t, 1, len(crush.Devices))
  272. assert.Equal(t, 4, len(crush.Buckets))
  273. assert.Equal(t, 3, len(crush.Rules))
  274. }
  275. func TestGetOSDOnHost(t *testing.T) {
  276. executor := &exectest.MockExecutor{}
  277. executor.MockExecuteCommandWithOutput = func(command string, args ...string) (string, error) {
  278. logger.Infof("Command: %s %v", command, args)
  279. if args[1] == "crush" && args[2] == "ls" {
  280. return "[\"osd.2\",\"osd.0\",\"osd.1\"]", nil
  281. }
  282. return "", errors.Errorf("unexpected ceph command '%v'", args)
  283. }
  284. _, err := GetOSDOnHost(&clusterd.Context{Executor: executor}, AdminTestClusterInfo("mycluster"), "my-host")
  285. assert.Nil(t, err)
  286. }
  287. func TestCrushName(t *testing.T) {
  288. // each is slightly different than the last
  289. crushNames := []string{
  290. "www.zxyz.com",
  291. "www.abcd.com",
  292. "ip-10-0-132-84.us-east-2.compute.internal",
  293. "ip-10-0-132-85.us-east-2.compute.internal",
  294. "worker1",
  295. "worker2",
  296. "master1",
  297. "master2",
  298. "us-east-2b",
  299. "us-east-2c",
  300. "us-east-1",
  301. "us-east-2",
  302. "ip-10-0-175-140",
  303. "ip-10-0-175-141",
  304. }
  305. for i, crushName := range crushNames {
  306. normalizedCrushName := NormalizeCrushName(crushName)
  307. fmt.Printf("crushName: %s, normalizedCrushName: %s\n", crushName, normalizedCrushName)
  308. assert.True(t, IsNormalizedCrushNameEqual(crushName, normalizedCrushName))
  309. assert.True(t, IsNormalizedCrushNameEqual(crushName, crushName))
  310. assert.True(t, IsNormalizedCrushNameEqual(normalizedCrushName, normalizedCrushName))
  311. if i > 0 {
  312. // slightly different crush name
  313. differentCrushName := crushNames[i-1]
  314. differentNormalizedCrushName := NormalizeCrushName(differentCrushName)
  315. assert.False(t, IsNormalizedCrushNameEqual(crushName, differentNormalizedCrushName))
  316. assert.False(t, IsNormalizedCrushNameEqual(crushName, differentCrushName))
  317. assert.False(t, IsNormalizedCrushNameEqual(normalizedCrushName, differentNormalizedCrushName))
  318. }
  319. }
  320. }
  321. func TestBuildCompiledDecompileCRUSHFileName(t *testing.T) {
  322. assert.Equal(t, "/tmp/06399022.decompiled", buildDecompileCRUSHFileName("/tmp/06399022"))
  323. assert.Equal(t, "/tmp/06399022.compiled", buildCompileCRUSHFileName("/tmp/06399022"))
  324. }