def _create_file_and_directory_from_blob(file_service, blob_service, share, container, sas, blob_name, destination_dir=None, metadata=None, timeout=None, existing_dirs=None): """ Copy a blob to file share and create the directory if needed. """ from azure.common import AzureException from azure.cli.command_modules.storage.util import normalize_blob_file_path blob_url = blob_service.make_blob_url(container, encode_for_url(blob_name), sas_token=sas) full_path = normalize_blob_file_path(destination_dir, blob_name) file_name = os.path.basename(full_path) dir_name = os.path.dirname(full_path) _make_directory_in_files_share(file_service, share, dir_name, existing_dirs) try: file_service.copy_file(share, dir_name, file_name, blob_url, metadata, timeout) return file_service.make_file_url(share, dir_name, file_name) except AzureException: error_template = 'Failed to copy blob {} to file share {}. Please check if you have permission to read ' \ 'source or set a correct sas token.' from knack.util import CLIError raise CLIError(error_template.format(blob_name, share))
def _copy_blob_to_blob_container(blob_service, source_blob_service, destination_container, source_container, source_sas, source_blob_name): source_blob_url = source_blob_service.make_blob_url(source_container, encode_for_url(source_blob_name), sas_token=source_sas) try: blob_service.copy_blob(destination_container, source_blob_name, source_blob_url) return blob_service.make_blob_url(destination_container, source_blob_name) except AzureException: error_template = 'Failed to copy blob {} to container {}.' raise CLIError(error_template.format(source_blob_name, destination_container))
def _copy_blob_to_blob_container(blob_service, source_blob_service, destination_container, destination_path, source_container, source_sas, source_blob_name): from azure.common import AzureException source_blob_url = source_blob_service.make_blob_url(source_container, encode_for_url(source_blob_name), sas_token=source_sas) destination_blob_name = normalize_blob_file_path(destination_path, source_blob_name) try: blob_service.copy_blob(destination_container, destination_blob_name, source_blob_url) return blob_service.make_blob_url(destination_container, destination_blob_name) except AzureException: error_template = 'Failed to copy blob {} to container {}.' raise CLIError(error_template.format(source_blob_name, destination_container))
def _copy_blob_to_blob_container(blob_service, source_blob_service, destination_container, destination_path, source_container, source_sas, source_blob_name): from azure.common import AzureException source_blob_url = source_blob_service.make_blob_url(source_container, encode_for_url(source_blob_name), sas_token=source_sas) destination_blob_name = normalize_blob_file_path(destination_path, source_blob_name) try: blob_service.copy_blob(destination_container, destination_blob_name, source_blob_url) return blob_service.make_blob_url(destination_container, destination_blob_name) except AzureException: from knack.util import CLIError error_template = 'Failed to copy blob {} to container {}.' raise CLIError(error_template.format(source_blob_name, destination_container))
def _create_file_and_directory_from_blob(file_service, blob_service, share, container, sas, blob_name, destination_dir=None, metadata=None, timeout=None, existing_dirs=None): """ Copy a blob to file share and create the directory if needed. """ blob_name = blob_name.encode('utf-8') blob_url = blob_service.make_blob_url(container, encode_for_url(blob_name), sas_token=sas) full_path = os.path.join(destination_dir, blob_name) if destination_dir else blob_name file_name = os.path.basename(full_path) dir_name = os.path.dirname(full_path) _make_directory_in_files_share(file_service, share, dir_name, existing_dirs) try: file_service.copy_file(share, dir_name, file_name, blob_url, metadata, timeout) return file_service.make_file_url(share, dir_name, file_name) except AzureException: error_template = 'Failed to copy blob {} to file share {}. Please check if you have ' + \ 'permission to read source or set a correct sas token.' raise CLIError(error_template.format(blob_name, share))
def _create_file_and_directory_from_blob(file_service, blob_service, share, container, sas, blob_name, destination_dir=None, metadata=None, timeout=None, existing_dirs=None): """ Copy a blob to file share and create the directory if needed. """ from azure.common import AzureException from azure.cli.command_modules.storage.util import normalize_blob_file_path blob_url = blob_service.make_blob_url(container, encode_for_url(blob_name), sas_token=sas) full_path = normalize_blob_file_path(destination_dir, blob_name) file_name = os.path.basename(full_path) dir_name = os.path.dirname(full_path) _make_directory_in_files_share(file_service, share, dir_name, existing_dirs) try: file_service.copy_file(share, dir_name, file_name, blob_url, metadata, timeout) return file_service.make_file_url(share, dir_name, file_name) except AzureException: error_template = 'Failed to copy blob {} to file share {}. Please check if you have permission to read ' \ 'source or set a correct sas token.' from knack.util import CLIError raise CLIError(error_template.format(blob_name, share))
def validate_source_uri(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' \ '\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) # source credential clues source_account_name = ns.pop('source_account_name', None) source_account_key = ns.pop('source_account_key', None) sas = ns.pop('source_sas', None) # source in the form of an uri uri = ns.get('copy_source', None) if uri: if any([ container, blob, sas, snapshot, share, path, source_account_name, source_account_key ]): raise ValueError( usage_string.format( 'Unused parameters are given in addition to the ' 'source URI')) else: # simplest scenario--no further processing necessary return # ensure either a file or blob source is specified valid_blob_source = container and blob and not share and not path 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')) elif 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 # determine if the copy will happen in the same storage account same_account = False if not source_account_name and source_account_key: raise ValueError( usage_string.format( 'Source account key is given but account name is not')) elif not source_account_name and not source_account_key: # neither source account name or key is given, assume that user intends to copy blob in # the same account same_account = True source_account_name = ns.get('account_name', None) source_account_key = ns.get('account_key', None) elif source_account_name and not source_account_key: if source_account_name == ns.get('account_name', None): # the source account name is same as the destination account name same_account = True source_account_key = ns.get('account_key', 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)) # else: both source account name and key are given by user if not source_account_name: raise ValueError(usage_string.format('Storage account name not found')) if not 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, '') 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): sas = create_short_lived_blob_sas(cmd, source_account_name, source_account_key, container, blob) query_params = [] if sas: query_params.append(sas) if snapshot: query_params.append('snapshot={}'.format(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.copy_source = uri
def validate_source_uri(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) # 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('copy_source', None) if uri: if any([container, blob, snapshot, share, path, 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 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')) elif 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)) 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.copy_source = uri