From 9d5495cf7f9d268bde80645c5330c30557f1e0a3 Mon Sep 17 00:00:00 2001 From: Roger Nhan Date: Thu, 23 Jul 2026 17:54:52 -0400 Subject: [PATCH 1/5] [AKS] `az aks create/update`: Add distributedcache storage option to --enable/--disable-azure-container-storage --- src/aks-preview/HISTORY.rst | 4 + src/aks-preview/azext_aks_preview/_params.py | 13 +- .../azurecontainerstorage/_consts.py | 5 + .../azurecontainerstorage/_helpers.py | 10 + .../azurecontainerstorage/_validators.py | 109 ++++++++++ .../azurecontainerstorage/acstor_ops.py | 109 ++++++++++ .../managed_cluster_decorator.py | 203 ++++++++++++++++++ .../tests/latest/test_validators.py | 126 +++++++++++ 8 files changed, 574 insertions(+), 5 deletions(-) diff --git a/src/aks-preview/HISTORY.rst b/src/aks-preview/HISTORY.rst index be6aa0cb576..89d9e256c90 100644 --- a/src/aks-preview/HISTORY.rst +++ b/src/aks-preview/HISTORY.rst @@ -11,6 +11,10 @@ To release a new version, please select a new version number (usually plus 1 to Pending +++++++ +* `az aks create/update`: Add `distributedAccelerator` storage option to `--enable-azure-container-storage` and `--disable-azure-container-storage` to install/uninstall the Azure Container Storage distributed accelerator cache controller. + +22.0.0b9 ++++++++++ * `az aks nodepool update`: Preserve the existing GPU management mode when `--enable-managed-gpu` is omitted, including when enabling, updating, or disabling the cluster autoscaler. * `az aks alert-config add`: Reject an empty `--name` before looking up existing configurations instead of reporting that it already exists. * `az aks nodepool scale`: add `--use-patch-api` to optionally scale a VMSS node pool via the new dedicated PATCH agent pool API (scales to the target count without triggering full reconciliation). The default behavior continues to use the PUT agent pool API. diff --git a/src/aks-preview/azext_aks_preview/_params.py b/src/aks-preview/azext_aks_preview/_params.py index 8409f18d526..bf6ffc3ef97 100644 --- a/src/aks-preview/azext_aks_preview/_params.py +++ b/src/aks-preview/azext_aks_preview/_params.py @@ -280,6 +280,7 @@ CONST_STORAGE_POOL_TYPE_AZURE_DISK, CONST_STORAGE_POOL_TYPE_EPHEMERAL_DISK, CONST_STORAGE_POOL_TYPE_ELASTIC_SAN, + CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE, CONST_STORAGE_POOL_SKU_PREMIUM_LRS, CONST_STORAGE_POOL_SKU_STANDARD_LRS, CONST_STORAGE_POOL_SKU_STANDARDSSD_LRS, @@ -529,12 +530,14 @@ def _deprecate_option(c, target, redirect): CONST_STORAGE_POOL_TYPE_AZURE_DISK, CONST_STORAGE_POOL_TYPE_EPHEMERAL_DISK, CONST_STORAGE_POOL_TYPE_ELASTIC_SAN, + CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE, ] disable_storage_pool_types = [ CONST_STORAGE_POOL_TYPE_AZURE_DISK, CONST_STORAGE_POOL_TYPE_EPHEMERAL_DISK, CONST_STORAGE_POOL_TYPE_ELASTIC_SAN, + CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE, CONST_ACSTOR_ALL, ] @@ -1294,7 +1297,7 @@ def load_arguments(self, _): "enable_azure_container_storage", arg_type=_get_container_storage_enum_type(storage_pool_types), help="enable azure container storage. Can be used as a flag (defaults to True) or with a" - " storage pool type value: (azureDisk, ephemeralDisk, elasticSan)", + " storage pool type value: (azureDisk, ephemeralDisk, elasticSan, distributedcache)", ) c.argument( "container_storage_version", @@ -2042,14 +2045,14 @@ def load_arguments(self, _): "enable_azure_container_storage", arg_type=_get_container_storage_enum_type(storage_pool_types), help="enable azure container storage. Can be used as a flag (defaults to True) or with a" - " storage pool type value: (azureDisk, ephemeralDisk, elasticSan)", + " storage pool type value: (azureDisk, ephemeralDisk, elasticSan, distributedcache)", ) c.argument( "disable_azure_container_storage", arg_type=_get_container_storage_enum_type(disable_storage_pool_types), - help="disable azure container storage or any one of the storage pool types." - " Can be used as a flag (defaults to True) or with a storagepool type value:" - " azureDisk, ephemeralDisk, elasticSan, all (to disable all storage pools).", + help="disable azure container storage or any one of the storage types." + " Can be used as a flag (defaults to True) or with a storage type value:" + " azureDisk, ephemeralDisk, elasticSan, distributedcache, all (to disable all storage types).", ) c.argument( "container_storage_version", diff --git a/src/aks-preview/azext_aks_preview/azurecontainerstorage/_consts.py b/src/aks-preview/azext_aks_preview/azurecontainerstorage/_consts.py index 3019cdbd640..fe634e345d7 100644 --- a/src/aks-preview/azext_aks_preview/azurecontainerstorage/_consts.py +++ b/src/aks-preview/azext_aks_preview/azurecontainerstorage/_consts.py @@ -17,6 +17,10 @@ CONST_ACSTOR_EXT_INSTALLATION_NAME = "acstor" CONST_ACSTOR_EXT_INSTALLATION_NAMESPACE = "kube-system" CONST_ACSTOR_K8S_EXTENSION_NAME = "microsoft.azurecontainerstoragev2" +# Distributed cache (Distributed Accelerator for Cloud Storage) install controller. +CONST_DISTRIBUTED_CACHE_EXT_INSTALLATION_NAME = "distributedcache" +CONST_DISTRIBUTED_CACHE_EXT_INSTALLATION_NAMESPACE = "kube-system" +CONST_DISTRIBUTED_CACHE_K8S_EXTENSION_NAME = "microsoft.dacs" CONST_K8S_EXTENSION_CLIENT_FACTORY_MOD_NAME = "azext_k8s_extension._client_factory" CONST_K8S_EXTENSION_CUSTOM_MOD_NAME = "azext_k8s_extension.custom" CONST_K8S_EXTENSION_NAME = "k8s-extension" @@ -35,3 +39,4 @@ CONST_STORAGE_POOL_TYPE_AZURE_DISK = "azureDisk" CONST_STORAGE_POOL_TYPE_ELASTIC_SAN = "elasticSan" CONST_STORAGE_POOL_TYPE_EPHEMERAL_DISK = "ephemeralDisk" +CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE = "distributedcache" diff --git a/src/aks-preview/azext_aks_preview/azurecontainerstorage/_helpers.py b/src/aks-preview/azext_aks_preview/azurecontainerstorage/_helpers.py index 6d2e110d939..21e7ea655fe 100644 --- a/src/aks-preview/azext_aks_preview/azurecontainerstorage/_helpers.py +++ b/src/aks-preview/azext_aks_preview/azurecontainerstorage/_helpers.py @@ -23,6 +23,7 @@ CONST_STORAGE_POOL_TYPE_AZURE_DISK, CONST_STORAGE_POOL_TYPE_ELASTIC_SAN, CONST_STORAGE_POOL_TYPE_EPHEMERAL_DISK, + CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE, CONST_ACSTOR_V1_K8S_EXTENSION_NAME, CONST_ACSTOR_V1_EXT_INSTALLATION_NAME, ) @@ -304,6 +305,15 @@ def should_delete_extension(storage_options_to_remove) -> bool: ) +def is_distributed_cache_requested(storage_options) -> bool: + # Detect whether distributed cache is among the requested storage options. + if storage_options is None or storage_options is True: + return False + if isinstance(storage_options, list): + return CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE in storage_options + return storage_options == CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE + + def get_container_storage_extension_installed( cmd, resource_group, diff --git a/src/aks-preview/azext_aks_preview/azurecontainerstorage/_validators.py b/src/aks-preview/azext_aks_preview/azurecontainerstorage/_validators.py index d4f71d622a5..c0f1749a4ec 100644 --- a/src/aks-preview/azext_aks_preview/azurecontainerstorage/_validators.py +++ b/src/aks-preview/azext_aks_preview/azurecontainerstorage/_validators.py @@ -21,6 +21,7 @@ CONST_STORAGE_POOL_TYPE_AZURE_DISK, CONST_STORAGE_POOL_TYPE_ELASTIC_SAN, CONST_STORAGE_POOL_TYPE_EPHEMERAL_DISK, + CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE, ) from azext_aks_preview.azurecontainerstorage._helpers import ( get_vm_sku_details @@ -571,6 +572,114 @@ def validate_disable_azure_container_storage_params( ) +def validate_enable_distributed_cache_params( + enablement_option, + is_extension_installed, + storage_pool_name, + storage_pool_sku, + storage_pool_option, + storage_pool_size, + ephemeral_disk_volume_type, + ephemeral_disk_nvme_perf_tier, + container_storage_version=None, +): + # Distributed cache has no storage pool construct, so none of the storage + # pool parameters are supported. + enablement_option_arr = enablement_option if isinstance(enablement_option, list) else [enablement_option] + other_pool_types = [ + opt for opt in enablement_option_arr + if opt != CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE + ] + if other_pool_types: + options_display = "', '".join(other_pool_types) + raise InvalidArgumentValueError( + f"'{CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE}' cannot be combined with other storage " + f"options ('{options_display}'). Distributed cache is enabled independently. " + f"Please run --enable-azure-container-storage {CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE} " + "on its own." + ) + + if is_extension_installed: + raise InvalidArgumentValueError( + 'Cannot enable distributed cache as it is already enabled on the cluster.' + ) + + unsupported_params = [] + if storage_pool_name is not None: + unsupported_params.append('--storage-pool-name') + if storage_pool_sku is not None: + unsupported_params.append('--storage-pool-sku') + if storage_pool_option is not None: + unsupported_params.append('--storage-pool-option') + if storage_pool_size is not None: + unsupported_params.append('--storage-pool-size') + if ephemeral_disk_volume_type is not None: + unsupported_params.append('--ephemeral-disk-volume-type') + if ephemeral_disk_nvme_perf_tier is not None: + unsupported_params.append('--ephemeral-disk-nvme-perf-tier') + if container_storage_version is not None: + unsupported_params.append('--container-storage-version') + + if unsupported_params: + params_defined = ', '.join(unsupported_params) + raise InvalidArgumentValueError( + f'{params_defined} cannot be used with ' + f'--enable-azure-container-storage {CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE}. ' + 'Distributed cache does not require or support any storage pool configuration. ' + 'Please remove these parameters and try again.' + ) + + +def validate_disable_distributed_cache_params( + disablement_option, + is_extension_installed, + storage_pool_name, + storage_pool_sku, + storage_pool_option, + storage_pool_size, + container_storage_version=None, +): + disablement_option_arr = disablement_option if isinstance(disablement_option, list) else [disablement_option] + other_pool_types = [ + opt for opt in disablement_option_arr + if opt != CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE + ] + if other_pool_types: + options_display = "', '".join(other_pool_types) + raise InvalidArgumentValueError( + f"'{CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE}' cannot be combined with other storage " + f"options ('{options_display}'). Distributed cache is disabled independently. " + f"Please run --disable-azure-container-storage {CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE} " + "on its own." + ) + + if not is_extension_installed: + raise InvalidArgumentValueError( + 'Cannot disable distributed cache as it could not be found on the cluster.' + ) + + unsupported_params = [] + if storage_pool_name is not None: + unsupported_params.append('--storage-pool-name') + if storage_pool_sku is not None: + unsupported_params.append('--storage-pool-sku') + if storage_pool_option is not None: + unsupported_params.append('--storage-pool-option') + if storage_pool_size is not None: + unsupported_params.append('--storage-pool-size') + if container_storage_version is not None: + unsupported_params.append('--container-storage-version') + + if unsupported_params: + params_defined = ', '.join(unsupported_params) + raise InvalidArgumentValueError( + f'{params_defined} cannot be used with ' + f'--disable-azure-container-storage {CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE}. ' + 'Distributed cache does not require or support any storage pool configuration. ' + 'Please remove these parameters and try again.' + ) + + # _Validate_storage_pool_size validates that the storage_pool_size is # string of a combination of a float number immediately followed by # Ti or Gi e.g. 2Ti, 512Gi, 1.5Ti. The function also validates that the diff --git a/src/aks-preview/azext_aks_preview/azurecontainerstorage/acstor_ops.py b/src/aks-preview/azext_aks_preview/azurecontainerstorage/acstor_ops.py index 4369e6e4e1a..9a5920e58e2 100644 --- a/src/aks-preview/azext_aks_preview/azurecontainerstorage/acstor_ops.py +++ b/src/aks-preview/azext_aks_preview/azurecontainerstorage/acstor_ops.py @@ -12,6 +12,9 @@ CONST_ACSTOR_EXT_INSTALLATION_NAME, CONST_ACSTOR_EXT_INSTALLATION_NAMESPACE, CONST_ACSTOR_K8S_EXTENSION_NAME, + CONST_DISTRIBUTED_CACHE_EXT_INSTALLATION_NAME, + CONST_DISTRIBUTED_CACHE_EXT_INSTALLATION_NAMESPACE, + CONST_DISTRIBUTED_CACHE_K8S_EXTENSION_NAME, CONST_DISK_TYPE_EPHEMERAL_VOLUME_ONLY, CONST_DISK_TYPE_PV_WITH_ANNOTATION, CONST_EPHEMERAL_NVME_PERF_TIER_STANDARD, @@ -797,3 +800,109 @@ def perform_azure_container_storage_update( raise UnknownError( "Failed to disable Azure Container Storage with error: %s" % delete_ex ) from delete_ex + + +def perform_enable_distributed_cache( + cmd, + resource_group, + cluster_name, + is_extension_installed=False, + is_called_from_extension=False, +): + # This will be set true only when aks-preview extension is used + # and we want the aks-preview ManagedClusterDecorator to call the + # perform_enable_distributed_cache function. + if not is_called_from_extension: + return + + # Enabling only installs the install controller. Cache components are + # deployed later, driven by the creation of the corresponding CR. + client_factory = get_k8s_extension_module(CONST_K8S_EXTENSION_CLIENT_FACTORY_MOD_NAME) + client = client_factory.cf_k8s_extension_operation(cmd.cli_ctx) + k8s_extension_custom_mod = get_k8s_extension_module(CONST_K8S_EXTENSION_CUSTOM_MOD_NAME) + + if is_extension_installed: + logger.warning("Distributed cache is already enabled on the cluster.") + return + + try: + result = k8s_extension_custom_mod.create_k8s_extension( + cmd, + client, + resource_group, + cluster_name, + CONST_DISTRIBUTED_CACHE_EXT_INSTALLATION_NAME, + "managedClusters", + CONST_DISTRIBUTED_CACHE_K8S_EXTENSION_NAME, + auto_upgrade_minor_version=True, + release_train="stable", + scope="cluster", + release_namespace=CONST_DISTRIBUTED_CACHE_EXT_INSTALLATION_NAMESPACE, + ) + long_op_result = LongRunningOperation(cmd.cli_ctx)(result) + if long_op_result.provisioning_state == "Succeeded": + logger.warning("Distributed cache successfully installed") + except Exception as ex: # pylint: disable=broad-except + logger.error("Distributed cache failed to install.\nError: %s", ex) + logger.warning("Cleaning up the cluster by disabling distributed cache") + try: + delete_op_result = k8s_extension_custom_mod.delete_k8s_extension( + cmd, + client, + resource_group, + cluster_name, + CONST_DISTRIBUTED_CACHE_EXT_INSTALLATION_NAME, + "managedClusters", + yes=True, + ) + LongRunningOperation(cmd.cli_ctx)(delete_op_result) + logger.warning( + "Please retry enabling distributed cache by running " + "`az aks update` along with " + "`--enable-azure-container-storage distributedcache`" + ) + except Exception as delete_ex: # pylint: disable=broad-except + raise UnknownError( + "Failed to clean up distributed cache with error: %s" % delete_ex + ) from delete_ex + + +def perform_disable_distributed_cache( + cmd, + resource_group, + cluster_name, + is_extension_installed=False, + is_called_from_extension=False, +): + # This will be set true only when aks-preview extension is used + # and we want the aks-preview ManagedClusterDecorator to call the + # perform_disable_distributed_cache function. + if not is_called_from_extension: + return + + client_factory = get_k8s_extension_module(CONST_K8S_EXTENSION_CLIENT_FACTORY_MOD_NAME) + client = client_factory.cf_k8s_extension_operation(cmd.cli_ctx) + k8s_extension_custom_mod = get_k8s_extension_module(CONST_K8S_EXTENSION_CUSTOM_MOD_NAME) + + if not is_extension_installed: + logger.warning("Distributed cache is not enabled on the cluster.") + return + + # Deleting the install controller triggers removal of the remaining cache + # components from the cluster. + try: + delete_op_result = k8s_extension_custom_mod.delete_k8s_extension( + cmd, + client, + resource_group, + cluster_name, + CONST_DISTRIBUTED_CACHE_EXT_INSTALLATION_NAME, + "managedClusters", + yes=True, + ) + LongRunningOperation(cmd.cli_ctx)(delete_op_result) + logger.warning("Distributed cache has been disabled.") + except Exception as delete_ex: # pylint: disable=broad-except + raise UnknownError( + "Failed to disable distributed cache with error: %s" % delete_ex + ) from delete_ex diff --git a/src/aks-preview/azext_aks_preview/managed_cluster_decorator.py b/src/aks-preview/azext_aks_preview/managed_cluster_decorator.py index a9a88b3c8e8..959c7c95397 100644 --- a/src/aks-preview/azext_aks_preview/managed_cluster_decorator.py +++ b/src/aks-preview/azext_aks_preview/managed_cluster_decorator.py @@ -60,6 +60,7 @@ CONST_ACSTOR_EXT_INSTALLATION_NAME, CONST_ACSTOR_V1_EXT_INSTALLATION_NAME, CONST_ACSTOR_VERSION_V1, + CONST_DISTRIBUTED_CACHE_EXT_INSTALLATION_NAME, ) from azext_aks_preview._helpers import ( check_is_apiserver_vnet_integration_cluster, @@ -95,6 +96,8 @@ perform_disable_azure_container_storage_v1, perform_enable_azure_container_storage_v1, perform_azure_container_storage_update, + perform_enable_distributed_cache, + perform_disable_distributed_cache, ) from azext_aks_preview.azuremonitormetrics.azuremonitorprofile import ( ensure_azure_monitor_profile_prerequisites, @@ -291,6 +294,12 @@ def external_functions(self) -> SimpleNamespace: "perform_disable_azure_container_storage_v1" ] = perform_disable_azure_container_storage_v1 external_functions["perform_azure_container_storage_update"] = perform_azure_container_storage_update + external_functions[ + "perform_enable_distributed_cache" + ] = perform_enable_distributed_cache + external_functions[ + "perform_disable_distributed_cache" + ] = perform_disable_distributed_cache external_functions["sanitize_loganalytics_ws_resource_id"] = sanitize_loganalytics_ws_resource_id # Override base module function with preview version that uses REST API to avoid # "Request Header Fields Too Large" errors @@ -5366,6 +5375,32 @@ def set_up_azure_container_storage(self, mc: ManagedCluster) -> ManagedCluster: enable_azure_container_storage_param = self.context.raw_param.get("enable_azure_container_storage") if enable_azure_container_storage_param: + from azext_aks_preview.azurecontainerstorage._helpers import is_distributed_cache_requested + + # Distributed cache installs the install controller only and does + # not go through the v1/v2 storage pool logic below. + if is_distributed_cache_requested(enable_azure_container_storage_param): + from azext_aks_preview.azurecontainerstorage._validators import ( + validate_enable_distributed_cache_params, + ) + validate_enable_distributed_cache_params( + enable_azure_container_storage_param, + False, + self.context.raw_param.get("storage_pool_name"), + self.context.raw_param.get("storage_pool_sku"), + self.context.raw_param.get("storage_pool_option"), + self.context.raw_param.get("storage_pool_size"), + self.context.raw_param.get("ephemeral_disk_volume_type"), + self.context.raw_param.get("ephemeral_disk_nvme_perf_tier"), + self.context.raw_param.get("container_storage_version"), + ) + self.context.set_intermediate( + "enable_distributed_cache", + True, + overwrite_exists=True, + ) + return mc + self.context.set_intermediate( "enable_azure_container_storage", enable_azure_container_storage_param, @@ -6033,6 +6068,10 @@ def check_is_postprocessing_required(self, mc: ManagedCluster) -> bool: "enable_azure_container_storage", default_value=False ) + enable_distributed_cache = self.context.get_intermediate( + "enable_distributed_cache", + default_value=False + ) enable_backup = self.context.raw_param.get("enable_backup", False) # pylint: disable=too-many-boolean-expressions @@ -6044,6 +6083,7 @@ def check_is_postprocessing_required(self, mc: ManagedCluster) -> bool: (enable_managed_identity and attach_acr) or need_grant_vnet_permission_to_cluster_identity or enable_azure_container_storage or + enable_distributed_cache or enable_backup ): return True @@ -6233,6 +6273,20 @@ def postprocessing_after_mc_created(self, cluster: ManagedCluster) -> None: # enable azure container storage enable_azure_container_storage = self.context.get_intermediate("enable_azure_container_storage") container_storage_version = self.context.get_intermediate("container_storage_version") + + # enable distributed cache (independent of the storage pool flow) + enable_distributed_cache = self.context.get_intermediate( + "enable_distributed_cache" + ) + if enable_distributed_cache: + self.context.external_functions.perform_enable_distributed_cache( + self.cmd, + self.context.get_resource_group_name(), + self.context.get_name(), + False, + is_called_from_extension=True, + ) + if enable_azure_container_storage: if container_storage_version is not None and container_storage_version == CONST_ACSTOR_VERSION_V1: if cluster.identity_profile is None or cluster.identity_profile["kubeletidentity"] is None: @@ -6752,6 +6806,123 @@ def update_azure_container_storage(self, mc: ManagedCluster) -> ManagedCluster: ) # pylint: disable=too-many-nested-blocks if enable_azure_container_storage_param is not None or disable_azure_container_storage_param is not None: + from azext_aks_preview.azurecontainerstorage._helpers import ( + is_distributed_cache_requested, + should_delete_extension, + get_container_storage_extension_installed, + ) + + # Distributed cache is enabled/disabled independently of the storage + # pool flow. Disable happens explicitly (`distributedcache`) or + # implicitly on a full teardown (bare `--disable...` or `all`). + dc_enable_requested = is_distributed_cache_requested(enable_azure_container_storage_param) + dc_disable_requested_explicit = is_distributed_cache_requested(disable_azure_container_storage_param) + disable_all_or_flag = should_delete_extension(disable_azure_container_storage_param) + + if dc_enable_requested or dc_disable_requested_explicit or disable_all_or_flag: + if enable_azure_container_storage_param is not None and \ + disable_azure_container_storage_param is not None: + raise MutuallyExclusiveArgumentError( + 'Conflicting flags. Cannot set --enable-azure-container-storage ' + 'and --disable-azure-container-storage together.' + ) + + try: + is_distributed_cache_installed, _ = get_container_storage_extension_installed( + self.cmd, + self.context.get_resource_group_name(), + self.context.get_name(), + CONST_DISTRIBUTED_CACHE_EXT_INSTALLATION_NAME, + ) + except Exception as ex: + raise UnknownError( + f"An error occurred while checking if distributed cache " + f"is installed on the cluster: {str(ex)}" + ) from ex + + storage_pool_name = self.context.raw_param.get("storage_pool_name") + pool_sku = self.context.raw_param.get("storage_pool_sku") + pool_option = self.context.raw_param.get("storage_pool_option") + pool_size = self.context.raw_param.get("storage_pool_size") + + if dc_enable_requested: + from azext_aks_preview.azurecontainerstorage._validators import ( + validate_enable_distributed_cache_params, + ) + validate_enable_distributed_cache_params( + enable_azure_container_storage_param, + is_distributed_cache_installed, + storage_pool_name, + pool_sku, + pool_option, + pool_size, + self.context.raw_param.get("ephemeral_disk_volume_type"), + self.context.raw_param.get("ephemeral_disk_nvme_perf_tier"), + self.context.raw_param.get("container_storage_version"), + ) + self.context.set_intermediate( + "enable_distributed_cache", True, overwrite_exists=True + ) + elif dc_disable_requested_explicit: + from azext_aks_preview.azurecontainerstorage._validators import ( + validate_disable_distributed_cache_params, + ) + validate_disable_distributed_cache_params( + disable_azure_container_storage_param, + is_distributed_cache_installed, + storage_pool_name, + pool_sku, + pool_option, + pool_size, + self.context.raw_param.get("container_storage_version"), + ) + self.context.set_intermediate( + "disable_distributed_cache", True, overwrite_exists=True + ) + elif disable_all_or_flag and is_distributed_cache_installed: + # Bare `--disable...` / `all` also tears down distributed cache. + self.context.set_intermediate( + "disable_distributed_cache", True, overwrite_exists=True + ) + + self.context.set_intermediate( + "is_distributed_cache_installed", is_distributed_cache_installed, overwrite_exists=True + ) + + # Explicit distributed cache operations do not touch the storage + # pool flow. + if dc_enable_requested or dc_disable_requested_explicit: + return mc + + # For a bare/all disable, only continue into the storage pool + # disable flow if a storage extension (v1 or v2) is installed. + try: + is_storage_v1_installed, _ = get_container_storage_extension_installed( + self.cmd, + self.context.get_resource_group_name(), + self.context.get_name(), + CONST_ACSTOR_V1_EXT_INSTALLATION_NAME, + ) + is_storage_v2_installed, _ = get_container_storage_extension_installed( + self.cmd, + self.context.get_resource_group_name(), + self.context.get_name(), + CONST_ACSTOR_EXT_INSTALLATION_NAME, + ) + except Exception as ex: + raise UnknownError( + f"An error occurred while checking if Azure Container Storage " + f"is installed on the cluster: {str(ex)}" + ) from ex + if not (is_storage_v1_installed or is_storage_v2_installed): + # Distributed-cache-only cluster: teardown already queued, + # nothing more to disable. + if is_distributed_cache_installed: + return mc + raise InvalidArgumentValueError( + 'Cannot disable Azure Container Storage as it could not be found on the cluster.' + ) + self.context.set_intermediate("container_storage_version", container_storage_version, overwrite_exists=True) enable_azure_container_storage_v1 = ( @@ -9146,6 +9317,12 @@ def check_is_postprocessing_required(self, mc: ManagedCluster) -> bool: disable_azure_container_storage = self.context.get_intermediate( "disable_azure_container_storage", default_value=False ) + enable_distributed_cache = self.context.get_intermediate( + "enable_distributed_cache", default_value=False + ) + disable_distributed_cache = self.context.get_intermediate( + "disable_distributed_cache", default_value=False + ) keyvault_id = self.context.get_keyvault_id() enable_azure_keyvault_secrets_provider_addon = self.context.get_enable_kv() or ( mc.addon_profiles and mc.addon_profiles.get(CONST_AZURE_KEYVAULT_SECRETS_PROVIDER_ADDON_NAME) @@ -9157,6 +9334,7 @@ def check_is_postprocessing_required(self, mc: ManagedCluster) -> bool: # Note: monitoring_addon_disable_postprocessing_required is no longer used - cleanup is done upfront # pylint: disable=too-many-boolean-expressions if (enable_azure_container_storage or disable_azure_container_storage) or \ + (enable_distributed_cache or disable_distributed_cache) or \ (keyvault_id and enable_azure_keyvault_secrets_provider_addon) or \ (monitoring_addon_postprocessing_required) or \ enable_backup: @@ -9241,6 +9419,31 @@ def postprocessing_after_mc_created(self, cluster: ManagedCluster) -> None: existing_ephemeral_nvme_perf_tier = self.context.get_intermediate("current_ephemeral_nvme_perf_tier") pool_option = self.context.raw_param.get("storage_pool_option") + # enable/disable distributed cache (independent of the storage pool flow) + enable_distributed_cache = self.context.get_intermediate( + "enable_distributed_cache" + ) + disable_distributed_cache = self.context.get_intermediate( + "disable_distributed_cache" + ) + is_distributed_cache_installed = self.context.get_intermediate("is_distributed_cache_installed") + if enable_distributed_cache: + self.context.external_functions.perform_enable_distributed_cache( + self.cmd, + self.context.get_resource_group_name(), + self.context.get_name(), + is_distributed_cache_installed, + is_called_from_extension=True, + ) + if disable_distributed_cache: + self.context.external_functions.perform_disable_distributed_cache( + self.cmd, + self.context.get_resource_group_name(), + self.context.get_name(), + is_distributed_cache_installed, + is_called_from_extension=True, + ) + # enable azure container storage if enable_azure_container_storage: if container_storage_version is not None and container_storage_version == CONST_ACSTOR_VERSION_V1: diff --git a/src/aks-preview/azext_aks_preview/tests/latest/test_validators.py b/src/aks-preview/azext_aks_preview/tests/latest/test_validators.py index 918f0fc4742..eda6a2cdd98 100644 --- a/src/aks-preview/azext_aks_preview/tests/latest/test_validators.py +++ b/src/aks-preview/azext_aks_preview/tests/latest/test_validators.py @@ -2001,6 +2001,132 @@ def test_enable_with_storagepool_size(self): self.assertEqual(str(cm.exception), err) +class TestValidateEnableDistributedCache(unittest.TestCase): + def test_enable_distributed_cache(self): + acstor_validator.validate_enable_distributed_cache_params( + acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE, + False, None, None, None, None, None, None, None, + ) + + def test_enable_when_already_installed(self): + with self.assertRaises(InvalidArgumentValueError) as cm: + acstor_validator.validate_enable_distributed_cache_params( + acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE, + True, None, None, None, None, None, None, None, + ) + err = ( + 'Cannot enable distributed cache as it is already enabled on the cluster.' + ) + self.assertEqual(str(cm.exception), err) + + def test_enable_combined_with_other_type(self): + other_type = acstor_consts.CONST_STORAGE_POOL_TYPE_EPHEMERAL_DISK + storage_types = [acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE, other_type] + with self.assertRaises(InvalidArgumentValueError) as cm: + acstor_validator.validate_enable_distributed_cache_params( + storage_types, False, None, None, None, None, None, None, None, + ) + err = ( + f"'{acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE}' cannot be combined with other storage " + f"options ('{other_type}'). Distributed cache is enabled independently. " + f"Please run --enable-azure-container-storage {acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE} " + "on its own." + ) + self.assertEqual(str(cm.exception), err) + + def test_enable_with_storage_pool_name(self): + storage_pool_name = "valid-name" + with self.assertRaises(InvalidArgumentValueError) as cm: + acstor_validator.validate_enable_distributed_cache_params( + acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE, + False, storage_pool_name, None, None, None, None, None, None, + ) + err = ( + '--storage-pool-name cannot be used with ' + '--enable-azure-container-storage distributedcache. ' + 'Distributed cache does not require or support any storage pool configuration. ' + 'Please remove these parameters and try again.' + ) + self.assertEqual(str(cm.exception), err) + + def test_enable_with_container_storage_version(self): + with self.assertRaises(InvalidArgumentValueError) as cm: + acstor_validator.validate_enable_distributed_cache_params( + acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE, + False, None, None, None, None, None, None, "1", + ) + err = ( + '--container-storage-version cannot be used with ' + '--enable-azure-container-storage distributedcache. ' + 'Distributed cache does not require or support any storage pool configuration. ' + 'Please remove these parameters and try again.' + ) + self.assertEqual(str(cm.exception), err) + + +class TestValidateDisableDistributedCache(unittest.TestCase): + def test_disable_distributed_cache(self): + acstor_validator.validate_disable_distributed_cache_params( + acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE, + True, None, None, None, None, None, + ) + + def test_disable_when_not_installed(self): + with self.assertRaises(InvalidArgumentValueError) as cm: + acstor_validator.validate_disable_distributed_cache_params( + acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE, + False, None, None, None, None, None, + ) + err = ( + 'Cannot disable distributed cache as it could not be found on the cluster.' + ) + self.assertEqual(str(cm.exception), err) + + def test_disable_combined_with_other_type(self): + other_type = acstor_consts.CONST_ACSTOR_ALL + storage_types = [acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE, other_type] + with self.assertRaises(InvalidArgumentValueError) as cm: + acstor_validator.validate_disable_distributed_cache_params( + storage_types, True, None, None, None, None, None, + ) + err = ( + f"'{acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE}' cannot be combined with other storage " + f"options ('{other_type}'). Distributed cache is disabled independently. " + f"Please run --disable-azure-container-storage {acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE} " + "on its own." + ) + self.assertEqual(str(cm.exception), err) + + def test_disable_with_storage_pool_name(self): + storage_pool_name = "valid-name" + with self.assertRaises(InvalidArgumentValueError) as cm: + acstor_validator.validate_disable_distributed_cache_params( + acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE, + True, storage_pool_name, None, None, None, None, + ) + err = ( + '--storage-pool-name cannot be used with ' + '--disable-azure-container-storage distributedcache. ' + 'Distributed cache does not require or support any storage pool configuration. ' + 'Please remove these parameters and try again.' + ) + self.assertEqual(str(cm.exception), err) + + def test_disable_with_container_storage_version(self): + with self.assertRaises(InvalidArgumentValueError) as cm: + acstor_validator.validate_disable_distributed_cache_params( + acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE, + True, None, None, None, None, "1", + ) + err = ( + '--container-storage-version cannot be used with ' + '--disable-azure-container-storage distributedcache. ' + 'Distributed cache does not require or support any storage pool configuration. ' + 'Please remove these parameters and try again.' + ) + self.assertEqual(str(cm.exception), err) + + class GatewayPrefixSizeSpace: def __init__(self, gateway_prefix_size=None, mode=None): self.gateway_prefix_size = gateway_prefix_size From 842d8c4eec1134064f056b388f67a7de67fee732 Mon Sep 17 00:00:00 2001 From: Roger Nhan Date: Mon, 14 Sep 2026 18:06:25 -0400 Subject: [PATCH 2/5] chore: update extension name to distributedaccelerator --- src/aks-preview/HISTORY.rst | 2 +- src/aks-preview/azext_aks_preview/_params.py | 12 +- .../azurecontainerstorage/_consts.py | 10 +- .../azurecontainerstorage/_helpers.py | 10 +- .../azurecontainerstorage/_validators.py | 36 ++-- .../azurecontainerstorage/acstor_ops.py | 44 ++--- .../managed_cluster_decorator.py | 120 +++++++------- .../tests/latest/test_aks_commands.py | 154 +++++++++++++++++- .../tests/latest/test_validators.py | 80 ++++----- 9 files changed, 310 insertions(+), 158 deletions(-) diff --git a/src/aks-preview/HISTORY.rst b/src/aks-preview/HISTORY.rst index 89d9e256c90..5be058b099d 100644 --- a/src/aks-preview/HISTORY.rst +++ b/src/aks-preview/HISTORY.rst @@ -11,7 +11,7 @@ To release a new version, please select a new version number (usually plus 1 to Pending +++++++ -* `az aks create/update`: Add `distributedAccelerator` storage option to `--enable-azure-container-storage` and `--disable-azure-container-storage` to install/uninstall the Azure Container Storage distributed accelerator cache controller. +* `az aks create/update`: Add `distributedAccelerator` storage option to `--enable-azure-container-storage` and `--disable-azure-container-storage` to install/uninstall the Azure Container Storage distributed accelerator controller. 22.0.0b9 +++++++++ diff --git a/src/aks-preview/azext_aks_preview/_params.py b/src/aks-preview/azext_aks_preview/_params.py index bf6ffc3ef97..c8eeb6f9b1c 100644 --- a/src/aks-preview/azext_aks_preview/_params.py +++ b/src/aks-preview/azext_aks_preview/_params.py @@ -280,7 +280,7 @@ CONST_STORAGE_POOL_TYPE_AZURE_DISK, CONST_STORAGE_POOL_TYPE_EPHEMERAL_DISK, CONST_STORAGE_POOL_TYPE_ELASTIC_SAN, - CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE, + CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, CONST_STORAGE_POOL_SKU_PREMIUM_LRS, CONST_STORAGE_POOL_SKU_STANDARD_LRS, CONST_STORAGE_POOL_SKU_STANDARDSSD_LRS, @@ -530,14 +530,14 @@ def _deprecate_option(c, target, redirect): CONST_STORAGE_POOL_TYPE_AZURE_DISK, CONST_STORAGE_POOL_TYPE_EPHEMERAL_DISK, CONST_STORAGE_POOL_TYPE_ELASTIC_SAN, - CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE, + CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, ] disable_storage_pool_types = [ CONST_STORAGE_POOL_TYPE_AZURE_DISK, CONST_STORAGE_POOL_TYPE_EPHEMERAL_DISK, CONST_STORAGE_POOL_TYPE_ELASTIC_SAN, - CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE, + CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, CONST_ACSTOR_ALL, ] @@ -1297,7 +1297,7 @@ def load_arguments(self, _): "enable_azure_container_storage", arg_type=_get_container_storage_enum_type(storage_pool_types), help="enable azure container storage. Can be used as a flag (defaults to True) or with a" - " storage pool type value: (azureDisk, ephemeralDisk, elasticSan, distributedcache)", + " storage pool type value: (azureDisk, ephemeralDisk, elasticSan, distributedaccelerator)", ) c.argument( "container_storage_version", @@ -2045,14 +2045,14 @@ def load_arguments(self, _): "enable_azure_container_storage", arg_type=_get_container_storage_enum_type(storage_pool_types), help="enable azure container storage. Can be used as a flag (defaults to True) or with a" - " storage pool type value: (azureDisk, ephemeralDisk, elasticSan, distributedcache)", + " storage pool type value: (azureDisk, ephemeralDisk, elasticSan, distributedaccelerator)", ) c.argument( "disable_azure_container_storage", arg_type=_get_container_storage_enum_type(disable_storage_pool_types), help="disable azure container storage or any one of the storage types." " Can be used as a flag (defaults to True) or with a storage type value:" - " azureDisk, ephemeralDisk, elasticSan, distributedcache, all (to disable all storage types).", + " azureDisk, ephemeralDisk, elasticSan, distributedaccelerator, all (to disable all storage types).", ) c.argument( "container_storage_version", diff --git a/src/aks-preview/azext_aks_preview/azurecontainerstorage/_consts.py b/src/aks-preview/azext_aks_preview/azurecontainerstorage/_consts.py index fe634e345d7..6033075d112 100644 --- a/src/aks-preview/azext_aks_preview/azurecontainerstorage/_consts.py +++ b/src/aks-preview/azext_aks_preview/azurecontainerstorage/_consts.py @@ -17,10 +17,10 @@ CONST_ACSTOR_EXT_INSTALLATION_NAME = "acstor" CONST_ACSTOR_EXT_INSTALLATION_NAMESPACE = "kube-system" CONST_ACSTOR_K8S_EXTENSION_NAME = "microsoft.azurecontainerstoragev2" -# Distributed cache (Distributed Accelerator for Cloud Storage) install controller. -CONST_DISTRIBUTED_CACHE_EXT_INSTALLATION_NAME = "distributedcache" -CONST_DISTRIBUTED_CACHE_EXT_INSTALLATION_NAMESPACE = "kube-system" -CONST_DISTRIBUTED_CACHE_K8S_EXTENSION_NAME = "microsoft.dacs" +# Distributed accelerator (Distributed Accelerator for Cloud Storage) install controller. +CONST_DISTRIBUTED_ACCELERATOR_EXT_INSTALLATION_NAME = "distributedaccelerator" +CONST_DISTRIBUTED_ACCELERATOR_EXT_INSTALLATION_NAMESPACE = "kube-system" +CONST_DISTRIBUTED_ACCELERATOR_K8S_EXTENSION_NAME = "microsoft.distributedaccelerator" CONST_K8S_EXTENSION_CLIENT_FACTORY_MOD_NAME = "azext_k8s_extension._client_factory" CONST_K8S_EXTENSION_CUSTOM_MOD_NAME = "azext_k8s_extension.custom" CONST_K8S_EXTENSION_NAME = "k8s-extension" @@ -39,4 +39,4 @@ CONST_STORAGE_POOL_TYPE_AZURE_DISK = "azureDisk" CONST_STORAGE_POOL_TYPE_ELASTIC_SAN = "elasticSan" CONST_STORAGE_POOL_TYPE_EPHEMERAL_DISK = "ephemeralDisk" -CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE = "distributedcache" +CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR = "distributedaccelerator" diff --git a/src/aks-preview/azext_aks_preview/azurecontainerstorage/_helpers.py b/src/aks-preview/azext_aks_preview/azurecontainerstorage/_helpers.py index 21e7ea655fe..f0c5388152c 100644 --- a/src/aks-preview/azext_aks_preview/azurecontainerstorage/_helpers.py +++ b/src/aks-preview/azext_aks_preview/azurecontainerstorage/_helpers.py @@ -23,7 +23,7 @@ CONST_STORAGE_POOL_TYPE_AZURE_DISK, CONST_STORAGE_POOL_TYPE_ELASTIC_SAN, CONST_STORAGE_POOL_TYPE_EPHEMERAL_DISK, - CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE, + CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, CONST_ACSTOR_V1_K8S_EXTENSION_NAME, CONST_ACSTOR_V1_EXT_INSTALLATION_NAME, ) @@ -305,13 +305,13 @@ def should_delete_extension(storage_options_to_remove) -> bool: ) -def is_distributed_cache_requested(storage_options) -> bool: - # Detect whether distributed cache is among the requested storage options. +def is_distributed_accelerator_requested(storage_options) -> bool: + # Detect whether distributed accelerator is among the requested storage options. if storage_options is None or storage_options is True: return False if isinstance(storage_options, list): - return CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE in storage_options - return storage_options == CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE + return CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR in storage_options + return storage_options == CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR def get_container_storage_extension_installed( diff --git a/src/aks-preview/azext_aks_preview/azurecontainerstorage/_validators.py b/src/aks-preview/azext_aks_preview/azurecontainerstorage/_validators.py index c0f1749a4ec..85722478650 100644 --- a/src/aks-preview/azext_aks_preview/azurecontainerstorage/_validators.py +++ b/src/aks-preview/azext_aks_preview/azurecontainerstorage/_validators.py @@ -21,7 +21,7 @@ CONST_STORAGE_POOL_TYPE_AZURE_DISK, CONST_STORAGE_POOL_TYPE_ELASTIC_SAN, CONST_STORAGE_POOL_TYPE_EPHEMERAL_DISK, - CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE, + CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, ) from azext_aks_preview.azurecontainerstorage._helpers import ( get_vm_sku_details @@ -572,7 +572,7 @@ def validate_disable_azure_container_storage_params( ) -def validate_enable_distributed_cache_params( +def validate_enable_distributed_accelerator_params( enablement_option, is_extension_installed, storage_pool_name, @@ -583,25 +583,25 @@ def validate_enable_distributed_cache_params( ephemeral_disk_nvme_perf_tier, container_storage_version=None, ): - # Distributed cache has no storage pool construct, so none of the storage + # Distributed accelerator has no storage pool construct, so none of the storage # pool parameters are supported. enablement_option_arr = enablement_option if isinstance(enablement_option, list) else [enablement_option] other_pool_types = [ opt for opt in enablement_option_arr - if opt != CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE + if opt != CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR ] if other_pool_types: options_display = "', '".join(other_pool_types) raise InvalidArgumentValueError( - f"'{CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE}' cannot be combined with other storage " - f"options ('{options_display}'). Distributed cache is enabled independently. " - f"Please run --enable-azure-container-storage {CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE} " + f"'{CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR}' cannot be combined with other storage " + f"options ('{options_display}'). Distributed accelerator is enabled independently. " + f"Please run --enable-azure-container-storage {CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR} " "on its own." ) if is_extension_installed: raise InvalidArgumentValueError( - 'Cannot enable distributed cache as it is already enabled on the cluster.' + 'Cannot enable distributed accelerator as it is already enabled on the cluster.' ) unsupported_params = [] @@ -624,13 +624,13 @@ def validate_enable_distributed_cache_params( params_defined = ', '.join(unsupported_params) raise InvalidArgumentValueError( f'{params_defined} cannot be used with ' - f'--enable-azure-container-storage {CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE}. ' - 'Distributed cache does not require or support any storage pool configuration. ' + f'--enable-azure-container-storage {CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR}. ' + 'Distributed accelerator does not require or support any storage pool configuration. ' 'Please remove these parameters and try again.' ) -def validate_disable_distributed_cache_params( +def validate_disable_distributed_accelerator_params( disablement_option, is_extension_installed, storage_pool_name, @@ -642,20 +642,20 @@ def validate_disable_distributed_cache_params( disablement_option_arr = disablement_option if isinstance(disablement_option, list) else [disablement_option] other_pool_types = [ opt for opt in disablement_option_arr - if opt != CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE + if opt != CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR ] if other_pool_types: options_display = "', '".join(other_pool_types) raise InvalidArgumentValueError( - f"'{CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE}' cannot be combined with other storage " - f"options ('{options_display}'). Distributed cache is disabled independently. " - f"Please run --disable-azure-container-storage {CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE} " + f"'{CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR}' cannot be combined with other storage " + f"options ('{options_display}'). Distributed accelerator is disabled independently. " + f"Please run --disable-azure-container-storage {CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR} " "on its own." ) if not is_extension_installed: raise InvalidArgumentValueError( - 'Cannot disable distributed cache as it could not be found on the cluster.' + 'Cannot disable distributed accelerator as it could not be found on the cluster.' ) unsupported_params = [] @@ -674,8 +674,8 @@ def validate_disable_distributed_cache_params( params_defined = ', '.join(unsupported_params) raise InvalidArgumentValueError( f'{params_defined} cannot be used with ' - f'--disable-azure-container-storage {CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE}. ' - 'Distributed cache does not require or support any storage pool configuration. ' + f'--disable-azure-container-storage {CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR}. ' + 'Distributed accelerator does not require or support any storage pool configuration. ' 'Please remove these parameters and try again.' ) diff --git a/src/aks-preview/azext_aks_preview/azurecontainerstorage/acstor_ops.py b/src/aks-preview/azext_aks_preview/azurecontainerstorage/acstor_ops.py index 9a5920e58e2..ffa25a168ca 100644 --- a/src/aks-preview/azext_aks_preview/azurecontainerstorage/acstor_ops.py +++ b/src/aks-preview/azext_aks_preview/azurecontainerstorage/acstor_ops.py @@ -12,9 +12,9 @@ CONST_ACSTOR_EXT_INSTALLATION_NAME, CONST_ACSTOR_EXT_INSTALLATION_NAMESPACE, CONST_ACSTOR_K8S_EXTENSION_NAME, - CONST_DISTRIBUTED_CACHE_EXT_INSTALLATION_NAME, - CONST_DISTRIBUTED_CACHE_EXT_INSTALLATION_NAMESPACE, - CONST_DISTRIBUTED_CACHE_K8S_EXTENSION_NAME, + CONST_DISTRIBUTED_ACCELERATOR_EXT_INSTALLATION_NAME, + CONST_DISTRIBUTED_ACCELERATOR_EXT_INSTALLATION_NAMESPACE, + CONST_DISTRIBUTED_ACCELERATOR_K8S_EXTENSION_NAME, CONST_DISK_TYPE_EPHEMERAL_VOLUME_ONLY, CONST_DISK_TYPE_PV_WITH_ANNOTATION, CONST_EPHEMERAL_NVME_PERF_TIER_STANDARD, @@ -802,7 +802,7 @@ def perform_azure_container_storage_update( ) from delete_ex -def perform_enable_distributed_cache( +def perform_enable_distributed_accelerator( cmd, resource_group, cluster_name, @@ -811,7 +811,7 @@ def perform_enable_distributed_cache( ): # This will be set true only when aks-preview extension is used # and we want the aks-preview ManagedClusterDecorator to call the - # perform_enable_distributed_cache function. + # perform_enable_distributed_accelerator function. if not is_called_from_extension: return @@ -822,7 +822,7 @@ def perform_enable_distributed_cache( k8s_extension_custom_mod = get_k8s_extension_module(CONST_K8S_EXTENSION_CUSTOM_MOD_NAME) if is_extension_installed: - logger.warning("Distributed cache is already enabled on the cluster.") + logger.warning("Distributed accelerator is already enabled on the cluster.") return try: @@ -831,43 +831,43 @@ def perform_enable_distributed_cache( client, resource_group, cluster_name, - CONST_DISTRIBUTED_CACHE_EXT_INSTALLATION_NAME, + CONST_DISTRIBUTED_ACCELERATOR_EXT_INSTALLATION_NAME, "managedClusters", - CONST_DISTRIBUTED_CACHE_K8S_EXTENSION_NAME, + CONST_DISTRIBUTED_ACCELERATOR_K8S_EXTENSION_NAME, auto_upgrade_minor_version=True, release_train="stable", scope="cluster", - release_namespace=CONST_DISTRIBUTED_CACHE_EXT_INSTALLATION_NAMESPACE, + release_namespace=CONST_DISTRIBUTED_ACCELERATOR_EXT_INSTALLATION_NAMESPACE, ) long_op_result = LongRunningOperation(cmd.cli_ctx)(result) if long_op_result.provisioning_state == "Succeeded": - logger.warning("Distributed cache successfully installed") + logger.warning("Distributed accelerator successfully installed") except Exception as ex: # pylint: disable=broad-except - logger.error("Distributed cache failed to install.\nError: %s", ex) - logger.warning("Cleaning up the cluster by disabling distributed cache") + logger.error("Distributed accelerator failed to install.\nError: %s", ex) + logger.warning("Cleaning up the cluster by disabling distributed accelerator") try: delete_op_result = k8s_extension_custom_mod.delete_k8s_extension( cmd, client, resource_group, cluster_name, - CONST_DISTRIBUTED_CACHE_EXT_INSTALLATION_NAME, + CONST_DISTRIBUTED_ACCELERATOR_EXT_INSTALLATION_NAME, "managedClusters", yes=True, ) LongRunningOperation(cmd.cli_ctx)(delete_op_result) logger.warning( - "Please retry enabling distributed cache by running " + "Please retry enabling distributed accelerator by running " "`az aks update` along with " - "`--enable-azure-container-storage distributedcache`" + "`--enable-azure-container-storage distributedaccelerator`" ) except Exception as delete_ex: # pylint: disable=broad-except raise UnknownError( - "Failed to clean up distributed cache with error: %s" % delete_ex + "Failed to clean up distributed accelerator with error: %s" % delete_ex ) from delete_ex -def perform_disable_distributed_cache( +def perform_disable_distributed_accelerator( cmd, resource_group, cluster_name, @@ -876,7 +876,7 @@ def perform_disable_distributed_cache( ): # This will be set true only when aks-preview extension is used # and we want the aks-preview ManagedClusterDecorator to call the - # perform_disable_distributed_cache function. + # perform_disable_distributed_accelerator function. if not is_called_from_extension: return @@ -885,7 +885,7 @@ def perform_disable_distributed_cache( k8s_extension_custom_mod = get_k8s_extension_module(CONST_K8S_EXTENSION_CUSTOM_MOD_NAME) if not is_extension_installed: - logger.warning("Distributed cache is not enabled on the cluster.") + logger.warning("Distributed accelerator is not enabled on the cluster.") return # Deleting the install controller triggers removal of the remaining cache @@ -896,13 +896,13 @@ def perform_disable_distributed_cache( client, resource_group, cluster_name, - CONST_DISTRIBUTED_CACHE_EXT_INSTALLATION_NAME, + CONST_DISTRIBUTED_ACCELERATOR_EXT_INSTALLATION_NAME, "managedClusters", yes=True, ) LongRunningOperation(cmd.cli_ctx)(delete_op_result) - logger.warning("Distributed cache has been disabled.") + logger.warning("Distributed accelerator has been disabled.") except Exception as delete_ex: # pylint: disable=broad-except raise UnknownError( - "Failed to disable distributed cache with error: %s" % delete_ex + "Failed to disable distributed accelerator with error: %s" % delete_ex ) from delete_ex diff --git a/src/aks-preview/azext_aks_preview/managed_cluster_decorator.py b/src/aks-preview/azext_aks_preview/managed_cluster_decorator.py index 959c7c95397..270ab62fe29 100644 --- a/src/aks-preview/azext_aks_preview/managed_cluster_decorator.py +++ b/src/aks-preview/azext_aks_preview/managed_cluster_decorator.py @@ -60,7 +60,7 @@ CONST_ACSTOR_EXT_INSTALLATION_NAME, CONST_ACSTOR_V1_EXT_INSTALLATION_NAME, CONST_ACSTOR_VERSION_V1, - CONST_DISTRIBUTED_CACHE_EXT_INSTALLATION_NAME, + CONST_DISTRIBUTED_ACCELERATOR_EXT_INSTALLATION_NAME, ) from azext_aks_preview._helpers import ( check_is_apiserver_vnet_integration_cluster, @@ -96,8 +96,8 @@ perform_disable_azure_container_storage_v1, perform_enable_azure_container_storage_v1, perform_azure_container_storage_update, - perform_enable_distributed_cache, - perform_disable_distributed_cache, + perform_enable_distributed_accelerator, + perform_disable_distributed_accelerator, ) from azext_aks_preview.azuremonitormetrics.azuremonitorprofile import ( ensure_azure_monitor_profile_prerequisites, @@ -295,11 +295,11 @@ def external_functions(self) -> SimpleNamespace: ] = perform_disable_azure_container_storage_v1 external_functions["perform_azure_container_storage_update"] = perform_azure_container_storage_update external_functions[ - "perform_enable_distributed_cache" - ] = perform_enable_distributed_cache + "perform_enable_distributed_accelerator" + ] = perform_enable_distributed_accelerator external_functions[ - "perform_disable_distributed_cache" - ] = perform_disable_distributed_cache + "perform_disable_distributed_accelerator" + ] = perform_disable_distributed_accelerator external_functions["sanitize_loganalytics_ws_resource_id"] = sanitize_loganalytics_ws_resource_id # Override base module function with preview version that uses REST API to avoid # "Request Header Fields Too Large" errors @@ -5375,15 +5375,15 @@ def set_up_azure_container_storage(self, mc: ManagedCluster) -> ManagedCluster: enable_azure_container_storage_param = self.context.raw_param.get("enable_azure_container_storage") if enable_azure_container_storage_param: - from azext_aks_preview.azurecontainerstorage._helpers import is_distributed_cache_requested + from azext_aks_preview.azurecontainerstorage._helpers import is_distributed_accelerator_requested - # Distributed cache installs the install controller only and does + # Distributed accelerator installs the install controller only and does # not go through the v1/v2 storage pool logic below. - if is_distributed_cache_requested(enable_azure_container_storage_param): + if is_distributed_accelerator_requested(enable_azure_container_storage_param): from azext_aks_preview.azurecontainerstorage._validators import ( - validate_enable_distributed_cache_params, + validate_enable_distributed_accelerator_params, ) - validate_enable_distributed_cache_params( + validate_enable_distributed_accelerator_params( enable_azure_container_storage_param, False, self.context.raw_param.get("storage_pool_name"), @@ -5395,7 +5395,7 @@ def set_up_azure_container_storage(self, mc: ManagedCluster) -> ManagedCluster: self.context.raw_param.get("container_storage_version"), ) self.context.set_intermediate( - "enable_distributed_cache", + "enable_distributed_accelerator", True, overwrite_exists=True, ) @@ -6068,8 +6068,8 @@ def check_is_postprocessing_required(self, mc: ManagedCluster) -> bool: "enable_azure_container_storage", default_value=False ) - enable_distributed_cache = self.context.get_intermediate( - "enable_distributed_cache", + enable_distributed_accelerator = self.context.get_intermediate( + "enable_distributed_accelerator", default_value=False ) enable_backup = self.context.raw_param.get("enable_backup", False) @@ -6083,7 +6083,7 @@ def check_is_postprocessing_required(self, mc: ManagedCluster) -> bool: (enable_managed_identity and attach_acr) or need_grant_vnet_permission_to_cluster_identity or enable_azure_container_storage or - enable_distributed_cache or + enable_distributed_accelerator or enable_backup ): return True @@ -6274,12 +6274,12 @@ def postprocessing_after_mc_created(self, cluster: ManagedCluster) -> None: enable_azure_container_storage = self.context.get_intermediate("enable_azure_container_storage") container_storage_version = self.context.get_intermediate("container_storage_version") - # enable distributed cache (independent of the storage pool flow) - enable_distributed_cache = self.context.get_intermediate( - "enable_distributed_cache" + # enable distributed accelerator (independent of the storage pool flow) + enable_distributed_accelerator = self.context.get_intermediate( + "enable_distributed_accelerator" ) - if enable_distributed_cache: - self.context.external_functions.perform_enable_distributed_cache( + if enable_distributed_accelerator: + self.context.external_functions.perform_enable_distributed_accelerator( self.cmd, self.context.get_resource_group_name(), self.context.get_name(), @@ -6807,16 +6807,16 @@ def update_azure_container_storage(self, mc: ManagedCluster) -> ManagedCluster: # pylint: disable=too-many-nested-blocks if enable_azure_container_storage_param is not None or disable_azure_container_storage_param is not None: from azext_aks_preview.azurecontainerstorage._helpers import ( - is_distributed_cache_requested, + is_distributed_accelerator_requested, should_delete_extension, get_container_storage_extension_installed, ) - # Distributed cache is enabled/disabled independently of the storage - # pool flow. Disable happens explicitly (`distributedcache`) or + # Distributed accelerator is enabled/disabled independently of the storage + # pool flow. Disable happens explicitly (`distributedaccelerator`) or # implicitly on a full teardown (bare `--disable...` or `all`). - dc_enable_requested = is_distributed_cache_requested(enable_azure_container_storage_param) - dc_disable_requested_explicit = is_distributed_cache_requested(disable_azure_container_storage_param) + dc_enable_requested = is_distributed_accelerator_requested(enable_azure_container_storage_param) + dc_disable_requested_explicit = is_distributed_accelerator_requested(disable_azure_container_storage_param) disable_all_or_flag = should_delete_extension(disable_azure_container_storage_param) if dc_enable_requested or dc_disable_requested_explicit or disable_all_or_flag: @@ -6828,15 +6828,15 @@ def update_azure_container_storage(self, mc: ManagedCluster) -> ManagedCluster: ) try: - is_distributed_cache_installed, _ = get_container_storage_extension_installed( + is_distributed_accelerator_installed, _ = get_container_storage_extension_installed( self.cmd, self.context.get_resource_group_name(), self.context.get_name(), - CONST_DISTRIBUTED_CACHE_EXT_INSTALLATION_NAME, + CONST_DISTRIBUTED_ACCELERATOR_EXT_INSTALLATION_NAME, ) except Exception as ex: raise UnknownError( - f"An error occurred while checking if distributed cache " + f"An error occurred while checking if distributed accelerator " f"is installed on the cluster: {str(ex)}" ) from ex @@ -6847,11 +6847,11 @@ def update_azure_container_storage(self, mc: ManagedCluster) -> ManagedCluster: if dc_enable_requested: from azext_aks_preview.azurecontainerstorage._validators import ( - validate_enable_distributed_cache_params, + validate_enable_distributed_accelerator_params, ) - validate_enable_distributed_cache_params( + validate_enable_distributed_accelerator_params( enable_azure_container_storage_param, - is_distributed_cache_installed, + is_distributed_accelerator_installed, storage_pool_name, pool_sku, pool_option, @@ -6861,15 +6861,15 @@ def update_azure_container_storage(self, mc: ManagedCluster) -> ManagedCluster: self.context.raw_param.get("container_storage_version"), ) self.context.set_intermediate( - "enable_distributed_cache", True, overwrite_exists=True + "enable_distributed_accelerator", True, overwrite_exists=True ) elif dc_disable_requested_explicit: from azext_aks_preview.azurecontainerstorage._validators import ( - validate_disable_distributed_cache_params, + validate_disable_distributed_accelerator_params, ) - validate_disable_distributed_cache_params( + validate_disable_distributed_accelerator_params( disable_azure_container_storage_param, - is_distributed_cache_installed, + is_distributed_accelerator_installed, storage_pool_name, pool_sku, pool_option, @@ -6877,19 +6877,19 @@ def update_azure_container_storage(self, mc: ManagedCluster) -> ManagedCluster: self.context.raw_param.get("container_storage_version"), ) self.context.set_intermediate( - "disable_distributed_cache", True, overwrite_exists=True + "disable_distributed_accelerator", True, overwrite_exists=True ) - elif disable_all_or_flag and is_distributed_cache_installed: - # Bare `--disable...` / `all` also tears down distributed cache. + elif disable_all_or_flag and is_distributed_accelerator_installed: + # Bare `--disable...` / `all` also tears down distributed accelerator. self.context.set_intermediate( - "disable_distributed_cache", True, overwrite_exists=True + "disable_distributed_accelerator", True, overwrite_exists=True ) self.context.set_intermediate( - "is_distributed_cache_installed", is_distributed_cache_installed, overwrite_exists=True + "is_distributed_accelerator_installed", is_distributed_accelerator_installed, overwrite_exists=True ) - # Explicit distributed cache operations do not touch the storage + # Explicit distributed accelerator operations do not touch the storage # pool flow. if dc_enable_requested or dc_disable_requested_explicit: return mc @@ -6917,7 +6917,7 @@ def update_azure_container_storage(self, mc: ManagedCluster) -> ManagedCluster: if not (is_storage_v1_installed or is_storage_v2_installed): # Distributed-cache-only cluster: teardown already queued, # nothing more to disable. - if is_distributed_cache_installed: + if is_distributed_accelerator_installed: return mc raise InvalidArgumentValueError( 'Cannot disable Azure Container Storage as it could not be found on the cluster.' @@ -9317,11 +9317,11 @@ def check_is_postprocessing_required(self, mc: ManagedCluster) -> bool: disable_azure_container_storage = self.context.get_intermediate( "disable_azure_container_storage", default_value=False ) - enable_distributed_cache = self.context.get_intermediate( - "enable_distributed_cache", default_value=False + enable_distributed_accelerator = self.context.get_intermediate( + "enable_distributed_accelerator", default_value=False ) - disable_distributed_cache = self.context.get_intermediate( - "disable_distributed_cache", default_value=False + disable_distributed_accelerator = self.context.get_intermediate( + "disable_distributed_accelerator", default_value=False ) keyvault_id = self.context.get_keyvault_id() enable_azure_keyvault_secrets_provider_addon = self.context.get_enable_kv() or ( @@ -9334,7 +9334,7 @@ def check_is_postprocessing_required(self, mc: ManagedCluster) -> bool: # Note: monitoring_addon_disable_postprocessing_required is no longer used - cleanup is done upfront # pylint: disable=too-many-boolean-expressions if (enable_azure_container_storage or disable_azure_container_storage) or \ - (enable_distributed_cache or disable_distributed_cache) or \ + (enable_distributed_accelerator or disable_distributed_accelerator) or \ (keyvault_id and enable_azure_keyvault_secrets_provider_addon) or \ (monitoring_addon_postprocessing_required) or \ enable_backup: @@ -9419,28 +9419,28 @@ def postprocessing_after_mc_created(self, cluster: ManagedCluster) -> None: existing_ephemeral_nvme_perf_tier = self.context.get_intermediate("current_ephemeral_nvme_perf_tier") pool_option = self.context.raw_param.get("storage_pool_option") - # enable/disable distributed cache (independent of the storage pool flow) - enable_distributed_cache = self.context.get_intermediate( - "enable_distributed_cache" + # enable/disable distributed accelerator (independent of the storage pool flow) + enable_distributed_accelerator = self.context.get_intermediate( + "enable_distributed_accelerator" ) - disable_distributed_cache = self.context.get_intermediate( - "disable_distributed_cache" + disable_distributed_accelerator = self.context.get_intermediate( + "disable_distributed_accelerator" ) - is_distributed_cache_installed = self.context.get_intermediate("is_distributed_cache_installed") - if enable_distributed_cache: - self.context.external_functions.perform_enable_distributed_cache( + is_distributed_accelerator_installed = self.context.get_intermediate("is_distributed_accelerator_installed") + if enable_distributed_accelerator: + self.context.external_functions.perform_enable_distributed_accelerator( self.cmd, self.context.get_resource_group_name(), self.context.get_name(), - is_distributed_cache_installed, + is_distributed_accelerator_installed, is_called_from_extension=True, ) - if disable_distributed_cache: - self.context.external_functions.perform_disable_distributed_cache( + if disable_distributed_accelerator: + self.context.external_functions.perform_disable_distributed_accelerator( self.cmd, self.context.get_resource_group_name(), self.context.get_name(), - is_distributed_cache_installed, + is_distributed_accelerator_installed, is_called_from_extension=True, ) diff --git a/src/aks-preview/azext_aks_preview/tests/latest/test_aks_commands.py b/src/aks-preview/azext_aks_preview/tests/latest/test_aks_commands.py index 98d8ca0a5b9..f9294333640 100644 --- a/src/aks-preview/azext_aks_preview/tests/latest/test_aks_commands.py +++ b/src/aks-preview/azext_aks_preview/tests/latest/test_aks_commands.py @@ -32,7 +32,12 @@ from azure.cli.testsdk.scenario_tests import AllowLargeResponse from azure.core.exceptions import HttpResponseError from knack.util import CLIError -from azext_aks_preview.azurecontainerstorage._consts import (CONST_ACSTOR_EXT_INSTALLATION_NAME, CONST_ACSTOR_K8S_EXTENSION_NAME) +from azext_aks_preview.azurecontainerstorage._consts import ( + CONST_ACSTOR_EXT_INSTALLATION_NAME, + CONST_ACSTOR_K8S_EXTENSION_NAME, + CONST_DISTRIBUTED_ACCELERATOR_EXT_INSTALLATION_NAME, + CONST_DISTRIBUTED_ACCELERATOR_K8S_EXTENSION_NAME, +) from .test_localdns_profile import assert_dns_overrides_equal, vnetDnsOverridesExpected, kubeDnsOverridesExpected, vnetDnsOverridesExpectedDefault, kubeDnsOverridesExpectedDefault @@ -16997,6 +17002,153 @@ def test_aks_update_with_azurecontainerstorage(self, resource_group, resource_gr self.is_empty(), ]) + @live_only() + @AllowLargeResponse(99999) + @AKSCustomResourceGroupPreparer( + random_name_length=17, name_prefix="clitest", location="uksouth" + ) + def test_aks_create_with_azurecontainerstorage_distributedaccelerator(self, resource_group, resource_group_location): + + # reset the count so in replay mode the random names will start with 0 + self.test_resources_count = 0 + # kwargs for string formatting + aks_name = self.create_random_name("cliakstest", 16) + + node_vm_size = "Standard_D4s_v4" + self.kwargs.update( + { + "resource_group": resource_group, + "name": aks_name, + "location": resource_group_location, + "resource_type": "Microsoft.ContainerService/ManagedClusters", + "ssh_key_value": self.generate_ssh_keys(), + "node_vm_size": node_vm_size, + } + ) + + # add k8s-extension extension for azurecontainerstorage operations. + self.cmd("extension add --name k8s-extension") + + create_cmd = ( + "aks create --resource-group={resource_group} --name={name} --location={location} " + "--ssh-key-value={ssh_key_value} --node-vm-size={node_vm_size} " + "--node-count 3 --enable-managed-identity " + "--enable-azure-container-storage distributedaccelerator --output=json" + ) + + self.cmd( + create_cmd, + checks=[ + self.check("provisioningState", "Succeeded"), + ], + ) + + # Verify that the distributed accelerator extension is installed + extension_list_cmd = "k8s-extension list --resource-group={resource_group} --cluster-name={name} --cluster-type managedClusters" + extensions = self.cmd(extension_list_cmd).get_output_in_json() + + # Check if distributed accelerator extension exists + dacs_extension_found = False + for extension in extensions: + if extension.get("name") == CONST_DISTRIBUTED_ACCELERATOR_EXT_INSTALLATION_NAME: + dacs_extension_found = True + # Additional checks on the extension properties + assert extension.get("provisioningState") == "Succeeded", "Extension provisioning failed" + assert extension.get("extensionType") == CONST_DISTRIBUTED_ACCELERATOR_K8S_EXTENSION_NAME, "Wrong extension type" + break + + assert dacs_extension_found, "Distributed accelerator extension not found" + + # delete + cmd = ( + "aks delete --resource-group={resource_group} --name={name} --yes --no-wait" + ) + self.cmd( + cmd, + checks=[ + self.is_empty(), + ], + ) + + @live_only() + @AllowLargeResponse(99999) + @AKSCustomResourceGroupPreparer(random_name_length=17, name_prefix='clitest', location='ukwest') + def test_aks_update_with_azurecontainerstorage_distributedaccelerator(self, resource_group, resource_group_location): + + aks_name = self.create_random_name('cliakstest', 16) + node_vm_size = 'Standard_D4s_v4' + self.kwargs.update({ + 'resource_group': resource_group, + 'name': aks_name, + 'location': resource_group_location, + 'ssh_key_value': self.generate_ssh_keys(), + 'node_vm_size': node_vm_size, + }) + + # add k8s-extension extension for azurecontainerstorage operations. + self.cmd('extension add --name k8s-extension') + + # create: without enable-azure-container-storage + create_cmd = 'aks create --resource-group={resource_group} --name={name} --location={location} --ssh-key-value={ssh_key_value} --node-vm-size={node_vm_size} --node-count 3 --enable-managed-identity --output=json' + self.cmd(create_cmd, checks=[ + self.check('provisioningState', 'Succeeded'), + ]) + + # update: enable distributed accelerator + update_cmd = 'aks update --resource-group={resource_group} --name={name} --yes --output=json ' \ + '--enable-azure-container-storage distributedaccelerator' + + self.cmd(update_cmd, checks=[ + self.check('provisioningState', 'Succeeded'), + ]) + + # Verify that the distributed accelerator extension is installed + extension_list_cmd = "k8s-extension list --resource-group={resource_group} --cluster-name={name} --cluster-type managedClusters" + extensions = self.cmd(extension_list_cmd).get_output_in_json() + + # Check if distributed accelerator extension exists + dacs_extension_found = False + for extension in extensions: + if extension.get("name") == CONST_DISTRIBUTED_ACCELERATOR_EXT_INSTALLATION_NAME: + dacs_extension_found = True + # Additional checks on the extension properties + assert extension.get("provisioningState") == "Succeeded", "Extension provisioning failed" + assert extension.get("extensionType") == CONST_DISTRIBUTED_ACCELERATOR_K8S_EXTENSION_NAME, "Wrong extension type" + break + + assert dacs_extension_found, "Distributed accelerator extension not found" + + # Sleep for 5 mins before next operation, + # since update operations take + # some time to finish. + time.sleep(10 * 60) + + # update: disable distributed accelerator + update_cmd = 'aks update --resource-group={resource_group} --name={name} --yes --output=json ' \ + '--disable-azure-container-storage distributedaccelerator' + self.cmd(update_cmd, checks=[ + self.check('provisioningState', 'Succeeded'), + ]) + + # Verify that the distributed accelerator extension doesn't exist anymore + extension_list_cmd = "k8s-extension list --resource-group={resource_group} --cluster-name={name} --cluster-type managedClusters" + extensions = self.cmd(extension_list_cmd).get_output_in_json() + + # Check if distributed accelerator extension still exists + dacs_extension_found = False + for extension in extensions: + if extension.get("name") == CONST_DISTRIBUTED_ACCELERATOR_EXT_INSTALLATION_NAME: + dacs_extension_found = True + break + + assert not dacs_extension_found, "Distributed accelerator extension still exists after disable operation" + + # delete + cmd = 'aks delete --resource-group={resource_group} --name={name} --yes --no-wait' + self.cmd(cmd, checks=[ + self.is_empty(), + ]) + @live_only() @AllowLargeResponse(99999) @AKSCustomResourceGroupPreparer(random_name_length=17, name_prefix='clitest', location='uksouth') diff --git a/src/aks-preview/azext_aks_preview/tests/latest/test_validators.py b/src/aks-preview/azext_aks_preview/tests/latest/test_validators.py index eda6a2cdd98..d245e6a8b34 100644 --- a/src/aks-preview/azext_aks_preview/tests/latest/test_validators.py +++ b/src/aks-preview/azext_aks_preview/tests/latest/test_validators.py @@ -2001,35 +2001,35 @@ def test_enable_with_storagepool_size(self): self.assertEqual(str(cm.exception), err) -class TestValidateEnableDistributedCache(unittest.TestCase): - def test_enable_distributed_cache(self): - acstor_validator.validate_enable_distributed_cache_params( - acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE, +class TestValidateEnableDistributedAccelerator(unittest.TestCase): + def test_enable_distributed_accelerator(self): + acstor_validator.validate_enable_distributed_accelerator_params( + acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, False, None, None, None, None, None, None, None, ) def test_enable_when_already_installed(self): with self.assertRaises(InvalidArgumentValueError) as cm: - acstor_validator.validate_enable_distributed_cache_params( - acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE, + acstor_validator.validate_enable_distributed_accelerator_params( + acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, True, None, None, None, None, None, None, None, ) err = ( - 'Cannot enable distributed cache as it is already enabled on the cluster.' + 'Cannot enable distributed accelerator as it is already enabled on the cluster.' ) self.assertEqual(str(cm.exception), err) def test_enable_combined_with_other_type(self): other_type = acstor_consts.CONST_STORAGE_POOL_TYPE_EPHEMERAL_DISK - storage_types = [acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE, other_type] + storage_types = [acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, other_type] with self.assertRaises(InvalidArgumentValueError) as cm: - acstor_validator.validate_enable_distributed_cache_params( + acstor_validator.validate_enable_distributed_accelerator_params( storage_types, False, None, None, None, None, None, None, None, ) err = ( - f"'{acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE}' cannot be combined with other storage " - f"options ('{other_type}'). Distributed cache is enabled independently. " - f"Please run --enable-azure-container-storage {acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE} " + f"'{acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR}' cannot be combined with other storage " + f"options ('{other_type}'). Distributed accelerator is enabled independently. " + f"Please run --enable-azure-container-storage {acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR} " "on its own." ) self.assertEqual(str(cm.exception), err) @@ -2037,62 +2037,62 @@ def test_enable_combined_with_other_type(self): def test_enable_with_storage_pool_name(self): storage_pool_name = "valid-name" with self.assertRaises(InvalidArgumentValueError) as cm: - acstor_validator.validate_enable_distributed_cache_params( - acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE, + acstor_validator.validate_enable_distributed_accelerator_params( + acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, False, storage_pool_name, None, None, None, None, None, None, ) err = ( '--storage-pool-name cannot be used with ' - '--enable-azure-container-storage distributedcache. ' - 'Distributed cache does not require or support any storage pool configuration. ' + '--enable-azure-container-storage distributedaccelerator. ' + 'Distributed accelerator does not require or support any storage pool configuration. ' 'Please remove these parameters and try again.' ) self.assertEqual(str(cm.exception), err) def test_enable_with_container_storage_version(self): with self.assertRaises(InvalidArgumentValueError) as cm: - acstor_validator.validate_enable_distributed_cache_params( - acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE, + acstor_validator.validate_enable_distributed_accelerator_params( + acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, False, None, None, None, None, None, None, "1", ) err = ( '--container-storage-version cannot be used with ' - '--enable-azure-container-storage distributedcache. ' - 'Distributed cache does not require or support any storage pool configuration. ' + '--enable-azure-container-storage distributedaccelerator. ' + 'Distributed accelerator does not require or support any storage pool configuration. ' 'Please remove these parameters and try again.' ) self.assertEqual(str(cm.exception), err) -class TestValidateDisableDistributedCache(unittest.TestCase): - def test_disable_distributed_cache(self): - acstor_validator.validate_disable_distributed_cache_params( - acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE, +class TestValidateDisableDistributedAccelerator(unittest.TestCase): + def test_disable_distributed_accelerator(self): + acstor_validator.validate_disable_distributed_accelerator_params( + acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, True, None, None, None, None, None, ) def test_disable_when_not_installed(self): with self.assertRaises(InvalidArgumentValueError) as cm: - acstor_validator.validate_disable_distributed_cache_params( - acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE, + acstor_validator.validate_disable_distributed_accelerator_params( + acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, False, None, None, None, None, None, ) err = ( - 'Cannot disable distributed cache as it could not be found on the cluster.' + 'Cannot disable distributed accelerator as it could not be found on the cluster.' ) self.assertEqual(str(cm.exception), err) def test_disable_combined_with_other_type(self): other_type = acstor_consts.CONST_ACSTOR_ALL - storage_types = [acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE, other_type] + storage_types = [acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, other_type] with self.assertRaises(InvalidArgumentValueError) as cm: - acstor_validator.validate_disable_distributed_cache_params( + acstor_validator.validate_disable_distributed_accelerator_params( storage_types, True, None, None, None, None, None, ) err = ( - f"'{acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE}' cannot be combined with other storage " - f"options ('{other_type}'). Distributed cache is disabled independently. " - f"Please run --disable-azure-container-storage {acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE} " + f"'{acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR}' cannot be combined with other storage " + f"options ('{other_type}'). Distributed accelerator is disabled independently. " + f"Please run --disable-azure-container-storage {acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR} " "on its own." ) self.assertEqual(str(cm.exception), err) @@ -2100,28 +2100,28 @@ def test_disable_combined_with_other_type(self): def test_disable_with_storage_pool_name(self): storage_pool_name = "valid-name" with self.assertRaises(InvalidArgumentValueError) as cm: - acstor_validator.validate_disable_distributed_cache_params( - acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE, + acstor_validator.validate_disable_distributed_accelerator_params( + acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, True, storage_pool_name, None, None, None, None, ) err = ( '--storage-pool-name cannot be used with ' - '--disable-azure-container-storage distributedcache. ' - 'Distributed cache does not require or support any storage pool configuration. ' + '--disable-azure-container-storage distributedaccelerator. ' + 'Distributed accelerator does not require or support any storage pool configuration. ' 'Please remove these parameters and try again.' ) self.assertEqual(str(cm.exception), err) def test_disable_with_container_storage_version(self): with self.assertRaises(InvalidArgumentValueError) as cm: - acstor_validator.validate_disable_distributed_cache_params( - acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_CACHE, + acstor_validator.validate_disable_distributed_accelerator_params( + acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, True, None, None, None, None, "1", ) err = ( '--container-storage-version cannot be used with ' - '--disable-azure-container-storage distributedcache. ' - 'Distributed cache does not require or support any storage pool configuration. ' + '--disable-azure-container-storage distributedaccelerator. ' + 'Distributed accelerator does not require or support any storage pool configuration. ' 'Please remove these parameters and try again.' ) self.assertEqual(str(cm.exception), err) From b79eaf805e969a92f966ecd0cf622f3a9cc48dcd Mon Sep 17 00:00:00 2001 From: Roger Nhan Date: Mon, 21 Sep 2026 11:43:05 -0400 Subject: [PATCH 3/5] chore: update customer facing casing --- src/aks-preview/azext_aks_preview/_params.py | 6 +++--- .../azext_aks_preview/azurecontainerstorage/_consts.py | 2 +- .../azext_aks_preview/azurecontainerstorage/acstor_ops.py | 2 +- .../azext_aks_preview/managed_cluster_decorator.py | 2 +- .../azext_aks_preview/tests/latest/test_aks_commands.py | 6 +++--- .../azext_aks_preview/tests/latest/test_validators.py | 8 ++++---- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/aks-preview/azext_aks_preview/_params.py b/src/aks-preview/azext_aks_preview/_params.py index c8eeb6f9b1c..00565c11a0d 100644 --- a/src/aks-preview/azext_aks_preview/_params.py +++ b/src/aks-preview/azext_aks_preview/_params.py @@ -1297,7 +1297,7 @@ def load_arguments(self, _): "enable_azure_container_storage", arg_type=_get_container_storage_enum_type(storage_pool_types), help="enable azure container storage. Can be used as a flag (defaults to True) or with a" - " storage pool type value: (azureDisk, ephemeralDisk, elasticSan, distributedaccelerator)", + " storage pool type value: (azureDisk, ephemeralDisk, elasticSan, distributedAccelerator)", ) c.argument( "container_storage_version", @@ -2045,14 +2045,14 @@ def load_arguments(self, _): "enable_azure_container_storage", arg_type=_get_container_storage_enum_type(storage_pool_types), help="enable azure container storage. Can be used as a flag (defaults to True) or with a" - " storage pool type value: (azureDisk, ephemeralDisk, elasticSan, distributedaccelerator)", + " storage pool type value: (azureDisk, ephemeralDisk, elasticSan, distributedAccelerator)", ) c.argument( "disable_azure_container_storage", arg_type=_get_container_storage_enum_type(disable_storage_pool_types), help="disable azure container storage or any one of the storage types." " Can be used as a flag (defaults to True) or with a storage type value:" - " azureDisk, ephemeralDisk, elasticSan, distributedaccelerator, all (to disable all storage types).", + " azureDisk, ephemeralDisk, elasticSan, distributedAccelerator, all (to disable all storage types).", ) c.argument( "container_storage_version", diff --git a/src/aks-preview/azext_aks_preview/azurecontainerstorage/_consts.py b/src/aks-preview/azext_aks_preview/azurecontainerstorage/_consts.py index 6033075d112..93c8b88e574 100644 --- a/src/aks-preview/azext_aks_preview/azurecontainerstorage/_consts.py +++ b/src/aks-preview/azext_aks_preview/azurecontainerstorage/_consts.py @@ -39,4 +39,4 @@ CONST_STORAGE_POOL_TYPE_AZURE_DISK = "azureDisk" CONST_STORAGE_POOL_TYPE_ELASTIC_SAN = "elasticSan" CONST_STORAGE_POOL_TYPE_EPHEMERAL_DISK = "ephemeralDisk" -CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR = "distributedaccelerator" +CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR = "distributedAccelerator" diff --git a/src/aks-preview/azext_aks_preview/azurecontainerstorage/acstor_ops.py b/src/aks-preview/azext_aks_preview/azurecontainerstorage/acstor_ops.py index ffa25a168ca..9f3dc7d321b 100644 --- a/src/aks-preview/azext_aks_preview/azurecontainerstorage/acstor_ops.py +++ b/src/aks-preview/azext_aks_preview/azurecontainerstorage/acstor_ops.py @@ -859,7 +859,7 @@ def perform_enable_distributed_accelerator( logger.warning( "Please retry enabling distributed accelerator by running " "`az aks update` along with " - "`--enable-azure-container-storage distributedaccelerator`" + "`--enable-azure-container-storage distributedAccelerator`" ) except Exception as delete_ex: # pylint: disable=broad-except raise UnknownError( diff --git a/src/aks-preview/azext_aks_preview/managed_cluster_decorator.py b/src/aks-preview/azext_aks_preview/managed_cluster_decorator.py index 270ab62fe29..ee1efa257c3 100644 --- a/src/aks-preview/azext_aks_preview/managed_cluster_decorator.py +++ b/src/aks-preview/azext_aks_preview/managed_cluster_decorator.py @@ -6813,7 +6813,7 @@ def update_azure_container_storage(self, mc: ManagedCluster) -> ManagedCluster: ) # Distributed accelerator is enabled/disabled independently of the storage - # pool flow. Disable happens explicitly (`distributedaccelerator`) or + # pool flow. Disable happens explicitly (`distributedAccelerator`) or # implicitly on a full teardown (bare `--disable...` or `all`). dc_enable_requested = is_distributed_accelerator_requested(enable_azure_container_storage_param) dc_disable_requested_explicit = is_distributed_accelerator_requested(disable_azure_container_storage_param) diff --git a/src/aks-preview/azext_aks_preview/tests/latest/test_aks_commands.py b/src/aks-preview/azext_aks_preview/tests/latest/test_aks_commands.py index f9294333640..884776e4ded 100644 --- a/src/aks-preview/azext_aks_preview/tests/latest/test_aks_commands.py +++ b/src/aks-preview/azext_aks_preview/tests/latest/test_aks_commands.py @@ -17033,7 +17033,7 @@ def test_aks_create_with_azurecontainerstorage_distributedaccelerator(self, reso "aks create --resource-group={resource_group} --name={name} --location={location} " "--ssh-key-value={ssh_key_value} --node-vm-size={node_vm_size} " "--node-count 3 --enable-managed-identity " - "--enable-azure-container-storage distributedaccelerator --output=json" + "--enable-azure-container-storage distributedAccelerator --output=json" ) self.cmd( @@ -17096,7 +17096,7 @@ def test_aks_update_with_azurecontainerstorage_distributedaccelerator(self, reso # update: enable distributed accelerator update_cmd = 'aks update --resource-group={resource_group} --name={name} --yes --output=json ' \ - '--enable-azure-container-storage distributedaccelerator' + '--enable-azure-container-storage distributedAccelerator' self.cmd(update_cmd, checks=[ self.check('provisioningState', 'Succeeded'), @@ -17125,7 +17125,7 @@ def test_aks_update_with_azurecontainerstorage_distributedaccelerator(self, reso # update: disable distributed accelerator update_cmd = 'aks update --resource-group={resource_group} --name={name} --yes --output=json ' \ - '--disable-azure-container-storage distributedaccelerator' + '--disable-azure-container-storage distributedAccelerator' self.cmd(update_cmd, checks=[ self.check('provisioningState', 'Succeeded'), ]) diff --git a/src/aks-preview/azext_aks_preview/tests/latest/test_validators.py b/src/aks-preview/azext_aks_preview/tests/latest/test_validators.py index d245e6a8b34..21d0d5da891 100644 --- a/src/aks-preview/azext_aks_preview/tests/latest/test_validators.py +++ b/src/aks-preview/azext_aks_preview/tests/latest/test_validators.py @@ -2043,7 +2043,7 @@ def test_enable_with_storage_pool_name(self): ) err = ( '--storage-pool-name cannot be used with ' - '--enable-azure-container-storage distributedaccelerator. ' + '--enable-azure-container-storage distributedAccelerator. ' 'Distributed accelerator does not require or support any storage pool configuration. ' 'Please remove these parameters and try again.' ) @@ -2057,7 +2057,7 @@ def test_enable_with_container_storage_version(self): ) err = ( '--container-storage-version cannot be used with ' - '--enable-azure-container-storage distributedaccelerator. ' + '--enable-azure-container-storage distributedAccelerator. ' 'Distributed accelerator does not require or support any storage pool configuration. ' 'Please remove these parameters and try again.' ) @@ -2106,7 +2106,7 @@ def test_disable_with_storage_pool_name(self): ) err = ( '--storage-pool-name cannot be used with ' - '--disable-azure-container-storage distributedaccelerator. ' + '--disable-azure-container-storage distributedAccelerator. ' 'Distributed accelerator does not require or support any storage pool configuration. ' 'Please remove these parameters and try again.' ) @@ -2120,7 +2120,7 @@ def test_disable_with_container_storage_version(self): ) err = ( '--container-storage-version cannot be used with ' - '--disable-azure-container-storage distributedaccelerator. ' + '--disable-azure-container-storage distributedAccelerator. ' 'Distributed accelerator does not require or support any storage pool configuration. ' 'Please remove these parameters and try again.' ) From 86e40ec8745294973b4c0c7e164b12f23c234940 Mon Sep 17 00:00:00 2001 From: Roger Nhan Date: Tue, 22 Sep 2026 12:18:34 -0400 Subject: [PATCH 4/5] chore: update validators --- .../azurecontainerstorage/_validators.py | 6 +++ .../managed_cluster_decorator.py | 2 + .../tests/latest/test_validators.py | 38 ++++++++++++++++--- 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/aks-preview/azext_aks_preview/azurecontainerstorage/_validators.py b/src/aks-preview/azext_aks_preview/azurecontainerstorage/_validators.py index 85722478650..fd25febcdd2 100644 --- a/src/aks-preview/azext_aks_preview/azurecontainerstorage/_validators.py +++ b/src/aks-preview/azext_aks_preview/azurecontainerstorage/_validators.py @@ -637,6 +637,8 @@ def validate_disable_distributed_accelerator_params( storage_pool_sku, storage_pool_option, storage_pool_size, + ephemeral_disk_volume_type, + ephemeral_disk_nvme_perf_tier, container_storage_version=None, ): disablement_option_arr = disablement_option if isinstance(disablement_option, list) else [disablement_option] @@ -667,6 +669,10 @@ def validate_disable_distributed_accelerator_params( unsupported_params.append('--storage-pool-option') if storage_pool_size is not None: unsupported_params.append('--storage-pool-size') + if ephemeral_disk_volume_type is not None: + unsupported_params.append('--ephemeral-disk-volume-type') + if ephemeral_disk_nvme_perf_tier is not None: + unsupported_params.append('--ephemeral-disk-nvme-perf-tier') if container_storage_version is not None: unsupported_params.append('--container-storage-version') diff --git a/src/aks-preview/azext_aks_preview/managed_cluster_decorator.py b/src/aks-preview/azext_aks_preview/managed_cluster_decorator.py index ee1efa257c3..f72bfb6e769 100644 --- a/src/aks-preview/azext_aks_preview/managed_cluster_decorator.py +++ b/src/aks-preview/azext_aks_preview/managed_cluster_decorator.py @@ -6874,6 +6874,8 @@ def update_azure_container_storage(self, mc: ManagedCluster) -> ManagedCluster: pool_sku, pool_option, pool_size, + self.context.raw_param.get("ephemeral_disk_volume_type"), + self.context.raw_param.get("ephemeral_disk_nvme_perf_tier"), self.context.raw_param.get("container_storage_version"), ) self.context.set_intermediate( diff --git a/src/aks-preview/azext_aks_preview/tests/latest/test_validators.py b/src/aks-preview/azext_aks_preview/tests/latest/test_validators.py index 21d0d5da891..f6d5e5e7416 100644 --- a/src/aks-preview/azext_aks_preview/tests/latest/test_validators.py +++ b/src/aks-preview/azext_aks_preview/tests/latest/test_validators.py @@ -2068,14 +2068,14 @@ class TestValidateDisableDistributedAccelerator(unittest.TestCase): def test_disable_distributed_accelerator(self): acstor_validator.validate_disable_distributed_accelerator_params( acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, - True, None, None, None, None, None, + True, None, None, None, None, None, None, None, ) def test_disable_when_not_installed(self): with self.assertRaises(InvalidArgumentValueError) as cm: acstor_validator.validate_disable_distributed_accelerator_params( acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, - False, None, None, None, None, None, + False, None, None, None, None, None, None, None, ) err = ( 'Cannot disable distributed accelerator as it could not be found on the cluster.' @@ -2087,7 +2087,7 @@ def test_disable_combined_with_other_type(self): storage_types = [acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, other_type] with self.assertRaises(InvalidArgumentValueError) as cm: acstor_validator.validate_disable_distributed_accelerator_params( - storage_types, True, None, None, None, None, None, + storage_types, True, None, None, None, None, None, None, None, ) err = ( f"'{acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR}' cannot be combined with other storage " @@ -2102,7 +2102,7 @@ def test_disable_with_storage_pool_name(self): with self.assertRaises(InvalidArgumentValueError) as cm: acstor_validator.validate_disable_distributed_accelerator_params( acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, - True, storage_pool_name, None, None, None, None, + True, storage_pool_name, None, None, None, None, None, None, ) err = ( '--storage-pool-name cannot be used with ' @@ -2112,11 +2112,39 @@ def test_disable_with_storage_pool_name(self): ) self.assertEqual(str(cm.exception), err) + def test_disable_with_ephemeral_disk_volume_type(self): + with self.assertRaises(InvalidArgumentValueError) as cm: + acstor_validator.validate_disable_distributed_accelerator_params( + acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, + True, None, None, None, None, "EphemeralVolumeOnly", None, None, + ) + err = ( + '--ephemeral-disk-volume-type cannot be used with ' + '--disable-azure-container-storage distributedAccelerator. ' + 'Distributed accelerator does not require or support any storage pool configuration. ' + 'Please remove these parameters and try again.' + ) + self.assertEqual(str(cm.exception), err) + + def test_disable_with_ephemeral_disk_nvme_perf_tier(self): + with self.assertRaises(InvalidArgumentValueError) as cm: + acstor_validator.validate_disable_distributed_accelerator_params( + acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, + True, None, None, None, None, None, "Premium", None, + ) + err = ( + '--ephemeral-disk-nvme-perf-tier cannot be used with ' + '--disable-azure-container-storage distributedAccelerator. ' + 'Distributed accelerator does not require or support any storage pool configuration. ' + 'Please remove these parameters and try again.' + ) + self.assertEqual(str(cm.exception), err) + def test_disable_with_container_storage_version(self): with self.assertRaises(InvalidArgumentValueError) as cm: acstor_validator.validate_disable_distributed_accelerator_params( acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, - True, None, None, None, None, "1", + True, None, None, None, None, None, None, "1", ) err = ( '--container-storage-version cannot be used with ' From b2a85639febd77970be89d116511479d77a54c92 Mon Sep 17 00:00:00 2001 From: Roger Nhan Date: Thu, 24 Sep 2026 11:18:38 -0400 Subject: [PATCH 5/5] fix: bump version and additional validations --- src/aks-preview/HISTORY.rst | 2 +- .../azurecontainerstorage/_helpers.py | 8 + .../azurecontainerstorage/_validators.py | 137 ++++++++++++------ .../managed_cluster_decorator.py | 22 +++ .../tests/latest/test_helpers.py | 56 +++++++ .../tests/latest/test_validators.py | 85 +++++++++-- src/aks-preview/setup.py | 2 +- 7 files changed, 251 insertions(+), 61 deletions(-) diff --git a/src/aks-preview/HISTORY.rst b/src/aks-preview/HISTORY.rst index 5be058b099d..ca0ceb943f0 100644 --- a/src/aks-preview/HISTORY.rst +++ b/src/aks-preview/HISTORY.rst @@ -11,10 +11,10 @@ To release a new version, please select a new version number (usually plus 1 to Pending +++++++ -* `az aks create/update`: Add `distributedAccelerator` storage option to `--enable-azure-container-storage` and `--disable-azure-container-storage` to install/uninstall the Azure Container Storage distributed accelerator controller. 22.0.0b9 +++++++++ +* `az aks create/update`: Add `distributedAccelerator` storage option to `--enable-azure-container-storage` and `--disable-azure-container-storage` to install/uninstall the Azure Container Storage distributed accelerator controller. * `az aks nodepool update`: Preserve the existing GPU management mode when `--enable-managed-gpu` is omitted, including when enabling, updating, or disabling the cluster autoscaler. * `az aks alert-config add`: Reject an empty `--name` before looking up existing configurations instead of reporting that it already exists. * `az aks nodepool scale`: add `--use-patch-api` to optionally scale a VMSS node pool via the new dedicated PATCH agent pool API (scales to the target count without triggering full reconciliation). The default behavior continues to use the PUT agent pool API. diff --git a/src/aks-preview/azext_aks_preview/azurecontainerstorage/_helpers.py b/src/aks-preview/azext_aks_preview/azurecontainerstorage/_helpers.py index f0c5388152c..7d817716050 100644 --- a/src/aks-preview/azext_aks_preview/azurecontainerstorage/_helpers.py +++ b/src/aks-preview/azext_aks_preview/azurecontainerstorage/_helpers.py @@ -319,6 +319,7 @@ def get_container_storage_extension_installed( resource_group, cluster_name, extension_name, + expected_extension_type=None, ) -> Tuple[bool, str]: client_factory = get_k8s_extension_module(CONST_K8S_EXTENSION_CLIENT_FACTORY_MOD_NAME) @@ -335,6 +336,13 @@ def get_container_storage_extension_installed( extension_name, "managedClusters", ) + # show_k8s_extension only matches on the instance name, so an unrelated + # extension that happens to share the name would otherwise be treated as + # installed. When an expected extension type is supplied, verify it before + # reporting the extension as installed to avoid acting on the wrong resource. + if expected_extension_type is not None and \ + (getattr(extension, "extension_type", None) or "").lower() != expected_extension_type.lower(): + return False, "" is_extension_installed = True extension_version = extension.current_version except ResourceNotFoundError: diff --git a/src/aks-preview/azext_aks_preview/azurecontainerstorage/_validators.py b/src/aks-preview/azext_aks_preview/azurecontainerstorage/_validators.py index fd25febcdd2..3f284e67c11 100644 --- a/src/aks-preview/azext_aks_preview/azurecontainerstorage/_validators.py +++ b/src/aks-preview/azext_aks_preview/azurecontainerstorage/_validators.py @@ -572,6 +572,46 @@ def validate_disable_azure_container_storage_params( ) +def _reject_unsupported_distributed_accelerator_params( + command_display, + storage_pool_name, + storage_pool_sku, + storage_pool_option, + storage_pool_size, + ephemeral_disk_volume_type, + ephemeral_disk_nvme_perf_tier, + nodepool_list, + container_storage_version, +): + # Distributed accelerator has no storage pool construct, so none of the storage + # pool scoping parameters are supported on the distributed accelerator paths. + unsupported_params = [] + if storage_pool_name is not None: + unsupported_params.append('--storage-pool-name') + if storage_pool_sku is not None: + unsupported_params.append('--storage-pool-sku') + if storage_pool_option is not None: + unsupported_params.append('--storage-pool-option') + if storage_pool_size is not None: + unsupported_params.append('--storage-pool-size') + if ephemeral_disk_volume_type is not None: + unsupported_params.append('--ephemeral-disk-volume-type') + if ephemeral_disk_nvme_perf_tier is not None: + unsupported_params.append('--ephemeral-disk-nvme-perf-tier') + if nodepool_list is not None: + unsupported_params.append('--azure-container-storage-nodepools') + if container_storage_version is not None: + unsupported_params.append('--container-storage-version') + + if unsupported_params: + params_defined = ', '.join(unsupported_params) + raise InvalidArgumentValueError( + f'{params_defined} cannot be used with {command_display}. ' + 'Distributed accelerator does not require or support any storage pool configuration. ' + 'Please remove these parameters and try again.' + ) + + def validate_enable_distributed_accelerator_params( enablement_option, is_extension_installed, @@ -581,6 +621,7 @@ def validate_enable_distributed_accelerator_params( storage_pool_size, ephemeral_disk_volume_type, ephemeral_disk_nvme_perf_tier, + nodepool_list=None, container_storage_version=None, ): # Distributed accelerator has no storage pool construct, so none of the storage @@ -604,30 +645,17 @@ def validate_enable_distributed_accelerator_params( 'Cannot enable distributed accelerator as it is already enabled on the cluster.' ) - unsupported_params = [] - if storage_pool_name is not None: - unsupported_params.append('--storage-pool-name') - if storage_pool_sku is not None: - unsupported_params.append('--storage-pool-sku') - if storage_pool_option is not None: - unsupported_params.append('--storage-pool-option') - if storage_pool_size is not None: - unsupported_params.append('--storage-pool-size') - if ephemeral_disk_volume_type is not None: - unsupported_params.append('--ephemeral-disk-volume-type') - if ephemeral_disk_nvme_perf_tier is not None: - unsupported_params.append('--ephemeral-disk-nvme-perf-tier') - if container_storage_version is not None: - unsupported_params.append('--container-storage-version') - - if unsupported_params: - params_defined = ', '.join(unsupported_params) - raise InvalidArgumentValueError( - f'{params_defined} cannot be used with ' - f'--enable-azure-container-storage {CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR}. ' - 'Distributed accelerator does not require or support any storage pool configuration. ' - 'Please remove these parameters and try again.' - ) + _reject_unsupported_distributed_accelerator_params( + f'--enable-azure-container-storage {CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR}', + storage_pool_name, + storage_pool_sku, + storage_pool_option, + storage_pool_size, + ephemeral_disk_volume_type, + ephemeral_disk_nvme_perf_tier, + nodepool_list, + container_storage_version, + ) def validate_disable_distributed_accelerator_params( @@ -639,6 +667,7 @@ def validate_disable_distributed_accelerator_params( storage_pool_size, ephemeral_disk_volume_type, ephemeral_disk_nvme_perf_tier, + nodepool_list=None, container_storage_version=None, ): disablement_option_arr = disablement_option if isinstance(disablement_option, list) else [disablement_option] @@ -660,30 +689,44 @@ def validate_disable_distributed_accelerator_params( 'Cannot disable distributed accelerator as it could not be found on the cluster.' ) - unsupported_params = [] - if storage_pool_name is not None: - unsupported_params.append('--storage-pool-name') - if storage_pool_sku is not None: - unsupported_params.append('--storage-pool-sku') - if storage_pool_option is not None: - unsupported_params.append('--storage-pool-option') - if storage_pool_size is not None: - unsupported_params.append('--storage-pool-size') - if ephemeral_disk_volume_type is not None: - unsupported_params.append('--ephemeral-disk-volume-type') - if ephemeral_disk_nvme_perf_tier is not None: - unsupported_params.append('--ephemeral-disk-nvme-perf-tier') - if container_storage_version is not None: - unsupported_params.append('--container-storage-version') + _reject_unsupported_distributed_accelerator_params( + f'--disable-azure-container-storage {CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR}', + storage_pool_name, + storage_pool_sku, + storage_pool_option, + storage_pool_size, + ephemeral_disk_volume_type, + ephemeral_disk_nvme_perf_tier, + nodepool_list, + container_storage_version, + ) - if unsupported_params: - params_defined = ', '.join(unsupported_params) - raise InvalidArgumentValueError( - f'{params_defined} cannot be used with ' - f'--disable-azure-container-storage {CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR}. ' - 'Distributed accelerator does not require or support any storage pool configuration. ' - 'Please remove these parameters and try again.' - ) + +def validate_disable_all_distributed_accelerator_params( + storage_pool_name, + storage_pool_sku, + storage_pool_option, + storage_pool_size, + ephemeral_disk_volume_type, + ephemeral_disk_nvme_perf_tier, + nodepool_list=None, + container_storage_version=None, +): + # A bare `--disable-azure-container-storage` or `all` teardown of a + # distributed-accelerator-only cluster removes the controller directly and + # returns before the storage pool validation runs, so reject the storage + # pool scoping parameters here as well. + _reject_unsupported_distributed_accelerator_params( + '--disable-azure-container-storage on a distributed accelerator cluster', + storage_pool_name, + storage_pool_sku, + storage_pool_option, + storage_pool_size, + ephemeral_disk_volume_type, + ephemeral_disk_nvme_perf_tier, + nodepool_list, + container_storage_version, + ) # _Validate_storage_pool_size validates that the storage_pool_size is diff --git a/src/aks-preview/azext_aks_preview/managed_cluster_decorator.py b/src/aks-preview/azext_aks_preview/managed_cluster_decorator.py index f72bfb6e769..d70011155bf 100644 --- a/src/aks-preview/azext_aks_preview/managed_cluster_decorator.py +++ b/src/aks-preview/azext_aks_preview/managed_cluster_decorator.py @@ -61,6 +61,7 @@ CONST_ACSTOR_V1_EXT_INSTALLATION_NAME, CONST_ACSTOR_VERSION_V1, CONST_DISTRIBUTED_ACCELERATOR_EXT_INSTALLATION_NAME, + CONST_DISTRIBUTED_ACCELERATOR_K8S_EXTENSION_NAME, ) from azext_aks_preview._helpers import ( check_is_apiserver_vnet_integration_cluster, @@ -5392,6 +5393,7 @@ def set_up_azure_container_storage(self, mc: ManagedCluster) -> ManagedCluster: self.context.raw_param.get("storage_pool_size"), self.context.raw_param.get("ephemeral_disk_volume_type"), self.context.raw_param.get("ephemeral_disk_nvme_perf_tier"), + self.context.raw_param.get("azure_container_storage_nodepools"), self.context.raw_param.get("container_storage_version"), ) self.context.set_intermediate( @@ -6833,6 +6835,7 @@ def update_azure_container_storage(self, mc: ManagedCluster) -> ManagedCluster: self.context.get_resource_group_name(), self.context.get_name(), CONST_DISTRIBUTED_ACCELERATOR_EXT_INSTALLATION_NAME, + expected_extension_type=CONST_DISTRIBUTED_ACCELERATOR_K8S_EXTENSION_NAME, ) except Exception as ex: raise UnknownError( @@ -6844,6 +6847,7 @@ def update_azure_container_storage(self, mc: ManagedCluster) -> ManagedCluster: pool_sku = self.context.raw_param.get("storage_pool_sku") pool_option = self.context.raw_param.get("storage_pool_option") pool_size = self.context.raw_param.get("storage_pool_size") + nodepool_list = self.context.raw_param.get("azure_container_storage_nodepools") if dc_enable_requested: from azext_aks_preview.azurecontainerstorage._validators import ( @@ -6858,6 +6862,7 @@ def update_azure_container_storage(self, mc: ManagedCluster) -> ManagedCluster: pool_size, self.context.raw_param.get("ephemeral_disk_volume_type"), self.context.raw_param.get("ephemeral_disk_nvme_perf_tier"), + nodepool_list, self.context.raw_param.get("container_storage_version"), ) self.context.set_intermediate( @@ -6876,6 +6881,7 @@ def update_azure_container_storage(self, mc: ManagedCluster) -> ManagedCluster: pool_size, self.context.raw_param.get("ephemeral_disk_volume_type"), self.context.raw_param.get("ephemeral_disk_nvme_perf_tier"), + nodepool_list, self.context.raw_param.get("container_storage_version"), ) self.context.set_intermediate( @@ -6920,6 +6926,22 @@ def update_azure_container_storage(self, mc: ManagedCluster) -> ManagedCluster: # Distributed-cache-only cluster: teardown already queued, # nothing more to disable. if is_distributed_accelerator_installed: + # This bare/`all` teardown returns before the storage pool + # validation runs, so reject any storage pool scoping + # parameters that would otherwise be silently ignored. + from azext_aks_preview.azurecontainerstorage._validators import ( + validate_disable_all_distributed_accelerator_params, + ) + validate_disable_all_distributed_accelerator_params( + storage_pool_name, + pool_sku, + pool_option, + pool_size, + self.context.raw_param.get("ephemeral_disk_volume_type"), + self.context.raw_param.get("ephemeral_disk_nvme_perf_tier"), + nodepool_list, + container_storage_version, + ) return mc raise InvalidArgumentValueError( 'Cannot disable Azure Container Storage as it could not be found on the cluster.' diff --git a/src/aks-preview/azext_aks_preview/tests/latest/test_helpers.py b/src/aks-preview/azext_aks_preview/tests/latest/test_helpers.py index c130c661b78..28fa06c0edb 100644 --- a/src/aks-preview/azext_aks_preview/tests/latest/test_helpers.py +++ b/src/aks-preview/azext_aks_preview/tests/latest/test_helpers.py @@ -22,6 +22,9 @@ ) from azext_aks_preview.__init__ import register_aks_preview_resource_type from azext_aks_preview._client_factory import CUSTOM_MGMT_AKS_PREVIEW +from azext_aks_preview.azurecontainerstorage._helpers import ( + get_container_storage_extension_installed, +) from azext_aks_preview.managed_cluster_decorator import ( AKSPreviewManagedClusterModels, ) @@ -421,5 +424,58 @@ def test_prefers_exact_match_over_case_insensitive(self): self.assertIn("omsAgent", addon_profiles) +class GetContainerStorageExtensionInstalledTestCase(unittest.TestCase): + """Tests for get_container_storage_extension_installed extension_type verification.""" + + def _patch_module(self, extension=None, side_effect=None): + mock_mod = Mock() + if side_effect is not None: + mock_mod.show_k8s_extension = Mock(side_effect=side_effect) + else: + mock_mod.show_k8s_extension = Mock(return_value=extension) + return patch( + "azext_aks_preview.azurecontainerstorage._helpers.get_k8s_extension_module", + return_value=mock_mod, + ) + + def test_installed_when_type_matches(self): + extension = SimpleNamespace(extension_type="microsoft.distributedaccelerator", current_version="1.0.0") + with self._patch_module(extension=extension): + installed, version = get_container_storage_extension_installed( + Mock(), "mock_rg", "mock_cluster", "distributedaccelerator", + expected_extension_type="microsoft.distributedaccelerator", + ) + self.assertTrue(installed) + self.assertEqual(version, "1.0.0") + + def test_not_installed_when_type_mismatches(self): + extension = SimpleNamespace(extension_type="microsoft.somethingelse", current_version="1.0.0") + with self._patch_module(extension=extension): + installed, version = get_container_storage_extension_installed( + Mock(), "mock_rg", "mock_cluster", "distributedaccelerator", + expected_extension_type="microsoft.distributedaccelerator", + ) + self.assertFalse(installed) + self.assertEqual(version, "") + + def test_installed_ignores_type_when_expected_not_supplied(self): + extension = SimpleNamespace(extension_type="microsoft.somethingelse", current_version="1.0.0") + with self._patch_module(extension=extension): + installed, version = get_container_storage_extension_installed( + Mock(), "mock_rg", "mock_cluster", "distributedaccelerator", + ) + self.assertTrue(installed) + self.assertEqual(version, "1.0.0") + + def test_not_installed_when_extension_not_found(self): + with self._patch_module(side_effect=ResourceNotFoundError("not found")): + installed, version = get_container_storage_extension_installed( + Mock(), "mock_rg", "mock_cluster", "distributedaccelerator", + expected_extension_type="microsoft.distributedaccelerator", + ) + self.assertFalse(installed) + self.assertEqual(version, "") + + if __name__ == "__main__": unittest.main() diff --git a/src/aks-preview/azext_aks_preview/tests/latest/test_validators.py b/src/aks-preview/azext_aks_preview/tests/latest/test_validators.py index f6d5e5e7416..301477bcfc6 100644 --- a/src/aks-preview/azext_aks_preview/tests/latest/test_validators.py +++ b/src/aks-preview/azext_aks_preview/tests/latest/test_validators.py @@ -2005,14 +2005,14 @@ class TestValidateEnableDistributedAccelerator(unittest.TestCase): def test_enable_distributed_accelerator(self): acstor_validator.validate_enable_distributed_accelerator_params( acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, - False, None, None, None, None, None, None, None, + False, None, None, None, None, None, None, None, None, ) def test_enable_when_already_installed(self): with self.assertRaises(InvalidArgumentValueError) as cm: acstor_validator.validate_enable_distributed_accelerator_params( acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, - True, None, None, None, None, None, None, None, + True, None, None, None, None, None, None, None, None, ) err = ( 'Cannot enable distributed accelerator as it is already enabled on the cluster.' @@ -2024,7 +2024,7 @@ def test_enable_combined_with_other_type(self): storage_types = [acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, other_type] with self.assertRaises(InvalidArgumentValueError) as cm: acstor_validator.validate_enable_distributed_accelerator_params( - storage_types, False, None, None, None, None, None, None, None, + storage_types, False, None, None, None, None, None, None, None, None, ) err = ( f"'{acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR}' cannot be combined with other storage " @@ -2039,7 +2039,7 @@ def test_enable_with_storage_pool_name(self): with self.assertRaises(InvalidArgumentValueError) as cm: acstor_validator.validate_enable_distributed_accelerator_params( acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, - False, storage_pool_name, None, None, None, None, None, None, + False, storage_pool_name, None, None, None, None, None, None, None, ) err = ( '--storage-pool-name cannot be used with ' @@ -2049,11 +2049,25 @@ def test_enable_with_storage_pool_name(self): ) self.assertEqual(str(cm.exception), err) + def test_enable_with_nodepool_list(self): + with self.assertRaises(InvalidArgumentValueError) as cm: + acstor_validator.validate_enable_distributed_accelerator_params( + acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, + False, None, None, None, None, None, None, "pool1", None, + ) + err = ( + '--azure-container-storage-nodepools cannot be used with ' + '--enable-azure-container-storage distributedAccelerator. ' + 'Distributed accelerator does not require or support any storage pool configuration. ' + 'Please remove these parameters and try again.' + ) + self.assertEqual(str(cm.exception), err) + def test_enable_with_container_storage_version(self): with self.assertRaises(InvalidArgumentValueError) as cm: acstor_validator.validate_enable_distributed_accelerator_params( acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, - False, None, None, None, None, None, None, "1", + False, None, None, None, None, None, None, None, "1", ) err = ( '--container-storage-version cannot be used with ' @@ -2068,14 +2082,14 @@ class TestValidateDisableDistributedAccelerator(unittest.TestCase): def test_disable_distributed_accelerator(self): acstor_validator.validate_disable_distributed_accelerator_params( acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, - True, None, None, None, None, None, None, None, + True, None, None, None, None, None, None, None, None, ) def test_disable_when_not_installed(self): with self.assertRaises(InvalidArgumentValueError) as cm: acstor_validator.validate_disable_distributed_accelerator_params( acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, - False, None, None, None, None, None, None, None, + False, None, None, None, None, None, None, None, None, ) err = ( 'Cannot disable distributed accelerator as it could not be found on the cluster.' @@ -2087,7 +2101,7 @@ def test_disable_combined_with_other_type(self): storage_types = [acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, other_type] with self.assertRaises(InvalidArgumentValueError) as cm: acstor_validator.validate_disable_distributed_accelerator_params( - storage_types, True, None, None, None, None, None, None, None, + storage_types, True, None, None, None, None, None, None, None, None, ) err = ( f"'{acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR}' cannot be combined with other storage " @@ -2102,7 +2116,7 @@ def test_disable_with_storage_pool_name(self): with self.assertRaises(InvalidArgumentValueError) as cm: acstor_validator.validate_disable_distributed_accelerator_params( acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, - True, storage_pool_name, None, None, None, None, None, None, + True, storage_pool_name, None, None, None, None, None, None, None, ) err = ( '--storage-pool-name cannot be used with ' @@ -2116,7 +2130,7 @@ def test_disable_with_ephemeral_disk_volume_type(self): with self.assertRaises(InvalidArgumentValueError) as cm: acstor_validator.validate_disable_distributed_accelerator_params( acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, - True, None, None, None, None, "EphemeralVolumeOnly", None, None, + True, None, None, None, None, "EphemeralVolumeOnly", None, None, None, ) err = ( '--ephemeral-disk-volume-type cannot be used with ' @@ -2130,7 +2144,7 @@ def test_disable_with_ephemeral_disk_nvme_perf_tier(self): with self.assertRaises(InvalidArgumentValueError) as cm: acstor_validator.validate_disable_distributed_accelerator_params( acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, - True, None, None, None, None, None, "Premium", None, + True, None, None, None, None, None, "Premium", None, None, ) err = ( '--ephemeral-disk-nvme-perf-tier cannot be used with ' @@ -2140,11 +2154,25 @@ def test_disable_with_ephemeral_disk_nvme_perf_tier(self): ) self.assertEqual(str(cm.exception), err) + def test_disable_with_nodepool_list(self): + with self.assertRaises(InvalidArgumentValueError) as cm: + acstor_validator.validate_disable_distributed_accelerator_params( + acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, + True, None, None, None, None, None, None, "pool1", None, + ) + err = ( + '--azure-container-storage-nodepools cannot be used with ' + '--disable-azure-container-storage distributedAccelerator. ' + 'Distributed accelerator does not require or support any storage pool configuration. ' + 'Please remove these parameters and try again.' + ) + self.assertEqual(str(cm.exception), err) + def test_disable_with_container_storage_version(self): with self.assertRaises(InvalidArgumentValueError) as cm: acstor_validator.validate_disable_distributed_accelerator_params( acstor_consts.CONST_STORAGE_POOL_TYPE_DISTRIBUTED_ACCELERATOR, - True, None, None, None, None, None, None, "1", + True, None, None, None, None, None, None, None, "1", ) err = ( '--container-storage-version cannot be used with ' @@ -2155,6 +2183,39 @@ def test_disable_with_container_storage_version(self): self.assertEqual(str(cm.exception), err) +class TestValidateDisableAllDistributedAccelerator(unittest.TestCase): + def test_disable_all_no_params(self): + acstor_validator.validate_disable_all_distributed_accelerator_params( + None, None, None, None, None, None, None, None, + ) + + def test_disable_all_with_storage_pool_name(self): + with self.assertRaises(InvalidArgumentValueError) as cm: + acstor_validator.validate_disable_all_distributed_accelerator_params( + "bogus", None, None, None, None, None, None, None, + ) + err = ( + '--storage-pool-name cannot be used with ' + '--disable-azure-container-storage on a distributed accelerator cluster. ' + 'Distributed accelerator does not require or support any storage pool configuration. ' + 'Please remove these parameters and try again.' + ) + self.assertEqual(str(cm.exception), err) + + def test_disable_all_with_nodepool_list(self): + with self.assertRaises(InvalidArgumentValueError) as cm: + acstor_validator.validate_disable_all_distributed_accelerator_params( + None, None, None, None, None, None, "pool1", None, + ) + err = ( + '--azure-container-storage-nodepools cannot be used with ' + '--disable-azure-container-storage on a distributed accelerator cluster. ' + 'Distributed accelerator does not require or support any storage pool configuration. ' + 'Please remove these parameters and try again.' + ) + self.assertEqual(str(cm.exception), err) + + class GatewayPrefixSizeSpace: def __init__(self, gateway_prefix_size=None, mode=None): self.gateway_prefix_size = gateway_prefix_size diff --git a/src/aks-preview/setup.py b/src/aks-preview/setup.py index f0feb773baf..e8d00b5171d 100644 --- a/src/aks-preview/setup.py +++ b/src/aks-preview/setup.py @@ -9,7 +9,7 @@ from setuptools import find_packages, setup -VERSION = "22.0.0b8" +VERSION = "22.0.0b9" CLASSIFIERS = [ "Development Status :: 4 - Beta",