Skip to content
25 changes: 25 additions & 0 deletions ocs_ci/framework/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
from collections.abc import Mapping
from contextlib import nullcontext
from dataclasses import dataclass, field, fields

from ocs_ci.ocs import constants
from ocs_ci.ocs.exceptions import ClusterNotFoundException
from threading import Thread, RLock, local, get_ident

Expand Down Expand Up @@ -339,7 +341,13 @@ def get_cluster_index_by_name(self, cluster_name):
for i, cluster in enumerate(self.clusters):
if cluster.ENV_DATA["cluster_name"] == cluster_name:
return i
dr_cluster_name = cluster_name.removeprefix(
f"{constants.HYPERSHIFT_ADDON_DISCOVERYPREFIX}-"
)

for i, cluster in enumerate(self.clusters):
if cluster.ENV_DATA["cluster_name"] == dr_cluster_name:
return i
raise ClusterNotFoundException(f"Didn't find the cluster '{cluster_name}' ")

def switch_to_provider(self):
Expand Down Expand Up @@ -505,6 +513,23 @@ def switch_to_cluster_by_cluster_type(self, cluster_type, num_of_cluster=0):
self.get_cluster_type_indices_list(cluster_type)[num_of_cluster]
)

def get_cluster_kubeconfig_by_index(self, index):
"""
Get the cluster kubeconfig by the cluster index
Args:
index (int): The cluster index
Returns:
str: The cluster kubeconfig path
Raises:
ClusterNotFoundException: In case it didn't find the cluster
"""
if index < 0 or index >= self.nclusters:
raise ClusterNotFoundException(f"Cluster with index {index} not found")
return os.path.join(
self.clusters[index].ENV_DATA["cluster_path"],
self.clusters[index].RUN.get("kubeconfig_location", "auth/kubeconfig"),
)

class RunWithConfigContext(object):
def __init__(self, config_index):
self.original_config_index = config.cur_index
Expand Down
55 changes: 50 additions & 5 deletions ocs_ci/helpers/dr_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
enable_mco_console_plugin,
set_recovery_as_primary,
get_all_acm_indexes,
get_non_acm_cluster_and_non_provider_cluster_config,
)
from ocs_ci.utility import version, templating
from ocs_ci.utility.retry import retry
Expand Down Expand Up @@ -385,6 +386,11 @@ def check_mirroring_status_ok(
if not cephbpradosns:
raise NotFoundError("Couldn't identify the cephblockpoolradosnamespace")

if "ocs-storagecluster-cephblockpool" not in cephbpradosns:
cephbpradosns = "ocs-storagecluster-cephblockpool-" + cephbpradosns

logger.info(f"Got cephblockpoolradosnamespace {cephbpradosns}")

cbp_obj = ocp.OCP(
kind=constants.CEPHBLOCKPOOLRADOSNS,
namespace=config.clusters[config.get_provider_index()].ENV_DATA[
Expand Down Expand Up @@ -467,7 +473,12 @@ def wait_for_mirroring_status_ok(replaying_images=None, timeout=900):

"""
restore_index = config.cur_index
for cluster in get_non_acm_cluster_config():
dr_cluster_relations = config.MULTICLUSTER.get("dr_cluster_relations", [])
if dr_cluster_relations:
non_acm_cluster_config = get_non_acm_cluster_and_non_provider_cluster_config()
else:
non_acm_cluster_config = get_non_acm_cluster_config()
for cluster in non_acm_cluster_config:
config.switch_ctx(cluster.MULTICLUSTER["multicluster_index"])
logger.info(
f"Validating mirroring status on cluster {cluster.ENV_DATA['cluster_name']}"
Expand Down Expand Up @@ -1320,10 +1331,34 @@ def get_all_drpolicy():
list: List of all DRPolicy

"""
return_drpolicy_list = []
current_managed_clusters_list = []
config.switch_acm_ctx()
acm_hub_name = config.current_cluster_name()
drpolicy_obj = ocp.OCP(kind=constants.DRPOLICY)
drpolicy_list = drpolicy_obj.get(all_namespaces=True).get("items")
return drpolicy_list
for cluster_name in config.clusters:
if cluster_name.ENV_DATA.get("rbd_dr_scenario"):
current_managed_clusters_list.append(
cluster_name.ENV_DATA.get("cluster_name")
)
dr_cluster_relations = config.MULTICLUSTER.get("dr_cluster_relations", [])
if dr_cluster_relations:
current_managed_clusters_list = [
f"{constants.HYPERSHIFT_ADDON_DISCOVERYPREFIX}-{item}"
for item in dr_cluster_relations[0]
]
else:
current_managed_clusters_list.remove(acm_hub_name)

for drpolicy in drpolicy_list:

if all(
mngcls in drpolicy["spec"]["drClusters"]
for mngcls in current_managed_clusters_list
):
return_drpolicy_list.append(drpolicy)
return return_drpolicy_list


@retry(UnexpectedBehaviour, tries=5, delay=10, backoff=2)
Expand Down Expand Up @@ -2410,12 +2445,22 @@ def get_cluster_set_name(switch_ctx=None):
list: List of uniq cluster set name
"""
cluster_set = []
current_managed_clusters_list = []
restore_index = config.cur_index
config.switch_ctx(switch_ctx) if switch_ctx else config.switch_acm_ctx()
managed_clusters = ocp.OCP(kind=constants.ACM_MANAGEDCLUSTER).get().get("items", [])
current_managed_clusters_list = [
cluster_name.ENV_DATA.get("cluster_name") for cluster_name in config.clusters
]
for cluster_name in config.clusters:
if cluster_name.ENV_DATA.get("rbd_dr_scenario"):
current_managed_clusters_list.append(
cluster_name.ENV_DATA.get("cluster_name")
)
dr_cluster_relations = config.MULTICLUSTER.get("dr_cluster_relations", [])
if dr_cluster_relations:
current_managed_clusters_list = [
f"{constants.HYPERSHIFT_ADDON_DISCOVERYPREFIX}-{item}"
for item in dr_cluster_relations[0]
]

# ignore local-cluster here
for i in managed_clusters:
if (
Expand Down
10 changes: 5 additions & 5 deletions ocs_ci/helpers/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6395,12 +6395,13 @@ def find_cephblockpoolradosnamespace(storageclient_uid=None):
f"StorageClient is {storageclient_name} with uid {storageclient_uid}. StorageConsumer is {storageconsumer}"
)

cephbpradosns = ""
cephbpradosns = storageconsumer

# from ODF 4.19 and onwards, StorageRequest does not exist on new clusters, upgraded clusters have it,
# but StorageRequest is not reconciled. StorageConsumer exists in storage hub cluster and in consumer clusters
# to make this function generic need to switch context between clusters
if version.get_semantic_ocs_version_from_config() < version.VERSION_4_19:
cephbpradosns = ""
storage_request_obj = ocp.OCP(
kind="StorageRequest", namespace=config.ENV_DATA["cluster_namespace"]
)
Expand All @@ -6415,9 +6416,6 @@ def find_cephblockpoolradosnamespace(storageclient_uid=None):
break
if cephbpradosns:
break
else:
storage_consumer = get_ocs_storage_consumer_configmap_obj(storageconsumer)
cephbpradosns = storage_consumer.get_rbd_rados_ns()
return cephbpradosns


Expand Down Expand Up @@ -6481,7 +6479,9 @@ def find_cephfilesystemsubvolumegroup(storageclient_uid=None):
break
else:
storage_consumer = get_ocs_storage_consumer_configmap_obj(storageconsumer)
cephbfssubvolumegroup = storage_consumer.get_cephfs_subvolumegroup()
cephbfssubvolumegroup = storage_consumer.get("data").get(
"cephfs-subvolumegroup"
)

return cephbfssubvolumegroup

Expand Down
11 changes: 7 additions & 4 deletions ocs_ci/ocs/acm/acm.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
get_running_acm_version,
string_chunkify,
run_cmd,
exec_cmd,
)
from ocs_ci.ocs.ui.acm_ui import AcmPageNavigator
from ocs_ci.ocs.ui.base_ui import (
Expand Down Expand Up @@ -882,7 +883,8 @@ def discover_hosted_clusters():
resource_name="hypershift-addon-deploy-config",
params=(
'{"spec":{"customizedVariables":[{"name":"disableMetrics","value": "true"},'
'{"name":"disableHOManagement","value": "true"},{"name":"discoveryPrefix","value": "dr"}]}}'
'{"name":"disableHOManagement","value": "true"},'
f'{{"name":"discoveryPrefix","value": "{constants.HYPERSHIFT_ADDON_DISCOVERYPREFIX}"}}]}}}}'
),
format_type="merge",
)
Expand Down Expand Up @@ -932,10 +934,11 @@ def install_clusteradm():
"""
try:
run_cmd("clusteradm")
except CommandFailed:
except (CommandFailed, FileNotFoundError):
# Install/re0install clusteradm
run_cmd(
"curl -L https://raw.githubusercontent.com/open-cluster-management-io/clusteradm/main/install.sh | bash"
exec_cmd(
"curl -L https://raw.githubusercontent.com/open-cluster-management-io/clusteradm/main/install.sh | bash",
shell=True,
)


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 @@ -3624,3 +3624,4 @@
"/var/lib/kubelet/plugins/openshift-storage.rbd.csi.ceph.com"
)
RBD_CSI_ADDONS_SOCKET_NAME = "csi-addons.sock"
HYPERSHIFT_ADDON_DISCOVERYPREFIX = "dr"
52 changes: 47 additions & 5 deletions ocs_ci/ocs/dr/dr_workload.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

from subprocess import TimeoutExpired

from ocs_ci.deployment.helpers.hypershift_base import is_hosted_cluster
from ocs_ci.framework import config
from ocs_ci.helpers import dr_helpers, helpers
from ocs_ci.helpers.cnv_helpers import create_vm_secret, cal_md5sum_vm
Expand All @@ -31,7 +32,11 @@
ResourceWrongStatusException,
)
from ocs_ci.ocs.resources.pod import get_all_pods
from ocs_ci.ocs.utils import get_primary_cluster_config, get_non_acm_cluster_config
from ocs_ci.ocs.utils import (
get_primary_cluster_config,
get_non_acm_cluster_config,
get_non_acm_cluster_and_non_provider_cluster_config,
)
from ocs_ci.utility import templating
from ocs_ci.utility.utils import clone_repo, run_cmd, TimeoutSampler

Expand Down Expand Up @@ -90,6 +95,17 @@ def __init__(self, **kwargs):
for cluster in dr_helpers.get_all_drclusters()
if cluster != self.preferred_primary_cluster
][0]
if is_hosted_cluster(get_primary_cluster_config().ENV_DATA["cluster_name"]):
self.preferred_primary_cluster = (
constants.HYPERSHIFT_ADDON_DISCOVERYPREFIX
+ "-"
+ self.preferred_primary_cluster
)
self.preferred_secondary_cluster = (
constants.HYPERSHIFT_ADDON_DISCOVERYPREFIX
+ "-"
+ self.preferred_secondary_cluster
)
self.target_clone_dir = config.ENV_DATA.get(
"target_clone_dir", constants.DR_WORKLOAD_REPO_BASE_DIR
)
Expand Down Expand Up @@ -566,6 +582,12 @@ def __init__(self, **kwargs):
self.preferred_primary_cluster = config.ENV_DATA.get(
"preferred_primary_cluster"
) or (get_primary_cluster_config().ENV_DATA["cluster_name"])
if is_hosted_cluster(get_primary_cluster_config().ENV_DATA["cluster_name"]):
self.preferred_primary_cluster = (
constants.HYPERSHIFT_ADDON_DISCOVERYPREFIX
+ "-"
+ self.preferred_primary_cluster
)
self.target_clone_dir = config.ENV_DATA.get(
"target_clone_dir", constants.DR_WORKLOAD_REPO_BASE_DIR
)
Expand Down Expand Up @@ -702,7 +724,7 @@ def verify_workload_deployment(self):
"""

self.check_pod_pvc_status(skip_replication_resources=False)

config.switch_acm_ctx()
appset_resource_name = (
self._get_applicaionset_name() + "-" + self.preferred_primary_cluster
)
Expand Down Expand Up @@ -1189,6 +1211,12 @@ def __init__(self, **kwargs):
self.preferred_primary_cluster = kwargs.get("preferred_primary_cluster") or (
get_primary_cluster_config().ENV_DATA["cluster_name"]
)
if is_hosted_cluster(get_primary_cluster_config().ENV_DATA["cluster_type"]):
self.self.preferred_primary_cluster = (
constants.HYPERSHIFT_ADDON_DISCOVERYPREFIX
+ "-"
+ self.preferred_primary_cluster
)
self.workload_dir = kwargs.get("workload_dir")
self.discovered_apps_placement_name = kwargs.get("workload_placement_name")
self.drpc_yaml_file = os.path.join(constants.DRPC_PATH)
Expand Down Expand Up @@ -1240,7 +1268,14 @@ def deploy_workload(self, recipe=None):

"""
self._deploy_prereqs()
for cluster in get_non_acm_cluster_config():
dr_cluster_relations = config.MULTICLUSTER.get("dr_cluster_relations", [])
if dr_cluster_relations:
non_acm_cluster_config = (
get_non_acm_cluster_and_non_provider_cluster_config()
)
else:
non_acm_cluster_config = get_non_acm_cluster_config()
for cluster in non_acm_cluster_config:
config.switch_ctx(cluster.MULTICLUSTER["multicluster_index"])
self.create_namespace()
config.switch_to_cluster_by_name(self.preferred_primary_cluster)
Expand All @@ -1256,7 +1291,7 @@ def deploy_workload(self, recipe=None):

# Switch back to primary, then to each managed cluster to apply recipe
config.switch_to_cluster_by_name(self.preferred_primary_cluster)
for cluster in get_non_acm_cluster_config():
for cluster in non_acm_cluster_config:
config.switch_ctx(cluster.MULTICLUSTER["multicluster_index"])
self.create_recipe_with_checkhooks()

Expand Down Expand Up @@ -1533,7 +1568,14 @@ def delete_workload(self, drpc_name=None, skip_vrg_check=False):
f"{self.discovered_apps_placement_name}-placement-1 {ignore_not_found_param}"
)

for cluster in get_non_acm_cluster_config():
dr_cluster_relations = config.MULTICLUSTER.get("dr_cluster_relations", [])
if dr_cluster_relations:
non_acm_cluster_config = (
get_non_acm_cluster_and_non_provider_cluster_config()
)
else:
non_acm_cluster_config = get_non_acm_cluster_config()
for cluster in non_acm_cluster_config:
config.switch_ctx(cluster.MULTICLUSTER["multicluster_index"])
log.info(f"Deleting workload from {cluster.ENV_DATA['cluster_name']}")
run_cmd(
Expand Down
22 changes: 17 additions & 5 deletions ocs_ci/ocs/resources/ocsconfigmaps.py
Original file line number Diff line number Diff line change
Expand Up @@ -522,10 +522,22 @@ def get_ocs_storage_consumer_configmap_obj(storageconsumer_name):
OcsStorageConsumerConfigMap: OCS Storage Consumer ConfigMap instance
"""
ocp_obj = OCP(
kind=constants.CONFIGMAP,
resource_name=f"storageconsumer-{storageconsumer_name}",
kind=constants.STORAGECONSUMER,
resource_name=storageconsumer_name,
namespace=config.ENV_DATA["cluster_namespace"],
).get()
cm_name = ocp_obj.get("status").get("resourceNameMappingConfigMap").get("name")

provider_cluster_index = config.get_provider_index()
provider_cluster_kubeconfig = config.get_cluster_kubeconfig_by_index(
provider_cluster_index
)
ocs_obj = OcsStorageConsumerConfigMap(**ocp_obj.data)
ocs_obj.reload()
return ocs_obj

ocp_obj = OCP(
kind=constants.CONFIGMAP,
resource_name=cm_name,
namespace=config.ENV_DATA["cluster_namespace"],
cluster_kubeconfig=provider_cluster_kubeconfig,
).get()

return ocp_obj
32 changes: 32 additions & 0 deletions ocs_ci/ocs/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1693,6 +1693,38 @@ def get_non_acm_cluster_config():
return non_acm_list


def get_non_acm_cluster_and_non_provider_cluster_config():
"""
Get a list of non-acm and non_provider cluster's config objects

Returns:
list: of cluster config objects
"""
non_acm_list = []
for i in range(len(ocsci_config.clusters)):
if i in get_non_acm_cluster_and_non_provider_cluster_index():
non_acm_list.append(ocsci_config.clusters[i])

return non_acm_list


def get_non_acm_cluster_and_non_provider_cluster_index():
"""
Get config index of all non-acm and non_provider clusters

Returns:
list: of cluster config objects
"""
non_acm_cluster_and_non_provider_cluster_indexes = []
for cluster in get_non_acm_cluster_config():
if not cluster.ENV_DATA["cluster_type"] == "provider":
Copy link
Contributor

Choose a reason for hiding this comment

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

Please use the function config.get_provider_cluster_indexes

non_acm_cluster_and_non_provider_cluster_indexes.append(
cluster.MULTICLUSTER["multicluster_index"]
)

return non_acm_cluster_and_non_provider_cluster_indexes


def get_non_acm_and_non_recovery_cluster_config():
"""
Get a list of non-acm and non-recovery cluster config objects
Expand Down
Loading