csi.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. /*
  2. Copyright 2018 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. /*
  14. * This file defines various csi volume test drivers for TestSuites.
  15. *
  16. * There are two ways, how to prepare test drivers:
  17. * 1) With containerized server (NFS, Ceph, Gluster, iSCSI, ...)
  18. * It creates a server pod which defines one volume for the tests.
  19. * These tests work only when privileged containers are allowed, exporting
  20. * various filesystems (NFS, GlusterFS, ...) usually needs some mounting or
  21. * other privileged magic in the server pod.
  22. *
  23. * Note that the server containers are for testing purposes only and should not
  24. * be used in production.
  25. *
  26. * 2) With server or cloud provider outside of Kubernetes (Cinder, GCE, AWS, Azure, ...)
  27. * Appropriate server or cloud provider must exist somewhere outside
  28. * the tested Kubernetes cluster. CreateVolume will create a new volume to be
  29. * used in the TestSuites for inlineVolume or DynamicPV tests.
  30. */
  31. package drivers
  32. import (
  33. "fmt"
  34. "math/rand"
  35. "strconv"
  36. "github.com/onsi/ginkgo"
  37. storagev1 "k8s.io/api/storage/v1"
  38. "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
  39. "k8s.io/apimachinery/pkg/util/sets"
  40. "k8s.io/kubernetes/test/e2e/framework"
  41. "k8s.io/kubernetes/test/e2e/storage/testpatterns"
  42. "k8s.io/kubernetes/test/e2e/storage/testsuites"
  43. "k8s.io/kubernetes/test/e2e/storage/utils"
  44. )
  45. const (
  46. // GCEPDCSIProvisionerName is the name of GCE Persistent Disk CSI provisioner
  47. GCEPDCSIProvisionerName = "pd.csi.storage.gke.io"
  48. // GCEPDCSIZoneTopologyKey is the key of GCE Persistent Disk CSI zone topology
  49. GCEPDCSIZoneTopologyKey = "topology.gke.io/zone"
  50. )
  51. // hostpathCSI
  52. type hostpathCSIDriver struct {
  53. driverInfo testsuites.DriverInfo
  54. manifests []string
  55. }
  56. func initHostPathCSIDriver(name string, capabilities map[testsuites.Capability]bool, manifests ...string) testsuites.TestDriver {
  57. return &hostpathCSIDriver{
  58. driverInfo: testsuites.DriverInfo{
  59. Name: name,
  60. FeatureTag: "",
  61. MaxFileSize: testpatterns.FileSizeMedium,
  62. SupportedFsType: sets.NewString(
  63. "", // Default fsType
  64. ),
  65. Capabilities: capabilities,
  66. },
  67. manifests: manifests,
  68. }
  69. }
  70. var _ testsuites.TestDriver = &hostpathCSIDriver{}
  71. var _ testsuites.DynamicPVTestDriver = &hostpathCSIDriver{}
  72. var _ testsuites.SnapshottableTestDriver = &hostpathCSIDriver{}
  73. // InitHostPathCSIDriver returns hostpathCSIDriver that implements TestDriver interface
  74. func InitHostPathCSIDriver() testsuites.TestDriver {
  75. return initHostPathCSIDriver("csi-hostpath",
  76. map[testsuites.Capability]bool{testsuites.CapPersistence: true, testsuites.CapDataSource: true,
  77. testsuites.CapMultiPODs: true, testsuites.CapBlock: true},
  78. "test/e2e/testing-manifests/storage-csi/driver-registrar/rbac.yaml",
  79. "test/e2e/testing-manifests/storage-csi/external-attacher/rbac.yaml",
  80. "test/e2e/testing-manifests/storage-csi/external-provisioner/rbac.yaml",
  81. "test/e2e/testing-manifests/storage-csi/external-snapshotter/rbac.yaml",
  82. "test/e2e/testing-manifests/storage-csi/hostpath/hostpath/csi-hostpath-attacher.yaml",
  83. "test/e2e/testing-manifests/storage-csi/hostpath/hostpath/csi-hostpath-provisioner.yaml",
  84. "test/e2e/testing-manifests/storage-csi/hostpath/hostpath/csi-hostpath-snapshotter.yaml",
  85. "test/e2e/testing-manifests/storage-csi/hostpath/hostpath/csi-hostpathplugin.yaml",
  86. "test/e2e/testing-manifests/storage-csi/hostpath/hostpath/e2e-test-rbac.yaml",
  87. )
  88. }
  89. func (h *hostpathCSIDriver) GetDriverInfo() *testsuites.DriverInfo {
  90. return &h.driverInfo
  91. }
  92. func (h *hostpathCSIDriver) SkipUnsupportedTest(pattern testpatterns.TestPattern) {
  93. }
  94. func (h *hostpathCSIDriver) GetDynamicProvisionStorageClass(config *testsuites.PerTestConfig, fsType string) *storagev1.StorageClass {
  95. provisioner := config.GetUniqueDriverName()
  96. parameters := map[string]string{}
  97. ns := config.Framework.Namespace.Name
  98. suffix := fmt.Sprintf("%s-sc", provisioner)
  99. return testsuites.GetStorageClass(provisioner, parameters, nil, ns, suffix)
  100. }
  101. func (h *hostpathCSIDriver) GetSnapshotClass(config *testsuites.PerTestConfig) *unstructured.Unstructured {
  102. snapshotter := config.GetUniqueDriverName()
  103. parameters := map[string]string{}
  104. ns := config.Framework.Namespace.Name
  105. suffix := fmt.Sprintf("%s-vsc", snapshotter)
  106. return testsuites.GetSnapshotClass(snapshotter, parameters, ns, suffix)
  107. }
  108. func (h *hostpathCSIDriver) GetClaimSize() string {
  109. return "5Gi"
  110. }
  111. func (h *hostpathCSIDriver) PrepareTest(f *framework.Framework) (*testsuites.PerTestConfig, func()) {
  112. ginkgo.By(fmt.Sprintf("deploying %s driver", h.driverInfo.Name))
  113. cancelLogging := testsuites.StartPodLogs(f)
  114. cs := f.ClientSet
  115. // The hostpath CSI driver only works when everything runs on the same node.
  116. nodes := framework.GetReadySchedulableNodesOrDie(cs)
  117. nodeName := nodes.Items[rand.Intn(len(nodes.Items))].Name
  118. config := &testsuites.PerTestConfig{
  119. Driver: h,
  120. Prefix: "hostpath",
  121. Framework: f,
  122. ClientNodeName: nodeName,
  123. }
  124. // TODO (?): the storage.csi.image.version and storage.csi.image.registry
  125. // settings are ignored for this test. We could patch the image definitions.
  126. o := utils.PatchCSIOptions{
  127. OldDriverName: h.driverInfo.Name,
  128. NewDriverName: config.GetUniqueDriverName(),
  129. DriverContainerName: "hostpath",
  130. DriverContainerArguments: []string{"--drivername=" + config.GetUniqueDriverName()},
  131. ProvisionerContainerName: "csi-provisioner",
  132. SnapshotterContainerName: "csi-snapshotter",
  133. NodeName: nodeName,
  134. }
  135. cleanup, err := config.Framework.CreateFromManifests(func(item interface{}) error {
  136. return utils.PatchCSIDeployment(config.Framework, o, item)
  137. },
  138. h.manifests...)
  139. if err != nil {
  140. framework.Failf("deploying %s driver: %v", h.driverInfo.Name, err)
  141. }
  142. return config, func() {
  143. ginkgo.By(fmt.Sprintf("uninstalling %s driver", h.driverInfo.Name))
  144. cleanup()
  145. cancelLogging()
  146. }
  147. }
  148. // mockCSI
  149. type mockCSIDriver struct {
  150. driverInfo testsuites.DriverInfo
  151. manifests []string
  152. podInfo *bool
  153. attachable bool
  154. attachLimit int
  155. enableNodeExpansion bool
  156. }
  157. // CSIMockDriverOpts defines options used for csi driver
  158. type CSIMockDriverOpts struct {
  159. RegisterDriver bool
  160. DisableAttach bool
  161. PodInfo *bool
  162. AttachLimit int
  163. EnableResizing bool
  164. EnableNodeExpansion bool
  165. }
  166. var _ testsuites.TestDriver = &mockCSIDriver{}
  167. var _ testsuites.DynamicPVTestDriver = &mockCSIDriver{}
  168. // InitMockCSIDriver returns a mockCSIDriver that implements TestDriver interface
  169. func InitMockCSIDriver(driverOpts CSIMockDriverOpts) testsuites.TestDriver {
  170. driverManifests := []string{
  171. "test/e2e/testing-manifests/storage-csi/cluster-driver-registrar/rbac.yaml",
  172. "test/e2e/testing-manifests/storage-csi/driver-registrar/rbac.yaml",
  173. "test/e2e/testing-manifests/storage-csi/external-attacher/rbac.yaml",
  174. "test/e2e/testing-manifests/storage-csi/external-provisioner/rbac.yaml",
  175. "test/e2e/testing-manifests/storage-csi/external-resizer/rbac.yaml",
  176. "test/e2e/testing-manifests/storage-csi/mock/csi-mock-rbac.yaml",
  177. "test/e2e/testing-manifests/storage-csi/mock/csi-storageclass.yaml",
  178. "test/e2e/testing-manifests/storage-csi/mock/csi-mock-driver.yaml",
  179. }
  180. if driverOpts.RegisterDriver {
  181. driverManifests = append(driverManifests, "test/e2e/testing-manifests/storage-csi/mock/csi-mock-cluster-driver-registrar.yaml")
  182. }
  183. if !driverOpts.DisableAttach {
  184. driverManifests = append(driverManifests, "test/e2e/testing-manifests/storage-csi/mock/csi-mock-driver-attacher.yaml")
  185. }
  186. if driverOpts.EnableResizing {
  187. driverManifests = append(driverManifests, "test/e2e/testing-manifests/storage-csi/mock/csi-mock-driver-resizer.yaml")
  188. }
  189. return &mockCSIDriver{
  190. driverInfo: testsuites.DriverInfo{
  191. Name: "csi-mock",
  192. FeatureTag: "",
  193. MaxFileSize: testpatterns.FileSizeMedium,
  194. SupportedFsType: sets.NewString(
  195. "", // Default fsType
  196. ),
  197. Capabilities: map[testsuites.Capability]bool{
  198. testsuites.CapPersistence: false,
  199. testsuites.CapFsGroup: false,
  200. testsuites.CapExec: false,
  201. },
  202. },
  203. manifests: driverManifests,
  204. podInfo: driverOpts.PodInfo,
  205. attachable: !driverOpts.DisableAttach,
  206. attachLimit: driverOpts.AttachLimit,
  207. enableNodeExpansion: driverOpts.EnableNodeExpansion,
  208. }
  209. }
  210. func (m *mockCSIDriver) GetDriverInfo() *testsuites.DriverInfo {
  211. return &m.driverInfo
  212. }
  213. func (m *mockCSIDriver) SkipUnsupportedTest(pattern testpatterns.TestPattern) {
  214. }
  215. func (m *mockCSIDriver) GetDynamicProvisionStorageClass(config *testsuites.PerTestConfig, fsType string) *storagev1.StorageClass {
  216. provisioner := config.GetUniqueDriverName()
  217. parameters := map[string]string{}
  218. ns := config.Framework.Namespace.Name
  219. suffix := fmt.Sprintf("%s-sc", provisioner)
  220. return testsuites.GetStorageClass(provisioner, parameters, nil, ns, suffix)
  221. }
  222. func (m *mockCSIDriver) GetClaimSize() string {
  223. return "5Gi"
  224. }
  225. func (m *mockCSIDriver) PrepareTest(f *framework.Framework) (*testsuites.PerTestConfig, func()) {
  226. ginkgo.By("deploying csi mock driver")
  227. cancelLogging := testsuites.StartPodLogs(f)
  228. cs := f.ClientSet
  229. // pods should be scheduled on the node
  230. nodes := framework.GetReadySchedulableNodesOrDie(cs)
  231. node := nodes.Items[rand.Intn(len(nodes.Items))]
  232. config := &testsuites.PerTestConfig{
  233. Driver: m,
  234. Prefix: "mock",
  235. Framework: f,
  236. ClientNodeName: node.Name,
  237. }
  238. containerArgs := []string{"--name=csi-mock-" + f.UniqueName}
  239. if !m.attachable {
  240. containerArgs = append(containerArgs, "--disable-attach")
  241. }
  242. if m.attachLimit > 0 {
  243. containerArgs = append(containerArgs, "--attach-limit", strconv.Itoa(m.attachLimit))
  244. }
  245. if m.enableNodeExpansion {
  246. containerArgs = append(containerArgs, "--node-expand-required=true")
  247. }
  248. // TODO (?): the storage.csi.image.version and storage.csi.image.registry
  249. // settings are ignored for this test. We could patch the image definitions.
  250. o := utils.PatchCSIOptions{
  251. OldDriverName: "csi-mock",
  252. NewDriverName: "csi-mock-" + f.UniqueName,
  253. DriverContainerName: "mock",
  254. DriverContainerArguments: containerArgs,
  255. ProvisionerContainerName: "csi-provisioner",
  256. ClusterRegistrarContainerName: "csi-cluster-driver-registrar",
  257. NodeName: config.ClientNodeName,
  258. PodInfo: m.podInfo,
  259. }
  260. cleanup, err := f.CreateFromManifests(func(item interface{}) error {
  261. return utils.PatchCSIDeployment(f, o, item)
  262. },
  263. m.manifests...)
  264. if err != nil {
  265. framework.Failf("deploying csi mock driver: %v", err)
  266. }
  267. return config, func() {
  268. ginkgo.By("uninstalling csi mock driver")
  269. cleanup()
  270. cancelLogging()
  271. }
  272. }
  273. // InitHostPathV0CSIDriver returns a variant of hostpathCSIDriver with different manifests.
  274. func InitHostPathV0CSIDriver() testsuites.TestDriver {
  275. return initHostPathCSIDriver("csi-hostpath-v0",
  276. map[testsuites.Capability]bool{testsuites.CapPersistence: true, testsuites.CapMultiPODs: true},
  277. "test/e2e/testing-manifests/storage-csi/driver-registrar/rbac.yaml",
  278. "test/e2e/testing-manifests/storage-csi/external-attacher/rbac.yaml",
  279. "test/e2e/testing-manifests/storage-csi/external-provisioner/rbac.yaml",
  280. "test/e2e/testing-manifests/storage-csi/hostpath/hostpath-v0/csi-hostpath-attacher.yaml",
  281. "test/e2e/testing-manifests/storage-csi/hostpath/hostpath-v0/csi-hostpath-provisioner.yaml",
  282. "test/e2e/testing-manifests/storage-csi/hostpath/hostpath-v0/csi-hostpathplugin.yaml",
  283. "test/e2e/testing-manifests/storage-csi/hostpath/hostpath-v0/e2e-test-rbac.yaml",
  284. )
  285. }
  286. // gce-pd
  287. type gcePDCSIDriver struct {
  288. driverInfo testsuites.DriverInfo
  289. }
  290. var _ testsuites.TestDriver = &gcePDCSIDriver{}
  291. var _ testsuites.DynamicPVTestDriver = &gcePDCSIDriver{}
  292. // InitGcePDCSIDriver returns gcePDCSIDriver that implements TestDriver interface
  293. func InitGcePDCSIDriver() testsuites.TestDriver {
  294. return &gcePDCSIDriver{
  295. driverInfo: testsuites.DriverInfo{
  296. Name: GCEPDCSIProvisionerName,
  297. FeatureTag: "[Serial]",
  298. MaxFileSize: testpatterns.FileSizeMedium,
  299. SupportedFsType: sets.NewString(
  300. "", // Default fsType
  301. "ext2",
  302. "ext3",
  303. "ext4",
  304. "xfs",
  305. ),
  306. SupportedMountOption: sets.NewString("debug", "nouid32"),
  307. Capabilities: map[testsuites.Capability]bool{
  308. testsuites.CapPersistence: true,
  309. testsuites.CapFsGroup: true,
  310. testsuites.CapExec: true,
  311. testsuites.CapMultiPODs: true,
  312. },
  313. },
  314. }
  315. }
  316. func (g *gcePDCSIDriver) GetDriverInfo() *testsuites.DriverInfo {
  317. return &g.driverInfo
  318. }
  319. func (g *gcePDCSIDriver) SkipUnsupportedTest(pattern testpatterns.TestPattern) {
  320. framework.SkipUnlessProviderIs("gce", "gke")
  321. if pattern.FsType == "xfs" {
  322. framework.SkipUnlessNodeOSDistroIs("ubuntu", "custom")
  323. }
  324. if pattern.FeatureTag == "[sig-windows]" {
  325. framework.Skipf("Skipping tests for windows since CSI does not support it yet")
  326. }
  327. }
  328. func (g *gcePDCSIDriver) GetDynamicProvisionStorageClass(config *testsuites.PerTestConfig, fsType string) *storagev1.StorageClass {
  329. ns := config.Framework.Namespace.Name
  330. provisioner := g.driverInfo.Name
  331. suffix := fmt.Sprintf("%s-sc", g.driverInfo.Name)
  332. parameters := map[string]string{"type": "pd-standard"}
  333. if fsType != "" {
  334. parameters["csi.storage.k8s.io/fstype"] = fsType
  335. }
  336. delayedBinding := storagev1.VolumeBindingWaitForFirstConsumer
  337. return testsuites.GetStorageClass(provisioner, parameters, &delayedBinding, ns, suffix)
  338. }
  339. func (g *gcePDCSIDriver) GetClaimSize() string {
  340. return "5Gi"
  341. }
  342. func (g *gcePDCSIDriver) PrepareTest(f *framework.Framework) (*testsuites.PerTestConfig, func()) {
  343. ginkgo.By("deploying csi gce-pd driver")
  344. cancelLogging := testsuites.StartPodLogs(f)
  345. // It would be safer to rename the gcePD driver, but that
  346. // hasn't been done before either and attempts to do so now led to
  347. // errors during driver registration, therefore it is disabled
  348. // by passing a nil function below.
  349. //
  350. // These are the options which would have to be used:
  351. // o := utils.PatchCSIOptions{
  352. // OldDriverName: g.driverInfo.Name,
  353. // NewDriverName: testsuites.GetUniqueDriverName(g),
  354. // DriverContainerName: "gce-driver",
  355. // ProvisionerContainerName: "csi-external-provisioner",
  356. // }
  357. createGCESecrets(f.ClientSet, f.Namespace.Name)
  358. manifests := []string{
  359. "test/e2e/testing-manifests/storage-csi/driver-registrar/rbac.yaml",
  360. "test/e2e/testing-manifests/storage-csi/external-attacher/rbac.yaml",
  361. "test/e2e/testing-manifests/storage-csi/external-provisioner/rbac.yaml",
  362. "test/e2e/testing-manifests/storage-csi/gce-pd/csi-controller-rbac.yaml",
  363. "test/e2e/testing-manifests/storage-csi/gce-pd/node_ds.yaml",
  364. "test/e2e/testing-manifests/storage-csi/gce-pd/controller_ss.yaml",
  365. }
  366. cleanup, err := f.CreateFromManifests(nil, manifests...)
  367. if err != nil {
  368. framework.Failf("deploying csi gce-pd driver: %v", err)
  369. }
  370. return &testsuites.PerTestConfig{
  371. Driver: g,
  372. Prefix: "gcepd",
  373. Framework: f,
  374. }, func() {
  375. ginkgo.By("uninstalling gce-pd driver")
  376. cleanup()
  377. cancelLogging()
  378. }
  379. }