Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

create multiple cnv workloads #10673

Merged
merged 16 commits into from
Dec 19, 2024
9 changes: 9 additions & 0 deletions ocs_ci/helpers/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,8 @@ def create_storage_class(
allow_volume_expansion=True,
kernelMountOptions=None,
annotations=None,
mapOptions=None,
mounter=None,
):
"""
Create a storage class
Expand All @@ -780,6 +782,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
avd-sagare marked this conversation as resolved.
Show resolved Hide resolved

Returns:
OCS: An OCS instance for the storage class
"""
Expand Down Expand Up @@ -833,6 +838,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,
PrasadDesala marked this conversation as resolved.
Show resolved Hide resolved
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 = (
parikshithb marked this conversation as resolved.
Show resolved Hide resolved
namespace if namespace else create_unique_resource_name("vm", "namespace")
)

# Setup csi-kms-connection-details configmap
PrasadDesala marked this conversation as resolved.
Show resolved Hide resolved
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
avd-sagare marked this conversation as resolved.
Show resolved Hide resolved
sc_obj_def_compr = storageclass_factory(
parikshithb marked this conversation as resolved.
Show resolved Hide resolved
interface=constants.CEPHBLOCKPOOL,
encrypted=True,
encryption_kms_id=kms.kmsid,
new_rbd_pool=True,
mapOptions="krbd:rxbounce",
mounter="rbd",
)

sc_obj_aggressive = storageclass_factory(
avd-sagare marked this conversation as resolved.
Show resolved Hide resolved
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:
avd-sagare marked this conversation as resolved.
Show resolved Hide resolved
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()
Loading