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# pylint: disable=invalid-overridden-method
7import functools
8from typing import (  # pylint: disable=unused-import
9    Union, Optional, Any, Iterable, Dict, List,
10    TYPE_CHECKING
11)
12
13from azure.core.async_paging import AsyncItemPaged
14from azure.core.exceptions import HttpResponseError
15from azure.core.tracing.decorator import distributed_trace
16from azure.core.pipeline import AsyncPipeline
17from azure.core.tracing.decorator_async import distributed_trace_async
18
19from .._shared.base_client_async import AsyncStorageAccountHostsMixin, AsyncTransportWrapper
20from .._shared.response_handlers import process_storage_error
21from .._shared.policies_async import ExponentialRetry
22from .._generated.aio import AzureFileStorage
23from .._generated.models import StorageServiceProperties
24from .._share_service_client import ShareServiceClient as ShareServiceClientBase
25from .._serialize import get_api_version
26from ._share_client_async import ShareClient
27from ._models import SharePropertiesPaged
28from .._models import service_properties_deserialize
29
30if TYPE_CHECKING:
31    from datetime import datetime
32    from .._shared.models import ResourceTypes, AccountSasPermissions
33    from .._models import (
34        ShareProperties,
35        Metrics,
36        CorsRule,
37        ShareProtocolSettings,
38    )
39
40
41class ShareServiceClient(AsyncStorageAccountHostsMixin, ShareServiceClientBase):
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,
56        an instance of a AzureSasCredential from azure.core.credentials or an account
57        shared access key.
58    :keyword str api_version:
59        The Storage API version to use for requests. Default value is '2019-07-07'.
60        Setting to an older version may result in reduced feature compatibility.
61
62        .. versionadded:: 12.1.0
63
64    :keyword str secondary_hostname:
65        The hostname of the secondary endpoint.
66    :keyword loop:
67        The event loop to run the asynchronous tasks.
68    :keyword int max_range_size: The maximum range size used for a file upload. Defaults to 4*1024*1024.
69
70    .. admonition:: Example:
71
72        .. literalinclude:: ../samples/file_samples_authentication_async.py
73            :start-after: [START create_share_service_client]
74            :end-before: [END create_share_service_client]
75            :language: python
76            :dedent: 8
77            :caption: Create the share service client with url and credential.
78    """
79    def __init__(
80            self, account_url,  # type: str
81            credential=None,  # type: Optional[Any]
82            **kwargs  # type: Any
83        ):
84        # type: (...) -> None
85        kwargs['retry_policy'] = kwargs.get('retry_policy') or ExponentialRetry(**kwargs)
86        loop = kwargs.pop('loop', None)
87        super(ShareServiceClient, self).__init__(
88            account_url,
89            credential=credential,
90            loop=loop,
91            **kwargs)
92        self._client = AzureFileStorage(url=self.url, pipeline=self._pipeline, loop=loop)
93        default_api_version = self._client._config.version  # pylint: disable=protected-access
94        self._client._config.version = get_api_version(kwargs, default_api_version)  # pylint: disable=protected-access
95        self._loop = loop
96
97    @distributed_trace_async
98    async def get_service_properties(self, **kwargs):
99        # type: (Any) -> Dict[str, Any]
100        """Gets the properties of a storage account's File Share service, including
101        Azure Storage Analytics.
102
103        :keyword int timeout:
104            The timeout parameter is expressed in seconds.
105        :returns: A dictionary containing file service properties such as
106            analytics logging, hour/minute metrics, cors rules, etc.
107        :rtype: Dict[str, Any]
108
109        .. admonition:: Example:
110
111            .. literalinclude:: ../samples/file_samples_service_async.py
112                :start-after: [START get_service_properties]
113                :end-before: [END get_service_properties]
114                :language: python
115                :dedent: 12
116                :caption: Get file share service properties.
117        """
118        timeout = kwargs.pop('timeout', None)
119        try:
120            service_props = await self._client.service.get_properties(timeout=timeout, **kwargs)
121            return service_properties_deserialize(service_props)
122        except HttpResponseError as error:
123            process_storage_error(error)
124
125    @distributed_trace_async
126    async def set_service_properties(
127            self, hour_metrics=None,  # type: Optional[Metrics]
128            minute_metrics=None,  # type: Optional[Metrics]
129            cors=None,  # type: Optional[List[CorsRule]]
130            protocol=None,  # type: Optional[ShareProtocolSettings],
131            **kwargs
132        ):
133        # type: (...) -> None
134        """Sets the properties of a storage account's File Share service, including
135        Azure Storage Analytics. If an element (e.g. hour_metrics) is left as None, the
136        existing settings on the service for that functionality are preserved.
137
138        :param hour_metrics:
139            The hour metrics settings provide a summary of request
140            statistics grouped by API in hourly aggregates for files.
141        :type hour_metrics: ~azure.storage.fileshare.Metrics
142        :param minute_metrics:
143            The minute metrics settings provide request statistics
144            for each minute for files.
145        :type minute_metrics: ~azure.storage.fileshare.Metrics
146        :param cors:
147            You can include up to five CorsRule elements in the
148            list. If an empty list is specified, all CORS rules will be deleted,
149            and CORS will be disabled for the service.
150        :type cors: list(:class:`~azure.storage.fileshare.CorsRule`)
151        :param protocol_settings:
152            Sets protocol settings
153        :type protocol: ~azure.storage.fileshare.ShareProtocolSettings
154        :keyword int timeout:
155            The timeout parameter is expressed in seconds.
156        :rtype: None
157
158        .. admonition:: Example:
159
160            .. literalinclude:: ../samples/file_samples_service_async.py
161                :start-after: [START set_service_properties]
162                :end-before: [END set_service_properties]
163                :language: python
164                :dedent: 8
165                :caption: Sets file share service properties.
166        """
167        timeout = kwargs.pop('timeout', None)
168        props = StorageServiceProperties(
169            hour_metrics=hour_metrics,
170            minute_metrics=minute_metrics,
171            cors=cors,
172            protocol=protocol
173        )
174        try:
175            await self._client.service.set_properties(props, timeout=timeout, **kwargs)
176        except HttpResponseError as error:
177            process_storage_error(error)
178
179    @distributed_trace
180    def list_shares(
181            self, name_starts_with=None,  # type: Optional[str]
182            include_metadata=False,  # type: Optional[bool]
183            include_snapshots=False, # type: Optional[bool]
184            **kwargs  # type: Any
185        ):  # type: (...) -> AsyncItemPaged
186        """Returns auto-paging iterable of dict-like ShareProperties under the specified account.
187        The generator will lazily follow the continuation tokens returned by
188        the service and stop when all shares have been returned.
189
190        :param str name_starts_with:
191            Filters the results to return only shares whose names
192            begin with the specified name_starts_with.
193        :param bool include_metadata:
194            Specifies that share metadata be returned in the response.
195        :param bool include_snapshots:
196            Specifies that share snapshot be returned in the response.
197        :keyword bool include_deleted:
198            Specifies that deleted shares be returned in the response.
199            This is only for share soft delete enabled account.
200        :keyword int timeout:
201            The timeout parameter is expressed in seconds.
202        :returns: An iterable (auto-paging) of ShareProperties.
203        :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.storage.fileshare.ShareProperties]
204
205        .. admonition:: Example:
206
207            .. literalinclude:: ../samples/file_samples_service_async.py
208                :start-after: [START fsc_list_shares]
209                :end-before: [END fsc_list_shares]
210                :language: python
211                :dedent: 16
212                :caption: List shares in the file share service.
213        """
214        timeout = kwargs.pop('timeout', None)
215        include = []
216        if include_metadata:
217            include.append('metadata')
218        if include_snapshots:
219            include.append('snapshots')
220        include_deleted = kwargs.pop('include_deleted', None)
221        if include_deleted:
222            include.append("deleted")
223
224        results_per_page = kwargs.pop('results_per_page', None)
225        command = functools.partial(
226            self._client.service.list_shares_segment,
227            include=include,
228            timeout=timeout,
229            **kwargs)
230        return AsyncItemPaged(
231            command, prefix=name_starts_with, results_per_page=results_per_page,
232            page_iterator_class=SharePropertiesPaged)
233
234    @distributed_trace_async
235    async def create_share(
236            self, share_name,  # type: str
237            **kwargs
238        ):
239        # type: (...) -> ShareClient
240        """Creates a new share under the specified account. If the share
241        with the same name already exists, the operation fails. Returns a client with
242        which to interact with the newly created share.
243
244        :param str share_name: The name of the share to create.
245        :keyword dict(str,str) metadata:
246            A dict with name_value pairs to associate with the
247            share as metadata. Example:{'Category':'test'}
248        :keyword int quota:
249            Quota in bytes.
250        :keyword int timeout:
251            The timeout parameter is expressed in seconds.
252        :rtype: ~azure.storage.fileshare.aio.ShareClient
253
254        .. admonition:: Example:
255
256            .. literalinclude:: ../samples/file_samples_service_async.py
257                :start-after: [START fsc_create_shares]
258                :end-before: [END fsc_create_shares]
259                :language: python
260                :dedent: 12
261                :caption: Create a share in the file share service.
262        """
263        metadata = kwargs.pop('metadata', None)
264        quota = kwargs.pop('quota', None)
265        timeout = kwargs.pop('timeout', None)
266        share = self.get_share_client(share_name)
267        kwargs.setdefault('merge_span', True)
268        await share.create_share(metadata=metadata, quota=quota, timeout=timeout, **kwargs)
269        return share
270
271    @distributed_trace_async
272    async def delete_share(
273            self, share_name,  # type: Union[ShareProperties, str]
274            delete_snapshots=False, # type: Optional[bool]
275            **kwargs
276        ):
277        # type: (...) -> None
278        """Marks the specified share for deletion. The share is
279        later deleted during garbage collection.
280
281        :param share_name:
282            The share to delete. This can either be the name of the share,
283            or an instance of ShareProperties.
284        :type share_name: str or ~azure.storage.fileshare.ShareProperties
285        :param bool delete_snapshots:
286            Indicates if snapshots are to be deleted.
287        :keyword int timeout:
288            The timeout parameter is expressed in seconds.
289        :rtype: None
290
291        .. admonition:: Example:
292
293            .. literalinclude:: ../samples/file_samples_service_async.py
294                :start-after: [START fsc_delete_shares]
295                :end-before: [END fsc_delete_shares]
296                :language: python
297                :dedent: 16
298                :caption: Delete a share in the file share service.
299        """
300        timeout = kwargs.pop('timeout', None)
301        share = self.get_share_client(share_name)
302        kwargs.setdefault('merge_span', True)
303        await share.delete_share(
304            delete_snapshots=delete_snapshots, timeout=timeout, **kwargs)
305
306    @distributed_trace_async
307    async def undelete_share(self, deleted_share_name, deleted_share_version, **kwargs):
308        # type: (str, str, **Any) -> ShareClient
309        """Restores soft-deleted share.
310
311        Operation will only be successful if used within the specified number of days
312        set in the delete retention policy.
313
314        .. versionadded:: 12.2.0
315            This operation was introduced in API version '2019-12-12'.
316
317        :param str deleted_share_name:
318            Specifies the name of the deleted share to restore.
319        :param str deleted_share_version:
320            Specifies the version of the deleted share to restore.
321        :keyword int timeout:
322            The timeout parameter is expressed in seconds.
323        :rtype: ~azure.storage.fileshare.aio.ShareClient
324        """
325        share = self.get_share_client(deleted_share_name)
326        try:
327            await share._client.share.restore(deleted_share_name=deleted_share_name,  # pylint: disable = protected-access
328                                              deleted_share_version=deleted_share_version,
329                                              timeout=kwargs.pop('timeout', None), **kwargs)
330            return share
331        except HttpResponseError as error:
332            process_storage_error(error)
333
334    def get_share_client(self, share, snapshot=None):
335        # type: (Union[ShareProperties, str],Optional[Union[Dict[str, Any], str]]) -> ShareClient
336        """Get a client to interact with the specified share.
337        The share need not already exist.
338
339        :param share:
340            The share. This can either be the name of the share,
341            or an instance of ShareProperties.
342        :type share: str or ~azure.storage.fileshare.ShareProperties
343        :param str snapshot:
344            An optional share snapshot on which to operate. This can be the snapshot ID string
345            or the response returned from :func:`create_snapshot`.
346        :returns: A ShareClient.
347        :rtype: ~azure.storage.fileshare.aio.ShareClient
348
349        .. admonition:: Example:
350
351            .. literalinclude:: ../samples/file_samples_service_async.py
352                :start-after: [START get_share_client]
353                :end-before: [END get_share_client]
354                :language: python
355                :dedent: 8
356                :caption: Gets the share client.
357        """
358        try:
359            share_name = share.name
360        except AttributeError:
361            share_name = share
362
363        _pipeline = AsyncPipeline(
364            transport=AsyncTransportWrapper(self._pipeline._transport), # pylint: disable = protected-access
365            policies=self._pipeline._impl_policies # pylint: disable = protected-access
366        )
367        return ShareClient(
368            self.url, share_name=share_name, snapshot=snapshot, credential=self.credential,
369            api_version=self.api_version, _hosts=self._hosts, _configuration=self._config,
370            _pipeline=_pipeline, _location_mode=self._location_mode, loop=self._loop)
371