From 082788556dd8b90b096b350566198965e492edf7 Mon Sep 17 00:00:00 2001 From: Zunli Hu Date: Wed, 19 May 2021 10:33:22 +0800 Subject: [PATCH 01/12] upgrade api version --- src/azure-cli-core/azure/cli/core/profiles/_shared.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/azure-cli-core/azure/cli/core/profiles/_shared.py b/src/azure-cli-core/azure/cli/core/profiles/_shared.py index 407b0190d34..c0ff7a46737 100644 --- a/src/azure-cli-core/azure/cli/core/profiles/_shared.py +++ b/src/azure-cli-core/azure/cli/core/profiles/_shared.py @@ -137,7 +137,7 @@ def default_api_version(self): 'latest': { ResourceType.MGMT_STORAGE: '2021-04-01', ResourceType.MGMT_NETWORK: '2021-02-01', - ResourceType.MGMT_COMPUTE: SDKProfile('2020-12-01', { + ResourceType.MGMT_COMPUTE: SDKProfile('2021-03-01', { 'resource_skus': '2019-04-01', 'disks': '2020-12-01', 'disk_encryption_sets': '2020-12-01', From 10273d3f23886b2a9e5d74c302efa8691686c8aa Mon Sep 17 00:00:00 2001 From: Zunli Hu Date: Wed, 19 May 2021 10:47:47 +0800 Subject: [PATCH 02/12] draft command design --- src/azure-cli-core/azure/cli/core/profiles/_shared.py | 2 +- src/azure-cli/azure/cli/command_modules/vm/_params.py | 7 ++++++- .../azure/cli/command_modules/vm/_template_builder.py | 7 ++++++- src/azure-cli/azure/cli/command_modules/vm/custom.py | 6 ++++-- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/azure-cli-core/azure/cli/core/profiles/_shared.py b/src/azure-cli-core/azure/cli/core/profiles/_shared.py index c0ff7a46737..69b28f90a3a 100644 --- a/src/azure-cli-core/azure/cli/core/profiles/_shared.py +++ b/src/azure-cli-core/azure/cli/core/profiles/_shared.py @@ -146,7 +146,7 @@ def default_api_version(self): 'galleries': '2019-12-01', 'gallery_images': '2020-09-30', 'gallery_image_versions': '2020-09-30', - 'virtual_machine_scale_sets': '2020-12-01' + 'virtual_machine_scale_sets': '2021-03-01' }), ResourceType.MGMT_RESOURCE_FEATURES: '2015-12-01', ResourceType.MGMT_RESOURCE_LINKS: '2016-09-01', diff --git a/src/azure-cli/azure/cli/command_modules/vm/_params.py b/src/azure-cli/azure/cli/command_modules/vm/_params.py index e733b810001..234a3314bde 100644 --- a/src/azure-cli/azure/cli/command_modules/vm/_params.py +++ b/src/azure-cli/azure/cli/command_modules/vm/_params.py @@ -569,8 +569,10 @@ def load_arguments(self, _): for dest in scaleset_name_aliases: c.argument(dest, vmss_name_type, id_part=None) # due to instance-ids parameter - with self.argument_context('vmss create') as c: + with self.argument_context('vmss create', operation_group='virtual_machine_scale_sets') as c: VirtualMachineEvictionPolicyTypes = self.get_models('VirtualMachineEvictionPolicyTypes', resource_type=ResourceType.MGMT_COMPUTE) + NetworkApiVersion = self.get_models('NetworkApiVersion', resource_type=ResourceType.MGMT_COMPUTE, + operation_group='virtual_machine_scale_sets') c.argument('name', name_arg_type) c.argument('nat_backend_port', default=None, help='Backend port to open with NAT rules. Defaults to 22 on Linux and 3389 on Windows.') c.argument('single_placement_group', arg_type=get_three_state_flag(), help="Limit the scale set to a single placement group." @@ -592,6 +594,9 @@ def load_arguments(self, _): c.argument('scale_in_policy', scale_in_policy_type) c.argument('automatic_repairs_grace_period', min_api='2018-10-01', help='The amount of time (in minutes, between 30 and 90) for which automatic repairs are suspended due to a state change on VM.') + c.argument('network_api_version', arg_type=get_enum_type(NetworkApiVersion), is_preview=True, min_api='2021-03-01', + help="Specify the Microsoft.Network API version used when creating networking resources in the Network " + "Interface Configurations for Virtual Machine Scale Set with orchestration mode 'Flexible'.") with self.argument_context('vmss create', arg_group='Network Balancer') as c: LoadBalancerSkuName = self.get_models('LoadBalancerSkuName', resource_type=ResourceType.MGMT_NETWORK) diff --git a/src/azure-cli/azure/cli/command_modules/vm/_template_builder.py b/src/azure-cli/azure/cli/command_modules/vm/_template_builder.py index 40a5ca7fc6c..9abec2cbc67 100644 --- a/src/azure-cli/azure/cli/command_modules/vm/_template_builder.py +++ b/src/azure-cli/azure/cli/command_modules/vm/_template_builder.py @@ -770,7 +770,8 @@ def build_vmss_resource(cmd, name, naming_prefix, location, tags, overprovision, specialized=None, os_disk_size_gb=None, encryption_at_host=None, host_group=None, max_batch_instance_percent=None, max_unhealthy_instance_percent=None, max_unhealthy_upgraded_instance_percent=None, pause_time_between_batches=None, - enable_cross_zone_upgrade=None, prioritize_unhealthy_instances=None, edge_zone=None): + enable_cross_zone_upgrade=None, prioritize_unhealthy_instances=None, edge_zone=None, + network_api_version=None): # Build IP configuration ip_configuration = { @@ -955,6 +956,10 @@ def build_vmss_resource(cmd, name, naming_prefix, location, tags, overprovision, if health_probe and cmd.supported_api_version(min_api='2017-03-30', operation_group='virtual_machine_scale_sets'): vmss_properties['virtualMachineProfile']['networkProfile']['healthProbe'] = {'id': health_probe} + if network_api_version and \ + cmd.supported_api_version(min_api='2021-03-01', operation_group='virtual_machine_scale_sets'): + vmss_properties['virtualMachineProfile']['networkProfile']['networkApVersion'] = network_api_version + if cmd.supported_api_version(min_api='2016-04-30-preview', operation_group='virtual_machine_scale_sets'): vmss_properties['singlePlacementGroup'] = single_placement_group diff --git a/src/azure-cli/azure/cli/command_modules/vm/custom.py b/src/azure-cli/azure/cli/command_modules/vm/custom.py index 86ea0b4f6ac..f7620d9f20b 100644 --- a/src/azure-cli/azure/cli/command_modules/vm/custom.py +++ b/src/azure-cli/azure/cli/command_modules/vm/custom.py @@ -2423,7 +2423,8 @@ def create_vmss(cmd, vmss_name, resource_group_name, image=None, automatic_repairs_grace_period=None, specialized=None, os_disk_size_gb=None, encryption_at_host=None, host_group=None, max_batch_instance_percent=None, max_unhealthy_instance_percent=None, max_unhealthy_upgraded_instance_percent=None, pause_time_between_batches=None, - enable_cross_zone_upgrade=None, prioritize_unhealthy_instances=None, edge_zone=None): + enable_cross_zone_upgrade=None, prioritize_unhealthy_instances=None, edge_zone=None, + network_api_version=None): from azure.cli.core.commands.client_factory import get_subscription_id from azure.cli.core.util import random_string, hash_string from azure.cli.core.commands.arm import ArmTemplateBuilder @@ -2662,7 +2663,8 @@ def _get_public_ip_address_allocation(value, sku): max_unhealthy_instance_percent=max_unhealthy_instance_percent, max_unhealthy_upgraded_instance_percent=max_unhealthy_upgraded_instance_percent, pause_time_between_batches=pause_time_between_batches, enable_cross_zone_upgrade=enable_cross_zone_upgrade, - prioritize_unhealthy_instances=prioritize_unhealthy_instances, edge_zone=edge_zone) + prioritize_unhealthy_instances=prioritize_unhealthy_instances, edge_zone=edge_zone, + network_api_version=network_api_version) vmss_resource['dependsOn'] = vmss_dependencies From c4ee8c6492d96c4ddd848a37ba0fd3692eb02613 Mon Sep 17 00:00:00 2001 From: Zunli Hu Date: Fri, 21 May 2021 16:12:26 +0800 Subject: [PATCH 03/12] test pass --- .../cli/command_modules/storage/_params.py | 53 +++++++-- .../command_modules/storage/_validators.py | 105 ++++++++++++++++++ .../cli/command_modules/storage/commands.py | 2 +- .../storage/operations/blob.py | 6 + .../test_storage_blob_copy_scenarios.py | 2 +- 5 files changed, 158 insertions(+), 10 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/storage/_params.py b/src/azure-cli/azure/cli/command_modules/storage/_params.py index 92b64582a1a..6bb2ff66842 100644 --- a/src/azure-cli/azure/cli/command_modules/storage/_params.py +++ b/src/azure-cli/azure/cli/command_modules/storage/_params.py @@ -186,9 +186,6 @@ def load_arguments(self, _): # pylint: disable=too-many-locals, too-many-statem help='Expiration period in days of the Key Policy assigned to the storage account' ) - t_blob_tier = self.get_sdk('_generated.models._azure_blob_storage_enums#AccessTierOptional', - resource_type=ResourceType.DATA_STORAGE_BLOB) - allow_cross_tenant_replication_type = CLIArgumentType( arg_type=get_three_state_flag(), options_list=['--allow-cross-tenant-replication', '-r'], min_api='2021-04-01', help='Allow or disallow cross AAD tenant object replication. The default interpretation is true for this ' @@ -201,6 +198,22 @@ def load_arguments(self, _): # pylint: disable=too-many-locals, too-many-statem arg_group='Azure Files Identity Based Authentication', help='Default share permission for users using Kerberos authentication if RBAC role is not assigned.') + t_blob_tier = self.get_sdk('_generated.models._azure_blob_storage_enums#AccessTierOptional', + resource_type=ResourceType.DATA_STORAGE_BLOB) + t_rehydrate_priority = self.get_sdk('_generated.models._azure_blob_storage_enums#RehydratePriority', + resource_type=ResourceType.DATA_STORAGE_BLOB) + tier_type = CLIArgumentType( + arg_type=get_enum_type(t_blob_tier), min_api='2019-02-02', + help='The tier value to set the blob to. For page blob, the tier correlates to the size of the blob ' + 'and number of allowed IOPS. Possible values are P10, P15, P20, P30, P4, P40, P50, P6, P60, P70, P80 ' + 'and this is only applicable to page blobs on premium storage accounts; For block blob, possible ' + 'values are Archive, Cool and Hot. This is only applicable to block blobs on standard storage accounts.' + ) + rehydrate_priority_type = CLIArgumentType( + arg_type=get_enum_type(t_rehydrate_priority), options_list=('--rehydrate-priority', '-r'), + min_api='2019-02-02', + help='Indicate the priority with which to rehydrate an archived blob.') + with self.argument_context('storage') as c: c.argument('container_name', container_name_type) c.argument('directory_name', directory_type) @@ -965,12 +978,36 @@ def load_arguments(self, _): # pylint: disable=too-many-locals, too-many-statem c.argument('source_lease_id', arg_group='Copy Source') with self.argument_context('storage blob copy start') as c: - from azure.cli.command_modules.storage._validators import validate_source_uri + from ._validators import validate_source_url - c.register_source_uri_arguments(validator=validate_source_uri) - c.argument('requires_sync', arg_type=get_three_state_flag(), - help='Enforce that the service will not return a response until the copy is complete.' - 'Not support for standard page blob.') + c.register_blob_arguments() + c.register_precondition_options() + c.register_precondition_options(prefix='source_') + c.register_source_uri_arguments(validator=validate_source_url) + + c.ignore('incremental_copy') + c.argument('if_match', options_list=['--destination-if-match']) + c.argument('if_modified_since', options_list=['--destination-if-modified-since']) + c.argument('if_none_match', options_list=['--destination-if-none-match']) + c.argument('if_unmodified_since', options_list=['--destination-if-unmodified-since']) + c.argument('if_tags_match_condition', options_list=['--destination-tags-condition']) + + c.argument('blob_name', options_list=['--destination-blob', '-b'], required=True, + help='Name of the destination blob. If the exists, it will be overwritten.') + c.argument('container_name', options_list=['--destination-container', '-c'], required=True, + help='The container name.') + c.extra('destination_lease', options_list='--destination-lease-id', + help='The lease ID specified for this header must match the lease ID of the estination blob. ' + 'If the request does not include the lease ID or it is not valid, the operation fails with status ' + 'code 412 (Precondition Failed).') + c.extra('source_lease', options_list='--source-lease-id', arg_group='Copy Source', + help='Specify this to perform the Copy Blob operation only if the lease ID given matches the ' + 'active lease ID of the source blob.') + c.extra('rehydrate_priority', rehydrate_priority_type) + c.extra('requires_sync', arg_type=get_three_state_flag(), + help='Enforce that the service will not return a response until the copy is complete.') + c.extra('tier', tier_type) + c.extra('tags', tags_type) with self.argument_context('storage blob copy start-batch', arg_group='Copy Source') as c: from azure.cli.command_modules.storage._validators import get_source_file_or_blob_service_client diff --git a/src/azure-cli/azure/cli/command_modules/storage/_validators.py b/src/azure-cli/azure/cli/command_modules/storage/_validators.py index e26851b3a00..f9cd7746178 100644 --- a/src/azure-cli/azure/cli/command_modules/storage/_validators.py +++ b/src/azure-cli/azure/cli/command_modules/storage/_validators.py @@ -387,6 +387,111 @@ def validate_source_uri(cmd, namespace): # pylint: disable=too-many-statements namespace.copy_source = uri +def validate_source_url(cmd, namespace): # pylint: disable=too-many-statements + from .util import create_short_lived_blob_sas, create_short_lived_file_sas + usage_string = \ + 'Invalid usage: {}. Supply only one of the following argument sets to specify source:' \ + '\n\t --source-uri [--source-sas]' \ + '\n\tOR --source-container --source-blob [--source-account-name & sas] [--source-snapshot]' \ + '\n\tOR --source-container --source-blob [--source-account-name & key] [--source-snapshot]' \ + '\n\tOR --source-share --source-path' \ + '\n\tOR --source-share --source-path [--source-account-name & sas]' \ + '\n\tOR --source-share --source-path [--source-account-name & key]' + + ns = vars(namespace) + + # source as blob + container = ns.pop('source_container', None) + blob = ns.pop('source_blob', None) + snapshot = ns.pop('source_snapshot', None) + + # source as file + share = ns.pop('source_share', None) + path = ns.pop('source_path', None) + file_snapshot = ns.pop('file_snapshot', None) + + # source credential clues + source_account_name = ns.pop('source_account_name', None) + source_account_key = ns.pop('source_account_key', None) + source_sas = ns.pop('source_sas', None) + + # source in the form of an uri + uri = ns.get('source_url', None) + if uri: + if any([container, blob, snapshot, share, path, file_snapshot, source_account_name, + source_account_key]): + raise ValueError(usage_string.format('Unused parameters are given in addition to the ' + 'source URI')) + if source_sas: + source_sas = source_sas.lstrip('?') + uri = '{}{}{}'.format(uri, '?', source_sas) + namespace.copy_source = uri + return + + # ensure either a file or blob source is specified + valid_blob_source = container and blob and not share and not path and not file_snapshot + valid_file_source = share and path and not container and not blob and not snapshot + + if not valid_blob_source and not valid_file_source: + raise ValueError(usage_string.format('Neither a valid blob or file source is specified')) + if valid_blob_source and valid_file_source: + raise ValueError(usage_string.format('Ambiguous parameters, both blob and file sources are ' + 'specified')) + + validate_client_parameters(cmd, namespace) # must run first to resolve storage account + + if not source_account_name: + if source_account_key: + raise ValueError(usage_string.format('Source account key is given but account name is not')) + # assume that user intends to copy blob in the same account + source_account_name = ns.get('account_name', None) + + # determine if the copy will happen in the same storage account + same_account = False + + if not source_account_key and not source_sas: + if source_account_name == ns.get('account_name', None): + same_account = True + source_account_key = ns.get('account_key', None) + source_sas = ns.get('sas_token', None) + else: + # the source account is different from destination account but the key is missing try to query one. + try: + source_account_key = _query_account_key(cmd.cli_ctx, source_account_name) + except ValueError: + raise ValueError('Source storage account {} not found.'.format(source_account_name)) + + # Both source account name and either key or sas (or both) are now available + if not source_sas: + # generate a sas token even in the same account when the source and destination are not the same kind. + if valid_file_source and (ns.get('container_name', None) or not same_account): + import os + dir_name, file_name = os.path.split(path) if path else (None, '') + source_sas = create_short_lived_file_sas(cmd, source_account_name, source_account_key, share, + dir_name, file_name) + elif valid_blob_source and (ns.get('share_name', None) or not same_account): + source_sas = create_short_lived_blob_sas(cmd, source_account_name, source_account_key, container, blob) + + query_params = [] + if source_sas: + query_params.append(source_sas.lstrip('?')) + if snapshot: + query_params.append('snapshot={}'.format(snapshot)) + if file_snapshot: + query_params.append('sharesnapshot={}'.format(file_snapshot)) + + uri = 'https://{0}.{1}.{6}/{2}/{3}{4}{5}'.format( + source_account_name, + 'blob' if valid_blob_source else 'file', + container if valid_blob_source else share, + encode_for_url(blob if valid_blob_source else path), + '?' if query_params else '', + '&'.join(query_params), + cmd.cli_ctx.cloud.suffixes.storage_endpoint) + + namespace.source_url = uri + + def validate_blob_type(namespace): if not namespace.blob_type: namespace.blob_type = 'page' if namespace.file_path.endswith('.vhd') else 'block' diff --git a/src/azure-cli/azure/cli/command_modules/storage/commands.py b/src/azure-cli/azure/cli/command_modules/storage/commands.py index 202a0390f45..987c378224e 100644 --- a/src/azure-cli/azure/cli/command_modules/storage/commands.py +++ b/src/azure-cli/azure/cli/command_modules/storage/commands.py @@ -312,6 +312,7 @@ def get_custom_sdk(custom_module, client_factory, resource_type=ResourceType.DAT resource_type=ResourceType.DATA_STORAGE_BLOB)) as g: from ._transformers import transform_blob_list_output, transform_blob_json_output from ._format import transform_blob_output + g.storage_custom_command_oauth('copy start', 'copy_blob') g.storage_custom_command_oauth('show', 'show_blob_v2', transform=transform_blob_json_output, table_transformer=transform_blob_output, exception_handler=show_exception_handler) @@ -376,7 +377,6 @@ def get_custom_sdk(custom_module, client_factory, resource_type=ResourceType.DAT g.storage_command_oauth( 'metadata show', 'get_blob_metadata', exception_handler=show_exception_handler) g.storage_command_oauth('metadata update', 'set_blob_metadata') - g.storage_command_oauth('copy start', 'copy_blob') g.storage_command_oauth('copy cancel', 'abort_copy_blob') g.storage_custom_command_oauth( 'copy start-batch', 'storage_blob_copy_batch') diff --git a/src/azure-cli/azure/cli/command_modules/storage/operations/blob.py b/src/azure-cli/azure/cli/command_modules/storage/operations/blob.py index 36287ae47b6..f48824a8706 100644 --- a/src/azure-cli/azure/cli/command_modules/storage/operations/blob.py +++ b/src/azure-cli/azure/cli/command_modules/storage/operations/blob.py @@ -837,3 +837,9 @@ def query_blob(client, query_expression, input_config=None, output_config=None, return None return reader.readall().decode("utf-8") + + +def copy_blob(client, source_url, metadata=None, **kwargs): + if not kwargs['requires_sync']: + kwargs.pop('requires_sync') + return client.start_copy_from_url(source_url=source_url, metadata=metadata, incremental_copy=False, **kwargs) diff --git a/src/azure-cli/azure/cli/command_modules/storage/tests/latest/test_storage_blob_copy_scenarios.py b/src/azure-cli/azure/cli/command_modules/storage/tests/latest/test_storage_blob_copy_scenarios.py index b4a50b5a8ef..6fd9dbc3aa4 100644 --- a/src/azure-cli/azure/cli/command_modules/storage/tests/latest/test_storage_blob_copy_scenarios.py +++ b/src/azure-cli/azure/cli/command_modules/storage/tests/latest/test_storage_blob_copy_scenarios.py @@ -86,7 +86,7 @@ def test_storage_blob_copy_same_account_sas(self, resource_group, storage_accoun expiry).output.strip() self.storage_cmd('storage blob copy start -b dst -c {} --source-blob src --sas-token {} --source-container {} ' - '--source-if-unmodified-since "2020-06-29T06:32Z" --destination-if-modified-since ' + '--source-if-unmodified-since "2021-06-29T06:32Z" --destination-if-modified-since ' '"2020-06-29T06:32Z" ', account_info, target_container, sas, source_container) from time import sleep, time From 632cf00c306158fd2e09d1fbeef10d092438977e Mon Sep 17 00:00:00 2001 From: Zunli Hu Date: Fri, 21 May 2021 16:46:51 +0800 Subject: [PATCH 04/12] test pass --- .../cli/command_modules/storage/_help.py | 44 +- .../cli/command_modules/storage/_params.py | 2 +- ..._storage_blob_copy_rehydrate_priority.yaml | 394 ++++++++++++++++++ .../latest/test_storage_blob_scenarios.py | 26 ++ 4 files changed, 460 insertions(+), 6 deletions(-) create mode 100644 src/azure-cli/azure/cli/command_modules/storage/tests/latest/recordings/test_storage_blob_copy_rehydrate_priority.yaml diff --git a/src/azure-cli/azure/cli/command_modules/storage/_help.py b/src/azure-cli/azure/cli/command_modules/storage/_help.py index a1f404c2958..a0b57944003 100644 --- a/src/azure-cli/azure/cli/command_modules/storage/_help.py +++ b/src/azure-cli/azure/cli/command_modules/storage/_help.py @@ -642,7 +642,7 @@ helps['storage blob copy start'] = """ type: command -short-summary: Copies a blob asynchronously. Use `az storage blob show` to check the status of the blobs. +short-summary: List blobs in a given container. parameters: - name: --source-uri -u type: string @@ -656,15 +656,49 @@ `https://myaccount.blob.core.windows.net/mycontainer/myblob`, `https://myaccount.blob.core.windows.net/mycontainer/myblob?snapshot=`, `https://otheraccount.blob.core.windows.net/mycontainer/myblob?sastoken` + - name: --destination-if-modified-since + type: string + short-summary: > + A DateTime value. Azure expects the date value passed in to be UTC. + If timezone is included, any non-UTC datetimes will be converted to UTC. + If a date is passed in without timezone info, it is assumed to be UTC. + Specify this conditional header to copy the blob only + if the destination blob has been modified since the specified date/time. + If the destination blob has not been modified, the Blob service returns + status code 412 (Precondition Failed). + - name: --destination-if-unmodified-since + type: string + short-summary: > + A DateTime value. Azure expects the date value passed in to be UTC. + If timezone is included, any non-UTC datetimes will be converted to UTC. + If a date is passed in without timezone info, it is assumed to be UTC. + Specify this conditional header to copy the blob only + if the destination blob has not been modified since the specified + date/time. If the destination blob has been modified, the Blob service + returns status code 412 (Precondition Failed). + - name: --source-if-modified-since + type: string + short-summary: > + A DateTime value. Azure expects the date value passed in to be UTC. + If timezone is included, any non-UTC datetimes will be converted to UTC. + If a date is passed in without timezone info, it is assumed to be UTC. + Specify this conditional header to copy the blob only if the source + blob has been modified since the specified date/time. + - name: --source-if-unmodified-since + type: string + short-summary: > + A DateTime value. Azure expects the date value passed in to be UTC. + If timezone is included, any non-UTC datetimes will be converted to UTC. + If a date is passed in without timezone info, it is assumed to be UTC. + Specify this conditional header to copy the blob only if the source blob + has not been modified since the specified date/time. examples: - - name: Copies a blob asynchronously. Use `az storage blob show` to check the status of the blobs. (autogenerated) + - name: Copy a blob asynchronously. Use `az storage blob show` to check the status of the blobs. text: | az storage blob copy start --account-key 00000000 --account-name MyAccount --destination-blob MyDestinationBlob --destination-container MyDestinationContainer --source-uri https://storage.blob.core.windows.net/photos - crafted: true - - name: Copies a blob asynchronously. Use `az storage blob show` to check the status of the blobs (autogenerated) + - name: Copy a blob asynchronously. Use `az storage blob show` to check the status of the blobs. text: | az storage blob copy start --account-name MyAccount --destination-blob MyDestinationBlob --destination-container MyDestinationContainer --sas-token $sas --source-uri https://storage.blob.core.windows.net/photos - crafted: true """ helps['storage blob copy start-batch'] = """ diff --git a/src/azure-cli/azure/cli/command_modules/storage/_params.py b/src/azure-cli/azure/cli/command_modules/storage/_params.py index 6bb2ff66842..b8e1ff29e9e 100644 --- a/src/azure-cli/azure/cli/command_modules/storage/_params.py +++ b/src/azure-cli/azure/cli/command_modules/storage/_params.py @@ -977,7 +977,7 @@ def load_arguments(self, _): # pylint: disable=too-many-locals, too-many-statem help='Name of the destination blob. If the exists, it will be overwritten.') c.argument('source_lease_id', arg_group='Copy Source') - with self.argument_context('storage blob copy start') as c: + with self.argument_context('storage blob copy start', resource_type=ResourceType.DATA_STORAGE_BLOB) as c: from ._validators import validate_source_url c.register_blob_arguments() diff --git a/src/azure-cli/azure/cli/command_modules/storage/tests/latest/recordings/test_storage_blob_copy_rehydrate_priority.yaml b/src/azure-cli/azure/cli/command_modules/storage/tests/latest/recordings/test_storage_blob_copy_rehydrate_priority.yaml new file mode 100644 index 00000000000..edaf5c9d236 --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/storage/tests/latest/recordings/test_storage_blob_copy_rehydrate_priority.yaml @@ -0,0 +1,394 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - storage account keys list + Connection: + - keep-alive + Content-Length: + - '0' + ParameterSetName: + - -n -g --query -o + User-Agent: + - AZURECLI/2.23.0 azsdk-python-azure-mgmt-storage/18.0.0 Python/3.8.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.Storage/storageAccounts/clitest000002/listKeys?api-version=2021-04-01&$expand=kerb + response: + body: + string: '{"keys":[{"creationTime":"2021-05-21T08:44:16.9185698Z","keyName":"key1","value":"veryFakedStorageAccountKey==","permissions":"FULL"},{"creationTime":"2021-05-21T08:44:16.9185698Z","keyName":"key2","value":"veryFakedStorageAccountKey==","permissions":"FULL"}]}' + headers: + cache-control: + - no-cache + content-length: + - '380' + content-type: + - application/json + date: + - Fri, 21 May 2021 08:44:48 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 + x-ms-ratelimit-remaining-subscription-resource-requests: + - '11998' + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - Azure-Storage/2.0.0-2.0.1 (Python CPython 3.8.3; Windows 10) AZURECLI/2.23.0 + x-ms-date: + - Fri, 21 May 2021 08:44:49 GMT + x-ms-version: + - '2018-11-09' + method: PUT + uri: https://clitest000002.blob.core.windows.net/cont000003?restype=container + response: + body: + string: '' + headers: + content-length: + - '0' + date: + - Fri, 21 May 2021 08:44:54 GMT + etag: + - '"0x8D91C34B4FDE43D"' + last-modified: + - Fri, 21 May 2021 08:44:55 GMT + server: + - Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 + x-ms-version: + - '2018-11-09' + status: + code: 201 + message: Created +- request: + body: null + headers: + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - Azure-Storage/2.0.0-2.0.1 (Python CPython 3.8.3; Windows 10) AZURECLI/2.23.0 + x-ms-date: + - Fri, 21 May 2021 08:44:55 GMT + x-ms-version: + - '2018-11-09' + method: PUT + uri: https://clitest000002.blob.core.windows.net/cont000004?restype=container + response: + body: + string: '' + headers: + content-length: + - '0' + date: + - Fri, 21 May 2021 08:44:55 GMT + etag: + - '"0x8D91C34B5B25013"' + last-modified: + - Fri, 21 May 2021 08:44:56 GMT + server: + - Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 + x-ms-version: + - '2018-11-09' + status: + code: 201 + message: Created +- request: + body: "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + headers: + Connection: + - keep-alive + Content-Length: + - '16384' + User-Agent: + - Azure-Storage/2.0.0-2.0.1 (Python CPython 3.8.3; Windows 10) AZURECLI/2.23.0 + x-ms-blob-type: + - BlockBlob + x-ms-date: + - Fri, 21 May 2021 08:44:56 GMT + x-ms-version: + - '2018-11-09' + method: PUT + uri: https://clitest000002.blob.core.windows.net/cont000003/src + response: + body: + string: '' + headers: + content-length: + - '0' + content-md5: + - zjOP5omXeKrPwoQU8tlJiw== + date: + - Fri, 21 May 2021 08:44:57 GMT + etag: + - '"0x8D91C34B6D52C41"' + last-modified: + - Fri, 21 May 2021 08:44:58 GMT + server: + - Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 + x-ms-request-server-encrypted: + - 'true' + x-ms-version: + - '2018-11-09' + status: + code: 201 + message: Created +- request: + body: null + headers: + Accept: + - application/xml + Accept-Encoding: + - gzip, deflate + CommandName: + - storage blob set-tier + Connection: + - keep-alive + Content-Length: + - '0' + ParameterSetName: + - -c -n --tier --account-name --account-key + User-Agent: + - AZURECLI/2.23.0 azsdk-python-storage-blob/12.7.1 Python/3.8.3 (Windows-10-10.0.19041-SP0) + x-ms-access-tier: + - Archive + x-ms-date: + - Fri, 21 May 2021 08:44:58 GMT + x-ms-rehydrate-priority: + - Standard + x-ms-version: + - '2020-04-08' + method: PUT + uri: https://clitest000002.blob.core.windows.net/cont000003/src?comp=tier + response: + body: + string: '' + headers: + content-length: + - '0' + date: + - Fri, 21 May 2021 08:44:59 GMT + server: + - Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 + x-ms-version: + - '2020-04-08' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/xml + Accept-Encoding: + - gzip, deflate + CommandName: + - storage blob show + Connection: + - keep-alive + ParameterSetName: + - -c -n --account-name --account-key + User-Agent: + - AZURECLI/2.23.0 azsdk-python-storage-blob/12.7.1 Python/3.8.3 (Windows-10-10.0.19041-SP0) + x-ms-date: + - Fri, 21 May 2021 08:44:59 GMT + x-ms-encryption-algorithm: + - AES256 + x-ms-version: + - '2020-04-08' + method: HEAD + uri: https://clitest000002.blob.core.windows.net/cont000003/src + response: + body: + string: '' + headers: + accept-ranges: + - bytes + content-length: + - '16384' + content-md5: + - zjOP5omXeKrPwoQU8tlJiw== + content-type: + - application/octet-stream + date: + - Fri, 21 May 2021 08:44:59 GMT + etag: + - '"0x8D91C34B6D52C41"' + last-modified: + - Fri, 21 May 2021 08:44:58 GMT + server: + - Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 + x-ms-access-tier: + - Archive + x-ms-access-tier-change-time: + - Fri, 21 May 2021 08:44:59 GMT + x-ms-blob-type: + - BlockBlob + x-ms-creation-time: + - Fri, 21 May 2021 08:44:58 GMT + x-ms-lease-state: + - available + x-ms-lease-status: + - unlocked + x-ms-server-encrypted: + - 'true' + x-ms-version: + - '2020-04-08' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/xml + Accept-Encoding: + - gzip, deflate + CommandName: + - storage blob copy start + Connection: + - keep-alive + Content-Length: + - '0' + ParameterSetName: + - -b -c --source-uri --tier -r --account-name --account-key + User-Agent: + - AZURECLI/2.23.0 azsdk-python-storage-blob/12.7.1 Python/3.8.3 (Windows-10-10.0.19041-SP0) + x-ms-access-tier: + - Cool + x-ms-copy-source: + - https://clitestsk3qbenqr7kw22355.blob.core.windows.net/contzd6sqh3zhov2iz2whtr2/src + x-ms-date: + - Fri, 21 May 2021 08:45:00 GMT + x-ms-rehydrate-priority: + - High + x-ms-version: + - '2020-04-08' + method: PUT + uri: https://clitest000002.blob.core.windows.net/cont000004/dst + response: + body: + string: '' + headers: + content-length: + - '0' + date: + - Fri, 21 May 2021 08:45:01 GMT + etag: + - '"0x8D91C34B91D169E"' + last-modified: + - Fri, 21 May 2021 08:45:01 GMT + server: + - Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 + x-ms-copy-id: + - e1e5a855-4197-45c6-9a64-1f96ab1f6428 + x-ms-copy-status: + - success + x-ms-version: + - '2020-04-08' + status: + code: 202 + message: Accepted +- request: + body: null + headers: + Accept: + - application/xml + Accept-Encoding: + - gzip, deflate + CommandName: + - storage blob show + Connection: + - keep-alive + ParameterSetName: + - -c -n --account-name --account-key + User-Agent: + - AZURECLI/2.23.0 azsdk-python-storage-blob/12.7.1 Python/3.8.3 (Windows-10-10.0.19041-SP0) + x-ms-date: + - Fri, 21 May 2021 08:45:02 GMT + x-ms-encryption-algorithm: + - AES256 + x-ms-version: + - '2020-04-08' + method: HEAD + uri: https://clitest000002.blob.core.windows.net/cont000004/dst + response: + body: + string: '' + headers: + accept-ranges: + - bytes + content-length: + - '16384' + content-md5: + - zjOP5omXeKrPwoQU8tlJiw== + content-type: + - application/octet-stream + date: + - Fri, 21 May 2021 08:45:02 GMT + etag: + - '"0x8D91C34B91D169E"' + last-modified: + - Fri, 21 May 2021 08:45:01 GMT + server: + - Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 + x-ms-access-tier: + - Archive + x-ms-access-tier-change-time: + - Fri, 21 May 2021 08:45:01 GMT + x-ms-archive-status: + - rehydrate-pending-to-cool + x-ms-blob-type: + - BlockBlob + x-ms-copy-completion-time: + - Fri, 21 May 2021 08:45:01 GMT + x-ms-copy-id: + - e1e5a855-4197-45c6-9a64-1f96ab1f6428 + x-ms-copy-progress: + - 16384/16384 + x-ms-copy-source: + - https://clitestsk3qbenqr7kw22355.blob.core.windows.net/contzd6sqh3zhov2iz2whtr2/src + x-ms-copy-status: + - success + x-ms-copy-status-description: + - pending + x-ms-creation-time: + - Fri, 21 May 2021 08:45:01 GMT + x-ms-lease-state: + - available + x-ms-lease-status: + - unlocked + x-ms-rehydrate-priority: + - High + x-ms-server-encrypted: + - 'true' + x-ms-version: + - '2020-04-08' + status: + code: 200 + message: OK +version: 1 diff --git a/src/azure-cli/azure/cli/command_modules/storage/tests/latest/test_storage_blob_scenarios.py b/src/azure-cli/azure/cli/command_modules/storage/tests/latest/test_storage_blob_scenarios.py index f03c95c86dd..766ad7dc900 100644 --- a/src/azure-cli/azure/cli/command_modules/storage/tests/latest/test_storage_blob_scenarios.py +++ b/src/azure-cli/azure/cli/command_modules/storage/tests/latest/test_storage_blob_scenarios.py @@ -755,5 +755,31 @@ def test_storage_blob_restore(self, resource_group, storage_account): time_to_restore, storage_account, resource_group)) +class StorageBlobCopyTestScenario(StorageScenarioMixin, ScenarioTest): + @ResourceGroupPreparer() + @StorageAccountPreparer(kind='storageV2') + def test_storage_blob_copy_rehydrate_priority(self, resource_group, storage_account): + source_file = self.create_temp_file(16) + account_info = self.get_account_info(resource_group, storage_account) + + source_container = self.create_container(account_info) + target_container = self.create_container(account_info) + + self.storage_cmd('storage blob upload -c {} -f "{}" -n src ', account_info, + source_container, source_file) + self.storage_cmd('storage blob set-tier -c {} -n {} --tier Archive', account_info, + source_container, 'src') + self.storage_cmd('az storage blob show -c {} -n {} ', account_info, source_container, 'src') \ + .assert_with_checks(JMESPathCheck('properties.blobTier', 'Archive')) + + source_uri = self.storage_cmd('storage blob url -c {} -n src', account_info, source_container).output + + self.storage_cmd('storage blob copy start -b dst -c {} --source-uri {} --tier Cool -r High', account_info, + target_container, source_uri) + self.storage_cmd('storage blob show -c {} -n {} ', account_info, target_container, 'dst') \ + .assert_with_checks(JMESPathCheck('properties.blobTier', 'Archive'), + JMESPathCheck('properties.rehydrationStatus', 'rehydrate-pending-to-cool')) + + if __name__ == '__main__': unittest.main() From 29aed8233ba78a0a6f273ff75e40c1e2d9308698 Mon Sep 17 00:00:00 2001 From: Zunli Hu Date: Fri, 21 May 2021 16:50:52 +0800 Subject: [PATCH 05/12] refine help --- src/azure-cli/azure/cli/command_modules/storage/_help.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/azure-cli/azure/cli/command_modules/storage/_help.py b/src/azure-cli/azure/cli/command_modules/storage/_help.py index a0b57944003..e96d8a042a3 100644 --- a/src/azure-cli/azure/cli/command_modules/storage/_help.py +++ b/src/azure-cli/azure/cli/command_modules/storage/_help.py @@ -642,7 +642,7 @@ helps['storage blob copy start'] = """ type: command -short-summary: List blobs in a given container. +short-summary: Copy a blob asynchronously. Use `az storage blob show` to check the status of the blobs. parameters: - name: --source-uri -u type: string From 3782060748c253e149b189111564aa21ce04d00b Mon Sep 17 00:00:00 2001 From: Zunli Hu Date: Fri, 21 May 2021 16:52:04 +0800 Subject: [PATCH 06/12] checkout --- src/azure-cli-core/azure/cli/core/profiles/_shared.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/azure-cli-core/azure/cli/core/profiles/_shared.py b/src/azure-cli-core/azure/cli/core/profiles/_shared.py index 69b28f90a3a..407b0190d34 100644 --- a/src/azure-cli-core/azure/cli/core/profiles/_shared.py +++ b/src/azure-cli-core/azure/cli/core/profiles/_shared.py @@ -137,7 +137,7 @@ def default_api_version(self): 'latest': { ResourceType.MGMT_STORAGE: '2021-04-01', ResourceType.MGMT_NETWORK: '2021-02-01', - ResourceType.MGMT_COMPUTE: SDKProfile('2021-03-01', { + ResourceType.MGMT_COMPUTE: SDKProfile('2020-12-01', { 'resource_skus': '2019-04-01', 'disks': '2020-12-01', 'disk_encryption_sets': '2020-12-01', @@ -146,7 +146,7 @@ def default_api_version(self): 'galleries': '2019-12-01', 'gallery_images': '2020-09-30', 'gallery_image_versions': '2020-09-30', - 'virtual_machine_scale_sets': '2021-03-01' + 'virtual_machine_scale_sets': '2020-12-01' }), ResourceType.MGMT_RESOURCE_FEATURES: '2015-12-01', ResourceType.MGMT_RESOURCE_LINKS: '2016-09-01', From db83e41bacf7b89e0c06ece9d86123d2c1fda3d7 Mon Sep 17 00:00:00 2001 From: Zunli Hu Date: Fri, 21 May 2021 16:53:26 +0800 Subject: [PATCH 07/12] checkout --- src/azure-cli/azure/cli/command_modules/vm/_params.py | 7 +------ .../azure/cli/command_modules/vm/_template_builder.py | 7 +------ src/azure-cli/azure/cli/command_modules/vm/custom.py | 6 ++---- 3 files changed, 4 insertions(+), 16 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/vm/_params.py b/src/azure-cli/azure/cli/command_modules/vm/_params.py index 234a3314bde..e733b810001 100644 --- a/src/azure-cli/azure/cli/command_modules/vm/_params.py +++ b/src/azure-cli/azure/cli/command_modules/vm/_params.py @@ -569,10 +569,8 @@ def load_arguments(self, _): for dest in scaleset_name_aliases: c.argument(dest, vmss_name_type, id_part=None) # due to instance-ids parameter - with self.argument_context('vmss create', operation_group='virtual_machine_scale_sets') as c: + with self.argument_context('vmss create') as c: VirtualMachineEvictionPolicyTypes = self.get_models('VirtualMachineEvictionPolicyTypes', resource_type=ResourceType.MGMT_COMPUTE) - NetworkApiVersion = self.get_models('NetworkApiVersion', resource_type=ResourceType.MGMT_COMPUTE, - operation_group='virtual_machine_scale_sets') c.argument('name', name_arg_type) c.argument('nat_backend_port', default=None, help='Backend port to open with NAT rules. Defaults to 22 on Linux and 3389 on Windows.') c.argument('single_placement_group', arg_type=get_three_state_flag(), help="Limit the scale set to a single placement group." @@ -594,9 +592,6 @@ def load_arguments(self, _): c.argument('scale_in_policy', scale_in_policy_type) c.argument('automatic_repairs_grace_period', min_api='2018-10-01', help='The amount of time (in minutes, between 30 and 90) for which automatic repairs are suspended due to a state change on VM.') - c.argument('network_api_version', arg_type=get_enum_type(NetworkApiVersion), is_preview=True, min_api='2021-03-01', - help="Specify the Microsoft.Network API version used when creating networking resources in the Network " - "Interface Configurations for Virtual Machine Scale Set with orchestration mode 'Flexible'.") with self.argument_context('vmss create', arg_group='Network Balancer') as c: LoadBalancerSkuName = self.get_models('LoadBalancerSkuName', resource_type=ResourceType.MGMT_NETWORK) diff --git a/src/azure-cli/azure/cli/command_modules/vm/_template_builder.py b/src/azure-cli/azure/cli/command_modules/vm/_template_builder.py index 9abec2cbc67..40a5ca7fc6c 100644 --- a/src/azure-cli/azure/cli/command_modules/vm/_template_builder.py +++ b/src/azure-cli/azure/cli/command_modules/vm/_template_builder.py @@ -770,8 +770,7 @@ def build_vmss_resource(cmd, name, naming_prefix, location, tags, overprovision, specialized=None, os_disk_size_gb=None, encryption_at_host=None, host_group=None, max_batch_instance_percent=None, max_unhealthy_instance_percent=None, max_unhealthy_upgraded_instance_percent=None, pause_time_between_batches=None, - enable_cross_zone_upgrade=None, prioritize_unhealthy_instances=None, edge_zone=None, - network_api_version=None): + enable_cross_zone_upgrade=None, prioritize_unhealthy_instances=None, edge_zone=None): # Build IP configuration ip_configuration = { @@ -956,10 +955,6 @@ def build_vmss_resource(cmd, name, naming_prefix, location, tags, overprovision, if health_probe and cmd.supported_api_version(min_api='2017-03-30', operation_group='virtual_machine_scale_sets'): vmss_properties['virtualMachineProfile']['networkProfile']['healthProbe'] = {'id': health_probe} - if network_api_version and \ - cmd.supported_api_version(min_api='2021-03-01', operation_group='virtual_machine_scale_sets'): - vmss_properties['virtualMachineProfile']['networkProfile']['networkApVersion'] = network_api_version - if cmd.supported_api_version(min_api='2016-04-30-preview', operation_group='virtual_machine_scale_sets'): vmss_properties['singlePlacementGroup'] = single_placement_group diff --git a/src/azure-cli/azure/cli/command_modules/vm/custom.py b/src/azure-cli/azure/cli/command_modules/vm/custom.py index f7620d9f20b..86ea0b4f6ac 100644 --- a/src/azure-cli/azure/cli/command_modules/vm/custom.py +++ b/src/azure-cli/azure/cli/command_modules/vm/custom.py @@ -2423,8 +2423,7 @@ def create_vmss(cmd, vmss_name, resource_group_name, image=None, automatic_repairs_grace_period=None, specialized=None, os_disk_size_gb=None, encryption_at_host=None, host_group=None, max_batch_instance_percent=None, max_unhealthy_instance_percent=None, max_unhealthy_upgraded_instance_percent=None, pause_time_between_batches=None, - enable_cross_zone_upgrade=None, prioritize_unhealthy_instances=None, edge_zone=None, - network_api_version=None): + enable_cross_zone_upgrade=None, prioritize_unhealthy_instances=None, edge_zone=None): from azure.cli.core.commands.client_factory import get_subscription_id from azure.cli.core.util import random_string, hash_string from azure.cli.core.commands.arm import ArmTemplateBuilder @@ -2663,8 +2662,7 @@ def _get_public_ip_address_allocation(value, sku): max_unhealthy_instance_percent=max_unhealthy_instance_percent, max_unhealthy_upgraded_instance_percent=max_unhealthy_upgraded_instance_percent, pause_time_between_batches=pause_time_between_batches, enable_cross_zone_upgrade=enable_cross_zone_upgrade, - prioritize_unhealthy_instances=prioritize_unhealthy_instances, edge_zone=edge_zone, - network_api_version=network_api_version) + prioritize_unhealthy_instances=prioritize_unhealthy_instances, edge_zone=edge_zone) vmss_resource['dependsOn'] = vmss_dependencies From e0a196229e994755ff3cda6256e44792ef32381f Mon Sep 17 00:00:00 2001 From: Zunli Hu Date: Fri, 21 May 2021 17:09:48 +0800 Subject: [PATCH 08/12] add linter exclusion --- .../storage/linter_exclusions.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/azure-cli/azure/cli/command_modules/storage/linter_exclusions.yml diff --git a/src/azure-cli/azure/cli/command_modules/storage/linter_exclusions.yml b/src/azure-cli/azure/cli/command_modules/storage/linter_exclusions.yml new file mode 100644 index 00000000000..7c508d79d7d --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/storage/linter_exclusions.yml @@ -0,0 +1,18 @@ +--- + # exclusions for the acr module + +storage blob copy start: + parameters: + if_modified_since: + rule_exclusions: + - option_length_too_long + if_none_match: + rule_exclusions: + - option_length_too_long + if_tags_match_condition: + rule_exclusions: + - option_length_too_long + if_unmodified_since: + rule_exclusions: + - option_length_too_long +... \ No newline at end of file From 6889a60ef8845c4e9288155ae97d60faf1936b97 Mon Sep 17 00:00:00 2001 From: Zunli Hu Date: Mon, 24 May 2021 11:50:22 +0800 Subject: [PATCH 09/12] fix style --- src/azure-cli/azure/cli/command_modules/storage/_validators.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/azure-cli/azure/cli/command_modules/storage/_validators.py b/src/azure-cli/azure/cli/command_modules/storage/_validators.py index f9cd7746178..8c7366de59e 100644 --- a/src/azure-cli/azure/cli/command_modules/storage/_validators.py +++ b/src/azure-cli/azure/cli/command_modules/storage/_validators.py @@ -465,7 +465,6 @@ def validate_source_url(cmd, namespace): # pylint: disable=too-many-statements if not source_sas: # generate a sas token even in the same account when the source and destination are not the same kind. if valid_file_source and (ns.get('container_name', None) or not same_account): - import os dir_name, file_name = os.path.split(path) if path else (None, '') source_sas = create_short_lived_file_sas(cmd, source_account_name, source_account_key, share, dir_name, file_name) From 2d898478744c869a7cd80005c801dd1272ddaafa Mon Sep 17 00:00:00 2001 From: Zunli Hu Date: Thu, 27 May 2021 17:08:17 +0800 Subject: [PATCH 10/12] fix error type --- .../azure/cli/command_modules/storage/_validators.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/storage/_validators.py b/src/azure-cli/azure/cli/command_modules/storage/_validators.py index 8c7366de59e..04cf6755f0f 100644 --- a/src/azure-cli/azure/cli/command_modules/storage/_validators.py +++ b/src/azure-cli/azure/cli/command_modules/storage/_validators.py @@ -389,6 +389,8 @@ def validate_source_uri(cmd, namespace): # pylint: disable=too-many-statements def validate_source_url(cmd, namespace): # pylint: disable=too-many-statements from .util import create_short_lived_blob_sas, create_short_lived_file_sas + from azure.cli.core.azclierror import InvalidArgumentValueError, RequiredArgumentMissingError, \ + MutuallyExclusiveArgumentError usage_string = \ 'Invalid usage: {}. Supply only one of the following argument sets to specify source:' \ '\n\t --source-uri [--source-sas]' \ @@ -420,7 +422,7 @@ def validate_source_url(cmd, namespace): # pylint: disable=too-many-statements if uri: if any([container, blob, snapshot, share, path, file_snapshot, source_account_name, source_account_key]): - raise ValueError(usage_string.format('Unused parameters are given in addition to the ' + raise InvalidArgumentValueError(usage_string.format('Unused parameters are given in addition to the ' 'source URI')) if source_sas: source_sas = source_sas.lstrip('?') @@ -433,16 +435,17 @@ def validate_source_url(cmd, namespace): # pylint: disable=too-many-statements valid_file_source = share and path and not container and not blob and not snapshot if not valid_blob_source and not valid_file_source: - raise ValueError(usage_string.format('Neither a valid blob or file source is specified')) + raise RequiredArgumentMissingError(usage_string.format('Neither a valid blob or file source is specified')) if valid_blob_source and valid_file_source: - raise ValueError(usage_string.format('Ambiguous parameters, both blob and file sources are ' + raise MutuallyExclusiveArgumentError(usage_string.format('Ambiguous parameters, both blob and file sources are ' 'specified')) validate_client_parameters(cmd, namespace) # must run first to resolve storage account if not source_account_name: if source_account_key: - raise ValueError(usage_string.format('Source account key is given but account name is not')) + raise RequiredArgumentMissingError(usage_string.format( + 'Source account key is given but account name is not')) # assume that user intends to copy blob in the same account source_account_name = ns.get('account_name', None) From 07057b0de4ee496177492a397021caaf593eb8d1 Mon Sep 17 00:00:00 2001 From: Zunli Hu Date: Thu, 27 May 2021 17:09:15 +0800 Subject: [PATCH 11/12] fix error type --- src/azure-cli/azure/cli/command_modules/storage/_validators.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/azure-cli/azure/cli/command_modules/storage/_validators.py b/src/azure-cli/azure/cli/command_modules/storage/_validators.py index 04cf6755f0f..2c30338416e 100644 --- a/src/azure-cli/azure/cli/command_modules/storage/_validators.py +++ b/src/azure-cli/azure/cli/command_modules/storage/_validators.py @@ -462,7 +462,7 @@ def validate_source_url(cmd, namespace): # pylint: disable=too-many-statements try: source_account_key = _query_account_key(cmd.cli_ctx, source_account_name) except ValueError: - raise ValueError('Source storage account {} not found.'.format(source_account_name)) + raise RequiredArgumentMissingError('Source storage account {} not found.'.format(source_account_name)) # Both source account name and either key or sas (or both) are now available if not source_sas: From b3594bdb3e9b127a3532b721136ed44b19ecec0e Mon Sep 17 00:00:00 2001 From: Zunli Hu Date: Fri, 28 May 2021 09:31:29 +0800 Subject: [PATCH 12/12] fix style --- .../azure/cli/command_modules/storage/_validators.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/storage/_validators.py b/src/azure-cli/azure/cli/command_modules/storage/_validators.py index 2c30338416e..f5e73d1b547 100644 --- a/src/azure-cli/azure/cli/command_modules/storage/_validators.py +++ b/src/azure-cli/azure/cli/command_modules/storage/_validators.py @@ -422,8 +422,8 @@ def validate_source_url(cmd, namespace): # pylint: disable=too-many-statements if uri: if any([container, blob, snapshot, share, path, file_snapshot, source_account_name, source_account_key]): - raise InvalidArgumentValueError(usage_string.format('Unused parameters are given in addition to the ' - 'source URI')) + raise InvalidArgumentValueError(usage_string.format( + 'Unused parameters are given in addition to the source URI')) if source_sas: source_sas = source_sas.lstrip('?') uri = '{}{}{}'.format(uri, '?', source_sas) @@ -437,8 +437,8 @@ def validate_source_url(cmd, namespace): # pylint: disable=too-many-statements if not valid_blob_source and not valid_file_source: raise RequiredArgumentMissingError(usage_string.format('Neither a valid blob or file source is specified')) if valid_blob_source and valid_file_source: - raise MutuallyExclusiveArgumentError(usage_string.format('Ambiguous parameters, both blob and file sources are ' - 'specified')) + raise MutuallyExclusiveArgumentError(usage_string.format( + 'Ambiguous parameters, both blob and file sources are specified')) validate_client_parameters(cmd, namespace) # must run first to resolve storage account