From c00b08de2630051c2986529add259f472b88c151 Mon Sep 17 00:00:00 2001 From: Zhiyi Huang <17182306+calvinhzy@users.noreply.github.com> Date: Thu, 2 Nov 2023 15:54:06 +0800 Subject: [PATCH] [Storage] `az storage account migration start/show`: Support customer inititated migration between replication options (#27692) * customer init migration ga, move from extension * use StorageAccountPreparer --- .../cli/command_modules/storage/__init__.py | 11 + .../command_modules/storage/aaz/__init__.py | 6 + .../storage/aaz/latest/__init__.py | 6 + .../storage/aaz/latest/storage/__cmd_group.py | 23 ++ .../storage/aaz/latest/storage/__init__.py | 11 + .../aaz/latest/storage/account/__cmd_group.py | 23 ++ .../aaz/latest/storage/account/__init__.py | 11 + .../storage/account/migration/__cmd_group.py | 23 ++ .../storage/account/migration/__init__.py | 13 ++ .../latest/storage/account/migration/_show.py | 209 ++++++++++++++++++ .../storage/account/migration/_start.py | 206 +++++++++++++++++ .../test_storage_account_migration.yaml | 100 +++++++++ .../latest/test_storage_account_scenarios.py | 13 +- 13 files changed, 654 insertions(+), 1 deletion(-) create mode 100644 src/azure-cli/azure/cli/command_modules/storage/aaz/__init__.py create mode 100644 src/azure-cli/azure/cli/command_modules/storage/aaz/latest/__init__.py create mode 100644 src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/__cmd_group.py create mode 100644 src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/__init__.py create mode 100644 src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/__cmd_group.py create mode 100644 src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/__init__.py create mode 100644 src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/migration/__cmd_group.py create mode 100644 src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/migration/__init__.py create mode 100644 src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/migration/_show.py create mode 100644 src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/migration/_start.py create mode 100644 src/azure-cli/azure/cli/command_modules/storage/tests/latest/recordings/test_storage_account_migration.yaml diff --git a/src/azure-cli/azure/cli/command_modules/storage/__init__.py b/src/azure-cli/azure/cli/command_modules/storage/__init__.py index 3e337459fbf..ca66325ab92 100644 --- a/src/azure-cli/azure/cli/command_modules/storage/__init__.py +++ b/src/azure-cli/azure/cli/command_modules/storage/__init__.py @@ -23,6 +23,17 @@ def __init__(self, cli_ctx=None): def load_command_table(self, args): from azure.cli.command_modules.storage.commands import load_command_table + from azure.cli.core.aaz import load_aaz_command_table + try: + from . import aaz + except ImportError: + aaz = None + if aaz: + load_aaz_command_table( + loader=self, + aaz_pkg_name=aaz.__name__, + args=args + ) load_command_table(self, args) return self.command_table diff --git a/src/azure-cli/azure/cli/command_modules/storage/aaz/__init__.py b/src/azure-cli/azure/cli/command_modules/storage/aaz/__init__.py new file mode 100644 index 00000000000..5757aea3175 --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/storage/aaz/__init__.py @@ -0,0 +1,6 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# +# Code generated by aaz-dev-tools +# -------------------------------------------------------------------------------------------- diff --git a/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/__init__.py b/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/__init__.py new file mode 100644 index 00000000000..5757aea3175 --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/__init__.py @@ -0,0 +1,6 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# +# Code generated by aaz-dev-tools +# -------------------------------------------------------------------------------------------- diff --git a/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/__cmd_group.py b/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/__cmd_group.py new file mode 100644 index 00000000000..579d8b500eb --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/__cmd_group.py @@ -0,0 +1,23 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# +# Code generated by aaz-dev-tools +# -------------------------------------------------------------------------------------------- + +# pylint: skip-file +# flake8: noqa + +from azure.cli.core.aaz import * + + +@register_command_group( + "storage", +) +class __CMDGroup(AAZCommandGroup): + """Manage Azure Cloud Storage resources. + """ + pass + + +__all__ = ["__CMDGroup"] diff --git a/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/__init__.py b/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/__init__.py new file mode 100644 index 00000000000..5a9d61963d6 --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/__init__.py @@ -0,0 +1,11 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# +# Code generated by aaz-dev-tools +# -------------------------------------------------------------------------------------------- + +# pylint: skip-file +# flake8: noqa + +from .__cmd_group import * diff --git a/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/__cmd_group.py b/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/__cmd_group.py new file mode 100644 index 00000000000..24f3f1d85aa --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/__cmd_group.py @@ -0,0 +1,23 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# +# Code generated by aaz-dev-tools +# -------------------------------------------------------------------------------------------- + +# pylint: skip-file +# flake8: noqa + +from azure.cli.core.aaz import * + + +@register_command_group( + "storage account", +) +class __CMDGroup(AAZCommandGroup): + """Manage storage accounts. + """ + pass + + +__all__ = ["__CMDGroup"] diff --git a/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/__init__.py b/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/__init__.py new file mode 100644 index 00000000000..5a9d61963d6 --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/__init__.py @@ -0,0 +1,11 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# +# Code generated by aaz-dev-tools +# -------------------------------------------------------------------------------------------- + +# pylint: skip-file +# flake8: noqa + +from .__cmd_group import * diff --git a/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/migration/__cmd_group.py b/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/migration/__cmd_group.py new file mode 100644 index 00000000000..3284dedf445 --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/migration/__cmd_group.py @@ -0,0 +1,23 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# +# Code generated by aaz-dev-tools +# -------------------------------------------------------------------------------------------- + +# pylint: skip-file +# flake8: noqa + +from azure.cli.core.aaz import * + + +@register_command_group( + "storage account migration", +) +class __CMDGroup(AAZCommandGroup): + """Manage Storage Account Migration + """ + pass + + +__all__ = ["__CMDGroup"] diff --git a/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/migration/__init__.py b/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/migration/__init__.py new file mode 100644 index 00000000000..1a94969d1a6 --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/migration/__init__.py @@ -0,0 +1,13 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# +# Code generated by aaz-dev-tools +# -------------------------------------------------------------------------------------------- + +# pylint: skip-file +# flake8: noqa + +from .__cmd_group import * +from ._show import * +from ._start import * diff --git a/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/migration/_show.py b/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/migration/_show.py new file mode 100644 index 00000000000..e6c76426d88 --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/migration/_show.py @@ -0,0 +1,209 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# +# Code generated by aaz-dev-tools +# -------------------------------------------------------------------------------------------- + +# pylint: skip-file +# flake8: noqa + +from azure.cli.core.aaz import * + + +@register_command( + "storage account migration show", +) +class Show(AAZCommand): + """Get the status of the ongoing migration for the specified storage account. + + :example: migration show + az storage account migration show --account-name "storage_account_name" -g "resource_group_name" + """ + + _aaz_info = { + "version": "2023-01-01", + "resources": [ + ["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.storage/storageaccounts/{}/accountmigrations/{}", "2023-01-01"], + ] + } + + def _handler(self, command_args): + super()._handler(command_args) + self._execute_operations() + return self._output() + + _args_schema = None + + @classmethod + def _build_arguments_schema(cls, *args, **kwargs): + if cls._args_schema is not None: + return cls._args_schema + cls._args_schema = super()._build_arguments_schema(*args, **kwargs) + + # define Arg Group "" + + _args_schema = cls._args_schema + _args_schema.account_name = AAZStrArg( + options=["--account-name"], + help="The name of the storage account within the specified resource group. Storage account names must be between 3 and 24 characters in length and use numbers and lower-case letters only.", + required=True, + id_part="name", + fmt=AAZStrArgFormat( + pattern="^[a-z0-9]+$", + max_length=24, + min_length=3, + ), + ) + _args_schema.migration_name = AAZStrArg( + options=["-n", "--name", "--migration-name"], + help="The name of the Storage Account Migration. It should always be 'default'", + required=True, + id_part="child_name_1", + enum={"default": "default"}, + fmt=AAZStrArgFormat( + pattern="^[a-z][a-z0-9]*$", + ), + ) + _args_schema.resource_group = AAZResourceGroupNameArg( + required=True, + ) + return cls._args_schema + + def _execute_operations(self): + self.pre_operations() + self.StorageAccountsGetCustomerInitiatedMigration(ctx=self.ctx)() + self.post_operations() + + @register_callback + def pre_operations(self): + pass + + @register_callback + def post_operations(self): + pass + + def _output(self, *args, **kwargs): + result = self.deserialize_output(self.ctx.vars.instance, client_flatten=True) + return result + + class StorageAccountsGetCustomerInitiatedMigration(AAZHttpOperation): + CLIENT_TYPE = "MgmtClient" + + def __call__(self, *args, **kwargs): + request = self.make_request() + session = self.client.send_request(request=request, stream=False, **kwargs) + if session.http_response.status_code in [200]: + return self.on_200(session) + + return self.on_error(session.http_response) + + @property + def url(self): + return self.client.format_url( + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Storage/storageAccounts/{accountName}/accountMigrations/{migrationName}", + **self.url_parameters + ) + + @property + def method(self): + return "GET" + + @property + def error_format(self): + return "MgmtErrorFormat" + + @property + def url_parameters(self): + parameters = { + **self.serialize_url_param( + "accountName", self.ctx.args.account_name, + required=True, + ), + **self.serialize_url_param( + "migrationName", self.ctx.args.migration_name, + required=True, + ), + **self.serialize_url_param( + "resourceGroupName", self.ctx.args.resource_group, + required=True, + ), + **self.serialize_url_param( + "subscriptionId", self.ctx.subscription_id, + required=True, + ), + } + return parameters + + @property + def query_parameters(self): + parameters = { + **self.serialize_query_param( + "api-version", "2023-01-01", + required=True, + ), + } + return parameters + + @property + def header_parameters(self): + parameters = { + **self.serialize_header_param( + "Accept", "application/json", + ), + } + return parameters + + def on_200(self, session): + data = self.deserialize_http_content(session) + self.ctx.set_var( + "instance", + data, + schema_builder=self._build_schema_on_200 + ) + + _schema_on_200 = None + + @classmethod + def _build_schema_on_200(cls): + if cls._schema_on_200 is not None: + return cls._schema_on_200 + + cls._schema_on_200 = AAZObjectType() + + _schema_on_200 = cls._schema_on_200 + _schema_on_200.id = AAZStrType( + flags={"read_only": True}, + ) + _schema_on_200.name = AAZStrType() + _schema_on_200.properties = AAZObjectType( + flags={"required": True, "client_flatten": True}, + ) + _schema_on_200.type = AAZStrType() + + properties = cls._schema_on_200.properties + properties.migration_failed_detailed_reason = AAZStrType( + serialized_name="migrationFailedDetailedReason", + flags={"read_only": True}, + ) + properties.migration_failed_reason = AAZStrType( + serialized_name="migrationFailedReason", + flags={"read_only": True}, + ) + properties.migration_status = AAZStrType( + serialized_name="migrationStatus", + flags={"read_only": True}, + ) + properties.target_sku_name = AAZStrType( + serialized_name="targetSkuName", + flags={"required": True}, + ) + + return cls._schema_on_200 + + +class _ShowHelper: + """Helper class for Show""" + + +__all__ = ["Show"] diff --git a/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/migration/_start.py b/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/migration/_start.py new file mode 100644 index 00000000000..d4fba6e9e23 --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/migration/_start.py @@ -0,0 +1,206 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# +# Code generated by aaz-dev-tools +# -------------------------------------------------------------------------------------------- + +# pylint: skip-file +# flake8: noqa + +from azure.cli.core.aaz import * + + +@register_command( + "storage account migration start", +) +class Start(AAZCommand): + """Account Migration request can be triggered for a storage account to change its redundancy level. The migration updates the non-zonal redundant storage account to a zonal redundant account or vice-versa in order to have better reliability and availability. Zone-redundant storage (ZRS) replicates your storage account synchronously across three Azure availability zones in the primary region. + + :example: migration start + az storage account migration start --account-name "storage_account_name" -g "resource_group_name" --sku Standard_ZRS --no-wait + """ + + _aaz_info = { + "version": "2023-01-01", + "resources": [ + ["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.storage/storageaccounts/{}/startaccountmigration", "2023-01-01"], + ] + } + + AZ_SUPPORT_NO_WAIT = True + + def _handler(self, command_args): + super()._handler(command_args) + return self.build_lro_poller(self._execute_operations, None) + + _args_schema = None + + @classmethod + def _build_arguments_schema(cls, *args, **kwargs): + if cls._args_schema is not None: + return cls._args_schema + cls._args_schema = super()._build_arguments_schema(*args, **kwargs) + + # define Arg Group "" + + _args_schema = cls._args_schema + _args_schema.account_name = AAZStrArg( + options=["--account-name"], + help="The name of the storage account within the specified resource group. Storage account names must be between 3 and 24 characters in length and use numbers and lower-case letters only.", + required=True, + id_part="name", + fmt=AAZStrArgFormat( + pattern="^[a-z0-9]+$", + max_length=24, + min_length=3, + ), + ) + _args_schema.resource_group = AAZResourceGroupNameArg( + required=True, + ) + + # define Arg Group "Parameters" + + _args_schema = cls._args_schema + _args_schema.name = AAZStrArg( + options=["--name"], + arg_group="Parameters", + help="current value is 'default' for customer initiated migration", + ) + _args_schema.type = AAZStrArg( + options=["--type"], + arg_group="Parameters", + help="SrpAccountMigrationType in ARM contract which is 'accountMigrations'", + ) + + # define Arg Group "Properties" + + _args_schema = cls._args_schema + _args_schema.target_sku_name = AAZStrArg( + options=["--sku", "--target-sku-name"], + arg_group="Properties", + help="Target sku name for the account", + required=True, + enum={"Premium_LRS": "Premium_LRS", "Premium_ZRS": "Premium_ZRS", "Standard_GRS": "Standard_GRS", "Standard_GZRS": "Standard_GZRS", "Standard_LRS": "Standard_LRS", "Standard_RAGRS": "Standard_RAGRS", "Standard_RAGZRS": "Standard_RAGZRS", "Standard_ZRS": "Standard_ZRS"}, + ) + return cls._args_schema + + def _execute_operations(self): + self.pre_operations() + yield self.StorageAccountsCustomerInitiatedMigration(ctx=self.ctx)() + self.post_operations() + + @register_callback + def pre_operations(self): + pass + + @register_callback + def post_operations(self): + pass + + class StorageAccountsCustomerInitiatedMigration(AAZHttpOperation): + CLIENT_TYPE = "MgmtClient" + + def __call__(self, *args, **kwargs): + request = self.make_request() + session = self.client.send_request(request=request, stream=False, **kwargs) + if session.http_response.status_code in [202]: + return self.client.build_lro_polling( + self.ctx.args.no_wait, + session, + self.on_200, + self.on_error, + lro_options={"final-state-via": "location"}, + path_format_arguments=self.url_parameters, + ) + if session.http_response.status_code in [200]: + return self.client.build_lro_polling( + self.ctx.args.no_wait, + session, + self.on_200, + self.on_error, + lro_options={"final-state-via": "location"}, + path_format_arguments=self.url_parameters, + ) + + return self.on_error(session.http_response) + + @property + def url(self): + return self.client.format_url( + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Storage/storageAccounts/{accountName}/startAccountMigration", + **self.url_parameters + ) + + @property + def method(self): + return "POST" + + @property + def error_format(self): + return "MgmtErrorFormat" + + @property + def url_parameters(self): + parameters = { + **self.serialize_url_param( + "accountName", self.ctx.args.account_name, + required=True, + ), + **self.serialize_url_param( + "resourceGroupName", self.ctx.args.resource_group, + required=True, + ), + **self.serialize_url_param( + "subscriptionId", self.ctx.subscription_id, + required=True, + ), + } + return parameters + + @property + def query_parameters(self): + parameters = { + **self.serialize_query_param( + "api-version", "2023-01-01", + required=True, + ), + } + return parameters + + @property + def header_parameters(self): + parameters = { + **self.serialize_header_param( + "Content-Type", "application/json", + ), + } + return parameters + + @property + def content(self): + _content_value, _builder = self.new_content_builder( + self.ctx.args, + typ=AAZObjectType, + typ_kwargs={"flags": {"required": True, "client_flatten": True}} + ) + _builder.set_prop("name", AAZStrType, ".name") + _builder.set_prop("properties", AAZObjectType, ".", typ_kwargs={"flags": {"required": True, "client_flatten": True}}) + _builder.set_prop("type", AAZStrType, ".type") + + properties = _builder.get(".properties") + if properties is not None: + properties.set_prop("targetSkuName", AAZStrType, ".target_sku_name", typ_kwargs={"flags": {"required": True}}) + + return self.serialize_content(_content_value) + + def on_200(self, session): + pass + + +class _StartHelper: + """Helper class for Start""" + + +__all__ = ["Start"] diff --git a/src/azure-cli/azure/cli/command_modules/storage/tests/latest/recordings/test_storage_account_migration.yaml b/src/azure-cli/azure/cli/command_modules/storage/tests/latest/recordings/test_storage_account_migration.yaml new file mode 100644 index 00000000000..80cab3537a7 --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/storage/tests/latest/recordings/test_storage_account_migration.yaml @@ -0,0 +1,100 @@ +interactions: +- request: + body: '{"properties": {"targetSkuName": "Standard_ZRS"}}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - storage account migration start + Connection: + - keep-alive + Content-Length: + - '49' + Content-Type: + - application/json + ParameterSetName: + - --account-name -g --sku --no-wait + User-Agent: + - AZURECLI/2.53.0 (PIP) (AAZ) azsdk-python-core/1.26.0 Python/3.9.13 (Windows-10-10.0.19045-SP0) + method: POST + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.Storage/storageAccounts/clitest000002/startAccountMigration?api-version=2023-01-01 + response: + body: + string: '' + headers: + azure-asyncoperation: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Storage/locations/eastus2euap/asyncoperations/fcbf86f3-5e3e-474b-821f-8ab02facc198?monitor=true&api-version=2023-01-01&t=638345051060070784&c=MIIHHjCCBgagAwIBAgITOgHct7O3aN_KxDKNJwAEAdy3szANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjMwODAyMDc1ODI0WhcNMjQwNzI3MDc1ODI0WjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALgLnSbzEbFP5vuRFjPkIRVhgz-iw8NSD7e9KiRk9joLl4YrnC0aSuKwshRe9v_Gl--CqxXgkcpCrfdylaxeXPCqPbSAySW8ZXeSDzD35sq_pFnpKhucgB99Ge-e1unJgvYfJTi3-ri0oDMpryPjlj-DSAQ7LPz35cKSbzFYKu3mynC6wWObzCuwGt5qbJ4uxeqzSw_EaLK0-6awwn50lVsKnZtiZhdfHXDKKLap7dLAww0CM1k9FmqGvlSPIwLevHqzTzDqw1Z7aqoRUH_sezhZxKvKw2KKL0h73J1uStBKaiwxPh-9JrGtrp5emkNsj2V-tuOQ7sam3Z3urFRWBZECAwEAAaOCBAswggQHMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBSNta6Ow680k6ap_o_3ZKd0BukJQTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMBcGA1UdIAQQMA4wDAYKKwYBBAGCN3sBATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAJfhqigISSFkp5G5sHIg7shqgq0nMu4ZkrFytKYoj9nyIkbp5wS2S2SnxApbk6DGfCopeW2bT-41LuABxrpHhInxdQRwc4hfNkVg5k48jbSkaP4RnY52VT70kH2vngG3zDcpdl_UdtXj5qCzEffHV2Z3zbzv9rw860jZIwkZ5VGmoYo9ghHXoYX5lQ9pm0T-M7GhW078gGjajjGJ-eR5CQ4ffnR5kBJRVe1B_S-nfakCqELdfDewiO64-k_-8RAsHI75vUnI6S_RQfa0Gah60wAwOXXXGRzSb-m5tvKIgqVb46MPp9rK1HgwcUkvk_MeoI2XtXUN_SW2uRXCFp9U_Po&s=Xq-5xUUz55Dx30q-KsFz_EZXAPxEcKWWDW7RHq_NkH156gQXkjr7JWnii6mkelczI60U3beGCOvK29ajFvfkyivUPDLd-AQawYGmTu2QKxp9yDqSSe8_fl_-g2CaEFz1KNc-3Couh4Ygf8RJNuE_Ex-8i0yGqulzUEL1xPC_2pbQ4BPD1Q3i8uhshHVlaBQ6EeFB0HEu_1wzq_b6gJaFZaHWBu2ROwF_C2Rjc_QoFcRuInxVU_lYDGB4tpo2_5qkGGTTJNz5J7i474VxtG_z22rKcwAjqm3Uxnt88hSixQXlrg44b9xoPWkZGNhHUlg_T1PtVUE_wZRqA1c0yThxlQ&h=uaRkP3i6-GLXOFT2gndR4rkq4dBDFgsXaYQV6I32O4w + cache-control: + - no-cache + content-length: + - '0' + content-type: + - text/plain; charset=utf-8 + date: + - Thu, 02 Nov 2023 06:58:25 GMT + expires: + - '-1' + location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Storage/locations/eastus2euap/asyncoperations/fcbf86f3-5e3e-474b-821f-8ab02facc198?monitor=true&api-version=2023-01-01&t=638345051060227154&c=MIIHHjCCBgagAwIBAgITOgHct7O3aN_KxDKNJwAEAdy3szANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjMwODAyMDc1ODI0WhcNMjQwNzI3MDc1ODI0WjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALgLnSbzEbFP5vuRFjPkIRVhgz-iw8NSD7e9KiRk9joLl4YrnC0aSuKwshRe9v_Gl--CqxXgkcpCrfdylaxeXPCqPbSAySW8ZXeSDzD35sq_pFnpKhucgB99Ge-e1unJgvYfJTi3-ri0oDMpryPjlj-DSAQ7LPz35cKSbzFYKu3mynC6wWObzCuwGt5qbJ4uxeqzSw_EaLK0-6awwn50lVsKnZtiZhdfHXDKKLap7dLAww0CM1k9FmqGvlSPIwLevHqzTzDqw1Z7aqoRUH_sezhZxKvKw2KKL0h73J1uStBKaiwxPh-9JrGtrp5emkNsj2V-tuOQ7sam3Z3urFRWBZECAwEAAaOCBAswggQHMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBSNta6Ow680k6ap_o_3ZKd0BukJQTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMBcGA1UdIAQQMA4wDAYKKwYBBAGCN3sBATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAJfhqigISSFkp5G5sHIg7shqgq0nMu4ZkrFytKYoj9nyIkbp5wS2S2SnxApbk6DGfCopeW2bT-41LuABxrpHhInxdQRwc4hfNkVg5k48jbSkaP4RnY52VT70kH2vngG3zDcpdl_UdtXj5qCzEffHV2Z3zbzv9rw860jZIwkZ5VGmoYo9ghHXoYX5lQ9pm0T-M7GhW078gGjajjGJ-eR5CQ4ffnR5kBJRVe1B_S-nfakCqELdfDewiO64-k_-8RAsHI75vUnI6S_RQfa0Gah60wAwOXXXGRzSb-m5tvKIgqVb46MPp9rK1HgwcUkvk_MeoI2XtXUN_SW2uRXCFp9U_Po&s=STZAM2kOgI1h864rZ87qfM2DdC3IeeY4NPY9nIijhkaf5e_QDvh2cgt-wNER17ROrNXEMMTxTOp0R5asYy8M4vkBKIkB0BIPXq2Nfh9xhuW1LQje_Cn4vdxUct-I1iyeh2brYnomARJJqCmcF-EySsLBGqlEG0CFgthihXkNSMnA_nZ0Zczh1qIZ7AjSOqsWl62ngREJSU3PfL3gREqa9mTSuMH1a7KaIgLXP77BZWGv_aq0H6ax5SYhpyuTFTPCbxqER2YMiseQOLSpiVQF20xG9BA9-Zks4xWKuEnOJAXk6HmG7T82MIWic0IieHK-9lkQJrB-pW3QNa0wz8oxcQ&h=pEna1t8BCpmiQW9RejqA8Tukzef6he5AS9a43NhlpMM + pragma: + - no-cache + server: + - Microsoft-Azure-Storage-Resource-Provider/1.0,Microsoft-HTTPAPI/2.0 Microsoft-HTTPAPI/2.0 + strict-transport-security: + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + x-ms-ratelimit-remaining-subscription-writes: + - '1199' + status: + code: 202 + message: Accepted +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - storage account migration show + Connection: + - keep-alive + ParameterSetName: + - -n -g --account-name + User-Agent: + - AZURECLI/2.53.0 (PIP) (AAZ) azsdk-python-core/1.26.0 Python/3.9.13 (Windows-10-10.0.19045-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.Storage/storageAccounts/clitest000002/accountMigrations/default?api-version=2023-01-01 + response: + body: + string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.Storage/storageAccounts/clitest000002/accountMigrations/default","name":"default","type":"Microsoft.Storage/storageAccounts/accountMigrations","properties":{"targetSkuName":"Standard_ZRS","migrationStatus":"SubmittedForConversion"}}' + headers: + cache-control: + - no-cache + content-length: + - '343' + content-type: + - application/json + date: + - Thu, 02 Nov 2023 06:58:26 GMT + expires: + - '-1' + pragma: + - no-cache + server: + - Microsoft-Azure-Storage-Resource-Provider/1.0,Microsoft-HTTPAPI/2.0 Microsoft-HTTPAPI/2.0 + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + vary: + - Accept-Encoding + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +version: 1 diff --git a/src/azure-cli/azure/cli/command_modules/storage/tests/latest/test_storage_account_scenarios.py b/src/azure-cli/azure/cli/command_modules/storage/tests/latest/test_storage_account_scenarios.py index 145bdacabfa..576a9a6eb3b 100644 --- a/src/azure-cli/azure/cli/command_modules/storage/tests/latest/test_storage_account_scenarios.py +++ b/src/azure-cli/azure/cli/command_modules/storage/tests/latest/test_storage_account_scenarios.py @@ -1784,6 +1784,17 @@ def test_storage_account_extended_location(self, resource_group): self.cmd('storage container create -n {container} --account-name {sa1} --blob-endpoint {endpoint} --account-key {storage_key}') \ .assert_with_checks(self.check('created', True)) + @ResourceGroupPreparer(location='eastus2euap') + @StorageAccountPreparer(location='eastus2euap', kind='StorageV2') + def test_storage_account_migration(self, resource_group, storage_account): + self.kwargs.update({ + 'sa': storage_account + }) + self.cmd('az storage account migration start --account-name {sa} -g {rg} --sku Standard_ZRS --no-wait') + # other status would take days to months + self.cmd('az storage account migration show -n default -g {rg} --account-name {sa}', + checks=[JMESPathCheck('migrationStatus', 'SubmittedForConversion')]) + class RoleScenarioTest(LiveScenarioTest): def run_under_service_principal(self): @@ -2787,4 +2798,4 @@ def test_storage_account_local_user(self, resource_group, storage_account): JMESPathCheckExists('sshPassword') ) - self.cmd('{cmd} delete --account-name {sa} -g {rg} -n {username}') \ No newline at end of file + self.cmd('{cmd} delete --account-name {sa} -g {rg} -n {username}')