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
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 @@
vm_configs:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these are vm_configs, should we rename the file according to it, something like cnv_vm_config.yaml?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the comment is to rename the file name not the dict key

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will take this in next PR.

- 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
120 changes: 119 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 @@ -7095,6 +7095,124 @@ 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 `vm_configs` 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:
lists: objects of cnv workload class with default comp and aggressive compression
PrasadDesala marked this conversation as resolved.
Show resolved Hide resolved

"""
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,
)

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,
)

# Patch the storage class to match the configuration of
# ocs-storagecluster-ceph-rbd-virtualization storage class.
storage_classes = [sc_obj_def_compr, sc_obj_aggressive]
parameter_patch = (
' \'{"parameters": {"mapOptions": "krbd:rxbounce", "mounter": "rbd"}}\''
)
for sc in storage_classes:
try:
run_cmd(
f"oc patch storageclass {sc.name} "
f"-p {parameter_patch} "
f"--request-timeout=120s"
)
log.info(f"Successfully patched parameters for storage class: {sc}")
except Exception as e:
log.info(f"Failed to patch storage class {sc}: {e}")
continue
PrasadDesala marked this conversation as resolved.
Show resolved Hide resolved

# 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["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
else:
raise ValueError(
f"Unknown storage class compression type: {vm_config['sc_name']}"
)

PrasadDesala marked this conversation as resolved.
Show resolved Hide resolved
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):
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):
PrasadDesala marked this conversation as resolved.
Show resolved Hide resolved
"""
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)

"""

# To Do
# 1. if os is windows then check rxbounce enabled in sc yaml
avd-sagare marked this conversation as resolved.
Show resolved Hide resolved

all_vm_list = self.vm_objs_def + self.vm_objs_aggr

# 2.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,
)

PrasadDesala marked this conversation as resolved.
Show resolved Hide resolved
# 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}"

# 3.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)

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