1# ------------------------------------------------------------------------- 2# Copyright (c) Microsoft Corporation. All rights reserved. 3# Licensed under the MIT License. See License.txt in the project root for 4# license information. 5# -------------------------------------------------------------------------- 6import sys 7from abc import ABCMeta 8 9from azure.common import AzureHttpError 10 11from ..common._auth import ( 12 _StorageSASAuthentication, 13 _StorageSharedKeyAuthentication, 14 _StorageNoAuthentication, 15) 16from ..common._common_conversion import ( 17 _int_to_str, 18 _to_str, 19 _datetime_to_utc_string, 20) 21from ..common._connection import _ServiceParameters 22from ..common._constants import ( 23 SERVICE_HOST_BASE, 24 DEFAULT_PROTOCOL, 25) 26from ..common._deserialization import ( 27 _convert_xml_to_service_properties, 28 _parse_metadata, 29 _parse_properties, 30 _convert_xml_to_service_stats, 31 _parse_length_from_content_range, 32) 33from ..common._error import ( 34 _dont_fail_not_exist, 35 _dont_fail_on_exist, 36 _validate_not_none, 37 _validate_decryption_required, 38 _validate_access_policies, 39 _ERROR_PARALLEL_NOT_SEEKABLE, 40 _validate_user_delegation_key, 41) 42from ..common._http import HTTPRequest 43from ..common._serialization import ( 44 _get_request_body, 45 _convert_signed_identifiers_to_xml, 46 _convert_service_properties_to_xml, 47 _add_metadata_headers, 48) 49from ..common.models import ( 50 Services, 51 ListGenerator, 52 _OperationContext, 53) 54from .sharedaccesssignature import ( 55 BlobSharedAccessSignature, 56) 57from ..common.storageclient import StorageClient 58from ._deserialization import ( 59 _convert_xml_to_containers, 60 _parse_blob, 61 _convert_xml_to_blob_list, 62 _convert_xml_to_blob_name_list, 63 _parse_container, 64 _parse_snapshot_blob, 65 _parse_lease, 66 _convert_xml_to_signed_identifiers_and_access, 67 _parse_base_properties, 68 _parse_account_information, 69 _convert_xml_to_user_delegation_key, 70) 71from ._download_chunking import _download_blob_chunks 72from ._error import ( 73 _ERROR_INVALID_LEASE_DURATION, 74 _ERROR_INVALID_LEASE_BREAK_PERIOD, 75) 76from ._serialization import ( 77 _get_path, 78 _validate_and_format_range_headers, 79 _convert_delegation_key_info_to_xml, 80) 81from .models import ( 82 BlobProperties, 83 _LeaseActions, 84 ContainerPermissions, 85 BlobPermissions, 86) 87 88from ._constants import ( 89 X_MS_VERSION, 90 __version__ as package_version, 91) 92 93_CONTAINER_ALREADY_EXISTS_ERROR_CODE = 'ContainerAlreadyExists' 94_BLOB_NOT_FOUND_ERROR_CODE = 'BlobNotFound' 95_CONTAINER_NOT_FOUND_ERROR_CODE = 'ContainerNotFound' 96 97if sys.version_info >= (3,): 98 from io import BytesIO 99else: 100 from cStringIO import StringIO as BytesIO 101 102 103class BaseBlobService(StorageClient): 104 ''' 105 This is the main class managing Blob resources. 106 107 The Blob service stores text and binary data as blobs in the cloud. 108 The Blob service offers the following three resources: the storage account, 109 containers, and blobs. Within your storage account, containers provide a 110 way to organize sets of blobs. For more information please see: 111 https://msdn.microsoft.com/en-us/library/azure/ee691964.aspx 112 113 :ivar int MAX_SINGLE_GET_SIZE: 114 The size of the first range get performed by get_blob_to_* methods if 115 max_connections is greater than 1. Less data will be returned if the 116 blob is smaller than this. 117 :ivar int MAX_CHUNK_GET_SIZE: 118 The size of subsequent range gets performed by get_blob_to_* methods if 119 max_connections is greater than 1 and the blob is larger than MAX_SINGLE_GET_SIZE. 120 Less data will be returned if the remainder of the blob is smaller than 121 this. If this is set to larger than 4MB, content_validation will throw an 122 error if enabled. However, if content_validation is not desired a size 123 greater than 4MB may be optimal. Setting this below 4MB is not recommended. 124 :ivar object key_encryption_key: 125 The key-encryption-key optionally provided by the user. If provided, will be used to 126 encrypt/decrypt in supported methods. 127 For methods requiring decryption, either the key_encryption_key OR the resolver must be provided. 128 If both are provided, the resolver will take precedence. 129 Must implement the following methods for APIs requiring encryption: 130 wrap_key(key)--wraps the specified key (bytes) using an algorithm of the user's choice. Returns the encrypted key as bytes. 131 get_key_wrap_algorithm()--returns the algorithm used to wrap the specified symmetric key. 132 get_kid()--returns a string key id for this key-encryption-key. 133 Must implement the following methods for APIs requiring decryption: 134 unwrap_key(key, algorithm)--returns the unwrapped form of the specified symmetric key using the string-specified algorithm. 135 get_kid()--returns a string key id for this key-encryption-key. 136 :ivar function key_resolver_function(kid): 137 A function to resolve keys optionally provided by the user. If provided, will be used to decrypt in supported methods. 138 For methods requiring decryption, either the key_encryption_key OR 139 the resolver must be provided. If both are provided, the resolver will take precedence. 140 It uses the kid string to return a key-encryption-key implementing the interface defined above. 141 :ivar bool require_encryption: 142 A flag that may be set to ensure that all messages successfully uploaded to the queue and all those downloaded and 143 successfully read from the queue are/were encrypted while on the server. If this flag is set, all required 144 parameters for encryption/decryption must be provided. See the above comments on the key_encryption_key and resolver. 145 ''' 146 147 __metaclass__ = ABCMeta 148 MAX_SINGLE_GET_SIZE = 32 * 1024 * 1024 149 MAX_CHUNK_GET_SIZE = 4 * 1024 * 1024 150 151 def __init__(self, account_name=None, account_key=None, sas_token=None, is_emulated=False, 152 protocol=DEFAULT_PROTOCOL, endpoint_suffix=SERVICE_HOST_BASE, custom_domain=None, request_session=None, 153 connection_string=None, socket_timeout=None, token_credential=None): 154 ''' 155 :param str account_name: 156 The storage account name. This is used to authenticate requests 157 signed with an account key and to construct the storage endpoint. It 158 is required unless a connection string is given, or if a custom 159 domain is used with anonymous authentication. 160 :param str account_key: 161 The storage account key. This is used for shared key authentication. 162 If neither account key or sas token is specified, anonymous access 163 will be used. 164 :param str sas_token: 165 A shared access signature token to use to authenticate requests 166 instead of the account key. If account key and sas token are both 167 specified, account key will be used to sign. If neither are 168 specified, anonymous access will be used. 169 :param bool is_emulated: 170 Whether to use the emulator. Defaults to False. If specified, will 171 override all other parameters besides connection string and request 172 session. 173 :param str protocol: 174 The protocol to use for requests. Defaults to https. 175 :param str endpoint_suffix: 176 The host base component of the url, minus the account name. Defaults 177 to Azure (core.windows.net). Override this to use the China cloud 178 (core.chinacloudapi.cn). 179 :param str custom_domain: 180 The custom domain to use. This can be set in the Azure Portal. For 181 example, 'www.mydomain.com'. 182 :param requests.Session request_session: 183 The session object to use for http requests. 184 :param str connection_string: 185 If specified, this will override all other parameters besides 186 request session. See 187 http://azure.microsoft.com/en-us/documentation/articles/storage-configure-connection-string/ 188 for the connection string format 189 :param int socket_timeout: 190 If specified, this will override the default socket timeout. The timeout specified is in seconds. 191 See DEFAULT_SOCKET_TIMEOUT in _constants.py for the default value. 192 :param token_credential: 193 A token credential used to authenticate HTTPS requests. The token value 194 should be updated before its expiration. 195 :type `~azure.storage.common.TokenCredential` 196 ''' 197 service_params = _ServiceParameters.get_service_parameters( 198 'blob', 199 account_name=account_name, 200 account_key=account_key, 201 sas_token=sas_token, 202 token_credential=token_credential, 203 is_emulated=is_emulated, 204 protocol=protocol, 205 endpoint_suffix=endpoint_suffix, 206 custom_domain=custom_domain, 207 request_session=request_session, 208 connection_string=connection_string, 209 socket_timeout=socket_timeout) 210 211 super(BaseBlobService, self).__init__(service_params) 212 213 if self.account_key: 214 self.authentication = _StorageSharedKeyAuthentication( 215 self.account_name, 216 self.account_key, 217 self.is_emulated 218 ) 219 elif self.sas_token: 220 self.authentication = _StorageSASAuthentication(self.sas_token) 221 elif self.token_credential: 222 self.authentication = self.token_credential 223 else: 224 self.authentication = _StorageNoAuthentication() 225 226 self.require_encryption = False 227 self.key_encryption_key = None 228 self.key_resolver_function = None 229 self._X_MS_VERSION = X_MS_VERSION 230 self._update_user_agent_string(package_version) 231 232 def make_blob_url(self, container_name, blob_name, protocol=None, sas_token=None, snapshot=None): 233 ''' 234 Creates the url to access a blob. 235 236 :param str container_name: 237 Name of container. 238 :param str blob_name: 239 Name of blob. 240 :param str protocol: 241 Protocol to use: 'http' or 'https'. If not specified, uses the 242 protocol specified when BaseBlobService was initialized. 243 :param str sas_token: 244 Shared access signature token created with 245 generate_shared_access_signature. 246 :param str snapshot: 247 An string value that uniquely identifies the snapshot. The value of 248 this query parameter indicates the snapshot version. 249 :return: blob access URL. 250 :rtype: str 251 ''' 252 253 url = '{}://{}/{}/{}'.format( 254 protocol or self.protocol, 255 self.primary_endpoint, 256 container_name, 257 blob_name, 258 ) 259 260 if snapshot and sas_token: 261 url = '{}?snapshot={}&{}'.format(url, snapshot, sas_token) 262 elif snapshot: 263 url = '{}?snapshot={}'.format(url, snapshot) 264 elif sas_token: 265 url = '{}?{}'.format(url, sas_token) 266 267 return url 268 269 def make_container_url(self, container_name, protocol=None, sas_token=None): 270 ''' 271 Creates the url to access a container. 272 273 :param str container_name: 274 Name of container. 275 :param str protocol: 276 Protocol to use: 'http' or 'https'. If not specified, uses the 277 protocol specified when BaseBlobService was initialized. 278 :param str sas_token: 279 Shared access signature token created with 280 generate_shared_access_signature. 281 :return: container access URL. 282 :rtype: str 283 ''' 284 285 url = '{}://{}/{}?restype=container'.format( 286 protocol or self.protocol, 287 self.primary_endpoint, 288 container_name, 289 ) 290 291 if sas_token: 292 url = '{}&{}'.format(url, sas_token) 293 294 return url 295 296 def generate_account_shared_access_signature(self, resource_types, permission, 297 expiry, start=None, ip=None, protocol=None): 298 ''' 299 Generates a shared access signature for the blob service. 300 Use the returned signature with the sas_token parameter of any BlobService. 301 302 :param ResourceTypes resource_types: 303 Specifies the resource types that are accessible with the account SAS. 304 :param AccountPermissions permission: 305 The permissions associated with the shared access signature. The 306 user is restricted to operations allowed by the permissions. 307 Required unless an id is given referencing a stored access policy 308 which contains this field. This field must be omitted if it has been 309 specified in an associated stored access policy. 310 :param expiry: 311 The time at which the shared access signature becomes invalid. 312 Required unless an id is given referencing a stored access policy 313 which contains this field. This field must be omitted if it has 314 been specified in an associated stored access policy. Azure will always 315 convert values to UTC. If a date is passed in without timezone info, it 316 is assumed to be UTC. 317 :type expiry: datetime or str 318 :param start: 319 The time at which the shared access signature becomes valid. If 320 omitted, start time for this call is assumed to be the time when the 321 storage service receives the request. Azure will always convert values 322 to UTC. If a date is passed in without timezone info, it is assumed to 323 be UTC. 324 :type start: datetime or str 325 :param str ip: 326 Specifies an IP address or a range of IP addresses from which to accept requests. 327 If the IP address from which the request originates does not match the IP address 328 or address range specified on the SAS token, the request is not authenticated. 329 For example, specifying sip=168.1.5.65 or sip=168.1.5.60-168.1.5.70 on the SAS 330 restricts the request to those IP addresses. 331 :param str protocol: 332 Specifies the protocol permitted for a request made. The default value 333 is https,http. See :class:`~azure.storage.common.models.Protocol` for possible values. 334 :return: A Shared Access Signature (sas) token. 335 :rtype: str 336 ''' 337 _validate_not_none('self.account_name', self.account_name) 338 _validate_not_none('self.account_key', self.account_key) 339 340 sas = BlobSharedAccessSignature(self.account_name, self.account_key) 341 return sas.generate_account(Services.BLOB, resource_types, permission, 342 expiry, start=start, ip=ip, protocol=protocol) 343 344 def generate_container_shared_access_signature(self, container_name, 345 permission=None, expiry=None, 346 start=None, id=None, ip=None, protocol=None, 347 cache_control=None, content_disposition=None, 348 content_encoding=None, content_language=None, 349 content_type=None, user_delegation_key=None): 350 ''' 351 Generates a shared access signature for the container. 352 Use the returned signature with the sas_token parameter of any BlobService. 353 354 :param str container_name: 355 Name of container. 356 :param ContainerPermissions permission: 357 The permissions associated with the shared access signature. The 358 user is restricted to operations allowed by the permissions. 359 Permissions must be ordered read, write, delete, list. 360 Required unless an id is given referencing a stored access policy 361 which contains this field. This field must be omitted if it has been 362 specified in an associated stored access policy. 363 :param expiry: 364 The time at which the shared access signature becomes invalid. 365 Required unless an id is given referencing a stored access policy 366 which contains this field. This field must be omitted if it has 367 been specified in an associated stored access policy. Azure will always 368 convert values to UTC. If a date is passed in without timezone info, it 369 is assumed to be UTC. 370 :type expiry: datetime or str 371 :param start: 372 The time at which the shared access signature becomes valid. If 373 omitted, start time for this call is assumed to be the time when the 374 storage service receives the request. Azure will always convert values 375 to UTC. If a date is passed in without timezone info, it is assumed to 376 be UTC. 377 :type start: datetime or str 378 :param str id: 379 A unique value up to 64 characters in length that correlates to a 380 stored access policy. To create a stored access policy, use 381 set_blob_service_properties. 382 :param str ip: 383 Specifies an IP address or a range of IP addresses from which to accept requests. 384 If the IP address from which the request originates does not match the IP address 385 or address range specified on the SAS token, the request is not authenticated. 386 For example, specifying sip=168.1.5.65 or sip=168.1.5.60-168.1.5.70 on the SAS 387 restricts the request to those IP addresses. 388 :param str protocol: 389 Specifies the protocol permitted for a request made. The default value 390 is https,http. See :class:`~azure.storage.common.models.Protocol` for possible values. 391 :param str cache_control: 392 Response header value for Cache-Control when resource is accessed 393 using this shared access signature. 394 :param str content_disposition: 395 Response header value for Content-Disposition when resource is accessed 396 using this shared access signature. 397 :param str content_encoding: 398 Response header value for Content-Encoding when resource is accessed 399 using this shared access signature. 400 :param str content_language: 401 Response header value for Content-Language when resource is accessed 402 using this shared access signature. 403 :param str content_type: 404 Response header value for Content-Type when resource is accessed 405 using this shared access signature. 406 :param ~azure.storage.blob.models.UserDelegationKey user_delegation_key: 407 Instead of an account key, the user could pass in a user delegation key. 408 A user delegation key can be obtained from the service by authenticating with an AAD identity; 409 this can be accomplished by calling get_user_delegation_key. 410 When present, the SAS is signed with the user delegation key instead. 411 :return: A Shared Access Signature (sas) token. 412 :rtype: str 413 ''' 414 _validate_not_none('container_name', container_name) 415 _validate_not_none('self.account_name', self.account_name) 416 417 if user_delegation_key is not None: 418 _validate_user_delegation_key(user_delegation_key) 419 sas = BlobSharedAccessSignature(self.account_name, user_delegation_key=user_delegation_key) 420 else: 421 _validate_not_none('self.account_key', self.account_key) 422 sas = BlobSharedAccessSignature(self.account_name, account_key=self.account_key) 423 424 return sas.generate_container( 425 container_name, 426 permission, 427 expiry, 428 start=start, 429 id=id, 430 ip=ip, 431 protocol=protocol, 432 cache_control=cache_control, 433 content_disposition=content_disposition, 434 content_encoding=content_encoding, 435 content_language=content_language, 436 content_type=content_type, 437 ) 438 439 def generate_blob_shared_access_signature( 440 self, container_name, blob_name, snapshot=None, permission=None, 441 expiry=None, start=None, id=None, ip=None, protocol=None, 442 cache_control=None, content_disposition=None, 443 content_encoding=None, content_language=None, 444 content_type=None, user_delegation_key=None): 445 ''' 446 Generates a shared access signature for the blob or one of its snapshots. 447 Use the returned signature with the sas_token parameter of any BlobService. 448 449 :param str container_name: 450 Name of container. 451 :param str blob_name: 452 Name of blob. 453 :param str snapshot: 454 The snapshot parameter is an opaque DateTime value that, 455 when present, specifies the blob snapshot to grant permission. 456 :param BlobPermissions permission: 457 The permissions associated with the shared access signature. The 458 user is restricted to operations allowed by the permissions. 459 Permissions must be ordered read, write, delete, list. 460 Required unless an id is given referencing a stored access policy 461 which contains this field. This field must be omitted if it has been 462 specified in an associated stored access policy. 463 :param expiry: 464 The time at which the shared access signature becomes invalid. 465 Required unless an id is given referencing a stored access policy 466 which contains this field. This field must be omitted if it has 467 been specified in an associated stored access policy. Azure will always 468 convert values to UTC. If a date is passed in without timezone info, it 469 is assumed to be UTC. 470 :type expiry: datetime or str 471 :param start: 472 The time at which the shared access signature becomes valid. If 473 omitted, start time for this call is assumed to be the time when the 474 storage service receives the request. Azure will always convert values 475 to UTC. If a date is passed in without timezone info, it is assumed to 476 be UTC. 477 :type start: datetime or str 478 :param str id: 479 A unique value up to 64 characters in length that correlates to a 480 stored access policy. To create a stored access policy, use :func:`~set_container_acl`. 481 :param str ip: 482 Specifies an IP address or a range of IP addresses from which to accept requests. 483 If the IP address from which the request originates does not match the IP address 484 or address range specified on the SAS token, the request is not authenticated. 485 For example, specifying sip=168.1.5.65 or sip=168.1.5.60-168.1.5.70 on the SAS 486 restricts the request to those IP addresses. 487 :param str protocol: 488 Specifies the protocol permitted for a request made. The default value 489 is https,http. See :class:`~azure.storage.common.models.Protocol` for possible values. 490 :param str cache_control: 491 Response header value for Cache-Control when resource is accessed 492 using this shared access signature. 493 :param str content_disposition: 494 Response header value for Content-Disposition when resource is accessed 495 using this shared access signature. 496 :param str content_encoding: 497 Response header value for Content-Encoding when resource is accessed 498 using this shared access signature. 499 :param str content_language: 500 Response header value for Content-Language when resource is accessed 501 using this shared access signature. 502 :param str content_type: 503 Response header value for Content-Type when resource is accessed 504 using this shared access signature. 505 :param ~azure.storage.blob.models.UserDelegationKey user_delegation_key: 506 Instead of an account key, the user could pass in a user delegation key. 507 A user delegation key can be obtained from the service by authenticating with an AAD identity; 508 this can be accomplished by calling get_user_delegation_key. 509 When present, the SAS is signed with the user delegation key instead. 510 :return: A Shared Access Signature (sas) token. 511 :rtype: str 512 ''' 513 _validate_not_none('container_name', container_name) 514 _validate_not_none('blob_name', blob_name) 515 _validate_not_none('self.account_name', self.account_name) 516 517 if user_delegation_key is not None: 518 _validate_user_delegation_key(user_delegation_key) 519 sas = BlobSharedAccessSignature(self.account_name, user_delegation_key=user_delegation_key) 520 else: 521 _validate_not_none('self.account_key', self.account_key) 522 sas = BlobSharedAccessSignature(self.account_name, account_key=self.account_key) 523 524 return sas.generate_blob( 525 container_name=container_name, 526 blob_name=blob_name, 527 snapshot=snapshot, 528 permission=permission, 529 expiry=expiry, 530 start=start, 531 id=id, 532 ip=ip, 533 protocol=protocol, 534 cache_control=cache_control, 535 content_disposition=content_disposition, 536 content_encoding=content_encoding, 537 content_language=content_language, 538 content_type=content_type, 539 ) 540 541 def get_user_delegation_key(self, key_start_time, key_expiry_time, timeout=None): 542 """ 543 Obtain a user delegation key for the purpose of signing SAS tokens. 544 A token credential must be present on the service object for this request to succeed. 545 546 :param datetime key_start_time: 547 A DateTime value. Indicates when the key becomes valid. 548 :param datetime key_expiry_time: 549 A DateTime value. Indicates when the key stops being valid. 550 :param int timeout: 551 The timeout parameter is expressed in seconds. 552 :return: 553 """ 554 _validate_not_none('key_start_time', key_start_time) 555 _validate_not_none('key_end_time', key_expiry_time) 556 557 request = HTTPRequest() 558 request.method = 'POST' 559 request.host_locations = self._get_host_locations(secondary=True) 560 request.query = { 561 'restype': 'service', 562 'comp': 'userdelegationkey', 563 'timeout': _int_to_str(timeout), 564 } 565 request.body = _get_request_body(_convert_delegation_key_info_to_xml(key_start_time, key_expiry_time)) 566 return self._perform_request(request, _convert_xml_to_user_delegation_key) 567 568 def list_containers(self, prefix=None, num_results=None, include_metadata=False, 569 marker=None, timeout=None): 570 ''' 571 Returns a generator to list the containers under the specified account. 572 The generator will lazily follow the continuation tokens returned by 573 the service and stop when all containers have been returned or num_results is reached. 574 575 If num_results is specified and the account has more than that number of 576 containers, the generator will have a populated next_marker field once it 577 finishes. This marker can be used to create a new generator if more 578 results are desired. 579 580 :param str prefix: 581 Filters the results to return only containers whose names 582 begin with the specified prefix. 583 :param int num_results: 584 Specifies the maximum number of containers to return. A single list 585 request may return up to 1000 contianers and potentially a continuation 586 token which should be followed to get additional resutls. 587 :param bool include_metadata: 588 Specifies that container metadata be returned in the response. 589 :param str marker: 590 An opaque continuation token. This value can be retrieved from the 591 next_marker field of a previous generator object if num_results was 592 specified and that generator has finished enumerating results. If 593 specified, this generator will begin returning results from the point 594 where the previous generator stopped. 595 :param int timeout: 596 The timeout parameter is expressed in seconds. 597 ''' 598 include = 'metadata' if include_metadata else None 599 operation_context = _OperationContext(location_lock=True) 600 kwargs = {'prefix': prefix, 'marker': marker, 'max_results': num_results, 601 'include': include, 'timeout': timeout, '_context': operation_context} 602 resp = self._list_containers(**kwargs) 603 604 return ListGenerator(resp, self._list_containers, (), kwargs) 605 606 def _list_containers(self, prefix=None, marker=None, max_results=None, 607 include=None, timeout=None, _context=None): 608 ''' 609 Returns a list of the containers under the specified account. 610 611 :param str prefix: 612 Filters the results to return only containers whose names 613 begin with the specified prefix. 614 :param str marker: 615 A string value that identifies the portion of the list 616 to be returned with the next list operation. The operation returns 617 a next_marker value within the response body if the list returned was 618 not complete. The marker value may then be used in a subsequent 619 call to request the next set of list items. The marker value is 620 opaque to the client. 621 :param int max_results: 622 Specifies the maximum number of containers to return. A single list 623 request may return up to 1000 contianers and potentially a continuation 624 token which should be followed to get additional resutls. 625 :param str include: 626 Include this parameter to specify that the container's 627 metadata be returned as part of the response body. set this 628 parameter to string 'metadata' to get container's metadata. 629 :param int timeout: 630 The timeout parameter is expressed in seconds. 631 ''' 632 request = HTTPRequest() 633 request.method = 'GET' 634 request.host_locations = self._get_host_locations(secondary=True) 635 request.path = _get_path() 636 request.query = { 637 'comp': 'list', 638 'prefix': _to_str(prefix), 639 'marker': _to_str(marker), 640 'maxresults': _int_to_str(max_results), 641 'include': _to_str(include), 642 'timeout': _int_to_str(timeout) 643 } 644 645 return self._perform_request(request, _convert_xml_to_containers, operation_context=_context) 646 647 def create_container(self, container_name, metadata=None, 648 public_access=None, fail_on_exist=False, timeout=None): 649 ''' 650 Creates a new container under the specified account. If the container 651 with the same name already exists, the operation fails if 652 fail_on_exist is True. 653 654 :param str container_name: 655 Name of container to create. 656 :param metadata: 657 A dict with name_value pairs to associate with the 658 container as metadata. Example:{'Category':'test'} 659 :type metadata: dict(str, str) 660 :param ~azure.storage.blob.models.PublicAccess public_access: 661 Possible values include: container, blob. 662 :param bool fail_on_exist: 663 Specify whether to throw an exception when the container exists. 664 :param int timeout: 665 The timeout parameter is expressed in seconds. 666 :return: True if container is created, False if container already exists. 667 :rtype: bool 668 ''' 669 _validate_not_none('container_name', container_name) 670 request = HTTPRequest() 671 request.method = 'PUT' 672 request.host_locations = self._get_host_locations() 673 request.path = _get_path(container_name) 674 request.query = { 675 'restype': 'container', 676 'timeout': _int_to_str(timeout), 677 } 678 request.headers = { 679 'x-ms-blob-public-access': _to_str(public_access) 680 } 681 _add_metadata_headers(metadata, request) 682 683 if not fail_on_exist: 684 try: 685 self._perform_request(request, expected_errors=[_CONTAINER_ALREADY_EXISTS_ERROR_CODE]) 686 return True 687 except AzureHttpError as ex: 688 _dont_fail_on_exist(ex) 689 return False 690 else: 691 self._perform_request(request) 692 return True 693 694 def get_container_properties(self, container_name, lease_id=None, timeout=None): 695 ''' 696 Returns all user-defined metadata and system properties for the specified 697 container. The data returned does not include the container's list of blobs. 698 699 :param str container_name: 700 Name of existing container. 701 :param str lease_id: 702 If specified, get_container_properties only succeeds if the 703 container's lease is active and matches this ID. 704 :param int timeout: 705 The timeout parameter is expressed in seconds. 706 :return: properties for the specified container within a container object. 707 :rtype: :class:`~azure.storage.blob.models.Container` 708 ''' 709 _validate_not_none('container_name', container_name) 710 request = HTTPRequest() 711 request.method = 'GET' 712 request.host_locations = self._get_host_locations(secondary=True) 713 request.path = _get_path(container_name) 714 request.query = { 715 'restype': 'container', 716 'timeout': _int_to_str(timeout), 717 } 718 request.headers = {'x-ms-lease-id': _to_str(lease_id)} 719 720 return self._perform_request(request, _parse_container, [container_name]) 721 722 def get_container_metadata(self, container_name, lease_id=None, timeout=None): 723 ''' 724 Returns all user-defined metadata for the specified container. 725 726 :param str container_name: 727 Name of existing container. 728 :param str lease_id: 729 If specified, get_container_metadata only succeeds if the 730 container's lease is active and matches this ID. 731 :param int timeout: 732 The timeout parameter is expressed in seconds. 733 :return: 734 A dictionary representing the container metadata name, value pairs. 735 :rtype: dict(str, str) 736 ''' 737 _validate_not_none('container_name', container_name) 738 request = HTTPRequest() 739 request.method = 'GET' 740 request.host_locations = self._get_host_locations(secondary=True) 741 request.path = _get_path(container_name) 742 request.query = { 743 'restype': 'container', 744 'comp': 'metadata', 745 'timeout': _int_to_str(timeout), 746 } 747 request.headers = {'x-ms-lease-id': _to_str(lease_id)} 748 749 return self._perform_request(request, _parse_metadata) 750 751 def set_container_metadata(self, container_name, metadata=None, 752 lease_id=None, if_modified_since=None, timeout=None): 753 ''' 754 Sets one or more user-defined name-value pairs for the specified 755 container. Each call to this operation replaces all existing metadata 756 attached to the container. To remove all metadata from the container, 757 call this operation with no metadata dict. 758 759 :param str container_name: 760 Name of existing container. 761 :param metadata: 762 A dict containing name-value pairs to associate with the container as 763 metadata. Example: {'category':'test'} 764 :type metadata: dict(str, str) 765 :param str lease_id: 766 If specified, set_container_metadata only succeeds if the 767 container's lease is active and matches this ID. 768 :param datetime if_modified_since: 769 A DateTime value. Azure expects the date value passed in to be UTC. 770 If timezone is included, any non-UTC datetimes will be converted to UTC. 771 If a date is passed in without timezone info, it is assumed to be UTC. 772 Specify this header to perform the operation only 773 if the resource has been modified since the specified time. 774 :param int timeout: 775 The timeout parameter is expressed in seconds. 776 :return: ETag and last modified properties for the updated Container 777 :rtype: :class:`~azure.storage.blob.models.ResourceProperties` 778 ''' 779 _validate_not_none('container_name', container_name) 780 request = HTTPRequest() 781 request.method = 'PUT' 782 request.host_locations = self._get_host_locations() 783 request.path = _get_path(container_name) 784 request.query = { 785 'restype': 'container', 786 'comp': 'metadata', 787 'timeout': _int_to_str(timeout), 788 } 789 request.headers = { 790 'If-Modified-Since': _datetime_to_utc_string(if_modified_since), 791 'x-ms-lease-id': _to_str(lease_id), 792 } 793 _add_metadata_headers(metadata, request) 794 795 return self._perform_request(request, _parse_base_properties) 796 797 def get_container_acl(self, container_name, lease_id=None, timeout=None): 798 ''' 799 Gets the permissions for the specified container. 800 The permissions indicate whether container data may be accessed publicly. 801 802 :param str container_name: 803 Name of existing container. 804 :param lease_id: 805 If specified, get_container_acl only succeeds if the 806 container's lease is active and matches this ID. 807 :param int timeout: 808 The timeout parameter is expressed in seconds. 809 :return: A dictionary of access policies associated with the container. dict of str to 810 :class:`azure.storage.common.models.AccessPolicy` and a public_access property 811 if public access is turned on 812 ''' 813 _validate_not_none('container_name', container_name) 814 request = HTTPRequest() 815 request.method = 'GET' 816 request.host_locations = self._get_host_locations(secondary=True) 817 request.path = _get_path(container_name) 818 request.query = { 819 'restype': 'container', 820 'comp': 'acl', 821 'timeout': _int_to_str(timeout), 822 } 823 request.headers = {'x-ms-lease-id': _to_str(lease_id)} 824 825 return self._perform_request(request, _convert_xml_to_signed_identifiers_and_access) 826 827 def set_container_acl(self, container_name, signed_identifiers=None, 828 public_access=None, lease_id=None, 829 if_modified_since=None, if_unmodified_since=None, timeout=None): 830 ''' 831 Sets the permissions for the specified container or stored access 832 policies that may be used with Shared Access Signatures. The permissions 833 indicate whether blobs in a container may be accessed publicly. 834 835 :param str container_name: 836 Name of existing container. 837 :param signed_identifiers: 838 A dictionary of access policies to associate with the container. The 839 dictionary may contain up to 5 elements. An empty dictionary 840 will clear the access policies set on the service. 841 :type signed_identifiers: dict(str, :class:`~azure.storage.common.models.AccessPolicy`) 842 :param ~azure.storage.blob.models.PublicAccess public_access: 843 Possible values include: container, blob. 844 :param str lease_id: 845 If specified, set_container_acl only succeeds if the 846 container's lease is active and matches this ID. 847 :param datetime if_modified_since: 848 A datetime value. Azure expects the date value passed in to be UTC. 849 If timezone is included, any non-UTC datetimes will be converted to UTC. 850 If a date is passed in without timezone info, it is assumed to be UTC. 851 Specify this header to perform the operation only 852 if the resource has been modified since the specified date/time. 853 :param datetime if_unmodified_since: 854 A datetime value. Azure expects the date value passed in to be UTC. 855 If timezone is included, any non-UTC datetimes will be converted to UTC. 856 If a date is passed in without timezone info, it is assumed to be UTC. 857 Specify this header to perform the operation only if 858 the resource has not been modified since the specified date/time. 859 :param int timeout: 860 The timeout parameter is expressed in seconds. 861 :return: ETag and last modified properties for the updated Container 862 :rtype: :class:`~azure.storage.blob.models.ResourceProperties` 863 ''' 864 _validate_not_none('container_name', container_name) 865 _validate_access_policies(signed_identifiers) 866 request = HTTPRequest() 867 request.method = 'PUT' 868 request.host_locations = self._get_host_locations() 869 request.path = _get_path(container_name) 870 request.query = { 871 'restype': 'container', 872 'comp': 'acl', 873 'timeout': _int_to_str(timeout), 874 } 875 request.headers = { 876 'x-ms-blob-public-access': _to_str(public_access), 877 'If-Modified-Since': _datetime_to_utc_string(if_modified_since), 878 'If-Unmodified-Since': _datetime_to_utc_string(if_unmodified_since), 879 'x-ms-lease-id': _to_str(lease_id), 880 } 881 request.body = _get_request_body( 882 _convert_signed_identifiers_to_xml(signed_identifiers)) 883 884 return self._perform_request(request, _parse_base_properties) 885 886 def delete_container(self, container_name, fail_not_exist=False, 887 lease_id=None, if_modified_since=None, 888 if_unmodified_since=None, timeout=None): 889 ''' 890 Marks the specified container for deletion. The container and any blobs 891 contained within it are later deleted during garbage collection. 892 893 :param str container_name: 894 Name of container to delete. 895 :param bool fail_not_exist: 896 Specify whether to throw an exception when the container doesn't 897 exist. 898 :param str lease_id: 899 If specified, delete_container only succeeds if the 900 container's lease is active and matches this ID. 901 Required if the container has an active lease. 902 :param datetime if_modified_since: 903 A DateTime value. Azure expects the date value passed in to be UTC. 904 If timezone is included, any non-UTC datetimes will be converted to UTC. 905 If a date is passed in without timezone info, it is assumed to be UTC. 906 Specify this header to perform the operation only 907 if the resource has been modified since the specified time. 908 :param datetime if_unmodified_since: 909 A DateTime value. Azure expects the date value passed in to be UTC. 910 If timezone is included, any non-UTC datetimes will be converted to UTC. 911 If a date is passed in without timezone info, it is assumed to be UTC. 912 Specify this header to perform the operation only if 913 the resource has not been modified since the specified date/time. 914 :param int timeout: 915 The timeout parameter is expressed in seconds. 916 :return: True if container is deleted, False container doesn't exist. 917 :rtype: bool 918 ''' 919 _validate_not_none('container_name', container_name) 920 request = HTTPRequest() 921 request.method = 'DELETE' 922 request.host_locations = self._get_host_locations() 923 request.path = _get_path(container_name) 924 request.query = { 925 'restype': 'container', 926 'timeout': _int_to_str(timeout), 927 } 928 request.headers = { 929 'x-ms-lease-id': _to_str(lease_id), 930 'If-Modified-Since': _datetime_to_utc_string(if_modified_since), 931 'If-Unmodified-Since': _datetime_to_utc_string(if_unmodified_since), 932 } 933 934 if not fail_not_exist: 935 try: 936 self._perform_request(request, expected_errors=[_CONTAINER_NOT_FOUND_ERROR_CODE]) 937 return True 938 except AzureHttpError as ex: 939 _dont_fail_not_exist(ex) 940 return False 941 else: 942 self._perform_request(request) 943 return True 944 945 def _lease_container_impl( 946 self, container_name, lease_action, lease_id, lease_duration, 947 lease_break_period, proposed_lease_id, if_modified_since, 948 if_unmodified_since, timeout): 949 ''' 950 Establishes and manages a lease on a container. 951 The Lease Container operation can be called in one of five modes 952 Acquire, to request a new lease 953 Renew, to renew an existing lease 954 Change, to change the ID of an existing lease 955 Release, to free the lease if it is no longer needed so that another 956 client may immediately acquire a lease against the container 957 Break, to end the lease but ensure that another client cannot acquire 958 a new lease until the current lease period has expired 959 960 :param str container_name: 961 Name of existing container. 962 :param str lease_action: 963 Possible _LeaseActions values: acquire|renew|release|break|change 964 :param str lease_id: 965 Required if the container has an active lease. 966 :param int lease_duration: 967 Specifies the duration of the lease, in seconds, or negative one 968 (-1) for a lease that never expires. A non-infinite lease can be 969 between 15 and 60 seconds. A lease duration cannot be changed 970 using renew or change. For backwards compatibility, the default is 971 60, and the value is only used on an acquire operation. 972 :param int lease_break_period: 973 For a break operation, this is the proposed duration of 974 seconds that the lease should continue before it is broken, between 975 0 and 60 seconds. This break period is only used if it is shorter 976 than the time remaining on the lease. If longer, the time remaining 977 on the lease is used. A new lease will not be available before the 978 break period has expired, but the lease may be held for longer than 979 the break period. If this header does not appear with a break 980 operation, a fixed-duration lease breaks after the remaining lease 981 period elapses, and an infinite lease breaks immediately. 982 :param str proposed_lease_id: 983 Optional for Acquire, required for Change. Proposed lease ID, in a 984 GUID string format. The Blob service returns 400 (Invalid request) 985 if the proposed lease ID is not in the correct format. 986 :param datetime if_modified_since: 987 A DateTime value. Azure expects the date value passed in to be UTC. 988 If timezone is included, any non-UTC datetimes will be converted to UTC. 989 If a date is passed in without timezone info, it is assumed to be UTC. 990 Specify this header to perform the operation only 991 if the resource has been modified since the specified time. 992 :param datetime if_unmodified_since: 993 A DateTime value. Azure expects the date value passed in to be UTC. 994 If timezone is included, any non-UTC datetimes will be converted to UTC. 995 If a date is passed in without timezone info, it is assumed to be UTC. 996 Specify this header to perform the operation only if 997 the resource has not been modified since the specified date/time. 998 :param int timeout: 999 The timeout parameter is expressed in seconds. 1000 :return: 1001 Response headers returned from the service call. 1002 :rtype: dict(str, str) 1003 ''' 1004 _validate_not_none('container_name', container_name) 1005 _validate_not_none('lease_action', lease_action) 1006 request = HTTPRequest() 1007 request.method = 'PUT' 1008 request.host_locations = self._get_host_locations() 1009 request.path = _get_path(container_name) 1010 request.query = { 1011 'restype': 'container', 1012 'comp': 'lease', 1013 'timeout': _int_to_str(timeout), 1014 } 1015 request.headers = { 1016 'x-ms-lease-id': _to_str(lease_id), 1017 'x-ms-lease-action': _to_str(lease_action), 1018 'x-ms-lease-duration': _to_str(lease_duration), 1019 'x-ms-lease-break-period': _to_str(lease_break_period), 1020 'x-ms-proposed-lease-id': _to_str(proposed_lease_id), 1021 'If-Modified-Since': _datetime_to_utc_string(if_modified_since), 1022 'If-Unmodified-Since': _datetime_to_utc_string(if_unmodified_since), 1023 } 1024 1025 return self._perform_request(request, _parse_lease) 1026 1027 def acquire_container_lease( 1028 self, container_name, lease_duration=-1, proposed_lease_id=None, 1029 if_modified_since=None, if_unmodified_since=None, timeout=None): 1030 ''' 1031 Requests a new lease. If the container does not have an active lease, 1032 the Blob service creates a lease on the container and returns a new 1033 lease ID. 1034 1035 :param str container_name: 1036 Name of existing container. 1037 :param int lease_duration: 1038 Specifies the duration of the lease, in seconds, or negative one 1039 (-1) for a lease that never expires. A non-infinite lease can be 1040 between 15 and 60 seconds. A lease duration cannot be changed 1041 using renew or change. Default is -1 (infinite lease). 1042 :param str proposed_lease_id: 1043 Proposed lease ID, in a GUID string format. The Blob service returns 1044 400 (Invalid request) if the proposed lease ID is not in the correct format. 1045 :param datetime if_modified_since: 1046 A DateTime value. Azure expects the date value passed in to be UTC. 1047 If timezone is included, any non-UTC datetimes will be converted to UTC. 1048 If a date is passed in without timezone info, it is assumed to be UTC. 1049 Specify this header to perform the operation only 1050 if the resource has been modified since the specified time. 1051 :param datetime if_unmodified_since: 1052 A DateTime value. Azure expects the date value passed in to be UTC. 1053 If timezone is included, any non-UTC datetimes will be converted to UTC. 1054 If a date is passed in without timezone info, it is assumed to be UTC. 1055 Specify this header to perform the operation only if 1056 the resource has not been modified since the specified date/time. 1057 :param int timeout: 1058 The timeout parameter is expressed in seconds. 1059 :return: the lease ID of the newly created lease. 1060 :return: str 1061 ''' 1062 _validate_not_none('lease_duration', lease_duration) 1063 if lease_duration != -1 and \ 1064 (lease_duration < 15 or lease_duration > 60): 1065 raise ValueError(_ERROR_INVALID_LEASE_DURATION) 1066 1067 lease = self._lease_container_impl(container_name, 1068 _LeaseActions.Acquire, 1069 None, # lease_id 1070 lease_duration, 1071 None, # lease_break_period 1072 proposed_lease_id, 1073 if_modified_since, 1074 if_unmodified_since, 1075 timeout) 1076 return lease['id'] 1077 1078 def renew_container_lease( 1079 self, container_name, lease_id, if_modified_since=None, 1080 if_unmodified_since=None, timeout=None): 1081 ''' 1082 Renews the lease. The lease can be renewed if the lease ID specified 1083 matches that associated with the container. Note that 1084 the lease may be renewed even if it has expired as long as the container 1085 has not been leased again since the expiration of that lease. When you 1086 renew a lease, the lease duration clock resets. 1087 1088 :param str container_name: 1089 Name of existing container. 1090 :param str lease_id: 1091 Lease ID for active lease. 1092 :param datetime if_modified_since: 1093 A DateTime value. Azure expects the date value passed in to be UTC. 1094 If timezone is included, any non-UTC datetimes will be converted to UTC. 1095 If a date is passed in without timezone info, it is assumed to be UTC. 1096 Specify this header to perform the operation only 1097 if the resource has been modified since the specified time. 1098 :param datetime if_unmodified_since: 1099 A DateTime value. Azure expects the date value passed in to be UTC. 1100 If timezone is included, any non-UTC datetimes will be converted to UTC. 1101 If a date is passed in without timezone info, it is assumed to be UTC. 1102 Specify this header to perform the operation only if 1103 the resource has not been modified since the specified date/time. 1104 :param int timeout: 1105 The timeout parameter is expressed in seconds. 1106 :return: the lease ID of the renewed lease. 1107 :return: str 1108 ''' 1109 _validate_not_none('lease_id', lease_id) 1110 1111 lease = self._lease_container_impl(container_name, 1112 _LeaseActions.Renew, 1113 lease_id, 1114 None, # lease_duration 1115 None, # lease_break_period 1116 None, # proposed_lease_id 1117 if_modified_since, 1118 if_unmodified_since, 1119 timeout) 1120 return lease['id'] 1121 1122 def release_container_lease( 1123 self, container_name, lease_id, if_modified_since=None, 1124 if_unmodified_since=None, timeout=None): 1125 ''' 1126 Release the lease. The lease may be released if the lease_id specified matches 1127 that associated with the container. Releasing the lease allows another client 1128 to immediately acquire the lease for the container as soon as the release is complete. 1129 1130 :param str container_name: 1131 Name of existing container. 1132 :param str lease_id: 1133 Lease ID for active lease. 1134 :param datetime if_modified_since: 1135 A DateTime value. Azure expects the date value passed in to be UTC. 1136 If timezone is included, any non-UTC datetimes will be converted to UTC. 1137 If a date is passed in without timezone info, it is assumed to be UTC. 1138 Specify this header to perform the operation only 1139 if the resource has been modified since the specified time. 1140 :param datetime if_unmodified_since: 1141 A DateTime value. Azure expects the date value passed in to be UTC. 1142 If timezone is included, any non-UTC datetimes will be converted to UTC. 1143 If a date is passed in without timezone info, it is assumed to be UTC. 1144 Specify this header to perform the operation only if 1145 the resource has not been modified since the specified date/time. 1146 :param int timeout: 1147 The timeout parameter is expressed in seconds. 1148 ''' 1149 _validate_not_none('lease_id', lease_id) 1150 1151 self._lease_container_impl(container_name, 1152 _LeaseActions.Release, 1153 lease_id, 1154 None, # lease_duration 1155 None, # lease_break_period 1156 None, # proposed_lease_id 1157 if_modified_since, 1158 if_unmodified_since, 1159 timeout) 1160 1161 def break_container_lease( 1162 self, container_name, lease_break_period=None, 1163 if_modified_since=None, if_unmodified_since=None, timeout=None): 1164 ''' 1165 Break the lease, if the container has an active lease. Once a lease is 1166 broken, it cannot be renewed. Any authorized request can break the lease; 1167 the request is not required to specify a matching lease ID. When a lease 1168 is broken, the lease break period is allowed to elapse, during which time 1169 no lease operation except break and release can be performed on the container. 1170 When a lease is successfully broken, the response indicates the interval 1171 in seconds until a new lease can be acquired. 1172 1173 :param str container_name: 1174 Name of existing container. 1175 :param int lease_break_period: 1176 This is the proposed duration of seconds that the lease 1177 should continue before it is broken, between 0 and 60 seconds. This 1178 break period is only used if it is shorter than the time remaining 1179 on the lease. If longer, the time remaining on the lease is used. 1180 A new lease will not be available before the break period has 1181 expired, but the lease may be held for longer than the break 1182 period. If this header does not appear with a break 1183 operation, a fixed-duration lease breaks after the remaining lease 1184 period elapses, and an infinite lease breaks immediately. 1185 :param datetime if_modified_since: 1186 A DateTime value. Azure expects the date value passed in to be UTC. 1187 If timezone is included, any non-UTC datetimes will be converted to UTC. 1188 If a date is passed in without timezone info, it is assumed to be UTC. 1189 Specify this header to perform the operation only 1190 if the resource has been modified since the specified time. 1191 :param datetime if_unmodified_since: 1192 A DateTime value. Azure expects the date value passed in to be UTC. 1193 If timezone is included, any non-UTC datetimes will be converted to UTC. 1194 If a date is passed in without timezone info, it is assumed to be UTC. 1195 Specify this header to perform the operation only if 1196 the resource has not been modified since the specified date/time. 1197 :param int timeout: 1198 The timeout parameter is expressed in seconds. 1199 :return: Approximate time remaining in the lease period, in seconds. 1200 :return: int 1201 ''' 1202 if (lease_break_period is not None) and (lease_break_period < 0 or lease_break_period > 60): 1203 raise ValueError(_ERROR_INVALID_LEASE_BREAK_PERIOD) 1204 1205 lease = self._lease_container_impl(container_name, 1206 _LeaseActions.Break, 1207 None, # lease_id 1208 None, # lease_duration 1209 lease_break_period, 1210 None, # proposed_lease_id 1211 if_modified_since, 1212 if_unmodified_since, 1213 timeout) 1214 return lease['time'] 1215 1216 def change_container_lease( 1217 self, container_name, lease_id, proposed_lease_id, 1218 if_modified_since=None, if_unmodified_since=None, timeout=None): 1219 ''' 1220 Change the lease ID of an active lease. A change must include the current 1221 lease ID and a new lease ID. 1222 1223 :param str container_name: 1224 Name of existing container. 1225 :param str lease_id: 1226 Lease ID for active lease. 1227 :param str proposed_lease_id: 1228 Proposed lease ID, in a GUID string format. The Blob service returns 400 1229 (Invalid request) if the proposed lease ID is not in the correct format. 1230 :param datetime if_modified_since: 1231 A DateTime value. Azure expects the date value passed in to be UTC. 1232 If timezone is included, any non-UTC datetimes will be converted to UTC. 1233 If a date is passed in without timezone info, it is assumed to be UTC. 1234 Specify this header to perform the operation only 1235 if the resource has been modified since the specified time. 1236 :param datetime if_unmodified_since: 1237 A DateTime value. Azure expects the date value passed in to be UTC. 1238 If timezone is included, any non-UTC datetimes will be converted to UTC. 1239 If a date is passed in without timezone info, it is assumed to be UTC. 1240 Specify this header to perform the operation only if 1241 the resource has not been modified since the specified date/time. 1242 :param int timeout: 1243 The timeout parameter is expressed in seconds. 1244 ''' 1245 _validate_not_none('lease_id', lease_id) 1246 1247 self._lease_container_impl(container_name, 1248 _LeaseActions.Change, 1249 lease_id, 1250 None, # lease_duration 1251 None, # lease_break_period 1252 proposed_lease_id, 1253 if_modified_since, 1254 if_unmodified_since, 1255 timeout) 1256 1257 def list_blobs(self, container_name, prefix=None, num_results=None, include=None, 1258 delimiter=None, marker=None, timeout=None): 1259 ''' 1260 Returns a generator to list the blobs under the specified container. 1261 The generator will lazily follow the continuation tokens returned by 1262 the service and stop when all blobs have been returned or num_results is reached. 1263 1264 If num_results is specified and the account has more than that number of 1265 blobs, the generator will have a populated next_marker field once it 1266 finishes. This marker can be used to create a new generator if more 1267 results are desired. 1268 1269 :param str container_name: 1270 Name of existing container. 1271 :param str prefix: 1272 Filters the results to return only blobs whose names 1273 begin with the specified prefix. 1274 :param int num_results: 1275 Specifies the maximum number of blobs to return, 1276 including all :class:`BlobPrefix` elements. If the request does not specify 1277 num_results or specifies a value greater than 5,000, the server will 1278 return up to 5,000 items. Setting num_results to a value less than 1279 or equal to zero results in error response code 400 (Bad Request). 1280 :param ~azure.storage.blob.models.Include include: 1281 Specifies one or more additional datasets to include in the response. 1282 :param str delimiter: 1283 When the request includes this parameter, the operation 1284 returns a :class:`~azure.storage.blob.models.BlobPrefix` element in the 1285 result list that acts as a placeholder for all blobs whose names begin 1286 with the same substring up to the appearance of the delimiter character. 1287 The delimiter may be a single character or a string. 1288 :param str marker: 1289 An opaque continuation token. This value can be retrieved from the 1290 next_marker field of a previous generator object if num_results was 1291 specified and that generator has finished enumerating results. If 1292 specified, this generator will begin returning results from the point 1293 where the previous generator stopped. 1294 :param int timeout: 1295 The timeout parameter is expressed in seconds. 1296 ''' 1297 operation_context = _OperationContext(location_lock=True) 1298 args = (container_name,) 1299 kwargs = {'prefix': prefix, 'marker': marker, 'max_results': num_results, 1300 'include': include, 'delimiter': delimiter, 'timeout': timeout, 1301 '_context': operation_context, 1302 '_converter': _convert_xml_to_blob_list} 1303 resp = self._list_blobs(*args, **kwargs) 1304 1305 return ListGenerator(resp, self._list_blobs, args, kwargs) 1306 1307 def list_blob_names(self, container_name, prefix=None, num_results=None, 1308 include=None, delimiter=None, marker=None, 1309 timeout=None): 1310 ''' 1311 Returns a generator to list the blob names under the specified container. 1312 The generator will lazily follow the continuation tokens returned by 1313 the service and stop when all blobs have been returned or num_results is reached. 1314 1315 If num_results is specified and the account has more than that number of 1316 blobs, the generator will have a populated next_marker field once it 1317 finishes. This marker can be used to create a new generator if more 1318 results are desired. 1319 1320 :param str container_name: 1321 Name of existing container. 1322 :param str prefix: 1323 Filters the results to return only blobs whose names 1324 begin with the specified prefix. 1325 :param int num_results: 1326 Specifies the maximum number of blobs to return, 1327 including all :class:`BlobPrefix` elements. If the request does not specify 1328 num_results or specifies a value greater than 5,000, the server will 1329 return up to 5,000 items. Setting num_results to a value less than 1330 or equal to zero results in error response code 400 (Bad Request). 1331 :param ~azure.storage.blob.models.Include include: 1332 Specifies one or more additional datasets to include in the response. 1333 :param str delimiter: 1334 When the request includes this parameter, the operation 1335 returns a :class:`~azure.storage.blob.models.BlobPrefix` element in the 1336 result list that acts as a placeholder for all blobs whose names begin 1337 with the same substring up to the appearance of the delimiter character. 1338 The delimiter may be a single character or a string. 1339 :param str marker: 1340 An opaque continuation token. This value can be retrieved from the 1341 next_marker field of a previous generator object if num_results was 1342 specified and that generator has finished enumerating results. If 1343 specified, this generator will begin returning results from the point 1344 where the previous generator stopped. 1345 :param int timeout: 1346 The timeout parameter is expressed in seconds. 1347 ''' 1348 operation_context = _OperationContext(location_lock=True) 1349 args = (container_name,) 1350 kwargs = {'prefix': prefix, 'marker': marker, 'max_results': num_results, 1351 'include': include, 'delimiter': delimiter, 'timeout': timeout, 1352 '_context': operation_context, 1353 '_converter': _convert_xml_to_blob_name_list} 1354 resp = self._list_blobs(*args, **kwargs) 1355 1356 return ListGenerator(resp, self._list_blobs, args, kwargs) 1357 1358 def _list_blobs(self, container_name, prefix=None, marker=None, 1359 max_results=None, include=None, delimiter=None, timeout=None, 1360 _context=None, _converter=None): 1361 ''' 1362 Returns the list of blobs under the specified container. 1363 1364 :param str container_name: 1365 Name of existing container. 1366 :parm str prefix: 1367 Filters the results to return only blobs whose names 1368 begin with the specified prefix. 1369 :param str marker: 1370 A string value that identifies the portion of the list 1371 to be returned with the next list operation. The operation returns 1372 a next_marker value within the response body if the list returned was 1373 not complete. The marker value may then be used in a subsequent 1374 call to request the next set of list items. The marker value is 1375 opaque to the client. 1376 :param int max_results: 1377 Specifies the maximum number of blobs to return, 1378 including all :class:`~azure.storage.blob.models.BlobPrefix` elements. If the request does not specify 1379 max_results or specifies a value greater than 5,000, the server will 1380 return up to 5,000 items. Setting max_results to a value less than 1381 or equal to zero results in error response code 400 (Bad Request). 1382 :param str include: 1383 Specifies one or more datasets to include in the 1384 response. To specify more than one of these options on the URI, 1385 you must separate each option with a comma. Valid values are: 1386 snapshots: 1387 Specifies that snapshots should be included in the 1388 enumeration. Snapshots are listed from oldest to newest in 1389 the response. 1390 metadata: 1391 Specifies that blob metadata be returned in the response. 1392 uncommittedblobs: 1393 Specifies that blobs for which blocks have been uploaded, 1394 but which have not been committed using Put Block List 1395 (REST API), be included in the response. 1396 copy: 1397 Version 2012-02-12 and newer. Specifies that metadata 1398 related to any current or previous Copy Blob operation 1399 should be included in the response. 1400 deleted: 1401 Version 2017-07-29 and newer. Specifies that soft deleted blobs 1402 which are retained by the service should be included 1403 in the response. 1404 :param str delimiter: 1405 When the request includes this parameter, the operation 1406 returns a :class:`~azure.storage.blob.models.BlobPrefix` element in the response body that acts as a 1407 placeholder for all blobs whose names begin with the same 1408 substring up to the appearance of the delimiter character. The 1409 delimiter may be a single character or a string. 1410 :param int timeout: 1411 The timeout parameter is expressed in seconds. 1412 ''' 1413 _validate_not_none('container_name', container_name) 1414 request = HTTPRequest() 1415 request.method = 'GET' 1416 request.host_locations = self._get_host_locations(secondary=True) 1417 request.path = _get_path(container_name) 1418 request.query = { 1419 'restype': 'container', 1420 'comp': 'list', 1421 'prefix': _to_str(prefix), 1422 'delimiter': _to_str(delimiter), 1423 'marker': _to_str(marker), 1424 'maxresults': _int_to_str(max_results), 1425 'include': _to_str(include), 1426 'timeout': _int_to_str(timeout), 1427 } 1428 1429 return self._perform_request(request, _converter, operation_context=_context) 1430 1431 def get_blob_account_information(self, container_name=None, blob_name=None, timeout=None): 1432 """ 1433 Gets information related to the storage account. 1434 The information can also be retrieved if the user has a SAS to a container or blob. 1435 1436 :param str container_name: 1437 Name of existing container. 1438 Optional, unless using a SAS token to a specific container or blob, in which case it's required. 1439 :param str blob_name: 1440 Name of existing blob. 1441 Optional, unless using a SAS token to a specific blob, in which case it's required. 1442 :param int timeout: 1443 The timeout parameter is expressed in seconds. 1444 :return: The :class:`~azure.storage.blob.models.AccountInformation`. 1445 """ 1446 request = HTTPRequest() 1447 request.method = 'HEAD' 1448 request.host_locations = self._get_host_locations(secondary=True) 1449 request.path = _get_path(container_name, blob_name) 1450 request.query = { 1451 'restype': 'account', 1452 'comp': 'properties', 1453 'timeout': _int_to_str(timeout), 1454 } 1455 1456 return self._perform_request(request, _parse_account_information) 1457 1458 def get_blob_service_stats(self, timeout=None): 1459 ''' 1460 Retrieves statistics related to replication for the Blob service. It is 1461 only available when read-access geo-redundant replication is enabled for 1462 the storage account. 1463 1464 With geo-redundant replication, Azure Storage maintains your data durable 1465 in two locations. In both locations, Azure Storage constantly maintains 1466 multiple healthy replicas of your data. The location where you read, 1467 create, update, or delete data is the primary storage account location. 1468 The primary location exists in the region you choose at the time you 1469 create an account via the Azure Management Azure classic portal, for 1470 example, North Central US. The location to which your data is replicated 1471 is the secondary location. The secondary location is automatically 1472 determined based on the location of the primary; it is in a second data 1473 center that resides in the same region as the primary location. Read-only 1474 access is available from the secondary location, if read-access geo-redundant 1475 replication is enabled for your storage account. 1476 1477 :param int timeout: 1478 The timeout parameter is expressed in seconds. 1479 :return: The blob service stats. 1480 :rtype: :class:`~azure.storage.common.models.ServiceStats` 1481 ''' 1482 request = HTTPRequest() 1483 request.method = 'GET' 1484 request.host_locations = self._get_host_locations(primary=False, secondary=True) 1485 request.path = _get_path() 1486 request.query = { 1487 'restype': 'service', 1488 'comp': 'stats', 1489 'timeout': _int_to_str(timeout), 1490 } 1491 1492 return self._perform_request(request, _convert_xml_to_service_stats) 1493 1494 def set_blob_service_properties( 1495 self, logging=None, hour_metrics=None, minute_metrics=None, 1496 cors=None, target_version=None, timeout=None, delete_retention_policy=None, static_website=None): 1497 ''' 1498 Sets the properties of a storage account's Blob service, including 1499 Azure Storage Analytics. If an element (ex Logging) is left as None, the 1500 existing settings on the service for that functionality are preserved. 1501 1502 :param logging: 1503 Groups the Azure Analytics Logging settings. 1504 :type logging: 1505 :class:`~azure.storage.common.models.Logging` 1506 :param hour_metrics: 1507 The hour metrics settings provide a summary of request 1508 statistics grouped by API in hourly aggregates for blobs. 1509 :type hour_metrics: 1510 :class:`~azure.storage.common.models.Metrics` 1511 :param minute_metrics: 1512 The minute metrics settings provide request statistics 1513 for each minute for blobs. 1514 :type minute_metrics: 1515 :class:`~azure.storage.common.models.Metrics` 1516 :param cors: 1517 You can include up to five CorsRule elements in the 1518 list. If an empty list is specified, all CORS rules will be deleted, 1519 and CORS will be disabled for the service. 1520 :type cors: list(:class:`~azure.storage.common.models.CorsRule`) 1521 :param str target_version: 1522 Indicates the default version to use for requests if an incoming 1523 request's version is not specified. 1524 :param int timeout: 1525 The timeout parameter is expressed in seconds. 1526 :param delete_retention_policy: 1527 The delete retention policy specifies whether to retain deleted blobs. 1528 It also specifies the number of days and versions of blob to keep. 1529 :type delete_retention_policy: 1530 :class:`~azure.storage.common.models.DeleteRetentionPolicy` 1531 :param static_website: 1532 Specifies whether the static website feature is enabled, 1533 and if yes, indicates the index document and 404 error document to use. 1534 :type static_website: 1535 :class:`~azure.storage.common.models.StaticWebsite` 1536 ''' 1537 if all(parameter is None for parameter in [logging, hour_metrics, minute_metrics, cors, target_version, 1538 delete_retention_policy, static_website]): 1539 1540 raise ValueError("set_blob_service_properties should be called with at least one parameter") 1541 1542 request = HTTPRequest() 1543 request.method = 'PUT' 1544 request.host_locations = self._get_host_locations() 1545 request.path = _get_path() 1546 request.query = { 1547 'restype': 'service', 1548 'comp': 'properties', 1549 'timeout': _int_to_str(timeout), 1550 } 1551 request.body = _get_request_body( 1552 _convert_service_properties_to_xml(logging, hour_metrics, minute_metrics, 1553 cors, target_version, delete_retention_policy, static_website)) 1554 1555 self._perform_request(request) 1556 1557 def get_blob_service_properties(self, timeout=None): 1558 ''' 1559 Gets the properties of a storage account's Blob service, including 1560 Azure Storage Analytics. 1561 1562 :param int timeout: 1563 The timeout parameter is expressed in seconds. 1564 :return: The blob :class:`~azure.storage.common.models.ServiceProperties` with an attached 1565 target_version property. 1566 ''' 1567 request = HTTPRequest() 1568 request.method = 'GET' 1569 request.host_locations = self._get_host_locations(secondary=True) 1570 request.path = _get_path() 1571 request.query = { 1572 'restype': 'service', 1573 'comp': 'properties', 1574 'timeout': _int_to_str(timeout), 1575 } 1576 1577 return self._perform_request(request, _convert_xml_to_service_properties) 1578 1579 def get_blob_properties( 1580 self, container_name, blob_name, snapshot=None, lease_id=None, 1581 if_modified_since=None, if_unmodified_since=None, if_match=None, 1582 if_none_match=None, timeout=None): 1583 ''' 1584 Returns all user-defined metadata, standard HTTP properties, and 1585 system properties for the blob. It does not return the content of the blob. 1586 Returns :class:`~azure.storage.blob.models.Blob` 1587 with :class:`~azure.storage.blob.models.BlobProperties` and a metadata dict. 1588 1589 :param str container_name: 1590 Name of existing container. 1591 :param str blob_name: 1592 Name of existing blob. 1593 :param str snapshot: 1594 The snapshot parameter is an opaque DateTime value that, 1595 when present, specifies the blob snapshot to retrieve. 1596 :param str lease_id: 1597 Required if the blob has an active lease. 1598 :param datetime if_modified_since: 1599 A DateTime value. Azure expects the date value passed in to be UTC. 1600 If timezone is included, any non-UTC datetimes will be converted to UTC. 1601 If a date is passed in without timezone info, it is assumed to be UTC. 1602 Specify this header to perform the operation only 1603 if the resource has been modified since the specified time. 1604 :param datetime if_unmodified_since: 1605 A DateTime value. Azure expects the date value passed in to be UTC. 1606 If timezone is included, any non-UTC datetimes will be converted to UTC. 1607 If a date is passed in without timezone info, it is assumed to be UTC. 1608 Specify this header to perform the operation only if 1609 the resource has not been modified since the specified date/time. 1610 :param str if_match: 1611 An ETag value, or the wildcard character (*). Specify this header to perform 1612 the operation only if the resource's ETag matches the value specified. 1613 :param str if_none_match: 1614 An ETag value, or the wildcard character (*). Specify this header 1615 to perform the operation only if the resource's ETag does not match 1616 the value specified. Specify the wildcard character (*) to perform 1617 the operation only if the resource does not exist, and fail the 1618 operation if it does exist. 1619 :param int timeout: 1620 The timeout parameter is expressed in seconds. 1621 :return: a blob object including properties and metadata. 1622 :rtype: :class:`~azure.storage.blob.models.Blob` 1623 ''' 1624 _validate_not_none('container_name', container_name) 1625 _validate_not_none('blob_name', blob_name) 1626 request = HTTPRequest() 1627 request.method = 'HEAD' 1628 request.host_locations = self._get_host_locations(secondary=True) 1629 request.path = _get_path(container_name, blob_name) 1630 request.query = { 1631 'snapshot': _to_str(snapshot), 1632 'timeout': _int_to_str(timeout), 1633 } 1634 request.headers = { 1635 'x-ms-lease-id': _to_str(lease_id), 1636 'If-Modified-Since': _datetime_to_utc_string(if_modified_since), 1637 'If-Unmodified-Since': _datetime_to_utc_string(if_unmodified_since), 1638 'If-Match': _to_str(if_match), 1639 'If-None-Match': _to_str(if_none_match), 1640 } 1641 1642 return self._perform_request(request, _parse_blob, [blob_name, snapshot]) 1643 1644 def set_blob_properties( 1645 self, container_name, blob_name, content_settings=None, lease_id=None, 1646 if_modified_since=None, if_unmodified_since=None, if_match=None, 1647 if_none_match=None, timeout=None): 1648 ''' 1649 Sets system properties on the blob. If one property is set for the 1650 content_settings, all properties will be overriden. 1651 1652 :param str container_name: 1653 Name of existing container. 1654 :param str blob_name: 1655 Name of existing blob. 1656 :param ~azure.storage.blob.models.ContentSettings content_settings: 1657 ContentSettings object used to set blob properties. 1658 :param str lease_id: 1659 Required if the blob has an active lease. 1660 :param datetime if_modified_since: 1661 A DateTime value. Azure expects the date value passed in to be UTC. 1662 If timezone is included, any non-UTC datetimes will be converted to UTC. 1663 If a date is passed in without timezone info, it is assumed to be UTC. 1664 Specify this header to perform the operation only 1665 if the resource has been modified since the specified time. 1666 :param datetime if_unmodified_since: 1667 A DateTime value. Azure expects the date value passed in to be UTC. 1668 If timezone is included, any non-UTC datetimes will be converted to UTC. 1669 If a date is passed in without timezone info, it is assumed to be UTC. 1670 Specify this header to perform the operation only if 1671 the resource has not been modified since the specified date/time. 1672 :param str if_match: 1673 An ETag value, or the wildcard character (*). Specify this header to perform 1674 the operation only if the resource's ETag matches the value specified. 1675 :param str if_none_match: 1676 An ETag value, or the wildcard character (*). Specify this header 1677 to perform the operation only if the resource's ETag does not match 1678 the value specified. Specify the wildcard character (*) to perform 1679 the operation only if the resource does not exist, and fail the 1680 operation if it does exist. 1681 :param int timeout: 1682 The timeout parameter is expressed in seconds. 1683 :return: ETag and last modified properties for the updated Blob 1684 :rtype: :class:`~azure.storage.blob.models.ResourceProperties` 1685 ''' 1686 _validate_not_none('container_name', container_name) 1687 _validate_not_none('blob_name', blob_name) 1688 request = HTTPRequest() 1689 request.method = 'PUT' 1690 request.host_locations = self._get_host_locations() 1691 request.path = _get_path(container_name, blob_name) 1692 request.query = { 1693 'comp': 'properties', 1694 'timeout': _int_to_str(timeout), 1695 } 1696 request.headers = { 1697 'If-Modified-Since': _datetime_to_utc_string(if_modified_since), 1698 'If-Unmodified-Since': _datetime_to_utc_string(if_unmodified_since), 1699 'If-Match': _to_str(if_match), 1700 'If-None-Match': _to_str(if_none_match), 1701 'x-ms-lease-id': _to_str(lease_id) 1702 } 1703 if content_settings is not None: 1704 request.headers.update(content_settings._to_headers()) 1705 1706 return self._perform_request(request, _parse_base_properties) 1707 1708 def exists(self, container_name, blob_name=None, snapshot=None, timeout=None): 1709 ''' 1710 Returns a boolean indicating whether the container exists (if blob_name 1711 is None), or otherwise a boolean indicating whether the blob exists. 1712 1713 :param str container_name: 1714 Name of a container. 1715 :param str blob_name: 1716 Name of a blob. If None, the container will be checked for existence. 1717 :param str snapshot: 1718 The snapshot parameter is an opaque DateTime value that, 1719 when present, specifies the snapshot. 1720 :param int timeout: 1721 The timeout parameter is expressed in seconds. 1722 :return: A boolean indicating whether the resource exists. 1723 :rtype: bool 1724 ''' 1725 _validate_not_none('container_name', container_name) 1726 try: 1727 # make head request to see if container/blob/snapshot exists 1728 request = HTTPRequest() 1729 request.method = 'GET' if blob_name is None else 'HEAD' 1730 request.host_locations = self._get_host_locations(secondary=True) 1731 request.path = _get_path(container_name, blob_name) 1732 request.query = { 1733 'snapshot': _to_str(snapshot), 1734 'timeout': _int_to_str(timeout), 1735 'restype': 'container' if blob_name is None else None, 1736 } 1737 1738 expected_errors = [_CONTAINER_NOT_FOUND_ERROR_CODE] if blob_name is None \ 1739 else [_CONTAINER_NOT_FOUND_ERROR_CODE, _BLOB_NOT_FOUND_ERROR_CODE] 1740 self._perform_request(request, expected_errors=expected_errors) 1741 1742 return True 1743 except AzureHttpError as ex: 1744 _dont_fail_not_exist(ex) 1745 return False 1746 1747 def _get_blob( 1748 self, container_name, blob_name, snapshot=None, start_range=None, 1749 end_range=None, validate_content=False, lease_id=None, if_modified_since=None, 1750 if_unmodified_since=None, if_match=None, if_none_match=None, timeout=None, 1751 _context=None): 1752 ''' 1753 Downloads a blob's content, metadata, and properties. You can also 1754 call this API to read a snapshot. You can specify a range if you don't 1755 need to download the blob in its entirety. If no range is specified, 1756 the full blob will be downloaded. 1757 1758 See get_blob_to_* for high level functions that handle the download 1759 of large blobs with automatic chunking and progress notifications. 1760 1761 :param str container_name: 1762 Name of existing container. 1763 :param str blob_name: 1764 Name of existing blob. 1765 :param str snapshot: 1766 The snapshot parameter is an opaque DateTime value that, 1767 when present, specifies the blob snapshot to retrieve. 1768 :param int start_range: 1769 Start of byte range to use for downloading a section of the blob. 1770 If no end_range is given, all bytes after the start_range will be downloaded. 1771 The start_range and end_range params are inclusive. 1772 Ex: start_range=0, end_range=511 will download first 512 bytes of blob. 1773 :param int end_range: 1774 End of byte range to use for downloading a section of the blob. 1775 If end_range is given, start_range must be provided. 1776 The start_range and end_range params are inclusive. 1777 Ex: start_range=0, end_range=511 will download first 512 bytes of blob. 1778 :param bool validate_content: 1779 When this is set to True and specified together with the Range header, 1780 the service returns the MD5 hash for the range, as long as the range 1781 is less than or equal to 4 MB in size. 1782 :param str lease_id: 1783 Required if the blob has an active lease. 1784 :param datetime if_modified_since: 1785 A DateTime value. Azure expects the date value passed in to be UTC. 1786 If timezone is included, any non-UTC datetimes will be converted to UTC. 1787 If a date is passed in without timezone info, it is assumed to be UTC. 1788 Specify this header to perform the operation only 1789 if the resource has been modified since the specified time. 1790 :param datetime if_unmodified_since: 1791 A DateTime value. Azure expects the date value passed in to be UTC. 1792 If timezone is included, any non-UTC datetimes will be converted to UTC. 1793 If a date is passed in without timezone info, it is assumed to be UTC. 1794 Specify this header to perform the operation only if 1795 the resource has not been modified since the specified date/time. 1796 :param str if_match: 1797 An ETag value, or the wildcard character (*). Specify this header to perform 1798 the operation only if the resource's ETag matches the value specified. 1799 :param str if_none_match: 1800 An ETag value, or the wildcard character (*). Specify this header 1801 to perform the operation only if the resource's ETag does not match 1802 the value specified. Specify the wildcard character (*) to perform 1803 the operation only if the resource does not exist, and fail the 1804 operation if it does exist. 1805 :param int timeout: 1806 The timeout parameter is expressed in seconds. 1807 :return: A Blob with content, properties, and metadata. 1808 :rtype: :class:`~azure.storage.blob.models.Blob` 1809 ''' 1810 _validate_not_none('container_name', container_name) 1811 _validate_not_none('blob_name', blob_name) 1812 _validate_decryption_required(self.require_encryption, 1813 self.key_encryption_key, 1814 self.key_resolver_function) 1815 1816 start_offset, end_offset = 0, 0 1817 if self.key_encryption_key is not None or self.key_resolver_function is not None: 1818 if start_range is not None: 1819 # Align the start of the range along a 16 byte block 1820 start_offset = start_range % 16 1821 start_range -= start_offset 1822 1823 # Include an extra 16 bytes for the IV if necessary 1824 # Because of the previous offsetting, start_range will always 1825 # be a multiple of 16. 1826 if start_range > 0: 1827 start_offset += 16 1828 start_range -= 16 1829 1830 if end_range is not None: 1831 # Align the end of the range along a 16 byte block 1832 end_offset = 15 - (end_range % 16) 1833 end_range += end_offset 1834 1835 request = HTTPRequest() 1836 request.method = 'GET' 1837 request.host_locations = self._get_host_locations(secondary=True) 1838 request.path = _get_path(container_name, blob_name) 1839 request.query = { 1840 'snapshot': _to_str(snapshot), 1841 'timeout': _int_to_str(timeout), 1842 } 1843 request.headers = { 1844 'x-ms-lease-id': _to_str(lease_id), 1845 'If-Modified-Since': _datetime_to_utc_string(if_modified_since), 1846 'If-Unmodified-Since': _datetime_to_utc_string(if_unmodified_since), 1847 'If-Match': _to_str(if_match), 1848 'If-None-Match': _to_str(if_none_match), 1849 } 1850 _validate_and_format_range_headers( 1851 request, 1852 start_range, 1853 end_range, 1854 start_range_required=False, 1855 end_range_required=False, 1856 check_content_md5=validate_content) 1857 1858 return self._perform_request(request, _parse_blob, 1859 [blob_name, snapshot, validate_content, self.require_encryption, 1860 self.key_encryption_key, self.key_resolver_function, 1861 start_offset, end_offset], 1862 operation_context=_context) 1863 1864 def get_blob_to_path( 1865 self, container_name, blob_name, file_path, open_mode='wb', 1866 snapshot=None, start_range=None, end_range=None, 1867 validate_content=False, progress_callback=None, 1868 max_connections=2, lease_id=None, if_modified_since=None, 1869 if_unmodified_since=None, if_match=None, if_none_match=None, 1870 timeout=None): 1871 ''' 1872 Downloads a blob to a file path, with automatic chunking and progress 1873 notifications. Returns an instance of :class:`~azure.storage.blob.models.Blob` with 1874 properties and metadata. 1875 1876 :param str container_name: 1877 Name of existing container. 1878 :param str blob_name: 1879 Name of existing blob. 1880 :param str file_path: 1881 Path of file to write out to. 1882 :param str open_mode: 1883 Mode to use when opening the file. Note that specifying append only 1884 open_mode prevents parallel download. So, max_connections must be set 1885 to 1 if this open_mode is used. 1886 :param str snapshot: 1887 The snapshot parameter is an opaque DateTime value that, 1888 when present, specifies the blob snapshot to retrieve. 1889 :param int start_range: 1890 Start of byte range to use for downloading a section of the blob. 1891 If no end_range is given, all bytes after the start_range will be downloaded. 1892 The start_range and end_range params are inclusive. 1893 Ex: start_range=0, end_range=511 will download first 512 bytes of blob. 1894 :param int end_range: 1895 End of byte range to use for downloading a section of the blob. 1896 If end_range is given, start_range must be provided. 1897 The start_range and end_range params are inclusive. 1898 Ex: start_range=0, end_range=511 will download first 512 bytes of blob. 1899 :param bool validate_content: 1900 If set to true, validates an MD5 hash for each retrieved portion of 1901 the blob. This is primarily valuable for detecting bitflips on the wire 1902 if using http instead of https as https (the default) will already 1903 validate. Note that the service will only return transactional MD5s 1904 for chunks 4MB or less so the first get request will be of size 1905 self.MAX_CHUNK_GET_SIZE instead of self.MAX_SINGLE_GET_SIZE. If 1906 self.MAX_CHUNK_GET_SIZE was set to greater than 4MB an error will be 1907 thrown. As computing the MD5 takes processing time and more requests 1908 will need to be done due to the reduced chunk size there may be some 1909 increase in latency. 1910 :param progress_callback: 1911 Callback for progress with signature function(current, total) 1912 where current is the number of bytes transfered so far, and total is 1913 the size of the blob if known. 1914 :type progress_callback: func(current, total) 1915 :param int max_connections: 1916 If set to 2 or greater, an initial get will be done for the first 1917 self.MAX_SINGLE_GET_SIZE bytes of the blob. If this is the entire blob, 1918 the method returns at this point. If it is not, it will download the 1919 remaining data parallel using the number of threads equal to 1920 max_connections. Each chunk will be of size self.MAX_CHUNK_GET_SIZE. 1921 If set to 1, a single large get request will be done. This is not 1922 generally recommended but available if very few threads should be 1923 used, network requests are very expensive, or a non-seekable stream 1924 prevents parallel download. This may also be useful if many blobs are 1925 expected to be empty as an extra request is required for empty blobs 1926 if max_connections is greater than 1. 1927 :param str lease_id: 1928 Required if the blob has an active lease. 1929 :param datetime if_modified_since: 1930 A DateTime value. Azure expects the date value passed in to be UTC. 1931 If timezone is included, any non-UTC datetimes will be converted to UTC. 1932 If a date is passed in without timezone info, it is assumed to be UTC. 1933 Specify this header to perform the operation only 1934 if the resource has been modified since the specified time. 1935 :param datetime if_unmodified_since: 1936 A DateTime value. Azure expects the date value passed in to be UTC. 1937 If timezone is included, any non-UTC datetimes will be converted to UTC. 1938 If a date is passed in without timezone info, it is assumed to be UTC. 1939 Specify this header to perform the operation only if 1940 the resource has not been modified since the specified date/time. 1941 :param str if_match: 1942 An ETag value, or the wildcard character (*). Specify this header to perform 1943 the operation only if the resource's ETag matches the value specified. 1944 :param str if_none_match: 1945 An ETag value, or the wildcard character (*). Specify this header 1946 to perform the operation only if the resource's ETag does not match 1947 the value specified. Specify the wildcard character (*) to perform 1948 the operation only if the resource does not exist, and fail the 1949 operation if it does exist. 1950 :param int timeout: 1951 The timeout parameter is expressed in seconds. This method may make 1952 multiple calls to the Azure service and the timeout will apply to 1953 each call individually. 1954 :return: A Blob with properties and metadata. If max_connections is greater 1955 than 1, the content_md5 (if set on the blob) will not be returned. If you 1956 require this value, either use get_blob_properties or set max_connections 1957 to 1. 1958 :rtype: :class:`~azure.storage.blob.models.Blob` 1959 ''' 1960 _validate_not_none('container_name', container_name) 1961 _validate_not_none('blob_name', blob_name) 1962 _validate_not_none('file_path', file_path) 1963 _validate_not_none('open_mode', open_mode) 1964 1965 if max_connections > 1 and 'a' in open_mode: 1966 raise ValueError(_ERROR_PARALLEL_NOT_SEEKABLE) 1967 1968 with open(file_path, open_mode) as stream: 1969 blob = self.get_blob_to_stream( 1970 container_name, 1971 blob_name, 1972 stream, 1973 snapshot, 1974 start_range, 1975 end_range, 1976 validate_content, 1977 progress_callback, 1978 max_connections, 1979 lease_id, 1980 if_modified_since, 1981 if_unmodified_since, 1982 if_match, 1983 if_none_match, 1984 timeout) 1985 1986 return blob 1987 1988 def get_blob_to_stream( 1989 self, container_name, blob_name, stream, snapshot=None, 1990 start_range=None, end_range=None, validate_content=False, 1991 progress_callback=None, max_connections=2, lease_id=None, 1992 if_modified_since=None, if_unmodified_since=None, if_match=None, 1993 if_none_match=None, timeout=None): 1994 1995 ''' 1996 Downloads a blob to a stream, with automatic chunking and progress 1997 notifications. Returns an instance of :class:`~azure.storage.blob.models.Blob` with 1998 properties and metadata. 1999 2000 :param str container_name: 2001 Name of existing container. 2002 :param str blob_name: 2003 Name of existing blob. 2004 :param io.IOBase stream: 2005 Opened stream to write to. 2006 :param str snapshot: 2007 The snapshot parameter is an opaque DateTime value that, 2008 when present, specifies the blob snapshot to retrieve. 2009 :param int start_range: 2010 Start of byte range to use for downloading a section of the blob. 2011 If no end_range is given, all bytes after the start_range will be downloaded. 2012 The start_range and end_range params are inclusive. 2013 Ex: start_range=0, end_range=511 will download first 512 bytes of blob. 2014 :param int end_range: 2015 End of byte range to use for downloading a section of the blob. 2016 If end_range is given, start_range must be provided. 2017 The start_range and end_range params are inclusive. 2018 Ex: start_range=0, end_range=511 will download first 512 bytes of blob. 2019 :param bool validate_content: 2020 If set to true, validates an MD5 hash for each retrieved portion of 2021 the blob. This is primarily valuable for detecting bitflips on the wire 2022 if using http instead of https as https (the default) will already 2023 validate. Note that the service will only return transactional MD5s 2024 for chunks 4MB or less so the first get request will be of size 2025 self.MAX_CHUNK_GET_SIZE instead of self.MAX_SINGLE_GET_SIZE. If 2026 self.MAX_CHUNK_GET_SIZE was set to greater than 4MB an error will be 2027 thrown. As computing the MD5 takes processing time and more requests 2028 will need to be done due to the reduced chunk size there may be some 2029 increase in latency. 2030 :param progress_callback: 2031 Callback for progress with signature function(current, total) 2032 where current is the number of bytes transfered so far, and total is 2033 the size of the blob if known. 2034 :type progress_callback: func(current, total) 2035 :param int max_connections: 2036 If set to 2 or greater, an initial get will be done for the first 2037 self.MAX_SINGLE_GET_SIZE bytes of the blob. If this is the entire blob, 2038 the method returns at this point. If it is not, it will download the 2039 remaining data parallel using the number of threads equal to 2040 max_connections. Each chunk will be of size self.MAX_CHUNK_GET_SIZE. 2041 If set to 1, a single large get request will be done. This is not 2042 generally recommended but available if very few threads should be 2043 used, network requests are very expensive, or a non-seekable stream 2044 prevents parallel download. This may also be useful if many blobs are 2045 expected to be empty as an extra request is required for empty blobs 2046 if max_connections is greater than 1. 2047 :param str lease_id: 2048 Required if the blob has an active lease. 2049 :param datetime if_modified_since: 2050 A DateTime value. Azure expects the date value passed in to be UTC. 2051 If timezone is included, any non-UTC datetimes will be converted to UTC. 2052 If a date is passed in without timezone info, it is assumed to be UTC. 2053 Specify this header to perform the operation only 2054 if the resource has been modified since the specified time. 2055 :param datetime if_unmodified_since: 2056 A DateTime value. Azure expects the date value passed in to be UTC. 2057 If timezone is included, any non-UTC datetimes will be converted to UTC. 2058 If a date is passed in without timezone info, it is assumed to be UTC. 2059 Specify this header to perform the operation only if 2060 the resource has not been modified since the specified date/time. 2061 :param str if_match: 2062 An ETag value, or the wildcard character (*). Specify this header to perform 2063 the operation only if the resource's ETag matches the value specified. 2064 :param str if_none_match: 2065 An ETag value, or the wildcard character (*). Specify this header 2066 to perform the operation only if the resource's ETag does not match 2067 the value specified. Specify the wildcard character (*) to perform 2068 the operation only if the resource does not exist, and fail the 2069 operation if it does exist. 2070 :param int timeout: 2071 The timeout parameter is expressed in seconds. This method may make 2072 multiple calls to the Azure service and the timeout will apply to 2073 each call individually. 2074 :return: A Blob with properties and metadata. If max_connections is greater 2075 than 1, the content_md5 (if set on the blob) will not be returned. If you 2076 require this value, either use get_blob_properties or set max_connections 2077 to 1. 2078 :rtype: :class:`~azure.storage.blob.models.Blob` 2079 ''' 2080 _validate_not_none('container_name', container_name) 2081 _validate_not_none('blob_name', blob_name) 2082 _validate_not_none('stream', stream) 2083 2084 if end_range is not None: 2085 _validate_not_none("start_range", start_range) 2086 2087 # the stream must be seekable if parallel download is required 2088 if max_connections > 1: 2089 if sys.version_info >= (3,) and not stream.seekable(): 2090 raise ValueError(_ERROR_PARALLEL_NOT_SEEKABLE) 2091 2092 try: 2093 stream.seek(stream.tell()) 2094 except (NotImplementedError, AttributeError): 2095 raise ValueError(_ERROR_PARALLEL_NOT_SEEKABLE) 2096 2097 # The service only provides transactional MD5s for chunks under 4MB. 2098 # If validate_content is on, get only self.MAX_CHUNK_GET_SIZE for the first 2099 # chunk so a transactional MD5 can be retrieved. 2100 first_get_size = self.MAX_SINGLE_GET_SIZE if not validate_content else self.MAX_CHUNK_GET_SIZE 2101 2102 initial_request_start = start_range if start_range is not None else 0 2103 2104 if end_range is not None and end_range - start_range < first_get_size: 2105 initial_request_end = end_range 2106 else: 2107 initial_request_end = initial_request_start + first_get_size - 1 2108 2109 # Send a context object to make sure we always retry to the initial location 2110 operation_context = _OperationContext(location_lock=True) 2111 try: 2112 blob = self._get_blob(container_name, 2113 blob_name, 2114 snapshot, 2115 start_range=initial_request_start, 2116 end_range=initial_request_end, 2117 validate_content=validate_content, 2118 lease_id=lease_id, 2119 if_modified_since=if_modified_since, 2120 if_unmodified_since=if_unmodified_since, 2121 if_match=if_match, 2122 if_none_match=if_none_match, 2123 timeout=timeout, 2124 _context=operation_context) 2125 2126 # Parse the total blob size and adjust the download size if ranges 2127 # were specified 2128 blob_size = _parse_length_from_content_range(blob.properties.content_range) 2129 if end_range is not None: 2130 # Use the end_range unless it is over the end of the blob 2131 download_size = min(blob_size, end_range - start_range + 1) 2132 elif start_range is not None: 2133 download_size = blob_size - start_range 2134 else: 2135 download_size = blob_size 2136 except AzureHttpError as ex: 2137 if start_range is None and ex.status_code == 416: 2138 # Get range will fail on an empty blob. If the user did not 2139 # request a range, do a regular get request in order to get 2140 # any properties. 2141 blob = self._get_blob(container_name, 2142 blob_name, 2143 snapshot, 2144 validate_content=validate_content, 2145 lease_id=lease_id, 2146 if_modified_since=if_modified_since, 2147 if_unmodified_since=if_unmodified_since, 2148 if_match=if_match, 2149 if_none_match=if_none_match, 2150 timeout=timeout, 2151 _context=operation_context) 2152 2153 # Set the download size to empty 2154 download_size = 0 2155 else: 2156 raise ex 2157 2158 # Mark the first progress chunk. If the blob is small or this is a single 2159 # shot download, this is the only call 2160 if progress_callback: 2161 progress_callback(blob.properties.content_length, download_size) 2162 2163 # Write the content to the user stream 2164 # Clear blob content since output has been written to user stream 2165 if blob.content is not None: 2166 stream.write(blob.content) 2167 blob.content = None 2168 2169 # If the blob is small, the download is complete at this point. 2170 # If blob size is large, download the rest of the blob in chunks. 2171 if blob.properties.content_length != download_size: 2172 # Lock on the etag. This can be overriden by the user by specifying '*' 2173 if_match = if_match if if_match is not None else blob.properties.etag 2174 2175 end_blob = blob_size 2176 if end_range is not None: 2177 # Use the end_range unless it is over the end of the blob 2178 end_blob = min(blob_size, end_range + 1) 2179 2180 _download_blob_chunks( 2181 self, 2182 container_name, 2183 blob_name, 2184 snapshot, 2185 download_size, 2186 self.MAX_CHUNK_GET_SIZE, 2187 first_get_size, 2188 initial_request_end + 1, # start where the first download ended 2189 end_blob, 2190 stream, 2191 max_connections, 2192 progress_callback, 2193 validate_content, 2194 lease_id, 2195 if_modified_since, 2196 if_unmodified_since, 2197 if_match, 2198 if_none_match, 2199 timeout, 2200 operation_context 2201 ) 2202 2203 # Set the content length to the download size instead of the size of 2204 # the last range 2205 blob.properties.content_length = download_size 2206 2207 # Overwrite the content range to the user requested range 2208 blob.properties.content_range = 'bytes {0}-{1}/{2}'.format(start_range, end_range, blob_size) 2209 2210 # Overwrite the content MD5 as it is the MD5 for the last range instead 2211 # of the stored MD5 2212 # TODO: Set to the stored MD5 when the service returns this 2213 blob.properties.content_md5 = None 2214 2215 return blob 2216 2217 def get_blob_to_bytes( 2218 self, container_name, blob_name, snapshot=None, 2219 start_range=None, end_range=None, validate_content=False, 2220 progress_callback=None, max_connections=2, lease_id=None, 2221 if_modified_since=None, if_unmodified_since=None, if_match=None, 2222 if_none_match=None, timeout=None): 2223 ''' 2224 Downloads a blob as an array of bytes, with automatic chunking and 2225 progress notifications. Returns an instance of :class:`~azure.storage.blob.models.Blob` with 2226 properties, metadata, and content. 2227 2228 :param str container_name: 2229 Name of existing container. 2230 :param str blob_name: 2231 Name of existing blob. 2232 :param str snapshot: 2233 The snapshot parameter is an opaque DateTime value that, 2234 when present, specifies the blob snapshot to retrieve. 2235 :param int start_range: 2236 Start of byte range to use for downloading a section of the blob. 2237 If no end_range is given, all bytes after the start_range will be downloaded. 2238 The start_range and end_range params are inclusive. 2239 Ex: start_range=0, end_range=511 will download first 512 bytes of blob. 2240 :param int end_range: 2241 End of byte range to use for downloading a section of the blob. 2242 If end_range is given, start_range must be provided. 2243 The start_range and end_range params are inclusive. 2244 Ex: start_range=0, end_range=511 will download first 512 bytes of blob. 2245 :param bool validate_content: 2246 If set to true, validates an MD5 hash for each retrieved portion of 2247 the blob. This is primarily valuable for detecting bitflips on the wire 2248 if using http instead of https as https (the default) will already 2249 validate. Note that the service will only return transactional MD5s 2250 for chunks 4MB or less so the first get request will be of size 2251 self.MAX_CHUNK_GET_SIZE instead of self.MAX_SINGLE_GET_SIZE. If 2252 self.MAX_CHUNK_GET_SIZE was set to greater than 4MB an error will be 2253 thrown. As computing the MD5 takes processing time and more requests 2254 will need to be done due to the reduced chunk size there may be some 2255 increase in latency. 2256 :param progress_callback: 2257 Callback for progress with signature function(current, total) 2258 where current is the number of bytes transfered so far, and total is 2259 the size of the blob if known. 2260 :type progress_callback: func(current, total) 2261 :param int max_connections: 2262 If set to 2 or greater, an initial get will be done for the first 2263 self.MAX_SINGLE_GET_SIZE bytes of the blob. If this is the entire blob, 2264 the method returns at this point. If it is not, it will download the 2265 remaining data parallel using the number of threads equal to 2266 max_connections. Each chunk will be of size self.MAX_CHUNK_GET_SIZE. 2267 If set to 1, a single large get request will be done. This is not 2268 generally recommended but available if very few threads should be 2269 used, network requests are very expensive, or a non-seekable stream 2270 prevents parallel download. This may also be useful if many blobs are 2271 expected to be empty as an extra request is required for empty blobs 2272 if max_connections is greater than 1. 2273 :param str lease_id: 2274 Required if the blob has an active lease. 2275 :param datetime if_modified_since: 2276 A DateTime value. Azure expects the date value passed in to be UTC. 2277 If timezone is included, any non-UTC datetimes will be converted to UTC. 2278 If a date is passed in without timezone info, it is assumed to be UTC. 2279 Specify this header to perform the operation only 2280 if the resource has been modified since the specified time. 2281 :param datetime if_unmodified_since: 2282 A DateTime value. Azure expects the date value passed in to be UTC. 2283 If timezone is included, any non-UTC datetimes will be converted to UTC. 2284 If a date is passed in without timezone info, it is assumed to be UTC. 2285 Specify this header to perform the operation only if 2286 the resource has not been modified since the specified date/time. 2287 :param str if_match: 2288 An ETag value, or the wildcard character (*). Specify this header to perform 2289 the operation only if the resource's ETag matches the value specified. 2290 :param str if_none_match: 2291 An ETag value, or the wildcard character (*). Specify this header 2292 to perform the operation only if the resource's ETag does not match 2293 the value specified. Specify the wildcard character (*) to perform 2294 the operation only if the resource does not exist, and fail the 2295 operation if it does exist. 2296 :param int timeout: 2297 The timeout parameter is expressed in seconds. This method may make 2298 multiple calls to the Azure service and the timeout will apply to 2299 each call individually. 2300 :return: A Blob with properties and metadata. If max_connections is greater 2301 than 1, the content_md5 (if set on the blob) will not be returned. If you 2302 require this value, either use get_blob_properties or set max_connections 2303 to 1. 2304 :rtype: :class:`~azure.storage.blob.models.Blob` 2305 ''' 2306 _validate_not_none('container_name', container_name) 2307 _validate_not_none('blob_name', blob_name) 2308 2309 stream = BytesIO() 2310 blob = self.get_blob_to_stream( 2311 container_name, 2312 blob_name, 2313 stream, 2314 snapshot, 2315 start_range, 2316 end_range, 2317 validate_content, 2318 progress_callback, 2319 max_connections, 2320 lease_id, 2321 if_modified_since, 2322 if_unmodified_since, 2323 if_match, 2324 if_none_match, 2325 timeout) 2326 2327 blob.content = stream.getvalue() 2328 return blob 2329 2330 def get_blob_to_text( 2331 self, container_name, blob_name, encoding='utf-8', snapshot=None, 2332 start_range=None, end_range=None, validate_content=False, 2333 progress_callback=None, max_connections=2, lease_id=None, 2334 if_modified_since=None, if_unmodified_since=None, if_match=None, 2335 if_none_match=None, timeout=None): 2336 ''' 2337 Downloads a blob as unicode text, with automatic chunking and progress 2338 notifications. Returns an instance of :class:`~azure.storage.blob.models.Blob` with 2339 properties, metadata, and content. 2340 2341 :param str container_name: 2342 Name of existing container. 2343 :param str blob_name: 2344 Name of existing blob. 2345 :param str encoding: 2346 Python encoding to use when decoding the blob data. 2347 :param str snapshot: 2348 The snapshot parameter is an opaque DateTime value that, 2349 when present, specifies the blob snapshot to retrieve. 2350 :param int start_range: 2351 Start of byte range to use for downloading a section of the blob. 2352 If no end_range is given, all bytes after the start_range will be downloaded. 2353 The start_range and end_range params are inclusive. 2354 Ex: start_range=0, end_range=511 will download first 512 bytes of blob. 2355 :param int end_range: 2356 End of byte range to use for downloading a section of the blob. 2357 If end_range is given, start_range must be provided. 2358 The start_range and end_range params are inclusive. 2359 Ex: start_range=0, end_range=511 will download first 512 bytes of blob. 2360 :param bool validate_content: 2361 If set to true, validates an MD5 hash for each retrieved portion of 2362 the blob. This is primarily valuable for detecting bitflips on the wire 2363 if using http instead of https as https (the default) will already 2364 validate. Note that the service will only return transactional MD5s 2365 for chunks 4MB or less so the first get request will be of size 2366 self.MAX_CHUNK_GET_SIZE instead of self.MAX_SINGLE_GET_SIZE. If 2367 self.MAX_CHUNK_GET_SIZE was set to greater than 4MB an error will be 2368 thrown. As computing the MD5 takes processing time and more requests 2369 will need to be done due to the reduced chunk size there may be some 2370 increase in latency. 2371 :param progress_callback: 2372 Callback for progress with signature function(current, total) 2373 where current is the number of bytes transfered so far, and total is 2374 the size of the blob if known. 2375 :type progress_callback: func(current, total) 2376 :param int max_connections: 2377 If set to 2 or greater, an initial get will be done for the first 2378 self.MAX_SINGLE_GET_SIZE bytes of the blob. If this is the entire blob, 2379 the method returns at this point. If it is not, it will download the 2380 remaining data parallel using the number of threads equal to 2381 max_connections. Each chunk will be of size self.MAX_CHUNK_GET_SIZE. 2382 If set to 1, a single large get request will be done. This is not 2383 generally recommended but available if very few threads should be 2384 used, network requests are very expensive, or a non-seekable stream 2385 prevents parallel download. This may also be useful if many blobs are 2386 expected to be empty as an extra request is required for empty blobs 2387 if max_connections is greater than 1. 2388 :param str lease_id: 2389 Required if the blob has an active lease. 2390 :param datetime if_modified_since: 2391 A DateTime value. Azure expects the date value passed in to be UTC. 2392 If timezone is included, any non-UTC datetimes will be converted to UTC. 2393 If a date is passed in without timezone info, it is assumed to be UTC. 2394 Specify this header to perform the operation only 2395 if the resource has been modified since the specified time. 2396 :param datetime if_unmodified_since: 2397 A DateTime value. Azure expects the date value passed in to be UTC. 2398 If timezone is included, any non-UTC datetimes will be converted to UTC. 2399 If a date is passed in without timezone info, it is assumed to be UTC. 2400 Specify this header to perform the operation only if 2401 the resource has not been modified since the specified date/time. 2402 :param str if_match: 2403 An ETag value, or the wildcard character (*). Specify this header to perform 2404 the operation only if the resource's ETag matches the value specified. 2405 :param str if_none_match: 2406 An ETag value, or the wildcard character (*). Specify this header 2407 to perform the operation only if the resource's ETag does not match 2408 the value specified. Specify the wildcard character (*) to perform 2409 the operation only if the resource does not exist, and fail the 2410 operation if it does exist. 2411 :param int timeout: 2412 The timeout parameter is expressed in seconds. This method may make 2413 multiple calls to the Azure service and the timeout will apply to 2414 each call individually. 2415 :return: A Blob with properties and metadata. If max_connections is greater 2416 than 1, the content_md5 (if set on the blob) will not be returned. If you 2417 require this value, either use get_blob_properties or set max_connections 2418 to 1. 2419 :rtype: :class:`~azure.storage.blob.models.Blob` 2420 ''' 2421 _validate_not_none('container_name', container_name) 2422 _validate_not_none('blob_name', blob_name) 2423 _validate_not_none('encoding', encoding) 2424 2425 blob = self.get_blob_to_bytes(container_name, 2426 blob_name, 2427 snapshot, 2428 start_range, 2429 end_range, 2430 validate_content, 2431 progress_callback, 2432 max_connections, 2433 lease_id, 2434 if_modified_since, 2435 if_unmodified_since, 2436 if_match, 2437 if_none_match, 2438 timeout) 2439 blob.content = blob.content.decode(encoding) 2440 return blob 2441 2442 def get_blob_metadata( 2443 self, container_name, blob_name, snapshot=None, lease_id=None, 2444 if_modified_since=None, if_unmodified_since=None, if_match=None, 2445 if_none_match=None, timeout=None): 2446 ''' 2447 Returns all user-defined metadata for the specified blob or snapshot. 2448 2449 :param str container_name: 2450 Name of existing container. 2451 :param str blob_name: 2452 Name of existing blob. 2453 :param str snapshot: 2454 The snapshot parameter is an opaque value that, 2455 when present, specifies the blob snapshot to retrieve. 2456 :param str lease_id: 2457 Required if the blob has an active lease. 2458 :param datetime if_modified_since: 2459 A DateTime value. Azure expects the date value passed in to be UTC. 2460 If timezone is included, any non-UTC datetimes will be converted to UTC. 2461 If a date is passed in without timezone info, it is assumed to be UTC. 2462 Specify this header to perform the operation only 2463 if the resource has been modified since the specified time. 2464 :param datetime if_unmodified_since: 2465 A DateTime value. Azure expects the date value passed in to be UTC. 2466 If timezone is included, any non-UTC datetimes will be converted to UTC. 2467 If a date is passed in without timezone info, it is assumed to be UTC. 2468 Specify this header to perform the operation only if 2469 the resource has not been modified since the specified date/time. 2470 :param str if_match: 2471 An ETag value, or the wildcard character (*). Specify this header to perform 2472 the operation only if the resource's ETag matches the value specified. 2473 :param str if_none_match: 2474 An ETag value, or the wildcard character (*). Specify this header 2475 to perform the operation only if the resource's ETag does not match 2476 the value specified. Specify the wildcard character (*) to perform 2477 the operation only if the resource does not exist, and fail the 2478 operation if it does exist. 2479 :param int timeout: 2480 The timeout parameter is expressed in seconds. 2481 :return: 2482 A dictionary representing the blob metadata name, value pairs. 2483 :rtype: dict(str, str) 2484 ''' 2485 _validate_not_none('container_name', container_name) 2486 _validate_not_none('blob_name', blob_name) 2487 request = HTTPRequest() 2488 request.method = 'GET' 2489 request.host_locations = self._get_host_locations(secondary=True) 2490 request.path = _get_path(container_name, blob_name) 2491 request.query = { 2492 'snapshot': _to_str(snapshot), 2493 'comp': 'metadata', 2494 'timeout': _int_to_str(timeout), 2495 } 2496 request.headers = { 2497 'x-ms-lease-id': _to_str(lease_id), 2498 'If-Modified-Since': _datetime_to_utc_string(if_modified_since), 2499 'If-Unmodified-Since': _datetime_to_utc_string(if_unmodified_since), 2500 'If-Match': _to_str(if_match), 2501 'If-None-Match': _to_str(if_none_match), 2502 } 2503 2504 return self._perform_request(request, _parse_metadata) 2505 2506 def set_blob_metadata(self, container_name, blob_name, 2507 metadata=None, lease_id=None, 2508 if_modified_since=None, if_unmodified_since=None, 2509 if_match=None, if_none_match=None, timeout=None): 2510 ''' 2511 Sets user-defined metadata for the specified blob as one or more 2512 name-value pairs. 2513 2514 :param str container_name: 2515 Name of existing container. 2516 :param str blob_name: 2517 Name of existing blob. 2518 :param metadata: 2519 Dict containing name and value pairs. Each call to this operation 2520 replaces all existing metadata attached to the blob. To remove all 2521 metadata from the blob, call this operation with no metadata headers. 2522 :type metadata: dict(str, str) 2523 :param str lease_id: 2524 Required if the blob has an active lease. 2525 :param datetime if_modified_since: 2526 A DateTime value. Azure expects the date value passed in to be UTC. 2527 If timezone is included, any non-UTC datetimes will be converted to UTC. 2528 If a date is passed in without timezone info, it is assumed to be UTC. 2529 Specify this header to perform the operation only 2530 if the resource has been modified since the specified time. 2531 :param datetime if_unmodified_since: 2532 A DateTime value. Azure expects the date value passed in to be UTC. 2533 If timezone is included, any non-UTC datetimes will be converted to UTC. 2534 If a date is passed in without timezone info, it is assumed to be UTC. 2535 Specify this header to perform the operation only if 2536 the resource has not been modified since the specified date/time. 2537 :param str if_match: 2538 An ETag value, or the wildcard character (*). Specify this header to perform 2539 the operation only if the resource's ETag matches the value specified. 2540 :param str if_none_match: 2541 An ETag value, or the wildcard character (*). Specify this header 2542 to perform the operation only if the resource's ETag does not match 2543 the value specified. Specify the wildcard character (*) to perform 2544 the operation only if the resource does not exist, and fail the 2545 operation if it does exist. 2546 :param int timeout: 2547 The timeout parameter is expressed in seconds. 2548 :return: ETag and last modified properties for the updated Blob 2549 :rtype: :class:`~azure.storage.blob.models.ResourceProperties` 2550 ''' 2551 _validate_not_none('container_name', container_name) 2552 _validate_not_none('blob_name', blob_name) 2553 request = HTTPRequest() 2554 request.method = 'PUT' 2555 request.host_locations = self._get_host_locations() 2556 request.path = _get_path(container_name, blob_name) 2557 request.query = { 2558 'comp': 'metadata', 2559 'timeout': _int_to_str(timeout), 2560 } 2561 request.headers = { 2562 'If-Modified-Since': _datetime_to_utc_string(if_modified_since), 2563 'If-Unmodified-Since': _datetime_to_utc_string(if_unmodified_since), 2564 'If-Match': _to_str(if_match), 2565 'If-None-Match': _to_str(if_none_match), 2566 'x-ms-lease-id': _to_str(lease_id), 2567 } 2568 _add_metadata_headers(metadata, request) 2569 2570 return self._perform_request(request, _parse_base_properties) 2571 2572 def _lease_blob_impl(self, container_name, blob_name, 2573 lease_action, lease_id, 2574 lease_duration, lease_break_period, 2575 proposed_lease_id, if_modified_since, 2576 if_unmodified_since, if_match, if_none_match, timeout=None): 2577 ''' 2578 Establishes and manages a lease on a blob for write and delete operations. 2579 The Lease Blob operation can be called in one of five modes: 2580 Acquire, to request a new lease. 2581 Renew, to renew an existing lease. 2582 Change, to change the ID of an existing lease. 2583 Release, to free the lease if it is no longer needed so that another 2584 client may immediately acquire a lease against the blob. 2585 Break, to end the lease but ensure that another client cannot acquire 2586 a new lease until the current lease period has expired. 2587 2588 :param str container_name: 2589 Name of existing container. 2590 :param str blob_name: 2591 Name of existing blob. 2592 :param str lease_action: 2593 Possible _LeaseActions acquire|renew|release|break|change 2594 :param str lease_id: 2595 Required if the blob has an active lease. 2596 :param int lease_duration: 2597 Specifies the duration of the lease, in seconds, or negative one 2598 (-1) for a lease that never expires. A non-infinite lease can be 2599 between 15 and 60 seconds. A lease duration cannot be changed 2600 using renew or change. 2601 :param int lease_break_period: 2602 For a break operation, this is the proposed duration of 2603 seconds that the lease should continue before it is broken, between 2604 0 and 60 seconds. This break period is only used if it is shorter 2605 than the time remaining on the lease. If longer, the time remaining 2606 on the lease is used. A new lease will not be available before the 2607 break period has expired, but the lease may be held for longer than 2608 the break period. If this header does not appear with a break 2609 operation, a fixed-duration lease breaks after the remaining lease 2610 period elapses, and an infinite lease breaks immediately. 2611 :param str proposed_lease_id: 2612 Optional for acquire, required for change. Proposed lease ID, in a 2613 GUID string format. The Blob service returns 400 (Invalid request) 2614 if the proposed lease ID is not in the correct format. 2615 :param datetime if_modified_since: 2616 A DateTime value. Azure expects the date value passed in to be UTC. 2617 If timezone is included, any non-UTC datetimes will be converted to UTC. 2618 If a date is passed in without timezone info, it is assumed to be UTC. 2619 Specify this header to perform the operation only 2620 if the resource has been modified since the specified time. 2621 :param datetime if_unmodified_since: 2622 A DateTime value. Azure expects the date value passed in to be UTC. 2623 If timezone is included, any non-UTC datetimes will be converted to UTC. 2624 If a date is passed in without timezone info, it is assumed to be UTC. 2625 Specify this header to perform the operation only if 2626 the resource has not been modified since the specified date/time. 2627 :param str if_match: 2628 An ETag value, or the wildcard character (*). Specify this header to perform 2629 the operation only if the resource's ETag matches the value specified. 2630 :param str if_none_match: 2631 An ETag value, or the wildcard character (*). Specify this header 2632 to perform the operation only if the resource's ETag does not match 2633 the value specified. Specify the wildcard character (*) to perform 2634 the operation only if the resource does not exist, and fail the 2635 operation if it does exist. 2636 :param int timeout: 2637 The timeout parameter is expressed in seconds. 2638 :return: 2639 Response headers returned from the service call. 2640 :rtype: dict(str, str) 2641 ''' 2642 _validate_not_none('container_name', container_name) 2643 _validate_not_none('blob_name', blob_name) 2644 _validate_not_none('lease_action', lease_action) 2645 request = HTTPRequest() 2646 request.method = 'PUT' 2647 request.host_locations = self._get_host_locations() 2648 request.path = _get_path(container_name, blob_name) 2649 request.query = { 2650 'comp': 'lease', 2651 'timeout': _int_to_str(timeout), 2652 } 2653 request.headers = { 2654 'x-ms-lease-id': _to_str(lease_id), 2655 'x-ms-lease-action': _to_str(lease_action), 2656 'x-ms-lease-duration': _to_str(lease_duration), 2657 'x-ms-lease-break-period': _to_str(lease_break_period), 2658 'x-ms-proposed-lease-id': _to_str(proposed_lease_id), 2659 'If-Modified-Since': _datetime_to_utc_string(if_modified_since), 2660 'If-Unmodified-Since': _datetime_to_utc_string(if_unmodified_since), 2661 'If-Match': _to_str(if_match), 2662 'If-None-Match': _to_str(if_none_match), 2663 } 2664 2665 return self._perform_request(request, _parse_lease) 2666 2667 def acquire_blob_lease(self, container_name, blob_name, 2668 lease_duration=-1, 2669 proposed_lease_id=None, 2670 if_modified_since=None, 2671 if_unmodified_since=None, 2672 if_match=None, 2673 if_none_match=None, timeout=None): 2674 ''' 2675 Requests a new lease. If the blob does not have an active lease, the Blob 2676 service creates a lease on the blob and returns a new lease ID. 2677 2678 :param str container_name: 2679 Name of existing container. 2680 :param str blob_name: 2681 Name of existing blob. 2682 :param int lease_duration: 2683 Specifies the duration of the lease, in seconds, or negative one 2684 (-1) for a lease that never expires. A non-infinite lease can be 2685 between 15 and 60 seconds. A lease duration cannot be changed 2686 using renew or change. Default is -1 (infinite lease). 2687 :param str proposed_lease_id: 2688 Proposed lease ID, in a GUID string format. The Blob service 2689 returns 400 (Invalid request) if the proposed lease ID is not 2690 in the correct format. 2691 :param datetime if_modified_since: 2692 A DateTime value. Azure expects the date value passed in to be UTC. 2693 If timezone is included, any non-UTC datetimes will be converted to UTC. 2694 If a date is passed in without timezone info, it is assumed to be UTC. 2695 Specify this header to perform the operation only 2696 if the resource has been modified since the specified time. 2697 :param datetime if_unmodified_since: 2698 A DateTime value. Azure expects the date value passed in to be UTC. 2699 If timezone is included, any non-UTC datetimes will be converted to UTC. 2700 If a date is passed in without timezone info, it is assumed to be UTC. 2701 Specify this header to perform the operation only if 2702 the resource has not been modified since the specified date/time. 2703 :param str if_match: 2704 An ETag value, or the wildcard character (*). Specify this header to perform 2705 the operation only if the resource's ETag matches the value specified. 2706 :param str if_none_match: 2707 An ETag value, or the wildcard character (*). Specify this header 2708 to perform the operation only if the resource's ETag does not match 2709 the value specified. Specify the wildcard character (*) to perform 2710 the operation only if the resource does not exist, and fail the 2711 operation if it does exist. 2712 :param int timeout: 2713 The timeout parameter is expressed in seconds. 2714 :return: the lease ID of the newly created lease. 2715 :return: str 2716 ''' 2717 _validate_not_none('lease_duration', lease_duration) 2718 2719 if lease_duration != -1 and \ 2720 (lease_duration < 15 or lease_duration > 60): 2721 raise ValueError(_ERROR_INVALID_LEASE_DURATION) 2722 lease = self._lease_blob_impl(container_name, 2723 blob_name, 2724 _LeaseActions.Acquire, 2725 None, # lease_id 2726 lease_duration, 2727 None, # lease_break_period 2728 proposed_lease_id, 2729 if_modified_since, 2730 if_unmodified_since, 2731 if_match, 2732 if_none_match, 2733 timeout) 2734 return lease['id'] 2735 2736 def renew_blob_lease(self, container_name, blob_name, 2737 lease_id, if_modified_since=None, 2738 if_unmodified_since=None, if_match=None, 2739 if_none_match=None, timeout=None): 2740 ''' 2741 Renews the lease. The lease can be renewed if the lease ID specified on 2742 the request matches that associated with the blob. Note that the lease may 2743 be renewed even if it has expired as long as the blob has not been modified 2744 or leased again since the expiration of that lease. When you renew a lease, 2745 the lease duration clock resets. 2746 2747 :param str container_name: 2748 Name of existing container. 2749 :param str blob_name: 2750 Name of existing blob. 2751 :param str lease_id: 2752 Lease ID for active lease. 2753 :param datetime if_modified_since: 2754 A DateTime value. Azure expects the date value passed in to be UTC. 2755 If timezone is included, any non-UTC datetimes will be converted to UTC. 2756 If a date is passed in without timezone info, it is assumed to be UTC. 2757 Specify this header to perform the operation only 2758 if the resource has been modified since the specified time. 2759 :param datetime if_unmodified_since: 2760 A DateTime value. Azure expects the date value passed in to be UTC. 2761 If timezone is included, any non-UTC datetimes will be converted to UTC. 2762 If a date is passed in without timezone info, it is assumed to be UTC. 2763 Specify this header to perform the operation only if 2764 the resource has not been modified since the specified date/time. 2765 :param str if_match: 2766 An ETag value, or the wildcard character (*). Specify this header to perform 2767 the operation only if the resource's ETag matches the value specified. 2768 :param str if_none_match: 2769 An ETag value, or the wildcard character (*). Specify this header 2770 to perform the operation only if the resource's ETag does not match 2771 the value specified. Specify the wildcard character (*) to perform 2772 the operation only if the resource does not exist, and fail the 2773 operation if it does exist. 2774 :param int timeout: 2775 The timeout parameter is expressed in seconds. 2776 :return: the lease ID of the renewed lease. 2777 :return: str 2778 ''' 2779 _validate_not_none('lease_id', lease_id) 2780 2781 lease = self._lease_blob_impl(container_name, 2782 blob_name, 2783 _LeaseActions.Renew, 2784 lease_id, 2785 None, # lease_duration 2786 None, # lease_break_period 2787 None, # proposed_lease_id 2788 if_modified_since, 2789 if_unmodified_since, 2790 if_match, 2791 if_none_match, 2792 timeout) 2793 return lease['id'] 2794 2795 def release_blob_lease(self, container_name, blob_name, 2796 lease_id, if_modified_since=None, 2797 if_unmodified_since=None, if_match=None, 2798 if_none_match=None, timeout=None): 2799 ''' 2800 Releases the lease. The lease may be released if the lease ID specified on the 2801 request matches that associated with the blob. Releasing the lease allows another 2802 client to immediately acquire the lease for the blob as soon as the release is complete. 2803 2804 :param str container_name: 2805 Name of existing container. 2806 :param str blob_name: 2807 Name of existing blob. 2808 :param str lease_id: 2809 Lease ID for active lease. 2810 :param datetime if_modified_since: 2811 A DateTime value. Azure expects the date value passed in to be UTC. 2812 If timezone is included, any non-UTC datetimes will be converted to UTC. 2813 If a date is passed in without timezone info, it is assumed to be UTC. 2814 Specify this header to perform the operation only 2815 if the resource has been modified since the specified time. 2816 :param datetime if_unmodified_since: 2817 A DateTime value. Azure expects the date value passed in to be UTC. 2818 If timezone is included, any non-UTC datetimes will be converted to UTC. 2819 If a date is passed in without timezone info, it is assumed to be UTC. 2820 Specify this header to perform the operation only if 2821 the resource has not been modified since the specified date/time. 2822 :param str if_match: 2823 An ETag value, or the wildcard character (*). Specify this header to perform 2824 the operation only if the resource's ETag matches the value specified. 2825 :param str if_none_match: 2826 An ETag value, or the wildcard character (*). Specify this header 2827 to perform the operation only if the resource's ETag does not match 2828 the value specified. Specify the wildcard character (*) to perform 2829 the operation only if the resource does not exist, and fail the 2830 operation if it does exist. 2831 :param int timeout: 2832 The timeout parameter is expressed in seconds. 2833 ''' 2834 _validate_not_none('lease_id', lease_id) 2835 2836 self._lease_blob_impl(container_name, 2837 blob_name, 2838 _LeaseActions.Release, 2839 lease_id, 2840 None, # lease_duration 2841 None, # lease_break_period 2842 None, # proposed_lease_id 2843 if_modified_since, 2844 if_unmodified_since, 2845 if_match, 2846 if_none_match, 2847 timeout) 2848 2849 def break_blob_lease(self, container_name, blob_name, 2850 lease_break_period=None, 2851 if_modified_since=None, 2852 if_unmodified_since=None, 2853 if_match=None, 2854 if_none_match=None, timeout=None): 2855 ''' 2856 Breaks the lease, if the blob has an active lease. Once a lease is broken, 2857 it cannot be renewed. Any authorized request can break the lease; the request 2858 is not required to specify a matching lease ID. When a lease is broken, 2859 the lease break period is allowed to elapse, during which time no lease operation 2860 except break and release can be performed on the blob. When a lease is successfully 2861 broken, the response indicates the interval in seconds until a new lease can be acquired. 2862 2863 A lease that has been broken can also be released, in which case another client may 2864 immediately acquire the lease on the blob. 2865 2866 :param str container_name: 2867 Name of existing container. 2868 :param str blob_name: 2869 Name of existing blob. 2870 :param int lease_break_period: 2871 For a break operation, this is the proposed duration of 2872 seconds that the lease should continue before it is broken, between 2873 0 and 60 seconds. This break period is only used if it is shorter 2874 than the time remaining on the lease. If longer, the time remaining 2875 on the lease is used. A new lease will not be available before the 2876 break period has expired, but the lease may be held for longer than 2877 the break period. If this header does not appear with a break 2878 operation, a fixed-duration lease breaks after the remaining lease 2879 period elapses, and an infinite lease breaks immediately. 2880 :param datetime if_modified_since: 2881 A DateTime value. Azure expects the date value passed in to be UTC. 2882 If timezone is included, any non-UTC datetimes will be converted to UTC. 2883 If a date is passed in without timezone info, it is assumed to be UTC. 2884 Specify this header to perform the operation only 2885 if the resource has been modified since the specified time. 2886 :param datetime if_unmodified_since: 2887 A DateTime value. Azure expects the date value passed in to be UTC. 2888 If timezone is included, any non-UTC datetimes will be converted to UTC. 2889 If a date is passed in without timezone info, it is assumed to be UTC. 2890 Specify this header to perform the operation only if 2891 the resource has not been modified since the specified date/time. 2892 :param str if_match: 2893 An ETag value, or the wildcard character (*). Specify this header to perform 2894 the operation only if the resource's ETag matches the value specified. 2895 :param str if_none_match: 2896 An ETag value, or the wildcard character (*). Specify this header 2897 to perform the operation only if the resource's ETag does not match 2898 the value specified. Specify the wildcard character (*) to perform 2899 the operation only if the resource does not exist, and fail the 2900 operation if it does exist. 2901 :param int timeout: 2902 The timeout parameter is expressed in seconds. 2903 :return: Approximate time remaining in the lease period, in seconds. 2904 :return: int 2905 ''' 2906 if (lease_break_period is not None) and (lease_break_period < 0 or lease_break_period > 60): 2907 raise ValueError(_ERROR_INVALID_LEASE_BREAK_PERIOD) 2908 2909 lease = self._lease_blob_impl(container_name, 2910 blob_name, 2911 _LeaseActions.Break, 2912 None, # lease_id 2913 None, # lease_duration 2914 lease_break_period, 2915 None, # proposed_lease_id 2916 if_modified_since, 2917 if_unmodified_since, 2918 if_match, 2919 if_none_match, 2920 timeout) 2921 return lease['time'] 2922 2923 def change_blob_lease(self, container_name, blob_name, 2924 lease_id, 2925 proposed_lease_id, 2926 if_modified_since=None, 2927 if_unmodified_since=None, 2928 if_match=None, 2929 if_none_match=None, timeout=None): 2930 ''' 2931 Changes the lease ID of an active lease. A change must include the current 2932 lease ID and a new lease ID. 2933 2934 :param str container_name: 2935 Name of existing container. 2936 :param str blob_name: 2937 Name of existing blob. 2938 :param str lease_id: 2939 Required if the blob has an active lease. 2940 :param str proposed_lease_id: 2941 Proposed lease ID, in a GUID string format. The Blob service returns 2942 400 (Invalid request) if the proposed lease ID is not in the correct format. 2943 :param datetime if_modified_since: 2944 A DateTime value. Azure expects the date value passed in to be UTC. 2945 If timezone is included, any non-UTC datetimes will be converted to UTC. 2946 If a date is passed in without timezone info, it is assumed to be UTC. 2947 Specify this header to perform the operation only 2948 if the resource has been modified since the specified time. 2949 :param datetime if_unmodified_since: 2950 A DateTime value. Azure expects the date value passed in to be UTC. 2951 If timezone is included, any non-UTC datetimes will be converted to UTC. 2952 If a date is passed in without timezone info, it is assumed to be UTC. 2953 Specify this header to perform the operation only if 2954 the resource has not been modified since the specified date/time. 2955 :param str if_match: 2956 An ETag value, or the wildcard character (*). Specify this header to perform 2957 the operation only if the resource's ETag matches the value specified. 2958 :param str if_none_match: 2959 An ETag value, or the wildcard character (*). Specify this header 2960 to perform the operation only if the resource's ETag does not match 2961 the value specified. Specify the wildcard character (*) to perform 2962 the operation only if the resource does not exist, and fail the 2963 operation if it does exist. 2964 :param int timeout: 2965 The timeout parameter is expressed in seconds. 2966 ''' 2967 self._lease_blob_impl(container_name, 2968 blob_name, 2969 _LeaseActions.Change, 2970 lease_id, 2971 None, # lease_duration 2972 None, # lease_break_period 2973 proposed_lease_id, 2974 if_modified_since, 2975 if_unmodified_since, 2976 if_match, 2977 if_none_match, 2978 timeout) 2979 2980 def snapshot_blob(self, container_name, blob_name, 2981 metadata=None, if_modified_since=None, 2982 if_unmodified_since=None, if_match=None, 2983 if_none_match=None, lease_id=None, timeout=None): 2984 ''' 2985 Creates a read-only snapshot of a blob. 2986 2987 :param str container_name: 2988 Name of existing container. 2989 :param str blob_name: 2990 Name of existing blob. 2991 :param metadata: 2992 Specifies a user-defined name-value pair associated with the blob. 2993 If no name-value pairs are specified, the operation will copy the 2994 base blob metadata to the snapshot. If one or more name-value pairs 2995 are specified, the snapshot is created with the specified metadata, 2996 and metadata is not copied from the base blob. 2997 :type metadata: dict(str, str) 2998 :param datetime if_modified_since: 2999 A DateTime value. Azure expects the date value passed in to be UTC. 3000 If timezone is included, any non-UTC datetimes will be converted to UTC. 3001 If a date is passed in without timezone info, it is assumed to be UTC. 3002 Specify this header to perform the operation only 3003 if the resource has been modified since the specified time. 3004 :param datetime if_unmodified_since: 3005 A DateTime value. Azure expects the date value passed in to be UTC. 3006 If timezone is included, any non-UTC datetimes will be converted to UTC. 3007 If a date is passed in without timezone info, it is assumed to be UTC. 3008 Specify this header to perform the operation only if 3009 the resource has not been modified since the specified date/time. 3010 :param str if_match: 3011 An ETag value, or the wildcard character (*). Specify this header to perform 3012 the operation only if the resource's ETag matches the value specified. 3013 :param str if_none_match: 3014 An ETag value, or the wildcard character (*). Specify this header 3015 to perform the operation only if the resource's ETag does not match 3016 the value specified. Specify the wildcard character (*) to perform 3017 the operation only if the resource does not exist, and fail the 3018 operation if it does exist. 3019 :param str lease_id: 3020 Required if the blob has an active lease. 3021 :param int timeout: 3022 The timeout parameter is expressed in seconds. 3023 :return: snapshot properties 3024 :rtype: :class:`~azure.storage.blob.models.Blob` 3025 ''' 3026 _validate_not_none('container_name', container_name) 3027 _validate_not_none('blob_name', blob_name) 3028 request = HTTPRequest() 3029 request.method = 'PUT' 3030 request.host_locations = self._get_host_locations() 3031 request.path = _get_path(container_name, blob_name) 3032 request.query = { 3033 'comp': 'snapshot', 3034 'timeout': _int_to_str(timeout), 3035 } 3036 request.headers = { 3037 'If-Modified-Since': _datetime_to_utc_string(if_modified_since), 3038 'If-Unmodified-Since': _datetime_to_utc_string(if_unmodified_since), 3039 'If-Match': _to_str(if_match), 3040 'If-None-Match': _to_str(if_none_match), 3041 'x-ms-lease-id': _to_str(lease_id) 3042 } 3043 _add_metadata_headers(metadata, request) 3044 3045 return self._perform_request(request, _parse_snapshot_blob, [blob_name]) 3046 3047 def copy_blob(self, container_name, blob_name, copy_source, 3048 metadata=None, 3049 source_if_modified_since=None, 3050 source_if_unmodified_since=None, 3051 source_if_match=None, source_if_none_match=None, 3052 destination_if_modified_since=None, 3053 destination_if_unmodified_since=None, 3054 destination_if_match=None, 3055 destination_if_none_match=None, 3056 destination_lease_id=None, 3057 source_lease_id=None, timeout=None): 3058 ''' 3059 Copies a blob asynchronously. This operation returns a copy operation 3060 properties object, including a copy ID you can use to check or abort the 3061 copy operation. The Blob service copies blobs on a best-effort basis. 3062 3063 The source blob for a copy operation may be a block blob, an append blob, 3064 or a page blob. If the destination blob already exists, it must be of the 3065 same blob type as the source blob. Any existing destination blob will be 3066 overwritten. The destination blob cannot be modified while a copy operation 3067 is in progress. 3068 3069 When copying from a page blob, the Blob service creates a destination page 3070 blob of the source blob's length, initially containing all zeroes. Then 3071 the source page ranges are enumerated, and non-empty ranges are copied. 3072 3073 For a block blob or an append blob, the Blob service creates a committed 3074 blob of zero length before returning from this operation. When copying 3075 from a block blob, all committed blocks and their block IDs are copied. 3076 Uncommitted blocks are not copied. At the end of the copy operation, the 3077 destination blob will have the same committed block count as the source. 3078 3079 When copying from an append blob, all committed blocks are copied. At the 3080 end of the copy operation, the destination blob will have the same committed 3081 block count as the source. 3082 3083 For all blob types, you can call get_blob_properties on the destination 3084 blob to check the status of the copy operation. The final blob will be 3085 committed when the copy completes. 3086 3087 :param str container_name: 3088 Name of the destination container. The container must exist. 3089 :param str blob_name: 3090 Name of the destination blob. If the destination blob exists, it will 3091 be overwritten. Otherwise, it will be created. 3092 :param str copy_source: 3093 A URL of up to 2 KB in length that specifies an Azure file or blob. 3094 The value should be URL-encoded as it would appear in a request URI. 3095 If the source is in another account, the source must either be public 3096 or must be authenticated via a shared access signature. If the source 3097 is public, no authentication is required. 3098 Examples: 3099 https://myaccount.blob.core.windows.net/mycontainer/myblob 3100 https://myaccount.blob.core.windows.net/mycontainer/myblob?snapshot=<DateTime> 3101 https://otheraccount.blob.core.windows.net/mycontainer/myblob?sastoken 3102 :param metadata: 3103 Name-value pairs associated with the blob as metadata. If no name-value 3104 pairs are specified, the operation will copy the metadata from the 3105 source blob or file to the destination blob. If one or more name-value 3106 pairs are specified, the destination blob is created with the specified 3107 metadata, and metadata is not copied from the source blob or file. 3108 :type metadata: dict(str, str) 3109 :param datetime source_if_modified_since: 3110 A DateTime value. Azure expects the date value passed in to be UTC. 3111 If timezone is included, any non-UTC datetimes will be converted to UTC. 3112 If a date is passed in without timezone info, it is assumed to be UTC. 3113 Specify this conditional header to copy the blob only if the source 3114 blob has been modified since the specified date/time. 3115 :param datetime source_if_unmodified_since: 3116 A DateTime value. Azure expects the date value passed in to be UTC. 3117 If timezone is included, any non-UTC datetimes will be converted to UTC. 3118 If a date is passed in without timezone info, it is assumed to be UTC. 3119 Specify this conditional header to copy the blob only if the source blob 3120 has not been modified since the specified date/time. 3121 :param ETag source_if_match: 3122 An ETag value, or the wildcard character (*). Specify this conditional 3123 header to copy the source blob only if its ETag matches the value 3124 specified. If the ETag values do not match, the Blob service returns 3125 status code 412 (Precondition Failed). This header cannot be specified 3126 if the source is an Azure File. 3127 :param ETag source_if_none_match: 3128 An ETag value, or the wildcard character (*). Specify this conditional 3129 header to copy the blob only if its ETag does not match the value 3130 specified. If the values are identical, the Blob service returns status 3131 code 412 (Precondition Failed). This header cannot be specified if the 3132 source is an Azure File. 3133 :param datetime destination_if_modified_since: 3134 A DateTime value. Azure expects the date value passed in to be UTC. 3135 If timezone is included, any non-UTC datetimes will be converted to UTC. 3136 If a date is passed in without timezone info, it is assumed to be UTC. 3137 Specify this conditional header to copy the blob only 3138 if the destination blob has been modified since the specified date/time. 3139 If the destination blob has not been modified, the Blob service returns 3140 status code 412 (Precondition Failed). 3141 :param datetime destination_if_unmodified_since: 3142 A DateTime value. Azure expects the date value passed in to be UTC. 3143 If timezone is included, any non-UTC datetimes will be converted to UTC. 3144 If a date is passed in without timezone info, it is assumed to be UTC. 3145 Specify this conditional header to copy the blob only 3146 if the destination blob has not been modified since the specified 3147 date/time. If the destination blob has been modified, the Blob service 3148 returns status code 412 (Precondition Failed). 3149 :param ETag destination_if_match: 3150 An ETag value, or the wildcard character (*). Specify an ETag value for 3151 this conditional header to copy the blob only if the specified ETag value 3152 matches the ETag value for an existing destination blob. If the ETag for 3153 the destination blob does not match the ETag specified for If-Match, the 3154 Blob service returns status code 412 (Precondition Failed). 3155 :param ETag destination_if_none_match: 3156 An ETag value, or the wildcard character (*). Specify an ETag value for 3157 this conditional header to copy the blob only if the specified ETag value 3158 does not match the ETag value for the destination blob. Specify the wildcard 3159 character (*) to perform the operation only if the destination blob does not 3160 exist. If the specified condition isn't met, the Blob service returns status 3161 code 412 (Precondition Failed). 3162 :param str destination_lease_id: 3163 The lease ID specified for this header must match the lease ID of the 3164 destination blob. If the request does not include the lease ID or it is not 3165 valid, the operation fails with status code 412 (Precondition Failed). 3166 :param str source_lease_id: 3167 Specify this to perform the Copy Blob operation only if 3168 the lease ID given matches the active lease ID of the source blob. 3169 :param int timeout: 3170 The timeout parameter is expressed in seconds. 3171 :return: Copy operation properties such as status, source, and ID. 3172 :rtype: :class:`~azure.storage.blob.models.CopyProperties` 3173 ''' 3174 return self._copy_blob(container_name, blob_name, copy_source, 3175 metadata, 3176 None, 3177 source_if_modified_since, source_if_unmodified_since, 3178 source_if_match, source_if_none_match, 3179 destination_if_modified_since, 3180 destination_if_unmodified_since, 3181 destination_if_match, 3182 destination_if_none_match, 3183 destination_lease_id, 3184 source_lease_id, timeout, 3185 False, False) 3186 3187 def _copy_blob(self, container_name, blob_name, copy_source, 3188 metadata=None, 3189 premium_page_blob_tier=None, 3190 source_if_modified_since=None, 3191 source_if_unmodified_since=None, 3192 source_if_match=None, source_if_none_match=None, 3193 destination_if_modified_since=None, 3194 destination_if_unmodified_since=None, 3195 destination_if_match=None, 3196 destination_if_none_match=None, 3197 destination_lease_id=None, 3198 source_lease_id=None, timeout=None, 3199 incremental_copy=False, 3200 requires_sync=None): 3201 ''' 3202 See copy_blob for more details. This helper method 3203 allows for standard copies as well as incremental copies which are only supported for page blobs and sync 3204 copies which are only supported for block blobs. 3205 :param bool incremental_copy: 3206 Performs an incremental copy operation on a page blob instead of a standard copy operation. 3207 :param bool requires_sync: 3208 Enforces that the service will not return a response until the copy is complete. 3209 ''' 3210 _validate_not_none('container_name', container_name) 3211 _validate_not_none('blob_name', blob_name) 3212 _validate_not_none('copy_source', copy_source) 3213 3214 if copy_source.startswith('/'): 3215 # Backwards compatibility for earlier versions of the SDK where 3216 # the copy source can be in the following formats: 3217 # - Blob in named container: 3218 # /accountName/containerName/blobName 3219 # - Snapshot in named container: 3220 # /accountName/containerName/blobName?snapshot=<DateTime> 3221 # - Blob in root container: 3222 # /accountName/blobName 3223 # - Snapshot in root container: 3224 # /accountName/blobName?snapshot=<DateTime> 3225 account, _, source = \ 3226 copy_source.partition('/')[2].partition('/') 3227 copy_source = self.protocol + '://' + \ 3228 self.primary_endpoint + '/' + source 3229 3230 request = HTTPRequest() 3231 request.method = 'PUT' 3232 request.host_locations = self._get_host_locations() 3233 request.path = _get_path(container_name, blob_name) 3234 3235 if incremental_copy: 3236 request.query = { 3237 'comp': 'incrementalcopy', 3238 'timeout': _int_to_str(timeout), 3239 } 3240 else: 3241 request.query = {'timeout': _int_to_str(timeout)} 3242 3243 request.headers = { 3244 'x-ms-copy-source': _to_str(copy_source), 3245 'x-ms-source-if-modified-since': _to_str(source_if_modified_since), 3246 'x-ms-source-if-unmodified-since': _to_str(source_if_unmodified_since), 3247 'x-ms-source-if-match': _to_str(source_if_match), 3248 'x-ms-source-if-none-match': _to_str(source_if_none_match), 3249 'If-Modified-Since': _datetime_to_utc_string(destination_if_modified_since), 3250 'If-Unmodified-Since': _datetime_to_utc_string(destination_if_unmodified_since), 3251 'If-Match': _to_str(destination_if_match), 3252 'If-None-Match': _to_str(destination_if_none_match), 3253 'x-ms-lease-id': _to_str(destination_lease_id), 3254 'x-ms-source-lease-id': _to_str(source_lease_id), 3255 'x-ms-access-tier': _to_str(premium_page_blob_tier), 3256 'x-ms-requires-sync': _to_str(requires_sync) 3257 } 3258 3259 _add_metadata_headers(metadata, request) 3260 3261 return self._perform_request(request, _parse_properties, [BlobProperties]).copy 3262 3263 def abort_copy_blob(self, container_name, blob_name, copy_id, 3264 lease_id=None, timeout=None): 3265 ''' 3266 Aborts a pending copy_blob operation, and leaves a destination blob 3267 with zero length and full metadata. 3268 3269 :param str container_name: 3270 Name of destination container. 3271 :param str blob_name: 3272 Name of destination blob. 3273 :param str copy_id: 3274 Copy identifier provided in the copy.id of the original 3275 copy_blob operation. 3276 :param str lease_id: 3277 Required if the destination blob has an active infinite lease. 3278 :param int timeout: 3279 The timeout parameter is expressed in seconds. 3280 ''' 3281 _validate_not_none('container_name', container_name) 3282 _validate_not_none('blob_name', blob_name) 3283 _validate_not_none('copy_id', copy_id) 3284 request = HTTPRequest() 3285 request.method = 'PUT' 3286 request.host_locations = self._get_host_locations() 3287 request.path = _get_path(container_name, blob_name) 3288 request.query = { 3289 'comp': 'copy', 3290 'copyid': _to_str(copy_id), 3291 'timeout': _int_to_str(timeout), 3292 } 3293 request.headers = { 3294 'x-ms-lease-id': _to_str(lease_id), 3295 'x-ms-copy-action': 'abort', 3296 } 3297 3298 self._perform_request(request) 3299 3300 def delete_blob(self, container_name, blob_name, snapshot=None, 3301 lease_id=None, delete_snapshots=None, 3302 if_modified_since=None, if_unmodified_since=None, 3303 if_match=None, if_none_match=None, timeout=None): 3304 ''' 3305 Marks the specified blob or snapshot for deletion. 3306 The blob is later deleted during garbage collection. 3307 3308 Note that in order to delete a blob, you must delete all of its 3309 snapshots. You can delete both at the same time with the Delete 3310 Blob operation. 3311 3312 If a delete retention policy is enabled for the service, then this operation soft deletes the blob or snapshot 3313 and retains the blob or snapshot for specified number of days. 3314 After specified number of days, blob's data is removed from the service during garbage collection. 3315 Soft deleted blob or snapshot is accessible through List Blobs API specifying include=Include.Deleted option. 3316 Soft-deleted blob or snapshot can be restored using Undelete API. 3317 3318 :param str container_name: 3319 Name of existing container. 3320 :param str blob_name: 3321 Name of existing blob. 3322 :param str snapshot: 3323 The snapshot parameter is an opaque DateTime value that, 3324 when present, specifies the blob snapshot to delete. 3325 :param str lease_id: 3326 Required if the blob has an active lease. 3327 :param ~azure.storage.blob.models.DeleteSnapshot delete_snapshots: 3328 Required if the blob has associated snapshots. 3329 :param datetime if_modified_since: 3330 A DateTime value. Azure expects the date value passed in to be UTC. 3331 If timezone is included, any non-UTC datetimes will be converted to UTC. 3332 If a date is passed in without timezone info, it is assumed to be UTC. 3333 Specify this header to perform the operation only 3334 if the resource has been modified since the specified time. 3335 :param datetime if_unmodified_since: 3336 A DateTime value. Azure expects the date value passed in to be UTC. 3337 If timezone is included, any non-UTC datetimes will be converted to UTC. 3338 If a date is passed in without timezone info, it is assumed to be UTC. 3339 Specify this header to perform the operation only if 3340 the resource has not been modified since the specified date/time. 3341 :param str if_match: 3342 An ETag value, or the wildcard character (*). Specify this header to perform 3343 the operation only if the resource's ETag matches the value specified. 3344 :param str if_none_match: 3345 An ETag value, or the wildcard character (*). Specify this header 3346 to perform the operation only if the resource's ETag does not match 3347 the value specified. Specify the wildcard character (*) to perform 3348 the operation only if the resource does not exist, and fail the 3349 operation if it does exist. 3350 :param int timeout: 3351 The timeout parameter is expressed in seconds. 3352 ''' 3353 _validate_not_none('container_name', container_name) 3354 _validate_not_none('blob_name', blob_name) 3355 request = HTTPRequest() 3356 request.method = 'DELETE' 3357 request.host_locations = self._get_host_locations() 3358 request.path = _get_path(container_name, blob_name) 3359 request.headers = { 3360 'x-ms-lease-id': _to_str(lease_id), 3361 'x-ms-delete-snapshots': _to_str(delete_snapshots), 3362 'If-Modified-Since': _datetime_to_utc_string(if_modified_since), 3363 'If-Unmodified-Since': _datetime_to_utc_string(if_unmodified_since), 3364 'If-Match': _to_str(if_match), 3365 'If-None-Match': _to_str(if_none_match), 3366 } 3367 request.query = { 3368 'snapshot': _to_str(snapshot), 3369 'timeout': _int_to_str(timeout) 3370 } 3371 3372 self._perform_request(request) 3373 3374 def undelete_blob(self, container_name, blob_name, timeout=None): 3375 ''' 3376 The undelete Blob operation restores the contents and metadata of soft deleted blob or snapshot. 3377 Attempting to undelete a blob or snapshot that is not soft deleted will succeed without any changes. 3378 3379 :param str container_name: 3380 Name of existing container. 3381 :param str blob_name: 3382 Name of existing blob. 3383 :param int timeout: 3384 The timeout parameter is expressed in seconds. 3385 ''' 3386 _validate_not_none('container_name', container_name) 3387 _validate_not_none('blob_name', blob_name) 3388 request = HTTPRequest() 3389 request.method = 'PUT' 3390 request.host_locations = self._get_host_locations() 3391 request.path = _get_path(container_name, blob_name) 3392 request.query = { 3393 'comp': 'undelete', 3394 'timeout': _int_to_str(timeout) 3395 } 3396 3397 self._perform_request(request) 3398