Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions src/mas/devops/ocp.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,30 @@ def getStorageClasses(dynClient: DynamicClient) -> list:
return storageClasses


def getStorageClassVolumeBindingMode(dynClient: DynamicClient, storageClassName: str) -> str:
"""
Get the volumeBindingMode for a storage class.

Args:
dynClient: OpenShift dynamic client
storageClassName: Name of the storage class

Returns:
str: "Immediate" or "WaitForFirstConsumer" (defaults to "Immediate" if not found)
"""
try:
storageClass = getStorageClass(dynClient, storageClassName)
if storageClass and hasattr(storageClass, 'volumeBindingMode'):
return storageClass.volumeBindingMode
# Default to Immediate if not specified (Kubernetes default)
logger.debug(f"Storage class {storageClassName} does not have volumeBindingMode set, defaulting to 'Immediate'")
return "Immediate"
except Exception as e:
logger.warning(f"Unable to determine volumeBindingMode for storage class {storageClassName}: {e}")
# Default to Immediate to maintain backward compatibility
return "Immediate"


def isSNO(dynClient: DynamicClient) -> bool:
"""
Check if the cluster is a Single Node OpenShift (SNO) deployment.
Expand Down
38 changes: 24 additions & 14 deletions src/mas/devops/tekton.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

from jinja2 import Environment, FileSystemLoader

from .ocp import getConsoleURL, waitForCRD, waitForDeployment, crdExists, waitForPVC, getStorageClasses
from .ocp import getConsoleURL, waitForCRD, waitForDeployment, crdExists, waitForPVC, getStorageClasses, getStorageClassVolumeBindingMode

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -314,18 +314,22 @@ def preparePipelinesNamespace(dynClient: DynamicClient, instanceId: str = None,
pvc = yaml.safe_load(renderedTemplate)
pvcAPI = dynClient.resources.get(api_version="v1", kind="PersistentVolumeClaim")
pvcAPI.apply(body=pvc, namespace=namespace)

if instanceId is not None and waitForBind:
logger.debug("Waiting for PVC to be bound")
pvcIsBound = False
while not pvcIsBound:
configPVC = pvcAPI.get(name="config-pvc", namespace=namespace)
if configPVC.status.phase == "Bound":
pvcIsBound = True
else:
logger.debug("Waiting 15s before checking status of PVC again")
logger.debug(configPVC)
sleep(15)
# Automatically determine if we should wait for PVC binding based on storage class
volumeBindingMode = getStorageClassVolumeBindingMode(dynClient, storageClass)
waitForBind = (volumeBindingMode == "Immediate")
if waitForBind:
logger.info(f"Storage class {storageClass} uses volumeBindingMode={volumeBindingMode}, waiting for PVC to bind")
pvcIsBound = False
while not pvcIsBound:
configPVC = pvcAPI.get(name="config-pvc", namespace=namespace)
if configPVC.status.phase == "Bound":
pvcIsBound = True
else:
logger.debug("Waiting 15s before checking status of PVC again")
logger.debug(configPVC)
sleep(15)
else:
logger.info(f"Storage class {storageClass} uses volumeBindingMode={volumeBindingMode}, skipping PVC bind wait")


def prepareAiServicePipelinesNamespace(dynClient: DynamicClient, instanceId: str = None, storageClass: str = None, accessMode: str = None, waitForBind: bool = True, configureRBAC: bool = True):
Expand Down Expand Up @@ -375,8 +379,12 @@ def prepareAiServicePipelinesNamespace(dynClient: DynamicClient, instanceId: str
pvcAPI = dynClient.resources.get(api_version="v1", kind="PersistentVolumeClaim")
pvcAPI.apply(body=pvc, namespace=namespace)

# Automatically determine if we should wait for PVC binding based on storage class
volumeBindingMode = getStorageClassVolumeBindingMode(dynClient, storageClass)
waitForBind = (volumeBindingMode == "Immediate")

if waitForBind:
logger.debug("Waiting for PVC to be bound")
logger.info(f"Storage class {storageClass} uses volumeBindingMode={volumeBindingMode}, waiting for PVC to bind")
pvcIsBound = False
while not pvcIsBound:
configPVC = pvcAPI.get(name="config-pvc", namespace=namespace)
Expand All @@ -386,6 +394,8 @@ def prepareAiServicePipelinesNamespace(dynClient: DynamicClient, instanceId: str
logger.debug("Waiting 15s before checking status of PVC again")
logger.debug(configPVC)
sleep(15)
else:
logger.info(f"Storage class {storageClass} uses volumeBindingMode={volumeBindingMode}, skipping PVC bind wait")


def prepareInstallSecrets(dynClient: DynamicClient, namespace: str, slsLicenseFile: str = None, additionalConfigs: dict = None, certs: str = None, podTemplates: str = None) -> None:
Expand Down