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# -------------------------------------------------------------------------- 6 7import functools 8from typing import ( # pylint: disable=unused-import 9 Union, Optional, Any, Dict, List, 10 TYPE_CHECKING 11) 12try: 13 from urllib.parse import urlparse 14except ImportError: 15 from urlparse import urlparse # type: ignore 16 17from azure.core.paging import ItemPaged 18from azure.core.tracing.decorator import distributed_trace 19from azure.core.pipeline import Pipeline 20from ._shared.base_client import StorageAccountHostsMixin, TransportWrapper, parse_connection_str, parse_query 21from ._shared.response_handlers import process_storage_error 22from ._generated import AzureFileStorage 23from ._generated.models import StorageErrorException, StorageServiceProperties 24from ._generated.version import VERSION 25from ._share_client import ShareClient 26from ._serialize import get_api_version 27from ._models import ( 28 SharePropertiesPaged, 29 service_properties_deserialize, 30) 31 32if TYPE_CHECKING: 33 from datetime import datetime 34 from ._models import ( 35 ShareProperties, 36 Metrics, 37 CorsRule, 38 ) 39 40 41class ShareServiceClient(StorageAccountHostsMixin): 42 """A client to interact with the File Share Service at the account level. 43 44 This client provides operations to retrieve and configure the account properties 45 as well as list, create and delete shares within the account. 46 For operations relating to a specific share, a client for that entity 47 can also be retrieved using the :func:`get_share_client` function. 48 49 :param str account_url: 50 The URL to the file share storage account. Any other entities included 51 in the URL path (e.g. share or file) will be discarded. This URL can be optionally 52 authenticated with a SAS token. 53 :param credential: 54 The credential with which to authenticate. This is optional if the 55 account URL already has a SAS token. The value can be a SAS token string or an account 56 shared access key. 57 :keyword str api_version: 58 The Storage API version to use for requests. Default value is '2019-07-07'. 59 Setting to an older version may result in reduced feature compatibility. 60 61 .. versionadded:: 12.1.0 62 63 :keyword str secondary_hostname: 64 The hostname of the secondary endpoint. 65 :keyword int max_range_size: The maximum range size used for a file upload. Defaults to 4*1024*1024. 66 67 .. admonition:: Example: 68 69 .. literalinclude:: ../samples/file_samples_authentication.py 70 :start-after: [START create_share_service_client] 71 :end-before: [END create_share_service_client] 72 :language: python 73 :dedent: 8 74 :caption: Create the share service client with url and credential. 75 """ 76 def __init__( 77 self, account_url, # type: str 78 credential=None, # type: Optional[Any] 79 **kwargs # type: Any 80 ): 81 # type: (...) -> None 82 try: 83 if not account_url.lower().startswith('http'): 84 account_url = "https://" + account_url 85 except AttributeError: 86 raise ValueError("Account URL must be a string.") 87 parsed_url = urlparse(account_url.rstrip('/')) 88 if not parsed_url.netloc: 89 raise ValueError("Invalid URL: {}".format(account_url)) 90 if hasattr(credential, 'get_token'): 91 raise ValueError("Token credentials not supported by the File Share service.") 92 93 _, sas_token = parse_query(parsed_url.query) 94 if not sas_token and not credential: 95 raise ValueError( 96 'You need to provide either an account shared key or SAS token when creating a storage service.') 97 self._query_str, credential = self._format_query_string(sas_token, credential) 98 super(ShareServiceClient, self).__init__(parsed_url, service='file-share', credential=credential, **kwargs) 99 self._client = AzureFileStorage(version=VERSION, url=self.url, pipeline=self._pipeline) 100 self._client._config.version = get_api_version(kwargs, VERSION) # pylint: disable=protected-access 101 102 def _format_url(self, hostname): 103 """Format the endpoint URL according to the current location 104 mode hostname. 105 """ 106 return "{}://{}/{}".format(self.scheme, hostname, self._query_str) 107 108 @classmethod 109 def from_connection_string( 110 cls, conn_str, # type: str 111 credential=None, # type: Optional[Any] 112 **kwargs # type: Any 113 ): # type: (...) -> ShareServiceClient 114 """Create ShareServiceClient from a Connection String. 115 116 :param str conn_str: 117 A connection string to an Azure Storage account. 118 :param credential: 119 The credential with which to authenticate. This is optional if the 120 account URL already has a SAS token. The value can be a SAS token string or an account 121 shared access key. 122 :returns: A File Share service client. 123 :rtype: ~azure.storage.fileshare.ShareServiceClient 124 125 .. admonition:: Example: 126 127 .. literalinclude:: ../samples/file_samples_authentication.py 128 :start-after: [START create_share_service_client_from_conn_string] 129 :end-before: [END create_share_service_client_from_conn_string] 130 :language: python 131 :dedent: 8 132 :caption: Create the share service client with connection string. 133 """ 134 account_url, secondary, credential = parse_connection_str(conn_str, credential, 'file') 135 if 'secondary_hostname' not in kwargs: 136 kwargs['secondary_hostname'] = secondary 137 return cls(account_url, credential=credential, **kwargs) 138 139 @distributed_trace 140 def get_service_properties(self, **kwargs): 141 # type: (Any) -> Dict[str, Any] 142 """Gets the properties of a storage account's File Share service, including 143 Azure Storage Analytics. 144 145 :keyword int timeout: 146 The timeout parameter is expressed in seconds. 147 :returns: A dictionary containing file service properties such as 148 analytics logging, hour/minute metrics, cors rules, etc. 149 :rtype: Dict[str, Any] 150 151 .. admonition:: Example: 152 153 .. literalinclude:: ../samples/file_samples_service.py 154 :start-after: [START get_service_properties] 155 :end-before: [END get_service_properties] 156 :language: python 157 :dedent: 8 158 :caption: Get file share service properties. 159 """ 160 timeout = kwargs.pop('timeout', None) 161 try: 162 service_props = self._client.service.get_properties(timeout=timeout, **kwargs) 163 return service_properties_deserialize(service_props) 164 except StorageErrorException as error: 165 process_storage_error(error) 166 167 @distributed_trace 168 def set_service_properties( 169 self, hour_metrics=None, # type: Optional[Metrics] 170 minute_metrics=None, # type: Optional[Metrics] 171 cors=None, # type: Optional[List[CorsRule]] 172 **kwargs 173 ): 174 # type: (...) -> None 175 """Sets the properties of a storage account's File Share service, including 176 Azure Storage Analytics. If an element (e.g. hour_metrics) is left as None, the 177 existing settings on the service for that functionality are preserved. 178 179 :param hour_metrics: 180 The hour metrics settings provide a summary of request 181 statistics grouped by API in hourly aggregates for files. 182 :type hour_metrics: ~azure.storage.fileshare.Metrics 183 :param minute_metrics: 184 The minute metrics settings provide request statistics 185 for each minute for files. 186 :type minute_metrics: ~azure.storage.fileshare.Metrics 187 :param cors: 188 You can include up to five CorsRule elements in the 189 list. If an empty list is specified, all CORS rules will be deleted, 190 and CORS will be disabled for the service. 191 :type cors: list(:class:`~azure.storage.fileshare.CorsRule`) 192 :keyword int timeout: 193 The timeout parameter is expressed in seconds. 194 :rtype: None 195 196 .. admonition:: Example: 197 198 .. literalinclude:: ../samples/file_samples_service.py 199 :start-after: [START set_service_properties] 200 :end-before: [END set_service_properties] 201 :language: python 202 :dedent: 8 203 :caption: Sets file share service properties. 204 """ 205 timeout = kwargs.pop('timeout', None) 206 props = StorageServiceProperties( 207 hour_metrics=hour_metrics, 208 minute_metrics=minute_metrics, 209 cors=cors 210 ) 211 try: 212 self._client.service.set_properties(props, timeout=timeout, **kwargs) 213 except StorageErrorException as error: 214 process_storage_error(error) 215 216 @distributed_trace 217 def list_shares( 218 self, name_starts_with=None, # type: Optional[str] 219 include_metadata=False, # type: Optional[bool] 220 include_snapshots=False, # type: Optional[bool] 221 **kwargs 222 ): 223 # type: (...) -> ItemPaged[ShareProperties] 224 """Returns auto-paging iterable of dict-like ShareProperties under the specified account. 225 The generator will lazily follow the continuation tokens returned by 226 the service and stop when all shares have been returned. 227 228 :param str name_starts_with: 229 Filters the results to return only shares whose names 230 begin with the specified name_starts_with. 231 :param bool include_metadata: 232 Specifies that share metadata be returned in the response. 233 :param bool include_snapshots: 234 Specifies that share snapshot be returned in the response. 235 :keyword bool include_deleted: 236 Specifies that deleted shares be returned in the response. 237 This is only for share soft delete enabled account. 238 :keyword int timeout: 239 The timeout parameter is expressed in seconds. 240 :returns: An iterable (auto-paging) of ShareProperties. 241 :rtype: ~azure.core.paging.ItemPaged[~azure.storage.fileshare.ShareProperties] 242 243 .. admonition:: Example: 244 245 .. literalinclude:: ../samples/file_samples_service.py 246 :start-after: [START fsc_list_shares] 247 :end-before: [END fsc_list_shares] 248 :language: python 249 :dedent: 12 250 :caption: List shares in the file share service. 251 """ 252 timeout = kwargs.pop('timeout', None) 253 include = [] 254 include_deleted = kwargs.pop('include_deleted', None) 255 if include_deleted: 256 include.append("deleted") 257 if include_metadata: 258 include.append('metadata') 259 if include_snapshots: 260 include.append('snapshots') 261 262 results_per_page = kwargs.pop('results_per_page', None) 263 command = functools.partial( 264 self._client.service.list_shares_segment, 265 include=include, 266 timeout=timeout, 267 **kwargs) 268 return ItemPaged( 269 command, prefix=name_starts_with, results_per_page=results_per_page, 270 page_iterator_class=SharePropertiesPaged) 271 272 @distributed_trace 273 def create_share( 274 self, share_name, # type: str 275 **kwargs 276 ): 277 # type: (...) -> ShareClient 278 """Creates a new share under the specified account. If the share 279 with the same name already exists, the operation fails. Returns a client with 280 which to interact with the newly created share. 281 282 :param str share_name: The name of the share to create. 283 :keyword dict(str,str) metadata: 284 A dict with name_value pairs to associate with the 285 share as metadata. Example:{'Category':'test'} 286 :keyword int quota: 287 Quota in bytes. 288 :keyword int timeout: 289 The timeout parameter is expressed in seconds. 290 :rtype: ~azure.storage.fileshare.ShareClient 291 292 .. admonition:: Example: 293 294 .. literalinclude:: ../samples/file_samples_service.py 295 :start-after: [START fsc_create_shares] 296 :end-before: [END fsc_create_shares] 297 :language: python 298 :dedent: 8 299 :caption: Create a share in the file share service. 300 """ 301 metadata = kwargs.pop('metadata', None) 302 quota = kwargs.pop('quota', None) 303 timeout = kwargs.pop('timeout', None) 304 share = self.get_share_client(share_name) 305 kwargs.setdefault('merge_span', True) 306 share.create_share(metadata=metadata, quota=quota, timeout=timeout, **kwargs) 307 return share 308 309 @distributed_trace 310 def delete_share( 311 self, share_name, # type: Union[ShareProperties, str] 312 delete_snapshots=False, # type: Optional[bool] 313 **kwargs 314 ): 315 # type: (...) -> None 316 """Marks the specified share for deletion. The share is 317 later deleted during garbage collection. 318 319 :param share_name: 320 The share to delete. This can either be the name of the share, 321 or an instance of ShareProperties. 322 :type share_name: str or ~azure.storage.fileshare.ShareProperties 323 :param bool delete_snapshots: 324 Indicates if snapshots are to be deleted. 325 :keyword int timeout: 326 The timeout parameter is expressed in seconds. 327 :rtype: None 328 329 .. admonition:: Example: 330 331 .. literalinclude:: ../samples/file_samples_service.py 332 :start-after: [START fsc_delete_shares] 333 :end-before: [END fsc_delete_shares] 334 :language: python 335 :dedent: 12 336 :caption: Delete a share in the file share service. 337 """ 338 timeout = kwargs.pop('timeout', None) 339 share = self.get_share_client(share_name) 340 kwargs.setdefault('merge_span', True) 341 share.delete_share( 342 delete_snapshots=delete_snapshots, timeout=timeout, **kwargs) 343 344 @distributed_trace 345 def undelete_share(self, deleted_share_name, deleted_share_version, **kwargs): 346 # type: (str, str, **Any) -> ShareClient 347 """Restores soft-deleted share. 348 349 Operation will only be successful if used within the specified number of days 350 set in the delete retention policy. 351 352 .. versionadded:: 12.2.0 353 This operation was introduced in API version '2019-12-12'. 354 355 :param str deleted_share_name: 356 Specifies the name of the deleted share to restore. 357 :param str deleted_share_version: 358 Specifies the version of the deleted share to restore. 359 :keyword int timeout: 360 The timeout parameter is expressed in seconds. 361 :rtype: ~azure.storage.fileshare.ShareClient 362 """ 363 share = self.get_share_client(deleted_share_name) 364 365 try: 366 share._client.share.restore(deleted_share_name=deleted_share_name, # pylint: disable = protected-access 367 deleted_share_version=deleted_share_version, 368 timeout=kwargs.pop('timeout', None), **kwargs) 369 return share 370 except StorageErrorException as error: 371 process_storage_error(error) 372 373 def get_share_client(self, share, snapshot=None): 374 # type: (Union[ShareProperties, str],Optional[Union[Dict[str, Any], str]]) -> ShareClient 375 """Get a client to interact with the specified share. 376 The share need not already exist. 377 378 :param share: 379 The share. This can either be the name of the share, 380 or an instance of ShareProperties. 381 :type share: str or ~azure.storage.fileshare.ShareProperties 382 :param str snapshot: 383 An optional share snapshot on which to operate. This can be the snapshot ID string 384 or the response returned from :func:`create_snapshot`. 385 :returns: A ShareClient. 386 :rtype: ~azure.storage.fileshare.ShareClient 387 388 .. admonition:: Example: 389 390 .. literalinclude:: ../samples/file_samples_service.py 391 :start-after: [START get_share_client] 392 :end-before: [END get_share_client] 393 :language: python 394 :dedent: 8 395 :caption: Gets the share client. 396 """ 397 try: 398 share_name = share.name 399 except AttributeError: 400 share_name = share 401 402 _pipeline = Pipeline( 403 transport=TransportWrapper(self._pipeline._transport), # pylint: disable = protected-access 404 policies=self._pipeline._impl_policies # pylint: disable = protected-access 405 ) 406 return ShareClient( 407 self.url, share_name=share_name, snapshot=snapshot, credential=self.credential, 408 api_version=self.api_version, _hosts=self._hosts, 409 _configuration=self._config, _pipeline=_pipeline, _location_mode=self._location_mode) 410