def test_read_only_many(self): pvc_name = 'pvc-rox' KubeUtils.create_pvc_and_wait_to_bound(self, pvc_name, TestAccessModes.StorageClass, access_modes=['ReadOnlyMany'], volumeMode='Block') # First Pod Should Succeed pod1_name = 'pod-1-node-1' self._create_pod_on_specific_node(pod1_name, pvc_name, node_index=1) KubeUtils.wait_for_pod_to_be_running(pod1_name) # Second Pod on the same Node should Succeed pod2_name = 'pod-2-node-1' self._create_pod_on_specific_node(pod2_name, pvc_name, node_index=1) KubeUtils.wait_for_pod_to_be_running(pod2_name) # Third Pod on a different Node should Succeed pod3_name = 'pod-3-node-2' self._create_pod_on_specific_node(pod3_name, pvc_name, node_index=2) KubeUtils.wait_for_pod_to_be_running(pod3_name) KubeUtils.delete_pod(pod1_name) KubeUtils.delete_pod(pod2_name) KubeUtils.delete_pod(pod3_name)
def _test_storage_class_case(self, sc_name, params): pvc_name = 'pvc-{}'.format(sc_name) KubeUtils.create_storage_class(sc_name, params) self.addCleanup(lambda: KubeUtils.delete_storage_class(sc_name)) KubeUtils.create_pvc_and_wait_to_bound(self, pvc_name, sc_name) nvmesh_vol_name = KubeUtils.get_nvmesh_vol_name_from_pvc_name(pvc_name) NVMeshUtils.wait_for_nvmesh_volume(nvmesh_vol_name) # Verify NVMesh Volume has the required properties NVMeshUtils.wait_for_nvmesh_vol_properties(nvmesh_vol_name, params, self)
def _test_extend_fs_volume(self, storage_class_name, fs_type): # Create PVC pvc_name = 'pvc-extend-fs' KubeUtils.create_pvc_and_wait_to_bound(self, pvc_name, storage_class_name, access_modes=['ReadWriteMany']) # Create Pod pod_name = 'extend-fs-consumer' pod = KubeUtils.get_fs_consumer_pod_template(pod_name, pvc_name) KubeUtils.create_pod(pod) self.addCleanup(lambda: KubeUtils.delete_pod_and_wait(pod_name)) KubeUtils.wait_for_pod_to_be_running(pod_name) # Edit the PVC to increase the volume capacity new_size = '5Gi' pvc_patch = { 'spec': { 'resources': { 'requests': { 'storage': new_size } }, } } logger.info("Extending Volume {}".format(pvc_name)) KubeUtils.patch_pvc(pvc_name, pvc_patch) # verify kuberentes object updated KubeUtils.wait_for_pvc_to_extend(pvc_name, new_size) # wait for NVMesh Volume to show the updated size nvmesh_vol_name = KubeUtils.get_nvmesh_vol_name_from_pvc_name(pvc_name) size_5_gib_in_bytes = 5368709120 NVMeshUtils.wait_for_nvmesh_vol_properties( nvmesh_vol_name, {'capacity': size_5_gib_in_bytes}, self, attempts=15) # check block device size in container (using lsblk) KubeUtils.wait_for_block_device_resize(self, pod_name, nvmesh_vol_name, '5G') # check file system size inside the container (using df -h) expected_size = '4.9G' if fs_type == FSType.EXT4 else '5.0G' self._wait_for_file_system_resize(pod_name, expected_size)
def test_block_volume(self): # create the PVC pvc_name = 'test-block-volume' KubeUtils.create_pvc_and_wait_to_bound(self, pvc_name, 'nvmesh-raid10', volumeMode='Block') # Create Consumer pod pod_name = 'block-volume-consumer' pod = KubeUtils.get_block_consumer_pod_template(pod_name, pvc_name) KubeUtils.create_pod(pod) KubeUtils.wait_for_pod_to_be_running(pod_name) self.addCleanup(lambda: KubeUtils.delete_pod_and_wait(pod_name))
def _test_storage_class_case(self, sc_name, params): pvc_name = 'pvc-{}'.format(sc_name) KubeUtils.create_storage_class(sc_name, params) self.addCleanup(lambda: KubeUtils.delete_storage_class(sc_name)) additional_fields = { 'description': 'Storage Class Parameters test for ' + sc_name } KubeUtils.create_pvc_and_wait_to_bound(self, pvc_name, sc_name, **additional_fields) nvmesh_vol_name = KubeUtils.get_nvmesh_vol_name_from_pvc_name(pvc_name) mgmt_address = NVMeshUtils.wait_for_nvmesh_volume(nvmesh_vol_name) # Verify NVMesh Volume has the required properties NVMeshUtils.wait_for_nvmesh_vol_properties(nvmesh_vol_name, params, self)
def test_block_volume_extend(self): # Create PVC pvc_name = 'pvc-extend-block' KubeUtils.create_pvc_and_wait_to_bound(self, pvc_name, 'nvmesh-raid10', volumeMode='Block', access_modes=['ReadWriteMany']) # Create Pod pod_name = 'extend-block-consumer' pod = KubeUtils.get_block_consumer_pod_template(pod_name, pvc_name) KubeUtils.create_pod(pod) self.addCleanup(lambda: KubeUtils.delete_pod_and_wait(pod_name)) KubeUtils.wait_for_pod_to_be_running(pod_name) # Edit the PVC to increase the volume capacity new_size = '5Gi' pvc_patch = { 'spec': { 'resources': { 'requests': { 'storage': new_size } }, } } logger.info("Extending Volume {}".format(pvc_name)) KubeUtils.patch_pvc(pvc_name, pvc_patch) # verify kuberentes object updated KubeUtils.wait_for_pvc_to_extend(pvc_name, new_size) # wait for NVMesh Volume to show the updated size nvmesh_vol_name = KubeUtils.get_nvmesh_vol_name_from_pvc_name(pvc_name) size_5_gib_in_bytes = 5368709120 NVMeshUtils.wait_for_nvmesh_vol_properties( nvmesh_vol_name, {'capacity': size_5_gib_in_bytes}, self, attempts=15) # check block device size in container (using lsblk) KubeUtils.wait_for_block_device_resize(self, pod_name, nvmesh_vol_name, '5G')
def test_migration(self): # create the PVC pvc_name = 'pvc-migration-test' sc_name = 'nvmesh-raid10' KubeUtils.create_pvc_and_wait_to_bound(self, pvc_name, sc_name) # Create Deployment dep_name = 'test-pod-migration' pod = KubeUtils.get_fs_consumer_pod_template(dep_name, pvc_name) deployment = KubeUtils.get_deployment_template(dep_name, pod['spec']) KubeUtils.create_deployment(deployment) self.addCleanup(lambda: KubeUtils.delete_deployment(dep_name)) attempts = 10 pod = None while attempts: logger.debug('Waiting for deployment pods to be scheduled') pod_list = KubeUtils.get_pods_for_deployment(dep_name) if len(pod_list): pod = pod_list[0] break attempts = attempts - 1 self.assertNotEqual(attempts, 0, 'Timed out waiting for deployment pod to be scheduled') time.sleep(1) initial_pod_name = pod.metadata.name # Set node as NoSchedule initial_node = pod.spec.node_name logger.debug("Tainting node %s with noSchedule" % initial_node) KubeUtils.node_prevent_schedule(initial_node) self.addCleanup(lambda: KubeUtils.node_allow_schedule(initial_node)) # Delete the pod (it is expected to be re-created on a different node KubeUtils.delete_pod(initial_pod_name) KubeUtils.wait_for_pod_to_delete(initial_pod_name, attempts=120) # Get the second Pod pods = KubeUtils.get_pods_for_deployment(dep_name) pod = pods[0] second_pod_name = pod.metadata.name self.assertNotEqual(initial_pod_name, second_pod_name) self.assertNotEqual(pod.spec.node_name, initial_node) KubeUtils.wait_for_pod_to_be_running(second_pod_name)
def test_file_system_persistency(self): # create the PVC pvc_name = 'pvc-fs-persistency-test' sc_name = 'nvmesh-raid10' KubeUtils.create_pvc_and_wait_to_bound(self, pvc_name, sc_name) data_to_write = "Persistency Test" # Create pod to write a file in the FS self._run_shell_pod('job-writer', pvc_name, "echo '{}' > /vol/file1".format(data_to_write)) # Create pod to read the file content pod_reader_name = 'job-reader' self._run_shell_pod(pod_reader_name, pvc_name, "cat /vol/file1") # get logs and verify output pod_log = KubeUtils.get_pod_log(pod_reader_name) self.assertEqual(pod_log.strip(), data_to_write)
def _test_raid_type(self, raid_type): storage_class_name = 'nvmesh-{}'.format(raid_type).replace('_', '-') pvc_name = storage_class_name KubeUtils.create_pvc_and_wait_to_bound(self, pvc_name, storage_class_name) # wait for nvmesh volume to be created nvmesh_vol_name = KubeUtils.get_nvmesh_vol_name_from_pvc_name(pvc_name) NVMeshUtils.wait_for_nvmesh_volume(nvmesh_vol_name) # verify NVMesh Volumes Properties NVMeshUtils.wait_for_nvmesh_vol_properties(nvmesh_vol_name, {'raidLevel': raid_type}, self) def cleanup_volume(): KubeUtils.delete_pvc(pvc_name) KubeUtils.wait_for_pvc_to_delete(pvc_name) self.addCleanup(cleanup_volume)
def _test_fs_type(self, fs_type, **kwargs): # Create Storage class for the specific File System Type sc_name = self._create_storage_class_for_fs_type(fs_type, **kwargs) # create the PVC pvc_name = 'test-{}'.format(fs_type) KubeUtils.create_pvc_and_wait_to_bound(self, pvc_name, sc_name) # Create Consumer pod pod_name = 'consumer-{}'.format(fs_type) pod = KubeUtils.get_fs_consumer_pod_template(pod_name, pvc_name) KubeUtils.create_pod(pod) def cleanup_pod(): KubeUtils.delete_pod(pod_name) KubeUtils.wait_for_pod_to_delete(pod_name) self.addCleanup(cleanup_pod) KubeUtils.wait_for_pod_to_be_running(pod_name)
def test_read_only_many_can_read_from_different_pods_and_nodes(self): pvc_name = 'pvc-rox' KubeUtils.create_pvc_and_wait_to_bound(self, pvc_name, TestAccessModes.StorageClass, access_modes=['ReadOnlyMany'], volumeMode='Block') # First Pod Should Succeed pod = KubeUtils.get_block_consumer_pod_template('pod-1-node-1', pvc_name) self.set_pod_node(pod, node_index=1) self.create_pod_with_cleanup(pod) KubeUtils.wait_for_pod_to_be_running(pod['metadata']['name']) # Second Pod on the same Node should Succeed pod = KubeUtils.get_block_consumer_pod_template('pod-2-node-1', pvc_name) self.set_pod_node(pod, node_index=1) self.create_pod_with_cleanup(pod) KubeUtils.wait_for_pod_to_be_running(pod['metadata']['name']) # Third Pod on a different Node should Succeed pod = KubeUtils.get_block_consumer_pod_template('pod-3-node-2', pvc_name) self.set_pod_node(pod, node_index=2) self.create_pod_with_cleanup(pod) KubeUtils.wait_for_pod_to_be_running(pod['metadata']['name'])
def test_read_write_once(self): pvc_name = 'pvc-rwo' KubeUtils.create_pvc_and_wait_to_bound(self, pvc_name, TestAccessModes.StorageClass, access_modes=['ReadWriteOnce'], volumeMode='Filesystem') # First Pod Should Succeed pod = KubeUtils.get_fs_consumer_pod_template('pod-1-node-1', pvc_name) self.set_pod_node(pod, node_index=1) self.create_pod_with_cleanup(pod) KubeUtils.wait_for_pod_to_be_running(pod['metadata']['name']) # Second Pod on the same Node - should be running pod = KubeUtils.get_fs_consumer_pod_template('pod-2-node-1', pvc_name) self.set_pod_node(pod, node_index=1) self.create_pod_with_cleanup(pod) KubeUtils.wait_for_pod_to_be_running(pod['metadata']['name']) # Third Pod on a different Node should Fail pod = KubeUtils.get_fs_consumer_pod_template('pod-3-node-2', pvc_name) self.set_pod_node(pod, node_index=2) self.create_pod_with_cleanup(pod) KubeUtils.wait_for_pod_event(pod['metadata']['name'], keyword='Access Mode Denied', attempts=20)
def _test_fs_type(self, fs_type): # Create Storage class for the specific File System Type sc_name = 'raid1-{}'.format(fs_type) sc_params = {'fsType': fs_type, 'vpg': 'DEFAULT_RAID_1_VPG'} KubeUtils.create_storage_class(sc_name, sc_params) self.addCleanup(lambda: KubeUtils.delete_storage_class(sc_name)) # create the PVC pvc_name = 'test-{}'.format(fs_type) KubeUtils.create_pvc_and_wait_to_bound(self, pvc_name, sc_name) # Create Consumer pod pod_name = 'consumer-{}'.format(fs_type) pod = KubeUtils.get_fs_consumer_pod_template(pod_name, pvc_name) KubeUtils.create_pod(pod) def cleanup_pod(): KubeUtils.delete_pod(pod_name) KubeUtils.wait_for_pod_to_delete(pod_name) self.addCleanup(cleanup_pod) KubeUtils.wait_for_pod_to_be_running(pod_name)
def test_mixed_access_modes(self): # This test creates a PV with reclaimPolicy: Retain (making sure it is not deleted when the bounded PVC is deleted) # Then will create PVC's with different AccessModes to use the same PV. in between some PV clean needs to be done. # Create Storage Class with reclaimPolicy: Retain sc_name = 'sc-nvmesh-retain' KubeUtils.create_storage_class(sc_name, {'vpg': 'DEFAULT_RAID_10_VPG'}, reclaimPolicy='Retain') self.addCleanup(lambda: KubeUtils.delete_storage_class(sc_name)) # Create NVMesh Volume nvmesh_volume_name = "vol1" volume = Volume( name=nvmesh_volume_name, RAIDLevel=RAIDLevels.STRIPED_AND_MIRRORED_RAID_10, VPG='DEFAULT_RAID_10_VPG', capacity=5 * GiB, description="Volume for CSI Driver Static Provisioning") err, out = NVMeshUtils.getVolumeAPI().save([volume]) self.assertIsNone(err, 'Error Creating NVMesh Volume. %s' % err) create_res = out[0] self.assertTrue( create_res['success'], 'Error Creating NVMesh Volume. %s' % create_res['error']) self.addCleanup(lambda: NVMeshUtils.getVolumeAPI().delete([volume])) # Create PV pv_name = 'csi-testing-pv-vol1' volume_size = '5Gi' self.create_pv_for_static_prov(nvmesh_volume_name, pv_name, sc_name, volume_size) # Create PVC with accessMode ReadWriteOnce pvc_name = 'pvc-rwo' KubeUtils.create_pvc_and_wait_to_bound(self, pvc_name, sc_name, access_modes=['ReadWriteOnce'], storage=volume_size, volumeMode='Filesystem') self.addCleanup(lambda: KubeUtils.delete_pvc(pvc_name)) # Create Pod to create a file on the File System pod_name = 'pod-file-writer' cmd = 'echo hello > /vol/file1' pod = KubeUtils.get_shell_pod_template(pod_name, pvc_name, cmd) KubeUtils.create_pod(pod) self.addCleanup(lambda: KubeUtils.delete_pod_and_wait(pod_name)) KubeUtils.wait_for_pod_to_complete(pod_name) KubeUtils.delete_pod_and_wait(pod_name) # Delete the PVC KubeUtils.delete_pvc(pvc_name) KubeUtils.wait_for_pv_to_be_released(pv_name) # Make PV Available for the next PVC (by removing claimRef field from the PV ==OR== deleting and recreating the PV) KubeUtils.delete_pv(pv_name) KubeUtils.wait_for_pv_to_delete(pv_name) self.create_pv_for_static_prov(nvmesh_volume_name, pv_name, sc_name, volume_size) # Create PVC With ReadOnlyMany pvc_name = 'pvc-rox' KubeUtils.create_pvc_and_wait_to_bound(self, pvc_name, sc_name, access_modes=['ReadOnlyMany'], storage=volume_size, volumeMode='Filesystem') self.addCleanup(lambda: KubeUtils.delete_pvc(pvc_name)) # 7. Create 2 Pods that will read the File System - Should Succeed pod1_name = 'pod-file-reader1' cmd = 'cat /vol/file1' pod = KubeUtils.get_shell_pod_template(pod1_name, pvc_name, cmd) KubeUtils.create_pod(pod) self.addCleanup(lambda: KubeUtils.delete_pod_and_wait(pod1_name)) pod2_name = 'pod-file-reader2' pod = KubeUtils.get_shell_pod_template(pod2_name, pvc_name, cmd) KubeUtils.create_pod(pod) self.addCleanup(lambda: KubeUtils.delete_pod_and_wait(pod2_name)) KubeUtils.wait_for_pod_to_complete(pod2_name) # 8. Create 1 Pod that will try to write to the FileSystem - Should Fail pod_name = 'pod-file-writer' cmd = 'echo hello > /vol/file1' pod = KubeUtils.get_shell_pod_template(pod_name, pvc_name, cmd) KubeUtils.create_pod(pod) self.addCleanup(lambda: KubeUtils.delete_pod_and_wait(pod_name)) KubeUtils.wait_for_pod_to_fail(pod_name)
def test_static_provisioning(self): # Create NVMesh Volume nvmesh_volume_name = "csi-testing-static-prov" volume = Volume( name=nvmesh_volume_name, RAIDLevel=RAIDLevels.STRIPED_AND_MIRRORED_RAID_10, VPG='DEFAULT_RAID_10_VPG', capacity=5 * GiB, description="Volume for CSI Driver Static Provisioning") err, out = NVMeshUtils.getVolumeAPI().save([volume]) self.assertIsNone(err, 'Error Creating NVMesh Volume. %s' % err) create_res = out[0] self.assertTrue( create_res['success'], 'Error Creating NVMesh Volume. %s' % create_res['error']) self.addCleanup(lambda: NVMeshUtils.getVolumeAPI().delete([volume])) # Create PV pv_name = 'pv-name-in-k8s' accessModes = ['ReadWriteOnce'] volume_size = '5Gi' sc_name = 'nvmesh-raid10' pv = KubeUtils.get_pv_for_static_provisioning(pv_name, nvmesh_volume_name, accessModes, sc_name, volume_size) core_api.create_persistent_volume(pv) self.addCleanup(lambda: core_api.delete_persistent_volume(pv_name)) pv_list = core_api.list_persistent_volume( field_selector='metadata.name={}'.format(pv_name)) self.assertIsNotNone(pv_list) self.assertTrue(len(pv_list.items)) self.assertEqual(pv_list.items[0].metadata.name, pv_name) # Create PVC pvc_name = 'pvc-static-prov' KubeUtils.create_pvc_and_wait_to_bound(self, pvc_name, sc_name, access_modes=accessModes, storage=volume_size, volumeMode='Block') self.addCleanup(lambda: KubeUtils.delete_pvc(pvc_name)) # Create Consumer pod pod_name = 'pod-static-prov' cmd = 'echo hello ; while true ; do sleep 60; done' pod = KubeUtils.get_shell_pod_template(pod_name, pvc_name, cmd, volume_mode_block=True) KubeUtils.create_pod(pod) self.addCleanup(lambda: KubeUtils.delete_pod_and_wait(pod_name)) KubeUtils.wait_for_pod_to_be_running(pod_name)