Skip to content

Commit dc07baf

Browse files
authored
[AKS] az aks create/update: Add ephemeralDisk and elasticSan storag… (#32558)
1 parent 58ea0ac commit dc07baf

File tree

6 files changed

+339
-177
lines changed

6 files changed

+339
-177
lines changed

src/azure-cli/azure/cli/command_modules/acs/_params.py

Lines changed: 14 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -558,7 +558,7 @@ def load_arguments(self, _):
558558
# azure container storage
559559
c.argument(
560560
"enable_azure_container_storage",
561-
arg_type=_get_enable_azure_container_storage_type(),
561+
arg_type=_get_container_storage_enum_type(storage_pool_types),
562562
help="enable azure container storage. Can be used as a flag (defaults to True) or with a storage pool type value: (azureDisk, ephemeralDisk, elasticSan)",
563563
)
564564
c.argument(
@@ -764,12 +764,12 @@ def load_arguments(self, _):
764764
# azure container storage
765765
c.argument(
766766
"enable_azure_container_storage",
767-
arg_type=_get_enable_azure_container_storage_type(),
767+
arg_type=_get_container_storage_enum_type(storage_pool_types),
768768
help="enable azure container storage. Can be used as a flag (defaults to True) or with a storage pool type value: (azureDisk, ephemeralDisk, elasticSan)",
769769
)
770770
c.argument(
771771
"disable_azure_container_storage",
772-
arg_type=_get_disable_azure_container_storage_type(),
772+
arg_type=_get_container_storage_enum_type(disable_storage_pool_types),
773773
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).",
774774
)
775775
c.argument(
@@ -1286,63 +1286,33 @@ def _get_default_install_location(exe_name):
12861286
return install_location
12871287

12881288

1289-
def _get_enable_azure_container_storage_type():
1289+
def _get_container_storage_enum_type(choices):
12901290
"""Custom argument type that accepts both None and enum values"""
12911291
import argparse
12921292
from azure.cli.core.azclierror import InvalidArgumentValueError
12931293

12941294
class AzureContainerStorageAction(argparse.Action):
12951295
def __call__(self, parser, namespace, values, option_string=None):
1296-
if values is None:
1296+
if values in [[], None]:
12971297
# When used as a flag without value, set as True
12981298
setattr(namespace, self.dest, True)
12991299
return
13001300

1301-
if isinstance(values, str):
1302-
# Handle enum values (case insensitive)
1303-
for storage_type in storage_pool_types:
1304-
if values.lower() == storage_type.lower():
1305-
setattr(namespace, self.dest, storage_type)
1306-
return
1307-
1308-
# Invalid value
1309-
valid_values = storage_pool_types
1310-
raise InvalidArgumentValueError(
1311-
f"Invalid value '{values}'. Valid values are: {', '.join(valid_values)}"
1312-
)
1313-
1314-
return CLIArgumentType(
1315-
nargs='?', # Optional argument
1316-
action=AzureContainerStorageAction,
1317-
)
1318-
1319-
1320-
def _get_disable_azure_container_storage_type():
1321-
"""Custom argument type that accepts both None and enum values"""
1322-
import argparse
1323-
from azure.cli.core.azclierror import InvalidArgumentValueError
1324-
1325-
class AzureContainerStorageAction(argparse.Action):
1326-
def __call__(self, parser, namespace, values, option_string=None):
1327-
if values is None:
1328-
# When used as a flag without value, set as True
1329-
setattr(namespace, self.dest, True)
1301+
# Allow multiple enum values in a case insensitive manner
1302+
normalized_value_arr = values if isinstance(values, list) else str(values).split(',')
1303+
normalized_value_arr = [str(v).lower().strip() for v in normalized_value_arr]
1304+
valid_value_arr = [v for v in choices if v.lower() in normalized_value_arr]
1305+
if len(valid_value_arr) == len(normalized_value_arr):
1306+
normalized_values = valid_value_arr[0] if len(valid_value_arr) == 1 else valid_value_arr
1307+
setattr(namespace, self.dest, normalized_values)
13301308
return
13311309

1332-
if isinstance(values, str):
1333-
# Handle enum values (case insensitive)
1334-
for storage_type in disable_storage_pool_types:
1335-
if values.lower() == storage_type.lower():
1336-
setattr(namespace, self.dest, storage_type)
1337-
return
1338-
13391310
# Invalid value
1340-
valid_values = disable_storage_pool_types
13411311
raise InvalidArgumentValueError(
1342-
f"Invalid value '{values}'. Valid values are: {', '.join(valid_values)}"
1312+
f"Invalid value '{values}'. Valid values are: {', '.join(choices)}"
13431313
)
13441314

13451315
return CLIArgumentType(
1346-
nargs='?', # Optional argument
1316+
nargs='*', # Allow multiple values
13471317
action=AzureContainerStorageAction,
13481318
)

src/azure-cli/azure/cli/command_modules/acs/azurecontainerstorage/_helpers.py

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77

88
from azure.cli.command_modules.acs.azurecontainerstorage._consts import (
99
CONST_ACSTOR_ALL,
10+
CONST_ACSTOR_EXT_INSTALLATION_NAME,
1011
CONST_ACSTOR_IO_ENGINE_LABEL_KEY,
12+
CONST_ACSTOR_K8S_EXTENSION_NAME,
1113
CONST_ACSTOR_V1_K8S_EXTENSION_NAME,
1214
CONST_DISK_TYPE_EPHEMERAL_VOLUME_ONLY,
1315
CONST_DISK_TYPE_PV_WITH_ANNOTATION,
@@ -146,7 +148,7 @@ def check_if_extension_is_installed(cmd, resource_group, cluster_name) -> bool:
146148
return return_val
147149

148150

149-
def get_extension_installed_and_cluster_configs(
151+
def get_extension_installed_and_cluster_configs_v1(
150152
cmd,
151153
resource_group,
152154
cluster_name,
@@ -245,6 +247,56 @@ def get_extension_installed_and_cluster_configs(
245247
)
246248

247249

250+
def get_extension_installed_and_cluster_configs(
251+
cmd,
252+
resource_group,
253+
cluster_name
254+
) -> Tuple[bool, bool, bool]:
255+
client_factory = get_k8s_extension_module(CONST_K8S_EXTENSION_CLIENT_FACTORY_MOD_NAME)
256+
client = client_factory.cf_k8s_extension_operation(cmd.cli_ctx)
257+
k8s_extension_custom_mod = get_k8s_extension_module(CONST_K8S_EXTENSION_CUSTOM_MOD_NAME)
258+
is_extension_installed = False
259+
is_ephemeral_disk_enabled = False
260+
is_elastic_san_enabled = False
261+
262+
try:
263+
extension = k8s_extension_custom_mod.show_k8s_extension(
264+
client,
265+
resource_group,
266+
cluster_name,
267+
CONST_ACSTOR_EXT_INSTALLATION_NAME,
268+
"managedClusters",
269+
)
270+
271+
extension_type = extension.extension_type.lower()
272+
is_extension_installed = extension_type == CONST_ACSTOR_K8S_EXTENSION_NAME
273+
config_settings = extension.configuration_settings
274+
275+
if is_extension_installed and config_settings is not None:
276+
is_ephemeral_disk_enabled = (
277+
config_settings.get("csiDriverConfigs.local-csi-driver.enabled", "False") == "True"
278+
)
279+
is_elastic_san_enabled = (
280+
config_settings.get("csiDriverConfigs.azuresan-csi-driver.enabled", "False") == "True"
281+
)
282+
283+
except: # pylint: disable=bare-except
284+
is_extension_installed = False
285+
286+
return (
287+
is_extension_installed,
288+
is_ephemeral_disk_enabled,
289+
is_elastic_san_enabled,
290+
)
291+
292+
293+
def should_delete_extension(storage_options_to_remove) -> bool:
294+
return (
295+
storage_options_to_remove in [True, CONST_ACSTOR_ALL] or
296+
(isinstance(storage_options_to_remove, list) and CONST_ACSTOR_ALL in storage_options_to_remove)
297+
)
298+
299+
248300
def get_container_storage_extension_installed(
249301
cmd,
250302
resource_group,

src/azure-cli/azure/cli/command_modules/acs/azurecontainerstorage/_validators.py

Lines changed: 51 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -432,10 +432,12 @@ def validate_enable_azure_container_storage_v1_params( # pylint: disable=too-ma
432432

433433

434434
def validate_enable_azure_container_storage_params(
435+
enablement_option,
435436
is_extension_installed,
437+
is_ephemeral_disk_enabled,
438+
is_elastic_san_enabled,
436439
is_v1_extension_installed,
437440
v1_extension_version,
438-
storage_pool_type,
439441
storage_pool_name,
440442
storage_pool_sku,
441443
storage_pool_option,
@@ -450,18 +452,28 @@ def validate_enable_azure_container_storage_params(
450452
'that depend on Azure Container Storage.'
451453
)
452454

453-
if is_extension_installed:
454-
raise InvalidArgumentValueError(
455-
'Cannot enable Azure Container Storage as it is already enabled on the cluster.'
456-
)
457-
458-
# Todo: Remove this for the 2.1.0 release
459-
if storage_pool_type is not None and not isinstance(storage_pool_type, bool):
460-
raise InvalidArgumentValueError(
461-
'The latest version of Azure Container Storage only supports ephemeral nvme storage and does not '
462-
'require or support a storage-pool-type value for --enable-azure-container-storage parameter. '
463-
f'Please remove {storage_pool_type} from the command and try again.'
464-
)
455+
if not enablement_option or enablement_option is True:
456+
if is_extension_installed:
457+
raise InvalidArgumentValueError(
458+
'Cannot enable Azure Container Storage as it is already enabled on the cluster.'
459+
)
460+
else:
461+
enablement_option_arr = enablement_option if isinstance(enablement_option, list) else [enablement_option]
462+
enable_ephemeral_disk = CONST_STORAGE_POOL_TYPE_EPHEMERAL_DISK in enablement_option
463+
enable_elastic_san = CONST_STORAGE_POOL_TYPE_ELASTIC_SAN in enablement_option
464+
for option in enablement_option_arr:
465+
if option not in [CONST_STORAGE_POOL_TYPE_EPHEMERAL_DISK, CONST_STORAGE_POOL_TYPE_ELASTIC_SAN]:
466+
raise InvalidArgumentValueError(
467+
f"Unsupported storage option '{option}'. "
468+
f"Supported values are '{CONST_STORAGE_POOL_TYPE_EPHEMERAL_DISK}' "
469+
f"and '{CONST_STORAGE_POOL_TYPE_ELASTIC_SAN}'."
470+
)
471+
if is_ephemeral_disk_enabled == enable_ephemeral_disk and is_elastic_san_enabled == enable_elastic_san:
472+
options_display = "', '".join(enablement_option_arr)
473+
raise InvalidArgumentValueError(
474+
f"Cannot enable the requested storage options ('{options_display}') "
475+
"as they are already enabled on the cluster."
476+
)
465477

466478
if storage_pool_name is not None:
467479
raise InvalidArgumentValueError(
@@ -493,25 +505,42 @@ def validate_enable_azure_container_storage_params(
493505

494506

495507
def validate_disable_azure_container_storage_params(
508+
disablement_option,
496509
is_extension_installed,
497-
storage_pool_type,
510+
is_ephemeral_disk_enabled,
511+
is_elastic_san_enabled,
498512
storage_pool_name,
499513
storage_pool_sku,
500514
storage_pool_option,
501515
storage_pool_size
502516
):
503517
if not is_extension_installed:
504518
raise InvalidArgumentValueError(
505-
'Cannot disable Azure Container Storage as it is not enabled on the cluster.'
519+
'Cannot disable Azure Container Storage as it could not be found on the cluster.'
506520
)
507521

508-
# Todo: Remove this for the 2.1.0 release
509-
if storage_pool_type is not None and not isinstance(storage_pool_type, bool):
510-
raise InvalidArgumentValueError(
511-
'The latest version of Azure Container Storage only supports ephemeral nvme storage and does not '
512-
'require or support a storage-pool-type value for --disable-azure-container-storage parameter. '
513-
f'Please remove {storage_pool_type} from the command and try again.'
514-
)
522+
if disablement_option and disablement_option not in [True, CONST_ACSTOR_ALL]:
523+
actionable = False
524+
disablement_option_arr = disablement_option if isinstance(disablement_option, list) else [disablement_option]
525+
for disable_option in disablement_option_arr:
526+
if disable_option == CONST_ACSTOR_ALL:
527+
actionable = True
528+
elif disable_option == CONST_STORAGE_POOL_TYPE_EPHEMERAL_DISK:
529+
actionable = actionable or is_ephemeral_disk_enabled
530+
elif disable_option == CONST_STORAGE_POOL_TYPE_ELASTIC_SAN:
531+
actionable = actionable or is_elastic_san_enabled
532+
else:
533+
raise InvalidArgumentValueError(
534+
f"Cannot disable unsupported storage option '{disable_option}'. "
535+
f"Supported values are '{CONST_STORAGE_POOL_TYPE_EPHEMERAL_DISK}', "
536+
f"'{CONST_STORAGE_POOL_TYPE_ELASTIC_SAN}' and '{CONST_ACSTOR_ALL}'."
537+
)
538+
if not actionable:
539+
options_display = "', '".join(disablement_option_arr)
540+
raise InvalidArgumentValueError(
541+
f"Cannot disable the requested storage options ('{options_display}') "
542+
"as they could not be found on the cluster."
543+
)
515544

516545
if storage_pool_name is not None:
517546
raise InvalidArgumentValueError(

0 commit comments

Comments
 (0)