persistent_volumes_test.go 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182
  1. /*
  2. Copyright 2014 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 volume
  14. import (
  15. "context"
  16. "fmt"
  17. "math/rand"
  18. "net/http/httptest"
  19. "os"
  20. "strconv"
  21. "testing"
  22. "time"
  23. "k8s.io/api/core/v1"
  24. storage "k8s.io/api/storage/v1"
  25. "k8s.io/apimachinery/pkg/api/resource"
  26. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  27. "k8s.io/apimachinery/pkg/watch"
  28. "k8s.io/client-go/informers"
  29. clientset "k8s.io/client-go/kubernetes"
  30. restclient "k8s.io/client-go/rest"
  31. ref "k8s.io/client-go/tools/reference"
  32. fakecloud "k8s.io/cloud-provider/fake"
  33. "k8s.io/kubernetes/pkg/api/legacyscheme"
  34. persistentvolumecontroller "k8s.io/kubernetes/pkg/controller/volume/persistentvolume"
  35. "k8s.io/kubernetes/pkg/volume"
  36. volumetest "k8s.io/kubernetes/pkg/volume/testing"
  37. "k8s.io/kubernetes/test/integration/framework"
  38. "k8s.io/apimachinery/pkg/runtime/schema"
  39. "k8s.io/klog"
  40. )
  41. // Several tests in this file are configurable by environment variables:
  42. // KUBE_INTEGRATION_PV_OBJECTS - nr. of PVs/PVCs to be created
  43. // (100 by default)
  44. // KUBE_INTEGRATION_PV_SYNC_PERIOD - volume controller sync period
  45. // (1s by default)
  46. // KUBE_INTEGRATION_PV_END_SLEEP - for how long should
  47. // TestPersistentVolumeMultiPVsPVCs sleep when it's finished (0s by
  48. // default). This is useful to test how long does it take for periodic sync
  49. // to process bound PVs/PVCs.
  50. //
  51. const defaultObjectCount = 100
  52. const defaultSyncPeriod = 1 * time.Second
  53. const provisionerPluginName = "kubernetes.io/mock-provisioner"
  54. func getObjectCount() int {
  55. objectCount := defaultObjectCount
  56. if s := os.Getenv("KUBE_INTEGRATION_PV_OBJECTS"); s != "" {
  57. var err error
  58. objectCount, err = strconv.Atoi(s)
  59. if err != nil {
  60. klog.Fatalf("cannot parse value of KUBE_INTEGRATION_PV_OBJECTS: %v", err)
  61. }
  62. }
  63. klog.V(2).Infof("using KUBE_INTEGRATION_PV_OBJECTS=%d", objectCount)
  64. return objectCount
  65. }
  66. func getSyncPeriod(syncPeriod time.Duration) time.Duration {
  67. period := syncPeriod
  68. if s := os.Getenv("KUBE_INTEGRATION_PV_SYNC_PERIOD"); s != "" {
  69. var err error
  70. period, err = time.ParseDuration(s)
  71. if err != nil {
  72. klog.Fatalf("cannot parse value of KUBE_INTEGRATION_PV_SYNC_PERIOD: %v", err)
  73. }
  74. }
  75. klog.V(2).Infof("using KUBE_INTEGRATION_PV_SYNC_PERIOD=%v", period)
  76. return period
  77. }
  78. func testSleep() {
  79. var period time.Duration
  80. if s := os.Getenv("KUBE_INTEGRATION_PV_END_SLEEP"); s != "" {
  81. var err error
  82. period, err = time.ParseDuration(s)
  83. if err != nil {
  84. klog.Fatalf("cannot parse value of KUBE_INTEGRATION_PV_END_SLEEP: %v", err)
  85. }
  86. }
  87. klog.V(2).Infof("using KUBE_INTEGRATION_PV_END_SLEEP=%v", period)
  88. if period != 0 {
  89. time.Sleep(period)
  90. klog.V(2).Infof("sleep finished")
  91. }
  92. }
  93. func TestPersistentVolumeRecycler(t *testing.T) {
  94. klog.V(2).Infof("TestPersistentVolumeRecycler started")
  95. _, s, closeFn := framework.RunAMaster(nil)
  96. defer closeFn()
  97. ns := framework.CreateTestingNamespace("pv-recycler", s, t)
  98. defer framework.DeleteTestingNamespace(ns, s, t)
  99. testClient, ctrl, informers, watchPV, watchPVC := createClients(ns, t, s, defaultSyncPeriod)
  100. defer watchPV.Stop()
  101. defer watchPVC.Stop()
  102. // NOTE: This test cannot run in parallel, because it is creating and deleting
  103. // non-namespaced objects (PersistenceVolumes).
  104. defer testClient.CoreV1().PersistentVolumes().DeleteCollection(context.TODO(), nil, metav1.ListOptions{})
  105. stopCh := make(chan struct{})
  106. informers.Start(stopCh)
  107. go ctrl.Run(stopCh)
  108. defer close(stopCh)
  109. // This PV will be claimed, released, and recycled.
  110. pv := createPV("fake-pv-recycler", "/tmp/foo", "10G", []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}, v1.PersistentVolumeReclaimRecycle)
  111. pvc := createPVC("fake-pvc-recycler", ns.Name, "5G", []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}, "")
  112. _, err := testClient.CoreV1().PersistentVolumes().Create(context.TODO(), pv, metav1.CreateOptions{})
  113. if err != nil {
  114. t.Errorf("Failed to create PersistentVolume: %v", err)
  115. }
  116. klog.V(2).Infof("TestPersistentVolumeRecycler pvc created")
  117. _, err = testClient.CoreV1().PersistentVolumeClaims(ns.Name).Create(context.TODO(), pvc, metav1.CreateOptions{})
  118. if err != nil {
  119. t.Errorf("Failed to create PersistentVolumeClaim: %v", err)
  120. }
  121. klog.V(2).Infof("TestPersistentVolumeRecycler pvc created")
  122. // wait until the controller pairs the volume and claim
  123. waitForPersistentVolumePhase(testClient, pv.Name, watchPV, v1.VolumeBound)
  124. klog.V(2).Infof("TestPersistentVolumeRecycler pv bound")
  125. waitForPersistentVolumeClaimPhase(testClient, pvc.Name, ns.Name, watchPVC, v1.ClaimBound)
  126. klog.V(2).Infof("TestPersistentVolumeRecycler pvc bound")
  127. // deleting a claim releases the volume, after which it can be recycled
  128. if err := testClient.CoreV1().PersistentVolumeClaims(ns.Name).Delete(context.TODO(), pvc.Name, nil); err != nil {
  129. t.Errorf("error deleting claim %s", pvc.Name)
  130. }
  131. klog.V(2).Infof("TestPersistentVolumeRecycler pvc deleted")
  132. waitForPersistentVolumePhase(testClient, pv.Name, watchPV, v1.VolumeReleased)
  133. klog.V(2).Infof("TestPersistentVolumeRecycler pv released")
  134. waitForPersistentVolumePhase(testClient, pv.Name, watchPV, v1.VolumeAvailable)
  135. klog.V(2).Infof("TestPersistentVolumeRecycler pv available")
  136. }
  137. func TestPersistentVolumeDeleter(t *testing.T) {
  138. klog.V(2).Infof("TestPersistentVolumeDeleter started")
  139. _, s, closeFn := framework.RunAMaster(nil)
  140. defer closeFn()
  141. ns := framework.CreateTestingNamespace("pv-deleter", s, t)
  142. defer framework.DeleteTestingNamespace(ns, s, t)
  143. testClient, ctrl, informers, watchPV, watchPVC := createClients(ns, t, s, defaultSyncPeriod)
  144. defer watchPV.Stop()
  145. defer watchPVC.Stop()
  146. // NOTE: This test cannot run in parallel, because it is creating and deleting
  147. // non-namespaced objects (PersistenceVolumes).
  148. defer testClient.CoreV1().PersistentVolumes().DeleteCollection(context.TODO(), nil, metav1.ListOptions{})
  149. stopCh := make(chan struct{})
  150. informers.Start(stopCh)
  151. go ctrl.Run(stopCh)
  152. defer close(stopCh)
  153. // This PV will be claimed, released, and deleted.
  154. pv := createPV("fake-pv-deleter", "/tmp/foo", "10G", []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}, v1.PersistentVolumeReclaimDelete)
  155. pvc := createPVC("fake-pvc-deleter", ns.Name, "5G", []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}, "")
  156. _, err := testClient.CoreV1().PersistentVolumes().Create(context.TODO(), pv, metav1.CreateOptions{})
  157. if err != nil {
  158. t.Errorf("Failed to create PersistentVolume: %v", err)
  159. }
  160. klog.V(2).Infof("TestPersistentVolumeDeleter pv created")
  161. _, err = testClient.CoreV1().PersistentVolumeClaims(ns.Name).Create(context.TODO(), pvc, metav1.CreateOptions{})
  162. if err != nil {
  163. t.Errorf("Failed to create PersistentVolumeClaim: %v", err)
  164. }
  165. klog.V(2).Infof("TestPersistentVolumeDeleter pvc created")
  166. waitForPersistentVolumePhase(testClient, pv.Name, watchPV, v1.VolumeBound)
  167. klog.V(2).Infof("TestPersistentVolumeDeleter pv bound")
  168. waitForPersistentVolumeClaimPhase(testClient, pvc.Name, ns.Name, watchPVC, v1.ClaimBound)
  169. klog.V(2).Infof("TestPersistentVolumeDeleter pvc bound")
  170. // deleting a claim releases the volume, after which it can be recycled
  171. if err := testClient.CoreV1().PersistentVolumeClaims(ns.Name).Delete(context.TODO(), pvc.Name, nil); err != nil {
  172. t.Errorf("error deleting claim %s", pvc.Name)
  173. }
  174. klog.V(2).Infof("TestPersistentVolumeDeleter pvc deleted")
  175. waitForPersistentVolumePhase(testClient, pv.Name, watchPV, v1.VolumeReleased)
  176. klog.V(2).Infof("TestPersistentVolumeDeleter pv released")
  177. for {
  178. event := <-watchPV.ResultChan()
  179. if event.Type == watch.Deleted {
  180. break
  181. }
  182. }
  183. klog.V(2).Infof("TestPersistentVolumeDeleter pv deleted")
  184. }
  185. func TestPersistentVolumeBindRace(t *testing.T) {
  186. // Test a race binding many claims to a PV that is pre-bound to a specific
  187. // PVC. Only this specific PVC should get bound.
  188. klog.V(2).Infof("TestPersistentVolumeBindRace started")
  189. _, s, closeFn := framework.RunAMaster(nil)
  190. defer closeFn()
  191. ns := framework.CreateTestingNamespace("pv-bind-race", s, t)
  192. defer framework.DeleteTestingNamespace(ns, s, t)
  193. testClient, ctrl, informers, watchPV, watchPVC := createClients(ns, t, s, defaultSyncPeriod)
  194. defer watchPV.Stop()
  195. defer watchPVC.Stop()
  196. // NOTE: This test cannot run in parallel, because it is creating and deleting
  197. // non-namespaced objects (PersistenceVolumes).
  198. defer testClient.CoreV1().PersistentVolumes().DeleteCollection(context.TODO(), nil, metav1.ListOptions{})
  199. stopCh := make(chan struct{})
  200. informers.Start(stopCh)
  201. go ctrl.Run(stopCh)
  202. defer close(stopCh)
  203. pv := createPV("fake-pv-race", "/tmp/foo", "10G", []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}, v1.PersistentVolumeReclaimRetain)
  204. pvc := createPVC("fake-pvc-race", ns.Name, "5G", []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}, "")
  205. counter := 0
  206. maxClaims := 100
  207. claims := []*v1.PersistentVolumeClaim{}
  208. for counter <= maxClaims {
  209. counter++
  210. newPvc := pvc.DeepCopy()
  211. newPvc.ObjectMeta = metav1.ObjectMeta{Name: fmt.Sprintf("fake-pvc-race-%d", counter)}
  212. claim, err := testClient.CoreV1().PersistentVolumeClaims(ns.Name).Create(context.TODO(), newPvc, metav1.CreateOptions{})
  213. if err != nil {
  214. t.Fatalf("Error creating newPvc: %v", err)
  215. }
  216. claims = append(claims, claim)
  217. }
  218. klog.V(2).Infof("TestPersistentVolumeBindRace claims created")
  219. // putting a bind manually on a pv should only match the claim it is bound to
  220. claim := claims[rand.Intn(maxClaims-1)]
  221. claimRef, err := ref.GetReference(legacyscheme.Scheme, claim)
  222. if err != nil {
  223. t.Fatalf("Unexpected error getting claimRef: %v", err)
  224. }
  225. pv.Spec.ClaimRef = claimRef
  226. pv.Spec.ClaimRef.UID = ""
  227. pv, err = testClient.CoreV1().PersistentVolumes().Create(context.TODO(), pv, metav1.CreateOptions{})
  228. if err != nil {
  229. t.Fatalf("Unexpected error creating pv: %v", err)
  230. }
  231. klog.V(2).Infof("TestPersistentVolumeBindRace pv created, pre-bound to %s", claim.Name)
  232. waitForPersistentVolumePhase(testClient, pv.Name, watchPV, v1.VolumeBound)
  233. klog.V(2).Infof("TestPersistentVolumeBindRace pv bound")
  234. waitForAnyPersistentVolumeClaimPhase(watchPVC, v1.ClaimBound)
  235. klog.V(2).Infof("TestPersistentVolumeBindRace pvc bound")
  236. pv, err = testClient.CoreV1().PersistentVolumes().Get(context.TODO(), pv.Name, metav1.GetOptions{})
  237. if err != nil {
  238. t.Fatalf("Unexpected error getting pv: %v", err)
  239. }
  240. if pv.Spec.ClaimRef == nil {
  241. t.Fatalf("Unexpected nil claimRef")
  242. }
  243. if pv.Spec.ClaimRef.Namespace != claimRef.Namespace || pv.Spec.ClaimRef.Name != claimRef.Name {
  244. t.Fatalf("Bind mismatch! Expected %s/%s but got %s/%s", claimRef.Namespace, claimRef.Name, pv.Spec.ClaimRef.Namespace, pv.Spec.ClaimRef.Name)
  245. }
  246. }
  247. // TestPersistentVolumeClaimLabelSelector test binding using label selectors
  248. func TestPersistentVolumeClaimLabelSelector(t *testing.T) {
  249. _, s, closeFn := framework.RunAMaster(nil)
  250. defer closeFn()
  251. ns := framework.CreateTestingNamespace("pvc-label-selector", s, t)
  252. defer framework.DeleteTestingNamespace(ns, s, t)
  253. testClient, controller, informers, watchPV, watchPVC := createClients(ns, t, s, defaultSyncPeriod)
  254. defer watchPV.Stop()
  255. defer watchPVC.Stop()
  256. // NOTE: This test cannot run in parallel, because it is creating and deleting
  257. // non-namespaced objects (PersistenceVolumes).
  258. defer testClient.CoreV1().PersistentVolumes().DeleteCollection(context.TODO(), nil, metav1.ListOptions{})
  259. stopCh := make(chan struct{})
  260. informers.Start(stopCh)
  261. go controller.Run(stopCh)
  262. defer close(stopCh)
  263. var (
  264. err error
  265. modes = []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}
  266. reclaim = v1.PersistentVolumeReclaimRetain
  267. pvTrue = createPV("pv-true", "/tmp/foo-label", "1G", modes, reclaim)
  268. pvFalse = createPV("pv-false", "/tmp/foo-label", "1G", modes, reclaim)
  269. pvc = createPVC("pvc-ls-1", ns.Name, "1G", modes, "")
  270. )
  271. pvTrue.ObjectMeta.SetLabels(map[string]string{"foo": "true"})
  272. pvFalse.ObjectMeta.SetLabels(map[string]string{"foo": "false"})
  273. _, err = testClient.CoreV1().PersistentVolumes().Create(context.TODO(), pvTrue, metav1.CreateOptions{})
  274. if err != nil {
  275. t.Fatalf("Failed to create PersistentVolume: %v", err)
  276. }
  277. _, err = testClient.CoreV1().PersistentVolumes().Create(context.TODO(), pvFalse, metav1.CreateOptions{})
  278. if err != nil {
  279. t.Fatalf("Failed to create PersistentVolume: %v", err)
  280. }
  281. t.Log("volumes created")
  282. pvc.Spec.Selector = &metav1.LabelSelector{
  283. MatchLabels: map[string]string{
  284. "foo": "true",
  285. },
  286. }
  287. _, err = testClient.CoreV1().PersistentVolumeClaims(ns.Name).Create(context.TODO(), pvc, metav1.CreateOptions{})
  288. if err != nil {
  289. t.Fatalf("Failed to create PersistentVolumeClaim: %v", err)
  290. }
  291. t.Log("claim created")
  292. waitForAnyPersistentVolumePhase(watchPV, v1.VolumeBound)
  293. t.Log("volume bound")
  294. waitForPersistentVolumeClaimPhase(testClient, pvc.Name, ns.Name, watchPVC, v1.ClaimBound)
  295. t.Log("claim bound")
  296. pv, err := testClient.CoreV1().PersistentVolumes().Get(context.TODO(), "pv-false", metav1.GetOptions{})
  297. if err != nil {
  298. t.Fatalf("Unexpected error getting pv: %v", err)
  299. }
  300. if pv.Spec.ClaimRef != nil {
  301. t.Fatalf("False PV shouldn't be bound")
  302. }
  303. pv, err = testClient.CoreV1().PersistentVolumes().Get(context.TODO(), "pv-true", metav1.GetOptions{})
  304. if err != nil {
  305. t.Fatalf("Unexpected error getting pv: %v", err)
  306. }
  307. if pv.Spec.ClaimRef == nil {
  308. t.Fatalf("True PV should be bound")
  309. }
  310. if pv.Spec.ClaimRef.Namespace != pvc.Namespace || pv.Spec.ClaimRef.Name != pvc.Name {
  311. t.Fatalf("Bind mismatch! Expected %s/%s but got %s/%s", pvc.Namespace, pvc.Name, pv.Spec.ClaimRef.Namespace, pv.Spec.ClaimRef.Name)
  312. }
  313. }
  314. // TestPersistentVolumeClaimLabelSelectorMatchExpressions test binding using
  315. // MatchExpressions label selectors
  316. func TestPersistentVolumeClaimLabelSelectorMatchExpressions(t *testing.T) {
  317. _, s, closeFn := framework.RunAMaster(nil)
  318. defer closeFn()
  319. ns := framework.CreateTestingNamespace("pvc-match-expressions", s, t)
  320. defer framework.DeleteTestingNamespace(ns, s, t)
  321. testClient, controller, informers, watchPV, watchPVC := createClients(ns, t, s, defaultSyncPeriod)
  322. defer watchPV.Stop()
  323. defer watchPVC.Stop()
  324. // NOTE: This test cannot run in parallel, because it is creating and deleting
  325. // non-namespaced objects (PersistenceVolumes).
  326. defer testClient.CoreV1().PersistentVolumes().DeleteCollection(context.TODO(), nil, metav1.ListOptions{})
  327. stopCh := make(chan struct{})
  328. informers.Start(stopCh)
  329. go controller.Run(stopCh)
  330. defer close(stopCh)
  331. var (
  332. err error
  333. modes = []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}
  334. reclaim = v1.PersistentVolumeReclaimRetain
  335. pvTrue = createPV("pv-true", "/tmp/foo-label", "1G", modes, reclaim)
  336. pvFalse = createPV("pv-false", "/tmp/foo-label", "1G", modes, reclaim)
  337. pvc = createPVC("pvc-ls-1", ns.Name, "1G", modes, "")
  338. )
  339. pvTrue.ObjectMeta.SetLabels(map[string]string{"foo": "valA", "bar": ""})
  340. pvFalse.ObjectMeta.SetLabels(map[string]string{"foo": "valB", "baz": ""})
  341. _, err = testClient.CoreV1().PersistentVolumes().Create(context.TODO(), pvTrue, metav1.CreateOptions{})
  342. if err != nil {
  343. t.Fatalf("Failed to create PersistentVolume: %v", err)
  344. }
  345. _, err = testClient.CoreV1().PersistentVolumes().Create(context.TODO(), pvFalse, metav1.CreateOptions{})
  346. if err != nil {
  347. t.Fatalf("Failed to create PersistentVolume: %v", err)
  348. }
  349. t.Log("volumes created")
  350. pvc.Spec.Selector = &metav1.LabelSelector{
  351. MatchExpressions: []metav1.LabelSelectorRequirement{
  352. {
  353. Key: "foo",
  354. Operator: metav1.LabelSelectorOpIn,
  355. Values: []string{"valA"},
  356. },
  357. {
  358. Key: "foo",
  359. Operator: metav1.LabelSelectorOpNotIn,
  360. Values: []string{"valB"},
  361. },
  362. {
  363. Key: "bar",
  364. Operator: metav1.LabelSelectorOpExists,
  365. Values: []string{},
  366. },
  367. {
  368. Key: "baz",
  369. Operator: metav1.LabelSelectorOpDoesNotExist,
  370. Values: []string{},
  371. },
  372. },
  373. }
  374. _, err = testClient.CoreV1().PersistentVolumeClaims(ns.Name).Create(context.TODO(), pvc, metav1.CreateOptions{})
  375. if err != nil {
  376. t.Fatalf("Failed to create PersistentVolumeClaim: %v", err)
  377. }
  378. t.Log("claim created")
  379. waitForAnyPersistentVolumePhase(watchPV, v1.VolumeBound)
  380. t.Log("volume bound")
  381. waitForPersistentVolumeClaimPhase(testClient, pvc.Name, ns.Name, watchPVC, v1.ClaimBound)
  382. t.Log("claim bound")
  383. pv, err := testClient.CoreV1().PersistentVolumes().Get(context.TODO(), "pv-false", metav1.GetOptions{})
  384. if err != nil {
  385. t.Fatalf("Unexpected error getting pv: %v", err)
  386. }
  387. if pv.Spec.ClaimRef != nil {
  388. t.Fatalf("False PV shouldn't be bound")
  389. }
  390. pv, err = testClient.CoreV1().PersistentVolumes().Get(context.TODO(), "pv-true", metav1.GetOptions{})
  391. if err != nil {
  392. t.Fatalf("Unexpected error getting pv: %v", err)
  393. }
  394. if pv.Spec.ClaimRef == nil {
  395. t.Fatalf("True PV should be bound")
  396. }
  397. if pv.Spec.ClaimRef.Namespace != pvc.Namespace || pv.Spec.ClaimRef.Name != pvc.Name {
  398. t.Fatalf("Bind mismatch! Expected %s/%s but got %s/%s", pvc.Namespace, pvc.Name, pv.Spec.ClaimRef.Namespace, pv.Spec.ClaimRef.Name)
  399. }
  400. }
  401. // TestPersistentVolumeMultiPVs tests binding of one PVC to 100 PVs with
  402. // different size.
  403. func TestPersistentVolumeMultiPVs(t *testing.T) {
  404. _, s, closeFn := framework.RunAMaster(nil)
  405. defer closeFn()
  406. ns := framework.CreateTestingNamespace("multi-pvs", s, t)
  407. defer framework.DeleteTestingNamespace(ns, s, t)
  408. testClient, controller, informers, watchPV, watchPVC := createClients(ns, t, s, defaultSyncPeriod)
  409. defer watchPV.Stop()
  410. defer watchPVC.Stop()
  411. // NOTE: This test cannot run in parallel, because it is creating and deleting
  412. // non-namespaced objects (PersistenceVolumes).
  413. defer testClient.CoreV1().PersistentVolumes().DeleteCollection(context.TODO(), nil, metav1.ListOptions{})
  414. stopCh := make(chan struct{})
  415. informers.Start(stopCh)
  416. go controller.Run(stopCh)
  417. defer close(stopCh)
  418. maxPVs := getObjectCount()
  419. pvs := make([]*v1.PersistentVolume, maxPVs)
  420. for i := 0; i < maxPVs; i++ {
  421. // This PV will be claimed, released, and deleted
  422. pvs[i] = createPV("pv-"+strconv.Itoa(i), "/tmp/foo"+strconv.Itoa(i), strconv.Itoa(i+1)+"G",
  423. []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}, v1.PersistentVolumeReclaimRetain)
  424. }
  425. pvc := createPVC("pvc-2", ns.Name, strconv.Itoa(maxPVs/2)+"G", []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}, "")
  426. for i := 0; i < maxPVs; i++ {
  427. _, err := testClient.CoreV1().PersistentVolumes().Create(context.TODO(), pvs[i], metav1.CreateOptions{})
  428. if err != nil {
  429. t.Errorf("Failed to create PersistentVolume %d: %v", i, err)
  430. }
  431. waitForPersistentVolumePhase(testClient, pvs[i].Name, watchPV, v1.VolumeAvailable)
  432. }
  433. t.Log("volumes created")
  434. _, err := testClient.CoreV1().PersistentVolumeClaims(ns.Name).Create(context.TODO(), pvc, metav1.CreateOptions{})
  435. if err != nil {
  436. t.Errorf("Failed to create PersistentVolumeClaim: %v", err)
  437. }
  438. t.Log("claim created")
  439. // wait until the binder pairs the claim with a volume
  440. waitForAnyPersistentVolumePhase(watchPV, v1.VolumeBound)
  441. t.Log("volume bound")
  442. waitForPersistentVolumeClaimPhase(testClient, pvc.Name, ns.Name, watchPVC, v1.ClaimBound)
  443. t.Log("claim bound")
  444. // only one PV is bound
  445. bound := 0
  446. for i := 0; i < maxPVs; i++ {
  447. pv, err := testClient.CoreV1().PersistentVolumes().Get(context.TODO(), pvs[i].Name, metav1.GetOptions{})
  448. if err != nil {
  449. t.Fatalf("Unexpected error getting pv: %v", err)
  450. }
  451. if pv.Spec.ClaimRef == nil {
  452. continue
  453. }
  454. // found a bounded PV
  455. p := pv.Spec.Capacity[v1.ResourceStorage]
  456. pvCap := p.Value()
  457. expectedCap := resource.MustParse(strconv.Itoa(maxPVs/2) + "G")
  458. expectedCapVal := expectedCap.Value()
  459. if pv.Spec.ClaimRef.Name != pvc.Name || pvCap != expectedCapVal {
  460. t.Fatalf("Bind mismatch! Expected %s capacity %d but got %s capacity %d", pvc.Name, expectedCapVal, pv.Spec.ClaimRef.Name, pvCap)
  461. }
  462. t.Logf("claim bounded to %s capacity %v", pv.Name, pv.Spec.Capacity[v1.ResourceStorage])
  463. bound++
  464. }
  465. t.Log("volumes checked")
  466. if bound != 1 {
  467. t.Fatalf("Only 1 PV should be bound but got %d", bound)
  468. }
  469. // deleting a claim releases the volume
  470. if err := testClient.CoreV1().PersistentVolumeClaims(ns.Name).Delete(context.TODO(), pvc.Name, nil); err != nil {
  471. t.Errorf("error deleting claim %s", pvc.Name)
  472. }
  473. t.Log("claim deleted")
  474. waitForAnyPersistentVolumePhase(watchPV, v1.VolumeReleased)
  475. t.Log("volumes released")
  476. }
  477. // TestPersistentVolumeMultiPVsPVCs tests binding of 100 PVC to 100 PVs.
  478. // This test is configurable by KUBE_INTEGRATION_PV_* variables.
  479. func TestPersistentVolumeMultiPVsPVCs(t *testing.T) {
  480. _, s, closeFn := framework.RunAMaster(nil)
  481. defer closeFn()
  482. ns := framework.CreateTestingNamespace("multi-pvs-pvcs", s, t)
  483. defer framework.DeleteTestingNamespace(ns, s, t)
  484. testClient, binder, informers, watchPV, watchPVC := createClients(ns, t, s, defaultSyncPeriod)
  485. defer watchPV.Stop()
  486. defer watchPVC.Stop()
  487. // NOTE: This test cannot run in parallel, because it is creating and deleting
  488. // non-namespaced objects (PersistenceVolumes).
  489. defer testClient.CoreV1().PersistentVolumes().DeleteCollection(context.TODO(), nil, metav1.ListOptions{})
  490. controllerStopCh := make(chan struct{})
  491. informers.Start(controllerStopCh)
  492. go binder.Run(controllerStopCh)
  493. defer close(controllerStopCh)
  494. objCount := getObjectCount()
  495. pvs := make([]*v1.PersistentVolume, objCount)
  496. pvcs := make([]*v1.PersistentVolumeClaim, objCount)
  497. for i := 0; i < objCount; i++ {
  498. // This PV will be claimed, released, and deleted
  499. pvs[i] = createPV("pv-"+strconv.Itoa(i), "/tmp/foo"+strconv.Itoa(i), "1G",
  500. []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}, v1.PersistentVolumeReclaimRetain)
  501. pvcs[i] = createPVC("pvc-"+strconv.Itoa(i), ns.Name, "1G", []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}, "")
  502. }
  503. // Create PVs first
  504. klog.V(2).Infof("TestPersistentVolumeMultiPVsPVCs: start")
  505. // Create the volumes in a separate goroutine to pop events from
  506. // watchPV early - it seems it has limited capacity and it gets stuck
  507. // with >3000 volumes.
  508. go func() {
  509. for i := 0; i < objCount; i++ {
  510. _, _ = testClient.CoreV1().PersistentVolumes().Create(context.TODO(), pvs[i], metav1.CreateOptions{})
  511. }
  512. }()
  513. // Wait for them to get Available
  514. for i := 0; i < objCount; i++ {
  515. waitForAnyPersistentVolumePhase(watchPV, v1.VolumeAvailable)
  516. klog.V(1).Infof("%d volumes available", i+1)
  517. }
  518. klog.V(2).Infof("TestPersistentVolumeMultiPVsPVCs: volumes are Available")
  519. // Start a separate goroutine that randomly modifies PVs and PVCs while the
  520. // binder is working. We test that the binder can bind volumes despite
  521. // users modifying objects underneath.
  522. stopCh := make(chan struct{}, 0)
  523. go func() {
  524. for {
  525. // Roll a dice and decide a PV or PVC to modify
  526. if rand.Intn(2) == 0 {
  527. // Modify PV
  528. i := rand.Intn(objCount)
  529. name := "pv-" + strconv.Itoa(i)
  530. pv, err := testClient.CoreV1().PersistentVolumes().Get(context.TODO(), name, metav1.GetOptions{})
  531. if err != nil {
  532. // Silently ignore error, the PV may have be already deleted
  533. // or not exists yet.
  534. klog.V(4).Infof("Failed to read PV %s: %v", name, err)
  535. continue
  536. }
  537. if pv.Annotations == nil {
  538. pv.Annotations = map[string]string{"TestAnnotation": fmt.Sprint(rand.Int())}
  539. } else {
  540. pv.Annotations["TestAnnotation"] = fmt.Sprint(rand.Int())
  541. }
  542. _, err = testClient.CoreV1().PersistentVolumes().Update(context.TODO(), pv, metav1.UpdateOptions{})
  543. if err != nil {
  544. // Silently ignore error, the PV may have been updated by
  545. // the controller.
  546. klog.V(4).Infof("Failed to update PV %s: %v", pv.Name, err)
  547. continue
  548. }
  549. klog.V(4).Infof("Updated PV %s", pv.Name)
  550. } else {
  551. // Modify PVC
  552. i := rand.Intn(objCount)
  553. name := "pvc-" + strconv.Itoa(i)
  554. pvc, err := testClient.CoreV1().PersistentVolumeClaims(metav1.NamespaceDefault).Get(context.TODO(), name, metav1.GetOptions{})
  555. if err != nil {
  556. // Silently ignore error, the PVC may have be already
  557. // deleted or not exists yet.
  558. klog.V(4).Infof("Failed to read PVC %s: %v", name, err)
  559. continue
  560. }
  561. if pvc.Annotations == nil {
  562. pvc.Annotations = map[string]string{"TestAnnotation": fmt.Sprint(rand.Int())}
  563. } else {
  564. pvc.Annotations["TestAnnotation"] = fmt.Sprint(rand.Int())
  565. }
  566. _, err = testClient.CoreV1().PersistentVolumeClaims(metav1.NamespaceDefault).Update(context.TODO(), pvc, metav1.UpdateOptions{})
  567. if err != nil {
  568. // Silently ignore error, the PVC may have been updated by
  569. // the controller.
  570. klog.V(4).Infof("Failed to update PVC %s: %v", pvc.Name, err)
  571. continue
  572. }
  573. klog.V(4).Infof("Updated PVC %s", pvc.Name)
  574. }
  575. select {
  576. case <-stopCh:
  577. return
  578. default:
  579. continue
  580. }
  581. }
  582. }()
  583. // Create the claims, again in a separate goroutine.
  584. go func() {
  585. for i := 0; i < objCount; i++ {
  586. _, _ = testClient.CoreV1().PersistentVolumeClaims(ns.Name).Create(context.TODO(), pvcs[i], metav1.CreateOptions{})
  587. }
  588. }()
  589. // wait until the binder pairs all claims
  590. for i := 0; i < objCount; i++ {
  591. waitForAnyPersistentVolumeClaimPhase(watchPVC, v1.ClaimBound)
  592. klog.V(1).Infof("%d claims bound", i+1)
  593. }
  594. // wait until the binder pairs all volumes
  595. for i := 0; i < objCount; i++ {
  596. waitForPersistentVolumePhase(testClient, pvs[i].Name, watchPV, v1.VolumeBound)
  597. klog.V(1).Infof("%d claims bound", i+1)
  598. }
  599. klog.V(2).Infof("TestPersistentVolumeMultiPVsPVCs: claims are bound")
  600. stopCh <- struct{}{}
  601. // check that everything is bound to something
  602. for i := 0; i < objCount; i++ {
  603. pv, err := testClient.CoreV1().PersistentVolumes().Get(context.TODO(), pvs[i].Name, metav1.GetOptions{})
  604. if err != nil {
  605. t.Fatalf("Unexpected error getting pv: %v", err)
  606. }
  607. if pv.Spec.ClaimRef == nil {
  608. t.Fatalf("PV %q is not bound", pv.Name)
  609. }
  610. klog.V(2).Infof("PV %q is bound to PVC %q", pv.Name, pv.Spec.ClaimRef.Name)
  611. pvc, err := testClient.CoreV1().PersistentVolumeClaims(ns.Name).Get(context.TODO(), pvcs[i].Name, metav1.GetOptions{})
  612. if err != nil {
  613. t.Fatalf("Unexpected error getting pvc: %v", err)
  614. }
  615. if pvc.Spec.VolumeName == "" {
  616. t.Fatalf("PVC %q is not bound", pvc.Name)
  617. }
  618. klog.V(2).Infof("PVC %q is bound to PV %q", pvc.Name, pvc.Spec.VolumeName)
  619. }
  620. testSleep()
  621. }
  622. // TestPersistentVolumeControllerStartup tests startup of the controller.
  623. // The controller should not unbind any volumes when it starts.
  624. func TestPersistentVolumeControllerStartup(t *testing.T) {
  625. _, s, closeFn := framework.RunAMaster(nil)
  626. defer closeFn()
  627. ns := framework.CreateTestingNamespace("controller-startup", s, t)
  628. defer framework.DeleteTestingNamespace(ns, s, t)
  629. objCount := getObjectCount()
  630. const shortSyncPeriod = 2 * time.Second
  631. syncPeriod := getSyncPeriod(shortSyncPeriod)
  632. testClient, binder, informers, watchPV, watchPVC := createClients(ns, t, s, shortSyncPeriod)
  633. defer watchPV.Stop()
  634. defer watchPVC.Stop()
  635. // Create *bound* volumes and PVCs
  636. pvs := make([]*v1.PersistentVolume, objCount)
  637. pvcs := make([]*v1.PersistentVolumeClaim, objCount)
  638. for i := 0; i < objCount; i++ {
  639. pvName := "pv-startup-" + strconv.Itoa(i)
  640. pvcName := "pvc-startup-" + strconv.Itoa(i)
  641. pvc := createPVC(pvcName, ns.Name, "1G", []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}, "")
  642. pvc.Annotations = map[string]string{"annBindCompleted": ""}
  643. pvc.Spec.VolumeName = pvName
  644. newPVC, err := testClient.CoreV1().PersistentVolumeClaims(ns.Name).Create(context.TODO(), pvc, metav1.CreateOptions{})
  645. if err != nil {
  646. t.Fatalf("Cannot create claim %q: %v", pvc.Name, err)
  647. }
  648. // Save Bound status as a separate transaction
  649. newPVC.Status.Phase = v1.ClaimBound
  650. newPVC, err = testClient.CoreV1().PersistentVolumeClaims(ns.Name).UpdateStatus(context.TODO(), newPVC, metav1.UpdateOptions{})
  651. if err != nil {
  652. t.Fatalf("Cannot update claim status %q: %v", pvc.Name, err)
  653. }
  654. pvcs[i] = newPVC
  655. // Drain watchPVC with all events generated by the PVC until it's bound
  656. // We don't want to catch "PVC created with Status.Phase == Pending"
  657. // later in this test.
  658. waitForAnyPersistentVolumeClaimPhase(watchPVC, v1.ClaimBound)
  659. pv := createPV(pvName, "/tmp/foo"+strconv.Itoa(i), "1G",
  660. []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}, v1.PersistentVolumeReclaimRetain)
  661. claimRef, err := ref.GetReference(legacyscheme.Scheme, newPVC)
  662. if err != nil {
  663. klog.V(3).Infof("unexpected error getting claim reference: %v", err)
  664. return
  665. }
  666. pv.Spec.ClaimRef = claimRef
  667. newPV, err := testClient.CoreV1().PersistentVolumes().Create(context.TODO(), pv, metav1.CreateOptions{})
  668. if err != nil {
  669. t.Fatalf("Cannot create volume %q: %v", pv.Name, err)
  670. }
  671. // Save Bound status as a separate transaction
  672. newPV.Status.Phase = v1.VolumeBound
  673. newPV, err = testClient.CoreV1().PersistentVolumes().UpdateStatus(context.TODO(), newPV, metav1.UpdateOptions{})
  674. if err != nil {
  675. t.Fatalf("Cannot update volume status %q: %v", pv.Name, err)
  676. }
  677. pvs[i] = newPV
  678. // Drain watchPV with all events generated by the PV until it's bound
  679. // We don't want to catch "PV created with Status.Phase == Pending"
  680. // later in this test.
  681. waitForAnyPersistentVolumePhase(watchPV, v1.VolumeBound)
  682. }
  683. // Start the controller when all PVs and PVCs are already saved in etcd
  684. stopCh := make(chan struct{})
  685. informers.Start(stopCh)
  686. go binder.Run(stopCh)
  687. defer close(stopCh)
  688. // wait for at least two sync periods for changes. No volume should be
  689. // Released and no claim should be Lost during this time.
  690. timer := time.NewTimer(2 * syncPeriod)
  691. defer timer.Stop()
  692. finished := false
  693. for !finished {
  694. select {
  695. case volumeEvent := <-watchPV.ResultChan():
  696. volume, ok := volumeEvent.Object.(*v1.PersistentVolume)
  697. if !ok {
  698. continue
  699. }
  700. if volume.Status.Phase != v1.VolumeBound {
  701. t.Errorf("volume %s unexpectedly changed state to %s", volume.Name, volume.Status.Phase)
  702. }
  703. case claimEvent := <-watchPVC.ResultChan():
  704. claim, ok := claimEvent.Object.(*v1.PersistentVolumeClaim)
  705. if !ok {
  706. continue
  707. }
  708. if claim.Status.Phase != v1.ClaimBound {
  709. t.Errorf("claim %s unexpectedly changed state to %s", claim.Name, claim.Status.Phase)
  710. }
  711. case <-timer.C:
  712. // Wait finished
  713. klog.V(2).Infof("Wait finished")
  714. finished = true
  715. }
  716. }
  717. // check that everything is bound to something
  718. for i := 0; i < objCount; i++ {
  719. pv, err := testClient.CoreV1().PersistentVolumes().Get(context.TODO(), pvs[i].Name, metav1.GetOptions{})
  720. if err != nil {
  721. t.Fatalf("Unexpected error getting pv: %v", err)
  722. }
  723. if pv.Spec.ClaimRef == nil {
  724. t.Fatalf("PV %q is not bound", pv.Name)
  725. }
  726. klog.V(2).Infof("PV %q is bound to PVC %q", pv.Name, pv.Spec.ClaimRef.Name)
  727. pvc, err := testClient.CoreV1().PersistentVolumeClaims(ns.Name).Get(context.TODO(), pvcs[i].Name, metav1.GetOptions{})
  728. if err != nil {
  729. t.Fatalf("Unexpected error getting pvc: %v", err)
  730. }
  731. if pvc.Spec.VolumeName == "" {
  732. t.Fatalf("PVC %q is not bound", pvc.Name)
  733. }
  734. klog.V(2).Infof("PVC %q is bound to PV %q", pvc.Name, pvc.Spec.VolumeName)
  735. }
  736. }
  737. // TestPersistentVolumeProvisionMultiPVCs tests provisioning of many PVCs.
  738. // This test is configurable by KUBE_INTEGRATION_PV_* variables.
  739. func TestPersistentVolumeProvisionMultiPVCs(t *testing.T) {
  740. _, s, closeFn := framework.RunAMaster(nil)
  741. defer closeFn()
  742. ns := framework.CreateTestingNamespace("provision-multi-pvs", s, t)
  743. defer framework.DeleteTestingNamespace(ns, s, t)
  744. testClient, binder, informers, watchPV, watchPVC := createClients(ns, t, s, defaultSyncPeriod)
  745. defer watchPV.Stop()
  746. defer watchPVC.Stop()
  747. // NOTE: This test cannot run in parallel, because it is creating and deleting
  748. // non-namespaced objects (PersistenceVolumes and StorageClasses).
  749. defer testClient.CoreV1().PersistentVolumes().DeleteCollection(context.TODO(), nil, metav1.ListOptions{})
  750. defer testClient.StorageV1().StorageClasses().DeleteCollection(context.TODO(), nil, metav1.ListOptions{})
  751. storageClass := storage.StorageClass{
  752. TypeMeta: metav1.TypeMeta{
  753. Kind: "StorageClass",
  754. },
  755. ObjectMeta: metav1.ObjectMeta{
  756. Name: "gold",
  757. },
  758. Provisioner: provisionerPluginName,
  759. }
  760. testClient.StorageV1().StorageClasses().Create(context.TODO(), &storageClass, metav1.CreateOptions{})
  761. stopCh := make(chan struct{})
  762. informers.Start(stopCh)
  763. go binder.Run(stopCh)
  764. defer close(stopCh)
  765. objCount := getObjectCount()
  766. pvcs := make([]*v1.PersistentVolumeClaim, objCount)
  767. for i := 0; i < objCount; i++ {
  768. pvc := createPVC("pvc-provision-"+strconv.Itoa(i), ns.Name, "1G", []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}, "gold")
  769. pvcs[i] = pvc
  770. }
  771. klog.V(2).Infof("TestPersistentVolumeProvisionMultiPVCs: start")
  772. // Create the claims in a separate goroutine to pop events from watchPVC
  773. // early. It gets stuck with >3000 claims.
  774. go func() {
  775. for i := 0; i < objCount; i++ {
  776. _, _ = testClient.CoreV1().PersistentVolumeClaims(ns.Name).Create(context.TODO(), pvcs[i], metav1.CreateOptions{})
  777. }
  778. }()
  779. // Wait until the controller provisions and binds all of them
  780. for i := 0; i < objCount; i++ {
  781. waitForAnyPersistentVolumeClaimPhase(watchPVC, v1.ClaimBound)
  782. klog.V(1).Infof("%d claims bound", i+1)
  783. }
  784. klog.V(2).Infof("TestPersistentVolumeProvisionMultiPVCs: claims are bound")
  785. // check that we have enough bound PVs
  786. pvList, err := testClient.CoreV1().PersistentVolumes().List(context.TODO(), metav1.ListOptions{})
  787. if err != nil {
  788. t.Fatalf("Failed to list volumes: %s", err)
  789. }
  790. if len(pvList.Items) != objCount {
  791. t.Fatalf("Expected to get %d volumes, got %d", objCount, len(pvList.Items))
  792. }
  793. for i := 0; i < objCount; i++ {
  794. pv := &pvList.Items[i]
  795. if pv.Status.Phase != v1.VolumeBound {
  796. t.Fatalf("Expected volume %s to be bound, is %s instead", pv.Name, pv.Status.Phase)
  797. }
  798. klog.V(2).Infof("PV %q is bound to PVC %q", pv.Name, pv.Spec.ClaimRef.Name)
  799. }
  800. // Delete the claims
  801. for i := 0; i < objCount; i++ {
  802. _ = testClient.CoreV1().PersistentVolumeClaims(ns.Name).Delete(context.TODO(), pvcs[i].Name, nil)
  803. }
  804. // Wait for the PVs to get deleted by listing remaining volumes
  805. // (delete events were unreliable)
  806. for {
  807. volumes, err := testClient.CoreV1().PersistentVolumes().List(context.TODO(), metav1.ListOptions{})
  808. if err != nil {
  809. t.Fatalf("Failed to list volumes: %v", err)
  810. }
  811. klog.V(1).Infof("%d volumes remaining", len(volumes.Items))
  812. if len(volumes.Items) == 0 {
  813. break
  814. }
  815. time.Sleep(time.Second)
  816. }
  817. klog.V(2).Infof("TestPersistentVolumeProvisionMultiPVCs: volumes are deleted")
  818. }
  819. // TestPersistentVolumeMultiPVsDiffAccessModes tests binding of one PVC to two
  820. // PVs with different access modes.
  821. func TestPersistentVolumeMultiPVsDiffAccessModes(t *testing.T) {
  822. _, s, closeFn := framework.RunAMaster(nil)
  823. defer closeFn()
  824. ns := framework.CreateTestingNamespace("multi-pvs-diff-access", s, t)
  825. defer framework.DeleteTestingNamespace(ns, s, t)
  826. testClient, controller, informers, watchPV, watchPVC := createClients(ns, t, s, defaultSyncPeriod)
  827. defer watchPV.Stop()
  828. defer watchPVC.Stop()
  829. // NOTE: This test cannot run in parallel, because it is creating and deleting
  830. // non-namespaced objects (PersistenceVolumes).
  831. defer testClient.CoreV1().PersistentVolumes().DeleteCollection(context.TODO(), nil, metav1.ListOptions{})
  832. stopCh := make(chan struct{})
  833. informers.Start(stopCh)
  834. go controller.Run(stopCh)
  835. defer close(stopCh)
  836. // This PV will be claimed, released, and deleted
  837. pvRwo := createPV("pv-rwo", "/tmp/foo", "10G",
  838. []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}, v1.PersistentVolumeReclaimRetain)
  839. pvRwm := createPV("pv-rwm", "/tmp/bar", "10G",
  840. []v1.PersistentVolumeAccessMode{v1.ReadWriteMany}, v1.PersistentVolumeReclaimRetain)
  841. pvc := createPVC("pvc-rwm", ns.Name, "5G", []v1.PersistentVolumeAccessMode{v1.ReadWriteMany}, "")
  842. _, err := testClient.CoreV1().PersistentVolumes().Create(context.TODO(), pvRwm, metav1.CreateOptions{})
  843. if err != nil {
  844. t.Errorf("Failed to create PersistentVolume: %v", err)
  845. }
  846. _, err = testClient.CoreV1().PersistentVolumes().Create(context.TODO(), pvRwo, metav1.CreateOptions{})
  847. if err != nil {
  848. t.Errorf("Failed to create PersistentVolume: %v", err)
  849. }
  850. t.Log("volumes created")
  851. _, err = testClient.CoreV1().PersistentVolumeClaims(ns.Name).Create(context.TODO(), pvc, metav1.CreateOptions{})
  852. if err != nil {
  853. t.Errorf("Failed to create PersistentVolumeClaim: %v", err)
  854. }
  855. t.Log("claim created")
  856. // wait until the controller pairs the volume and claim
  857. waitForAnyPersistentVolumePhase(watchPV, v1.VolumeBound)
  858. t.Log("volume bound")
  859. waitForPersistentVolumeClaimPhase(testClient, pvc.Name, ns.Name, watchPVC, v1.ClaimBound)
  860. t.Log("claim bound")
  861. // only RWM PV is bound
  862. pv, err := testClient.CoreV1().PersistentVolumes().Get(context.TODO(), "pv-rwo", metav1.GetOptions{})
  863. if err != nil {
  864. t.Fatalf("Unexpected error getting pv: %v", err)
  865. }
  866. if pv.Spec.ClaimRef != nil {
  867. t.Fatalf("ReadWriteOnce PV shouldn't be bound")
  868. }
  869. pv, err = testClient.CoreV1().PersistentVolumes().Get(context.TODO(), "pv-rwm", metav1.GetOptions{})
  870. if err != nil {
  871. t.Fatalf("Unexpected error getting pv: %v", err)
  872. }
  873. if pv.Spec.ClaimRef == nil {
  874. t.Fatalf("ReadWriteMany PV should be bound")
  875. }
  876. if pv.Spec.ClaimRef.Name != pvc.Name {
  877. t.Fatalf("Bind mismatch! Expected %s but got %s", pvc.Name, pv.Spec.ClaimRef.Name)
  878. }
  879. // deleting a claim releases the volume
  880. if err := testClient.CoreV1().PersistentVolumeClaims(ns.Name).Delete(context.TODO(), pvc.Name, nil); err != nil {
  881. t.Errorf("error deleting claim %s", pvc.Name)
  882. }
  883. t.Log("claim deleted")
  884. waitForAnyPersistentVolumePhase(watchPV, v1.VolumeReleased)
  885. t.Log("volume released")
  886. }
  887. func waitForPersistentVolumePhase(client *clientset.Clientset, pvName string, w watch.Interface, phase v1.PersistentVolumePhase) {
  888. // Check if the volume is already in requested phase
  889. volume, err := client.CoreV1().PersistentVolumes().Get(context.TODO(), pvName, metav1.GetOptions{})
  890. if err == nil && volume.Status.Phase == phase {
  891. return
  892. }
  893. // Wait for the phase
  894. for {
  895. event := <-w.ResultChan()
  896. volume, ok := event.Object.(*v1.PersistentVolume)
  897. if !ok {
  898. continue
  899. }
  900. if volume.Status.Phase == phase && volume.Name == pvName {
  901. klog.V(2).Infof("volume %q is %s", volume.Name, phase)
  902. break
  903. }
  904. }
  905. }
  906. func waitForPersistentVolumeClaimPhase(client *clientset.Clientset, claimName, namespace string, w watch.Interface, phase v1.PersistentVolumeClaimPhase) {
  907. // Check if the claim is already in requested phase
  908. claim, err := client.CoreV1().PersistentVolumeClaims(namespace).Get(context.TODO(), claimName, metav1.GetOptions{})
  909. if err == nil && claim.Status.Phase == phase {
  910. return
  911. }
  912. // Wait for the phase
  913. for {
  914. event := <-w.ResultChan()
  915. claim, ok := event.Object.(*v1.PersistentVolumeClaim)
  916. if !ok {
  917. continue
  918. }
  919. if claim.Status.Phase == phase && claim.Name == claimName {
  920. klog.V(2).Infof("claim %q is %s", claim.Name, phase)
  921. break
  922. }
  923. }
  924. }
  925. func waitForAnyPersistentVolumePhase(w watch.Interface, phase v1.PersistentVolumePhase) {
  926. for {
  927. event := <-w.ResultChan()
  928. volume, ok := event.Object.(*v1.PersistentVolume)
  929. if !ok {
  930. continue
  931. }
  932. if volume.Status.Phase == phase {
  933. klog.V(2).Infof("volume %q is %s", volume.Name, phase)
  934. break
  935. }
  936. }
  937. }
  938. func waitForAnyPersistentVolumeClaimPhase(w watch.Interface, phase v1.PersistentVolumeClaimPhase) {
  939. for {
  940. event := <-w.ResultChan()
  941. claim, ok := event.Object.(*v1.PersistentVolumeClaim)
  942. if !ok {
  943. continue
  944. }
  945. if claim.Status.Phase == phase {
  946. klog.V(2).Infof("claim %q is %s", claim.Name, phase)
  947. break
  948. }
  949. }
  950. }
  951. func createClients(ns *v1.Namespace, t *testing.T, s *httptest.Server, syncPeriod time.Duration) (*clientset.Clientset, *persistentvolumecontroller.PersistentVolumeController, informers.SharedInformerFactory, watch.Interface, watch.Interface) {
  952. // Use higher QPS and Burst, there is a test for race conditions which
  953. // creates many objects and default values were too low.
  954. binderClient := clientset.NewForConfigOrDie(&restclient.Config{
  955. Host: s.URL,
  956. ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}},
  957. QPS: 1000000,
  958. Burst: 1000000,
  959. })
  960. testClient := clientset.NewForConfigOrDie(&restclient.Config{
  961. Host: s.URL,
  962. ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}},
  963. QPS: 1000000,
  964. Burst: 1000000,
  965. })
  966. host := volumetest.NewFakeVolumeHost(t, "/tmp/fake", nil, nil)
  967. plugin := &volumetest.FakeVolumePlugin{
  968. PluginName: provisionerPluginName,
  969. Host: host,
  970. Config: volume.VolumeConfig{},
  971. LastProvisionerOptions: volume.VolumeOptions{},
  972. NewAttacherCallCount: 0,
  973. NewDetacherCallCount: 0,
  974. Mounters: nil,
  975. Unmounters: nil,
  976. Attachers: nil,
  977. Detachers: nil,
  978. }
  979. plugins := []volume.VolumePlugin{plugin}
  980. cloud := &fakecloud.Cloud{}
  981. informers := informers.NewSharedInformerFactory(testClient, getSyncPeriod(syncPeriod))
  982. ctrl, err := persistentvolumecontroller.NewController(
  983. persistentvolumecontroller.ControllerParameters{
  984. KubeClient: binderClient,
  985. SyncPeriod: getSyncPeriod(syncPeriod),
  986. VolumePlugins: plugins,
  987. Cloud: cloud,
  988. VolumeInformer: informers.Core().V1().PersistentVolumes(),
  989. ClaimInformer: informers.Core().V1().PersistentVolumeClaims(),
  990. ClassInformer: informers.Storage().V1().StorageClasses(),
  991. PodInformer: informers.Core().V1().Pods(),
  992. NodeInformer: informers.Core().V1().Nodes(),
  993. EnableDynamicProvisioning: true,
  994. })
  995. if err != nil {
  996. t.Fatalf("Failed to construct PersistentVolumes: %v", err)
  997. }
  998. watchPV, err := testClient.CoreV1().PersistentVolumes().Watch(context.TODO(), metav1.ListOptions{})
  999. if err != nil {
  1000. t.Fatalf("Failed to watch PersistentVolumes: %v", err)
  1001. }
  1002. watchPVC, err := testClient.CoreV1().PersistentVolumeClaims(ns.Name).Watch(context.TODO(), metav1.ListOptions{})
  1003. if err != nil {
  1004. t.Fatalf("Failed to watch PersistentVolumeClaims: %v", err)
  1005. }
  1006. return testClient, ctrl, informers, watchPV, watchPVC
  1007. }
  1008. func createPV(name, path, cap string, mode []v1.PersistentVolumeAccessMode, reclaim v1.PersistentVolumeReclaimPolicy) *v1.PersistentVolume {
  1009. return &v1.PersistentVolume{
  1010. ObjectMeta: metav1.ObjectMeta{Name: name},
  1011. Spec: v1.PersistentVolumeSpec{
  1012. PersistentVolumeSource: v1.PersistentVolumeSource{HostPath: &v1.HostPathVolumeSource{Path: path}},
  1013. Capacity: v1.ResourceList{v1.ResourceName(v1.ResourceStorage): resource.MustParse(cap)},
  1014. AccessModes: mode,
  1015. PersistentVolumeReclaimPolicy: reclaim,
  1016. },
  1017. }
  1018. }
  1019. func createPVC(name, namespace, cap string, mode []v1.PersistentVolumeAccessMode, class string) *v1.PersistentVolumeClaim {
  1020. return &v1.PersistentVolumeClaim{
  1021. ObjectMeta: metav1.ObjectMeta{
  1022. Name: name,
  1023. Namespace: namespace,
  1024. },
  1025. Spec: v1.PersistentVolumeClaimSpec{
  1026. Resources: v1.ResourceRequirements{Requests: v1.ResourceList{v1.ResourceName(v1.ResourceStorage): resource.MustParse(cap)}},
  1027. AccessModes: mode,
  1028. StorageClassName: &class,
  1029. },
  1030. }
  1031. }