Skip to content

Commit 737b240

Browse files
authored
AKS: Change --enable-azure-container-storage --disable-azure-container -storage behavior and add --container-storage-version (#9138)
1 parent 128dd90 commit 737b240

File tree

12 files changed

+1561
-600
lines changed

12 files changed

+1561
-600
lines changed

src/aks-preview/HISTORY.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,15 @@ To release a new version, please select a new version number (usually plus 1 to
1111

1212
Pending
1313
+++++++
14+
15+
18.0.0b40
16+
+++++++
1417
* Add option `Windows2025` to `--os-sku` for `az aks nodepool add`.
18+
* `az aks create`: Add new parameter `--container-storage-version` to enable the given version of Azure Container Storage.
19+
* `az aks update`: Add new parameter `--container-storage-version` to enable the given version of Azure Container Storage.
20+
* `az aks create`: Change behavior of `--enable-azure-container-storage` to enable latest Azure Container Storage by default.
21+
* `az aks update`: Change behavior of `--enable-azure-container-storage` to enable latest Azure Container Storage by default.
22+
* `az aks update`: Change behavior of `--disable-azure-container-storage` to handle disable based on the installed version.
1523

1624
18.0.0b39
1725
+++++++

src/aks-preview/azext_aks_preview/_params.py

Lines changed: 88 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,12 @@
441441
]
442442

443443
# azure container storage
444+
# azure container storage
445+
container_storage_versions = [
446+
"1",
447+
"2"
448+
]
449+
444450
storage_pool_types = [
445451
CONST_STORAGE_POOL_TYPE_AZURE_DISK,
446452
CONST_STORAGE_POOL_TYPE_EPHEMERAL_DISK,
@@ -1028,8 +1034,14 @@ def load_arguments(self, _):
10281034
# azure container storage
10291035
c.argument(
10301036
"enable_azure_container_storage",
1031-
arg_type=get_enum_type(storage_pool_types),
1032-
help="enable azure container storage and define storage pool type",
1037+
arg_type=_get_enable_azure_container_storage_type(),
1038+
help="enable azure container storage. Can be used as a flag (defaults to True) or with a"
1039+
" storage pool type value: (azureDisk, ephemeralDisk, elasticSan)",
1040+
)
1041+
c.argument(
1042+
"container_storage_version",
1043+
arg_type=get_enum_type(container_storage_versions),
1044+
help="set azure container storage version, the latest version will be installed by default",
10331045
)
10341046
c.argument(
10351047
"storage_pool_name",
@@ -1488,13 +1500,21 @@ def load_arguments(self, _):
14881500
# azure container storage
14891501
c.argument(
14901502
"enable_azure_container_storage",
1491-
arg_type=get_enum_type(storage_pool_types),
1492-
help="enable azure container storage and define storage pool type",
1503+
arg_type=_get_enable_azure_container_storage_type(),
1504+
help="enable azure container storage. Can be used as a flag (defaults to True) or with a"
1505+
" storage pool type value: (azureDisk, ephemeralDisk, elasticSan)",
14931506
)
14941507
c.argument(
14951508
"disable_azure_container_storage",
1496-
arg_type=get_enum_type(disable_storage_pool_types),
1497-
help="disable azure container storage or any one of the storage pool types",
1509+
arg_type=_get_disable_azure_container_storage_type(),
1510+
help="disable azure container storage or any one of the storage pool types."
1511+
" Can be used as a flag (defaults to True) or with a storagepool type value:"
1512+
" azureDisk, ephemeralDisk, elasticSan, all (to disable all storage pools).",
1513+
)
1514+
c.argument(
1515+
"container_storage_version",
1516+
arg_type=get_enum_type(container_storage_versions),
1517+
help="set azure container storage version, the latest version will be installed by default",
14981518
)
14991519
c.argument(
15001520
"storage_pool_name",
@@ -2922,3 +2942,65 @@ def _get_default_install_location(exe_name):
29222942
else:
29232943
install_location = None
29242944
return install_location
2945+
2946+
2947+
def _get_enable_azure_container_storage_type():
2948+
"""Custom argument type that accepts both None and enum values"""
2949+
import argparse
2950+
from azure.cli.core.azclierror import InvalidArgumentValueError
2951+
2952+
class AzureContainerStorageAction(argparse.Action):
2953+
def __call__(self, parser, namespace, values, option_string=None):
2954+
if values is None:
2955+
# When used as a flag without value, set as True
2956+
setattr(namespace, self.dest, True)
2957+
return
2958+
2959+
if isinstance(values, str):
2960+
# Handle enum values (case insensitive)
2961+
for storage_type in storage_pool_types:
2962+
if values.lower() == storage_type.lower():
2963+
setattr(namespace, self.dest, storage_type)
2964+
return
2965+
2966+
# Invalid value
2967+
valid_values = storage_pool_types
2968+
raise InvalidArgumentValueError(
2969+
f"Invalid value '{values}'. Valid values are: {', '.join(valid_values)}"
2970+
)
2971+
2972+
return CLIArgumentType(
2973+
nargs='?', # Optional argument
2974+
action=AzureContainerStorageAction,
2975+
)
2976+
2977+
2978+
def _get_disable_azure_container_storage_type():
2979+
"""Custom argument type that accepts both None and enum values"""
2980+
import argparse
2981+
from azure.cli.core.azclierror import InvalidArgumentValueError
2982+
2983+
class AzureContainerStorageAction(argparse.Action):
2984+
def __call__(self, parser, namespace, values, option_string=None):
2985+
if values is None:
2986+
# When used as a flag without value, set as True
2987+
setattr(namespace, self.dest, True)
2988+
return
2989+
2990+
if isinstance(values, str):
2991+
# Handle enum values (case insensitive)
2992+
for storage_type in disable_storage_pool_types:
2993+
if values.lower() == storage_type.lower():
2994+
setattr(namespace, self.dest, storage_type)
2995+
return
2996+
2997+
# Invalid value
2998+
valid_values = disable_storage_pool_types
2999+
raise InvalidArgumentValueError(
3000+
f"Invalid value '{values}'. Valid values are: {', '.join(valid_values)}"
3001+
)
3002+
3003+
return CLIArgumentType(
3004+
nargs='?', # Optional argument
3005+
action=AzureContainerStorageAction,
3006+
)

src/aks-preview/azext_aks_preview/azurecontainerstorage/_consts.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,17 @@
66
CONST_ACSTOR_ALL = "all"
77
CONST_ACSTOR_IO_ENGINE_LABEL_KEY = "acstor.azure.com/io-engine"
88
CONST_ACSTOR_IO_ENGINE_LABEL_VAL = "acstor"
9-
CONST_ACSTOR_K8S_EXTENSION_NAME = "microsoft.azurecontainerstorage"
9+
CONST_ACSTOR_V1_K8S_EXTENSION_NAME = "microsoft.azurecontainerstorage"
10+
CONST_ACSTOR_V1_EXT_INSTALLATION_NAME = "azurecontainerstorage"
11+
CONST_ACSTOR_VERSION_V1 = "1"
1012
CONST_DISK_TYPE_EPHEMERAL_VOLUME_ONLY = "EphemeralVolumeOnly"
1113
CONST_DISK_TYPE_PV_WITH_ANNOTATION = "PersistentVolumeWithAnnotation"
1214
CONST_EPHEMERAL_NVME_PERF_TIER_BASIC = "Basic"
1315
CONST_EPHEMERAL_NVME_PERF_TIER_PREMIUM = "Premium"
1416
CONST_EPHEMERAL_NVME_PERF_TIER_STANDARD = "Standard"
15-
CONST_EXT_INSTALLATION_NAME = "azurecontainerstorage"
17+
CONST_ACSTOR_EXT_INSTALLATION_NAME = "acstor"
18+
CONST_ACSTOR_EXT_INSTALLATION_NAMESPACE = "kube-system"
19+
CONST_ACSTOR_K8S_EXTENSION_NAME = "microsoft.azurecontainerstoragev2"
1620
CONST_K8S_EXTENSION_CLIENT_FACTORY_MOD_NAME = "azext_k8s_extension._client_factory"
1721
CONST_K8S_EXTENSION_CUSTOM_MOD_NAME = "azext_k8s_extension.custom"
1822
CONST_K8S_EXTENSION_NAME = "k8s-extension"

src/aks-preview/azext_aks_preview/azurecontainerstorage/_helpers.py

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,11 @@
88
from azext_aks_preview.azurecontainerstorage._consts import (
99
CONST_ACSTOR_ALL,
1010
CONST_ACSTOR_IO_ENGINE_LABEL_KEY,
11-
CONST_ACSTOR_K8S_EXTENSION_NAME,
1211
CONST_DISK_TYPE_EPHEMERAL_VOLUME_ONLY,
1312
CONST_DISK_TYPE_PV_WITH_ANNOTATION,
1413
CONST_EPHEMERAL_NVME_PERF_TIER_BASIC,
1514
CONST_EPHEMERAL_NVME_PERF_TIER_PREMIUM,
1615
CONST_EPHEMERAL_NVME_PERF_TIER_STANDARD,
17-
CONST_EXT_INSTALLATION_NAME,
1816
CONST_K8S_EXTENSION_CLIENT_FACTORY_MOD_NAME,
1917
CONST_K8S_EXTENSION_CUSTOM_MOD_NAME,
2018
CONST_K8S_EXTENSION_NAME,
@@ -23,13 +21,15 @@
2321
CONST_STORAGE_POOL_TYPE_AZURE_DISK,
2422
CONST_STORAGE_POOL_TYPE_ELASTIC_SAN,
2523
CONST_STORAGE_POOL_TYPE_EPHEMERAL_DISK,
24+
CONST_ACSTOR_V1_K8S_EXTENSION_NAME,
25+
CONST_ACSTOR_V1_EXT_INSTALLATION_NAME,
2626
)
2727
from azure.cli.command_modules.acs._roleassignments import (
2828
add_role_assignment,
2929
build_role_scope,
3030
delete_role_assignments,
3131
)
32-
from azure.cli.core.azclierror import UnknownError
32+
from azure.cli.core.azclierror import ResourceNotFoundError, UnknownError
3333
from knack.log import get_logger
3434

3535
logger = get_logger(__name__)
@@ -133,12 +133,12 @@ def check_if_extension_is_installed(cmd, resource_group, cluster_name) -> bool:
133133
client,
134134
resource_group,
135135
cluster_name,
136-
CONST_EXT_INSTALLATION_NAME,
136+
CONST_ACSTOR_V1_EXT_INSTALLATION_NAME,
137137
"managedClusters",
138138
)
139139

140140
extension_type = extension.extension_type.lower()
141-
if extension_type != CONST_ACSTOR_K8S_EXTENSION_NAME:
141+
if extension_type != CONST_ACSTOR_V1_K8S_EXTENSION_NAME:
142142
return_val = False
143143
except: # pylint: disable=bare-except
144144
return_val = False
@@ -177,11 +177,11 @@ def get_extension_installed_and_cluster_configs(
177177
client,
178178
resource_group,
179179
cluster_name,
180-
CONST_EXT_INSTALLATION_NAME,
180+
CONST_ACSTOR_V1_EXT_INSTALLATION_NAME,
181181
"managedClusters",
182182
)
183183

184-
is_extension_installed = extension.extension_type.lower() == CONST_ACSTOR_K8S_EXTENSION_NAME
184+
is_extension_installed = extension.extension_type.lower() == CONST_ACSTOR_V1_K8S_EXTENSION_NAME
185185
config_settings = extension.configuration_settings
186186

187187
if is_extension_installed and config_settings is not None:
@@ -252,6 +252,35 @@ def get_extension_installed_and_cluster_configs(
252252
)
253253

254254

255+
def get_container_storage_extension_installed(
256+
cmd,
257+
resource_group,
258+
cluster_name,
259+
extension_name,
260+
) -> Tuple[bool, str]:
261+
262+
client_factory = get_k8s_extension_module(CONST_K8S_EXTENSION_CLIENT_FACTORY_MOD_NAME)
263+
client = client_factory.cf_k8s_extension_operation(cmd.cli_ctx)
264+
k8s_extension_custom_mod = get_k8s_extension_module(CONST_K8S_EXTENSION_CUSTOM_MOD_NAME)
265+
is_extension_installed = False
266+
extension_version = ""
267+
268+
try:
269+
extension = k8s_extension_custom_mod.show_k8s_extension(
270+
client,
271+
resource_group,
272+
cluster_name,
273+
extension_name,
274+
"managedClusters",
275+
)
276+
is_extension_installed = True
277+
extension_version = extension.current_version
278+
except ResourceNotFoundError:
279+
# Extension not found, which is expected if not installed.
280+
is_extension_installed = False
281+
return is_extension_installed, extension_version
282+
283+
255284
def get_initial_resource_value_args(
256285
storage_pool_type,
257286
storage_pool_option,

0 commit comments

Comments
 (0)