Skip to content

Commit

Permalink
create multiple cnv workloads (#10673)
Browse files Browse the repository at this point in the history
Signed-off-by: Avdhoot <[email protected]>
  • Loading branch information
avd-sagare authored Dec 19, 2024
1 parent 4688944 commit fe4c7f9
Show file tree
Hide file tree
Showing 5 changed files with 266 additions and 1 deletion.
9 changes: 9 additions & 0 deletions ocs_ci/helpers/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -757,6 +757,8 @@ def create_storage_class(
allow_volume_expansion=True,
kernelMountOptions=None,
annotations=None,
mapOptions=None,
mounter=None,
):
"""
Create a storage class
Expand All @@ -781,6 +783,9 @@ def create_storage_class(
allow_volume_expansion(bool): True to create sc with volume expansion
kernelMountOptions (str): Mount option for security context
annotations(dict): dict of annotations to be added to the storageclass.
mapOptions (str): mapOtions match the configuration of ocs-storagecluster-ceph-rbd-virtualization storage class
mounter (str): mounter to match the configuration of ocs-storagecluster-ceph-rbd-virtualization storage class
Returns:
OCS: An OCS instance for the storage class
"""
Expand Down Expand Up @@ -834,6 +839,10 @@ def create_storage_class(
if annotations:
sc_data["metadata"]["annotations"] = annotations

if mapOptions and mounter:
sc_data["parameters"]["mapOptions"] = mapOptions
sc_data["parameters"]["mounter"] = mounter

sc_data["parameters"]["clusterID"] = config.ENV_DATA["cluster_namespace"]
sc_data["reclaimPolicy"] = reclaim_policy
sc_data["volumeBindingMode"] = volume_binding_mode
Expand Down
1 change: 1 addition & 0 deletions ocs_ci/ocs/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -995,6 +995,7 @@
TEMPLATE_CNV_VM_WORKLOAD_DIR, "dv_role_binding.yaml"
)
CNV_VM_TEMPLATE_YAML = os.path.join(TEMPLATE_CNV_VM_WORKLOAD_DIR, "vm.yaml")
CNV_VM_WORKLOADS = os.path.join(TEMPLATE_CNV_VM_WORKLOAD_DIR, "cnv_vm_workload.yaml")

METALLB = "metallb-operator"
METALLB_CONTROLLER_MANAGER_PREFIX = "metallb-operator-controller-manager"
Expand Down
16 changes: 16 additions & 0 deletions ocs_ci/templates/cnv-vm-workload/cnv_vm_workload.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
cnv_vm_configs:
- volume_interface: PVC
access_mode: ReadWriteMany
sc_compression: default
- volume_interface: PVC
access_mode: ReadWriteMany
sc_compression: aggressive
- volume_interface: PVC
access_mode: ReadWriteOnce
sc_compression: default
- volume_interface: DVT
access_mode: ReadWriteMany
sc_compression: default
- volume_interface: DVT
access_mode: ReadWriteMany
sc_compression: aggressive
113 changes: 112 additions & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@
)
from ocs_ci.ocs.longevity import start_app_workload
from ocs_ci.utility.decorators import switch_to_default_cluster_index_at_last

from ocs_ci.helpers.keyrotation_helper import PVKeyrotation

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -860,6 +860,8 @@ def factory(
allow_volume_expansion=True,
kernelMountOptions=None,
annotations=None,
mapOptions=None,
mounter=None,
):
"""
Args:
Expand All @@ -886,6 +888,8 @@ def factory(
allow_volume_expansion (bool): True to Allows volume expansion
kernelMountOptions (str): Mount option for security context
annotations (dict): dict of annotation to be added to the storageclass.
mapOptions (str): mapOtions match the configuration of ocs-storagecluster-ceph-rbd-virtualization SC
mounter (str): mounter to match the configuration of ocs-storagecluster-ceph-rbd-virtualization SC
Returns:
object: helpers.create_storage_class instance with links to
Expand Down Expand Up @@ -925,6 +929,8 @@ def factory(
allow_volume_expansion=allow_volume_expansion,
kernelMountOptions=kernelMountOptions,
annotations=annotations,
mapOptions=mapOptions,
mounter=mounter,
)
assert sc_obj, f"Failed to create {interface} storage class"
sc_obj.secret = secret
Expand Down Expand Up @@ -7095,6 +7101,111 @@ def teardown():
return factory


@pytest.fixture()
def multi_cnv_workload(
pv_encryption_kms_setup_factory, storageclass_factory, cnv_workload
):
"""
Fixture to create virtual machines (VMs) with specific configurations.
This fixture sets up multiple VMs with varying storage configurations as specified
in the `cnv_vm_workload.yaml`. Each VM configuration includes the volume interface type,
access mode, and the storage class to be used.
The configurations applied to the VMs are:
- Volume interface: `VM_VOLUME_PVC` or `VM_VOLUME_DVT`
- Access mode: `ACCESS_MODE_RWX` or `ACCESS_MODE_RWO`
- Storage class: Custom storage classes, including default compression and aggressive profiles.
"""

def factory(namespace=None):
"""
Args:
namespace (str, optional): The namespace to create the vm on.
Returns:
tuple: tuple containing:
vm_list_default_compr(list): objects of cnv workload class with default comp
vm_list_agg_compr(list): objects of cnv workload class with aggressive compression
sc_obj_def_compr(list): objects of storage class with default comp
sc_obj_aggressive(list): objects of storage class with aggressive compression
"""
vm_list_agg_compr = []
vm_list_default_compr = []

namespace = (
namespace if namespace else create_unique_resource_name("vm", "namespace")
)

# Setup csi-kms-connection-details configmap
log.info("Setting up csi-kms-connection-details configmap")
kms = pv_encryption_kms_setup_factory(kv_version="v2")
log.info("csi-kms-connection-details setup successful")

# Create an encryption enabled storageclass for RBD
sc_obj_def_compr = storageclass_factory(
interface=constants.CEPHBLOCKPOOL,
encrypted=True,
encryption_kms_id=kms.kmsid,
new_rbd_pool=True,
mapOptions="krbd:rxbounce",
mounter="rbd",
)

sc_obj_aggressive = storageclass_factory(
interface=constants.CEPHBLOCKPOOL,
encrypted=True,
encryption_kms_id=kms.kmsid,
compression="aggressive",
new_rbd_pool=True,
mapOptions="krbd:rxbounce",
mounter="rbd",
)

storage_classes = [sc_obj_def_compr, sc_obj_aggressive]

# Create ceph-csi-kms-token in the tenant namespace
kms.vault_path_token = kms.generate_vault_token()
kms.create_vault_csi_kms_token(namespace=namespace)

for sc_obj in storage_classes:
pvk_obj = PVKeyrotation(sc_obj)
pvk_obj.annotate_storageclass_key_rotation(schedule="*/3 * * * *")

# Load VMconfigs from cnv_vm_workload yaml
vm_configs = templating.load_yaml(constants.CNV_VM_WORKLOADS)

# Loop through vm_configs and create the VMs using the cnv_workload fixture
for index, vm_config in enumerate(vm_configs["cnv_vm_configs"]):
# Determine the storage class based on the compression type
if vm_config["sc_compression"] == "default":
storageclass = sc_obj_def_compr.name
elif vm_config["sc_compression"] == "aggressive":
storageclass = sc_obj_aggressive.name
vm_obj = cnv_workload(
volume_interface=vm_config["volume_interface"],
access_mode=vm_config["access_mode"],
storageclass=storageclass,
pvc_size="30Gi", # Assuming pvc_size is fixed for all
source_url=constants.CNV_FEDORA_SOURCE, # Assuming source_url is the same for all VMs
namespace=namespace,
)[index]
if vm_config["sc_compression"] == "aggressive":
vm_list_agg_compr.append(vm_obj)
else:
vm_list_default_compr.append(vm_obj)
return (
vm_list_default_compr,
vm_list_agg_compr,
sc_obj_def_compr,
sc_obj_aggressive,
)

return factory


@pytest.fixture()
def clone_vm_workload(request):
"""
Expand Down
128 changes: 128 additions & 0 deletions tests/functional/workloads/cnv/test_multi_vm_configurations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import logging
import pytest

from ocs_ci.framework.testlib import E2ETest
from ocs_ci.framework.pytest_customization.marks import workloads, magenta_squad
from ocs_ci.helpers.cnv_helpers import cal_md5sum_vm
from ocs_ci.helpers.performance_lib import run_oc_command
from ocs_ci.helpers.keyrotation_helper import PVKeyrotation
from ocs_ci.utility.utils import run_cmd
from ocs_ci.ocs import constants

logger = logging.getLogger(__name__)


@magenta_squad
class TestCNVVM(E2ETest):
"""
Includes tests related to CNV+ODF workloads.
"""

@pytest.fixture(autouse=True)
def setup(self, project_factory, multi_cnv_workload):
"""
Setting up VMs for tests
"""

# Create a project
proj_obj = project_factory()
(
self.vm_objs_def,
self.vm_objs_aggr,
self.sc_obj_def_compr,
self.sc_obj_aggressive,
) = multi_cnv_workload(namespace=proj_obj.namespace)

logger.info("All vms created successfully")

def verify_keyrotation(self, vm_objs, sc_obj):
"""
Verify the keyrotation is succeed.
Args:
vm_objs (obj): virtual machine Object
sc_obj (obj): storage class object
"""
for vm in vm_objs:
if vm.volume_interface == constants.VM_VOLUME_PVC:
pvk_obj = PVKeyrotation(sc_obj)
volume_name = vm.pvc_obj.get().get("spec", {}).get("volumeName")
volume_handle = None
for line in run_oc_command(
f"describe pv {volume_name}", namespace=vm.namespace
):
if "VolumeHandle:" in line:
volume_handle = line.split()[1]
break
if not volume_handle:
logger.error(f"Cannot get volume handle for pv {volume_name}")
raise Exception("Cannot get volume handle")
assert pvk_obj.wait_till_keyrotation(
volume_handle
), f"Failed to rotate Key for the PVC {vm.pvc_obj.name}"

@workloads
@pytest.mark.polarion_id("OCS-6298")
def test_cnv_vms(self, setup, setup_cnv):
"""
Tests to verify configuration for non-GS like environment
Steps:
1) Create VMs using fixture multi_cnv_workload
2) Validate data integrity using md5sum.
a. create file locally and take md5sum
b. copy same file to vm and take md5sum
c. Validate both are same or not
3) Validate pvc level key rotation
4) Stop the VM
5) Delete the VM (as part of factory teardown)
"""
all_vm_list = self.vm_objs_def + self.vm_objs_aggr

# 1.Validate data integrity using md5sum.
file_name = "/tmp/dd_file"
vm_filepath = "/home/admin/dd_file1_copy"

# Create file locally
cmd = f"dd if=/dev/zero of={file_name} bs=1M count=1024"
run_cmd(cmd)
# Calculate the MD5 checksum
if file_name:
cmd = f"md5sum {file_name}"
md5sum_on_local = run_cmd(cmd).split()[0]
if md5sum_on_local:
logger.info(f"MD5 checksum of the file: {md5sum_on_local}")
else:
raise ValueError(
"MD5 checksum could not be calculated. Ensure the file exists and is accessible."
)
else:
raise ValueError(
"File name is not provided. Please specify a valid file name."
)
# Copy local file to all vms
for vm_obj in all_vm_list:
vm_obj.scp_to_vm(
local_path=file_name,
vm_dest_path=vm_filepath,
)
# Take md5sum of copied file and compare with md5sum taken locally
for vm_obj in all_vm_list:
md5sum_on_vm = cal_md5sum_vm(vm_obj, vm_filepath, username=None)
assert (
md5sum_on_vm == md5sum_on_local
), f"md5sum has changed after copying file on {vm_obj.name}"

# 2.Verify PV Keyrotation.
# Process VMs with default compression
self.verify_keyrotation(self.vm_objs_def, self.sc_obj_def_compr)
# Process VMs with aggressive compression
self.verify_keyrotation(self.vm_objs_aggr, self.sc_obj_aggressive)

# 3.Stop all VMs
for vm_obj in all_vm_list:
vm_obj.stop()

0 comments on commit fe4c7f9

Please sign in to comment.