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