diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 00000000..64251efc --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,12 @@ +# Git blame ignore revisions +# This file contains commit hashes that should be ignored by git blame +# to avoid showing formatting/style changes in blame output. +# +# To use this file, run: +# git config blame.ignoreRevsFile .git-blame-ignore-revs + +# Ruff formatting commits to ignore +0ef57c0f49b9c0a6be358a87fff67869c0dc95b4 +95bd3aca64ddec062b884521349914866ddb4672 +16aaa8e7439bb8441c7a9ceff8d398fda276c553 +3e3b385c8c20b94b57255a3f34b39a249ba0a3ae diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 11db1d1c..935d4fff 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,24 +1,33 @@ --- -default_language_version: - # force all unspecified python hooks to run python3 - python: python3 repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v6.0.0 hooks: - id: trailing-whitespace - id: mixed-line-ending args: ['--fix', 'lf'] exclude: '.*\.(svg)$' - - id: check-byte-order-marker + - id: fix-byte-order-marker - id: check-executables-have-shebangs - id: check-merge-conflict - id: debug-statements - id: check-yaml files: .*\.(yaml|yml)$ exclude: '^(zuul.d|rally-jobs)/.*$' + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.14.0 + hooks: + - id: ruff-check + args: ['--fix', '--unsafe-fixes'] + - id: ruff-format + - repo: https://opendev.org/openstack/hacking + rev: 7.0.0 + hooks: + - id: hacking + additional_dependencies: [] + exclude: '^(doc|releasenotes|tools)/.*$' - repo: https://github.com/PyCQA/doc8 - rev: v1.1.1 + rev: v2.0.0 hooks: - id: doc8 args: ['--ignore', 'D001'] @@ -27,13 +36,3 @@ repos: hooks: - id: bashate args: ['--ignore', 'E006,E042,E043'] - - repo: local - hooks: - - id: flake8 - name: flake8 - additional_dependencies: - - hacking>=6.1.0,<6.2.0 - language: python - entry: flake8 - files: '^.*\.py$' - exclude: '^(doc|releasenotes|tools)/.*$' \ No newline at end of file diff --git a/README.rst b/README.rst index 53ae74a6..b3ea62df 100644 --- a/README.rst +++ b/README.rst @@ -52,20 +52,20 @@ Command-line API ---------------- Installing this package gets you a shell command, ``manila``, that you -can use to interact with any Rackspace compatible API (including OpenStack). +can use to interact with the OpenStack Manila API. You'll need to provide your OpenStack username and password. You can do this -with the ``--os-username``, ``--os-password`` and ``--os-tenant-name`` +with the ``--os-username``, ``--os-password`` and ``--os-project-name`` params, but it's easier to just set them as environment variables:: export OS_USERNAME=foouser export OS_PASSWORD=barpass - export OS_TENANT_NAME=fooproject + export OS_PROJECT_NAME=fooproject You will also need to define the authentication url either with param ``--os-auth-url`` or as an environment variable:: - export OS_AUTH_URL=http://example.com:5000/v2.0/ + export OS_AUTH_URL=http://example.com:5000/v3/ Since Keystone can return multiple regions in the Service Catalog, you can specify the one you want with ``--os-region-name`` (or @@ -81,9 +81,9 @@ There's also a complete Python API, but it has not yet been documented. Quick-start using keystone:: - # use v2.0 auth with http://example.com:5000/v2.0/ - >>> from manilaclient.v1 import client - >>> nt = client.Client(USER, PASS, TENANT, AUTH_URL, service_type="share") + # use v3 auth with http://example.com:5000/v3/ + >>> from manilaclient.v2 import client + >>> nt = client.Client("2", USER, PASS, PROJECT, AUTH_URL, service_type="share") >>> nt.shares.list() [...] diff --git a/doc/.gitignore b/doc/.gitignore deleted file mode 100644 index 567609b1..00000000 --- a/doc/.gitignore +++ /dev/null @@ -1 +0,0 @@ -build/ diff --git a/doc/Makefile b/doc/Makefile deleted file mode 100644 index 76a65711..00000000 --- a/doc/Makefile +++ /dev/null @@ -1,90 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -SPHINXSOURCE = source -PAPER = -BUILDDIR = build - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SPHINXSOURCE) - -.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest - -help: - @echo "Please use \`make ' where is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - -clean: - -rm -rf $(BUILDDIR)/* - -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." - -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." - -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/python-manilaclient.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/python-manilaclient.qhc" - -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ - "run these through (pdf)latex." - -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." diff --git a/doc/source/cli/decoder.rst b/doc/source/cli/decoder.rst index 2c336df4..b97d745e 100644 --- a/doc/source/cli/decoder.rst +++ b/doc/source/cli/decoder.rst @@ -2,10 +2,14 @@ OpenStackClient Mapping Guide ============================= +.. note:: + + The legacy ``manila`` CLI has been removed. This guide is maintained for + historical reference to help users upgrading from older versions. + The following is a mapping between the legacy ``manila`` CLI client and OpenStackClient. Command options are only shown when necessary. - .. only:: html .. csv-table:: diff --git a/doc/source/cli/osc/v2/index.rst b/doc/source/cli/osc/v2/index.rst index 53420859..6946f4c8 100644 --- a/doc/source/cli/osc/v2/index.rst +++ b/doc/source/cli/osc/v2/index.rst @@ -221,3 +221,10 @@ resource locks .. autoprogram-cliff:: openstack.share.v2 :command: share lock * + +========= +qos types +========= + +.. autoprogram-cliff:: openstack.share.v2 + :command: share qos type * diff --git a/doc/source/cli/osc_plugin_cli.rst b/doc/source/cli/osc_plugin_cli.rst index b43aead9..5ea18a62 100644 --- a/doc/source/cli/osc_plugin_cli.rst +++ b/doc/source/cli/osc_plugin_cli.rst @@ -27,10 +27,17 @@ environment variables:: export OS_USERNAME=foo export OS_PASSWORD=bar - export OS_TENANT_NAME=foobarproject + export OS_PROJECT_NAME=foobarproject export OS_AUTH_URL=http://... export OS_SHARE_API_VERSION=2.51 +It is possible to use different Manila endpoint while using Openstack +Client. In this case, you can use configuration option +``--os-endpoint-override`` or set the corresponding environment +variable:: + + export OS_SHARED_FILE_SYSTEM_ENDPOINT_OVERRIDE=http://... + Getting help ============ diff --git a/doc/source/conf.py b/doc/source/conf.py index 52b03f1c..198d7d5a 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -29,10 +29,12 @@ # Add any Sphinx extension module names here, as strings. They can be # extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.autodoc', - 'openstackdocstheme', - 'sphinxcontrib.programoutput', - 'cliff.sphinxext'] +extensions = [ + 'sphinx.ext.autodoc', + 'openstackdocstheme', + 'sphinxcontrib.programoutput', + 'cliff.sphinxext', +] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] @@ -87,8 +89,13 @@ # (source start file, target name, title, author, documentclass # [howto/manual]). latex_documents = [ - ('index', 'Manila-client.tex', 'Manila Python Client Documentation', - 'Manila contributors', 'manual'), + ( + 'index', + 'Manila-client.tex', + 'Manila Python Client Documentation', + 'Manila contributors', + 'manual', + ), ] # The name of an image file (relative to this directory) to place at the top of diff --git a/doc/source/contributor/functional-tests.rst b/doc/source/contributor/functional-tests.rst index 95c19ee3..bee3713e 100644 --- a/doc/source/contributor/functional-tests.rst +++ b/doc/source/contributor/functional-tests.rst @@ -28,7 +28,7 @@ run manila, a good place to start would be the `manila contributor guide`_. You can use the following local.conf file to configure DevStack including Manila using a few fake back ends: -.. code-block:: console +.. code-block:: bash [[local|localrc]] @@ -117,7 +117,7 @@ For DevStack On your DevStack machine, you can run the following script. It assumes that ``devstack`` is cloned onto your base folder. -.. code-block:: console +.. code-block:: bash DEST=${DEST:-/opt/stack} MANILACLIENT_DIR=${MANILACLIENT_DIR:-$DEST/python-manilaclient} @@ -163,7 +163,7 @@ On your DevStack machine, you can run the following script. It assumes that # Create share network and use it for functional tests if required USE_SHARE_NETWORK=$(trueorfalse True USE_SHARE_NETWORK) -.. code-block:: console +.. code-block:: bash if [[ ${USE_SHARE_NETWORK} = True ]]; then SHARE_NETWORK_NAME=${SHARE_NETWORK_NAME:-ci} @@ -177,7 +177,7 @@ On your DevStack machine, you can run the following script. It assumes that fi -.. code-block:: console +.. code-block:: bash # Set share type if required if [[ "$SHARE_TYPE" ]]; then diff --git a/doc/source/index.rst b/doc/source/index.rst index bbd0c7f3..934e83e3 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -2,26 +2,17 @@ Python bindings to the OpenStack Manila API =========================================== This is a client for OpenStack Manila API. There's :doc:`a Python API -` (the :mod:`manilaclient` module), and a :doc:`command-line script -` (installed as :program:`manila`). Each implements the entire -OpenStack Manila API. See :ref:`project-structure` for more information. +` (the :mod:`manilaclient` module) for programmatic access, and +a command-line interface via the OpenStack CLI client. See +:ref:`project-structure` for more information. You'll need credentials for an OpenStack cloud that implements the Manila API in order to use the manila client. Command-Line Reference ~~~~~~~~~~~~~~~~~~~~~~ -There are two shell implementations in python-manilaclient. - -.. important:: - - The legacy "manila" shell client is deprecated as of version ``5.0.0``. - A future version of python-manilaclient may not ship this legacy shell - client. If you rely on it, it is highly recommended that you begin using - the openstack CLI client right away. Refer to the `mapping guide - `_ to help with this transition. - -The "openstack" CLI client intends to be fully compatible with the manila API: +Use the "openstack" CLI client to interact with the Manila API from the +command line: .. toctree:: :maxdepth: 1 @@ -29,14 +20,6 @@ The "openstack" CLI client intends to be fully compatible with the manila API: cli/osc_plugin_cli cli/decoder -The legacy "manila" client is deprecated and may not support newer API -features: - -.. toctree:: - :maxdepth: 2 - - user/shell - Using the python module ~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/source/user/api.rst b/doc/source/user/api.rst index 8c67f998..49f9e39c 100644 --- a/doc/source/user/api.rst +++ b/doc/source/user/api.rst @@ -14,7 +14,7 @@ token and identify which endpoint you wish to speak to. Once you have done so, you can use the API like so:: >>> from manilaclient import client - >>> manila = client.Client('1', $OS_USER_NAME, $OS_PASSWORD, $OS_TENANT_NAME, $OS_AUTH_URL) + >>> manila = client.Client('2', $OS_USER_NAME, $OS_PASSWORD, $OS_PROJECT_NAME, $OS_AUTH_URL) >>> manila.shares.list() [] >>> share = manila.shares.create(share_proto="nfs", size=1, share_network_id="some_share_network_id") @@ -26,7 +26,7 @@ done so, you can use the API like so:: In addition to creating and deleting shares, the manilaclient can manage share-types, access controls, and more! Using CephFS with Ganesha for NFS -support as an example (assuumes this continues from the above initialization):: +support as an example (assumes this continues from the above initialization):: >>> share_type = client.share_types.create( >>> name="cephfsnfstype", spec_driver_handles_share_servers=False, diff --git a/doc/source/user/shell.rst b/doc/source/user/shell.rst deleted file mode 100644 index 13553ae7..00000000 --- a/doc/source/user/shell.rst +++ /dev/null @@ -1,59 +0,0 @@ -The :program:`manila` shell utility -========================================= - -.. important:: - - This shell client is deprecated as of version ``5.0.0``. A future - version of python-manilaclient may not ship this legacy shell client. If - you rely on it, it is highly recommended that you begin using the - openstack CLI client right away. Refer to the `mapping guide - <../cli/decoder.html>`_ to help with this transition. - -.. program:: manila -.. highlight:: bash - -The :program:`manila` shell utility interacts with the OpenStack Manila API -from the command line. It supports the entirety of the OpenStack Manila API. - -You'll need to provide :program:`manila` with your OpenStack username and API -key. You can do this with the `--os-username`, `--os-password` and -`--os-tenant-name` options, but it's easier to just set them as environment -variables by setting two environment variables: - -.. envvar:: OS_USERNAME or MANILA_USERNAME - - Your OpenStack Manila username. - -.. envvar:: OS_PASSWORD or MANILA_PASSWORD - - Your password. - -.. envvar:: OS_TENANT_NAME or MANILA_PROJECT_ID - - Project for work. - -.. envvar:: OS_AUTH_URL or MANILA_URL - - The OpenStack API server URL. - -.. envvar:: OS_SHARE_API_VERSION - - The OpenStack Shared Filesystems API version. - -For example, in Bash you'd use:: - - export OS_USERNAME=foo - export OS_PASSWORD=bar - export OS_TENANT_NAME=foobarproject - export OS_AUTH_URL=http://... - export OS_SHARE_API_VERSION=2 - -From there, all shell commands take the form:: - - manila [arguments...] - -Run :program:`manila help` to get a full list of all possible commands, -and run :program:`manila help ` to get detailed help for that -command. - -.. program-output:: manila --help diff --git a/manilaclient/__init__.py b/manilaclient/__init__.py index c4d5a667..404b965b 100644 --- a/manilaclient/__init__.py +++ b/manilaclient/__init__.py @@ -32,4 +32,5 @@ API_MAX_VERSION = api_versions.APIVersion(api_versions.MAX_VERSION) API_MIN_VERSION = api_versions.APIVersion(api_versions.MIN_VERSION) API_DEPRECATED_VERSION = api_versions.APIVersion( - api_versions.DEPRECATED_VERSION) + api_versions.DEPRECATED_VERSION +) diff --git a/manilaclient/api_versions.py b/manilaclient/api_versions.py index e6b6f512..d0c8c719 100644 --- a/manilaclient/api_versions.py +++ b/manilaclient/api_versions.py @@ -18,6 +18,8 @@ import re import warnings +from oslo_utils import strutils + import manilaclient from manilaclient.common._i18n import _ from manilaclient.common import cliutils @@ -27,13 +29,13 @@ LOG = logging.getLogger(__name__) -MAX_VERSION = '2.89' +MAX_VERSION = '2.96' MIN_VERSION = '2.0' DEPRECATED_VERSION = '1.0' _VERSIONED_METHOD_MAP = {} -class APIVersion(object): +class APIVersion: """Top level object to support Manila API Versioning. This class represents an API Version with convenience @@ -54,44 +56,57 @@ def __init__(self, version_str=None): self.ver_major = int(match.group(1)) self.ver_minor = int(match.group(2)) else: - msg = _("Invalid format of client version '%s'. " + msg = ( + _( + "Invalid format of client version '%s'. " "Expected format 'X.Y', where X is a major part and Y " - "is a minor part of version.") % version_str + "is a minor part of version." + ) + % version_str + ) raise exceptions.UnsupportedVersion(msg) def __str__(self): """Debug/Logging representation of object.""" - return ("API Version Major: %s, Minor: %s" - % (self.ver_major, self.ver_minor)) + return f"API Version Major: {self.ver_major}, Minor: {self.ver_minor}" def __repr__(self): if self.is_null(): return "" else: - return "" % self.get_string() + return f"" def __lt__(self, other): if not isinstance(other, APIVersion): - raise TypeError(self.TYPE_ERROR_MSG % {"other": other, - "cls": self.__class__}) + raise TypeError( + self.TYPE_ERROR_MSG % {"other": other, "cls": self.__class__} + ) - return ((self.ver_major, self.ver_minor) < - (other.ver_major, other.ver_minor)) + return (self.ver_major, self.ver_minor) < ( + other.ver_major, + other.ver_minor, + ) def __eq__(self, other): if not isinstance(other, APIVersion): - raise TypeError(self.TYPE_ERROR_MSG % {"other": other, - "cls": self.__class__}) + raise TypeError( + self.TYPE_ERROR_MSG % {"other": other, "cls": self.__class__} + ) - return ((self.ver_major, self.ver_minor) == - (other.ver_major, other.ver_minor)) + return (self.ver_major, self.ver_minor) == ( + other.ver_major, + other.ver_minor, + ) def __gt__(self, other): if not isinstance(other, APIVersion): - raise TypeError(self.TYPE_ERROR_MSG % {"other": other, - "cls": self.__class__}) - return ((self.ver_major, self.ver_minor) > - (other.ver_major, other.ver_minor)) + raise TypeError( + self.TYPE_ERROR_MSG % {"other": other, "cls": self.__class__} + ) + return (self.ver_major, self.ver_minor) > ( + other.ver_major, + other.ver_minor, + ) def __le__(self, other): return self < other or self == other @@ -139,15 +154,15 @@ def get_string(self): """String representation of an APIVersion object.""" if self.is_null(): raise ValueError( - _("Null APIVersion cannot be converted to string.")) - return "%s.%s" % (self.ver_major, self.ver_minor) + _("Null APIVersion cannot be converted to string.") + ) + return f"{self.ver_major}.{self.ver_minor}" def get_major_version(self): - return "%s" % self.ver_major - + return f"{self.ver_major}" -class VersionedMethod(object): +class VersionedMethod: def __init__(self, name, start_version, end_version, func): """Versioning information for a single method @@ -164,11 +179,13 @@ def __init__(self, name, start_version, end_version, func): self.func = func def __str__(self): - return ("Version Method %s: min: %s, max: %s" - % (self.name, self.start_version, self.end_version)) + return ( + f"Version Method {self.name}: min: {self.start_version}, " + f"max: {self.end_version}" + ) def __repr__(self): - return "" % self.name + return f"" def check_version_supported(api_version): @@ -176,23 +193,27 @@ def check_version_supported(api_version): :warn Sends warning if version is not supported. """ - if (check_version_matches_min_max(api_version) or - check_version_deprecated(api_version)): + if check_version_matches_min_max(api_version) or check_version_deprecated( + api_version + ): return True return False def check_version_matches_min_max(api_version): """Returns True if the API version is within the supported range.""" - if (not api_version.matches( - manilaclient.API_MIN_VERSION, - manilaclient.API_MAX_VERSION)): - msg = _("Invalid client version '%(version)s'. " - "Current version range is '%(min)s' through " - " '%(max)s'") % { + if not api_version.matches( + manilaclient.API_MIN_VERSION, manilaclient.API_MAX_VERSION + ): + msg = _( + "Invalid client version '%(version)s'. " + "Current version range is '%(min)s' through " + " '%(max)s'" + ) % { "version": api_version.get_string(), "min": manilaclient.API_MIN_VERSION.get_string(), - "max": manilaclient.API_MAX_VERSION.get_string()} + "max": manilaclient.API_MAX_VERSION.get_string(), + } warnings.warn(msg) return False return True @@ -202,7 +223,8 @@ def check_version_deprecated(api_version): """Returns True if API version is deprecated.""" if api_version == manilaclient.API_DEPRECATED_VERSION: msg = _("Client version '%(version)s' is deprecated.") % { - "version": api_version.get_string()} + "version": api_version.get_string() + } warnings.warn(msg) return True return False @@ -211,6 +233,8 @@ def check_version_deprecated(api_version): def get_api_version(version_string): """Returns checked APIVersion object.""" version_string = str(version_string) + if strutils.is_int_like(version_string): + version_string = f"{version_string}.0" api_version = APIVersion(version_string) check_version_supported(api_version) @@ -249,27 +273,29 @@ def discover_version(client, requested_version): :returns: APIVersion """ server_start_version, server_end_version = _get_server_version_range( - client) + client + ) valid_version = requested_version if server_start_version.is_null() and server_end_version.is_null(): - msg = ("Server does not support microversions. Changing server " - "version to %(min_version)s.") + msg = ( + "Server does not support microversions. Changing server " + "version to %(min_version)s." + ) LOG.debug(msg, {"min_version": DEPRECATED_VERSION}) valid_version = APIVersion(DEPRECATED_VERSION) else: valid_version = _validate_requested_version( - requested_version, - server_start_version, - server_end_version) + requested_version, server_start_version, server_end_version + ) _validate_server_version(server_start_version, server_end_version) return valid_version -def _validate_requested_version(requested_version, - server_start_version, - server_end_version): +def _validate_requested_version( + requested_version, server_start_version, server_end_version +): """Validates the requested version. Checks 'requested_version' is within the min/max range supported by the @@ -284,21 +310,34 @@ def _validate_requested_version(requested_version, valid_version = requested_version if not requested_version.matches(server_start_version, server_end_version): if server_end_version <= requested_version: - if (manilaclient.API_MIN_VERSION <= server_end_version and - server_end_version <= manilaclient.API_MAX_VERSION): - msg = _("Requested version %(requested_version)s is " - "not supported. Downgrading requested version " - "to %(server_end_version)s.") - LOG.debug(msg, { - "requested_version": requested_version, - "server_end_version": server_end_version}) + if ( + manilaclient.API_MIN_VERSION <= server_end_version + and server_end_version <= manilaclient.API_MAX_VERSION + ): + msg = _( + "Requested version %(requested_version)s is " + "not supported. Downgrading requested version " + "to %(server_end_version)s." + ) + LOG.debug( + msg, + { + "requested_version": requested_version, + "server_end_version": server_end_version, + }, + ) valid_version = server_end_version else: raise exceptions.UnsupportedVersion( - _("The specified version isn't supported by server. The valid " - "version range is '%(min)s' to '%(max)s'") % { + _( + "The specified version isn't supported by server. " + "The valid version range is '%(min)s' to '%(max)s'" + ) + % { "min": server_start_version.get_string(), - "max": server_end_version.get_string()}) + "max": server_end_version.get_string(), + } + ) return valid_version @@ -316,22 +355,34 @@ def _validate_server_version(server_start_version, server_end_version): """ if manilaclient.API_MIN_VERSION > server_end_version: raise exceptions.UnsupportedVersion( - _("Server's version is too old. The client's valid version range " - "is '%(client_min)s' to '%(client_max)s'. The server valid " - "version range is '%(server_min)s' to '%(server_max)s'.") % { - 'client_min': manilaclient.API_MIN_VERSION.get_string(), - 'client_max': manilaclient.API_MAX_VERSION.get_string(), - 'server_min': server_start_version.get_string(), - 'server_max': server_end_version.get_string()}) + _( + "Server's version is too old. " + "The client's valid version range " + "is '%(client_min)s' to '%(client_max)s'. The server valid " + "version range is '%(server_min)s' to '%(server_max)s'." + ) + % { + 'client_min': manilaclient.API_MIN_VERSION.get_string(), + 'client_max': manilaclient.API_MAX_VERSION.get_string(), + 'server_min': server_start_version.get_string(), + 'server_max': server_end_version.get_string(), + } + ) elif manilaclient.API_MAX_VERSION < server_start_version: raise exceptions.UnsupportedVersion( - _("Server's version is too new. The client's valid version range " - "is '%(client_min)s' to '%(client_max)s'. The server valid " - "version range is '%(server_min)s' to '%(server_max)s'.") % { - 'client_min': manilaclient.API_MIN_VERSION.get_string(), - 'client_max': manilaclient.API_MAX_VERSION.get_string(), - 'server_min': server_start_version.get_string(), - 'server_max': server_end_version.get_string()}) + _( + "Server's version is too new. " + "The client's valid version range " + "is '%(client_min)s' to '%(client_max)s'. The server valid " + "version range is '%(server_min)s' to '%(server_max)s'." + ) + % { + 'client_min': manilaclient.API_MIN_VERSION.get_string(), + 'client_max': manilaclient.API_MAX_VERSION.get_string(), + 'server_min': server_start_version.get_string(), + 'server_max': server_end_version.get_string(), + } + ) def add_versioned_method(versioned_method): @@ -342,8 +393,11 @@ def add_versioned_method(versioned_method): def get_versioned_methods(func_name, api_version=None): versioned_methods = _VERSIONED_METHOD_MAP.get(func_name, []) if api_version and not api_version.is_null(): - return [m for m in versioned_methods - if api_version.matches(m.start_version, m.end_version)] + return [ + m + for m in versioned_methods + if api_version.matches(m.start_version, m.end_version) + ] return versioned_methods @@ -353,11 +407,13 @@ def experimental_api(f): @functools.wraps(f) def _wrapper(*args, **kwargs): client = args[0] - if (isinstance(client, manilaclient.v2.client.Client) or - hasattr(client, 'client')): + if isinstance(client, manilaclient.v2.client.Client) or hasattr( + client, 'client' + ): dh = client.client.default_headers dh[constants.EXPERIMENTAL_HTTP_HEADER] = 'true' return f(*args, **kwargs) + return _wrapper @@ -378,8 +434,9 @@ def wraps(start_version, end_version=MAX_VERSION): def decor(func): func.versioned = True name = utils.get_function_name(func) - versioned_method = VersionedMethod(name, start_version, - end_version, func) + versioned_method = VersionedMethod( + name, start_version, end_version, func + ) add_versioned_method(versioned_method) @functools.wraps(func) @@ -388,11 +445,15 @@ def substitution(obj, *args, **kwargs): if not methods: raise exceptions.UnsupportedVersion( - _("API version '%(version)s' is not supported on " - "'%(method)s' method.") % { + _( + "API version '%(version)s' is not supported on " + "'%(method)s' method." + ) + % { "version": obj.api_version.get_string(), "method": name, - }) + } + ) method = max(methods, key=lambda f: f.start_version) diff --git a/manilaclient/base.py b/manilaclient/base.py index a636a96e..079fc0c5 100644 --- a/manilaclient/base.py +++ b/manilaclient/base.py @@ -25,6 +25,8 @@ import hashlib import os +from oslo_utils import strutils + from manilaclient import api_versions from manilaclient.common import cliutils from manilaclient import exceptions @@ -54,6 +56,7 @@ class Manager(utils.HookableMixin): Managers interact with a particular type of API (shares, snapshots, etc.) and provide CRUD operations for them. """ + resource_class = None def __init__(self, api): @@ -64,8 +67,9 @@ def __init__(self, api): def api_version(self): return self.api.api_version - def _list(self, url, response_key, manager=None, body=None, - return_raw=None): + def _list( + self, url, response_key, manager=None, body=None, return_raw=None + ): """List the collection. :param url: a partial URL, e.g., '/shares' @@ -100,8 +104,9 @@ def _list(self, url, response_key, manager=None, body=None, with self.completion_cache('uuid', obj_class, mode="w"): if return_raw: return data - resource = [obj_class(manager, res, loaded=True) - for res in data if res] + resource = [ + obj_class(manager, res, loaded=True) for res in data if res + ] if 'count' in body: return resource, body['count'] else: @@ -121,16 +126,19 @@ def completion_cache(self, cache_type, obj_class, mode): Delete is not handled because listings are assumed to be performed often enough to keep the cache reasonably up-to-date. """ - base_dir = cliutils.env('manilaclient_UUID_CACHE_DIR', - 'MANILACLIENT_UUID_CACHE_DIR', - default="~/.cache/manilaclient") + base_dir = cliutils.env( + 'manilaclient_UUID_CACHE_DIR', + 'MANILACLIENT_UUID_CACHE_DIR', + default="~/.cache/manilaclient", + ) # NOTE(sirp): Keep separate UUID caches for each username + endpoint # pair username = cliutils.env('OS_USERNAME', 'MANILA_USERNAME') url = cliutils.env('OS_URL', 'MANILA_URL') - uniqifier = hashlib.sha256(username.encode('utf-8') + - url.encode('utf-8')).hexdigest() + uniqifier = hashlib.sha256( + username.encode('utf-8') + url.encode('utf-8') + ).hexdigest() cache_dir = os.path.expanduser(os.path.join(base_dir, uniqifier)) @@ -143,14 +151,14 @@ def completion_cache(self, cache_type, obj_class, mode): pass resource = obj_class.__name__.lower() - filename = "%s-%s-cache" % (resource, cache_type.replace('_', '-')) + filename = "{}-{}-cache".format(resource, cache_type.replace('_', '-')) path = os.path.join(cache_dir, filename) - cache_attr = "_%s_cache" % cache_type + cache_attr = f"_{cache_type}_cache" try: setattr(self, cache_attr, open(path, mode)) - except IOError: + except OSError: # NOTE(kiall): This is typically a permission denied while # attempting to write the cache file. pass @@ -164,10 +172,10 @@ def completion_cache(self, cache_type, obj_class, mode): delattr(self, cache_attr) def write_to_completion_cache(self, cache_type, val): - cache = getattr(self, "_%s_cache" % cache_type, None) + cache = getattr(self, f"_{cache_type}_cache", None) if cache: try: - cache.write("%s\n" % val) + cache.write(f"{val}\n") except UnicodeEncodeError: pass @@ -183,8 +191,11 @@ def _get(self, url, response_key, return_raw=False): def _get_with_base_url(self, url, response_key=None): resp, body = self.api.client.get_with_base_url(url) if response_key: - return [self.resource_class(self, res, loaded=True) - for res in body[response_key] if res] + return [ + self.resource_class(self, res, loaded=True) + for res in body[response_key] + if res + ] else: return self.resource_class(self, body, loaded=True) @@ -215,14 +226,14 @@ def _update(self, url, body, response_key=None, **kwargs): def _build_query_string(self, search_opts): search_opts = search_opts or {} - params = sorted( - [(k, v) for (k, v) in search_opts.items() if v]) - query_string = "?%s" % utils.safe_urlencode(params) if params else '' + params = sorted([(k, v) for (k, v) in search_opts.items() if v]) + query_string = f"?{utils.safe_urlencode(params)}" if params else '' return query_string class ManagerWithFind(Manager): """Like a `Manager`, but with additional `find()`/`findall()` methods.""" + def find(self, **kwargs): """Find a single item with attributes matching ``**kwargs``. @@ -232,7 +243,7 @@ def find(self, **kwargs): matches = self.findall(**kwargs) num_matches = len(matches) if num_matches == 0: - msg = "No %s matching %s." % (self.resource_class.__name__, kwargs) + msg = f"No {self.resource_class.__name__} matching {kwargs}." raise exceptions.NotFound(404, msg) elif num_matches > 1: raise exceptions.NoUniqueMatch @@ -250,16 +261,17 @@ def findall(self, **kwargs): search_opts = {'all_tenants': 1} resources = self.list(search_opts=search_opts) - if ('v2.shares.ShareManager' in str(self.__class__) and - self.api_version >= api_versions.APIVersion("2.69")): - search_opts_2 = {'all_tenants': 1, - 'is_soft_deleted': True} + if 'v2.shares.ShareManager' in str( + self.__class__ + ) and self.api_version >= api_versions.APIVersion("2.69"): + search_opts_2 = {'all_tenants': 1, 'is_soft_deleted': True} shares_soft_deleted = self.list(search_opts=search_opts_2) resources += shares_soft_deleted for obj in resources: try: - if all(getattr(obj, attr) == value - for (attr, value) in searches): + if all( + getattr(obj, attr) == value for (attr, value) in searches + ): found.append(obj) except AttributeError: continue @@ -270,7 +282,7 @@ def list(self, search_opts=None): raise NotImplementedError -class Resource(object): +class Resource: """Base class for OpenStack resources (tenant, user, etc.). This is pretty much just a bag for attributes. @@ -292,11 +304,11 @@ def __init__(self, manager, info, loaded=False): self._loaded = loaded def __repr__(self): - reprkeys = sorted(k - for k in self.__dict__.keys() - if k[0] != '_' and k != 'manager') - info = ", ".join("%s=%s" % (k, getattr(self, k)) for k in reprkeys) - return "<%s %s>" % (self.__class__.__name__, info) + reprkeys = sorted( + k for k in self.__dict__.keys() if k[0] != '_' and k != 'manager' + ) + info = ", ".join(f"{k}={getattr(self, k)}" for k in reprkeys) + return f"<{self.__class__.__name__} {info}>" @property def human_id(self): @@ -308,7 +320,7 @@ def human_id(self): return None def _add_details(self, info): - for (k, v) in info.items(): + for k, v in info.items(): try: setattr(self, k, v) self._info[k] = v @@ -366,7 +378,6 @@ def to_dict(self): class MetadataCapableResource(Resource, metaclass=abc.ABCMeta): - superresource = None def _get_subresource_and_resource(self, superresource): @@ -388,7 +399,8 @@ def get_metadata(self, superresource=None): """ resource, subresource = self._get_subresource_and_resource( - superresource) + superresource + ) return self.manager.get_metadata(resource, subresource=subresource) @@ -403,10 +415,12 @@ def set_metadata(self, metadata, superresource=None): by default """ resource, subresource = self._get_subresource_and_resource( - superresource) + superresource + ) - return self.manager.set_metadata(resource, metadata, - subresource=subresource) + return self.manager.set_metadata( + resource, metadata, subresource=subresource + ) def delete_metadata(self, keys, superresource=None): """Delete specified keys from the given resource. @@ -418,10 +432,12 @@ def delete_metadata(self, keys, superresource=None): by default """ resource, subresource = self._get_subresource_and_resource( - superresource) + superresource + ) - return self.manager.delete_metadata(resource, keys, - subresource=subresource) + return self.manager.delete_metadata( + resource, keys, subresource=subresource + ) def update_all_metadata(self, metadata, superresource=None): """Update all metadata for this resource. @@ -434,11 +450,12 @@ def update_all_metadata(self, metadata, superresource=None): by default """ resource, subresource = self._get_subresource_and_resource( - superresource) + superresource + ) - return self.manager.update_all_metadata(resource, - metadata, - subresource=subresource) + return self.manager.update_all_metadata( + resource, metadata, subresource=subresource + ) class MetadataCapableManager(ManagerWithFind, metaclass=abc.ABCMeta): @@ -458,8 +475,9 @@ def get_metadata(self, resource, subresource=None): subresource = getid(subresource) resource = f"{resource}{self.subresource_path}/{subresource}" - return self._get(f"{self.resource_path}/{resource}/metadata", - "metadata") + return self._get( + f"{self.resource_path}/{resource}/metadata", "metadata" + ) def set_metadata(self, resource, metadata, subresource=None): """Set or update metadata for resource. @@ -475,9 +493,9 @@ def set_metadata(self, resource, metadata, subresource=None): subresource = getid(subresource) resource = f"{resource}{self.subresource_path}/{subresource}" - return self._create(f"{self.resource_path}/{resource}/metadata", - body, - "metadata") + return self._create( + f"{self.resource_path}/{resource}/metadata", body, "metadata" + ) def delete_metadata(self, resource, keys, subresource=None): """Delete specified keys from resource metadata. @@ -508,5 +526,4 @@ def update_all_metadata(self, resource, metadata, subresource=None): subresource = getid(subresource) resource = f"{resource}{self.subresource_path}/{subresource}" - return self._update(f"{self.resource_path}/{resource}/metadata", - body) + return self._update(f"{self.resource_path}/{resource}/metadata", body) diff --git a/manilaclient/client.py b/manilaclient/client.py index 4868e802..f1a708e5 100644 --- a/manilaclient/client.py +++ b/manilaclient/client.py @@ -34,15 +34,15 @@ def get_client_class(version): try: client_path = version_map[str(version)] except (KeyError, ValueError): - msg = "Invalid client version '%s'. must be one of: %s" % ( - (version, ', '.join(version_map))) + msg = "Invalid client version '{}'. must be one of: {}".format( + version, ', '.join(version_map) + ) raise exceptions.UnsupportedVersion(msg) return importutils.import_class(client_path) def Client(client_version, *args, **kwargs): - def _convert_to_api_version(version): """Convert version to an APIVersion object unless it already is one.""" @@ -51,7 +51,8 @@ def _convert_to_api_version(version): else: if version in ('1', '1.0'): api_version = api_versions.APIVersion( - api_versions.DEPRECATED_VERSION) + api_versions.DEPRECATED_VERSION + ) elif version == '2': api_version = api_versions.APIVersion(api_versions.MIN_VERSION) else: @@ -64,6 +65,7 @@ def _convert_to_api_version(version): # Make sure the kwarg api_version is set with an APIVersion object. # 1st choice is to use the incoming kwarg. 2nd choice is the positional. kwargs['api_version'] = _convert_to_api_version( - kwargs.get('api_version', api_version)) + kwargs.get('api_version', api_version) + ) return client_class(*args, **kwargs) diff --git a/manilaclient/common/apiclient/exceptions.py b/manilaclient/common/apiclient/exceptions.py index 71418f72..ef95f0bc 100644 --- a/manilaclient/common/apiclient/exceptions.py +++ b/manilaclient/common/apiclient/exceptions.py @@ -41,87 +41,107 @@ class ClientException(Exception): """The base exception class for all exceptions this library raises.""" + pass class ValidationError(ClientException): """Error in validation on API client side.""" + pass class UnsupportedVersion(ClientException): """User is trying to use an unsupported version of the API.""" + pass class CommandError(ClientException): """Error in CLI tool.""" + pass class AuthorizationFailure(ClientException): """Cannot authorize API client.""" + pass class ConnectionError(ClientException): """Cannot connect to API service.""" + pass class ConnectionRefused(ConnectionError): """Connection refused while trying to connect to API service.""" + pass class AuthPluginOptionsMissing(AuthorizationFailure): """Auth plugin misses some options.""" + def __init__(self, opt_names): - super(AuthPluginOptionsMissing, self).__init__( - _("Authentication failed. Missing options: %s") % - ", ".join(opt_names)) + super().__init__( + _("Authentication failed. Missing options: %s") + % ", ".join(opt_names) + ) self.opt_names = opt_names class AuthSystemNotFound(AuthorizationFailure): """User has specified an AuthSystem that is not installed.""" + def __init__(self, auth_system): - super(AuthSystemNotFound, self).__init__( - _("AuthSystemNotFound: %r") % auth_system) + super().__init__(_("AuthSystemNotFound: %r") % auth_system) self.auth_system = auth_system class NoUniqueMatch(ClientException): """Multiple entities found instead of one.""" + pass class EndpointException(ClientException): """Something is rotten in Service Catalog.""" + pass class EndpointNotFound(EndpointException): """Could not find requested endpoint in Service Catalog.""" + pass class AmbiguousEndpoints(EndpointException): """Found more than one matching endpoint in Service Catalog.""" + def __init__(self, endpoints=None): - super(AmbiguousEndpoints, self).__init__( - _("AmbiguousEndpoints: %r") % endpoints) + super().__init__(_("AmbiguousEndpoints: %r") % endpoints) self.endpoints = endpoints class HttpError(ClientException): """The base exception class for all HTTP exceptions.""" + http_status = 0 message = _("HTTP Error") - def __init__(self, message=None, details=None, - response=None, request_id=None, - url=None, method=None, http_status=None): + def __init__( + self, + message=None, + details=None, + response=None, + request_id=None, + url=None, + method=None, + http_status=None, + ): self.http_status = http_status or self.http_status self.message = message or self.message self.details = details @@ -129,14 +149,15 @@ def __init__(self, message=None, details=None, self.response = response self.url = url self.method = method - formatted_string = "%s (HTTP %s)" % (self.message, self.http_status) + formatted_string = f"{self.message} (HTTP {self.http_status})" if request_id: - formatted_string += " (Request-ID: %s)" % request_id - super(HttpError, self).__init__(formatted_string) + formatted_string += f" (Request-ID: {request_id})" + super().__init__(formatted_string) class HTTPRedirection(HttpError): """HTTP Redirection.""" + message = _("HTTP Redirection") @@ -145,6 +166,7 @@ class HTTPClientError(HttpError): Exception for cases in which the client seems to have erred. """ + message = _("HTTP Client Error") @@ -154,6 +176,7 @@ class HttpServerError(HttpError): Exception for cases in which the server is aware that it has erred or is incapable of performing the request. """ + message = _("HTTP Server Error") @@ -172,6 +195,7 @@ class BadRequest(HTTPClientError): The request cannot be fulfilled due to bad syntax. """ + http_status = 400 message = _("Bad Request") @@ -182,6 +206,7 @@ class Unauthorized(HTTPClientError): Similar to 403 Forbidden, but specifically for use when authentication is required and has failed or has not yet been provided. """ + http_status = 401 message = _("Unauthorized") @@ -191,6 +216,7 @@ class PaymentRequired(HTTPClientError): Reserved for future use. """ + http_status = 402 message = _("Payment Required") @@ -201,6 +227,7 @@ class Forbidden(HTTPClientError): The request was a valid request, but the server is refusing to respond to it. """ + http_status = 403 message = _("Forbidden") @@ -211,6 +238,7 @@ class NotFound(HTTPClientError): The requested resource could not be found but may be available again in the future. """ + http_status = 404 message = _("Not Found") @@ -221,6 +249,7 @@ class MethodNotAllowed(HTTPClientError): A request was made of a resource using a request method not supported by that resource. """ + http_status = 405 message = _("Method Not Allowed") @@ -231,6 +260,7 @@ class NotAcceptable(HTTPClientError): The requested resource is only capable of generating content not acceptable according to the Accept headers sent in the request. """ + http_status = 406 message = _("Not Acceptable") @@ -240,6 +270,7 @@ class ProxyAuthenticationRequired(HTTPClientError): The client must first authenticate itself with the proxy. """ + http_status = 407 message = _("Proxy Authentication Required") @@ -249,6 +280,7 @@ class RequestTimeout(HTTPClientError): The server timed out waiting for the request. """ + http_status = 408 message = _("Request Timeout") @@ -259,6 +291,7 @@ class Conflict(HTTPClientError): Indicates that the request could not be processed because of conflict in the request, such as an edit conflict. """ + http_status = 409 message = _("Conflict") @@ -269,6 +302,7 @@ class Gone(HTTPClientError): Indicates that the resource requested is no longer available and will not be available again. """ + http_status = 410 message = _("Gone") @@ -279,6 +313,7 @@ class LengthRequired(HTTPClientError): The request did not specify the length of its content, which is required by the requested resource. """ + http_status = 411 message = _("Length Required") @@ -289,6 +324,7 @@ class PreconditionFailed(HTTPClientError): The server does not meet one of the preconditions that the requester put on the request. """ + http_status = 412 message = _("Precondition Failed") @@ -298,6 +334,7 @@ class RequestEntityTooLarge(HTTPClientError): The request is larger than the server is willing or able to process. """ + http_status = 413 message = _("Request Entity Too Large") @@ -307,7 +344,7 @@ def __init__(self, *args, **kwargs): except (KeyError, ValueError): self.retry_after = 0 - super(RequestEntityTooLarge, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) class RequestUriTooLong(HTTPClientError): @@ -315,6 +352,7 @@ class RequestUriTooLong(HTTPClientError): The URI provided was too long for the server to process. """ + http_status = 414 message = _("Request-URI Too Long") @@ -325,6 +363,7 @@ class UnsupportedMediaType(HTTPClientError): The request entity has a media type which the server or resource does not support. """ + http_status = 415 message = _("Unsupported Media Type") @@ -335,6 +374,7 @@ class RequestedRangeNotSatisfiable(HTTPClientError): The client has asked for a portion of the file, but the server cannot supply that portion. """ + http_status = 416 message = _("Requested Range Not Satisfiable") @@ -344,6 +384,7 @@ class ExpectationFailed(HTTPClientError): The server cannot meet the requirements of the Expect request-header field. """ + http_status = 417 message = _("Expectation Failed") @@ -354,6 +395,7 @@ class UnprocessableEntity(HTTPClientError): The request was well-formed but was unable to be followed due to semantic errors. """ + http_status = 422 message = _("Unprocessable Entity") @@ -363,6 +405,7 @@ class InternalServerError(HttpServerError): A generic error message, given when no more specific message is suitable. """ + http_status = 500 message = _("Internal Server Error") @@ -374,6 +417,7 @@ class HttpNotImplemented(HttpServerError): The server either does not recognize the request method, or it lacks the ability to fulfill the request. """ + http_status = 501 message = _("Not Implemented") @@ -384,6 +428,7 @@ class BadGateway(HttpServerError): The server was acting as a gateway or proxy and received an invalid response from the upstream server. """ + http_status = 502 message = _("Bad Gateway") @@ -393,6 +438,7 @@ class ServiceUnavailable(HttpServerError): The server is currently unavailable. """ + http_status = 503 message = _("Service Unavailable") @@ -403,6 +449,7 @@ class GatewayTimeout(HttpServerError): The server was acting as a gateway or proxy and did not receive a timely response from the upstream server. """ + http_status = 504 message = _("Gateway Timeout") @@ -412,6 +459,7 @@ class HttpVersionNotSupported(HttpServerError): The server does not support the HTTP protocol version used in the request. """ + http_status = 505 message = _("HTTP Version Not Supported") @@ -456,8 +504,9 @@ def from_response(response, method, url): if isinstance(body, dict): error = body.get(list(body)[0]) if isinstance(error, dict): - kwargs["message"] = (error.get("message") or - error.get("faultstring")) + kwargs["message"] = error.get("message") or error.get( + "faultstring" + ) kwargs["details"] = error.get("details") or str(body) elif content_type.startswith("text/"): kwargs["details"] = response.text diff --git a/manilaclient/common/apiclient/utils.py b/manilaclient/common/apiclient/utils.py index 2b361d85..5b333009 100644 --- a/manilaclient/common/apiclient/utils.py +++ b/manilaclient/common/apiclient/utils.py @@ -27,7 +27,7 @@ def find_resource(manager, name_or_id, **find_args): .. code-block:: python def _find_hypervisor(cs, hypervisor): - #Get a hypervisor by name or ID. + # Get a hypervisor by name or ID. return cliutils.find_resource(cs.hypervisors, hypervisor) """ # first try to get entity as integer id @@ -66,14 +66,19 @@ def _find_hypervisor(cs, hypervisor): kwargs.update(find_args) return manager.find(**kwargs) except exceptions.NotFound: - msg = _("No %(name)s with a name or " - "ID of '%(name_or_id)s' exists.") % \ - {"name": manager.resource_class.__name__.lower(), - "name_or_id": name_or_id} + msg = _( + "No %(name)s with a name or ID of '%(name_or_id)s' exists." + ) % { + "name": manager.resource_class.__name__.lower(), + "name_or_id": name_or_id, + } raise exceptions.CommandError(msg) except exceptions.NoUniqueMatch: - msg = _("Multiple %(name)s matches found for " - "'%(name_or_id)s', use an ID to be more specific.") % \ - {"name": manager.resource_class.__name__.lower(), - "name_or_id": name_or_id} + msg = _( + "Multiple %(name)s matches found for " + "'%(name_or_id)s', use an ID to be more specific." + ) % { + "name": manager.resource_class.__name__.lower(), + "name_or_id": name_or_id, + } raise exceptions.CommandError(msg) diff --git a/manilaclient/common/cliutils.py b/manilaclient/common/cliutils.py index 552653a5..143de946 100644 --- a/manilaclient/common/cliutils.py +++ b/manilaclient/common/cliutils.py @@ -31,10 +31,11 @@ class MissingArgs(Exception): """Supplied arguments are not sufficient for calling a function.""" + def __init__(self, missing): self.missing = missing msg = _("Missing arguments: %s") % ", ".join(missing) - super(MissingArgs, self).__init__(msg) + super().__init__(msg) def validate_args(fn, *args, **kwargs): @@ -56,7 +57,7 @@ def validate_args(fn, *args, **kwargs): argspec = inspect.getfullargspec(fn) num_defaults = len(argspec.defaults or []) - required_args = argspec.args[:len(argspec.args) - num_defaults] + required_args = argspec.args[: len(argspec.args) - num_defaults] def isbound(method): return getattr(method, '__self__', None) is not None @@ -65,7 +66,7 @@ def isbound(method): required_args.pop(0) missing = [arg for arg in required_args if arg not in kwargs] - missing = missing[len(args):] + missing = missing[len(args) :] if missing: raise MissingArgs(missing) @@ -79,9 +80,11 @@ def arg(*args, **kwargs): ... def entity_create(args): ... pass """ + def _decorator(func): add_arg(func, *args, **kwargs) return func + return _decorator @@ -134,8 +137,14 @@ def isunauthenticated(func): return getattr(func, 'unauthenticated', False) -def print_list(objs, fields, formatters=None, sortby_index=0, - mixed_case_fields=None, field_labels=None): +def print_list( + objs, + fields, + formatters=None, + sortby_index=0, + mixed_case_fields=None, + field_labels=None, +): """Print a list or objects as a table, one row per object. :param objs: iterable of :class:`Resource` @@ -151,9 +160,13 @@ def print_list(objs, fields, formatters=None, sortby_index=0, mixed_case_fields = mixed_case_fields or [] field_labels = field_labels or fields if len(field_labels) != len(fields): - raise ValueError(_("Field labels list %(labels)s has different number " - "of elements than fields list %(fields)s"), - {'labels': field_labels, 'fields': fields}) + raise ValueError( + _( + "Field labels list %(labels)s has different number " + "of elements than fields list %(fields)s" + ), + {'labels': field_labels, 'fields': fields}, + ) if sortby_index is None: kwargs = {} @@ -240,9 +253,11 @@ def service_type(stype): def mymethod(f): ... """ + def inner(f): f.service_type = stype return f + return inner @@ -252,7 +267,7 @@ def get_service_type(f): def pretty_choice_list(choices): - return ', '.join("'%s'" % choice for choice in choices) + return ', '.join(f"'{choice}'" for choice in choices) def exit(msg=''): @@ -273,6 +288,5 @@ def convert_dict_list_to_string(data, ignored_keys=None): datum_dict = datum for k, v in datum_dict.items(): if k not in ignored_keys: - data_string += '\n%(k)s = %(v)s' % { - 'k': k, 'v': v} + data_string += f'\n{k} = {v}' return data_string diff --git a/manilaclient/common/constants.py b/manilaclient/common/constants.py index 08e609f9..bb57f52a 100644 --- a/manilaclient/common/constants.py +++ b/manilaclient/common/constants.py @@ -19,14 +19,25 @@ SORT_DIR_VALUES = ('asc', 'desc') SHARE_SORT_KEY_VALUES = ( - 'id', 'status', 'size', 'host', 'share_proto', - 'availability_zone_id', 'availability_zone', - 'user_id', 'project_id', - 'created_at', 'updated_at', - 'display_name', 'name', - 'share_type_id', 'share_type', - 'share_network_id', 'share_network', - 'snapshot_id', 'snapshot', + 'id', + 'status', + 'size', + 'host', + 'share_proto', + 'availability_zone_id', + 'availability_zone', + 'user_id', + 'project_id', + 'created_at', + 'updated_at', + 'display_name', + 'name', + 'share_type_id', + 'share_type', + 'share_network_id', + 'share_network', + 'snapshot_id', + 'snapshot', ) SNAPSHOT_SORT_KEY_VALUES = ( @@ -85,7 +96,7 @@ 'updated_at', 'resource_id', 'resource_type', - 'resource_action' + 'resource_action', 'lock_reason', ) @@ -102,6 +113,14 @@ 'project_id', ) +QOS_TYPE_SORT_KEY_VALUES = ( + 'id', + 'name', + 'created_at', + 'updated_at', +) + + TASK_STATE_MIGRATION_SUCCESS = 'migration_success' TASK_STATE_MIGRATION_ERROR = 'migration_error' TASK_STATE_MIGRATION_CANCELLED = 'migration_cancelled' @@ -119,9 +138,17 @@ EXTENSION_PLUGIN_NAMESPACE = 'manilaclient.common.apiclient.auth' MESSAGE_SORT_KEY_VALUES = ( - 'id', 'project_id', 'request_id', 'resource_type', 'action_id', - 'detail_id', 'resource_id', 'message_level', 'expires_at', - 'request_id', 'created_at' + 'id', + 'project_id', + 'request_id', + 'resource_type', + 'action_id', + 'detail_id', + 'resource_id', + 'message_level', + 'expires_at', + 'request_id', + 'created_at', ) STATUS_AVAILABLE = 'available' @@ -147,11 +174,12 @@ ) # share group types -GROUP_BOOL_SPECS = ( - CONSISTENT_SNAPSHOT_SUPPORT, -) +GROUP_BOOL_SPECS = (CONSISTENT_SNAPSHOT_SUPPORT,) REPLICA_GRADUATION_VERSION = '2.56' REPLICA_PRE_GRADUATION_VERSION = '2.55' SHARE_TRANSFER_VERSION = '2.77' RESOURCE_LOCK_VERSION = '2.81' +QOS_TYPE_VERSION = '2.94' +SHARE_MIGRATION_GRADUATION_VERSION = '2.96' +SHARE_MIGRATION_PRE_GRADUATION_VERSION = '2.95' diff --git a/manilaclient/common/httpclient.py b/manilaclient/common/httpclient.py index d7a79c16..0337cc17 100644 --- a/manilaclient/common/httpclient.py +++ b/manilaclient/common/httpclient.py @@ -32,11 +32,11 @@ try: osprofiler_web = importutils.try_import("osprofiler.web") -except Exception: +except ImportError: pass -class HTTPClient(object): +class HTTPClient: """HTTP Client class used by multiple clients. The imported Requests module caches and reuses objects with the same @@ -45,18 +45,30 @@ class HTTPClient(object): execution. This class is shared by multiple client versions so that the client can be changed to another version during execution. """ + API_VERSION_HEADER = "X-Openstack-Manila-Api-Version" - def __init__(self, endpoint_url, token, user_agent, api_version, - insecure=False, cacert=None, timeout=None, retries=None, - http_log_debug=False, cert=None): + def __init__( + self, + endpoint_url, + token, + user_agent, + api_version, + insecure=False, + cacert=None, + timeout=None, + retries=None, + http_log_debug=False, + cert=None, + ): self.endpoint_url = endpoint_url self.base_url = self._get_base_url(self.endpoint_url) self.retries = int(retries or 0) self.http_log_debug = http_log_debug self.request_options = self._set_request_options( - insecure, cacert, timeout, cert) + insecure, cacert, timeout, cert + ) self.default_headers = { 'X-Auth-Token': token, @@ -85,9 +97,13 @@ def _get_base_url(self, url): """Truncates url and returns base endpoint""" service_endpoint = parse.urlparse(url) service_endpoint_base_path = re.search( - r'(.+?)/v([0-9]+|[0-9]+\.[0-9]+)(/.*|$)', service_endpoint.path) - base_path = (service_endpoint_base_path.group(1) - if service_endpoint_base_path else '') + r'(.+?)/v([0-9]+|[0-9]+\.[0-9]+)(/.*|$)', service_endpoint.path + ) + base_path = ( + service_endpoint_base_path.group(1) + if service_endpoint_base_path + else '' + ) base_url = service_endpoint._replace(path=base_path) return parse.urlunparse(base_url) + '/' @@ -120,7 +136,7 @@ def request(self, url, method, **kwargs): options['data'] = jsonutils.dumps(kwargs['body']) self.log_request(method, url, headers, options.get('data', None)) - resp = requests.request(method, url, headers=headers, **options) + resp = requests.request(method, url, headers=headers, **options) # noqa: S113 self.log_response(resp) body = None @@ -138,15 +154,13 @@ def request(self, url, method, **kwargs): def _cs_request(self, url, method, **kwargs): return self._cs_request_with_retries( - self.endpoint_url + url, - method, - **kwargs) + self.endpoint_url + url, method, **kwargs + ) def _cs_request_base_url(self, url, method, **kwargs): return self._cs_request_with_retries( - self.base_url + url, - method, - **kwargs) + self.base_url + url, method, **kwargs + ) def _cs_request_with_retries(self, url, method, **kwargs): attempts = 0 @@ -156,9 +170,11 @@ def _cs_request_with_retries(self, url, method, **kwargs): try: resp, body = self.request(url, method, **kwargs) return resp, body - except (exceptions.BadRequest, - requests.exceptions.RequestException, - exceptions.ClientException) as e: + except ( + exceptions.BadRequest, + requests.exceptions.RequestException, + exceptions.ClientException, + ) as e: if attempts > self.retries: raise @@ -166,11 +182,9 @@ def _cs_request_with_retries(self, url, method, **kwargs): self._logger.debug( "Failed attempt(%(current)s of %(total)s), " - " retrying in %(sec)s seconds", { - 'current': attempts, - 'total': self.retries, - 'sec': timeout - }) + " retrying in %(sec)s seconds", + {'current': attempts, 'total': self.retries, 'sec': timeout}, + ) sleep(timeout) timeout *= 2 @@ -193,24 +207,26 @@ def log_request(self, method, url, headers, data=None): if not self.http_log_debug: return - string_parts = ['curl -i', ' -X %s' % method, ' %s' % url] + string_parts = ['curl -i', f' -X {method}', f' {url}'] for element in headers: - header = ' -H "%s: %s"' % (element, headers[element]) + header = f' -H "{element}: {headers[element]}"' string_parts.append(header) if data: if "password" in data: data = strutils.mask_password(data) - string_parts.append(" -d '%s'" % data) + string_parts.append(f" -d '{data}'") self._logger.debug("\nREQ: %s\n", "".join(string_parts)) def log_response(self, resp): if not self.http_log_debug: return self._logger.debug( - "RESP: [%(code)s] %(headers)s\nRESP BODY: %(body)s\n", { + "RESP: [%(code)s] %(headers)s\nRESP BODY: %(body)s\n", + { 'code': resp.status_code, 'headers': resp.headers, - 'body': resp.text - }) + 'body': resp.text, + }, + ) diff --git a/manilaclient/config.py b/manilaclient/config.py index 94e41489..a838a6bf 100644 --- a/manilaclient/config.py +++ b/manilaclient/config.py @@ -27,171 +27,255 @@ # directory "%project_root%/manilaclient/tests/functional" auth_opts = [ # Options for user with 'member' role. - cfg.StrOpt("username", - help="This should be the username of a user WITHOUT " - "administrative privileges."), - cfg.StrOpt("tenant_name", - help="The non-administrative user's tenant name."), - cfg.StrOpt("password", - secret=True, - help="The non-administrative user's password."), - cfg.StrOpt("auth_url", - help="URL for where to find the OpenStack Identity public " - "API endpoint."), - cfg.StrOpt("project_domain_name", - help=("Project domain Name of user with 'member' role " - "as specified for auth v3.")), - cfg.StrOpt("project_domain_id", - help=("Project domain ID of user with 'member' role " - "as specified for auth v3.")), - cfg.StrOpt("user_domain_name", - help=("User domain Name of user with 'member' role " - "as specified for auth v3.")), - cfg.StrOpt("user_domain_id", - help=("User domain ID of user with 'member' role " - "as specified for auth v3.")), - + cfg.StrOpt( + "username", + help="This should be the username of a user WITHOUT " + "administrative privileges.", + ), + cfg.StrOpt( + "tenant_name", help="The non-administrative user's tenant name." + ), + cfg.StrOpt( + "password", secret=True, help="The non-administrative user's password." + ), + cfg.StrOpt( + "auth_url", + help="URL for where to find the OpenStack Identity public " + "API endpoint.", + ), + cfg.StrOpt( + "project_domain_name", + help=( + "Project domain Name of user with 'member' role " + "as specified for auth v3." + ), + ), + cfg.StrOpt( + "project_domain_id", + help=( + "Project domain ID of user with 'member' role " + "as specified for auth v3." + ), + ), + cfg.StrOpt( + "user_domain_name", + help=( + "User domain Name of user with 'member' role " + "as specified for auth v3." + ), + ), + cfg.StrOpt( + "user_domain_id", + help=( + "User domain ID of user with 'member' role " + "as specified for auth v3." + ), + ), # Options for user with 'admin' role. - cfg.StrOpt("admin_username", - help="This should be the username of a user WITH " - "administrative privileges."), - cfg.StrOpt("admin_tenant_name", - help="The administrative user's tenant name."), - cfg.StrOpt("admin_password", - secret=True, - help="The administrative user's password."), - cfg.StrOpt("admin_auth_url", - help="URL for where to find the OpenStack Identity admin " - "API endpoint."), - cfg.StrOpt("admin_project_domain_name", - help=("Project domain Name of user with 'admin' role " - "as specified for auth v3.")), - cfg.StrOpt("admin_project_domain_id", - help=("Project domain ID of user with 'admin' role " - "as specified for auth v3.")), - cfg.StrOpt("admin_user_domain_name", - help=("User domain Name of user with 'admin' role " - "as specified for auth v3.")), - cfg.StrOpt("admin_user_domain_id", - help=("User domain ID of user with 'admin' role " - "as specified for auth v3.")), - + cfg.StrOpt( + "admin_username", + help="This should be the username of a user WITH " + "administrative privileges.", + ), + cfg.StrOpt( + "admin_tenant_name", help="The administrative user's tenant name." + ), + cfg.StrOpt( + "admin_password", + secret=True, + help="The administrative user's password.", + ), + cfg.StrOpt( + "admin_auth_url", + help="URL for where to find the OpenStack Identity admin " + "API endpoint.", + ), + cfg.StrOpt( + "admin_project_domain_name", + help=( + "Project domain Name of user with 'admin' role " + "as specified for auth v3." + ), + ), + cfg.StrOpt( + "admin_project_domain_id", + help=( + "Project domain ID of user with 'admin' role " + "as specified for auth v3." + ), + ), + cfg.StrOpt( + "admin_user_domain_name", + help=( + "User domain Name of user with 'admin' role " + "as specified for auth v3." + ), + ), + cfg.StrOpt( + "admin_user_domain_id", + help=( + "User domain ID of user with 'admin' role " + "as specified for auth v3." + ), + ), # Other auth options - cfg.BoolOpt("insecure", - default=False, - help="Disable SSL certificate verification."), + cfg.BoolOpt( + "insecure", default=False, help="Disable SSL certificate verification." + ), ] base_opts = [ - cfg.StrOpt("manila_exec_dir", - default=os.environ.get( - 'OS_MANILA_EXEC_DIR', - os.path.join(os.path.abspath('.'), '.tox/functional/bin')), - help="The path to manilaclient to be executed."), - cfg.BoolOpt("suppress_errors_in_cleanup", - default=True, - help="Whether to suppress errors with clean up operation " - "or not."), + cfg.StrOpt( + "manila_exec_dir", + default=os.environ.get( + 'OS_MANILA_EXEC_DIR', + os.path.join(os.path.abspath('.'), '.tox/functional/bin'), + ), + help="The path to manilaclient to be executed.", + ), + cfg.BoolOpt( + "suppress_errors_in_cleanup", + default=True, + help="Whether to suppress errors with clean up operation or not.", + ), ] share_opts = [ - cfg.StrOpt("min_api_microversion", - default="1.0", - help="The minimum API microversion is configured to be the " - "value of the minimum microversion supported by " - "Manilaclient functional tests. Defaults to 1.0."), - cfg.StrOpt("max_api_microversion", - default=api_versions.MAX_VERSION, - help="The maximum API microversion is configured to be the " - "value of the latest microversion supported by " - "Manilaclient functional tests. Defaults to " - "manilaclient's max supported API microversion."), - cfg.StrOpt("share_network", - help="Share network Name or ID, that will be used for shares. " - "Some backend drivers require a share network for share " - "creation."), - cfg.StrOpt("share_network_subnet", - help="Share network subnet ID. Some backend drivers require a " - "share network for share creation."), - cfg.StrOpt("admin_share_network", - help="Share network Name or ID, that will be used for shares " - "in admin tenant."), - cfg.StrOpt("share_type", - help="Share type Name or ID, that will be used with share " - "creation scheduling. Optional."), - cfg.ListOpt("enable_protocols", - default=["nfs", "cifs"], - help="List of all enabled protocols. The first protocol in " - "the list will be used as the default protocol."), - cfg.IntOpt("build_interval", - default=3, - help="Time in seconds between share availability checks."), - cfg.IntOpt("build_timeout", - default=500, - help="Timeout in seconds to wait for a share to become " - "available."), - cfg.DictOpt('access_types_mapping', - default={'nfs': 'ip', 'cifs': 'ip'}, - help="Dict contains access types mapping to share " - "protocol. It will be used to create access rules " - "for shares. Format: ': ',..." - "Allowed share protocols: nfs, cifs, cephfs, glusterfs, " - "hdfs."), - cfg.DictOpt('access_levels_mapping', - default={'nfs': 'rw ro', 'cifs': 'rw'}, - help="Dict contains access levels mapping to share " - "protocol. It will be used to create access rules for " - "shares. Format: ': ',... " - "Allowed share protocols: nfs, cifs, cephfs, glusterfs, " - "hdfs."), - cfg.StrOpt("username_for_user_rules", - default="stack", - help="Username, that will be used in share access tests for " - "user type of access."), - cfg.StrOpt("replication_type", - default="readable", - choices=["readable", "writable", "dr"], - help="Replication type to be used when running replication " - "tests. This option is ignored if run_replication_tests " - "is set to False."), - cfg.BoolOpt("run_replication_tests", - default=True, - help="Defines whether to run tests for share replication " - "or not. Disable this feature if manila driver used " - "doesn't support share replication."), - cfg.BoolOpt("run_snapshot_tests", - default=True, - help="Defines whether to run tests that use share snapshots " - "or not. Disable this feature if used driver doesn't " - "support it."), - cfg.BoolOpt("run_share_servers_tests", - default=True, - help="Defines whether to run tests that use share servers " - "or not. Disable this feature if used driver doesn't " - "support it or when autodeletion of share servers " - "is enabled."), - cfg.BoolOpt("run_migration_tests", - default=False, - help="Defines whether to run share migration tests or not. " - "Disable this feature if there is no more than one " - "storage pool being tested or if used driver does not " - "support it."), - cfg.BoolOpt("run_mount_snapshot_tests", - default=False, - help="Defines whether to run mountable snapshots tests or " - "not. Disable this feature if used driver doesn't " - "support it."), - cfg.BoolOpt("run_manage_tests", - default=False, - help="Defines whether to run manage/unmanage tests or " - "not. Disable this feature if used driver does not " - "support it."), - cfg.BoolOpt("run_share_servers_migration_tests", - default=False, - help="Defines whether to run share server migration tests or " - "not. Disable this feature if used driver does not " - "support it."), - + cfg.StrOpt( + "min_api_microversion", + default="1.0", + help="The minimum API microversion is configured to be the " + "value of the minimum microversion supported by " + "Manilaclient functional tests. Defaults to 1.0.", + ), + cfg.StrOpt( + "max_api_microversion", + default=api_versions.MAX_VERSION, + help="The maximum API microversion is configured to be the " + "value of the latest microversion supported by " + "Manilaclient functional tests. Defaults to " + "manilaclient's max supported API microversion.", + ), + cfg.StrOpt( + "share_network", + help="Share network Name or ID, that will be used for shares. " + "Some backend drivers require a share network for share " + "creation.", + ), + cfg.StrOpt( + "share_network_subnet", + help="Share network subnet ID. Some backend drivers require a " + "share network for share creation.", + ), + cfg.StrOpt( + "admin_share_network", + help="Share network Name or ID, that will be used for shares " + "in admin tenant.", + ), + cfg.StrOpt( + "share_type", + help="Share type Name or ID, that will be used with share " + "creation scheduling. Optional.", + ), + cfg.ListOpt( + "enable_protocols", + default=["nfs", "cifs"], + help="List of all enabled protocols. The first protocol in " + "the list will be used as the default protocol.", + ), + cfg.IntOpt( + "build_interval", + default=3, + help="Time in seconds between share availability checks.", + ), + cfg.IntOpt( + "build_timeout", + default=500, + help="Timeout in seconds to wait for a share to become available.", + ), + cfg.DictOpt( + 'access_types_mapping', + default={'nfs': 'ip', 'cifs': 'ip'}, + help="Dict contains access types mapping to share " + "protocol. It will be used to create access rules " + "for shares. Format: ': ',..." + "Allowed share protocols: nfs, cifs, cephfs, glusterfs, " + "hdfs.", + ), + cfg.DictOpt( + 'access_levels_mapping', + default={'nfs': 'rw ro', 'cifs': 'rw'}, + help="Dict contains access levels mapping to share " + "protocol. It will be used to create access rules for " + "shares. Format: ': ',... " + "Allowed share protocols: nfs, cifs, cephfs, glusterfs, " + "hdfs.", + ), + cfg.StrOpt( + "username_for_user_rules", + default="stack", + help="Username, that will be used in share access tests for " + "user type of access.", + ), + cfg.StrOpt( + "replication_type", + default="readable", + choices=["readable", "writable", "dr"], + help="Replication type to be used when running replication " + "tests. This option is ignored if run_replication_tests " + "is set to False.", + ), + cfg.BoolOpt( + "run_replication_tests", + default=True, + help="Defines whether to run tests for share replication " + "or not. Disable this feature if manila driver used " + "doesn't support share replication.", + ), + cfg.BoolOpt( + "run_snapshot_tests", + default=True, + help="Defines whether to run tests that use share snapshots " + "or not. Disable this feature if used driver doesn't " + "support it.", + ), + cfg.BoolOpt( + "run_share_servers_tests", + default=True, + help="Defines whether to run tests that use share servers " + "or not. Disable this feature if used driver doesn't " + "support it or when autodeletion of share servers " + "is enabled.", + ), + cfg.BoolOpt( + "run_migration_tests", + default=False, + help="Defines whether to run share migration tests or not. " + "Disable this feature if there is no more than one " + "storage pool being tested or if used driver does not " + "support it.", + ), + cfg.BoolOpt( + "run_mount_snapshot_tests", + default=False, + help="Defines whether to run mountable snapshots tests or " + "not. Disable this feature if used driver doesn't " + "support it.", + ), + cfg.BoolOpt( + "run_manage_tests", + default=False, + help="Defines whether to run manage/unmanage tests or " + "not. Disable this feature if used driver does not " + "support it.", + ), + cfg.BoolOpt( + "run_share_servers_migration_tests", + default=False, + help="Defines whether to run share server migration tests or " + "not. Disable this feature if used driver does not " + "support it.", + ), ] # 2. Generate config @@ -199,16 +283,17 @@ PROJECT_NAME = 'manilaclient' DEFAULT_CONFIG_FILE = ( - os.environ.get('OS_%s_CONFIG_FILE' % PROJECT_NAME.upper()) or - '%s.conf' % PROJECT_NAME) -DEFAULT_CONFIG_DIR = ( - os.environ.get('OS_%s_CONFIG_DIR' % PROJECT_NAME.upper()) or - os.path.join(os.path.abspath(os.path.dirname(os.path.dirname(__file__))), - "etc/manilaclient") + os.environ.get(f'OS_{PROJECT_NAME.upper()}_CONFIG_FILE') + or f'{PROJECT_NAME}.conf' +) +DEFAULT_CONFIG_DIR = os.environ.get( + f'OS_{PROJECT_NAME.upper()}_CONFIG_DIR' +) or os.path.join( + os.path.abspath(os.path.dirname(os.path.dirname(__file__))), + "etc/manilaclient", ) DEFAULT_CONFIG_PATH = os.path.join(DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILE) -FAILOVER_CONFIG_PATH = '/etc/%(pn)s/%(cn)s' % { - 'pn': PROJECT_NAME, 'cn': DEFAULT_CONFIG_FILE} +FAILOVER_CONFIG_PATH = f'/etc/{PROJECT_NAME}/{DEFAULT_CONFIG_FILE}' CONFIG_FILES = [] if os.path.isfile(DEFAULT_CONFIG_PATH): diff --git a/manilaclient/exceptions.py b/manilaclient/exceptions.py index efe3f20b..daeb3a05 100644 --- a/manilaclient/exceptions.py +++ b/manilaclient/exceptions.py @@ -23,7 +23,8 @@ class ManilaclientException(Exception): """A generic client error.""" - message = _("An unexpected error occured.") + + message = _("An unexpected error occurred.") def __init__(self, message): self.message = message or self.message @@ -34,11 +35,13 @@ def __str__(self): class ResourceInErrorState(ManilaclientException): """A resource is in an unexpected 'error' state.""" + message = _("Resource is in error state") class TimeoutException(ManilaclientException): """A request has timed out""" + message = _("Request has timed out") @@ -48,6 +51,7 @@ class NoTokenLookupException(ClientException): # noqa: F405 This form of authentication does not support looking up endpoints from an existing token. """ + pass diff --git a/manilaclient/extension.py b/manilaclient/extension.py index 01529f26..2f7f9d80 100644 --- a/manilaclient/extension.py +++ b/manilaclient/extension.py @@ -36,4 +36,4 @@ def _parse_extension_module(self): self.manager_class = attr_value def __repr__(self): - return "" % self.name + return f"" diff --git a/manilaclient/osc/plugin.py b/manilaclient/osc/plugin.py index 568b2f3f..2009b874 100644 --- a/manilaclient/osc/plugin.py +++ b/manilaclient/osc/plugin.py @@ -32,28 +32,31 @@ LATEST_VERSION = api_versions.MAX_VERSION LATEST_MINOR_VERSION = api_versions.MAX_VERSION.split('.')[-1] - API_VERSIONS = { - '2.%d' % i: CLIENT_CLASS - for i in range(0, int(LATEST_MINOR_VERSION) + 1) + f'2.{i}': CLIENT_CLASS for i in range(0, int(LATEST_MINOR_VERSION) + 1) } def _get_manila_url_from_service_catalog(instance): service_type = constants.SFS_SERVICE_TYPE url = instance.get_endpoint_for_service_type( - constants.SFS_SERVICE_TYPE, region_name=instance._region_name, - interface=instance.interface) + constants.SFS_SERVICE_TYPE, + region_name=instance._region_name, + interface=instance.interface, + ) # Fallback if cloud is using an older service type name if not url: url = instance.get_endpoint_for_service_type( - constants.V2_SERVICE_TYPE, region_name=instance._region_name, - interface=instance.interface) + constants.V2_SERVICE_TYPE, + region_name=instance._region_name, + interface=instance.interface, + ) service_type = constants.V2_SERVICE_TYPE if url is None: raise exceptions.EndpointNotFound( message="Could not find manila / shared-file-system endpoint in " - "the service catalog.") + "the service catalog." + ) return service_type, url @@ -61,39 +64,54 @@ def make_client(instance): """Returns a shared file system service client.""" requested_api_version = instance._api_version[API_NAME] - service_type, manila_endpoint_url = _get_manila_url_from_service_catalog( - instance) + endpoint_override = getattr( + instance._cli_options, 'os_endpoint_override', None + ) + if endpoint_override: + manila_endpoint_url = endpoint_override + service_type = constants.SFS_SERVICE_TYPE + else: + service_type, manila_endpoint_url = ( + _get_manila_url_from_service_catalog(instance) + ) + instance.setup_auth() debugging_enabled = instance._cli_options.debug - client_args = dict(session=instance.session, - service_catalog_url=manila_endpoint_url, - endpoint_type=instance.interface, - region_name=instance.region_name, - service_type=service_type, - auth=instance.auth, - http_log_debug=debugging_enabled, - cacert=instance.cacert, - cert=instance.cert, - insecure=not instance.verify) + client_args = dict( + session=instance.session, + service_catalog_url=manila_endpoint_url, + endpoint_type=instance.interface, + region_name=instance.region_name, + service_type=service_type, + auth=instance.auth, + http_log_debug=debugging_enabled, + cacert=instance.cacert, + cert=instance.cert, + insecure=not instance.verify, + ) # Cast the API version into an object for further processing requested_api_version = api_versions.APIVersion( - version_str=requested_api_version) + version_str=requested_api_version + ) max_version = api_versions.APIVersion(api_versions.MAX_VERSION) client_args.update(dict(api_version=max_version)) temp_client = client.Client(max_version, **client_args) - discovered_version = api_versions.discover_version(temp_client, - requested_api_version) + discovered_version = api_versions.discover_version( + temp_client, requested_api_version + ) shared_file_system_client = utils.get_client_class( - API_NAME, discovered_version.get_string(), API_VERSIONS) + API_NAME, discovered_version.get_string(), API_VERSIONS + ) - LOG.debug('Instantiating Shared File System (share) client: %s', - shared_file_system_client) - LOG.debug('Shared File System API version: %s', - discovered_version) + LOG.debug( + 'Instantiating Shared File System (share) client: %s', + shared_file_system_client, + ) + LOG.debug('Shared File System API version: %s', discovered_version) client_args.update(dict(api_version=discovered_version)) return shared_file_system_client(**client_args) @@ -107,10 +125,25 @@ def build_option_parser(parser): metavar='', default=default_api_version, choices=sorted( - API_VERSIONS, - key=lambda k: [int(x) for x in k.split('.')]), - help='Shared File System API version, default=' + default_api_version + - 'version supported by both the client and the server). ' - '(Env: OS_SHARE_API_VERSION)', + API_VERSIONS, key=lambda k: [int(x) for x in k.split('.')] + ), + help='Shared File System API version, default=' + + default_api_version + + ' (version supported by both the client and the server) ' + '(Env: OS_SHARE_API_VERSION)', + ) + parser.add_argument( + "--os-endpoint-override", + metavar="", + default=utils.env( + "OS_SHARED_FILE_SYSTEM_ENDPOINT_OVERRIDE", + "OS_ENDPOINT_OVERRIDE", + "OS_MANILA_BYPASS_URL", + "MANILACLIENT_BYPASS_URL", + ), + help=( + "Use this API endpoint instead of the Service Catalog. " + "Defaults to env[OS_SHARED_FILE_SYSTEM_ENDPOINT_OVERRIDE]." + ), ) return parser diff --git a/manilaclient/osc/utils.py b/manilaclient/osc/utils.py index abf36c4f..fe7d93db 100644 --- a/manilaclient/osc/utils.py +++ b/manilaclient/osc/utils.py @@ -36,7 +36,7 @@ def extract_key_value_options(pairs): if pairs and len(duplicate_options) > 0: duplicate_str = ', '.join(duplicate_options) - msg = "Following options were duplicated: %s" % duplicate_str + msg = f"Following options were duplicated: {duplicate_str}" raise exceptions.CommandError(msg) return result_dict @@ -46,7 +46,7 @@ def format_properties(properties): formatted_data = [] for item in properties: - formatted_data.append("%s : %s" % (item, properties[item])) + formatted_data.append(f"{item} : {properties[item]}") return "\n".join(formatted_data) @@ -57,7 +57,8 @@ def extract_properties(properties): (key, value) = item.split('=', 1) if key in result_dict: raise exceptions.CommandError( - "Argument '%s' is specified twice." % key) + f"Argument '{key}' is specified twice." + ) else: result_dict[key] = value except ValueError: @@ -67,42 +68,44 @@ def extract_properties(properties): return result_dict -def extract_extra_specs(extra_specs, specs_to_add, - bool_specs=constants.BOOL_SPECS): +def extract_extra_specs( + extra_specs, specs_to_add, bool_specs=constants.BOOL_SPECS +): try: for item in specs_to_add: (key, value) = item.split('=', 1) if key in extra_specs: - msg = ("Argument '%s' value specified twice." % key) + msg = f"Argument '{key}' value specified twice." raise exceptions.CommandError(msg) elif key in bool_specs: if strutils.is_valid_boolstr(value): extra_specs[key] = value.capitalize() else: msg = ( - "Argument '%s' is of boolean " - "type and has invalid value: %s" - % (key, str(value))) + f"Argument '{key}' is of boolean " + f"type and has invalid value: {str(value)}" + ) raise exceptions.CommandError(msg) else: extra_specs[key] = value except ValueError: - msg = LOG.error(_( - "Wrong format: specs should be key=value pairs.")) + msg = _("Wrong format: specs should be key=value pairs.") raise exceptions.CommandError(msg) return extra_specs def extract_group_specs(extra_specs, specs_to_add): - return extract_extra_specs(extra_specs, - specs_to_add, constants.GROUP_BOOL_SPECS) + return extract_extra_specs( + extra_specs, specs_to_add, constants.GROUP_BOOL_SPECS + ) def format_column_headers(columns): column_headers = [] for column in columns: column_headers.append( - column.replace('_', ' ').title().replace('Id', 'ID')) + column.replace('_', ' ').title().replace('Id', 'ID') + ) return column_headers @@ -112,13 +115,15 @@ def format_share_group_type(share_group_type, formatter='table'): is_public = printable_share_group_type.pop('is_public') printable_share_group_type['visibility'] = ( - 'public' if is_public else 'private') + 'public' if is_public else 'private' + ) if formatter == 'table': - printable_share_group_type['group_specs'] = ( - format_properties(share_group_type.group_specs)) - printable_share_group_type['share_types'] = ( - "\n".join(printable_share_group_type['share_types']) + printable_share_group_type['group_specs'] = format_properties( + share_group_type.group_specs + ) + printable_share_group_type['share_types'] = "\n".join( + printable_share_group_type['share_types'] ) return printable_share_group_type diff --git a/manilaclient/osc/v2/availability_zones.py b/manilaclient/osc/v2/availability_zones.py index f8c8c00d..a084e5fc 100644 --- a/manilaclient/osc/v2/availability_zones.py +++ b/manilaclient/osc/v2/availability_zones.py @@ -23,8 +23,7 @@ class ShareAvailabilityZoneList(command.Lister): _description = _("List all availability zones") def get_parser(self, prog_name): - parser = super(ShareAvailabilityZoneList, self).get_parser( - prog_name) + parser = super().get_parser(prog_name) return parser def take_action(self, parsed_args): @@ -33,5 +32,10 @@ def take_action(self, parsed_args): fields = ("Id", "Name", "Created At", "Updated At") - return (fields, (oscutils.get_item_properties - (s, fields) for s in availability_zones)) + return ( + fields, + ( + oscutils.get_item_properties(s, fields) + for s in availability_zones + ), + ) diff --git a/manilaclient/osc/v2/data/manila.csv b/manilaclient/osc/v2/data/manila.csv index dbfeba34..24199a7e 100644 --- a/manilaclient/osc/v2/data/manila.csv +++ b/manilaclient/osc/v2/data/manila.csv @@ -1,3 +1,5 @@ +# NOTE: The legacy "manila" CLI has been removed. This file is maintained +# for historical reference and migration purposes. manila command,openstack command,command description --version,module list,List the client software version absolute-limits,share limits show --absolute,Print a list of absolute limits for a user diff --git a/manilaclient/osc/v2/messages.py b/manilaclient/osc/v2/messages.py index 632c5116..fcf8d3b8 100644 --- a/manilaclient/osc/v2/messages.py +++ b/manilaclient/osc/v2/messages.py @@ -33,21 +33,23 @@ 'detail_id', 'created_at', 'expires_at', - 'request_id' + 'request_id', ] class DeleteMessage(command.Command): """Remove one or more messages.""" + _description = _("Remove one or more messages") def get_parser(self, prog_name): - parser = super(DeleteMessage, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'message', metavar='', nargs='+', - help=_('ID of the message(s).')) + help=_('ID of the message(s).'), + ) return parser def take_action(self, parsed_args): @@ -57,78 +59,98 @@ def take_action(self, parsed_args): for message in parsed_args.message: try: message_ref = apiutils.find_resource( - share_client.messages, - message) + share_client.messages, message + ) share_client.messages.delete(message_ref) except Exception as e: failure_count += 1 - LOG.error(_( - "Delete for message %(message)s failed: %(e)s"), - {'message': message, 'e': e}) + LOG.error( + _("Delete for message %(message)s failed: %(e)s"), + {'message': message, 'e': e}, + ) if failure_count > 0: - raise exceptions.CommandError(_( - "Unable to delete some or all of the specified messages.")) + raise exceptions.CommandError( + _("Unable to delete some or all of the specified messages.") + ) class ListMessage(command.Lister): """Lists all messages.""" + _description = _("Lists all messages") def get_parser(self, prog_name): - parser = super(ListMessage, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( '--resource-id', metavar='', default=None, - help=_('Filters results by a resource uuid. Default=None.')) + help=_('Filters results by a resource uuid. Default=None.'), + ) parser.add_argument( '--resource-type', metavar='', default=None, - help=_('Filters results by a resource type. Default=None. ' - 'Example: "openstack message list --resource-type share"')) + help=_( + 'Filters results by a resource type. Default=None. ' + 'Example: "openstack message list --resource-type share"' + ), + ) parser.add_argument( '--action-id', metavar='', default=None, - help=_('Filters results by action id. Default=None.')) + help=_('Filters results by action id. Default=None.'), + ) parser.add_argument( '--detail-id', metavar='', default=None, - help=_('Filters results by detail id. Default=None.')) + help=_('Filters results by detail id. Default=None.'), + ) parser.add_argument( '--request-id', metavar='', default=None, - help=_('Filters results by request id. Default=None.')) + help=_('Filters results by request id. Default=None.'), + ) parser.add_argument( '--message-level', metavar='', default=None, - help=_('Filters results by the message level. Default=None. ' - 'Example: "openstack message list --message-level ERROR".')) + help=_( + 'Filters results by the message level. Default=None. ' + 'Example: "openstack message list --message-level ERROR".' + ), + ) parser.add_argument( '--limit', metavar='', type=int, default=None, - help=_('Maximum number of messages to return. (Default=None)')) + help=_('Maximum number of messages to return. (Default=None)'), + ) parser.add_argument( '--since', metavar='', default=None, - help=_('Return only user messages created since given date. ' - 'The date format must be conforming to ISO8601. ' - 'Available only for microversion >= 2.52.')) + help=_( + 'Return only user messages created since given date. ' + 'The date format must be conforming to ISO8601. ' + 'Available only for microversion >= 2.52.' + ), + ) parser.add_argument( '--before', metavar='', default=None, - help=_('Return only user messages created before given date. ' - 'The date format must be conforming to ISO8601. ' - 'Available only for microversion >= 2.52.')) + help=_( + 'Return only user messages created before given date. ' + 'The date format must be conforming to ISO8601. ' + 'Available only for microversion >= 2.52.' + ), + ) return parser def take_action(self, parsed_args): @@ -141,14 +163,17 @@ def take_action(self, parsed_args): 'resource_id': parsed_args.resource_id, 'action_id': parsed_args.action_id, 'detail_id': parsed_args.detail_id, - 'message_level': parsed_args.message_level + 'message_level': parsed_args.message_level, } if share_client.api_version < api_versions.APIVersion("2.52"): if getattr(parsed_args, 'since') or getattr(parsed_args, 'before'): - raise exceptions.CommandError(_( - "Filtering messages by 'since' and 'before'" - " is possible only with Manila API version >=2.52")) + raise exceptions.CommandError( + _( + "Filtering messages by 'since' and 'before'" + " is possible only with Manila API version >=2.52" + ) + ) else: search_opts['created_since'] = parsed_args.since search_opts['created_before'] = parsed_args.before @@ -161,30 +186,35 @@ def take_action(self, parsed_args): 'Action ID', 'User Message', 'Detail ID', - 'Created At'] + 'Created At', + ] - return (columns, (oscutils.get_item_properties - (m, columns) for m in messages)) + return ( + columns, + (oscutils.get_item_properties(m, columns) for m in messages), + ) class ShowMessage(command.ShowOne): """Show details about a message.""" + _description = _("Show details about a message") def get_parser(self, prog_name): - parser = super(ShowMessage, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( - 'message', - metavar='', - help=_('ID of the message.')) + 'message', metavar='', help=_('ID of the message.') + ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share message = apiutils.find_resource( - share_client.messages, - parsed_args.message) + share_client.messages, parsed_args.message + ) - return (MESSAGE_ATTRIBUTES, oscutils.get_dict_properties( - message._info, MESSAGE_ATTRIBUTES)) + return ( + MESSAGE_ATTRIBUTES, + oscutils.get_dict_properties(message._info, MESSAGE_ATTRIBUTES), + ) diff --git a/manilaclient/osc/v2/qos_types.py b/manilaclient/osc/v2/qos_types.py new file mode 100644 index 00000000..0b8edc74 --- /dev/null +++ b/manilaclient/osc/v2/qos_types.py @@ -0,0 +1,390 @@ +# Copyright (c) 2025 Cloudification GmbH. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import logging + +from osc_lib.cli import parseractions +from osc_lib.command import command +from osc_lib import exceptions +from osc_lib import utils as oscutils + +from manilaclient.common._i18n import _ +from manilaclient.common.apiclient import utils as apiutils +from manilaclient.common import constants +from manilaclient.osc import utils + +LOG = logging.getLogger(__name__) + +ATTRIBUTES = [ + 'id', + 'name', + 'description', + 'specs', + 'created_at', + 'updated_at', +] + + +def format_qos_type(qos_type, formatter='table'): + specs = qos_type.specs + if formatter == 'table': + qos_type._info.update({'specs': utils.format_properties(specs)}) + else: + qos_type._info.update({'specs': specs}) + return qos_type + + +class CreateQosType(command.ShowOne): + """Create new qos type.""" + + _description = _("Create new qos type") + + def get_parser(self, prog_name): + parser = super().get_parser(prog_name) + parser.add_argument( + 'name', + metavar="", + help=_('QoS type name. This must be unique.'), + ) + parser.add_argument( + "--description", + metavar="", + default=None, + help=_("QoS type description."), + ) + parser.add_argument( + "--spec", + type=str, + metavar='', + action='append', + default=None, + help=_( + "Spec key and value of QoS type that will be" + " used for QoS type creation. OPTIONAL: Default=None." + " Example: --spec qos_type='fixed' --spec peak_iops=300." + ), + ) + return parser + + def take_action(self, parsed_args): + share_client = self.app.client_manager.share + + kwargs = {'name': parsed_args.name} + if parsed_args.description: + kwargs['description'] = parsed_args.description + + if parsed_args.spec: + specs = utils.extract_properties(parsed_args.spec) + kwargs['specs'] = specs + + qos_type = share_client.qos_types.create(**kwargs) + formatted_type = format_qos_type(qos_type, parsed_args.formatter) + + return ( + ATTRIBUTES, + oscutils.get_dict_properties(formatted_type._info, ATTRIBUTES), + ) + + +class DeleteQosType(command.Command): + """Delete a qos type.""" + + _description = _("Delete a qos type") + + def get_parser(self, prog_name): + parser = super().get_parser(prog_name) + parser.add_argument( + 'qos_types', + metavar="", + nargs="+", + help=_("Name or ID of the qos type(s) to delete"), + ) + return parser + + def take_action(self, parsed_args): + share_client = self.app.client_manager.share + result = 0 + + for qos_type in parsed_args.qos_types: + try: + qos_type_obj = apiutils.find_resource( + share_client.qos_types, qos_type + ) + + share_client.qos_types.delete(qos_type_obj) + except Exception as e: + result += 1 + LOG.error( + _( + "Failed to delete qos type with " + "name or ID '%(qos_type)s': %(e)s" + ), + {'qos_type': qos_type, 'e': e}, + ) + + if result > 0: + total = len(parsed_args.qos_types) + msg = _("%(result)s of %(total)s qos types failed to delete.") % { + 'result': result, + 'total': total, + } + raise exceptions.CommandError(msg) + + +class SetQosType(command.Command): + """Set qos type description or specs.""" + + _description = _("Set qos type description or specs") + + def get_parser(self, prog_name): + parser = super().get_parser(prog_name) + parser.add_argument( + 'qos_type', + metavar="", + help=_("Name or ID of the qos type to modify"), + ) + parser.add_argument( + "--description", + metavar="", + default=None, + help=_("New description of qos type."), + ) + parser.add_argument( + "--spec", + type=str, + metavar='', + action='append', + default=None, + help=_( + "Spec key and value of qos type that will be " + "used for QoS type. OPTIONAL: Default=None. For " + "example --spec qos_type='fixed' --spec peak_iops=300" + ), + ) + return parser + + def take_action(self, parsed_args): + share_client = self.app.client_manager.share + + qos_type = apiutils.find_resource( + share_client.qos_types, parsed_args.qos_type + ) + + kwargs = {} + if parsed_args.description: + kwargs['description'] = parsed_args.description + if kwargs: + try: + qos_type.update(**kwargs) + except Exception as e: + raise exceptions.CommandError( + _("Failed to set qos type description: %s") % e + ) + + # These are dict of key=value to be added as qos type specs. + if parsed_args.spec: + specs = utils.extract_properties(parsed_args.spec) + try: + qos_type.set_keys(specs) + except Exception as e: + raise exceptions.CommandError( + _("Failed to set qos type spec: %s") % e + ) + + +class UnsetQosType(command.Command): + """Unset qos type specs.""" + + _description = _("Unset qos type specs") + + def get_parser(self, prog_name): + parser = super().get_parser(prog_name) + parser.add_argument( + 'qos_type', + metavar="", + help=_("Name or ID of the qos type to modify"), + ) + parser.add_argument( + "--description", + action='store_true', + help=_("Unset qos type description."), + ) + parser.add_argument( + '--spec', + metavar='', + action='append', + help=_('Remove specified spec from this qos type'), + ) + return parser + + def take_action(self, parsed_args): + share_client = self.app.client_manager.share + + qos_type = apiutils.find_resource( + share_client.qos_types, parsed_args.qos_type + ) + + kwargs = {} + if parsed_args.description: + kwargs['description'] = None + if kwargs: + try: + qos_type.update(**kwargs) + except Exception as e: + raise exceptions.CommandError( + _("Failed to unset qos type description: %s") % e + ) + + # These are list of keys to be deleted from qos type specs. + if parsed_args.spec: + try: + qos_type.unset_keys(parsed_args.spec) + except Exception as e: + raise exceptions.CommandError( + _("Failed to remove qos type spec: %s") % e + ) + + +class ListQosType(command.Lister): + """List Qos Types.""" + + _description = _("List qos types") + + def get_parser(self, prog_name): + parser = super().get_parser(prog_name) + parser.add_argument( + '--name', + metavar="", + default=None, + help=_('Filter results by name. Default=None.'), + ) + parser.add_argument( + '--description', + metavar="", + default=None, + help=_("Filter results by description. Default=None."), + ) + parser.add_argument( + "--name~", + metavar="", + default=None, + help=_("Filter results matching a qos name pattern. "), + ) + parser.add_argument( + '--description~', + metavar="", + default=None, + help=_("Filter results matching a qos description pattern."), + ) + parser.add_argument( + "--limit", + metavar="", + type=int, + default=None, + action=parseractions.NonNegativeAction, + help=_("Limit the number of qos types returned. Default=None."), + ) + parser.add_argument( + '--offset', + metavar="", + default=None, + help=_('Start position of qos type records listing.'), + ) + parser.add_argument( + '--sort-key', + '--sort_key', + metavar='', + type=str, + default=None, + help=_( + 'Key to be sorted with, available keys are ' + '%(keys)s. Default=None.' + ) + % {'keys': constants.QOS_TYPE_SORT_KEY_VALUES}, + ) + parser.add_argument( + '--sort-dir', + '--sort_dir', + metavar='', + type=str, + default=None, + help=_( + 'Sort direction, available values are ' + '%(dirs)s. OPTIONAL: Default=None.' + ) + % {'dirs': constants.SORT_DIR_VALUES}, + ) + return parser + + def take_action(self, parsed_args): + share_client = self.app.client_manager.share + + search_opts = { + 'name': parsed_args.name, + 'description': parsed_args.description, + 'limit': parsed_args.limit, + 'offset': parsed_args.offset, + } + search_opts['name~'] = getattr(parsed_args, 'name~') + search_opts['description~'] = getattr(parsed_args, 'description~') + + qos_types = share_client.qos_types.list( + search_opts=search_opts, + sort_key=parsed_args.sort_key, + sort_dir=parsed_args.sort_dir, + ) + + formatted_types = [] + for qos_type in qos_types: + formatted_types.append( + format_qos_type(qos_type, parsed_args.formatter) + ) + + values = ( + oscutils.get_dict_properties(s._info, ATTRIBUTES) + for s in formatted_types + ) + + columns = utils.format_column_headers(ATTRIBUTES) + + return (columns, values) + + +class ShowQosType(command.ShowOne): + """Show a qos type.""" + + _description = _("Display qos type details") + + def get_parser(self, prog_name): + parser = super().get_parser(prog_name) + parser.add_argument( + 'qos_type', + metavar="", + help=_("Qos type to display (name or ID)"), + ) + return parser + + def take_action(self, parsed_args): + share_client = self.app.client_manager.share + + qos_type = apiutils.find_resource( + share_client.qos_types, parsed_args.qos_type + ) + + formatted_type = format_qos_type(qos_type, parsed_args.formatter) + + return ( + ATTRIBUTES, + oscutils.get_dict_properties(formatted_type._info, ATTRIBUTES), + ) diff --git a/manilaclient/osc/v2/quotas.py b/manilaclient/osc/v2/quotas.py index bde7d341..c9bd7c32 100644 --- a/manilaclient/osc/v2/quotas.py +++ b/manilaclient/osc/v2/quotas.py @@ -24,123 +24,150 @@ class QuotaSet(command.Command): It can be used to set the default class for all projects. """ - _description = _("Set Quota for a project, or project/user or " - "project/share-type or a class.") + _description = _( + "Set Quota for a project, or project/user or " + "project/share-type or a class." + ) def get_parser(self, prog_name): - parser = super(QuotaSet, self).get_parser(prog_name) + parser = super().get_parser(prog_name) quota_type = parser.add_mutually_exclusive_group() parser.add_argument( 'project', metavar='', - help=_("A project (name/ID) or a class (e.g.: default).") + help=_("A project (name/ID) or a class (e.g.: default)."), ) quota_type.add_argument( '--class', dest='quota_class', action='store_true', default=False, - help=_("Update class quota to all projects. " - "Mutually exclusive with '--user' and '--share-type'.") + help=_( + "Update class quota to all projects. " + "Mutually exclusive with '--user' and '--share-type'." + ), ) quota_type.add_argument( '--user', metavar='', default=None, - help=_("Name or ID of a user to set the quotas for. " - "Mutually exclusive with '--share-type' and '--class'.") + help=_( + "Name or ID of a user to set the quotas for. " + "Mutually exclusive with '--share-type' and '--class'." + ), ) quota_type.add_argument( '--share-type', metavar='', type=str, default=None, - help=_("Name or ID of a share type to set the quotas for. " - "Mutually exclusive with '--user' and '--class'. " - "Available only for microversion >= 2.39") + help=_( + "Name or ID of a share type to set the quotas for. " + "Mutually exclusive with '--user' and '--class'. " + "Available only for microversion >= 2.39" + ), ) parser.add_argument( '--shares', metavar='', type=int, default=None, - help=_('New value for the "shares" quota.') + help=_('New value for the "shares" quota.'), ) parser.add_argument( '--snapshots', metavar='', type=int, default=None, - help=_('New value for the "snapshots" quota.') + help=_('New value for the "snapshots" quota.'), ) parser.add_argument( '--gigabytes', metavar='', type=int, default=None, - help=_('New value for the "gigabytes" quota.') + help=_('New value for the "gigabytes" quota.'), ) parser.add_argument( '--snapshot-gigabytes', metavar='', type=int, default=None, - help=_('New value for the "snapshot-gigabytes" quota.') + help=_('New value for the "snapshot-gigabytes" quota.'), ) parser.add_argument( '--share-networks', metavar='', type=int, default=None, - help=_('New value for the "share-networks" quota.') + help=_('New value for the "share-networks" quota.'), ) parser.add_argument( '--share-groups', metavar='', type=int, default=None, - help=_('New value for the "share-groups" quota. ' - 'Available only for microversion >= 2.40') + help=_( + 'New value for the "share-groups" quota. ' + 'Available only for microversion >= 2.40' + ), ) parser.add_argument( '--share-group-snapshots', metavar='', type=int, default=None, - help=_('New value for the "share-group-snapshots" quota. ' - 'Available only for microversion >= 2.40') + help=_( + 'New value for the "share-group-snapshots" quota. ' + 'Available only for microversion >= 2.40' + ), ) parser.add_argument( '--share-replicas', metavar='', type=int, default=None, - help=_("Number of share replicas. " - "Available only for microversion >= 2.53") + help=_( + "Number of share replicas. " + "Available only for microversion >= 2.53" + ), ) parser.add_argument( '--replica-gigabytes', metavar='', type=int, default=None, - help=_("Capacity of share replicas in total. " - "Available only for microversion >= 2.53") + help=_( + "Capacity of share replicas in total. " + "Available only for microversion >= 2.53" + ), ) parser.add_argument( '--per-share-gigabytes', metavar='', type=int, default=None, - help=_("New value for the 'per-share-gigabytes' quota." - "Available only for microversion >= 2.62") + help=_( + 'New value for the "per-share-gigabytes" quota. ' + 'Available only for microversion >= 2.62' + ), + ) + parser.add_argument( + '--encryption-keys', + metavar='', + type=int, + default=None, + help=_( + 'New value for the "encryption-keys" quota. ' + 'Available only for microversion >= 2.90' + ), ) parser.add_argument( '--force', dest='force', action="store_true", default=None, - help=_('Force update the quota. ' - 'Not applicable for class update.') + help=_('Force update the quota. Not applicable for class update.'), ) return parser @@ -151,8 +178,8 @@ def take_action(self, parsed_args): user_id = None if parsed_args.user: user_id = utils.find_resource( - identity_client.users, - parsed_args.user).id + identity_client.users, parsed_args.user + ).id kwargs = { "shares": parsed_args.shares, @@ -164,122 +191,169 @@ def take_action(self, parsed_args): if parsed_args.share_type is not None: if share_client.api_version < api_versions.APIVersion('2.39'): - raise exceptions.CommandError(_( - "'share type' quotas are available only starting with " - "'2.39' API microversion.")) + raise exceptions.CommandError( + _( + "'share type' quotas are available only starting with " + "'2.39' API microversion." + ) + ) kwargs["share_type"] = parsed_args.share_type if parsed_args.share_groups is not None: if share_client.api_version < api_versions.APIVersion('2.40'): - raise exceptions.CommandError(_( - "'share group' quotas are available only starting with " - "'2.40' API microversion.")) + raise exceptions.CommandError( + _( + "'share group' quotas are available only " + "starting with '2.40' API microversion." + ) + ) kwargs["share_groups"] = parsed_args.share_groups if parsed_args.share_group_snapshots is not None: if share_client.api_version < api_versions.APIVersion('2.40'): - raise exceptions.CommandError(_( - "'share group snapshots' quotas are available only " - "starting with '2.40' API microversion.")) + raise exceptions.CommandError( + _( + "'share group snapshots' quotas are available only " + "starting with '2.40' API microversion." + ) + ) kwargs["share_group_snapshots"] = parsed_args.share_group_snapshots if parsed_args.share_replicas is not None: if share_client.api_version < api_versions.APIVersion('2.53'): - raise exceptions.CommandError(_( - "setting the number of 'share replicas' is available only " - "starting with API microversion '2.53'.")) + raise exceptions.CommandError( + _( + "setting the number of 'share replicas' is available " + "only starting with API microversion '2.53'." + ) + ) kwargs["share_replicas"] = parsed_args.share_replicas if parsed_args.replica_gigabytes is not None: if share_client.api_version < api_versions.APIVersion('2.53'): - raise exceptions.CommandError(_( - "setting the capacity of share replicas in total " - "is available only starting with API microversion '2.53'.") + raise exceptions.CommandError( + _( + "setting the capacity of share replicas in total " + "is available only starting with API microversion " + "'2.53'." + ) ) kwargs["replica_gigabytes"] = parsed_args.replica_gigabytes if parsed_args.per_share_gigabytes is not None: if share_client.api_version < api_versions.APIVersion('2.62'): - raise exceptions.CommandError(_( - "'per share gigabytes' quotas are available only " - "starting with '2.62' API microversion.") + raise exceptions.CommandError( + _( + "'per share gigabytes' quotas are available only " + "starting with '2.62' API microversion." + ) ) kwargs["per_share_gigabytes"] = parsed_args.per_share_gigabytes + if parsed_args.encryption_keys is not None: + if share_client.api_version < api_versions.APIVersion('2.90'): + raise exceptions.CommandError( + _( + "'encryption keys' quotas are available only " + "starting with '2.90' API microversion." + ) + ) + kwargs["encryption_keys"] = parsed_args.encryption_keys if all(value is None for value in kwargs.values()): - raise exceptions.CommandError(_( - "Nothing to set. " - "New quota must be specified to at least one of the following " - "resources: 'shares', 'snapshots', 'gigabytes', " - "'snapshot-gigabytes', 'share-networks', 'share-type', " - "'share-groups', 'share-group-snapshots', 'share-replicas', " - "'replica-gigabytes', 'per-share-gigabytes'")) + raise exceptions.CommandError( + _( + "Nothing to set. " + "New quota must be specified to at least one of the " + "following resources: 'shares', 'snapshots', 'gigabytes', " + "'snapshot-gigabytes', 'share-networks', 'share-type', " + "'share-groups', 'share-group-snapshots', " + "'share-replicas', 'replica-gigabytes', " + "'per-share-gigabytes', 'encryption_keys'" + ) + ) if parsed_args.quota_class: - kwargs.update({ - "class_name": parsed_args.project, - }) + kwargs.update( + { + "class_name": parsed_args.project, + } + ) try: share_client.quota_classes.update(**kwargs) except Exception as e: - raise exceptions.CommandError(_( - "Failed to set quotas for %s class: '%s'") - % (parsed_args.project, e)) + msg = _( + "Failed to set quotas for class '%(project)s': '%(e)s'" + ) + raise exceptions.CommandError( + msg % {'project': parsed_args.project, 'e': e} + ) else: project_id = utils.find_resource( - identity_client.projects, - parsed_args.project).id + identity_client.projects, parsed_args.project + ).id - kwargs.update({ - "tenant_id": project_id, - "force": parsed_args.force, - "user_id": user_id - }) + kwargs.update( + { + "tenant_id": project_id, + "force": parsed_args.force, + "user_id": user_id, + } + ) try: share_client.quotas.update(**kwargs) except Exception as e: - raise exceptions.CommandError(_( - "Failed to set quotas for project '%s' : '%s'") - % (parsed_args.project, e)) + msg = _( + "Failed to set quotas for project '%(project)s': '%(e)s'" + ) + raise exceptions.CommandError( + msg % {'project': parsed_args.project, 'e': e} + ) class QuotaShow(command.ShowOne): """List the quotas for a project or project/user or project/share-type.""" + _description = _("Show Quota") def get_parser(self, prog_name): - parser = super(QuotaShow, self).get_parser(prog_name) + parser = super().get_parser(prog_name) quota_type = parser.add_mutually_exclusive_group() parser.add_argument( 'project', metavar='', - help=_('Name or ID of the project to list quotas for.') + help=_('Name or ID of the project to list quotas for.'), ) quota_type.add_argument( '--user', metavar='', default=None, - help=_("Name or ID of user to list the quotas for. Optional. " - "Mutually exclusive with '--share-type'.") + help=_( + "Name or ID of user to list the quotas for. Optional. " + "Mutually exclusive with '--share-type'." + ), ) quota_type.add_argument( '--share-type', metavar='', type=str, default=None, - help=_("Name or ID of a share type to list the quotas for. " - "Optional. " - "Mutually exclusive with '--user'. " - "Available only for microversion >= 2.39") + help=_( + "Name or ID of a share type to list the quotas for. " + "Optional. " + "Mutually exclusive with '--user'. " + "Available only for microversion >= 2.39" + ), ) parser.add_argument( '--detail', action='store_true', default=False, - help=_('Optional flag to indicate whether to show quota in detail.' - ' Default false, available only for microversion >= 2.25.') + help=_( + 'Optional flag to indicate whether to show quota in detail.' + ' Default false, available only for microversion >= 2.25.' + ), ) parser.add_argument( '--defaults', action='store_true', default=False, - help=_('Show the default quotas for the project.') + help=_('Show the default quotas for the project.'), ) return parser @@ -290,12 +364,12 @@ def take_action(self, parsed_args): user_id = None if parsed_args.user: user_id = utils.find_resource( - identity_client.users, - parsed_args.user).id + identity_client.users, parsed_args.user + ).id project_id = utils.find_resource( - identity_client.projects, - parsed_args.project).id + identity_client.projects, parsed_args.project + ).id quotas = {} if parsed_args.defaults: @@ -308,9 +382,12 @@ def take_action(self, parsed_args): } if parsed_args.share_type is not None: if share_client.api_version < api_versions.APIVersion("2.39"): - raise exceptions.CommandError(_( - "'share type' quotas are available only starting with " - "'2.39' API microversion.")) + raise exceptions.CommandError( + _( + "'share type' quotas are available only " + "starting with '2.39' API microversion." + ) + ) kwargs["share_type"] = parsed_args.share_type quotas = share_client.quotas.get(**kwargs) @@ -319,7 +396,8 @@ def take_action(self, parsed_args): for quota_k, quota_v in sorted(quotas.to_dict().items()): if isinstance(quota_v, dict): quota_v = '\n'.join( - ['%s = %s' % (k, v) for k, v in sorted(quota_v.items())]) + [f'{k} = {v}' for k, v in sorted(quota_v.items())] + ) printable_quotas[quota_k] = quota_v return self.dict2columns(printable_quotas) @@ -334,29 +412,33 @@ class QuotaDelete(command.Command): _description = _("Delete Quota") def get_parser(self, prog_name): - parser = super(QuotaDelete, self).get_parser(prog_name) + parser = super().get_parser(prog_name) quota_type = parser.add_mutually_exclusive_group() parser.add_argument( 'project', metavar='', - help=_('Name or ID of the project to delete quotas for.') + help=_('Name or ID of the project to delete quotas for.'), ) quota_type.add_argument( '--user', metavar='', default=None, - help=_("Name or ID of user to delete the quotas for. Optional. " - "Mutually exclusive with '--share-type'.") + help=_( + "Name or ID of user to delete the quotas for. Optional. " + "Mutually exclusive with '--share-type'." + ), ) quota_type.add_argument( '--share-type', metavar='', type=str, default=None, - help=_("Name or ID of a share type to delete the quotas for. " - "Optional. " - "Mutually exclusive with '--user'. " - "Available only for microversion >= 2.39") + help=_( + "Name or ID of a share type to delete the quotas for. " + "Optional. " + "Mutually exclusive with '--user'. " + "Available only for microversion >= 2.39" + ), ) return parser @@ -367,22 +449,22 @@ def take_action(self, parsed_args): user_id = None if parsed_args.user: user_id = utils.find_resource( - identity_client.users, - parsed_args.user).id + identity_client.users, parsed_args.user + ).id project_id = utils.find_resource( - identity_client.projects, - parsed_args.project).id + identity_client.projects, parsed_args.project + ).id - kwargs = { - "tenant_id": project_id, - "user_id": user_id - } + kwargs = {"tenant_id": project_id, "user_id": user_id} if parsed_args.share_type: if share_client.api_version < api_versions.APIVersion("2.39"): - raise exceptions.CommandError(_( - "'share type' quotas are available only starting with " - "API microversion '2.39'.")) + raise exceptions.CommandError( + _( + "'share type' quotas are available only starting with " + "API microversion '2.39'." + ) + ) kwargs["share_type"] = parsed_args.share_type share_client.quotas.delete(**kwargs) diff --git a/manilaclient/osc/v2/resource_locks.py b/manilaclient/osc/v2/resource_locks.py index 6f0ca873..c262b0fc 100644 --- a/manilaclient/osc/v2/resource_locks.py +++ b/manilaclient/osc/v2/resource_locks.py @@ -48,36 +48,41 @@ RESOURCE_TYPE_MANAGERS = { 'share': 'shares', - 'access_rule': 'share_access_rules' + 'access_rule': 'share_access_rules', } class CreateResourceLock(command.ShowOne): """Create a new resource lock.""" + _description = _("Lock a resource action from occurring on a resource") def get_parser(self, prog_name): - parser = super(CreateResourceLock, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'resource', metavar='', - help='Name or ID of resource to lock.') + help='Name or ID of resource to lock.', + ) parser.add_argument( 'resource_type', metavar='', - help='Type of the resource (e.g.: share, access).') + help='Type of the resource (e.g.: share, access).', + ) parser.add_argument( '--resource-action', '--resource_action', metavar='', default='delete', - help='Action to lock on the resource (default="delete")') + help='Action to lock on the resource (default="delete")', + ) parser.add_argument( '--lock-reason', '--lock_reason', '--reason', metavar='', - help='Reason for the resource lock.') + help='Reason for the resource lock.', + ) return parser def take_action(self, parsed_args): @@ -87,13 +92,14 @@ def take_action(self, parsed_args): raise exceptions.CommandError(_("Unsupported resource type")) res_manager = RESOURCE_TYPE_MANAGERS[resource_type] - resource = osc_utils.find_resource(getattr(share_client, res_manager), - parsed_args.resource) + resource = osc_utils.find_resource( + getattr(share_client, res_manager), parsed_args.resource + ) resource_lock = share_client.resource_locks.create( resource.id, resource_type, parsed_args.resource_action, - parsed_args.lock_reason + parsed_args.lock_reason, ) resource_lock._info.pop('links', None) @@ -103,15 +109,14 @@ def take_action(self, parsed_args): class DeleteResourceLock(command.Command): """Remove one or more resource locks.""" + _description = _("Remove one or more resource locks") def get_parser(self, prog_name): - parser = super(DeleteResourceLock, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( - 'lock', - metavar='', - nargs='+', - help='ID(s) of the lock(s).') + 'lock', metavar='', nargs='+', help='ID(s) of the lock(s).' + ) return parser def take_action(self, parsed_args): @@ -121,50 +126,57 @@ def take_action(self, parsed_args): for lock in parsed_args.lock: try: lock = apiutils.find_resource( - share_client.resource_locks, - lock + share_client.resource_locks, lock ) lock.delete() except Exception as e: failure_count += 1 - LOG.error(_( - "Failed to delete %(lock)s: %(e)s"), - {'lock': lock, 'e': e}) + LOG.error( + _("Failed to delete %(lock)s: %(e)s"), + {'lock': lock, 'e': e}, + ) if failure_count > 0: - raise exceptions.CommandError(_( - "Unable to delete some or all of the specified locks.")) + raise exceptions.CommandError( + _("Unable to delete some or all of the specified locks.") + ) class ListResourceLock(command.Lister): """Lists all resource locks.""" + _description = _("Lists all resource locks") def get_parser(self, prog_name): - parser = super(ListResourceLock, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( '--all-projects', action='store_true', - help=_("Filter resource locks for all projects. (Admin only).") + help=_("Filter resource locks for all projects. (Admin only)."), ) parser.add_argument( '--project', default=None, - help=_("Filter resource locks for specific project by name or ID, " - "combine with --all-projects (Admin only).") + help=_( + "Filter resource locks for specific project by name or ID, " + "combine with --all-projects (Admin only)." + ), ) parser.add_argument( '--user', default=None, - help=_("Filter resource locks for specific user by name or ID, " - "combine with --all-projects to search across projects " - "(Admin only).") + help=_( + "Filter resource locks for specific user by name or ID, " + "combine with --all-projects to search across projects " + "(Admin only)." + ), ) parser.add_argument( '--id', metavar='', default=None, - help='Filter resource locks by ID. Default=None.') + help='Filter resource locks by ID. Default=None.', + ) parser.add_argument( '--resource', '--resource-id', @@ -172,22 +184,24 @@ def get_parser(self, prog_name): default=None, metavar='', dest='resource', - help=_("Filter resource locks for a resource by ID, specify " - "--resource-type to look up by name.") + help=_( + "Filter resource locks for a resource by ID, specify " + "--resource-type to look up by name." + ), ) parser.add_argument( '--resource-type', '--resource_type', default=None, metavar='', - help=_("Filter resource locks by type of resource.") + help=_("Filter resource locks by type of resource."), ) parser.add_argument( '--resource-action', '--resource_action', default=None, metavar='', - help=_("Filter resource locks by resource action.") + help=_("Filter resource locks by resource action."), ) parser.add_argument( @@ -197,52 +211,64 @@ def get_parser(self, prog_name): default=None, choices=['user', 'admin', 'service'], metavar='', - help=_("Filter resource locks by context.") + help=_("Filter resource locks by context."), ) parser.add_argument( '--since', default=None, metavar='', - help=_("Filter resource locks created since given date. " - "The date format must be conforming to ISO8601. ") + help=_( + "Filter resource locks created since given date. " + "The date format must be conforming to ISO8601. " + ), ) parser.add_argument( '--before', default=None, metavar='', - help=_("Filter resource locks created before given date. " - "The date format must be conforming to ISO8601. ") + help=_( + "Filter resource locks created before given date. " + "The date format must be conforming to ISO8601. " + ), ) parser.add_argument( '--limit', metavar='', type=int, default=None, - help=_("Number of resource locks to list. (Default=None)")) + help=_("Number of resource locks to list. (Default=None)"), + ) parser.add_argument( '--offset', metavar="", default=None, help='Starting position of resource lock records ' - 'in a paginated list.') + 'in a paginated list.', + ) parser.add_argument( - '--sort-key', '--sort_key', + '--sort-key', + '--sort_key', metavar='', type=str, default=None, choices=constants.RESOURCE_LOCK_SORT_KEY_VALUES, - help='Key to be sorted, available keys are %(keys)s. ' - 'Default=None.' - % {'keys': constants.RESOURCE_LOCK_SORT_KEY_VALUES}) + help=( + f'Key to be sorted, available keys are ' + f'{constants.RESOURCE_LOCK_SORT_KEY_VALUES}. Default=None.' + ), + ) parser.add_argument( - '--sort-dir', '--sort_dir', + '--sort-dir', + '--sort_dir', metavar='', type=str, default=None, choices=constants.SORT_DIR_VALUES, - help='Sort direction, available values are %(values)s. ' - 'OPTIONAL: Default=None.' % { - 'values': constants.SORT_DIR_VALUES}) + help=( + f'Sort direction, available values are ' + f'{constants.SORT_DIR_VALUES}. OPTIONAL: Default=None.' + ), + ) parser.add_argument( '--detailed', dest='detailed', @@ -251,11 +277,13 @@ def get_parser(self, prog_name): type=int, const=1, default=0, - help="Show detailed information about filtered resource locks.") + help="Show detailed information about filtered resource locks.", + ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share + identity_client = self.app.client_manager.identity columns = ( LOCK_SUMMARY_ATTRIBUTES @@ -270,11 +298,12 @@ def take_action(self, parsed_args): project_id = identity_common.find_project( identity_client, parsed_args.project, - parsed_args.project_domain).id + parsed_args.project_domain, + ).id if parsed_args.user: - user_id = identity_common.find_user(identity_client, - parsed_args.user, - parsed_args.user_domain).id + user_id = identity_common.find_user( + identity_client, parsed_args.user, parsed_args.user_domain + ).id # set all_projects when using project option all_projects = bool(parsed_args.project) or parsed_args.all_projects @@ -286,12 +315,12 @@ def take_action(self, parsed_args): if resource_id is not None: res_manager = RESOURCE_TYPE_MANAGERS[resource_type] resource_id = osc_utils.find_resource( - getattr(share_client, res_manager), - parsed_args.resource + getattr(share_client, res_manager), parsed_args.resource ).id elif resource_id and not uuidutils.is_uuid_like(resource_id): raise exceptions.CommandError( - _("Provide resource ID or specify --resource-type.")) + _("Provide resource ID or specify --resource-type.") + ) search_opts = { 'all_projects': all_projects, @@ -311,60 +340,68 @@ def take_action(self, parsed_args): resource_locks = share_client.resource_locks.list( search_opts=search_opts, sort_key=parsed_args.sort_key, - sort_dir=parsed_args.sort_dir + sort_dir=parsed_args.sort_dir, ) - return (columns, (osc_utils.get_item_properties - (m, columns) for m in resource_locks)) + return ( + columns, + ( + osc_utils.get_item_properties(m, columns) + for m in resource_locks + ), + ) class ShowResourceLock(command.ShowOne): """Show details about a resource lock.""" + _description = _("Show details about a resource lock") def get_parser(self, prog_name): - parser = super(ShowResourceLock, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( - 'lock', - metavar='', - help=_('ID of resource lock to show.')) + 'lock', metavar='', help=_('ID of resource lock to show.') + ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share resource_lock = apiutils.find_resource( - share_client.resource_locks, - parsed_args.lock) + share_client.resource_locks, parsed_args.lock + ) return ( LOCK_DETAIL_ATTRIBUTES, - osc_utils.get_dict_properties(resource_lock._info, - LOCK_DETAIL_ATTRIBUTES) + osc_utils.get_dict_properties( + resource_lock._info, LOCK_DETAIL_ATTRIBUTES + ), ) class SetResourceLock(command.Command): """Set resource lock properties.""" + _description = _("Update resource lock properties") def get_parser(self, prog_name): - parser = super(SetResourceLock, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( - 'lock', - metavar='', - help='ID of lock to update.') + 'lock', metavar='', help='ID of lock to update.' + ) parser.add_argument( '--resource-action', '--resource_action', metavar='', - help='Resource action to set in the resource lock') + help='Resource action to set in the resource lock', + ) parser.add_argument( '--lock-reason', '--lock_reason', '--reason', dest='lock_reason', - help="Reason for the resource lock") + help="Reason for the resource lock", + ) return parser def take_action(self, parsed_args): @@ -377,21 +414,20 @@ def take_action(self, parsed_args): update_kwargs['lock_reason'] = parsed_args.lock_reason if update_kwargs: share_client.resource_locks.update( - parsed_args.lock, - **update_kwargs + parsed_args.lock, **update_kwargs ) class UnsetResourceLock(command.Command): """Unsets a property on a resource lock.""" + _description = _("Remove resource lock properties") def get_parser(self, prog_name): - parser = super(UnsetResourceLock, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( - 'lock', - metavar='', - help='ID of resource lock to update.') + 'lock', metavar='', help='ID of resource lock to update.' + ) parser.add_argument( '--lock-reason', '--lock_reason', @@ -399,7 +435,8 @@ def get_parser(self, prog_name): dest='lock_reason', action='store_true', default=False, - help="Unset the lock reason. (Default=False)") + help="Unset the lock reason. (Default=False)", + ) return parser def take_action(self, parsed_args): @@ -407,6 +444,5 @@ def take_action(self, parsed_args): if parsed_args.lock_reason: share_client.resource_locks.update( - parsed_args.lock, - lock_reason=None + parsed_args.lock, lock_reason=None ) diff --git a/manilaclient/osc/v2/security_services.py b/manilaclient/osc/v2/security_services.py index c8230f14..0daa84c6 100644 --- a/manilaclient/osc/v2/security_services.py +++ b/manilaclient/osc/v2/security_services.py @@ -25,76 +25,85 @@ class CreateShareSecurityService(command.ShowOne): """Create security service used by project.""" + _description = _("Create security service used by project.") def get_parser(self, prog_name): - parser = super(CreateShareSecurityService, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'type', metavar='', default=None, choices=['ldap', 'kerberos', 'active_directory'], - help=_("Security service type. Possible options are: " - "'ldap', 'kerberos', 'active_directory'.") + help=_( + "Security service type. Possible options are: " + "'ldap', 'kerberos', 'active_directory'." + ), ) parser.add_argument( '--dns-ip', metavar='', default=None, - help=_("DNS IP address of the security service used " - "inside project's network.") + help=_( + "DNS IP address of the security service used " + "inside project's network." + ), ) parser.add_argument( '--ou', metavar='', default=None, - help=_("Security service OU (Organizational Unit). " - "Available only for microversion >= 2.44.") + help=_( + "Security service OU (Organizational Unit). " + "Available only for microversion >= 2.44." + ), ) parser.add_argument( '--server', metavar='', default=None, - help=_("Security service IP address or hostname.") + help=_("Security service IP address or hostname."), ) parser.add_argument( '--domain', metavar='', default=None, - help=_("Security service domain.") + help=_("Security service domain."), ) parser.add_argument( '--user', metavar='= 2.76. Can be provided in the " - "place of '--server' but not along with it.") + help=_( + "Default AD site. Available only for " + "microversion >= 2.76. Can be provided in the " + "place of '--server' but not along with it." + ), ) return parser @@ -116,14 +125,16 @@ def take_action(self, parsed_args): elif parsed_args.ou: raise exceptions.CommandError( "Defining a security service Organizational Unit is " - "available only for microversion >= 2.44") + "available only for microversion >= 2.44" + ) if share_client.api_version >= api_versions.APIVersion("2.76"): kwargs['default_ad_site'] = parsed_args.default_ad_site elif parsed_args.default_ad_site: raise exceptions.CommandError( "Defining a security service Default AD site is " - "available only for microversion >= 2.76") + "available only for microversion >= 2.76" + ) if parsed_args.type == 'active_directory': server = parsed_args.server @@ -132,25 +143,28 @@ def take_action(self, parsed_args): raise exceptions.CommandError( "Cannot create security service because both " "server and 'default_ad_site' were provided. " - "Specify either server or 'default_ad_site'.") + "Specify either server or 'default_ad_site'." + ) security_service = share_client.security_services.create( - parsed_args.type, **kwargs) + parsed_args.type, **kwargs + ) return self.dict2columns(security_service._info) class DeleteShareSecurityService(command.Command): """Delete one or more security services.""" + _description = _("Delete one or more security services.") def get_parser(self, prog_name): - parser = super(DeleteShareSecurityService, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'security_service', metavar='', nargs="+", - help=_("Name or ID of the security service(s) to delete.") + help=_("Name or ID of the security service(s) to delete."), ) return parser @@ -161,33 +175,36 @@ def take_action(self, parsed_args): for security_service in parsed_args.security_service: try: security_service_obj = oscutils.find_resource( - share_client.security_services, - security_service) - share_client.security_services.delete( - security_service_obj) + share_client.security_services, security_service + ) + share_client.security_services.delete(security_service_obj) except Exception as e: result += 1 - LOG.error(f"Failed to delete security service with " - f"name or ID {security_service}: {e}") + LOG.error( + f"Failed to delete security service with " + f"name or ID {security_service}: {e}" + ) if result > 0: total = len(parsed_args.security_service) - msg = (f"{result} of {total} security services failed " - f"to be deleted.") + msg = ( + f"{result} of {total} security services failed to be deleted." + ) raise exceptions.CommandError(msg) class ShowShareSecurityService(command.ShowOne): """Show security service.""" + _description = _("Show security service.") def get_parser(self, prog_name): - parser = super(ShowShareSecurityService, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'security_service', metavar='', - help=_("Security service name or ID to show.") + help=_("Security service name or ID to show."), ) return parser @@ -195,85 +212,88 @@ def take_action(self, parsed_args): share_client = self.app.client_manager.share security_service = oscutils.find_resource( - share_client.security_services, - parsed_args.security_service) + share_client.security_services, parsed_args.security_service + ) data = security_service._info if parsed_args.formatter == 'table': if 'share_networks' in data.keys(): - data['share_networks'] = "\n".join( - data['share_networks']) + data['share_networks'] = "\n".join(data['share_networks']) return self.dict2columns(data) class SetShareSecurityService(command.Command): """Set security service.""" + _description = _("Set security service.") def get_parser(self, prog_name): - parser = super(SetShareSecurityService, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'security_service', metavar='', - help=_("Security service name or ID.") + help=_("Security service name or ID."), ) parser.add_argument( '--dns-ip', metavar='', default=None, - help=_("Set DNS IP address used inside project's network.") + help=_("Set DNS IP address used inside project's network."), ) parser.add_argument( '--ou', metavar='', default=None, - help=_("Set security service OU (Organizational Unit). " - "Available only for microversion >= 2.44.") + help=_( + "Set security service OU (Organizational Unit). " + "Available only for microversion >= 2.44." + ), ) parser.add_argument( '--server', metavar='', default=None, - help=_("Set security service IP address or hostname.") + help=_("Set security service IP address or hostname."), ) parser.add_argument( '--domain', metavar='', default=None, - help=_("Set security service domain.") + help=_("Set security service domain."), ) parser.add_argument( '--user', metavar='= 2.76.") + help=_( + "Default AD site. Available only for microversion >= 2.76." + ), ) return parser @@ -281,8 +301,8 @@ def take_action(self, parsed_args): share_client = self.app.client_manager.share security_service = oscutils.find_resource( - share_client.security_services, - parsed_args.security_service) + share_client.security_services, parsed_args.security_service + ) kwargs = { 'dns_ip': parsed_args.dns_ip, @@ -297,16 +317,20 @@ def take_action(self, parsed_args): if share_client.api_version >= api_versions.APIVersion("2.44"): kwargs['ou'] = parsed_args.ou elif parsed_args.ou: - raise exceptions.CommandError(_( - "Setting a security service Organizational Unit is " - "available only for microversion >= 2.44")) + raise exceptions.CommandError( + _( + "Setting a security service Organizational Unit is " + "available only for microversion >= 2.44" + ) + ) if share_client.api_version >= api_versions.APIVersion("2.76"): kwargs['default_ad_site'] = parsed_args.default_ad_site elif parsed_args.default_ad_site: raise exceptions.CommandError( "Defining a security service Default AD site is " - "available only for microversion >= 2.76") + "available only for microversion >= 2.76" + ) if security_service.type == 'active_directory': server = parsed_args.server @@ -315,72 +339,78 @@ def take_action(self, parsed_args): raise exceptions.CommandError( "Cannot set security service because both " "server and 'default_ad_site' were provided. " - "Specify either server or 'default_ad_site'.") + "Specify either server or 'default_ad_site'." + ) try: security_service.update(**kwargs) except Exception as e: raise exceptions.CommandError( - f"One or more set operations failed: {e}") + f"One or more set operations failed: {e}" + ) class UnsetShareSecurityService(command.Command): """Unset security service.""" + _description = _("Unset security service.") def get_parser(self, prog_name): - parser = super(UnsetShareSecurityService, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'security_service', metavar='', - help=_("Security service name or ID.") + help=_("Security service name or ID."), ) parser.add_argument( '--dns-ip', action='store_true', - help=_("Unset DNS IP address used inside project's network.") + help=_("Unset DNS IP address used inside project's network."), ) parser.add_argument( '--ou', action='store_true', - help=_("Unset security service OU (Organizational Unit). " - "Available only for microversion >= 2.44.") + help=_( + "Unset security service OU (Organizational Unit). " + "Available only for microversion >= 2.44." + ), ) parser.add_argument( '--server', action='store_true', - help=_("Unset security service IP address or hostname.") + help=_("Unset security service IP address or hostname."), ) parser.add_argument( '--domain', action='store_true', - help=_("Unset security service domain.") + help=_("Unset security service domain."), ) parser.add_argument( '--user', action='store_true', - help=_("Unset security service user or group used by project.") + help=_("Unset security service user or group used by project."), ) parser.add_argument( '--password', action='store_true', - help=_("Unset password used by user.") + help=_("Unset password used by user."), ) parser.add_argument( '--name', action='store_true', - help=_("Unset security service name.") + help=_("Unset security service name."), ) parser.add_argument( '--description', action='store_true', - help=_("Unset security service description.") + help=_("Unset security service description."), ) parser.add_argument( '--default-ad-site', dest='default_ad_site', action='store_true', - help=_("Default AD site. " - "Available only for microversion >= 2.76.") + help=_( + "Default AD site. Available only for microversion >= 2.76." + ), ) return parser @@ -388,126 +418,155 @@ def take_action(self, parsed_args): share_client = self.app.client_manager.share security_service = oscutils.find_resource( - share_client.security_services, - parsed_args.security_service) + share_client.security_services, parsed_args.security_service + ) kwargs = {} - args = ['dns_ip', 'server', 'domain', 'user', 'password', - 'name', 'description'] + args = [ + 'dns_ip', + 'server', + 'domain', + 'user', + 'password', + 'name', + 'description', + ] for arg in args: if getattr(parsed_args, arg): # the SDK unsets a value if it is an empty string kwargs[arg] = '' - if (parsed_args.ou and - share_client.api_version >= api_versions.APIVersion("2.44")): + if ( + parsed_args.ou + and share_client.api_version >= api_versions.APIVersion("2.44") + ): # the SDK unsets a value if it is an empty string kwargs['ou'] = '' elif parsed_args.ou: - raise exceptions.CommandError(_( - "Unsetting a security service Organizational Unit is " - "available only for microversion >= 2.44")) - - if (parsed_args.default_ad_site and - share_client.api_version >= api_versions.APIVersion("2.76")): + raise exceptions.CommandError( + _( + "Unsetting a security service Organizational Unit is " + "available only for microversion >= 2.44" + ) + ) + + if ( + parsed_args.default_ad_site + and share_client.api_version >= api_versions.APIVersion("2.76") + ): # the SDK unsets a value if it is an empty string kwargs['default_ad_site'] = '' elif parsed_args.default_ad_site: - raise exceptions.CommandError(_( - "Unsetting a security service Default AD site is " - "available only for microversion >= 2.76")) + raise exceptions.CommandError( + _( + "Unsetting a security service Default AD site is " + "available only for microversion >= 2.76" + ) + ) try: security_service.update(**kwargs) except Exception as e: raise exceptions.CommandError( - f"One or more unset operations failed: {e}") + f"One or more unset operations failed: {e}" + ) class ListShareSecurityService(command.Lister): """List security services.""" + _description = _("List security services.") def get_parser(self, prog_name): - parser = super(ListShareSecurityService, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( '--all-projects', action='store_true', - help=_("Display information from all projects (Admin only).") + help=_("Display information from all projects (Admin only)."), ) parser.add_argument( '--share-network', metavar='', default=None, - help=_("Filter results by share network name or ID.") + help=_("Filter results by share network name or ID."), ) parser.add_argument( '--status', metavar='', default=None, - help=_("Filter results by status.") + help=_("Filter results by status."), ) parser.add_argument( '--name', metavar='', default=None, - help=_("Filter results by security service name.") + help=_("Filter results by security service name."), ) parser.add_argument( '--type', metavar='', default=None, - help=_("Filter results by security service type.") + help=_("Filter results by security service type."), ) parser.add_argument( '--user', metavar='= 2.44.") + help=_( + "Filter results by security service OU " + "(Organizational Unit). " + "Available only for microversion >= 2.44." + ), ) parser.add_argument( '--default-ad-site', metavar='', dest='default_ad_site', default=None, - help=_("Filter results by security service default_ad_site. " - "Available only for microversion >= 2.76.") + help=_( + "Filter results by security service default_ad_site. " + "Available only for microversion >= 2.76." + ), ) parser.add_argument( '--server', metavar='', default=None, - help=_("Filter results by security service IP " - "address or hostname.") + help=_( + "Filter results by security service IP address or hostname." + ), ) parser.add_argument( '--domain', metavar='', default=None, - help=_("Filter results by security service domain.") + help=_("Filter results by security service domain."), ) parser.add_argument( '--detail', action='store_true', - help=_("Show detailed information about filtered " - "security services.") + help=_( + "Show detailed information about filtered security services." + ), ) parser.add_argument( "--limit", @@ -515,12 +574,12 @@ def get_parser(self, prog_name): type=int, default=None, action=parseractions.NonNegativeAction, - help=_("Limit the number of security services returned") + help=_("Limit the number of security services returned"), ) parser.add_argument( "--marker", metavar="", - help=_("The last security service ID of the previous page") + help=_("The last security service ID of the previous page"), ) return parser @@ -548,34 +607,43 @@ def take_action(self, parsed_args): 'limit': parsed_args.limit, } - if (parsed_args.ou and - share_client.api_version >= api_versions.APIVersion("2.44")): + if ( + parsed_args.ou + and share_client.api_version >= api_versions.APIVersion("2.44") + ): search_opts['ou'] = parsed_args.ou elif parsed_args.ou: - raise exceptions.CommandError(_( - "Filtering results by security service Organizational Unit is " - "available only for microversion >= 2.44")) - - if (parsed_args.default_ad_site and - share_client.api_version >= api_versions.APIVersion("2.76")): + raise exceptions.CommandError( + _( + "Filtering results by security service Organizational " + "Unit is available only for microversion >= 2.44" + ) + ) + + if ( + parsed_args.default_ad_site + and share_client.api_version >= api_versions.APIVersion("2.76") + ): search_opts['default_ad_site'] = parsed_args.default_ad_site elif parsed_args.default_ad_site: - raise exceptions.CommandError(_( - "Filtering results by security service Default AD site is " - "available only for microversion >= 2.76")) + raise exceptions.CommandError( + _( + "Filtering results by security service Default AD site is " + "available only for microversion >= 2.76" + ) + ) if parsed_args.share_network: search_opts['share_network_id'] = oscutils.find_resource( - share_client.share_networks, - parsed_args.share_network).id + share_client.share_networks, parsed_args.share_network + ).id data = share_client.security_services.list( - search_opts=search_opts, - detailed=parsed_args.detail + search_opts=search_opts, detailed=parsed_args.detail ) return ( columns, - (oscutils.get_item_properties(s, columns) for s in data) + (oscutils.get_item_properties(s, columns) for s in data), ) diff --git a/manilaclient/osc/v2/services.py b/manilaclient/osc/v2/services.py index 68e55cee..757eeca4 100644 --- a/manilaclient/osc/v2/services.py +++ b/manilaclient/osc/v2/services.py @@ -19,20 +19,23 @@ class SetShareService(command.Command): """Enable/disable share service (Admin only).""" + _description = _("Enable/Disable share service (Admin only).") def get_parser(self, prog_name): - parser = super(SetShareService, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'host', metavar='', - help=_("Host name as 'example_host@example_backend'.") + help=_("Host name as 'example_host@example_backend'."), ) parser.add_argument( 'binary', metavar='', - help=_("Service binary, could be 'manila-share', " - "'manila-scheduler' or 'manila-data'") + help=_( + "Service binary, could be 'manila-share', " + "'manila-scheduler' or 'manila-data'" + ), ) enable_group = parser.add_mutually_exclusive_group() enable_group.add_argument( @@ -48,15 +51,19 @@ def get_parser(self, prog_name): parser.add_argument( "--disable-reason", metavar="", - help=_("Reason for disabling the service " - "(should be used with --disable option)") + help=_( + "Reason for disabling the service " + "(should be used with --disable option)" + ), ) return parser def take_action(self, parsed_args): if parsed_args.disable_reason and not parsed_args.disable: - msg = _("Cannot specify option --disable-reason without " - "--disable specified.") + msg = _( + "Cannot specify option --disable-reason without " + "--disable specified." + ) raise exceptions.CommandError(msg) share_client = self.app.client_manager.share @@ -64,66 +71,79 @@ def take_action(self, parsed_args): if parsed_args.enable: try: share_client.services.enable( - parsed_args.host, parsed_args.binary) + parsed_args.host, parsed_args.binary + ) except Exception as e: - raise exceptions.CommandError(_( - "Failed to enable service: %s" % e)) + msg = _("Failed to enable service: %(e)s") + raise exceptions.CommandError(msg % {'e': e}) if parsed_args.disable: if parsed_args.disable_reason: if share_client.api_version < api_versions.APIVersion("2.83"): raise exceptions.CommandError( "Service disable reason can be specified only with " - "manila API version >= 2.83") + "manila API version >= 2.83" + ) try: if parsed_args.disable_reason: share_client.services.disable( - parsed_args.host, parsed_args.binary, - disable_reason=parsed_args.disable_reason) + parsed_args.host, + parsed_args.binary, + disable_reason=parsed_args.disable_reason, + ) else: share_client.services.disable( - parsed_args.host, parsed_args.binary) + parsed_args.host, parsed_args.binary + ) except Exception as e: - raise exceptions.CommandError(_( - "Failed to disable service: %s" % e)) + msg = _("Failed to disable service: %(e)s") + raise exceptions.CommandError(msg % {'e': e}) class ListShareService(command.Lister): """List share services (Admin only).""" + _description = _("List share services (Admin only).") def get_parser(self, prog_name): - parser = super(ListShareService, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "--host", metavar="", default=None, - help=_("Filter services by name of the host.") + help=_("Filter services by name of the host."), ) parser.add_argument( "--binary", metavar="", default=None, - help=_("Filter services by the name of the service.") + help=_("Filter services by the name of the service."), ) parser.add_argument( "--status", metavar="", default=None, - help=_("Filter results by status.") + help=_("Filter results by status."), ) parser.add_argument( "--state", metavar="", default=None, choices=['up', 'down'], - help=_("Filter results by state.") + help=_("Filter results by state."), ) parser.add_argument( "--zone", metavar="", default=None, - help=_("Filter services by their availability zone.") + help=_("Filter services by their availability zone."), + ) + parser.add_argument( + "--ensuring", + metavar="", + choices=['True', 'False'], + default=None, + help=_("Filter services running ensure shares or not."), ) return parser @@ -137,6 +157,14 @@ def take_action(self, parsed_args): 'state': parsed_args.state, 'zone': parsed_args.zone, } + if parsed_args.ensuring: + if share_client.api_version < api_versions.APIVersion("2.93"): + raise exceptions.CommandError( + "Filtering services whether they are running ensure " + "shares or not is only supported by manila API version " + ">= 2.93" + ) + search_opts['ensuring'] = parsed_args.ensuring services = share_client.services.list(search_opts=search_opts) @@ -147,30 +175,34 @@ def take_action(self, parsed_args): 'Zone', 'Status', 'State', - 'Updated At' + 'Updated At', ] if share_client.api_version >= api_versions.APIVersion("2.83"): columns.append('Disabled Reason') - if share_client.api_version >= api_versions.APIVersion("2.86"): + if share_client.api_version >= api_versions.APIVersion("2.93"): columns.append('Ensuring') - data = (osc_utils.get_dict_properties( - service._info, columns) for service in services) + data = ( + osc_utils.get_dict_properties(service._info, columns) + for service in services + ) return (columns, data) class EnsureShareService(command.Command): """Run ensure shares in a back end (Admin only).""" + _description = _("Run ensure shares in a back end (Admin only).") def get_parser(self, prog_name): - parser = super(EnsureShareService, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'host', metavar='', - help=_("Host to run ensure shares. " - "'example_host@example_backend'.") + help=_( + "Host to run ensure shares. 'example_host@example_backend'." + ), ) return parser @@ -180,11 +212,11 @@ def take_action(self, parsed_args): if share_client.api_version < api_versions.APIVersion("2.86"): raise exceptions.CommandError( "Ensure shares API is only available in " - "manila API version >= 2.86") + "manila API version >= 2.86" + ) try: share_client.services.ensure_shares(parsed_args.host) except Exception as e: - raise exceptions.CommandError( - _("Failed to run ensure shares: %s" % e) - ) + msg = _("Failed to ensure shares: %(e)s") + raise exceptions.CommandError(msg % {'e': e}) diff --git a/manilaclient/osc/v2/share.py b/manilaclient/osc/v2/share.py index 57f5e635..c32e9ce2 100644 --- a/manilaclient/osc/v2/share.py +++ b/manilaclient/osc/v2/share.py @@ -58,7 +58,8 @@ 'replication_type', 'has_replicas', 'created_at', - 'metadata' + 'metadata', + 'encryption_key_ref', ] SHARE_ATTRIBUTES_HEADERS = [ @@ -90,38 +91,38 @@ 'Has Replicas', 'Created At', 'Properties', + 'Encryption Key Ref', ] class CreateShare(command.ShowOne): """Create a new share.""" + _description = _("Create new share") def get_parser(self, prog_name): - parser = super(CreateShare, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'share_proto', metavar="", - help=_('Share protocol (NFS, CIFS, CephFS, GlusterFS or HDFS)') + help=_('Share protocol (NFS, CIFS, CephFS, GlusterFS or HDFS)'), ) parser.add_argument( - 'size', - metavar="", - type=int, - help=_('Share size in GiB.') + 'size', metavar="", type=int, help=_('Share size in GiB.') ) parser.add_argument( '--name', metavar="", default=None, - help=_('Optional share name. (Default=None)') + help=_('Optional share name. (Default=None)'), ) parser.add_argument( '--snapshot-id', metavar="", default=None, - help=_("Optional snapshot ID to create the share from." - " (Default=None)") + help=_( + "Optional snapshot ID to create the share from. (Default=None)" + ), ) # NOTE(vkmc) --property replaces --metadata in osc parser.add_argument( @@ -129,8 +130,10 @@ def get_parser(self, prog_name): metavar="", default={}, action=parseractions.KeyValueAction, - help=_("Set a property to this share " - "(repeat option to set multiple properties)"), + help=_( + "Set a property to this share " + "(repeat option to set multiple properties)" + ), ) parser.add_argument( '--share-network', @@ -142,58 +145,78 @@ def get_parser(self, prog_name): '--description', metavar='', default=None, - help=_('Optional share description. (Default=None)') + help=_('Optional share description. (Default=None)'), ) parser.add_argument( '--public', metavar='', default=False, - help=_('Level of visibility for share. ' - 'Defines whether other tenants are able to see it or not. ' - '(Default = False)') + help=_( + 'Level of visibility for share. ' + 'Defines whether other tenants are able to see it or not. ' + '(Default = False)' + ), ) parser.add_argument( '--share-type', metavar='', default=None, - help=_('The share type to create the share with. If not ' - 'specified, unless creating from a snapshot, the default ' - 'share type will be used.') + help=_( + 'The share type to create the share with. If not ' + 'specified, unless creating from a snapshot, the default ' + 'share type will be used.' + ), ) parser.add_argument( '--availability-zone', metavar='', default=None, - help=_('Availability zone in which share should be created.') + help=_('Availability zone in which share should be created.'), ) parser.add_argument( '--share-group', metavar='', default=None, - help=_('Optional share group name or ID in which to create ' - 'the share. (Default=None).') + help=_( + 'Optional share group name or ID in which to create ' + 'the share. (Default=None).' + ), ) parser.add_argument( '--wait', action='store_true', default=False, - help=_('Wait for share creation') + help=_('Wait for share creation'), ) parser.add_argument( "--scheduler-hint", metavar="", default={}, action=parseractions.KeyValueAction, - help=_("Set Scheduler hints for the share as key=value pairs, " - "possible keys are same_host, different_host." - "(repeat option to set multiple hints)"), + help=_( + "Set Scheduler hints for the share as key=value pairs, " + "possible keys are same_host, different_host. " + "(repeat option to set multiple hints)" + ), ) parser.add_argument( '--mount-point-name', metavar="", default=None, - help=_('Optional custom export location. Available for ' - 'microversion >= 2.84') + help=_( + 'Optional custom export location. Available for ' + 'microversion >= 2.84' + ), + ) + parser.add_argument( + '--encryption-key-ref', + metavar="", + default=None, + help=_( + 'Set encryption key reference i.e. UUID of the secret ' + 'stored in the key manager. Available for ' + 'microversion >= 2.90' + ), ) return parser @@ -204,38 +227,45 @@ def take_action(self, parsed_args): if parsed_args.name: if parsed_args.name.capitalize() == 'None': raise apiclient_exceptions.CommandError( - "Share name cannot be with the value 'None'") + "Share name cannot be with the value 'None'" + ) share_type = None if parsed_args.share_type: - share_type = apiutils.find_resource(share_client.share_types, - parsed_args.share_type).id + share_type = apiutils.find_resource( + share_client.share_types, parsed_args.share_type + ).id elif not parsed_args.snapshot_id: try: share_type = share_client.share_types.get( - share_type='default').id + share_type='default' + ).id except apiclient_exceptions.CommandError: - msg = ("There is no default share type available. You must " - "pick a valid share type to create a share.") + msg = ( + "There is no default share type available. You must " + "pick a valid share type to create a share." + ) raise exceptions.CommandError(msg) share_network = None if parsed_args.share_network: share_network = apiutils.find_resource( - share_client.share_networks, - parsed_args.share_network).id + share_client.share_networks, parsed_args.share_network + ).id share_group = None if parsed_args.share_group: - share_group = apiutils.find_resource(share_client.share_groups, - parsed_args.share_group).id + share_group = apiutils.find_resource( + share_client.share_groups, parsed_args.share_group + ).id size = parsed_args.size snapshot_id = None if parsed_args.snapshot_id: - snapshot = apiutils.find_resource(share_client.share_snapshots, - parsed_args.snapshot_id) + snapshot = apiutils.find_resource( + share_client.share_snapshots, parsed_args.snapshot_id + ) snapshot_id = snapshot.id size = max(size or 0, snapshot.size) @@ -244,36 +274,52 @@ def take_action(self, parsed_args): if share_client.api_version < api_versions.APIVersion('2.84'): raise exceptions.CommandError( 'Setting share mount point name is ' - 'available only for API microversion >= 2.84') + 'available only for API microversion >= 2.84' + ) else: mount_point_name = parsed_args.mount_point_name + encryption_key_ref = None + if parsed_args.encryption_key_ref: + if share_client.api_version < api_versions.APIVersion('2.90'): + raise exceptions.CommandError( + 'Setting share encryption key reference is ' + 'available only for API microversion >= 2.90' + ) + else: + encryption_key_ref = parsed_args.encryption_key_ref + scheduler_hints = {} if parsed_args.scheduler_hint: if share_client.api_version < api_versions.APIVersion('2.65'): raise exceptions.CommandError( 'Setting share scheduler hints for a share is ' - 'available only for API microversion >= 2.65') + 'available only for API microversion >= 2.65' + ) else: scheduler_hints = utils.extract_key_value_options( - parsed_args.scheduler_hint) + parsed_args.scheduler_hint + ) same_host_hint_shares = scheduler_hints.get('same_host') different_host_hint_shares = scheduler_hints.get( - 'different_host') + 'different_host' + ) if same_host_hint_shares: same_host_hint_shares = [ apiutils.find_resource(share_client.shares, sh).id for sh in same_host_hint_shares.split(',') ] - scheduler_hints['same_host'] = ( - ','.join(same_host_hint_shares)) + scheduler_hints['same_host'] = ','.join( + same_host_hint_shares + ) if different_host_hint_shares: different_host_hint_shares = [ apiutils.find_resource(share_client.shares, sh).id for sh in different_host_hint_shares.split(',') ] - scheduler_hints['different_host'] = ( - ','.join(different_host_hint_shares)) + scheduler_hints['different_host'] = ','.join( + different_host_hint_shares + ) body = { 'share_proto': parsed_args.share_proto, @@ -289,6 +335,7 @@ def take_action(self, parsed_args): 'share_group_id': share_group, 'scheduler_hints': scheduler_hints, 'mount_point_name': mount_point_name, + 'encryption_key_ref': encryption_key_ref, } share = share_client.shares.create(**body) @@ -297,12 +344,11 @@ def take_action(self, parsed_args): if not oscutils.wait_for_status( status_f=share_client.shares.get, res_id=share.id, - success_status=['available'] + success_status=['available'], ): LOG.error(_("ERROR: Share is in error state.")) - share = apiutils.find_resource(share_client.shares, - share.id) + share = apiutils.find_resource(share_client.shares, share.id) printable_share = share._info printable_share.pop('links', None) @@ -313,41 +359,45 @@ def take_action(self, parsed_args): class DeleteShare(command.Command): """Delete a share.""" + _description = _("Delete a share") def get_parser(self, prog_name): - parser = super(DeleteShare, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "shares", metavar="", nargs="+", - help=_("Share(s) to delete (name or ID)") + help=_("Share(s) to delete (name or ID)"), ) parser.add_argument( "--share-group", metavar="", default=None, - help=_("Optional share group (name or ID) " - "which contains the share") + help=_( + "Optional share group (name or ID) which contains the share" + ), ) parser.add_argument( "--force", action='store_true', default=False, - help=_("Attempt forced removal of share(s), regardless of state " - "(defaults to False)") + help=_( + "Attempt forced removal of share(s), regardless of state " + "(defaults to False)" + ), ) parser.add_argument( "--wait", action='store_true', default=False, - help=_("Wait for share deletion") + help=_("Wait for share deletion"), ) parser.add_argument( "--soft", action='store_true', default=False, - help=_("Soft delete one or more shares.") + help=_("Soft delete one or more shares."), ) return parser @@ -357,61 +407,68 @@ def take_action(self, parsed_args): for share in parsed_args.shares: try: - share_obj = apiutils.find_resource( - share_client.shares, share - ) + share_obj = apiutils.find_resource(share_client.shares, share) share_group_id = None if parsed_args.share_group: share_group_id = apiutils.find_resource( - share_client.share_groups, parsed_args.share_group).id + share_client.share_groups, parsed_args.share_group + ).id if parsed_args.force: share_client.shares.force_delete(share_obj) elif parsed_args.soft: if share_client.api_version >= api_versions.APIVersion( - '2.69'): + '2.69' + ): share_client.shares.soft_delete(share_obj) else: raise exceptions.CommandError( "Soft Deleting shares is only " - "available with manila API version >= 2.69") + "available with manila API version >= 2.69" + ) else: - share_client.shares.delete(share_obj, - share_group_id) + share_client.shares.delete(share_obj, share_group_id) if parsed_args.wait: if not oscutils.wait_for_delete( - manager=share_client.shares, - res_id=share_obj.id): + manager=share_client.shares, res_id=share_obj.id + ): result += 1 except Exception as exc: result += 1 - LOG.error(_("Failed to delete share with " - "name or ID '%(share)s': %(e)s"), - {'share': share, 'e': exc}) + LOG.error( + _( + "Failed to delete share with " + "name or ID '%(share)s': %(e)s" + ), + {'share': share, 'e': exc}, + ) if result > 0: total = len(parsed_args.shares) - msg = (_("%(result)s of %(total)s shares failed " - "to delete.") % {'result': result, 'total': total}) + msg = _("%(result)s of %(total)s shares failed to delete.") % { + 'result': result, + 'total': total, + } raise exceptions.CommandError(msg) class ListShare(command.Lister): """List Shared file systems (shares).""" + _description = _("List shares") def get_parser(self, prog_name): - parser = super(ListShare, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( '--name', metavar="", - help=_('Filter shares by share name') + help=_('Filter shares by share name'), ) parser.add_argument( '--status', metavar="", - help=_('Filter shares by status') + help=_('Filter shares by status'), ) parser.add_argument( '--snapshot', @@ -421,16 +478,20 @@ def get_parser(self, prog_name): parser.add_argument( '--export-location', metavar='', - help=_('Filter shares by export location id or path. ' - 'Available only for microversion >= 2.35'), + help=_( + 'Filter shares by export location id or path. ' + 'Available only for microversion >= 2.35' + ), ) parser.add_argument( '--soft-deleted', action='store_true', - help=_('Get shares in recycle bin. If this parameter is set to ' - 'True (Default=False), only shares in the recycle bin ' - 'will be displayed. Available only for microversion >= ' - '2.69.') + help=_( + 'Get shares in recycle bin. If this parameter is set to ' + 'True (Default=False), only shares in the recycle bin ' + 'will be displayed. Available only for microversion >= ' + '2.69.' + ), ) parser.add_argument( '--public', @@ -461,19 +522,20 @@ def get_parser(self, prog_name): parser.add_argument( '--share-server', metavar='', - help=_('Filter shares exported via a given share server ' - '(admin only)'), + help=_( + 'Filter shares exported via a given share server (admin only)' + ), ) parser.add_argument( '--project', metavar='', - help=_('Filter shares by project (name or ID) (admin only)') + help=_('Filter shares by project (name or ID) (admin only)'), ) identity_common.add_project_domain_option_to_parser(parser) parser.add_argument( '--user', metavar='', - help=_('Filter results by user (name or ID) (admin only)') + help=_('Filter results by user (name or ID) (admin only)'), ) identity_common.add_user_domain_option_to_parser(parser) parser.add_argument( @@ -486,16 +548,20 @@ def get_parser(self, prog_name): '--property', metavar='', action=parseractions.KeyValueAction, - help=_('Filter shares having a given metadata key=value property ' - '(repeat option to filter by multiple properties)'), + help=_( + 'Filter shares having a given metadata key=value property ' + '(repeat option to filter by multiple properties)' + ), ) parser.add_argument( '--extra-spec', metavar='', action=parseractions.KeyValueAction, - help=_('Filter shares with extra specs (key=value) of the share ' - 'type that they belong to. ' - '(repeat option to filter by multiple extra specs)'), + help=_( + 'Filter shares with extra specs (key=value) of the share ' + 'type that they belong to. ' + '(repeat option to filter by multiple extra specs)' + ), ) parser.add_argument( '--long', @@ -507,9 +573,11 @@ def get_parser(self, prog_name): '--sort', metavar="[:]", default='name:asc', - help=_("Sort output by selected keys and directions(asc or desc) " - "(default: name:asc), multiple keys and directions can be " - "specified separated by comma"), + help=_( + "Sort output by selected keys and directions(asc or desc) " + "(default: name:asc), multiple keys and directions can be " + "specified separated by comma" + ), ) parser.add_argument( '--limit', @@ -527,15 +595,27 @@ def get_parser(self, prog_name): "--name~", metavar="", default=None, - help=_("Filter results matching a share name pattern. " - "Available only for microversion >= 2.36.") + help=_( + "Filter results matching a share name pattern. " + "Available only for microversion >= 2.36." + ), ) parser.add_argument( '--description~', metavar="", default=None, - help=_("Filter results matching a share description pattern." - "Available only for microversion >= 2.36.") + help=_( + "Filter results matching a share description pattern." + "Available only for microversion >= 2.36." + ), + ) + parser.add_argument( + '--encryption-key-ref', + metavar="", + help=_( + 'Filter shares by their encryption key ref. ' + 'Available for microversion >= 2.90' + ), ) return parser @@ -557,7 +637,7 @@ def take_action(self, parsed_args): 'is_public', 'share_type_name', 'host', - 'availability_zone' + 'availability_zone', ] column_headers = [ 'ID', @@ -568,7 +648,7 @@ def take_action(self, parsed_args): 'Is Public', 'Share Type Name', 'Host', - 'Availability Zone' + 'Availability Zone', ] project_id = None @@ -576,51 +656,55 @@ def take_action(self, parsed_args): project_id = identity_common.find_project( identity_client, parsed_args.project, - parsed_args.project_domain).id + parsed_args.project_domain, + ).id user_id = None if parsed_args.user: - user_id = identity_common.find_user(identity_client, - parsed_args.user, - parsed_args.user_domain).id + user_id = identity_common.find_user( + identity_client, parsed_args.user, parsed_args.user_domain + ).id # set value of 'all_tenants' when using project option all_tenants = bool(parsed_args.project) or parsed_args.all_projects share_type_id = None if parsed_args.share_type: - share_type_id = apiutils.find_resource(share_client.share_types, - parsed_args.share_type).id + share_type_id = apiutils.find_resource( + share_client.share_types, parsed_args.share_type + ).id snapshot_id = None if parsed_args.snapshot: - snapshot_id = apiutils.find_resource(share_client.share_snapshots, - parsed_args.snapshot).id + snapshot_id = apiutils.find_resource( + share_client.share_snapshots, parsed_args.snapshot + ).id share_network_id = None if parsed_args.share_network: share_network_id = apiutils.find_resource( - share_client.share_networks, - parsed_args.share_network).id + share_client.share_networks, parsed_args.share_network + ).id share_group_id = None if parsed_args.share_group: - share_group_id = apiutils.find_resource(share_client.share_groups, - parsed_args.share_group).id + share_group_id = apiutils.find_resource( + share_client.share_groups, parsed_args.share_group + ).id share_server_id = None if parsed_args.share_server: share_server_id = apiutils.find_resource( - share_client.share_servers, - parsed_args.share_server).id + share_client.share_servers, parsed_args.share_server + ).id search_opts = { 'all_tenants': all_tenants, 'is_public': parsed_args.public, - 'metadata': utils.extract_key_value_options( - parsed_args.property), + 'metadata': utils.extract_key_value_options(parsed_args.property), 'extra_specs': utils.extract_key_value_options( - parsed_args.extra_spec), + parsed_args.extra_spec + ), 'limit': parsed_args.limit, 'name': parsed_args.name, 'status': parsed_args.status, @@ -636,62 +720,84 @@ def take_action(self, parsed_args): } if share_client.api_version >= api_versions.APIVersion('2.69'): search_opts['is_soft_deleted'] = parsed_args.soft_deleted - elif (getattr(parsed_args, 'soft_deleted')): + elif getattr(parsed_args, 'soft_deleted'): raise exceptions.CommandError( "Filtering soft deleted shares is only " - "available with manila API version >= 2.69") + "available with manila API version >= 2.69" + ) if share_client.api_version >= api_versions.APIVersion("2.35"): search_opts['export_location'] = parsed_args.export_location - elif (getattr(parsed_args, 'export_location')): + elif getattr(parsed_args, 'export_location'): raise exceptions.CommandError( "Filtering by export location is only " - "available with manila API version >= 2.35") + "available with manila API version >= 2.35" + ) + + if share_client.api_version >= api_versions.APIVersion('2.90'): + search_opts['encryption_key_ref'] = parsed_args.encryption_key_ref + elif getattr(parsed_args, 'encryption_key_ref'): + raise exceptions.CommandError( + "Filtering shares by encryption key ref is only " + "available with manila API version >= 2.90" + ) # NOTE(vkmc) We implemented sorting and filtering in manilaclient # but we will use the one provided by osc if share_client.api_version >= api_versions.APIVersion("2.36"): search_opts['name~'] = getattr(parsed_args, 'name~') search_opts['description~'] = getattr(parsed_args, 'description~') - elif (getattr(parsed_args, 'name~') or - getattr(parsed_args, 'description~')): + elif getattr(parsed_args, 'name~') or getattr( + parsed_args, 'description~' + ): raise exceptions.CommandError( "Pattern based filtering (name~ and description~)" - " is only available with manila API version >= 2.36") + " is only available with manila API version >= 2.36" + ) data = share_client.shares.list(search_opts=search_opts) data = oscutils.sort_items(data, parsed_args.sort, str) - return (column_headers, (oscutils.get_item_properties - (s, columns, formatters={'Metadata': oscutils.format_dict},) - for s in data)) + return ( + column_headers, + ( + oscutils.get_item_properties( + s, + columns, + formatters={'Metadata': oscutils.format_dict}, + ) + for s in data + ), + ) class ShowShare(command.ShowOne): """Show a share.""" + _description = _("Display share details") def get_parser(self, prog_name): - parser = super(ShowShare, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( - 'share', - metavar="", - help=_('Share to display (name or ID)') + 'share', metavar="", help=_('Share to display (name or ID)') ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share - share_obj = apiutils.find_resource(share_client.shares, - parsed_args.share) + share_obj = apiutils.find_resource( + share_client.shares, parsed_args.share + ) export_locations = share_client.share_export_locations.list(share_obj) export_locations = cliutils.convert_dict_list_to_string( export_locations, - ignored_keys=['replica_state', - 'availability_zone', - 'share_replica_id'] + ignored_keys=[ + 'replica_state', + 'availability_zone', + 'share_replica_id', + ], ) data = share_obj._info @@ -700,8 +806,9 @@ def take_action(self, parsed_args): # 'metadata' --> 'properties' data.update( { - 'properties': - format_columns.DictColumn(data.pop('metadata', {})), + 'properties': format_columns.DictColumn( + data.pop('metadata', {}) + ), }, ) @@ -714,14 +821,13 @@ def take_action(self, parsed_args): class SetShare(command.Command): """Set share properties.""" + _description = _("Set share properties") def get_parser(self, prog_name): - parser = super(SetShare, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( - 'share', - metavar="", - help=_('Share to modify (name or ID)') + 'share', metavar="", help=_('Share to modify (name or ID)') ) # 'metadata' --> 'properties' parser.add_argument( @@ -729,65 +835,78 @@ def get_parser(self, prog_name): metavar="", default={}, action=parseractions.KeyValueAction, - help=_("Set a property to this share " - "(repeat option to set multiple properties)"), + help=_( + "Set a property to this share " + "(repeat option to set multiple properties)" + ), ) parser.add_argument( '--name', metavar="", default=None, - help=_('New share name. (Default=None)') + help=_('New share name. (Default=None)'), ) parser.add_argument( '--description', metavar='', default=None, - help=_('New share description. (Default=None)') + help=_('New share description. (Default=None)'), ) parser.add_argument( '--public', metavar='', - help=_('Level of visibility for share. ' - 'Defines whether other tenants are able to see it or not. ') + help=_( + 'Level of visibility for share. ' + 'Defines whether other tenants are able to see it or not. ' + ), ) parser.add_argument( '--status', metavar='', default=None, - help=_('Explicitly update the status of a share (Admin only). ' - 'Examples include: available, error, creating, deleting, ' - 'error_deleting.') + help=_( + 'Explicitly update the status of a share (Admin only). ' + 'Examples include: available, error, creating, deleting, ' + 'error_deleting.' + ), ) parser.add_argument( '--task-state', metavar="", required=False, default=None, - help=_("Indicate which task state to assign the share. Options " - "include migration_starting, migration_in_progress, " - "migration_completing, migration_success, migration_error, " - "migration_cancelled, migration_driver_in_progress, " - "migration_driver_phase1_done, data_copying_starting, " - "data_copying_in_progress, data_copying_completing, " - "data_copying_completed, data_copying_cancelled, " - "data_copying_error. ") + nargs='?', + help=_( + "Indicate which task state to assign the share. Options " + "include migration_starting, migration_in_progress, " + "migration_completing, migration_success, migration_error, " + "migration_cancelled, migration_driver_in_progress, " + "migration_driver_phase1_done, data_copying_starting, " + "data_copying_in_progress, data_copying_completing, " + "data_copying_completed, data_copying_cancelled, " + "data_copying_error. " + ), ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share - share_obj = apiutils.find_resource(share_client.shares, - parsed_args.share) + share_obj = apiutils.find_resource( + share_client.shares, parsed_args.share + ) result = 0 if parsed_args.property: try: share_obj.set_metadata(parsed_args.property) except Exception as e: - LOG.error(_("Failed to set share properties " - "'%(properties)s': %(exception)s"), - {'properties': parsed_args.property, - 'exception': e}) + LOG.error( + _( + "Failed to set share properties " + "'%(properties)s': %(exception)s" + ), + {'properties': parsed_args.property, 'exception': e}, + ) result += 1 kwargs = {} @@ -801,64 +920,71 @@ def take_action(self, parsed_args): try: share_client.shares.update(share_obj.id, **kwargs) except Exception as e: - LOG.error(_("Failed to update share display name, visibility " - "or display description: %s"), e) + LOG.error( + _( + "Failed to update share display name, visibility " + "or display description: %s" + ), + e, + ) result += 1 if parsed_args.status: try: share_obj.reset_state(parsed_args.status) except Exception as e: - LOG.error(_( - "Failed to set status for the share: %s"), e) + LOG.error(_("Failed to set status for the share: %s"), e) result += 1 - if parsed_args.task_state: + if hasattr(parsed_args, 'task_state'): + task_state = parsed_args.task_state + if task_state and task_state.lower() == "none": + task_state = None try: - share_obj.reset_task_state(parsed_args.task_state) + share_obj.reset_task_state(task_state) except Exception as e: - LOG.error(_("Failed to update share task state " - "%s"), e) + LOG.error(_("Failed to update share task state %s"), e) result += 1 if result > 0: - raise exceptions.CommandError(_("One or more of the " - "set operations failed")) + raise exceptions.CommandError( + _("One or more of the set operations failed") + ) class UnsetShare(command.Command): """Unset share properties.""" + _description = _("Unset share properties") def get_parser(self, prog_name): - parser = super(UnsetShare, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( - 'share', - metavar="", - help=_('Share to modify (name or ID)') + 'share', metavar="", help=_('Share to modify (name or ID)') ) # 'metadata' --> 'properties' parser.add_argument( '--property', metavar='', action='append', - help=_('Remove a property from share ' - '(repeat option to remove multiple properties)'), + help=_( + 'Remove a property from share ' + '(repeat option to remove multiple properties)' + ), ) parser.add_argument( - '--name', - action='store_true', - help=_('Unset share name.') + '--name', action='store_true', help=_('Unset share name.') ) parser.add_argument( '--description', action='store_true', - help=_('Unset share description.') + help=_('Unset share description.'), ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share - share_obj = apiutils.find_resource(share_client.shares, - parsed_args.share) + share_obj = apiutils.find_resource( + share_client.shares, parsed_args.share + ) result = 0 kwargs = {} if parsed_args.name: @@ -869,8 +995,13 @@ def take_action(self, parsed_args): try: share_client.shares.update(share_obj.id, **kwargs) except Exception as e: - LOG.error(_("Failed to unset share display name " - "or display description: %s"), e) + LOG.error( + _( + "Failed to unset share display name " + "or display description: %s" + ), + e, + ) result += 1 if parsed_args.property: @@ -878,54 +1009,55 @@ def take_action(self, parsed_args): try: share_obj.delete_metadata([key]) except Exception as e: - LOG.error(_("Failed to unset share property " - "'%(key)s': %(e)s"), - {'key': key, 'e': e}) + LOG.error( + _("Failed to unset share property '%(key)s': %(e)s"), + {'key': key, 'e': e}, + ) result += 1 if result > 0: - raise exceptions.CommandError(_( - "One or more of the " - "unset operations failed")) + raise exceptions.CommandError( + _("One or more of the unset operations failed") + ) class ResizeShare(command.Command): """Resize a share""" + _description = _("Resize a share") def get_parser(self, prog_name): - parser = super(ResizeShare, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( - 'share', - metavar="", - help=_('Name or ID of share to resize') + 'share', metavar="", help=_('Name or ID of share to resize') ) parser.add_argument( 'new_size', metavar="", type=int, - help=_('New size of share, in GiBs') + help=_('New size of share, in GiBs'), ) parser.add_argument( '--wait', action='store_true', default=False, - help=_('Wait for share resize') + help=_('Wait for share resize'), ) parser.add_argument( '--force', action='store_true', default=False, - help=_('Only applicable when increasing the size of the ' - 'share,only available with microversion ' - '2.64 and higher. (admin only)') + help=_( + 'Only applicable when increasing the size of the ' + 'share,only available with microversion ' + '2.64 and higher. (admin only)' + ), ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share - share = apiutils.find_resource(share_client.shares, - parsed_args.share) + share = apiutils.find_resource(share_client.shares, parsed_args.share) share_size = share._info['size'] new_size = parsed_args.new_size @@ -933,16 +1065,16 @@ def take_action(self, parsed_args): try: share_client.shares.shrink(share, new_size) except Exception as e: - raise exceptions.CommandError(_( - "Share resize failed: %s" % e - )) + msg = _("Share resize failed: %(e)s") + raise exceptions.CommandError(msg % {'e': e}) elif share_size < new_size: force = False if parsed_args.force: if share_client.api_version < api_versions.APIVersion("2.64"): raise exceptions.CommandError( 'args force is available only for ' - 'API microversion >= 2.64') + 'API microversion >= 2.64' + ) force = True try: if force: @@ -950,65 +1082,65 @@ def take_action(self, parsed_args): else: share_client.shares.extend(share, new_size) except Exception as e: - raise exceptions.CommandError(_( - "Share resize failed: %s" % e - )) + msg = _("Share resize failed: %(e)s") + raise exceptions.CommandError(msg % {'e': e}) else: - raise exceptions.CommandError(_( - "Share size is already at %s GiBs" % new_size - )) + msg = _("Share size is already at %(new_size)s GiBs") + raise exceptions.CommandError(msg % {'new_size': new_size}) if parsed_args.wait: if not oscutils.wait_for_status( status_f=share_client.shares.get, res_id=share.id, - success_status=['available'] + success_status=['available'], ): - raise exceptions.CommandError(_( - "Share not available after resize attempt.")) + raise exceptions.CommandError( + _("Share not available after resize attempt.") + ) class AdoptShare(command.ShowOne): """Adopt share not handled by Manila (Admin only).""" + _description = _("Adopt a share") def get_parser(self, prog_name): - parser = super(AdoptShare, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'service_host', metavar="", - help=_('Service host: some.host@driver#pool.') + help=_('Service host: some.host@driver#pool.'), ) parser.add_argument( 'protocol', metavar="", - help=_( - 'Protocol of the share to manage, such as NFS or CIFS.') + help=_('Protocol of the share to manage, such as NFS or CIFS.'), ) parser.add_argument( 'export_path', metavar="", - help=_('Share export path, NFS share such as: ' - '10.0.0.1:/example_path, CIFS share such as: ' - '\\\\10.0.0.1\\example_cifs_share.') + help=_( + 'Share export path, NFS share such as: ' + '10.0.0.1:/example_path, CIFS share such as: ' + '\\\\10.0.0.1\\example_cifs_share.' + ), ) parser.add_argument( '--name', metavar="", default=None, - help=_('Optional share name. (Default=None)') + help=_('Optional share name. (Default=None)'), ) parser.add_argument( '--description', metavar="", default=None, - help=_('Optional share description. (Default=None)') + help=_('Optional share description. (Default=None)'), ) parser.add_argument( '--share-type', metavar="", default=None, - help=_( - 'Optional share type assigned to share. (Default=None)') + help=_('Optional share type assigned to share. (Default=None)'), ) parser.add_argument( '--driver-options', @@ -1017,27 +1149,41 @@ def get_parser(self, prog_name): metavar='', default=None, help=_( - 'Optional driver options as key=value pairs (Default=None).') + 'Optional driver options as key=value pairs (Default=None).' + ), ) parser.add_argument( '--public', action='store_true', - help=_('Level of visibility for share. Defines whether other ' - 'projects are able to see it or not. Available only for ' - 'microversion >= 2.8. (Default=False)') + help=_( + 'Level of visibility for share. Defines whether other ' + 'projects are able to see it or not. Available only for ' + 'microversion >= 2.8. (Default=False)' + ), ) parser.add_argument( '--share-server-id', metavar="", - help=_('Share server associated with share when using a share ' - 'type with "driver_handles_share_servers" extra_spec ' - 'set to True. Available only for microversion >= 2.49. ' - '(Default=None)') + help=_( + 'Share server associated with share when using a share ' + 'type with "driver_handles_share_servers" extra_spec ' + 'set to True. Available only for microversion >= 2.49. ' + '(Default=None)' + ), + ) + parser.add_argument( + '--mount-point-name', + metavar="", + default=None, + help=_( + 'Optional custom export location. Available only for ' + 'microversion >= 2.92. (Default=None)' + ), ) parser.add_argument( "--wait", action='store_true', - help=_("Wait until share is adopted") + help=_("Wait until share is adopted"), ) return parser @@ -1049,19 +1195,21 @@ def take_action(self, parsed_args): 'protocol': parsed_args.protocol, 'export_path': parsed_args.export_path, 'name': parsed_args.name, - 'description': parsed_args.description + 'description': parsed_args.description, } share_type = None if parsed_args.share_type: - share_type = apiutils.find_resource(share_client.share_types, - parsed_args.share_type).id + share_type = apiutils.find_resource( + share_client.share_types, parsed_args.share_type + ).id kwargs['share_type'] = share_type driver_options = None if parsed_args.driver_options: driver_options = utils.extract_properties( - parsed_args.driver_options) + parsed_args.driver_options + ) kwargs['driver_options'] = driver_options if parsed_args.public: @@ -1070,7 +1218,8 @@ def take_action(self, parsed_args): else: raise exceptions.CommandError( 'Setting share visibility while adopting a share is ' - 'available only for API microversion >= 2.8') + 'available only for API microversion >= 2.8' + ) if parsed_args.share_server_id: if share_client.api_version >= api_versions.APIVersion("2.49"): @@ -1078,7 +1227,17 @@ def take_action(self, parsed_args): else: raise exceptions.CommandError( 'Selecting a share server ID is available only for ' - 'API microversion >= 2.49') + 'API microversion >= 2.49' + ) + + if parsed_args.mount_point_name: + if share_client.api_version >= api_versions.APIVersion("2.92"): + kwargs['mount_point_name'] = parsed_args.mount_point_name + else: + raise exceptions.CommandError( + 'Setting share mount point name is available only for ' + 'API microversion >= 2.92' + ) share = share_client.shares.manage(**kwargs) @@ -1087,12 +1246,11 @@ def take_action(self, parsed_args): status_f=share_client.shares.get, res_id=share.id, success_status=['available'], - error_status=['manage_error', 'error'] + error_status=['manage_error', 'error'], ): LOG.error(_("ERROR: Share is in error state.")) - share = apiutils.find_resource(share_client.shares, - share.id) + share = apiutils.find_resource(share_client.shares, share.id) share._info.pop('links', None) return self.dict2columns(share._info) @@ -1100,20 +1258,21 @@ def take_action(self, parsed_args): class AbandonShare(command.Command): """Abandon a share (Admin only).""" + _description = _("Abandon a share") def get_parser(self, prog_name): - parser = super(AbandonShare, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'share', metavar="", nargs="+", - help=_('Name or ID of the share(s)') + help=_('Name or ID of the share(s)'), ) parser.add_argument( "--wait", action='store_true', - help=_("Wait until share is abandoned") + help=_("Wait until share is abandoned"), ) return parser @@ -1123,9 +1282,7 @@ def take_action(self, parsed_args): for share in parsed_args.share: try: - share_obj = apiutils.find_resource( - share_client.shares, share - ) + share_obj = apiutils.find_resource(share_client.shares, share) share_client.shares.unmanage(share_obj) if parsed_args.wait: @@ -1133,20 +1290,25 @@ def take_action(self, parsed_args): # retrievable with the given 'res_id' so we can use it # to check that the share has been abandoned if not oscutils.wait_for_delete( - manager=share_client.shares, - res_id=share_obj.id): + manager=share_client.shares, res_id=share_obj.id + ): result += 1 except Exception as e: result += 1 - LOG.error(_("Failed to abandon share with " - "name or ID '%(share)s': %(e)s"), - {'share': share, 'e': e}) + LOG.error( + _( + "Failed to abandon share with " + "name or ID '%(share)s': %(e)s" + ), + {'share': share, 'e': e}, + ) if result > 0: total = len(parsed_args.share) - msg = (_("Failed to abandon %(result)s out of %(total)s shares.") - % {'result': result, 'total': total}) + msg = _( + "Failed to abandon %(result)s out of %(total)s shares." + ) % {'result': result, 'total': total} raise exceptions.CommandError(msg) @@ -1156,34 +1318,30 @@ class ShareExportLocationShow(command.ShowOne): _description = _("Show export location of a share") def get_parser(self, prog_name): - parser = super(ShareExportLocationShow, self).get_parser( - prog_name) + parser = super().get_parser(prog_name) parser.add_argument( - 'share', - metavar="", - help=_('Name or ID of share') + 'share', metavar="", help=_('Name or ID of share') ) parser.add_argument( 'export_location', metavar="", - help=_('ID of the share export location') + help=_('ID of the share export location'), ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share - share = apiutils.find_resource(share_client.shares, - parsed_args.share) + share = apiutils.find_resource(share_client.shares, parsed_args.share) export_location = share_client.share_export_locations.get( - share=share, - export_location=parsed_args.export_location + share=share, export_location=parsed_args.export_location ) data = export_location._info data.update( { - 'properties': - format_columns.DictColumn(data.pop('metadata', {})), + 'properties': format_columns.DictColumn( + data.pop('metadata', {}) + ), }, ) @@ -1196,33 +1354,30 @@ class ShareExportLocationList(command.Lister): _description = _("List export location of a share") def get_parser(self, prog_name): - parser = super(ShareExportLocationList, self).get_parser( - prog_name) + parser = super().get_parser(prog_name) parser.add_argument( - 'share', - metavar="", - help=_('Name or ID of share') + 'share', metavar="", help=_('Name or ID of share') ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share - share = apiutils.find_resource(share_client.shares, - parsed_args.share) + share = apiutils.find_resource(share_client.shares, parsed_args.share) export_locations = share_client.share_export_locations.list( share=share ) - list_of_keys = [ - 'ID', - 'Path', - 'Preferred' - ] + list_of_keys = ['ID', 'Path', 'Preferred'] - return (list_of_keys, (oscutils.get_item_properties - (s, list_of_keys) for s in export_locations)) + return ( + list_of_keys, + ( + oscutils.get_item_properties(s, list_of_keys) + for s in export_locations + ), + ) class ShareExportLocationSet(command.Command): @@ -1231,131 +1386,145 @@ class ShareExportLocationSet(command.Command): _description = _("Set an export location property.") def get_parser(self, prog_name): - parser = super(ShareExportLocationSet, self).get_parser( - prog_name) + parser = super().get_parser(prog_name) parser.add_argument( - 'share', - metavar="", - help=_('Name or ID of share') + 'share', metavar="", help=_('Name or ID of share') ) parser.add_argument( 'export_location', metavar="", - help=_('ID of the export location') + help=_('ID of the export location'), ) parser.add_argument( "--property", metavar="", default={}, action=parseractions.KeyValueAction, - help=_("Set a property to this export location " - "(repeat option to set multiple properties). " - "Available only for microversion >= 2.87."), + help=_( + "Set a property to this export location " + "(repeat option to set multiple properties). " + "Available only for microversion >= 2.87." + ), ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share share_id = apiutils.find_resource( - share_client.shares, - parsed_args.share).id + share_client.shares, parsed_args.share + ).id - if (parsed_args.property and - share_client.api_version < api_versions.APIVersion("2.87")): + if ( + parsed_args.property + and share_client.api_version < api_versions.APIVersion("2.87") + ): raise exceptions.CommandError( "Property can be specified only with manila API " - "version >= 2.87.") + "version >= 2.87." + ) if parsed_args.property: try: share_client.share_export_locations.set_metadata( share_id, parsed_args.property, - subresource=parsed_args.export_location) + subresource=parsed_args.export_location, + ) except Exception as e: - raise exceptions.CommandError(_( - "Failed to set export location property " - "'%(properties)s': %(e)s") % - {'properties': parsed_args.property, 'e': e} + raise exceptions.CommandError( + _( + "Failed to set export location property " + "'%(properties)s': %(e)s" + ) + % {'properties': parsed_args.property, 'e': e} ) class ShareExportLocationUnset(command.Command): """Unset a share export location property""" + _description = _("Unset a share export location property") def get_parser(self, prog_name): - parser = super(ShareExportLocationUnset, self).get_parser( - prog_name) + parser = super().get_parser(prog_name) parser.add_argument( - 'share', - metavar="", - help=_('Name or ID of share') + 'share', metavar="", help=_('Name or ID of share') ) parser.add_argument( 'export_location', metavar="", - help=_('ID of the export location') + help=_('ID of the export location'), ) parser.add_argument( "--property", metavar="", action='append', - help=_("Remove a property from export location " - "(repeat option to remove multiple properties). " - "Available only for microversion >= 2.87."), + help=_( + "Remove a property from export location " + "(repeat option to remove multiple properties). " + "Available only for microversion >= 2.87." + ), ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share share_id = apiutils.find_resource( - share_client.shares, - parsed_args.share).id + share_client.shares, parsed_args.share + ).id - if (parsed_args.property and - share_client.api_version < api_versions.APIVersion("2.87")): + if ( + parsed_args.property + and share_client.api_version < api_versions.APIVersion("2.87") + ): raise exceptions.CommandError( "Property can be specified only with manila API " - "version >= 2.87.") + "version >= 2.87." + ) if parsed_args.property: result = 0 for key in parsed_args.property: try: share_client.share_export_locations.delete_metadata( - share_id, [key], - subresource=parsed_args.export_location) + share_id, + [key], + subresource=parsed_args.export_location, + ) except Exception as e: result += 1 - LOG.error("Failed to unset export location property " - "'%(key)s': %(e)s", {'key': key, 'e': e}) + LOG.error( + "Failed to unset export location property " + "'%(key)s': %(e)s", + {'key': key, 'e': e}, + ) if result > 0: total = len(parsed_args.property) raise exceptions.CommandError( f"{result} of {total} export location properties failed " - f"to be unset.") + f"to be unset." + ) class ShowShareProperties(command.ShowOne): """Show properties of a share""" + _description = _("Show share properties") def get_parser(self, prog_name): - parser = super(ShowShareProperties, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( - 'share', - metavar="", - help=_('Name or ID of share') + 'share', metavar="", help=_('Name or ID of share') ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share share_obj = apiutils.find_resource( - share_client.shares, parsed_args.share) + share_client.shares, parsed_args.share + ) share_properties = share_client.shares.get_metadata(share_obj) return self.dict2columns(share_properties._info) @@ -1367,118 +1536,138 @@ class RevertShare(command.Command): _description = _("Revert a share to the specified snapshot.") def get_parser(self, prog_name): - parser = super(RevertShare, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'snapshot', metavar="", - help=_('Name or ID of the snapshot to restore. The snapshot ' - 'must be the most recent one known to manila.') + help=_( + 'Name or ID of the snapshot to restore. The snapshot ' + 'must be the most recent one known to manila.' + ), ) parser.add_argument( '--wait', action='store_true', default=False, - help=_('Wait for share revert') + help=_('Wait for share revert'), ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share - snapshot = apiutils.find_resource(share_client.share_snapshots, - parsed_args.snapshot) - share = apiutils.find_resource(share_client.shares, - snapshot.share_id) + snapshot = apiutils.find_resource( + share_client.share_snapshots, parsed_args.snapshot + ) + share = apiutils.find_resource(share_client.shares, snapshot.share_id) try: share.revert_to_snapshot(snapshot) except Exception as e: - raise exceptions.CommandError(_( - "Failed to revert share to snapshot: %s" % (e))) + msg = _("Failed to revert share to snapshot: %(e)s") + raise exceptions.CommandError(msg % {'e': e}) if parsed_args.wait: if not oscutils.wait_for_status( status_f=share_client.shares.get, res_id=share.id, - success_status=['available'] + success_status=['available'], ): - raise exceptions.CommandError(_( - "Share not available after revert attempt.")) + raise exceptions.CommandError( + _("Share not available after revert attempt.") + ) class ShareMigrationStart(command.Command): """Migrates share to a new host (Admin only, Experimental).""" + _description = _("Migrates share to a new host.") def get_parser(self, prog_name): - parser = super(ShareMigrationStart, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'share', metavar="", - help=_('Name or ID of share to migrate.') + help=_('Name or ID of share to migrate.'), ) parser.add_argument( 'host', metavar="", - help=_("Destination host where share will be migrated to. Use the " - "format 'host@backend#pool'.") + help=_( + "Destination host where share will be migrated to. Use the " + "format 'host@backend#pool'." + ), ) parser.add_argument( '--force-host-assisted-migration', metavar="", choices=['True', 'False'], default=False, - help=_("Enforces the use of the host-assisted migration approach, " - "which bypasses driver optimizations. Default=False.") + help=_( + "Enforces the use of the host-assisted migration approach, " + "which bypasses driver optimizations. Default=False." + ), ) parser.add_argument( '--preserve-metadata', metavar="", required=True, choices=['True', 'False'], - help=_("Enforces migration to preserve all file metadata when " - "moving its contents. If set to True, host-assisted" - "migration will not be attempted.") + help=_( + "Enforces migration to preserve all file metadata when " + "moving its contents. If set to True, host-assisted " + "migration will not be attempted." + ), ) parser.add_argument( '--preserve-snapshots', metavar="", required=True, choices=['True', 'False'], - help=_("Enforces migration of the share snapshots to the " - "destination. If set to True, host-assisted migration" - "will not be attempted.") + help=_( + "Enforces migration of the share snapshots to the " + "destination. If set to True, host-assisted migration " + "will not be attempted." + ), ) parser.add_argument( '--writable', metavar="", required=True, choices=['True', 'False'], - help=_("Enforces migration to keep the share writable while " - "contents are being moved. If set to True, host-assisted" - "migration will not be attempted.") + help=_( + "Enforces migration to keep the share writable while " + "contents are being moved. If set to True, host-assisted " + "migration will not be attempted." + ), ) parser.add_argument( '--nondisruptive', metavar="", choices=['True', 'False'], required=True, - help=_("Enforces migration to be nondisruptive. If set to True, " - "host-assisted migration will not be attempted.") + help=_( + "Enforces migration to be nondisruptive. If set to True, " + "host-assisted migration will not be attempted." + ), ) parser.add_argument( '--new-share-network', metavar="", default=None, - help=_("Specify the new share network for the share. Do not " - "specify this parameter if the migrating share has to be" - "retained within its current share network.") + help=_( + "Specify the new share network for the share. Do not " + "specify this parameter if the migrating share has to be " + "retained within its current share network." + ), ) parser.add_argument( '--new-share-type', metavar="", default=None, - help=_("Specify the new share type for the share. Do not specify " - "this parameter if the migrating share has to be retained " - "with its current share type.") + help=_( + "Specify the new share type for the share. Do not specify " + "this parameter if the migrating share has to be retained " + "with its current share type." + ), ) return parser @@ -1488,22 +1677,24 @@ def take_action(self, parsed_args): new_share_net_id = None if parsed_args.new_share_network: new_share_net_id = apiutils.find_resource( - share_client.share_networks, - parsed_args.new_share_network).id + share_client.share_networks, parsed_args.new_share_network + ).id new_share_type_id = None if parsed_args.new_share_type: new_share_type_id = apiutils.find_resource( - share_client.share_types, - parsed_args.new_share_type).id - share = apiutils.find_resource(share_client.shares, - parsed_args.share) - share.migration_start(parsed_args.host, - parsed_args.force_host_assisted_migration, - parsed_args.preserve_metadata, - parsed_args.writable, - parsed_args.nondisruptive, - parsed_args.preserve_snapshots, - new_share_net_id, new_share_type_id) + share_client.share_types, parsed_args.new_share_type + ).id + share = apiutils.find_resource(share_client.shares, parsed_args.share) + share.migration_start( + parsed_args.host, + parsed_args.force_host_assisted_migration, + parsed_args.preserve_metadata, + parsed_args.writable, + parsed_args.nondisruptive, + parsed_args.preserve_snapshots, + new_share_net_id, + new_share_type_id, + ) class ShareMigrationCancel(command.Command): @@ -1512,41 +1703,41 @@ class ShareMigrationCancel(command.Command): (Admin only, Experimental). """ + _description = _("Cancels migration of a given share when copying") def get_parser(self, prog_name): - parser = super(ShareMigrationCancel, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'share', metavar="", - help=_('Name or ID of share to migrate.') + help=_('Name or ID of share to migrate.'), ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share - share = apiutils.find_resource(share_client.shares, - parsed_args.share) + share = apiutils.find_resource(share_client.shares, parsed_args.share) share.migration_cancel() class ShareMigrationComplete(command.Command): """Completes migration for a given share (Admin only, Experimental).""" + _description = _("Completes migration for a given share") def get_parser(self, prog_name): - parser = super(ShareMigrationComplete, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'share', metavar="", - help=_('Name or ID of share to migrate.') + help=_('Name or ID of share to migrate.'), ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share - share = apiutils.find_resource(share_client.shares, - parsed_args.share) + share = apiutils.find_resource(share_client.shares, parsed_args.share) share.migration_complete() @@ -1556,22 +1747,24 @@ class ShareMigrationShow(command.ShowOne): (Admin only, Experimental). """ + _description = _("Gets migration progress of a given share when copying") def get_parser(self, prog_name): - parser = super(ShareMigrationShow, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'share', metavar="", - help=_('Name or ID of the share to get share migration progress ' - 'information.') + help=_( + 'Name or ID of the share to get share migration progress ' + 'information.' + ), ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share - share = apiutils.find_resource(share_client.shares, - parsed_args.share) + share = apiutils.find_resource(share_client.shares, parsed_args.share) result = share.migration_get_progress() return self.dict2columns(result[1]) @@ -1582,12 +1775,12 @@ class RestoreShare(command.Command): _description = _("Restores this share or more shares from the recycle bin") def get_parser(self, prog_name): - parser = super(RestoreShare, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'share', metavar="", nargs="+", - help=_('Name or ID of the share(s)') + help=_('Name or ID of the share(s)'), ) return parser @@ -1601,16 +1794,27 @@ def take_action(self, parsed_args): share_client.shares.restore(share) except Exception as e: failure_count += 1 - LOG.error(_("Failed to restore share with " - "name or ID '%(share)s': %(e)s"), - {'share': share, 'e': e}) + LOG.error( + _( + "Failed to restore share with " + "name or ID '%(share)s': %(e)s" + ), + {'share': share, 'e': e}, + ) if failure_count > 0: - total = len(parsed_args.share) - msg = (f"Failed to restore {failure_count} out of " - f"{total} shares.") - msg = _(msg) - raise exceptions.CommandError(msg) + msg = _( + "Failed to restore %(failure_count)s out of %(total)s " + "shares." + ) + raise exceptions.CommandError( + msg + % { + 'failure_count': failure_count, + 'total': len(parsed_args.share), + }, + ) else: raise exceptions.CommandError( "Restoring a share from the recycle bin is only " - "available with manila API version >= 2.69") + "available with manila API version >= 2.69" + ) diff --git a/manilaclient/osc/v2/share_access_rules.py b/manilaclient/osc/v2/share_access_rules.py index 05c75af0..422a2dad 100644 --- a/manilaclient/osc/v2/share_access_rules.py +++ b/manilaclient/osc/v2/share_access_rules.py @@ -32,7 +32,7 @@ 'access_key', 'created_at', 'updated_at', - 'properties' + 'properties', ] LOG = logging.getLogger(__name__) @@ -40,25 +40,28 @@ class ShareAccessAllow(command.ShowOne): """Create a new share access rule.""" + _description = _("Create new share access rule") def get_parser(self, prog_name): - parser = super(ShareAccessAllow, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'share', metavar="", - help=_('Name or ID of the NAS share to modify.') + help=_('Name or ID of the NAS share to modify.'), ) parser.add_argument( 'access_type', metavar="", - help=_('Access rule type (only "ip", "user" (user or group), ' - '"cert" or "cephx" are supported).') + help=_( + 'Access rule type (only "ip", "user" (user or group), ' + '"cert" or "cephx" are supported).' + ), ) parser.add_argument( 'access_to', metavar="", - help=_('Value that defines access.') + help=_('Value that defines access.'), ) # metadata --> properties in osc parser.add_argument( @@ -66,9 +69,11 @@ def get_parser(self, prog_name): type=str, nargs='*', metavar='', - help=_('Space separated list of key=value pairs of properties. ' - 'OPTIONAL: Default=None. ' - 'Available only for API microversion >= 2.45.'), + help=_( + 'Space separated list of key=value pairs of properties. ' + 'OPTIONAL: Default=None. ' + 'Available only for API microversion >= 2.45.' + ), ) parser.add_argument( '--access-level', @@ -76,45 +81,52 @@ def get_parser(self, prog_name): type=str, default=None, choices=['rw', 'ro'], - help=_('Share access level ("rw" and "ro" access levels ' - 'are supported). Defaults to rw.') + help=_( + 'Share access level ("rw" and "ro" access levels ' + 'are supported). Defaults to rw.' + ), ) parser.add_argument( "--wait", action='store_true', - help=_("Wait for share access rule creation.") + help=_("Wait for share access rule creation."), ) parser.add_argument( "--lock-visibility", action='store_true', default=False, - help=_("Whether the sensitive fields of the access rule redacted " - "to other users. Only available with API version >= 2.82.") + help=_( + "Whether the sensitive fields of the access rule redacted " + "to other users. Only available with API version >= 2.82." + ), ) parser.add_argument( "--lock-deletion", action='store_true', default=False, - help=_("When enabled, a 'delete' lock will be placed against the " - "rule and the rule cannot be deleted while the lock " - "exists. Only available with API version >= 2.82.") + help=_( + "When enabled, a 'delete' lock will be placed against the " + "rule and the rule cannot be deleted while the lock " + "exists. Only available with API version >= 2.82." + ), ) parser.add_argument( '--lock-reason', metavar="", type=str, default=None, - help=_("Reason for locking the access rule. Should only be " - "provided alongside a deletion or visibility lock. " - "Only available with API version >= 2.82.") + help=_( + "Reason for locking the access rule. Should only be " + "provided alongside a deletion or visibility lock. " + "Only available with API version >= 2.82." + ), ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share - share = apiutils.find_resource(share_client.shares, - parsed_args.share) + share = apiutils.find_resource(share_client.shares, parsed_args.share) lock_kwargs = {} if parsed_args.lock_visibility: lock_kwargs['lock_visibility'] = parsed_args.lock_visibility @@ -123,19 +135,22 @@ def take_action(self, parsed_args): if parsed_args.lock_reason: lock_kwargs['lock_reason'] = parsed_args.lock_reason - if (lock_kwargs - and share_client.api_version < api_versions.APIVersion( - "2.82")): + if lock_kwargs and share_client.api_version < api_versions.APIVersion( + "2.82" + ): raise exceptions.CommandError( 'Restricted access rules are only available starting ' - 'from API version 2.82.') + 'from API version 2.82.' + ) - if (lock_kwargs.get('lock_reason', None) - and not (lock_kwargs.get('lock_visibility', None) - or lock_kwargs.get('lock_deletion', None))): + if lock_kwargs.get('lock_reason', None) and not ( + lock_kwargs.get('lock_visibility', None) + or lock_kwargs.get('lock_deletion', None) + ): raise exceptions.CommandError( 'Lock reason can only be set while locking the deletion or ' - 'visibility.') + 'visibility.' + ) properties = {} if parsed_args.properties: @@ -144,112 +159,121 @@ def take_action(self, parsed_args): else: raise exceptions.CommandError( "Adding properties to access rules is supported only " - "with API microversion 2.45 and beyond") + "with API microversion 2.45 and beyond" + ) try: share_access_rule = share.allow( access_type=parsed_args.access_type, access=parsed_args.access_to, access_level=parsed_args.access_level, metadata=properties, - **lock_kwargs + **lock_kwargs, ) if parsed_args.wait: if not oscutils.wait_for_status( status_f=share_client.share_access_rules.get, res_id=share_access_rule['id'], - status_field='state' + status_field='state', ): LOG.error(_("ERROR: Share access rule is in error state.")) share_access_rule = oscutils.find_resource( - share_client.share_access_rules, - share_access_rule['id'])._info + share_client.share_access_rules, share_access_rule['id'] + )._info share_access_rule.update( { 'properties': utils.format_properties( - share_access_rule.pop('metadata', {})) + share_access_rule.pop('metadata', {}) + ) } ) - return (ACCESS_RULE_ATTRIBUTES, oscutils.get_dict_properties( - share_access_rule, - ACCESS_RULE_ATTRIBUTES)) + return ( + ACCESS_RULE_ATTRIBUTES, + oscutils.get_dict_properties( + share_access_rule, ACCESS_RULE_ATTRIBUTES + ), + ) except Exception as e: raise exceptions.CommandError( - "Failed to create access to share " - "'%s': %s" % (share, e)) + f"Failed to create access to share '{share}': {e}" + ) class ShareAccessDeny(command.Command): """Delete a share access rule.""" + _description = _("Delete a share access rule") def get_parser(self, prog_name): - parser = super(ShareAccessDeny, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'share', metavar="", - help=_('Name or ID of the NAS share to modify.') + help=_('Name or ID of the NAS share to modify.'), ) parser.add_argument( 'id', metavar="", - help=_('ID of the access rule to be deleted.') + help=_('ID of the access rule to be deleted.'), ) parser.add_argument( "--wait", action='store_true', default=False, - help=_("Wait for share access rule deletion") + help=_("Wait for share access rule deletion"), ) parser.add_argument( "--unrestrict", action='store_true', default=False, - help=_("Seek access rule deletion despite restrictions. Only " - "available with API version >= 2.82.") + help=_( + "Seek access rule deletion despite restrictions. Only " + "available with API version >= 2.82." + ), ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share - share = apiutils.find_resource(share_client.shares, - parsed_args.share) + share = apiutils.find_resource(share_client.shares, parsed_args.share) kwargs = {} if parsed_args.unrestrict: if share_client.api_version < api_versions.APIVersion("2.82"): raise exceptions.CommandError( 'Restricted access rules are only available starting from ' - 'API version 2.82.') + 'API version 2.82.' + ) kwargs['unrestrict'] = True - error = None try: share.deny(parsed_args.id, **kwargs) if parsed_args.wait: if not oscutils.wait_for_delete( - manager=share_client.share_access_rules, - res_id=parsed_args.id): - error = _("Failed to delete share access rule with ID: %s" - % parsed_args.id) + manager=share_client.share_access_rules, + res_id=parsed_args.id, + ): + raise Exception('timed out while waiting for deletion') except Exception as e: - error = e - if error: - raise exceptions.CommandError(_( - "Failed to delete share access rule for share " - "'%s': %s" % (share, error))) + msg = _( + "Failed to delete share access rule %(id)s for share " + "%(share)s: %(e)s" + ) + raise exceptions.CommandError( + msg + % {'id': parsed_args.id, 'share': parsed_args.share, 'e': e} + ) class ListShareAccess(command.Lister): """List share access rules.""" + _description = _("List share access rule") def get_parser(self, prog_name): - parser = super(ListShareAccess, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( - 'share', - metavar="", - help=_('Name or ID of the share.') + 'share', metavar="", help=_('Name or ID of the share.') ) # metadata --> properties in osc @@ -259,41 +283,42 @@ def get_parser(self, prog_name): nargs='*', metavar='', default=None, - help=_('Filters results by properties (key=value). ' - 'OPTIONAL: Default=None. ' - 'Available only for API microversion >= 2.45'), + help=_( + 'Filters results by properties (key=value). ' + 'OPTIONAL: Default=None. ' + 'Available only for API microversion >= 2.45' + ), ) parser.add_argument( "--access-type", metavar="", default=None, - help=_("Filter access rules by the access type.") + help=_("Filter access rules by the access type."), ) parser.add_argument( "--access-key", metavar="", default=None, - help=_("Filter access rules by the access key.") + help=_("Filter access rules by the access key."), ) parser.add_argument( "--access-to", metavar="", default=None, - help=_("Filter access rules by the access to field.") + help=_("Filter access rules by the access to field."), ) parser.add_argument( "--access-level", metavar="", default=None, - help=_("Filter access rules by the access level.") + help=_("Filter access rules by the access level."), ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share - share = apiutils.find_resource(share_client.shares, - parsed_args.share) + share = apiutils.find_resource(share_client.shares, parsed_args.share) access_type = parsed_args.access_type access_key = parsed_args.access_key access_to = parsed_args.access_to @@ -303,16 +328,17 @@ def take_action(self, parsed_args): 'access_type': access_type, 'access_key': access_key, 'access_to': access_to, - 'access_level': access_level + 'access_level': access_level, } - if (any(extended_filter_keys.values()) - and share_client.api_version < api_versions.APIVersion( - "2.82")): + if any( + extended_filter_keys.values() + ) and share_client.api_version < api_versions.APIVersion("2.82"): raise exceptions.CommandError( 'Filtering access rules by access_type, access_key, access_to ' 'and access_level is available starting from API version ' - '2.82.') + '2.82.' + ) search_opts = {} if share_client.api_version >= api_versions.APIVersion("2.82"): @@ -324,15 +350,17 @@ def take_action(self, parsed_args): if parsed_args.properties: search_opts = { 'metadata': utils.extract_properties( - parsed_args.properties) + parsed_args.properties + ) } access_list = share_client.share_access_rules.access_list( - share, - search_opts) + share, search_opts + ) elif parsed_args.properties: raise exceptions.CommandError( "Filtering access rules by properties is supported only " - "with API microversion 2.45 and beyond.") + "with API microversion 2.45 and beyond." + ) else: access_list = share.access_list() @@ -341,7 +369,7 @@ def take_action(self, parsed_args): 'Access Type', 'Access To', 'Access Level', - 'State' + 'State', ] if share_client.api_version >= api_versions.APIVersion("2.21"): @@ -351,24 +379,27 @@ def take_action(self, parsed_args): list_of_keys.append('Created At') list_of_keys.append('Updated At') - values = (oscutils.get_item_properties( - a, list_of_keys) for a in access_list) + values = ( + oscutils.get_item_properties(a, list_of_keys) for a in access_list + ) return (list_of_keys, values) class ShowShareAccess(command.ShowOne): """Display a share access rule.""" + _description = _( "Display a share access rule. " - "Available for API microversion 2.45 and higher") + "Available for API microversion 2.45 and higher" + ) def get_parser(self, prog_name): - parser = super(ShowShareAccess, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'access_id', metavar="", - help=_('ID of the NAS share access rule.') + help=_('ID of the NAS share access rule.'), ) return parser @@ -382,30 +413,37 @@ def take_action(self, parsed_args): access_rule._info.update( { 'properties': utils.format_properties( - access_rule._info.pop('metadata', {})) + access_rule._info.pop('metadata', {}) + ) } ) - return (ACCESS_RULE_ATTRIBUTES, oscutils.get_dict_properties( - access_rule._info, - ACCESS_RULE_ATTRIBUTES)) + return ( + ACCESS_RULE_ATTRIBUTES, + oscutils.get_dict_properties( + access_rule._info, ACCESS_RULE_ATTRIBUTES + ), + ) else: raise exceptions.CommandError( "Displaying share access rule details is only available " - "with API microversion 2.45 and higher.") + "with API microversion 2.45 and higher." + ) class SetShareAccess(command.Command): """Set properties to share access rule.""" + _description = _( "Set properties to share access rule. " - "Available for API microversion 2.45 and higher") + "Available for API microversion 2.45 and higher" + ) def get_parser(self, prog_name): - parser = super(SetShareAccess, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'access_id', metavar="", - help=_('ID of the NAS share access rule.') + help=_('ID of the NAS share access rule.'), ) # metadata --> properties in osc parser.add_argument( @@ -413,34 +451,44 @@ def get_parser(self, prog_name): metavar='', default={}, action=parseractions.KeyValueAction, - help=_('Set a property to this share access rule. ' - '(Repeat option to set multiple properties) ' - 'Available only for API microversion >= 2.45.'), + help=_( + 'Set a property to this share access rule. ' + '(Repeat option to set multiple properties) ' + 'Available only for API microversion >= 2.45.' + ), ) parser.add_argument( "--access-level", metavar="", default=None, choices=['rw', 'ro'], - help=_('Share access level ("rw" and "ro" access levels ' - 'are supported) to set.') + help=_( + 'Share access level ("rw" and "ro" access levels ' + 'are supported) to set.' + ), ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share - if (parsed_args.property and - share_client.api_version < api_versions.APIVersion("2.45")): + if ( + parsed_args.property + and share_client.api_version < api_versions.APIVersion("2.45") + ): raise exceptions.CommandError( "Setting properties to access rule is supported only " - "with API microversion 2.45 and higher") + "with API microversion 2.45 and higher" + ) - if (parsed_args.access_level and - share_client.api_version < api_versions.APIVersion("2.88")): + if ( + parsed_args.access_level + and share_client.api_version < api_versions.APIVersion("2.88") + ): raise exceptions.CommandError( "Setting access level to access rule is supported only " - "with API microversion 2.88 and higher") + "with API microversion 2.88 and higher" + ) access_rule = share_client.share_access_rules.get( parsed_args.access_id @@ -448,45 +496,51 @@ def take_action(self, parsed_args): if parsed_args.property: try: share_client.share_access_rules.set_metadata( - access_rule, - parsed_args.property) + access_rule, parsed_args.property + ) except Exception as e: raise exceptions.CommandError( "Failed to set properties to share access rule with ID " - "'%s': %s" % (access_rule.id, e)) + f"'{access_rule.id}': {e}" + ) if parsed_args.access_level: try: share_client.share_access_rules.set_access_level( - access_rule, - parsed_args.access_level) + access_rule, parsed_args.access_level + ) except Exception as e: raise exceptions.CommandError( "Failed to set access level to share access rule with ID " - "'%s': %s" % (access_rule.id, e)) + f"'{access_rule.id}': {e}" + ) class UnsetShareAccess(command.Command): """Unset properties of share access rule.""" + _description = _( "Unset properties of share access rule. " - "Available for API microversion 2.45 and higher") + "Available for API microversion 2.45 and higher" + ) def get_parser(self, prog_name): - parser = super(UnsetShareAccess, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'access_id', metavar="", - help=_('ID of the NAS share access rule.') + help=_('ID of the NAS share access rule.'), ) # metadata --> properties in osc parser.add_argument( '--property', metavar='', action='append', - help=_('Remove property from share access rule. ' - '(Repeat option to remove multiple properties) ' - 'Available only for API microversion >= 2.45.'), + help=_( + 'Remove property from share access rule. ' + '(Repeat option to remove multiple properties) ' + 'Available only for API microversion >= 2.45.' + ), ) return parser @@ -500,17 +554,20 @@ def take_action(self, parsed_args): if parsed_args.property: try: share_client.share_access_rules.unset_metadata( - access_rule, - parsed_args.property) + access_rule, parsed_args.property + ) except Exception as e: raise exceptions.CommandError( "Failed to unset properties for share access rule " - "with ID '%s': %s" % (access_rule.id, e)) + f"with ID '{access_rule.id}': {e}" + ) else: raise exceptions.CommandError( - "Please specify '--property ' to unset a property. ") + "Please specify '--property ' to unset a property. " + ) else: raise exceptions.CommandError( "Option to unset properties of access rule is available only " - "for API microversion 2.45 and higher") + "for API microversion 2.45 and higher" + ) diff --git a/manilaclient/osc/v2/share_backups.py b/manilaclient/osc/v2/share_backups.py index 8c9dc9e0..f3934a5c 100644 --- a/manilaclient/osc/v2/share_backups.py +++ b/manilaclient/osc/v2/share_backups.py @@ -20,55 +20,60 @@ from osc_lib import exceptions from osc_lib import utils as osc_utils +from manilaclient import api_versions from manilaclient.common._i18n import _ from manilaclient.common import constants from manilaclient.osc import utils + LOG = logging.getLogger(__name__) class CreateShareBackup(command.ShowOne): """Create a share backup.""" + _description = _("Create a backup of the given share") def get_parser(self, prog_name): - parser = super(CreateShareBackup, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "share", metavar="", - help=_("Name or ID of the share to backup.") + help=_("Name or ID of the share to backup."), ) parser.add_argument( '--name', metavar='', default=None, - help=_('Optional share backup name. (Default=None).') + help=_('Optional share backup name. (Default=None).'), ) parser.add_argument( '--description', metavar='', default=None, - help=_('Optional share backup description. (Default=None).') + help=_('Optional share backup description. (Default=None).'), ) parser.add_argument( "--backup-options", metavar="", default={}, action=parseractions.KeyValueAction, - help=_("Backup driver option key=value pairs (Optional, " - "Default=None)."), + help=_( + "Backup driver option key=value pairs (Optional, " + "Default=None)." + ), ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share - share = osc_utils.find_resource( - share_client.shares, parsed_args.share) + share = osc_utils.find_resource(share_client.shares, parsed_args.share) body = {} if parsed_args.backup_options: body['backup_options'] = utils.extract_key_value_options( - parsed_args.backup_options) + parsed_args.backup_options + ) if parsed_args.description: body['description'] = parsed_args.description if parsed_args.name: @@ -81,21 +86,22 @@ def take_action(self, parsed_args): class DeleteShareBackup(command.Command): """Delete one or more share backups.""" + _description = _("Delete one or more share backups") def get_parser(self, prog_name): - parser = super(DeleteShareBackup, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "backup", metavar="", nargs="+", - help=_("Name or ID of the backup(s) to delete") + help=_("Name or ID of the backup(s) to delete"), ) parser.add_argument( "--wait", action='store_true', default=False, - help=_("Wait for share backup deletion") + help=_("Wait for share backup deletion"), ) return parser @@ -106,70 +112,78 @@ def take_action(self, parsed_args): for backup in parsed_args.backup: try: share_backup_obj = osc_utils.find_resource( - share_client.share_backups, backup) + share_client.share_backups, backup + ) share_client.share_backups.delete(share_backup_obj) if parsed_args.wait: if not osc_utils.wait_for_delete( - manager=share_client.share_backups, - res_id=share_backup_obj.id): + manager=share_client.share_backups, + res_id=share_backup_obj.id, + ): result += 1 except Exception as e: result += 1 - LOG.error(_( - "Failed to delete a share backup with " - "name or ID '%(backup)s': %(e)s"), - {'backup': backup, 'e': e}) + LOG.error( + _( + "Failed to delete a share backup with " + "name or ID '%(backup)s': %(e)s" + ), + {'backup': backup, 'e': e}, + ) if result > 0: total = len(parsed_args.backup) - msg = (_("%(result)s of %(total)s backups failed " - "to delete.") % {'result': result, 'total': total}) + msg = _("%(result)s of %(total)s backups failed to delete.") % { + 'result': result, + 'total': total, + } raise exceptions.CommandError(msg) class ListShareBackup(command.Lister): """List share backups.""" + _description = _("List share backups") def get_parser(self, prog_name): - parser = super(ListShareBackup, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "--share", metavar="", default=None, - help=_("Name or ID of the share to list backups for.") + help=_("Name or ID of the share to list backups for."), ) parser.add_argument( "--name", metavar="", default=None, - help=_("Filter results by name. Default=None.") + help=_("Filter results by name. Default=None."), ) parser.add_argument( '--description', metavar="", default=None, - help=_("Filter results by description. Default=None.") + help=_("Filter results by description. Default=None."), ) parser.add_argument( "--name~", metavar="", default=None, - help=_("Filter results matching a share backup name pattern. ") + help=_("Filter results matching a share backup name pattern. "), ) parser.add_argument( '--description~', metavar="", default=None, - help=_("Filter results matching a share backup description ") + help=_("Filter results matching a share backup description "), ) parser.add_argument( '--status', metavar="", default=None, - help=_('Filter results by status. Default=None.') + help=_('Filter results by status. Default=None.'), ) parser.add_argument( "--limit", @@ -177,29 +191,36 @@ def get_parser(self, prog_name): type=int, default=None, action=parseractions.NonNegativeAction, - help=_("Limit the number of backups returned. Default=None.") + help=_("Limit the number of backups returned. Default=None."), ) parser.add_argument( '--offset', metavar="", default=None, - help='Start position of backup records listing.') + help='Start position of backup records listing.', + ) parser.add_argument( - '--sort-key', '--sort_key', + '--sort-key', + '--sort_key', metavar='', type=str, default=None, - help='Key to be sorted, available keys are %(keys)s. ' - 'Default=None.' - % {'keys': constants.BACKUP_SORT_KEY_VALUES}) + help=( + f'Key to be sorted, available keys are ' + f'{constants.BACKUP_SORT_KEY_VALUES}. Default=None.' + ), + ) parser.add_argument( - '--sort-dir', '--sort_dir', + '--sort-dir', + '--sort_dir', metavar='', type=str, default=None, - help='Sort direction, available values are %(values)s. ' - 'OPTIONAL: Default=None.' % { - 'values': constants.SORT_DIR_VALUES}) + help=( + f'Sort direction, available values are ' + f'{constants.SORT_DIR_VALUES}. OPTIONAL: Default=None.' + ), + ) parser.add_argument( '--detail', dest='detail', @@ -208,7 +229,8 @@ def get_parser(self, prog_name): type=int, const=1, default=0, - help="Show detailed information about share backups.") + help="Show detailed information about share backups.", + ) return parser def take_action(self, parsed_args): @@ -216,19 +238,25 @@ def take_action(self, parsed_args): share_id = None if parsed_args.share: - share_id = osc_utils.find_resource(share_client.shares, - parsed_args.share).id - columns = [ - 'ID', - 'Name', - 'Share ID', - 'Status' - ] + share_id = osc_utils.find_resource( + share_client.shares, parsed_args.share + ).id + columns = ['ID', 'Name', 'Share ID', 'Status'] if parsed_args.detail: - columns.extend(['Description', 'Size', 'Created At', - 'Updated At', 'Availability Zone', 'Progress', - 'Restore Progress', 'Host', 'Topic']) + columns.extend( + [ + 'Description', + 'Size', + 'Created At', + 'Updated At', + 'Availability Zone', + 'Progress', + 'Restore Progress', + 'Host', + 'Topic', + ] + ) search_opts = { 'limit': parsed_args.limit, @@ -243,86 +271,136 @@ def take_action(self, parsed_args): search_opts['description~'] = getattr(parsed_args, 'description~') backups = share_client.share_backups.list( - detailed=parsed_args.detail, search_opts=search_opts, - sort_key=parsed_args.sort_key, sort_dir=parsed_args.sort_dir) + detailed=parsed_args.detail, + search_opts=search_opts, + sort_key=parsed_args.sort_key, + sort_dir=parsed_args.sort_dir, + ) - return (columns, - (osc_utils.get_item_properties(b, columns) for b in backups)) + return ( + columns, + (osc_utils.get_item_properties(b, columns) for b in backups), + ) class ShowShareBackup(command.ShowOne): """Show share backup.""" + _description = _("Show details of a backup") def get_parser(self, prog_name): - parser = super(ShowShareBackup, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( - "backup", - metavar="", - help=_("ID of the share backup. ") + "backup", metavar="", help=_("ID of the share backup. ") ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share - backup = osc_utils.find_resource(share_client.share_backups, - parsed_args.backup) + backup = osc_utils.find_resource( + share_client.share_backups, parsed_args.backup + ) backup._info.pop('links', None) return self.dict2columns(backup._info) class RestoreShareBackup(command.Command): """Restore share backup to share""" + _description = _("Attempt to restore share backup") def get_parser(self, prog_name): - parser = super(RestoreShareBackup, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( - "backup", - metavar="", - help=_('ID of backup to restore.') + "backup", metavar="", help=_('ID of backup to restore.') + ) + parser.add_argument( + "--target-share", + metavar="", + default=None, + help=_( + 'share to restore backup to. Source share if none supplied' + ), + ) + parser.add_argument( + '--wait', + action='store_true', + default=False, + help=_('Wait for restore conclusion'), ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share + kwargs = {} + share_backup = osc_utils.find_resource( - share_client.share_backups, - parsed_args.backup) - share_client.share_backups.restore(share_backup.id) + share_client.share_backups, parsed_args.backup + ) + target_share_id = None + if parsed_args.target_share is not None: + if share_client.api_version < api_versions.APIVersion('2.91'): + raise exceptions.CommandError( + 'performing targeted restores is only available ' + 'for API microversion >= 2.91' + ) + else: + target_share_id = osc_utils.find_resource( + share_client.shares, parsed_args.target_share + ).id + kwargs['target_share_id'] = target_share_id + + share_client.share_backups.restore(share_backup.id, **kwargs) + + if parsed_args.wait: + if not osc_utils.wait_for_status( + status_f=share_client.shares.get, + res_id=(target_share_id or share_backup.share_id), + success_status=['available'], + error_status=['error', 'backup_restoring_error'], + ): + LOG.error(_("ERROR: share is in error state.")) class SetShareBackup(command.Command): """Set share backup properties.""" + _description = _("Set share backup properties") def get_parser(self, prog_name): - parser = super(SetShareBackup, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "backup", metavar="", - help=_('Name or ID of the backup to set a property for') + help=_('Name or ID of the backup to set a property for'), ) parser.add_argument( "--name", metavar="", default=None, - help=_("Set a name to the backup.") + help=_("Set a name to the backup."), ) parser.add_argument( "--description", metavar="", default=None, - help=_("Set a description to the backup.") + help=_("Set a description to the backup."), ) parser.add_argument( "--status", metavar="", - choices=['available', 'error', 'creating', 'deleting', - 'restoring'], - help=_("Assign a status to the backup(Admin only). " - "Options include : available, error, creating, " - "deleting, restoring.") + choices=[ + 'available', + 'error', + 'creating', + 'deleting', + 'restoring', + ], + help=_( + "Assign a status to the backup(Admin only). " + "Options include : available, error, creating, " + "deleting, restoring." + ), ) return parser @@ -331,8 +409,8 @@ def take_action(self, parsed_args): result = 0 share_backup = osc_utils.find_resource( - share_client.share_backups, - parsed_args.backup) + share_client.share_backups, parsed_args.backup + ) kwargs = {} @@ -345,57 +423,60 @@ def take_action(self, parsed_args): share_client.share_backups.update(share_backup, **kwargs) except Exception as e: result += 1 - LOG.error(_( - "Failed to set share backup properties " - "'%(properties)s': %(exception)s"), - {'properties': kwargs, - 'exception': e}) + LOG.error( + _( + "Failed to set share backup properties " + "'%(properties)s': %(exception)s" + ), + {'properties': kwargs, 'exception': e}, + ) if parsed_args.status: try: share_client.share_backups.reset_status( - share_backup, - parsed_args.status + share_backup, parsed_args.status ) except Exception as e: result += 1 - LOG.error(_( - "Failed to update backup status to " - "'%(status)s': %(e)s"), - {'status': parsed_args.status, 'e': e}) + LOG.error( + _("Failed to update backup status to '%(status)s': %(e)s"), + {'status': parsed_args.status, 'e': e}, + ) if result > 0: - raise exceptions.CommandError(_("One or more of the " - "set operations failed")) + raise exceptions.CommandError( + _("One or more of the set operations failed") + ) class UnsetShareBackup(command.Command): """Unset share backup properties.""" + _description = _("Unset share backup properties") def get_parser(self, prog_name): - parser = super(UnsetShareBackup, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "backup", metavar="", - help=_('Name or ID of the backup to unset a property for') + help=_('Name or ID of the backup to unset a property for'), ) parser.add_argument( "--name", action='store_true', - help=_("Unset a name to the backup.") + help=_("Unset a name to the backup."), ) parser.add_argument( "--description", action='store_true', - help=_("Unset a description to the backup.") + help=_("Unset a description to the backup."), ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share share_backup = osc_utils.find_resource( - share_client.share_backups, - parsed_args.backup) + share_client.share_backups, parsed_args.backup + ) kwargs = {} if parsed_args.name: @@ -409,8 +490,10 @@ def take_action(self, parsed_args): try: share_client.share_backups.update(share_backup, **kwargs) except Exception as e: - LOG.error(_( - "Failed to unset share backup properties " - "'%(properties)s': %(exception)s"), - {'properties': kwargs, - 'exception': e}) + LOG.error( + _( + "Failed to unset share backup properties " + "'%(properties)s': %(exception)s" + ), + {'properties': kwargs, 'exception': e}, + ) diff --git a/manilaclient/osc/v2/share_group_snapshots.py b/manilaclient/osc/v2/share_group_snapshots.py index 1680d490..5f3747b0 100644 --- a/manilaclient/osc/v2/share_group_snapshots.py +++ b/manilaclient/osc/v2/share_group_snapshots.py @@ -25,35 +25,35 @@ class CreateShareGroupSnapshot(command.ShowOne): """Create a share group snapshot.""" - _description = _( - "Create a share group snapshot of the given share group") + + _description = _("Create a share group snapshot of the given share group") def get_parser(self, prog_name): - parser = super( - CreateShareGroupSnapshot, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "share_group", metavar="", - help=_("Name or ID of the share group.") + help=_("Name or ID of the share group."), ) parser.add_argument( "--name", metavar="", default=None, - help=_("Optional share group snapshot name. (Default=None)") + help=_("Optional share group snapshot name. (Default=None)"), ) parser.add_argument( "--description", metavar="", default=None, - help=_("Optional share group snapshot description. " - "(Default=None)") + help=_( + "Optional share group snapshot description. (Default=None)" + ), ) parser.add_argument( '--wait', action='store_true', default=False, - help=_('Wait for share group snapshot creation') + help=_('Wait for share group snapshot creation'), ) return parser @@ -61,8 +61,8 @@ def take_action(self, parsed_args): share_client = self.app.client_manager.share share_group = osc_utils.find_resource( - share_client.share_groups, - parsed_args.share_group) + share_client.share_groups, parsed_args.share_group + ) share_group_snapshot = share_client.share_group_snapshots.create( share_group, @@ -73,13 +73,13 @@ def take_action(self, parsed_args): if not osc_utils.wait_for_status( status_f=share_client.share_group_snapshots.get, res_id=share_group_snapshot.id, - success_status=['available'] + success_status=['available'], ): LOG.error(_("ERROR: Share group snapshot is in error state.")) share_group_snapshot = osc_utils.find_resource( - share_client.share_group_snapshots, - share_group_snapshot.id) + share_client.share_group_snapshots, share_group_snapshot.id + ) data = share_group_snapshot._info data.pop('links', None) @@ -90,28 +90,31 @@ def take_action(self, parsed_args): class DeleteShareGroupSnapshot(command.Command): """Delete one or more share group snapshots.""" + _description = _("Delete one or more share group snapshot") def get_parser(self, prog_name): - parser = super(DeleteShareGroupSnapshot, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "share_group_snapshot", metavar="", nargs="+", - help=_("Name or ID of the group snapshot(s) to delete") + help=_("Name or ID of the group snapshot(s) to delete"), ) parser.add_argument( "--force", action='store_true', default=False, - help=_("Attempt to force delete the share group snapshot(s) " - "(Default=False) (Admin only).") + help=_( + "Attempt to force delete the share group snapshot(s) " + "(Default=False) (Admin only)." + ), ) parser.add_argument( "--wait", action='store_true', default=False, - help=_("Wait for share group snapshot deletion") + help=_("Wait for share group snapshot deletion"), ) return parser @@ -122,43 +125,46 @@ def take_action(self, parsed_args): for share_group_snapshot in parsed_args.share_group_snapshot: try: share_group_snapshot_obj = osc_utils.find_resource( - share_client.share_group_snapshots, - share_group_snapshot) + share_client.share_group_snapshots, share_group_snapshot + ) share_client.share_group_snapshots.delete( - share_group_snapshot_obj, - force=parsed_args.force) + share_group_snapshot_obj, force=parsed_args.force + ) if parsed_args.wait: if not osc_utils.wait_for_delete( - manager=share_client.share_group_snapshots, - res_id=share_group_snapshot_obj.id): + manager=share_client.share_group_snapshots, + res_id=share_group_snapshot_obj.id, + ): result += 1 except Exception as e: result += 1 LOG.error( 'Failed to delete a share group snapshot with ' - f'name or ID {share_group_snapshot}: {e}') + f'name or ID {share_group_snapshot}: {e}' + ) if result > 0: total = len(parsed_args.share_group_snapshot) - msg = (f'{result} of {total} share group snapshots failed ' - 'to delete.') + msg = ( + f'{result} of {total} share group snapshots failed to delete.' + ) raise exceptions.CommandError(msg) class ShowShareGroupSnapshot(command.ShowOne): """Display a share group snapshot""" - _description = _( - "Show details about a share group snapshot") + + _description = _("Show details about a share group snapshot") def get_parser(self, prog_name): - parser = super(ShowShareGroupSnapshot, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "share_group_snapshot", metavar="", - help=_("Name or ID of the share group snapshot to display") + help=_("Name or ID of the share group snapshot to display"), ) return parser @@ -167,7 +173,8 @@ def take_action(self, parsed_args): share_group_snapshot = osc_utils.find_resource( share_client.share_group_snapshots, - parsed_args.share_group_snapshot) + parsed_args.share_group_snapshot, + ) data = share_group_snapshot._info data.pop('links', None) @@ -178,36 +185,44 @@ def take_action(self, parsed_args): class SetShareGroupSnapshot(command.Command): """Set share group snapshot properties.""" + _description = _("Set share group snapshot properties") def get_parser(self, prog_name): - parser = super(SetShareGroupSnapshot, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "share_group_snapshot", metavar="", - help=_('Name or ID of the snapshot to set a property for') + help=_('Name or ID of the snapshot to set a property for'), ) parser.add_argument( "--name", metavar="", default=None, - help=_("Set a name to the snapshot.") + help=_("Set a name to the snapshot."), ) parser.add_argument( "--description", metavar="", default=None, - help=_("Set a description to the snapshot.") + help=_("Set a description to the snapshot."), ) parser.add_argument( "--status", metavar="", - choices=['available', 'error', 'creating', - 'deleting', 'error_deleting'], - help=_("Explicitly set the state of a share group snapshot" - "(Admin only). " - "Options include : available, error, creating, " - "deleting, error_deleting.") + choices=[ + 'available', + 'error', + 'creating', + 'deleting', + 'error_deleting', + ], + help=_( + "Explicitly set the state of a share group snapshot" + "(Admin only). " + "Options include : available, error, creating, " + "deleting, error_deleting." + ), ) return parser @@ -217,7 +232,8 @@ def take_action(self, parsed_args): share_group_snapshot = osc_utils.find_resource( share_client.share_group_snapshots, - parsed_args.share_group_snapshot) + parsed_args.share_group_snapshot, + ) kwargs = {} @@ -229,42 +245,46 @@ def take_action(self, parsed_args): if kwargs: try: share_client.share_group_snapshots.update( - share_group_snapshot, - **kwargs + share_group_snapshot, **kwargs ) except Exception as e: result += 1 - LOG.error('Failed to set name or desciption for ' - 'share group snapshot with ID ' - f'{share_group_snapshot.id}: {e}') + LOG.error( + 'Failed to set name or desciption for ' + 'share group snapshot with ID ' + f'{share_group_snapshot.id}: {e}' + ) if parsed_args.status: try: share_client.share_group_snapshots.reset_state( - share_group_snapshot, - parsed_args.status + share_group_snapshot, parsed_args.status ) except Exception as e: result += 1 - LOG.error('Failed to set status for ' - 'share group snapshot with ID ' - f'{share_group_snapshot.id}: {e}') + LOG.error( + 'Failed to set status for ' + 'share group snapshot with ID ' + f'{share_group_snapshot.id}: {e}' + ) if result > 0: - raise exceptions.CommandError(_( - "One or more of the set operations failed")) + raise exceptions.CommandError( + _("One or more of the set operations failed") + ) class UnsetShareGroupSnapshot(command.Command): """Unset a share group snapshot property.""" + _description = _("Unset a share group snapshot property") def get_parser(self, prog_name): - parser = super(UnsetShareGroupSnapshot, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "share_group_snapshot", metavar="", - help=_("Name or ID of the group snapshot to unset a property of") + help=_("Name or ID of the group snapshot to unset a property of"), ) parser.add_argument( "--name", @@ -283,7 +303,8 @@ def take_action(self, parsed_args): share_group_snapshot = osc_utils.find_resource( share_client.share_group_snapshots, - parsed_args.share_group_snapshot) + parsed_args.share_group_snapshot, + ) kwargs = {} if parsed_args.name: @@ -295,44 +316,45 @@ def take_action(self, parsed_args): if kwargs: try: share_client.share_group_snapshots.update( - share_group_snapshot, - **kwargs + share_group_snapshot, **kwargs ) except Exception as e: raise exceptions.CommandError( 'Failed to unset name or description for ' - f'share group snapshot : {e}') + f'share group snapshot : {e}' + ) class ListShareGroupSnapshot(command.Lister): """List share group snapshots.""" + _description = _("List share group snapshots") def get_parser(self, prog_name): - parser = super(ListShareGroupSnapshot, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "--all-projects", action='store_true', default=False, - help=_("Display information from all projects (Admin only).") + help=_("Display information from all projects (Admin only)."), ) parser.add_argument( "--name", metavar="", default=None, - help=_("Filter results by name.") + help=_("Filter results by name."), ) parser.add_argument( "--status", metavar="", default=None, - help=_("Filter results by status.") + help=_("Filter results by status."), ) parser.add_argument( "--share-group", metavar="", default=None, - help=_("Filter results by share group name or ID.") + help=_("Filter results by share group name or ID."), ) parser.add_argument( "--limit", @@ -340,26 +362,27 @@ def get_parser(self, prog_name): type=int, default=None, action=parseractions.NonNegativeAction, - help=_("Limit the number of share groups returned") + help=_("Limit the number of share groups returned"), ) parser.add_argument( "--marker", metavar="", - help=_("The last share group snapshot ID of the " - "previous page") + help=_("The last share group snapshot ID of the previous page"), ) parser.add_argument( '--sort', metavar="[:]", default='name:asc', - help=_("Sort output by selected keys and directions(asc or desc) " - "(default: name:asc), multiple keys and directions can be " - "specified separated by comma") + help=_( + "Sort output by selected keys and directions(asc or desc) " + "(default: name:asc), multiple keys and directions can be " + "specified separated by comma" + ), ) parser.add_argument( "--detailed", action="store_true", - help=_("Show detailed information about share group snapshot. ") + help=_("Show detailed information about share group snapshot. "), ) return parser @@ -369,8 +392,8 @@ def take_action(self, parsed_args): share_group_id = None if parsed_args.share_group: share_group_id = osc_utils.find_resource( - share_client.share_groups, - parsed_args.share_group).id + share_client.share_groups, parsed_args.share_group + ).id columns = [ 'ID', @@ -389,19 +412,23 @@ def take_action(self, parsed_args): } if parsed_args.detailed: - columns.extend([ - 'Created At', - 'Share Group ID', - ]) + columns.extend( + [ + 'Created At', + 'Share Group ID', + ] + ) if parsed_args.all_projects: columns.append('Project ID') share_group_snapshots = share_client.share_group_snapshots.list( - search_opts=search_opts) + search_opts=search_opts + ) share_group_snapshots = utils.sort_items( - share_group_snapshots, parsed_args.sort, str) + share_group_snapshots, parsed_args.sort, str + ) data = ( osc_utils.get_dict_properties(share_group_snapshot._info, columns) @@ -413,15 +440,15 @@ def take_action(self, parsed_args): class ListShareGroupSnapshotMembers(command.Lister): """List members for share group snapshot.""" + _description = _("List members of share group snapshot") def get_parser(self, prog_name): - parser = super( - ListShareGroupSnapshotMembers, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "share_group_snapshot", metavar="", - help=_("Name or ID of the group snapshot to list members for") + help=_("Name or ID of the group snapshot to list members for"), ) return parser @@ -432,7 +459,8 @@ def take_action(self, parsed_args): share_group_snapshot = osc_utils.find_resource( share_client.share_group_snapshots, - parsed_args.share_group_snapshot) + parsed_args.share_group_snapshot, + ) data = ( osc_utils.get_dict_properties(member, columns) diff --git a/manilaclient/osc/v2/share_group_type_access.py b/manilaclient/osc/v2/share_group_type_access.py index 1f46139e..10de8f51 100644 --- a/manilaclient/osc/v2/share_group_type_access.py +++ b/manilaclient/osc/v2/share_group_type_access.py @@ -25,21 +25,23 @@ class ShareGroupTypeAccessAllow(command.Command): """Allow a project to access a share group type.""" - _description = _("Allow a project to access a share group type " - "(Admin only).") + + _description = _( + "Allow a project to access a share group type (Admin only)." + ) def get_parser(self, prog_name): - parser = super(ShareGroupTypeAccessAllow, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'share_group_type', metavar="", - help=_("Share group type name or ID to allow access to.") + help=_("Share group type name or ID to allow access to."), ) parser.add_argument( 'projects', metavar="", nargs="+", - help=_("Project Name or ID to add share group type access for.") + help=_("Project Name or ID to add share group type access for."), ) identity_common.add_project_domain_option_to_parser(parser) return parser @@ -50,42 +52,52 @@ def take_action(self, parsed_args): result = 0 share_group_type = apiutils.find_resource( - share_client.share_group_types, parsed_args.share_group_type) + share_client.share_group_types, parsed_args.share_group_type + ) for project in parsed_args.projects: try: project_obj = identity_common.find_project( - identity_client, project, parsed_args.project_domain) + identity_client, project, parsed_args.project_domain + ) share_client.share_group_type_access.add_project_access( - share_group_type, project_obj.id) + share_group_type, project_obj.id + ) except Exception as e: result += 1 - LOG.error(_( - "Failed to allow access for project '%(project)s' " - "to share group type with name or ID " - "'%(share_group_type)s': %(e)s"), - {'project': project, - 'share_group_type': share_group_type, 'e': e}) + LOG.error( + _( + "Failed to allow access for project '%(project)s' " + "to share group type with name or ID " + "'%(share_group_type)s': %(e)s" + ), + { + 'project': project, + 'share_group_type': share_group_type, + 'e': e, + }, + ) if result > 0: total = len(parsed_args.projects) - msg = (_("Failed to allow access to " - "%(result)s of %(total)s projects") % {'result': result, - 'total': total}) + msg = _( + "Failed to allow access to %(result)s of %(total)s projects" + ) % {'result': result, 'total': total} raise exceptions.CommandError(msg) class ListShareGroupTypeAccess(command.Lister): """Get access list for share group type.""" + _description = _("Get access list for share group type (Admin only).") def get_parser(self, prog_name): - parser = super(ListShareGroupTypeAccess, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'share_group_type', metavar="", - help=_("Filter results by share group type name or ID.") + help=_("Filter results by share group type name or ID."), ) return parser @@ -93,11 +105,13 @@ def take_action(self, parsed_args): share_client = self.app.client_manager.share share_group_type = apiutils.find_resource( - share_client.share_group_types, parsed_args.share_group_type) + share_client.share_group_types, parsed_args.share_group_type + ) if share_group_type._info.get('is_public'): raise exceptions.CommandError( - 'Forbidden to get access list for public share group type.') + 'Forbidden to get access list for public share group type.' + ) data = share_client.share_group_type_access.list(share_group_type) @@ -109,22 +123,25 @@ def take_action(self, parsed_args): class ShareGroupTypeAccessDeny(command.Command): """Deny a project to access a share group type.""" - _description = _("Deny a project to access a share group type " - "(Admin only).") + + _description = _( + "Deny a project to access a share group type (Admin only)." + ) def get_parser(self, prog_name): - parser = super(ShareGroupTypeAccessDeny, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'share_group_type', metavar="", - help=_("Share group type name or ID to deny access from") + help=_("Share group type name or ID to deny access from"), ) parser.add_argument( 'projects', metavar="", nargs="+", - help=_("Project Name(s) or ID(s) " - "to deny share group type access for.") + help=_( + "Project Name(s) or ID(s) to deny share group type access for." + ), ) identity_common.add_project_domain_option_to_parser(parser) return parser @@ -135,29 +152,36 @@ def take_action(self, parsed_args): result = 0 share_group_type = apiutils.find_resource( - share_client.share_group_types, parsed_args.share_group_type) + share_client.share_group_types, parsed_args.share_group_type + ) for project in parsed_args.projects: try: project_obj = identity_common.find_project( - identity_client, - project, - parsed_args.project_domain) + identity_client, project, parsed_args.project_domain + ) share_client.share_group_type_access.remove_project_access( - share_group_type, project_obj.id) + share_group_type, project_obj.id + ) except Exception as e: result += 1 - LOG.error(_( - "Failed to deny access for project '%(project)s' " - "to share group type with name or ID " - "'%(share_group_type)s': %(e)s"), - {'project': project, - 'share_group_type': share_group_type, 'e': e}) + LOG.error( + _( + "Failed to deny access for project '%(project)s' " + "to share group type with name or ID " + "'%(share_group_type)s': %(e)s" + ), + { + 'project': project, + 'share_group_type': share_group_type, + 'e': e, + }, + ) if result > 0: total = len(parsed_args.projects) - msg = (_("Failed to deny access to " - "%(result)s of %(total)s projects") % {'result': result, - 'total': total}) + msg = _( + "Failed to deny access to %(result)s of %(total)s projects" + ) % {'result': result, 'total': total} raise exceptions.CommandError(msg) diff --git a/manilaclient/osc/v2/share_group_types.py b/manilaclient/osc/v2/share_group_types.py index 70e588b4..3edb2a32 100644 --- a/manilaclient/osc/v2/share_group_types.py +++ b/manilaclient/osc/v2/share_group_types.py @@ -29,32 +29,34 @@ 'share_types', 'visibility', 'is_default', - 'group_specs' + 'group_specs', ] class CreateShareGroupType(command.ShowOne): """Create new share group type.""" - _description = _( - "Create new share group type") + + _description = _("Create new share group type") log = logging.getLogger(__name__ + ".CreateShareGroupType") def get_parser(self, prog_name): - parser = super(CreateShareGroupType, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'name', metavar="", default=None, - help=_('Share group type name') + help=_('Share group type name'), ) parser.add_argument( "share_types", metavar="", nargs="+", default=None, - help=_("List of share type names or IDs. Example:" - " my-share-type-1 my-share-type-2"), + help=_( + "List of share type names or IDs. Example:" + " my-share-type-1 my-share-type-2" + ), ) parser.add_argument( "--group-specs", @@ -62,44 +64,48 @@ def get_parser(self, prog_name): nargs='*', metavar='', default=None, - help=_("Share Group type extra specs by key and value." - " OPTIONAL: Default=None. Example:" - " --group-specs consistent_snapshot_support=host."), + help=_( + "Share Group type extra specs by key and value." + " OPTIONAL: Default=None. Example:" + " --group-specs consistent_snapshot_support=host." + ), ) parser.add_argument( '--public', metavar="", default=True, - help=_('Make type accessible to the public (default true).') + help=_('Make type accessible to the public (default true).'), ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share - kwargs = { - 'name': parsed_args.name - } + kwargs = {'name': parsed_args.name} share_types_list = [] for share_type in parsed_args.share_types: try: share_type_obj = apiutils.find_resource( - share_client.share_types, - share_type) + share_client.share_types, share_type + ) share_types_list.append(share_type_obj.name) except Exception as e: - msg = LOG.error(_("Failed to find the share type with " - "name or ID '%(share_type)s': %(e)s"), - {'share_type': share_type, 'e': e}) - raise exceptions.CommandError(msg) + msg = _( + "Failed to find the share type with name or ID " + "'%(share_type)s': %(e)s" + ) + raise exceptions.CommandError( + msg % {'share_type': share_type, 'e': e} + ) kwargs['share_types'] = share_types_list if parsed_args.public: kwargs['is_public'] = strutils.bool_from_string( - parsed_args.public, default=True) + parsed_args.public, default=True + ) group_specs = {} if parsed_args.group_specs: @@ -113,25 +119,29 @@ def take_action(self, parsed_args): formatter = parsed_args.formatter formatted_group_type = utils.format_share_group_type( - share_group_type, formatter) + share_group_type, formatter + ) - return (ATTRIBUTES, oscutils.get_dict_properties( - formatted_group_type, ATTRIBUTES)) + return ( + ATTRIBUTES, + oscutils.get_dict_properties(formatted_group_type, ATTRIBUTES), + ) class DeleteShareGroupType(command.Command): """Delete a share group type.""" + _description = _("Delete a share group type") log = logging.getLogger(__name__ + ".DeleteShareGroupType") def get_parser(self, prog_name): - parser = super(DeleteShareGroupType, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'share_group_types', metavar="", nargs="+", - help=_("Name or ID of the share group type(s) to delete") + help=_("Name or ID of the share group type(s) to delete"), ) return parser @@ -142,38 +152,45 @@ def take_action(self, parsed_args): for share_group_type in parsed_args.share_group_types: try: share_group_type_obj = apiutils.find_resource( - share_client.share_group_types, - share_group_type) + share_client.share_group_types, share_group_type + ) share_client.share_group_types.delete(share_group_type_obj) except Exception as e: result += 1 - LOG.error(_( - "Failed to delete share group type with " - "name or ID '%(share_group_type)s': %(e)s"), - {'share_group_type': share_group_type, 'e': e}) + LOG.error( + _( + "Failed to delete share group type with " + "name or ID '%(share_group_type)s': %(e)s" + ), + {'share_group_type': share_group_type, 'e': e}, + ) if result > 0: total = len(parsed_args.share_group_types) - msg = (_("%(result)s of %(total)s share group types failed " - "to delete.") % {'result': result, 'total': total}) + msg = _( + "%(result)s of %(total)s share group types failed to delete." + ) % {'result': result, 'total': total} raise exceptions.CommandError(msg) class ListShareGroupType(command.Lister): """List Share Group Types.""" + _description = _("List share types") log = logging.getLogger(__name__ + ".ListShareGroupType") def get_parser(self, prog_name): - parser = super(ListShareGroupType, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( '--all', action='store_true', default=False, - help=_('Display all share group types whether public or private. ' - 'Default=False. (Admin only)'), + help=_( + 'Display all share group types whether public or private. ' + 'Default=False. (Admin only)' + ), ) parser.add_argument( '--group-specs', @@ -192,40 +209,44 @@ def take_action(self, parsed_args): if parsed_args.group_specs: search_opts = { 'group_specs': utils.extract_group_specs( - extra_specs={}, - specs_to_add=parsed_args.group_specs) + extra_specs={}, specs_to_add=parsed_args.group_specs + ) } formatter = parsed_args.formatter share_group_types = share_client.share_group_types.list( - search_opts=search_opts, - show_all=parsed_args.all) + search_opts=search_opts, show_all=parsed_args.all + ) formatted_types = [] for share_group_type in share_group_types: - formatted_types.append(utils.format_share_group_type( - share_group_type, formatter)) + formatted_types.append( + utils.format_share_group_type(share_group_type, formatter) + ) column_headers = utils.format_column_headers(ATTRIBUTES) - values = (oscutils.get_dict_properties( - sgt, ATTRIBUTES) for sgt in formatted_types) + values = ( + oscutils.get_dict_properties(sgt, ATTRIBUTES) + for sgt in formatted_types + ) return (column_headers, values) class ShowShareGroupType(command.ShowOne): """Show Share Group Types.""" + _description = _("Show share group types") log = logging.getLogger(__name__ + ".ShowShareGroupType") def get_parser(self, prog_name): - parser = super(ShowShareGroupType, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'share_group_type', metavar="", - help=_("Name or ID of the share group type to show") + help=_("Name or ID of the share group type to show"), ) return parser @@ -233,32 +254,38 @@ def take_action(self, parsed_args): share_client = self.app.client_manager.share share_group_type = apiutils.find_resource( - share_client.share_group_types, parsed_args.share_group_type) + share_client.share_group_types, parsed_args.share_group_type + ) share_group_type_obj = share_client.share_group_types.get( - share_group_type) + share_group_type + ) formatter = parsed_args.formatter formatted_group_type = utils.format_share_group_type( - share_group_type_obj, formatter) + share_group_type_obj, formatter + ) - return (ATTRIBUTES, oscutils.get_dict_properties( - formatted_group_type, ATTRIBUTES)) + return ( + ATTRIBUTES, + oscutils.get_dict_properties(formatted_group_type, ATTRIBUTES), + ) class SetShareGroupType(command.Command): """Set share type properties.""" + _description = _("Set share group type properties") log = logging.getLogger(__name__ + ".SetShareGroupType") def get_parser(self, prog_name): - parser = super(SetShareGroupType, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'share_group_type', metavar="", - help=_("Name or ID of the share group type to modify") + help=_("Name or ID of the share group type to modify"), ) parser.add_argument( "--group-specs", @@ -266,9 +293,11 @@ def get_parser(self, prog_name): nargs='*', metavar='', default=None, - help=_("Extra specs key and value of share group type that will be" - " used for share type creation. OPTIONAL: Default=None." - " Example: --group-specs consistent-snapshot-support=True"), + help=_( + "Extra specs key and value of share group type that will be" + " used for share type creation. OPTIONAL: Default=None." + " Example: --group-specs consistent-snapshot-support=True" + ), ) return parser @@ -277,41 +306,43 @@ def take_action(self, parsed_args): try: share_group_type_obj = apiutils.find_resource( - share_client.share_group_types, parsed_args.share_group_type) + share_client.share_group_types, parsed_args.share_group_type + ) except Exception as e: - msg = LOG.error(_( + msg = _( "Failed to find the share group type with " - "name or ID '%(share_group_type)s': %(e)s"), - {'share_group_type': parsed_args.share_group_type, 'e': e}) - raise exceptions.CommandError(msg) - kwargs = {} - - if kwargs: - share_group_type_obj.set_keys(**kwargs) + "name or ID '%(share_group_type)s': %(e)s" + ) + raise exceptions.CommandError( + msg + % {'share_group_type': parsed_args.share_group_type, 'e': e} + ) if parsed_args.group_specs: group_specs = utils.extract_group_specs( - extra_specs={}, - specs_to_add=parsed_args.group_specs) + extra_specs={}, specs_to_add=parsed_args.group_specs + ) try: share_group_type_obj.set_keys(group_specs) except Exception as e: raise exceptions.CommandError( - "Failed to set share group type key: %s" % e) + f"Failed to set share group type key: {e}" + ) class UnsetShareGroupType(command.Command): """Unset share group type extra specs.""" + _description = _("Unset share group type extra specs") log = logging.getLogger(__name__ + ".UnsetShareGroupType") def get_parser(self, prog_name): - parser = super(UnsetShareGroupType, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'share_group_type', metavar="", - help=_("Name or ID of the share grouptype to modify") + help=_("Name or ID of the share grouptype to modify"), ) parser.add_argument( 'group_specs', @@ -326,17 +357,22 @@ def take_action(self, parsed_args): try: share_group_type_obj = apiutils.find_resource( - share_client.share_group_types, parsed_args.share_group_type) + share_client.share_group_types, parsed_args.share_group_type + ) except Exception as e: - msg = LOG.error(_( + msg = _( "Failed to find the share group type with " - "name or ID '%(share_group_type)s': %(e)s"), - {'share_group_type': parsed_args.share_group_type, 'e': e}) - raise exceptions.CommandError(msg) + "name or ID '%(share_group_type)s': %(e)s" + ) + raise exceptions.CommandError( + msg + % {'share_group_type': parsed_args.share_group_type, 'e': e} + ) if parsed_args.group_specs: try: share_group_type_obj.unset_keys(parsed_args.group_specs) except Exception as e: raise exceptions.CommandError( - "Failed to remove share type group extra spec: %s" % e) + f"Failed to remove share type group extra spec: {e}" + ) diff --git a/manilaclient/osc/v2/share_groups.py b/manilaclient/osc/v2/share_groups.py index 35ba1cb7..175a29d9 100644 --- a/manilaclient/osc/v2/share_groups.py +++ b/manilaclient/osc/v2/share_groups.py @@ -25,16 +25,16 @@ class CreateShareGroup(command.ShowOne): """Create new share group.""" - _description = _( - "Create new share group") + + _description = _("Create new share group") def get_parser(self, prog_name): - parser = super(CreateShareGroup, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( '--name', metavar="", default=None, - help=_('Share group name') + help=_('Share group name'), ) parser.add_argument( "--description", @@ -53,8 +53,9 @@ def get_parser(self, prog_name): "--share-group-type", metavar="", default=None, - help=_("Share group type name or ID of the share " - "group to be created."), + help=_( + "Share group type name or ID of the share group to be created." + ), ) parser.add_argument( "--share-network", @@ -66,21 +67,24 @@ def get_parser(self, prog_name): "--source-share-group-snapshot", metavar="", default=False, - help=_("Share group snapshot name or ID to create " - "the share group from."), + help=_( + "Share group snapshot name or ID to create " + "the share group from." + ), ) parser.add_argument( "--availability-zone", metavar='', default=None, - help=_("Optional availability zone in which group " - "should be created"), + help=_( + "Optional availability zone in which group should be created" + ), ) parser.add_argument( "--wait", action='store_true', default=False, - help=_('Wait for share group creation') + help=_('Wait for share group creation'), ) return parser @@ -98,20 +102,21 @@ def take_action(self, parsed_args): share_group_type = None if parsed_args.share_group_type: share_group_type = osc_utils.find_resource( - share_client.share_group_types, - parsed_args.share_group_type).id + share_client.share_group_types, parsed_args.share_group_type + ).id share_network = None if parsed_args.share_network: share_network = osc_utils.find_resource( - share_client.share_networks, - parsed_args.share_network).id + share_client.share_networks, parsed_args.share_network + ).id source_share_group_snapshot = None if parsed_args.source_share_group_snapshot: source_share_group_snapshot = osc_utils.find_resource( share_client.share_group_snapshots, - parsed_args.source_share_group_snapshot).id + parsed_args.source_share_group_snapshot, + ).id body = { 'name': parsed_args.name, @@ -120,7 +125,7 @@ def take_action(self, parsed_args): 'share_group_type': share_group_type, 'share_network': share_network, 'source_share_group_snapshot': source_share_group_snapshot, - 'availability_zone': parsed_args.availability_zone + 'availability_zone': parsed_args.availability_zone, } share_group = share_client.share_groups.create(**body) @@ -129,21 +134,21 @@ def take_action(self, parsed_args): if not osc_utils.wait_for_status( status_f=share_client.share_groups.get, res_id=share_group.id, - success_status=['available'] + success_status=['available'], ): LOG.error(_("ERROR: Share group is in error state.")) share_group = osc_utils.find_resource( - share_client.share_groups, - share_group.id) + share_client.share_groups, share_group.id + ) printable_share_group = share_group._info printable_share_group.pop('links', None) if printable_share_group.get('share_types'): if parsed_args.formatter == 'table': - printable_share_group['share_types'] = ( - "\n".join(printable_share_group['share_types']) + printable_share_group['share_types'] = "\n".join( + printable_share_group['share_types'] ) return self.dict2columns(printable_share_group) @@ -151,28 +156,31 @@ def take_action(self, parsed_args): class DeleteShareGroup(command.Command): """Delete one or more share groups.""" + _description = _("Delete one or more share groups") def get_parser(self, prog_name): - parser = super(DeleteShareGroup, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "share_group", metavar="", nargs="+", - help=_("Name or ID of the share group(s) to delete") + help=_("Name or ID of the share group(s) to delete"), ) parser.add_argument( "--force", action='store_true', default=False, - help=_("Attempt to force delete the share group (Default=False) " - "(Admin only).") + help=_( + "Attempt to force delete the share group (Default=False) " + "(Admin only)." + ), ) parser.add_argument( "--wait", action='store_true', default=False, - help=_("Wait for share group to delete") + help=_("Wait for share group to delete"), ) return parser @@ -183,105 +191,118 @@ def take_action(self, parsed_args): for share_group in parsed_args.share_group: try: share_group_obj = osc_utils.find_resource( - share_client.share_groups, - share_group) + share_client.share_groups, share_group + ) share_client.share_groups.delete( - share_group_obj, - force=parsed_args.force) + share_group_obj, force=parsed_args.force + ) if parsed_args.wait: if not osc_utils.wait_for_delete( - manager=share_client.share_groups, - res_id=share_group_obj.id): + manager=share_client.share_groups, + res_id=share_group_obj.id, + ): result += 1 except Exception as e: result += 1 - LOG.error(_( - "Failed to delete share group with " - "name or ID '%(share_group)s': %(e)s"), - {'share_group': share_group, 'e': e}) + LOG.error( + _( + "Failed to delete share group with " + "name or ID '%(share_group)s': %(e)s" + ), + {'share_group': share_group, 'e': e}, + ) if result > 0: total = len(parsed_args.share_group) - msg = (_("%(result)s of %(total)s share groups failed " - "to delete.") % {'result': result, 'total': total}) + msg = _( + "%(result)s of %(total)s share groups failed to delete." + ) % {'result': result, 'total': total} raise exceptions.CommandError(msg) class ListShareGroup(command.Lister): """List share groups.""" + _description = _("List share groups") def get_parser(self, prog_name): - parser = super(ListShareGroup, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "--all-projects", action='store_true', default=False, - help=_("Display share groups from all projects (Admin only).") + help=_("Display share groups from all projects (Admin only)."), ) parser.add_argument( "--name", metavar="", default=None, - help=_("Filter results by name.") + help=_("Filter results by name."), ) parser.add_argument( "--description", metavar="", default=None, - help=_("Filter results by description. Available " - "only for microversion >= 2.36.") + help=_( + "Filter results by description. Available " + "only for microversion >= 2.36." + ), ) parser.add_argument( "--status", metavar="", default=None, - help=_("Filter results by status.") + help=_("Filter results by status."), ) parser.add_argument( "--share-server", metavar="", default=None, - help=_("Filter results by share server ID.") + help=_("Filter results by share server ID."), ) parser.add_argument( "--share-group-type", metavar="", default=None, - help=_("Filter results by a share group type ID " - "or name that was used for share group " - "creation. ") + help=_( + "Filter results by a share group type ID " + "or name that was used for share group " + "creation. " + ), ) parser.add_argument( "--snapshot", metavar="", default=None, - help=_("Filter results by share group snapshot " - "name or ID that was used to create the " - "share group. ") + help=_( + "Filter results by share group snapshot " + "name or ID that was used to create the " + "share group. " + ), ) parser.add_argument( "--host", metavar="", default=None, - help=_("Filter results by host.") + help=_("Filter results by host."), ) parser.add_argument( "--share-network", metavar="", default=None, - help=_("Filter results by share-network name or " - "ID. ") + help=_("Filter results by share-network name or ID. "), ) parser.add_argument( "--project", metavar="", default=None, - help=_("Filter results by project name or ID. Useful with " - "set key '--all-projects'. ") + help=_( + "Filter results by project name or ID. Useful with " + "set key '--all-projects'. " + ), ) identity_common.add_project_domain_option_to_parser(parser) parser.add_argument( @@ -290,36 +311,42 @@ def get_parser(self, prog_name): type=int, default=None, action=parseractions.NonNegativeAction, - help=_("Limit the number of share groups returned") + help=_("Limit the number of share groups returned"), ) parser.add_argument( "--marker", metavar="", - help=_("The last share group ID of the previous page") + help=_("The last share group ID of the previous page"), ) parser.add_argument( '--sort', metavar="[:]", default='name:asc', - help=_("Sort output by selected keys and directions(asc or desc) " - "(default: name:asc), multiple keys and directions can be " - "specified separated by comma") + help=_( + "Sort output by selected keys and directions(asc or desc) " + "(default: name:asc), multiple keys and directions can be " + "specified separated by comma" + ), ) parser.add_argument( "--name~", metavar="", default=None, - help=_("Filter results matching a share group " - "name pattern. Available only for " - "microversion >= 2.36. ") + help=_( + "Filter results matching a share group " + "name pattern. Available only for " + "microversion >= 2.36. " + ), ) parser.add_argument( "--description~", metavar="", default=None, - help=_("Filter results matching a share group " - "description pattern. Available only for " - "microversion >= 2.36. ") + help=_( + "Filter results matching a share group " + "description pattern. Available only for " + "microversion >= 2.36. " + ), ) return parser @@ -330,33 +357,34 @@ def take_action(self, parsed_args): share_server_id = None if parsed_args.share_server: share_server_id = osc_utils.find_resource( - share_client.share_servers, - parsed_args.share_server).id + share_client.share_servers, parsed_args.share_server + ).id share_group_type = None if parsed_args.share_group_type: share_group_type = osc_utils.find_resource( - share_client.share_group_types, - parsed_args.share_group_type).id + share_client.share_group_types, parsed_args.share_group_type + ).id snapshot = None if parsed_args.snapshot: - snapshot = apiutils.find_resource( - share_client.share_snapshots, - parsed_args.snapshot).id + snapshot = osc_utils.find_resource( + share_client.share_snapshots, parsed_args.snapshot + ).id share_network = None if parsed_args.share_network: share_network = osc_utils.find_resource( - share_client.share_networks, - parsed_args.share_network).id + share_client.share_networks, parsed_args.share_network + ).id project_id = None if parsed_args.project: project_id = identity_common.find_project( identity_client, parsed_args.project, - parsed_args.project_domain).id + parsed_args.project_domain, + ).id columns = [ 'ID', @@ -383,32 +411,39 @@ def take_action(self, parsed_args): search_opts['name~'] = getattr(parsed_args, 'name~') search_opts['description~'] = getattr(parsed_args, 'description~') search_opts['description'] = parsed_args.description - elif (parsed_args.description or getattr(parsed_args, 'name~') or - getattr(parsed_args, 'description~')): + elif ( + parsed_args.description + or getattr(parsed_args, 'name~') + or getattr(parsed_args, 'description~') + ): raise exceptions.CommandError( "Pattern based filtering (name~, description~ and description)" - " is only available with manila API version >= 2.36") + " is only available with manila API version >= 2.36" + ) if parsed_args.all_projects: columns.append('Project ID') share_groups = share_client.share_groups.list(search_opts=search_opts) - data = (osc_utils.get_dict_properties( - share_group._info, columns) for share_group in share_groups) + data = ( + osc_utils.get_dict_properties(share_group._info, columns) + for share_group in share_groups + ) return (columns, data) class ShowShareGroup(command.ShowOne): """Show share group.""" + _description = _("Show details about a share group") def get_parser(self, prog_name): - parser = super(ShowShareGroup, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "share_group", metavar="", - help=_("Name or ID of the share group.") + help=_("Name or ID of the share group."), ) return parser @@ -416,8 +451,8 @@ def take_action(self, parsed_args): share_client = self.app.client_manager.share share_group = osc_utils.find_resource( - share_client.share_groups, - parsed_args.share_group) + share_client.share_groups, parsed_args.share_group + ) printable_share_group = share_group._info printable_share_group.pop('links', None) @@ -425,41 +460,45 @@ def take_action(self, parsed_args): if printable_share_group.get('share_types'): if parsed_args.formatter == 'table': printable_share_group['share_types'] = "\n".join( - printable_share_group['share_types']) + printable_share_group['share_types'] + ) return self.dict2columns(printable_share_group) class SetShareGroup(command.Command): """Set share group.""" + _description = _("Explicitly set share group status") def get_parser(self, prog_name): - parser = super(SetShareGroup, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'share_group', metavar="", - help=_('Name or ID of the share group to update.') + help=_('Name or ID of the share group to update.'), ) parser.add_argument( '--name', metavar="", default=None, - help=_('New name for the share group. (Default=None)') + help=_('New name for the share group. (Default=None)'), ) parser.add_argument( '--description', metavar='', default=None, - help=_('Share group description. (Default=None)') + help=_('Share group description. (Default=None)'), ) parser.add_argument( '--status', metavar='', default=None, - help=_('Explicitly update the status of a share group (Admin ' - 'only). Examples include: available, error, creating, ' - 'deleting, error_deleting.') + help=_( + 'Explicitly update the status of a share group (Admin ' + 'only). Examples include: available, error, creating, ' + 'deleting, error_deleting.' + ), ) return parser @@ -468,8 +507,8 @@ def take_action(self, parsed_args): result = 0 share_group = osc_utils.find_resource( - share_client.share_groups, - parsed_args.share_group) + share_client.share_groups, parsed_args.share_group + ) kwargs = {} if parsed_args.name is not None: @@ -478,38 +517,37 @@ def take_action(self, parsed_args): kwargs['description'] = parsed_args.description if kwargs: try: - share_client.share_groups.update( - share_group.id, - **kwargs - ) + share_client.share_groups.update(share_group.id, **kwargs) except Exception as e: - LOG.error(_("Failed to update share group name " - "or description: %s"), e) + LOG.error( + _("Failed to update share group name or description: %s"), + e, + ) result += 1 if parsed_args.status: try: share_group.reset_state(parsed_args.status) except Exception as e: - LOG.error(_( - "Failed to set status for the share group: %s"), e) + LOG.error(_("Failed to set status for the share group: %s"), e) result += 1 if result > 0: - raise exceptions.CommandError(_("One or more of the " - "set operations failed")) + raise exceptions.CommandError( + _("One or more of the set operations failed") + ) class UnsetShareGroup(command.Command): """Unset a share group property.""" + _description = _("Unset a share group property") def get_parser(self, prog_name): - parser = super(UnsetShareGroup, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'share_group', metavar="", - help=_("Name or ID of the share group " - "to set a property for.") + help=_("Name or ID of the share group to set a property for."), ) parser.add_argument( "--name", @@ -527,8 +565,8 @@ def take_action(self, parsed_args): share_client = self.app.client_manager.share share_group = osc_utils.find_resource( - share_client.share_groups, - parsed_args.share_group) + share_client.share_groups, parsed_args.share_group + ) kwargs = {} if parsed_args.name: @@ -537,11 +575,9 @@ def take_action(self, parsed_args): kwargs['description'] = None if kwargs: try: - share_client.share_groups.update( - share_group, - **kwargs - ) + share_client.share_groups.update(share_group, **kwargs) except Exception as e: - raise exceptions.CommandError(_( - "Failed to unset share_group name " - "or description : %s" % e)) + msg = _( + "Failed to unset share_group name or description: %(e)s" + ) + raise exceptions.CommandError(msg % {'e': e}) diff --git a/manilaclient/osc/v2/share_instance_export_locations.py b/manilaclient/osc/v2/share_instance_export_locations.py index e8e75b70..a2ab3ad9 100644 --- a/manilaclient/osc/v2/share_instance_export_locations.py +++ b/manilaclient/osc/v2/share_instance_export_locations.py @@ -21,15 +21,15 @@ class ShareInstanceListExportLocation(command.Lister): """List share instance export locations.""" + _description = _("List share instance export locations") def get_parser(self, prog_name): - parser = super( - ShareInstanceListExportLocation, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "instance", metavar="", - help=_("ID of the share instance.") + help=_("ID of the share instance."), ) return parser @@ -37,12 +37,12 @@ def take_action(self, parsed_args): share_client = self.app.client_manager.share instance = osc_utils.find_resource( - share_client.share_instances, - parsed_args.instance) + share_client.share_instances, parsed_args.instance + ) export_locations = share_client.share_instance_export_locations.list( - instance, - search_opts=None) + instance, search_opts=None + ) columns = [ 'ID', @@ -61,21 +61,20 @@ def take_action(self, parsed_args): class ShareInstanceShowExportLocation(command.ShowOne): """Display the export location for a share instance.""" - _description = _( - "Show export location for a share instance.") + + _description = _("Show export location for a share instance.") def get_parser(self, prog_name): - parser = super( - ShareInstanceShowExportLocation, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "instance", metavar="", - help=_("Name or ID of the share instance") + help=_("Name or ID of the share instance"), ) parser.add_argument( "export_location", metavar="", - help=_("ID of the share instance export location.") + help=_("ID of the share instance export location."), ) return parser @@ -83,13 +82,13 @@ def take_action(self, parsed_args): share_client = self.app.client_manager.share share_instance = osc_utils.find_resource( - share_client.share_instances, - parsed_args.instance) + share_client.share_instances, parsed_args.instance + ) share_instance_export_locations = ( share_client.share_instance_export_locations.get( - share_instance.id, - parsed_args.export_location) + share_instance.id, parsed_args.export_location + ) ) data = share_instance_export_locations._info diff --git a/manilaclient/osc/v2/share_instances.py b/manilaclient/osc/v2/share_instances.py index 2f48c667..06e91a45 100644 --- a/manilaclient/osc/v2/share_instances.py +++ b/manilaclient/osc/v2/share_instances.py @@ -27,21 +27,22 @@ class ShareInstanceDelete(command.Command): """Forces the deletion of the share instance.""" + _description = _("Forces the deletion of a share instance") def get_parser(self, prog_name): - parser = super(ShareInstanceDelete, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'instance', metavar="", nargs="+", - help=_('ID of the share instance to delete.') + help=_('ID of the share instance to delete.'), ) parser.add_argument( "--wait", action='store_true', default=False, - help=_("Wait for share instance deletion.") + help=_("Wait for share instance deletion."), ) return parser @@ -52,48 +53,57 @@ def take_action(self, parsed_args): for instance in parsed_args.instance: try: share_instance = apiutils.find_resource( - share_client.share_instances, instance) + share_client.share_instances, instance + ) share_client.share_instances.force_delete(share_instance) if parsed_args.wait: if not osc_utils.wait_for_delete( - manager=share_client.share_instances, - res_id=share_instance.id): + manager=share_client.share_instances, + res_id=share_instance.id, + ): number_of_deletion_failures += 1 except Exception as e: number_of_deletion_failures += 1 - LOG.error(_( - "Failed to delete a share instance with " - "ID '%(instance)s': %(e)s"), - {'instance': instance, 'e': e}) + LOG.error( + _( + "Failed to delete a share instance with " + "ID '%(instance)s': %(e)s" + ), + {'instance': instance, 'e': e}, + ) if number_of_deletion_failures > 0: - msg = (_("%(number_of_deletion_failures)s of " - "%(total_of_instances)s instances failed " - "to delete.") % { + msg = _( + "%(number_of_deletion_failures)s of " + "%(total_of_instances)s instances failed " + "to delete." + ) % { 'number_of_deletion_failures': number_of_deletion_failures, - 'total_of_instances': len(parsed_args.instance)}) + 'total_of_instances': len(parsed_args.instance), + } raise exceptions.CommandError(msg) class ShareInstanceList(command.Lister): """List share instances.""" + _description = _("List share instances") def get_parser(self, prog_name): - parser = super(ShareInstanceList, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "--share", metavar="", default=None, - help=_("Name or ID of the share to list instances for.") + help=_("Name or ID of the share to list instances for."), ) parser.add_argument( "--export-location", metavar="", default=None, - help=_("Export location to list instances for.") + help=_("Export location to list instances for."), ) return parser @@ -106,7 +116,8 @@ def take_action(self, parsed_args): if parsed_args.share: # Check if the share exists share = osc_utils.find_resource( - share_client.shares, parsed_args.share) + share_client.shares, parsed_args.share + ) instances = share_client.shares.list_instances(share) else: @@ -114,7 +125,8 @@ def take_action(self, parsed_args): if parsed_args.export_location: raise exceptions.CommandError( "Filtering by export location is only " - "available with manila API version >= 2.35") + "available with manila API version >= 2.35" + ) else: if parsed_args.export_location: kwargs['export_location'] = parsed_args.export_location @@ -131,8 +143,10 @@ def take_action(self, parsed_args): 'Share Type ID', ] - data = (osc_utils.get_dict_properties( - instance._info, columns) for instance in instances) + data = ( + osc_utils.get_dict_properties(instance._info, columns) + for instance in instances + ) return (columns, data) @@ -143,19 +157,20 @@ class ShareInstanceSet(command.Command): _description = _("Explicitly reset share instance status") def get_parser(self, prog_name): - parser = super(ShareInstanceSet, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "instance", metavar="", - help=_("Instance to be modified.") + help=_("Instance to be modified."), ) parser.add_argument( "--status", metavar="", - help=_('Indicate which state to assign the instance. Options are: ' - 'available, error, creating, deleting,' - 'error_deleting, migrating, migrating_to, server_migrating.' - ) + help=_( + 'Indicate which state to assign the instance. Options are: ' + 'available, error, creating, deleting,' + 'error_deleting, migrating, migrating_to, server_migrating.' + ), ) return parser @@ -163,36 +178,38 @@ def take_action(self, parsed_args): share_client = self.app.client_manager.share instance = osc_utils.find_resource( - share_client.share_instances, - parsed_args.instance) + share_client.share_instances, parsed_args.instance + ) if parsed_args.status: try: share_client.share_instances.reset_state( - instance, - parsed_args.status + instance, parsed_args.status ) except Exception as e: - LOG.error(_( - "Failed to set status '%(status)s': %(exception)s"), - {'status': parsed_args.status, 'exception': e}) + LOG.error( + _("Failed to set status '%(status)s': %(exception)s"), + {'status': parsed_args.status, 'exception': e}, + ) raise exceptions.CommandError(_("Set operation failed")) if not instance or not parsed_args.status: - raise exceptions.CommandError(_( - "Nothing to set. Please define a '--status'.")) + raise exceptions.CommandError( + _("Nothing to set. Please define a '--status'.") + ) class ShareInstanceShow(command.ShowOne): """Show share instance.""" + _description = _("Show share instance") def get_parser(self, prog_name): - parser = super(ShareInstanceShow, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "instance", metavar="", - help=_("ID of the share instance.") + help=_("ID of the share instance."), ) return parser @@ -200,11 +217,12 @@ def take_action(self, parsed_args): share_client = self.app.client_manager.share instance = osc_utils.find_resource( - share_client.share_instances, - parsed_args.instance) + share_client.share_instances, parsed_args.instance + ) export_locations = share_client.share_instance_export_locations.list( - instance) + instance + ) instance._info['export_locations'] = [] for export_location in export_locations: @@ -214,7 +232,9 @@ def take_action(self, parsed_args): if parsed_args.formatter == 'table': instance._info['export_locations'] = ( cliutils.convert_dict_list_to_string( - instance._info['export_locations'])) + instance._info['export_locations'] + ) + ) instance._info.pop('links', None) diff --git a/manilaclient/osc/v2/share_limits.py b/manilaclient/osc/v2/share_limits.py index 1a3ff305..a93d4544 100644 --- a/manilaclient/osc/v2/share_limits.py +++ b/manilaclient/osc/v2/share_limits.py @@ -24,20 +24,20 @@ class ShareLimitsShow(command.Lister): _description = _("Show a list of share limits for a user.") def get_parser(self, prog_name): - parser = super(ShareLimitsShow, self).get_parser(prog_name) + parser = super().get_parser(prog_name) limit_type_group = parser.add_mutually_exclusive_group(required=True) limit_type_group.add_argument( '--absolute', action='store_true', default=False, - help=_('Get the absolute limits for the user') + help=_('Get the absolute limits for the user'), ) limit_type_group.add_argument( '--rate', action='store_true', default=False, - help=_('Get the API rate limits for the user') + help=_('Get the API rate limits for the user'), ) return parser @@ -66,5 +66,7 @@ def take_action(self, parsed_args): data = list(share_client.limits.get().absolute) - return (columns, (oscutils.get_item_properties(s, columns) - for s in data)) + return ( + columns, + (oscutils.get_item_properties(s, columns) for s in data), + ) diff --git a/manilaclient/osc/v2/share_network_subnets.py b/manilaclient/osc/v2/share_network_subnets.py index 09e0385b..36f582f3 100644 --- a/manilaclient/osc/v2/share_network_subnets.py +++ b/manilaclient/osc/v2/share_network_subnets.py @@ -29,63 +29,76 @@ class CreateShareNetworkSubnet(command.ShowOne): """Create a share network subnet.""" + _description = _("Create a share network subnet") def get_parser(self, prog_name): - parser = super(CreateShareNetworkSubnet, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "share_network", metavar="", - help=_("Share network name or ID.") + help=_("Share network name or ID."), ) parser.add_argument( "--neutron-net-id", metavar="", default=None, - help=_("Neutron network ID. Used to set up network for share " - "servers (optional). Should be defined together with " - "'--neutron-subnet-id'.") + help=_( + "Neutron network ID. Used to set up network for share " + "servers (optional). Should be defined together with " + "'--neutron-subnet-id'." + ), ) parser.add_argument( "--neutron-subnet-id", metavar="", default=None, - help=_("Neutron subnet ID. Used to set up network for share " - "servers (optional). Should be defined together with " - "'--neutron-net-id' to which this subnet belongs to. ") + help=_( + "Neutron subnet ID. Used to set up network for share " + "servers (optional). Should be defined together with " + "'--neutron-net-id' to which this subnet belongs to. " + ), ) parser.add_argument( "--availability-zone", metavar="", default=None, - help=_("Optional availability zone that the subnet is available " - "within (Default=None). If None, the subnet will be " - "considered as being available across all availability " - "zones.") + help=_( + "Optional availability zone that the subnet is available " + "within (Default=None). If None, the subnet will be " + "considered as being available across all availability " + "zones." + ), ) parser.add_argument( '--check-only', default=False, action='store_true', - help=_("Run a dry-run of a share network subnet create. " - "Available only for microversion >= 2.70.") + help=_( + "Run a dry-run of a share network subnet create. " + "Available only for microversion >= 2.70." + ), ) parser.add_argument( '--restart-check', default=False, action='store_true', - help=_("Restart a dry-run of a share network subnet create. " - "Helpful when check results are stale. " - "Available only for microversion >= 2.70.") + help=_( + "Restart a dry-run of a share network subnet create. " + "Helpful when check results are stale. " + "Available only for microversion >= 2.70." + ), ) parser.add_argument( "--property", metavar="", default={}, action=parseractions.KeyValueAction, - help=_("Set a property to this share network subnet " - "(repeat option to set multiple properties). " - "Available only for microversion >= 2.78."), + help=_( + "Set a property to this share network subnet " + "(repeat option to set multiple properties). " + "Available only for microversion >= 2.78." + ), ) return parser @@ -93,47 +106,81 @@ def take_action(self, parsed_args): share_client = self.app.client_manager.share # check and restart check during create is only available from 2.70. - if (parsed_args.check_only and - share_client.api_version < api_versions.APIVersion("2.70")): + if ( + parsed_args.check_only + and share_client.api_version < api_versions.APIVersion("2.70") + ): raise exceptions.CommandError( "Check only can be specified only with manila API " - "version >= 2.70.") - if (parsed_args.restart_check and - share_client.api_version < api_versions.APIVersion("2.70")): + "version >= 2.70." + ) + if ( + parsed_args.restart_check + and share_client.api_version < api_versions.APIVersion("2.70") + ): raise exceptions.CommandError( "Restart check can be specified only with manila API " - "version >= 2.70.") + "version >= 2.70." + ) - if (parsed_args.property and - share_client.api_version < api_versions.APIVersion("2.78")): + if ( + parsed_args.property + and share_client.api_version < api_versions.APIVersion("2.78") + ): raise exceptions.CommandError( "Property can be specified only with manila API " - "version >= 2.78.") + "version >= 2.78." + ) + + neutron_client = getattr(self.app.client_manager, 'network', None) + neutron_net_id = parsed_args.neutron_net_id + neutron_subnet_id = parsed_args.neutron_subnet_id - if xor(bool(parsed_args.neutron_net_id), - bool(parsed_args.neutron_subnet_id)): + if xor(bool(neutron_net_id), bool(neutron_subnet_id)): raise exceptions.CommandError( "Both neutron_net_id and neutron_subnet_id should be " "specified. Alternatively, neither of them should be " - "specified.") + "specified." + ) + + if neutron_client and neutron_net_id: + try: + neutron_net_id = neutron_client.find_network( + neutron_net_id, ignore_missing=False + ).id + except Exception: + raise exceptions.CommandError( + f"Neutron network '{neutron_net_id}' not found." + ) + + if neutron_client and neutron_subnet_id: + try: + neutron_subnet_id = neutron_client.find_subnet( + neutron_subnet_id, ignore_missing=False + ).id + except Exception: + raise exceptions.CommandError( + f"Neutron subnet '{neutron_subnet_id}' not found." + ) share_network_id = oscutils.find_resource( - share_client.share_networks, - parsed_args.share_network).id + share_client.share_networks, parsed_args.share_network + ).id if parsed_args.check_only or parsed_args.restart_check: - if parsed_args.property: raise exceptions.CommandError( - "Property cannot be specified with check operation.") + "Property cannot be specified with check operation." + ) subnet_create_check = ( share_client.share_networks.share_network_subnet_create_check( - neutron_net_id=parsed_args.neutron_net_id, - neutron_subnet_id=parsed_args.neutron_subnet_id, + neutron_net_id=neutron_net_id, + neutron_subnet_id=neutron_subnet_id, availability_zone=parsed_args.availability_zone, reset_operation=parsed_args.restart_check, - share_network_id=share_network_id) + share_network_id=share_network_id, + ) ) subnet_data = subnet_create_check[1] if subnet_data: @@ -147,11 +194,11 @@ def take_action(self, parsed_args): subnet_data[k] = dict_values else: share_network_subnet = share_client.share_network_subnets.create( - neutron_net_id=parsed_args.neutron_net_id, - neutron_subnet_id=parsed_args.neutron_subnet_id, + neutron_net_id=neutron_net_id, + neutron_subnet_id=neutron_subnet_id, availability_zone=parsed_args.availability_zone, share_network_id=share_network_id, - metadata=parsed_args.property + metadata=parsed_args.property, ) subnet_data = share_network_subnet._info @@ -160,20 +207,21 @@ def take_action(self, parsed_args): class DeleteShareNetworkSubnet(command.Command): """Delete a share network subnet.""" + _description = _("Delete a share network subnet") def get_parser(self, prog_name): - parser = super(DeleteShareNetworkSubnet, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "share_network", metavar="", - help=_("Share network name or ID.") + help=_("Share network name or ID."), ) parser.add_argument( "share_network_subnet", metavar="", nargs="+", - help=_("ID(s) of share network subnet(s) to be deleted.") + help=_("ID(s) of share network subnet(s) to be deleted."), ) return parser @@ -182,41 +230,45 @@ def take_action(self, parsed_args): result = 0 share_network_id = oscutils.find_resource( - share_client.share_networks, - parsed_args.share_network).id + share_client.share_networks, parsed_args.share_network + ).id for subnet in parsed_args.share_network_subnet: try: share_client.share_network_subnets.delete( - share_network_id, - subnet) + share_network_id, subnet + ) except Exception as e: result += 1 - LOG.error(f"Failed to delete share network subnet with " - f"ID {subnet}: {e}") + LOG.error( + f"Failed to delete share network subnet with " + f"ID {subnet}: {e}" + ) if result > 0: total = len(parsed_args.share_network_subnet) raise exceptions.CommandError( f"{result} of {total} share network subnets failed to be " - f"deleted.") + f"deleted." + ) class ShowShareNetworkSubnet(command.ShowOne): """Show share network subnet.""" + _description = _("Show share network subnet") def get_parser(self, prog_name): - parser = super(ShowShareNetworkSubnet, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "share_network", metavar="", - help=_("Share network name or ID.") + help=_("Share network name or ID."), ) parser.add_argument( "share_network_subnet", metavar="", - help=_("ID of share network subnet to show.") + help=_("ID of share network subnet to show."), ) return parser @@ -224,20 +276,21 @@ def take_action(self, parsed_args): share_client = self.app.client_manager.share share_network_id = oscutils.find_resource( - share_client.share_networks, - parsed_args.share_network).id + share_client.share_networks, parsed_args.share_network + ).id share_network_subnet = share_client.share_network_subnets.get( - share_network_id, - parsed_args.share_network_subnet) + share_network_id, parsed_args.share_network_subnet + ) data = share_network_subnet._info # Special mapping for columns to make the output easier to read: # 'metadata' --> 'properties' data.update( { - 'properties': - format_columns.DictColumn(data.pop('metadata', {})), + 'properties': format_columns.DictColumn( + data.pop('metadata', {}) + ), }, ) @@ -246,107 +299,127 @@ def take_action(self, parsed_args): class SetShareNetworkSubnet(command.Command): """Set share network subnet properties.""" + _description = _("Set share network subnet properties") def get_parser(self, prog_name): - parser = super(SetShareNetworkSubnet, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "share_network", metavar="", - help=_("Share network name or ID.") + help=_("Share network name or ID."), ) parser.add_argument( "share_network_subnet", metavar="", - help=_("ID of share network subnet to set a property.") + help=_("ID of share network subnet to set a property."), ) parser.add_argument( "--property", metavar="", default={}, action=parseractions.KeyValueAction, - help=_("Set a property to this share network subnet " - "(repeat option to set multiple properties). " - "Available only for microversion >= 2.78."), + help=_( + "Set a property to this share network subnet " + "(repeat option to set multiple properties). " + "Available only for microversion >= 2.78." + ), ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share - if (parsed_args.property and - share_client.api_version < api_versions.APIVersion("2.78")): + if ( + parsed_args.property + and share_client.api_version < api_versions.APIVersion("2.78") + ): raise exceptions.CommandError( "Property can be specified only with manila API " - "version >= 2.78.") + "version >= 2.78." + ) share_network_id = oscutils.find_resource( - share_client.share_networks, - parsed_args.share_network).id + share_client.share_networks, parsed_args.share_network + ).id if parsed_args.property: try: share_client.share_network_subnets.set_metadata( - share_network_id, parsed_args.property, - subresource=parsed_args.share_network_subnet) + share_network_id, + parsed_args.property, + subresource=parsed_args.share_network_subnet, + ) except Exception as e: - raise exceptions.CommandError(_( - "Failed to set subnet property '%(properties)s': %(e)s") % - {'properties': parsed_args.property, 'e': e}) + raise exceptions.CommandError( + _("Failed to set subnet property '%(properties)s': %(e)s") + % {'properties': parsed_args.property, 'e': e} + ) class UnsetShareNetworkSubnet(command.Command): """Unset a share network subnet property.""" + _description = _("Unset a share network subnet property") def get_parser(self, prog_name): - parser = super(UnsetShareNetworkSubnet, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "share_network", metavar="", - help=_("Share network name or ID.") + help=_("Share network name or ID."), ) parser.add_argument( "share_network_subnet", metavar="", - help=_("ID of share network subnet to set a property.") + help=_("ID of share network subnet to set a property."), ) parser.add_argument( '--property', metavar='', action='append', - help=_("Remove a property from share network subnet " - "(repeat option to remove multiple properties). " - "Available only for microversion >= 2.78."), + help=_( + "Remove a property from share network subnet " + "(repeat option to remove multiple properties). " + "Available only for microversion >= 2.78." + ), ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share - if (parsed_args.property and - share_client.api_version < api_versions.APIVersion("2.78")): + if ( + parsed_args.property + and share_client.api_version < api_versions.APIVersion("2.78") + ): raise exceptions.CommandError( "Property can be specified only with manila API " - "version >= 2.78.") + "version >= 2.78." + ) share_network_id = oscutils.find_resource( - share_client.share_networks, - parsed_args.share_network).id + share_client.share_networks, parsed_args.share_network + ).id if parsed_args.property: result = 0 for key in parsed_args.property: try: share_client.share_network_subnets.delete_metadata( - share_network_id, [key], - subresource=parsed_args.share_network_subnet) + share_network_id, + [key], + subresource=parsed_args.share_network_subnet, + ) except Exception as e: result += 1 - LOG.error("Failed to unset subnet property " - "'%(key)s': %(e)s", {'key': key, 'e': e}) + LOG.error( + "Failed to unset subnet property '%(key)s': %(e)s", + {'key': key, 'e': e}, + ) if result > 0: total = len(parsed_args.property) raise exceptions.CommandError( f"{result} of {total} subnet properties failed to be " - f"unset.") + f"unset." + ) diff --git a/manilaclient/osc/v2/share_networks.py b/manilaclient/osc/v2/share_networks.py index fbad5aa8..b2a3b0a4 100644 --- a/manilaclient/osc/v2/share_networks.py +++ b/manilaclient/osc/v2/share_networks.py @@ -31,30 +31,36 @@ class ListShareNetwork(command.Lister): _description = _("List share networks") def get_parser(self, prog_name): - parser = super(ListShareNetwork, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( '--name', metavar="", - help=_('Filter share networks by name') + help=_('Filter share networks by name'), ) parser.add_argument( '--name~', metavar="", - help=_('Filter share networks by name-pattern. Available only ' - 'for microversion >= 2.36.') + help=_( + 'Filter share networks by name-pattern. Available only ' + 'for microversion >= 2.36.' + ), ) parser.add_argument( '--description', metavar="", - help=_('Filter share networks by description. Available ' - 'only for microversion >= 2.36') + help=_( + 'Filter share networks by description. Available ' + 'only for microversion >= 2.36' + ), ) parser.add_argument( '--description~', metavar="", - help=_('Filter share networks by description-pattern. Available ' - 'only for microversion >= 2.36.') + help=_( + 'Filter share networks by description-pattern. Available ' + 'only for microversion >= 2.36.' + ), ) parser.add_argument( '--all-projects', @@ -65,68 +71,83 @@ def get_parser(self, prog_name): parser.add_argument( '--project', metavar='', - help=_('Filter share networks by project (name or ID) ' - '(admin only)') + help=_( + 'Filter share networks by project (name or ID) (admin only)' + ), ) identity_common.add_project_domain_option_to_parser(parser) parser.add_argument( '--created-since', metavar='', - help=_('Filter share networks by date they were created after. ' - 'The date can be in the format yyyy-mm-dd.') + help=_( + 'Filter share networks by date they were created after. ' + 'The date can be in the format yyyy-mm-dd.' + ), ) parser.add_argument( '--created-before', metavar='', - help=_('Filter share networks by date they were created before. ' - 'The date can be in the format yyyy-mm-dd.') + help=_( + 'Filter share networks by date they were created before. ' + 'The date can be in the format yyyy-mm-dd.' + ), ) parser.add_argument( '--security-service', metavar='', - help=_('Filter share networks by the name or ID of a security ' - 'service attached to the network.') + help=_( + 'Filter share networks by the name or ID of a security ' + 'service attached to the network.' + ), ) parser.add_argument( '--neutron-net-id', metavar='', - help=_('Filter share networks by the ID of a neutron network.') + help=_('Filter share networks by the ID of a neutron network.'), ) parser.add_argument( '--neutron-subnet-id', metavar='', - help=_('Filter share networks by the ID of a neutron sub network.') + help=_( + 'Filter share networks by the ID of a neutron sub network.' + ), ) parser.add_argument( '--network-type', metavar='', - help=_('Filter share networks by the type of network. Examples ' - 'include "flat", "vlan", "vxlan", "geneve", etc.') + help=_( + 'Filter share networks by the type of network. Examples ' + 'include "flat", "vlan", "vxlan", "geneve", etc.' + ), ) parser.add_argument( '--segmentation-id', metavar='', - help=_('Filter share networks by the segmentation ID of network. ' - 'Relevant only for segmented networks such as "vlan", ' - '"vxlan", "geneve", etc.') + help=_( + 'Filter share networks by the segmentation ID of network. ' + 'Relevant only for segmented networks such as "vlan", ' + '"vxlan", "geneve", etc.' + ), ) parser.add_argument( '--cidr', metavar='', - help=_('Filter share networks by the CIDR of network.') + help=_('Filter share networks by the CIDR of network.'), ) parser.add_argument( '--ip-version', metavar='4/6', choices=['4', '6'], - help=_('Filter share networks by the IP Version of the network, ' - 'either 4 or 6.') + help=_( + 'Filter share networks by the IP Version of the network, ' + 'either 4 or 6.' + ), ) parser.add_argument( '--detail', action='store_true', default=False, - help=_("List share networks with details") + help=_("List share networks with details"), ) return parser @@ -137,19 +158,22 @@ def take_action(self, parsed_args): columns = ['ID', 'Name'] if parsed_args.detail: - columns.extend([ - 'Status', - 'Created At', - 'Updated At', - 'Description', - ]) + columns.extend( + [ + 'Status', + 'Created At', + 'Updated At', + 'Description', + ] + ) project_id = None if parsed_args.project: project_id = identity_common.find_project( identity_client, parsed_args.project, - parsed_args.project_domain).id + parsed_args.project_domain, + ).id # set value of 'all_tenants' when using project option all_tenants = bool(parsed_args.project) or parsed_args.all_projects @@ -176,30 +200,35 @@ def take_action(self, parsed_args): search_opts['name~'] = getattr(parsed_args, 'name~') search_opts['description~'] = getattr(parsed_args, 'description~') search_opts['description'] = parsed_args.description - elif (parsed_args.description or getattr(parsed_args, 'name~') or - getattr(parsed_args, 'description~')): + elif ( + parsed_args.description + or getattr(parsed_args, 'name~') + or getattr(parsed_args, 'description~') + ): raise exceptions.CommandError( "Pattern based filtering (name~, description~ and description)" - " is only available with manila API version >= 2.36") + " is only available with manila API version >= 2.36" + ) data = share_client.share_networks.list(search_opts=search_opts) return ( columns, - (oscutils.get_item_properties(s, columns) for s in data) + (oscutils.get_item_properties(s, columns) for s in data), ) class ShowShareNetwork(command.ShowOne): """Display a share network""" + _description = _("Show details about a share network") def get_parser(self, prog_name): - parser = super(ShowShareNetwork, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "share_network", metavar="", - help=_("Name or ID of the share network to display") + help=_("Name or ID of the share network to display"), ) return parser @@ -207,8 +236,8 @@ def take_action(self, parsed_args): share_client = self.app.client_manager.share share_network = oscutils.find_resource( - share_client.share_networks, - parsed_args.share_network) + share_client.share_networks, parsed_args.share_network + ) data = share_network._info if 'share_network_subnets' not in data: @@ -219,14 +248,16 @@ def take_action(self, parsed_args): for ss in data['share_network_subnets']: ss.update( { - 'properties': - format_columns.DictColumn(ss.pop('metadata', {})), + 'properties': format_columns.DictColumn( + ss.pop('metadata', {}) + ), }, ) # Add security services information security_services = share_client.security_services.list( - search_opts={'share_network_id': share_network.id}, detailed=False) + search_opts={'share_network_id': share_network.id}, detailed=False + ) data['security_services'] = [ { 'security_service_name': ss.name, @@ -238,7 +269,8 @@ def take_action(self, parsed_args): if parsed_args.formatter == 'table': data['share_network_subnets'] = ( cliutils.convert_dict_list_to_string( - data['share_network_subnets']) + data['share_network_subnets'] + ) ) data['security_services'] = cliutils.convert_dict_list_to_string( data['security_services'] @@ -251,70 +283,104 @@ def take_action(self, parsed_args): class CreateShareNetwork(command.ShowOne): """Create a share network.""" + _description = _("Create a share network") def get_parser(self, prog_name): - parser = super(CreateShareNetwork, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "--name", metavar="", - help=_("Add a name to the share network (Optional)") + help=_("Add a name to the share network (Optional)"), ) parser.add_argument( "--description", metavar="", default=None, - help=_("Add a description to the share network (Optional).") + help=_("Add a description to the share network (Optional)."), ) parser.add_argument( "--neutron-net-id", metavar="", default=None, - help=_("ID of the neutron network that must be associated with " - "the share network (Optional). The network specified will " - "be associated with the 'default' share network subnet, " - "unless 'availability-zone' is also specified.") + help=_( + "ID of the neutron network that must be associated with " + "the share network (Optional). The network specified will " + "be associated with the 'default' share network subnet, " + "unless 'availability-zone' is also specified." + ), ) parser.add_argument( "--neutron-subnet-id", metavar="", default=None, - help=_("ID of the neutron sub-network that must be associated " - "with the share network (Optional). The subnet specified " - "will be associated with the 'default' share network " - "subnet, unless 'availability-zone' is also specified.") + help=_( + "ID of the neutron sub-network that must be associated " + "with the share network (Optional). The subnet specified " + "will be associated with the 'default' share network " + "subnet, unless 'availability-zone' is also specified." + ), ) parser.add_argument( "--availability-zone", metavar="", default=None, - help=_("Name or ID of the avalilability zone to assign the " - "specified network subnet parameters to. Must be used " - "in conjunction with 'neutron-net-id' and " - "'neutron-subnet-id'. Do not specify this parameter if " - "the network must be available across all availability " - "zones ('default' share network subnet). Available " - "only for microversion >= 2.51.") + help=_( + "Name or ID of the avalilability zone to assign the " + "specified network subnet parameters to. Must be used " + "in conjunction with 'neutron-net-id' and " + "'neutron-subnet-id'. Do not specify this parameter if " + "the network must be available across all availability " + "zones ('default' share network subnet). Available " + "only for microversion >= 2.51." + ), ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share + neutron_client = getattr(self.app.client_manager, 'network', None) + neutron_net_id = parsed_args.neutron_net_id + neutron_subnet_id = parsed_args.neutron_subnet_id + + if neutron_client and neutron_net_id: + try: + neutron_net_id = neutron_client.find_network( + neutron_net_id, ignore_missing=False + ).id + except Exception: + raise exceptions.CommandError( + f"Neutron network '{parsed_args.neutron_net_id}'" + f" not found." + ) + if neutron_client and neutron_subnet_id: + try: + neutron_subnet_id = neutron_client.find_subnet( + neutron_subnet_id, ignore_missing=False + ).id + except Exception: + raise exceptions.CommandError( + f"Neutron subnet '{parsed_args.neutron_subnet_id}'" + f" not found." + ) availability_zone = None - if (parsed_args.availability_zone and - share_client.api_version < api_versions.APIVersion("2.51")): + if ( + parsed_args.availability_zone + and share_client.api_version < api_versions.APIVersion("2.51") + ): raise exceptions.CommandError( "Availability zone can be specified only with manila API " - "version >= 2.51") + "version >= 2.51" + ) elif parsed_args.availability_zone: availability_zone = parsed_args.availability_zone kwargs = { "name": parsed_args.name, "description": parsed_args.description, - "neutron_net_id": parsed_args.neutron_net_id, - "neutron_subnet_id": parsed_args.neutron_subnet_id, + "neutron_net_id": neutron_net_id, + "neutron_subnet_id": neutron_subnet_id, } if availability_zone: kwargs['availability_zone'] = availability_zone @@ -327,28 +393,30 @@ def take_action(self, parsed_args): if parsed_args.formatter == 'table': share_network_data['share_network_subnets'] = ( cliutils.convert_dict_list_to_string( - share_network_data['share_network_subnets']) + share_network_data['share_network_subnets'] + ) ) return self.dict2columns(share_network_data) class DeleteShareNetwork(command.Command): """Delete one or more share networks""" + _description = _("Delete one or more share networks") def get_parser(self, prog_name): - parser = super(DeleteShareNetwork, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "share_network", metavar="", nargs="+", - help=_("Name or ID of the share network(s) to delete") + help=_("Name or ID of the share network(s) to delete"), ) parser.add_argument( "--wait", action='store_true', default=False, - help=_("Wait for the share network(s) to be deleted") + help=_("Wait for the share network(s) to be deleted"), ) return parser @@ -359,20 +427,22 @@ def take_action(self, parsed_args): for share_network in parsed_args.share_network: try: share_network_obj = oscutils.find_resource( - share_client.share_networks, - share_network) - share_client.share_networks.delete( - share_network_obj) + share_client.share_networks, share_network + ) + share_client.share_networks.delete(share_network_obj) if parsed_args.wait: if not oscutils.wait_for_delete( - manager=share_client.share_networks, - res_id=share_network_obj.id): + manager=share_client.share_networks, + res_id=share_network_obj.id, + ): result += 1 except Exception as e: result += 1 - LOG.error(f"Failed to delete share network with " - f"name or ID {share_network}: {e}") + LOG.error( + f"Failed to delete share network with " + f"name or ID {share_network}: {e}" + ) if result > 0: total = len(parsed_args.share_network) @@ -382,81 +452,96 @@ def take_action(self, parsed_args): class SetShareNetwork(command.Command): """Set share network properties.""" + _description = _("Set share network properties") def get_parser(self, prog_name): - parser = super(SetShareNetwork, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "share_network", metavar="", - help=_('Name or ID of the share network to set a property for') + help=_('Name or ID of the share network to set a property for'), ) parser.add_argument( "--name", metavar="", default=None, - help=_("Set a new name to the share network.") + help=_("Set a new name to the share network."), ) parser.add_argument( "--description", metavar="", default=None, - help=_("Set a new description to the share network.") + help=_("Set a new description to the share network."), ) parser.add_argument( "--status", metavar="", choices=['active', 'error', 'network_change'], - help=_("Assign a status to the share network (Admin only). " - "Options include : active, error, network_change. " - "Available only for microversion >= 2.63.") + help=_( + "Assign a status to the share network (Admin only). " + "Options include : active, error, network_change. " + "Available only for microversion >= 2.63." + ), ) parser.add_argument( '--neutron-net-id', metavar='', - help=_("Update the neutron network associated with the default " - "share network subnet. If a default share network subnet " - "is not present or if the share network is in use, setting " - "this will fail.") + help=_( + "Update the neutron network associated with the default " + "share network subnet. If a default share network subnet " + "is not present or if the share network is in use, setting " + "this will fail." + ), ) parser.add_argument( '--neutron-subnet-id', metavar='', - help=_("Update the neutron subnetwork associated with the default " - "share network subnet. If a default share network subnet " - "is not present or if the share network is in use, setting " - "this will fail.") + help=_( + "Update the neutron subnetwork associated with the default " + "share network subnet. If a default share network subnet " + "is not present or if the share network is in use, setting " + "this will fail." + ), ) parser.add_argument( '--current-security-service', metavar='', - help=_("Name or ID of a security service that is currently " - "associated with a share network that must be replaced. " - "Replacing a security service is only available for " - "microversions >= 2.63.") + help=_( + "Name or ID of a security service that is currently " + "associated with a share network that must be replaced. " + "Replacing a security service is only available for " + "microversions >= 2.63." + ), ) parser.add_argument( '--new-security-service', metavar='', - help=_("Name or ID of a security service that must be associated " - "with the share network. When replacing a security " - "service, the current security service must also be " - "provided with the '--current-security-service' option. " - "Replacing a security service is only available for " - "microversions >= 2.63.") + help=_( + "Name or ID of a security service that must be associated " + "with the share network. When replacing a security " + "service, the current security service must also be " + "provided with the '--current-security-service' option. " + "Replacing a security service is only available for " + "microversions >= 2.63." + ), ) parser.add_argument( '--check-only', action='store_true', - help=_("Run a dry-run of a security service replacement. " - "Available only for microversion >=2.63") + help=_( + "Run a dry-run of a security service replacement. " + "Available only for microversion >=2.63" + ), ) parser.add_argument( '--restart-check', action='store_true', - help=_("Restart a dry-run of a security service " - "replacement. Helpful when check results are " - "stale. Available only for microversion >=2.63.") + help=_( + "Restart a dry-run of a security service " + "replacement. Helpful when check results are " + "stale. Available only for microversion >=2.63." + ), ) return parser @@ -464,30 +549,40 @@ def take_action(self, parsed_args): share_client = self.app.client_manager.share result = 0 - share_network = oscutils.find_resource(share_client.share_networks, - parsed_args.share_network) + share_network = oscutils.find_resource( + share_client.share_networks, parsed_args.share_network + ) kwargs = {} # some args are only for newer API micro-version if share_client.api_version < api_versions.APIVersion("2.63"): - new_args = ('status', 'check_only', 'restart_check', - 'current_security_service') + new_args = ( + 'status', + 'check_only', + 'restart_check', + 'current_security_service', + ) invalid_args = [ - arg for arg in new_args + arg + for arg in new_args if getattr(parsed_args, arg) is not None ] raise exceptions.CommandError( f"Use of {' '.join(invalid_args)} is only available for API " - f"microversions >= 2.63.") + f"microversions >= 2.63." + ) # If "--check-only" and "--restart-check" are used, a new security # service option must be supplied if parsed_args.check_only or parsed_args.restart_check: if not parsed_args.new_security_service: raise exceptions.CommandError( - _("Must provide new security service with --check-only " - "and --restart-check.")) + _( + "Must provide new security service with --check-only " + "and --restart-check." + ) + ) if parsed_args.name is not None: kwargs['name'] = parsed_args.name @@ -500,43 +595,47 @@ def take_action(self, parsed_args): if kwargs: try: - share_client.share_networks.update( - share_network, - **kwargs - ) + share_client.share_networks.update(share_network, **kwargs) except Exception as e: result += 1 - LOG.error(f"Failed to set share network properties " - f"{kwargs}: {e}") + LOG.error( + f"Failed to set share network properties {kwargs}: {e}" + ) if parsed_args.status: try: share_client.share_networks.reset_state( - share_network, - parsed_args.status + share_network, parsed_args.status ) except Exception as e: result += 1 - LOG.error(f"Failed to update share network status to " - f"{parsed_args.status}: {e}") + LOG.error( + f"Failed to update share network status to " + f"{parsed_args.status}: {e}" + ) new_security_service = current_security_service = None if parsed_args.new_security_service: new_security_service = oscutils.find_resource( share_client.security_services, - parsed_args.new_security_service) + parsed_args.new_security_service, + ) if parsed_args.current_security_service: current_security_service = oscutils.find_resource( share_client.security_services, - parsed_args.current_security_service) + parsed_args.current_security_service, + ) if new_security_service and not current_security_service: try: if parsed_args.check_only: - check_result = share_client.share_networks\ - .add_security_service_check( - share_network, new_security_service, - reset_operation=parsed_args.restart_check) + check_result = ( + share_client.share_networks.add_security_service_check( + share_network, + new_security_service, + reset_operation=parsed_args.restart_check, + ) + ) is_compatible = check_result[1].get('compatible') # NOTE(gouthamr): We're logging to the console here, # because there's no need to print useful @@ -544,39 +643,46 @@ def take_action(self, parsed_args): # logging is a hack, since other kinds of logs may # not print to console by default. if is_compatible is None: - LOG.error("Security service check has been " - "successfully initiated, please retry " - "after some time.") + LOG.error( + "Security service check has been " + "successfully initiated, please retry " + "after some time." + ) elif is_compatible: LOG.error( f"Security service " f"{parsed_args.new_security_service} can " f"be added to share network " - f"{parsed_args.share_network}.") + f"{parsed_args.share_network}." + ) else: LOG.error( f"Security service " f"{parsed_args.new_security_service} cannot " f"be added to share network " - f"{parsed_args.share_network}.") + f"{parsed_args.share_network}." + ) else: share_client.share_networks.add_security_service( - share_network, new_security_service) + share_network, new_security_service + ) except Exception as e: result += 1 - LOG.error(f"Failed to add security service " - f"{parsed_args.new_security_service} to " - f"share network {parsed_args.share_network}: {e}") + LOG.error( + f"Failed to add security service " + f"{parsed_args.new_security_service} to " + f"share network {parsed_args.share_network}: {e}" + ) if new_security_service and current_security_service: try: if parsed_args.check_only: - check_result = share_client.share_networks.\ - update_share_network_security_service_check( - share_network, - current_security_service, - new_security_service, - reset_operation=parsed_args.restart_check) + check_result = share_client.share_networks.update_share_network_security_service_check( # noqa: E501 + share_network, + current_security_service, + new_security_service, + reset_operation=parsed_args.restart_check, + ) is_compatible = check_result[1].get('compatible') # NOTE(gouthamr): We're logging to the console here, @@ -585,51 +691,59 @@ def take_action(self, parsed_args): # logging is a hack, since other kinds of logs may # not print to console by default. if is_compatible is None: - LOG.error("Security service check has been " - "successfully initiated, please retry " - "after some time.") + LOG.error( + "Security service check has been " + "successfully initiated, please retry " + "after some time." + ) elif is_compatible: LOG.error( f"Security service " f"{parsed_args.current_security_service} can " f"be replaced with security service " f"{parsed_args.new_security_service} on share " - f"network {parsed_args.share_network}.") + f"network {parsed_args.share_network}." + ) else: LOG.error( f"Security service " f"{parsed_args.current_security_service} cannot " f"be replaced with security service " f"{parsed_args.new_security_service} on share " - f"network {parsed_args.share_network}.") + f"network {parsed_args.share_network}." + ) else: - share_client.share_networks.\ - update_share_network_security_service( - share_network, - current_security_service, - new_security_service) + share_client.share_networks.update_share_network_security_service( + share_network, + current_security_service, + new_security_service, + ) except Exception as e: result += 1 - LOG.error(f"Failed to update security service " - f"{parsed_args.current_security_service} on " - f"share network " - f"{parsed_args.share_network}: {e}") + LOG.error( + f"Failed to update security service " + f"{parsed_args.current_security_service} on " + f"share network " + f"{parsed_args.share_network}: {e}" + ) if result > 0: - raise exceptions.CommandError(_("One or more of the " - "set operations failed")) + raise exceptions.CommandError( + _("One or more of the set operations failed") + ) class UnsetShareNetwork(command.Command): """Unset a share network property.""" + _description = _("Unset a share network property") def get_parser(self, prog_name): - parser = super(UnsetShareNetwork, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "share_network", metavar="", - help=_("Name or ID of the share network to unset a property of") + help=_("Name or ID of the share network to unset a property of"), ) parser.add_argument( "--name", @@ -644,8 +758,10 @@ def get_parser(self, prog_name): parser.add_argument( "--security-service", metavar="", - help=_("Disassociate a security service from the share network. " - "This is only possible with unused share networks."), + help=_( + "Disassociate a security service from the share network. " + "This is only possible with unused share networks." + ), ) return parser @@ -653,14 +769,14 @@ def take_action(self, parsed_args): share_client = self.app.client_manager.share share_network = oscutils.find_resource( - share_client.share_networks, - parsed_args.share_network) + share_client.share_networks, parsed_args.share_network + ) security_service = None if parsed_args.security_service: security_service = oscutils.find_resource( - share_client.security_services, - parsed_args.security_service) + share_client.security_services, parsed_args.security_service + ) result = 0 kwargs = {} @@ -672,25 +788,27 @@ def take_action(self, parsed_args): kwargs['description'] = '' if kwargs: try: - share_client.share_networks.update( - share_network, - **kwargs - ) + share_client.share_networks.update(share_network, **kwargs) except Exception as e: result += 1 - LOG.error(f"Failed to unset share network properties " - f"{kwargs}: {e}") + LOG.error( + f"Failed to unset share network properties {kwargs}: {e}" + ) if security_service: try: share_client.share_networks.remove_security_service( - share_network, security_service) + share_network, security_service + ) except Exception as e: result += 1 - LOG.error(f"Failed to dissociate security service" - f"{parsed_args.security_service} from " - f"{parsed_args.share_network}: {e}") + LOG.error( + f"Failed to dissociate security service" + f"{parsed_args.security_service} from " + f"{parsed_args.share_network}: {e}" + ) if result > 0: - raise exceptions.CommandError(_("One or more of the " - "unset operations failed")) + raise exceptions.CommandError( + _("One or more of the unset operations failed") + ) diff --git a/manilaclient/osc/v2/share_pools.py b/manilaclient/osc/v2/share_pools.py index 13bf815a..2eb2b35b 100644 --- a/manilaclient/osc/v2/share_pools.py +++ b/manilaclient/osc/v2/share_pools.py @@ -20,44 +20,54 @@ class ListSharePools(command.Lister): """List all backend storage pools known to the scheduler (Admin only).""" + _description = _( - "List all backend storage pools known to the scheduler (Admin only).") + "List all backend storage pools known to the scheduler (Admin only)." + ) def get_parser(self, prog_name): - parser = super(ListSharePools, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "--host", metavar="", default=None, - help=_("Filter results by host name. " - "Regular expressions are supported.") + help=_( + "Filter results by host name. " + "Regular expressions are supported." + ), ) parser.add_argument( "--backend", metavar="", default=None, - help=_("Filter results by backend name. " - "Regular expressions are supported.") + help=_( + "Filter results by backend name. " + "Regular expressions are supported." + ), ) parser.add_argument( "--pool", metavar="", default=None, - help=_("Filter results by pool name. " - "Regular expressions are supported.") + help=_( + "Filter results by pool name. " + "Regular expressions are supported." + ), ) parser.add_argument( "--detail", action='store_true', default=False, - help=_("Show detailed information about pools.") + help=_("Show detailed information about pools."), ) parser.add_argument( "--share-type", metavar="", default=None, - help=_("Filter results by share type name or ID. " - "Available only for microversion >= 2.23") + help=_( + "Filter results by share type name or ID. " + "Available only for microversion >= 2.23" + ), ) return parser @@ -68,12 +78,15 @@ def take_action(self, parsed_args): if parsed_args.share_type: if share_client.api_version >= api_versions.APIVersion("2.23"): share_type = osc_utils.find_resource( - share_client.share_types, - parsed_args.share_type).id + share_client.share_types, parsed_args.share_type + ).id else: - raise exceptions.CommandError(_( - "Filtering results by share type is only available with " - "manila API version >= 2.23")) + raise exceptions.CommandError( + _( + "Filtering results by share type is only " + "available with manila API version >= 2.23" + ) + ) search_opts = { 'host': parsed_args.host, @@ -83,7 +96,8 @@ def take_action(self, parsed_args): } pools = share_client.pools.list( - detailed=parsed_args.detail, search_opts=search_opts) + detailed=parsed_args.detail, search_opts=search_opts + ) columns = ["Name", "Host", "Backend", "Pool"] @@ -91,11 +105,17 @@ def take_action(self, parsed_args): columns.append("Capabilities") if parsed_args.formatter == 'table': for pool in pools: - pool._info.update({ - 'capabilities': utils.format_properties( - pool.capabilities)}) + pool._info.update( + { + 'capabilities': utils.format_properties( + pool.capabilities + ) + } + ) - data = (osc_utils.get_dict_properties( - pool._info, columns) for pool in pools) + data = ( + osc_utils.get_dict_properties(pool._info, columns) + for pool in pools + ) return (columns, data) diff --git a/manilaclient/osc/v2/share_replica_export_locations.py b/manilaclient/osc/v2/share_replica_export_locations.py index 2e219789..620a374a 100644 --- a/manilaclient/osc/v2/share_replica_export_locations.py +++ b/manilaclient/osc/v2/share_replica_export_locations.py @@ -21,12 +21,9 @@ class ShareReplicaListExportLocation(command.Lister): _description = _("List export locations of a share replica.") def get_parser(self, prog_name): - parser = super( - ShareReplicaListExportLocation, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( - "replica", - metavar="", - help=_("ID of the share replica.") + "replica", metavar="", help=_("ID of the share replica.") ) return parser @@ -42,14 +39,17 @@ def take_action(self, parsed_args): ] replica = osc_utils.find_resource( - share_client.share_replicas, - parsed_args.replica) + share_client.share_replicas, parsed_args.replica + ) export_locations = share_client.share_replica_export_locations.list( - replica) + replica + ) - data = (osc_utils.get_dict_properties( - location._info, columns) for location in export_locations) + data = ( + osc_utils.get_dict_properties(location._info, columns) + for location in export_locations + ) return (columns, data) @@ -60,17 +60,14 @@ class ShareReplicaShowExportLocation(command.ShowOne): _description = _("Show details of a share replica's export location.") def get_parser(self, prog_name): - parser = super( - ShareReplicaShowExportLocation, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( - "replica", - metavar="", - help=_("ID of the share replica.") + "replica", metavar="", help=_("ID of the share replica.") ) parser.add_argument( "export_location", metavar="", - help=_("ID of the share replica export location.") + help=_("ID of the share replica export location."), ) return parser @@ -78,10 +75,11 @@ def take_action(self, parsed_args): share_client = self.app.client_manager.share replica = osc_utils.find_resource( - share_client.share_replicas, - parsed_args.replica) + share_client.share_replicas, parsed_args.replica + ) export_location = share_client.share_replica_export_locations.get( - replica, parsed_args.export_location) + replica, parsed_args.export_location + ) return self.dict2columns(export_location._info) diff --git a/manilaclient/osc/v2/share_replicas.py b/manilaclient/osc/v2/share_replicas.py index 5b0d01e7..cfe92d3f 100644 --- a/manilaclient/osc/v2/share_replicas.py +++ b/manilaclient/osc/v2/share_replicas.py @@ -11,6 +11,7 @@ # under the License. import logging +from osc_lib.cli import format_columns from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions @@ -26,68 +27,104 @@ class CreateShareReplica(command.ShowOne): """Create a share replica.""" + _description = _("Create a replica of the given share") def get_parser(self, prog_name): - parser = super(CreateShareReplica, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "share", metavar="", - help=_("Name or ID of the share to replicate.") + help=_("Name or ID of the share to replicate."), ) parser.add_argument( '--availability-zone', metavar='', default=None, - help=_('Availability zone in which the replica should be created.') + help=_( + 'Availability zone in which the replica should be created.' + ), ) parser.add_argument( '--wait', action='store_true', default=False, - help=_('Wait for replica creation') + help=_('Wait for replica creation'), ) parser.add_argument( "--scheduler-hint", metavar="", default={}, action=parseractions.KeyValueAction, - help=_("Scheduler hint for the share replica as key=value pairs, " - "Supported key is only_host. Available for microversion " - ">= 2.67."), + help=_( + "Scheduler hint for the share replica as key=value pairs, " + "Supported key is only_host. Available for microversion " + ">= 2.67." + ), ) parser.add_argument( '--share-network', metavar='', default=None, - help=_('Optional network info ID or name. Available for ' - 'microversion >= 2.72') + help=_( + 'Optional network info ID or name. Available for ' + 'microversion >= 2.72' + ), + ) + parser.add_argument( + "--property", + metavar="", + default={}, + action=parseractions.KeyValueAction, + help=_( + "Set a property to this replica " + "(repeat option to set multiple properties). " + "Available only for microversion >= 2.95" + ), ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share - share = osc_utils.find_resource(share_client.shares, - parsed_args.share) + share = osc_utils.find_resource(share_client.shares, parsed_args.share) scheduler_hints = {} if parsed_args.scheduler_hint: if share_client.api_version < api_versions.APIVersion("2.67"): - raise exceptions.CommandError(_( - "arg '--scheduler_hint' is available only starting with " - "API microversion '2.67'.")) + raise exceptions.CommandError( + _( + "arg '--scheduler_hint' is available only starting " + "with API microversion '2.67'." + ) + ) hints = utils.extract_key_value_options(parsed_args.scheduler_hint) if 'only_host' not in hints.keys() or len(hints) > 1: raise exceptions.CommandError( "The only valid key supported with the --scheduler-hint " - "argument is 'only_host'.") + "argument is 'only_host'." + ) scheduler_hints['only_host'] = hints.get('only_host') body = { 'share': share, 'availability_zone': parsed_args.availability_zone, } + + metadata = {} + if parsed_args.property: + if share_client.api_version < api_versions.APIVersion("2.95"): + raise exceptions.CommandError( + _( + "arg '--property' is available only starting " + "with API microversion '2.95'." + ) + ) + metadata = parsed_args.property + + if metadata: + body['metadata'] = metadata + if scheduler_hints: body['scheduler_hints'] = scheduler_hints @@ -96,10 +133,11 @@ def take_action(self, parsed_args): if share_client.api_version < api_versions.APIVersion("2.72"): raise exceptions.CommandError( "'share-network' option is available only starting " - "with '2.72' API microversion.") + "with '2.72' API microversion." + ) share_network_id = osc_utils.find_resource( - share_client.share_networks, - parsed_args.share_network).id + share_client.share_networks, parsed_args.share_network + ).id body['share_network'] = share_network_id share_replica = share_client.share_replicas.create(**body) @@ -107,42 +145,45 @@ def take_action(self, parsed_args): if not osc_utils.wait_for_status( status_f=share_client.share_replicas.get, res_id=share_replica.id, - success_status=['available'] + success_status=['available'], ): LOG.error(_("ERROR: Share replica is in error state.")) share_replica = osc_utils.find_resource( - share_client.share_replicas, - share_replica.id) + share_client.share_replicas, share_replica.id + ) return self.dict2columns(share_replica._info) class DeleteShareReplica(command.Command): """Delete one or more share replicas.""" + _description = _("Delete one or more share replicas") def get_parser(self, prog_name): - parser = super(DeleteShareReplica, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "replica", metavar="", nargs="+", - help=_("Name or ID of the replica(s) to delete") + help=_("Name or ID of the replica(s) to delete"), ) parser.add_argument( "--force", action='store_true', default=False, - help=_("Attempt to force delete a replica on its backend. " - "Using this option will purge the replica from Manila " - "even if it is not cleaned up on the backend. ") + help=_( + "Attempt to force delete a replica on its backend. " + "Using this option will purge the replica from Manila " + "even if it is not cleaned up on the backend. " + ), ) parser.add_argument( "--wait", action='store_true', default=False, - help=_("Wait for share replica deletion") + help=_("Wait for share replica deletion"), ) return parser @@ -153,44 +194,61 @@ def take_action(self, parsed_args): for replica in parsed_args.replica: try: replica_obj = osc_utils.find_resource( - share_client.share_replicas, - replica) + share_client.share_replicas, replica + ) share_client.share_replicas.delete( - replica_obj, - force=parsed_args.force) + replica_obj, force=parsed_args.force + ) if parsed_args.wait: if not osc_utils.wait_for_delete( - manager=share_client.share_replicas, - res_id=replica_obj.id): + manager=share_client.share_replicas, + res_id=replica_obj.id, + ): result += 1 except Exception as e: result += 1 - LOG.error(_( - "Failed to delete a share replica with " - "name or ID '%(replica)s': %(e)s"), - {'replica': replica, 'e': e}) + LOG.error( + _( + "Failed to delete a share replica with " + "name or ID '%(replica)s': %(e)s" + ), + {'replica': replica, 'e': e}, + ) if result > 0: total = len(parsed_args.replica) - msg = (_("%(result)s of %(total)s replicas failed " - "to delete.") % {'result': result, 'total': total}) + msg = _("%(result)s of %(total)s replicas failed to delete.") % { + 'result': result, + 'total': total, + } raise exceptions.CommandError(msg) class ListShareReplica(command.Lister): """List share replicas.""" + _description = _("List share replicas") def get_parser(self, prog_name): - parser = super(ListShareReplica, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "--share", metavar="", default=None, - help=_("Name or ID of the share to list replicas for.") + help=_("Name or ID of the share to list replicas for."), + ) + parser.add_argument( + '--property', + metavar='', + action=parseractions.KeyValueAction, + help=_( + 'Filter replicas having a given metadata key=value ' + 'property. (repeat option to filter by multiple ' + 'properties)' + ), ) return parser @@ -200,10 +258,35 @@ def take_action(self, parsed_args): share = None if parsed_args.share: share = osc_utils.find_resource( - share_client.shares, - parsed_args.share) + share_client.shares, parsed_args.share + ) + + properties = parsed_args.property or {} + if properties: + if share_client.api_version < api_versions.APIVersion("2.95"): + raise exceptions.CommandError( + "Property based filtering is only available " + "with manila API version >= 2.95" + ) - replicas = share_client.share_replicas.list(share=share) + search_opts = {} + if properties: + meta_str = ",".join(f"{k}:{v}" for k, v in properties.items()) + search_opts['metadata'] = meta_str + + replicas = share_client.share_replicas.list( + share=share, search_opts=search_opts + ) + + if properties: + replicas = [ + r + for r in replicas + if all( + r._info.get('metadata', {}).get(k) == v + for k, v in properties.items() + ) + ] columns = [ 'id', @@ -214,48 +297,63 @@ def take_action(self, parsed_args): 'availability_zone', 'updated_at', ] - column_headers = utils.format_column_headers(columns) - data = (osc_utils.get_dict_properties( - replica._info, columns) for replica in replicas) + data = ( + osc_utils.get_dict_properties(replica._info, columns) + for replica in replicas + ) return (column_headers, data) class ShowShareReplica(command.ShowOne): """Show share replica.""" + _description = _("Show details about a replica") def get_parser(self, prog_name): - parser = super(ShowShareReplica, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "replica", metavar="", - help=_("ID of the share replica. Available only for " - "microversion >= 2.47. ") + help=_( + "ID of the share replica. Available only for " + "microversion >= 2.47. " + ), ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share - replica = share_client.share_replicas.get( - parsed_args.replica) + replica = share_client.share_replicas.get(parsed_args.replica) replica_export_locations = ( share_client.share_replica_export_locations.list( - share_replica=replica)) + share_replica=replica + ) + ) replica._info['export_locations'] = [] for element_location in replica_export_locations: element_location._info.pop('links', None) - replica._info['export_locations'].append( - element_location._info) + replica._info['export_locations'].append(element_location._info) if parsed_args.formatter == 'table': replica._info['export_locations'] = ( cliutils.convert_dict_list_to_string( - replica._info['export_locations'])) + replica._info['export_locations'] + ) + ) + # Special mapping for columns to make the output easier to read: + # 'metadata' --> 'properties' + replica._info.update( + { + 'properties': format_columns.DictColumn( + replica._info.pop('metadata', {}) + ), + }, + ) replica._info.pop('links', None) @@ -265,31 +363,53 @@ def take_action(self, parsed_args): class SetShareReplica(command.Command): """Set share replica""" - _description = _("Explicitly set share replica status and/or " - "replica-state") + _description = _( + "Explicitly set share replica status and/or replica-state " + "and/or property" + ) def get_parser(self, prog_name): - parser = super(SetShareReplica, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "replica", metavar="", - help=_("ID of the share replica to modify.") + help=_("ID of the share replica to modify."), ) parser.add_argument( "--replica-state", metavar="", choices=['in_sync', 'out_of_sync', 'active', 'error'], - help=_("Indicate which replica_state to assign the replica. " - "Options include in_sync, out_of_sync, active and error.") + help=_( + "Indicate which replica_state to assign the replica. " + "Options include in_sync, out_of_sync, active and error." + ), ) parser.add_argument( "--status", metavar="", - choices=['available', 'error', 'creating', 'deleting', - 'error_deleting'], - help=_("Indicate which status to assign the replica. Options " - "include available, error, creating, deleting and " - "error_deleting.") + choices=[ + 'available', + 'error', + 'creating', + 'deleting', + 'error_deleting', + ], + help=_( + "Indicate which status to assign the replica. Options " + "include available, error, creating, deleting and " + "error_deleting." + ), + ) + parser.add_argument( + "--property", + metavar="", + default={}, + action=parseractions.KeyValueAction, + help=_( + "Set a property to this replica " + "(repeat option to set multiple properties). " + "Available only for microversion >= 2.95" + ), ) return parser @@ -298,69 +418,161 @@ def take_action(self, parsed_args): result = 0 replica = osc_utils.find_resource( - share_client.share_replicas, - parsed_args.replica) + share_client.share_replicas, parsed_args.replica + ) if parsed_args.replica_state: try: share_client.share_replicas.reset_replica_state( - replica, - parsed_args.replica_state + replica, parsed_args.replica_state ) except Exception as e: result += 1 - LOG.error(_( - "Failed to set replica_state " - "'%(replica_state)s': %(exception)s"), - {'replica_state': parsed_args.replica_state, - 'exception': e}) + LOG.error( + _( + "Failed to set replica_state " + "'%(replica_state)s': %(exception)s" + ), + { + 'replica_state': parsed_args.replica_state, + 'exception': e, + }, + ) if parsed_args.status: try: share_client.share_replicas.reset_state( - replica, - parsed_args.status + replica, parsed_args.status + ) + except Exception as e: + result += 1 + LOG.error( + _("Failed to set status '%(status)s': %(exception)s"), + {'status': parsed_args.status, 'exception': e}, ) + + if parsed_args.property: + if share_client.api_version < api_versions.APIVersion("2.95"): + raise exceptions.CommandError( + _( + "Setting properties in share replicas is available " + "only starting with API microversion '2.95'." + ) + ) + try: + replica.set_metadata(parsed_args.property) except Exception as e: + LOG.error( + _( + "Failed to set share replica properties " + "'%(properties)s': %(exception)s" + ), + {'properties': parsed_args.property, 'exception': e}, + ) result += 1 - LOG.error(_( - "Failed to set status '%(status)s': %(exception)s"), - {'status': parsed_args.status, 'exception': e}) - - if not parsed_args.replica_state and not parsed_args.status: - raise exceptions.CommandError(_( - "Nothing to set. Please define " - "either '--replica_state' or '--status'.")) + + if ( + not parsed_args.replica_state + and not parsed_args.status + and not parsed_args.property + ): + raise exceptions.CommandError( + _( + "Nothing to set. Please define " + "either '--replica_state' or '--status' or '--property'." + ) + ) if result > 0: - raise exceptions.CommandError(_("One or more of the " - "set operations failed")) + raise exceptions.CommandError( + _("One or more of the set operations failed") + ) -class PromoteShareReplica(command.Command): - """Promote share replica""" +class UnsetShareReplica(command.Command): + """Unset a share replica property.""" - _description = _("Promote specified replica to 'active' " - "replica_state.") + _description = _("Unset a share replica property") def get_parser(self, prog_name): - parser = super(PromoteShareReplica, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "replica", metavar="", - help=_("ID of the share replica.") + help=_("ID of the share replica to unset property from"), + ) + parser.add_argument( + '--property', + metavar='', + action='append', + help=_( + 'Remove a property from replica ' + '(repeat option to remove multiple properties)' + ), + ) + return parser + + def take_action(self, parsed_args): + share_client = self.app.client_manager.share + + replica = osc_utils.find_resource( + share_client.share_replicas, parsed_args.replica + ) + + if parsed_args.property: + if share_client.api_version < api_versions.APIVersion("2.95"): + raise exceptions.CommandError( + _( + "arg '--property' is available only starting " + "with API microversion '2.95'." + ) + ) + result = 0 + for key in parsed_args.property: + try: + replica.delete_metadata([key]) + except Exception as e: + result += 1 + LOG.error( + _( + "Failed to unset replica property " + "'%(key)s': %(exception)s" + ), + {'key': key, 'exception': e}, + ) + if result > 0: + raise exceptions.CommandError( + _("One or more of the unset operations failed") + ) + else: + raise exceptions.CommandError( + "Please specify '--property ' to unset a property." + ) + + +class PromoteShareReplica(command.Command): + """Promote share replica""" + + _description = _("Promote specified replica to 'active' replica_state.") + + def get_parser(self, prog_name): + parser = super().get_parser(prog_name) + parser.add_argument( + "replica", metavar="", help=_("ID of the share replica.") ) parser.add_argument( '--quiesce-wait-time', metavar='', default=None, - help=_('Quiesce wait time in seconds. Available for ' - 'microversion >= 2.75') + help=_( + 'Quiesce wait time in seconds. Available for ' + 'microversion >= 2.75' + ), ) parser.add_argument( '--wait', action='store_true', default=False, - help=_('Wait for share replica promotion') + help=_('Wait for share replica promotion'), ) return parser @@ -368,8 +580,8 @@ def take_action(self, parsed_args): share_client = self.app.client_manager.share replica = osc_utils.find_resource( - share_client.share_replicas, - parsed_args.replica) + share_client.share_replicas, parsed_args.replica + ) args = [ replica, @@ -378,37 +590,39 @@ def take_action(self, parsed_args): if share_client.api_version < api_versions.APIVersion("2.75"): raise exceptions.CommandError( "'quiesce-wait-time' option is available only starting " - "with '2.75' API microversion.") + "with '2.75' API microversion." + ) args += [parsed_args.quiesce_wait_time] try: share_client.share_replicas.promote(*args) if parsed_args.wait: if not osc_utils.wait_for_status( - status_f=share_client.share_replicas.get, - res_id=replica.id, - success_status=['active'], - status_field='replica_state' + status_f=share_client.share_replicas.get, + res_id=replica.id, + success_status=['active'], + status_field='replica_state', ): LOG.error(_("ERROR: Share replica is in error state.")) except Exception as e: - raise exceptions.CommandError(_( - "Failed to promote replica to 'active': %s" % (e))) + msg = "Failed to promote replica to 'active': %(e)s" + raise exceptions.CommandError(msg % {'e': e}) class ResyncShareReplica(command.Command): """Resync share replica""" - _description = _("Attempt to update the share replica with its " - "'active' mirror.") + _description = _( + "Attempt to update the share replica with its 'active' mirror." + ) def get_parser(self, prog_name): - parser = super(ResyncShareReplica, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "replica", metavar="", - help=_("ID of the share replica to resync.") + help=_("ID of the share replica to resync."), ) return parser @@ -416,11 +630,11 @@ def take_action(self, parsed_args): share_client = self.app.client_manager.share replica = osc_utils.find_resource( - share_client.share_replicas, - parsed_args.replica) + share_client.share_replicas, parsed_args.replica + ) try: share_client.share_replicas.resync(replica) except Exception as e: - raise exceptions.CommandError(_( - "Failed to resync share replica: %s" % (e))) + msg = "Failed to resync share replica: %(e)s" + raise exceptions.CommandError(msg % {'e': e}) diff --git a/manilaclient/osc/v2/share_servers.py b/manilaclient/osc/v2/share_servers.py index dda2d976..6ed479f7 100644 --- a/manilaclient/osc/v2/share_servers.py +++ b/manilaclient/osc/v2/share_servers.py @@ -29,22 +29,22 @@ class DeleteShareServer(command.Command): """Delete one or more share servers (Admin only)""" - _description = _( - "Delete one or more share servers") + + _description = _("Delete one or more share servers") def get_parser(self, prog_name): - parser = super(DeleteShareServer, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "share_servers", metavar="", nargs="+", - help=_("ID(s) of the server(s) to delete") + help=_("ID(s) of the server(s) to delete"), ) parser.add_argument( "--wait", action='store_true', default=False, - help=_("Wait for share server deletion.") + help=_("Wait for share server deletion."), ) return parser @@ -55,38 +55,46 @@ def take_action(self, parsed_args): for server in parsed_args.share_servers: try: server_obj = osc_utils.find_resource( - share_client.share_servers, server) + share_client.share_servers, server + ) share_client.share_servers.delete(server_obj) if parsed_args.wait: if not osc_utils.wait_for_delete( - manager=share_client.share_servers, - res_id=server_obj.id): + manager=share_client.share_servers, + res_id=server_obj.id, + ): result += 1 except Exception as e: result += 1 - LOG.error(_( - "Failed to delete a share server with " - "ID '%(server)s': %(e)s"), - {'server': server, 'e': e}) + LOG.error( + _( + "Failed to delete a share server with " + "ID '%(server)s': %(e)s" + ), + {'server': server, 'e': e}, + ) if result > 0: - total = len(parsed_args.share_servers) - msg = f'Failed to delete {result} servers out of {total}.' - raise exceptions.CommandError(_(msg)) + msg = "Failed to delete %(result)d servers out %(total)d" + raise exceptions.CommandError( + msg + % {'result': result, 'total': len(parsed_args.share_servers)}, + ) class ShowShareServer(command.ShowOne): """Show share server (Admin only).""" + _description = _("Show details about a share server (Admin only).") def get_parser(self, prog_name): - parser = super(ShowShareServer, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "share_server", metavar="", - help=_("ID of share server.") + help=_("ID of share server."), ) return parser @@ -94,8 +102,8 @@ def take_action(self, parsed_args): share_client = self.app.client_manager.share share_server = osc_utils.find_resource( - share_client.share_servers, - parsed_args.share_server) + share_client.share_servers, parsed_args.share_server + ) # All 'backend_details' data already present as separated strings, # so remove big dict from view. @@ -108,10 +116,11 @@ def take_action(self, parsed_args): class ListShareServer(command.Lister): """List all share servers (Admin only).""" + _description = _("List all share servers (Admin only).") def get_parser(self, prog_name): - parser = super(ListShareServer, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( '--host', metavar='', @@ -122,7 +131,7 @@ def get_parser(self, prog_name): '--status', metavar="", default=None, - help=_('Filter results by status.') + help=_('Filter results by status.'), ) parser.add_argument( '--share-network', @@ -134,34 +143,40 @@ def get_parser(self, prog_name): '--project', metavar='', default=None, - help=_('Filter results by project name or ID.') + help=_('Filter results by project name or ID.'), ) parser.add_argument( '--share-network-subnet', metavar='', type=str, default=None, - help=_("Filter results by share network subnet that the " - "share server's network allocation exists within. " - "Available for microversion >= 2.51 (Optional, " - "Default=None)") + help=_( + "Filter results by share network subnet that the " + "share server's network allocation exists within. " + "Available for microversion >= 2.51 (Optional, " + "Default=None)" + ), ) parser.add_argument( '--source-share-server-id', metavar='', type=str, default=None, - help=_("Share server ID to be used as a filter. Available for " - "microversion >= 2.57 (Optional, Default=None)") + help=_( + "Share server ID to be used as a filter. Available for " + "microversion >= 2.57 (Optional, Default=None)" + ), ) parser.add_argument( '--identifier', metavar='', type=str, default=None, - help=_("Identifier of the share server in the share back end. " - "Available for microversion >= 2.49 " - "(Optional, Default=None)") + help=_( + "Identifier of the share server in the share back end. " + "Available for microversion >= 2.49 " + "(Optional, Default=None)" + ), ) identity_common.add_project_domain_option_to_parser(parser) return parser @@ -175,22 +190,29 @@ def take_action(self, parsed_args): project_id = identity_common.find_project( identity_client, parsed_args.project, - parsed_args.project_domain).id + parsed_args.project_domain, + ).id - if (parsed_args.identifier and - share_client.api_version < api_versions.APIVersion("2.49")): + if ( + parsed_args.identifier + and share_client.api_version < api_versions.APIVersion("2.49") + ): raise exceptions.CommandError( "Filtering by identifier is only allowed with manila API " "version >= 2.49." ) - if (parsed_args.share_network_subnet and - share_client.api_version < api_versions.APIVersion("2.51")): + if ( + parsed_args.share_network_subnet + and share_client.api_version < api_versions.APIVersion("2.51") + ): raise exceptions.CommandError( "Share network subnet can be specified only with manila API " "version >= 2.51" ) - if (parsed_args.source_share_server_id and - share_client.api_version < api_versions.APIVersion("2.57")): + if ( + parsed_args.source_share_server_id + and share_client.api_version < api_versions.APIVersion("2.57") + ): raise exceptions.CommandError( "Filtering by source_share_server_id is only allowed with " "manila API version >= 2.57." @@ -212,8 +234,8 @@ def take_action(self, parsed_args): if parsed_args.share_network: share_network_id = osc_utils.find_resource( - share_client.share_networks, - parsed_args.share_network).id + share_client.share_networks, parsed_args.share_network + ).id search_opts['share_network'] = share_network_id if parsed_args.source_share_server_id: @@ -222,19 +244,21 @@ def take_action(self, parsed_args): ) if parsed_args.identifier: - search_opts['identifier'] = ( - parsed_args.identifier - ) + search_opts['identifier'] = parsed_args.identifier if parsed_args.share_network_subnet: search_opts['share_network_subnet_id'] = ( - parsed_args.share_network_subnet) + parsed_args.share_network_subnet + ) share_servers = share_client.share_servers.list( - search_opts=search_opts) + search_opts=search_opts + ) - data = (osc_utils.get_dict_properties( - share_server._info, columns) for share_server in share_servers) + data = ( + osc_utils.get_dict_properties(share_server._info, columns) + for share_server in share_servers + ) return (columns, data) @@ -245,34 +269,39 @@ class AdoptShareServer(command.ShowOne): _description = _("Adopt share server not handled by Manila (Admin only).") def get_parser(self, prog_name): - parser = super(AdoptShareServer, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'host', metavar='', type=str, - help=_('Backend name as "@".') + help=_('Backend name as "@".'), ) parser.add_argument( "share_network", metavar="", - help=_("Share network where share server has network " - "allocations in.") + help=_( + "Share network where share server has network allocations in." + ), ) parser.add_argument( 'identifier', metavar='', type=str, - help=_("A driver-specific share server identifier required " - "by the driver to manage the share server.") + help=_( + "A driver-specific share server identifier required " + "by the driver to manage the share server." + ), ) parser.add_argument( '--driver-options', metavar='', action=parseractions.KeyValueAction, default={}, - help=_("One or more driver-specific key=value pairs that may be " - "necessary to manage the share server (Optional, " - "Default=None).") + help=_( + "One or more driver-specific key=value pairs that may be " + "necessary to manage the share server (Optional, " + "Default=None)." + ), ) parser.add_argument( '--share-network-subnet', @@ -280,14 +309,14 @@ def get_parser(self, prog_name): metavar='', default=None, help="Share network subnet where share server has network " - "allocations in.The default subnet will be used if " - "it's not specified. Available for microversion " - ">= 2.51 (Optional, Default=None)." + "allocations in.The default subnet will be used if " + "it's not specified. Available for microversion " + ">= 2.51 (Optional, Default=None).", ) parser.add_argument( "--wait", action='store_true', - help=_("Wait until share server is adopted") + help=_("Wait until share server is adopted"), ) return parser @@ -297,26 +326,29 @@ def take_action(self, parsed_args): share_network = None if parsed_args.share_network: share_network = osc_utils.find_resource( - share_client.share_networks, - parsed_args.share_network).id + share_client.share_networks, parsed_args.share_network + ).id share_network_subnet = None - if (parsed_args.share_network_subnet and - share_client.api_version < api_versions.APIVersion("2.51")): + if ( + parsed_args.share_network_subnet + and share_client.api_version < api_versions.APIVersion("2.51") + ): raise exceptions.CommandError( "Share network subnet can be specified only with manila API " "version >= 2.51" ) elif parsed_args.share_network_subnet: share_network_subnet = share_client.share_network_subnets.get( - share_network, parsed_args.share_network_subnet).id + share_network, parsed_args.share_network_subnet + ).id share_server = share_client.share_servers.manage( host=parsed_args.host, share_network_id=share_network, identifier=parsed_args.identifier, driver_options=parsed_args.driver_options, - share_network_subnet_id=share_network_subnet + share_network_subnet_id=share_network_subnet, ) if parsed_args.wait: @@ -324,12 +356,13 @@ def take_action(self, parsed_args): status_f=share_client.share_servers.get, res_id=share_server.id, success_status=['active'], - error_status=['manage_error', 'error'] + error_status=['manage_error', 'error'], ): LOG.error(_("ERROR: Share server is in error state.")) - share_server = osc_utils.find_resource(share_client.share_servers, - share_server.id) + share_server = osc_utils.find_resource( + share_client.share_servers, share_server.id + ) share_server._info.pop('links', None) @@ -346,25 +379,27 @@ class AbandonShareServer(command.Command): _description = _("Remove one or more share server(s) (Admin only).") def get_parser(self, prog_name): - parser = super(AbandonShareServer, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "share_server", metavar="", nargs='+', - help=_("ID of the server(s) to be abandoned.") + help=_("ID of the server(s) to be abandoned."), ) parser.add_argument( "--force", action='store_true', default=False, - help=_("Enforces the unmanage share server operation, even " - "if the backend driver does not support it.") + help=_( + "Enforces the unmanage share server operation, even " + "if the backend driver does not support it." + ), ) parser.add_argument( "--wait", action='store_true', default=False, - help=_("Wait until share server is abandoned") + help=_("Wait until share server is abandoned"), ) return parser @@ -375,31 +410,36 @@ def take_action(self, parsed_args): for server in parsed_args.share_server: try: server_obj = osc_utils.find_resource( - share_client.share_servers, - server) + share_client.share_servers, server + ) kwargs = {} if parsed_args.force: kwargs['force'] = parsed_args.force - share_client.share_servers.unmanage( - server_obj, **kwargs) + share_client.share_servers.unmanage(server_obj, **kwargs) if parsed_args.wait: if not osc_utils.wait_for_delete( - manager=share_client.share_servers, - res_id=server_obj.id): + manager=share_client.share_servers, + res_id=server_obj.id, + ): result += 1 except Exception as e: result += 1 - LOG.error(_( - "Failed to abandon share server with " - "ID '%(server)s': %(e)s"), - {'server': server, 'e': e}) + LOG.error( + _( + "Failed to abandon share server with " + "ID '%(server)s': %(e)s" + ), + {'server': server, 'e': e}, + ) if result > 0: - total = len(parsed_args.share_server) - msg = f'Failed to abandon {result} of {total} servers.' - raise exceptions.CommandError(_(msg)) + msg = _('Failed to abandon %(result)s of %(total)s servers.') + raise exceptions.CommandError( + msg + % {'result': result, 'total': len(parsed_args.share_server)} + ) class SetShareServer(command.Command): @@ -408,87 +448,110 @@ class SetShareServer(command.Command): _description = _("Set share server properties (Admin only).") def get_parser(self, prog_name): - parser = super(SetShareServer, self).get_parser(prog_name) allowed_update_choices = [ - 'unmanage_starting', 'server_migrating_to', 'error', - 'unmanage_error', 'manage_error', 'inactive', 'active', - 'server_migrating', 'manage_starting', 'deleting', - 'network_change'] + 'unmanage_starting', + 'server_migrating_to', + 'error', + 'unmanage_error', + 'manage_error', + 'inactive', + 'active', + 'server_migrating', + 'manage_starting', + 'deleting', + 'network_change', + ] allowed_update_choices_str = ', '.join(allowed_update_choices) + + parser = super().get_parser(prog_name) parser.add_argument( "share_server", metavar="", - help=_("ID of the share server to modify.") + help=_("ID of the share server to modify."), ) parser.add_argument( "--status", metavar="", required=False, default=constants.STATUS_ACTIVE, - help=_("Assign a status to the share server. Options " - "include: %s. If no state is " - "provided, active will be " - "used." % allowed_update_choices_str) + help=_( + "Assign a status to the share server. Options " + "include: %s. If no state is " + "provided, active will be " + "used." + ) + % allowed_update_choices_str, ) parser.add_argument( '--task-state', metavar="", required=False, default=None, - help=_("Indicate which task state to assign the share server. " - "Options include migration_starting, migration_in_progress," - " migration_completing, migration_success, migration_error," - " migration_cancelled, migration_driver_in_progress, " - "migration_driver_phase1_done, data_copying_starting, " - "data_copying_in_progress, data_copying_completing, " - "data_copying_completed, data_copying_cancelled, " - "data_copying_error. ") + nargs='?', + help=_( + "Indicate which task state to assign the share server. " + "Options include migration_starting, migration_in_progress," + " migration_completing, migration_success, migration_error," + " migration_cancelled, migration_driver_in_progress, " + "migration_driver_phase1_done, data_copying_starting, " + "data_copying_in_progress, data_copying_completing, " + "data_copying_completed, data_copying_cancelled, " + "data_copying_error. " + ), ) return parser def take_action(self, parsed_args): if not parsed_args.status and not parsed_args.task_state: - msg = (_("A status or a task state should be provided for this " - "command.")) + msg = _( + "A status or a task state should be provided for this command." + ) LOG.error(msg) raise exceptions.CommandError(msg) share_client = self.app.client_manager.share share_server = osc_utils.find_resource( - share_client.share_servers, - parsed_args.share_server) + share_client.share_servers, parsed_args.share_server + ) if parsed_args.status: try: share_client.share_servers.reset_state( - share_server, - parsed_args.status + share_server, parsed_args.status ) except Exception as e: - msg = (_( - "Failed to set status '%(status)s': %(exception)s"), - {'status': parsed_args.status, 'exception': e}) + msg = ( + _("Failed to set status '%(status)s': %(exception)s"), + {'status': parsed_args.status, 'exception': e}, + ) LOG.error(msg) raise exceptions.CommandError(msg) - if parsed_args.task_state: + if hasattr(parsed_args, 'task_state'): if share_client.api_version < api_versions.APIVersion("2.57"): raise exceptions.CommandError( "Setting the state of a share server is only available " - "with manila API version >= 2.57") + "with manila API version >= 2.57" + ) else: + task_state = parsed_args.task_state + if task_state and task_state.lower() == "none": + task_state = None result = 0 try: share_client.share_servers.reset_task_state( - share_server, parsed_args.task_state) + share_server, task_state + ) except Exception as e: - LOG.error(_("Failed to update share server task state " - "%s"), e) + LOG.error( + _("Failed to update share server task state %s"), e + ) result += 1 if result > 0: - raise exceptions.CommandError(_("One or more of the " - "reset operations failed")) + raise exceptions.CommandError( + _("One or more of the reset operations failed") + ) class ShareServerMigrationCancel(command.Command): @@ -501,54 +564,54 @@ class ShareServerMigrationCancel(command.Command): _description = _("Cancels migration of a given share server when copying") def get_parser(self, prog_name): - parser = super(ShareServerMigrationCancel, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'share_server', metavar='', - help=_('ID of share server to cancel migration.') + help=_('ID of share server to cancel migration.'), ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share share_server = osc_utils.find_resource( - share_client.share_servers, - parsed_args.share_server) + share_client.share_servers, parsed_args.share_server + ) if share_client.api_version >= api_versions.APIVersion("2.57"): share_server.migration_cancel() else: raise exceptions.CommandError( "Share Server Migration cancel is only available " - "with manila API version >= 2.57") + "with manila API version >= 2.57" + ) class ShareServerMigrationComplete(command.Command): - """Completes migration for a given share server (Admin only, Experimental). + """Completes migration for a share server (Admin only, Experimental).""" - """ _description = _("Completes migration for a given share server") def get_parser(self, prog_name): - parser = super(ShareServerMigrationComplete, self).get_parser( - prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'share_server', metavar='', - help=_('ID of share server to complete migration.') + help=_('ID of share server to complete migration.'), ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share share_server = osc_utils.find_resource( - share_client.share_servers, - parsed_args.share_server) + share_client.share_servers, parsed_args.share_server + ) if share_client.api_version >= api_versions.APIVersion("2.57"): share_server.migration_complete() else: raise exceptions.CommandError( "Share Server Migration complete is only available " - "with manila API version >= 2.57") + "with manila API version >= 2.57" + ) class ShareServerMigrationShow(command.ShowOne): @@ -561,29 +624,30 @@ class ShareServerMigrationShow(command.ShowOne): """ _description = _( - "Gets migration progress of a given share server when copying") + "Gets migration progress of a given share server when copying" + ) def get_parser(self, prog_name): - parser = super(ShareServerMigrationShow, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'share_server', metavar='', - help='ID of share server to show migration progress for.' + help='ID of share server to show migration progress for.', ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share if share_client.api_version >= api_versions.APIVersion("2.57"): - share_server = osc_utils.find_resource( - share_client.share_servers, - parsed_args.share_server) - result = share_server.migration_get_progress() + result = share_client.share_servers.migration_get_progress( + parsed_args.share_server + ) return self.dict2columns(result) else: raise exceptions.CommandError( "Share Server Migration show is only available " - "with manila API version >= 2.57") + "with manila API version >= 2.57" + ) class ShareServerMigrationStart(command.ShowOne): @@ -592,76 +656,86 @@ class ShareServerMigrationStart(command.ShowOne): _description = _("Migrates share server to a new host.") def get_parser(self, prog_name): - parser = super(ShareServerMigrationStart, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'share_server', metavar='', - help=_('ID of share server to start migration.') + help=_('ID of share server to start migration.'), ) parser.add_argument( 'host', metavar='', - help=_("Destination to migrate the share server to. Use " - "the format '@'.") + help=_( + "Destination to migrate the share server to. Use " + "the format '@'." + ), ) parser.add_argument( '--preserve-snapshots', metavar='', choices=['True', 'False'], required=True, - help=_("Set to True if snapshots must be preserved at " - "the migration destination.") + help=_( + "Set to True if snapshots must be preserved at " + "the migration destination." + ), ) parser.add_argument( '--writable', metavar='', choices=['True', 'False'], required=True, - help=_("Enforces migration to keep all its shares writable " - "while contents are being moved.") + help=_( + "Enforces migration to keep all its shares writable " + "while contents are being moved." + ), ) parser.add_argument( '--nondisruptive', metavar='', choices=['True', 'False'], required=True, - help=_("Enforces migration to be nondisruptive.") + help=_("Enforces migration to be nondisruptive."), ) parser.add_argument( '--new-share-network', metavar='', required=False, default=None, - help=_('Specify a new share network for the share server. Do not ' - 'specify this parameter if the migrating share server has ' - 'to be retained within its current share network.',) + help=_( + 'Specify a new share network for the share server. Do not ' + 'specify this parameter if the migrating share server has ' + 'to be retained within its current share network.' + ), ) parser.add_argument( '--check-only', action='store_true', default=False, - help=_("Run a dry-run of the share server migration. ") + help=_("Run a dry-run of the share server migration. "), ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share share_server = osc_utils.find_resource( - share_client.share_servers, - parsed_args.share_server) + share_client.share_servers, parsed_args.share_server + ) if share_client.api_version >= api_versions.APIVersion("2.57"): new_share_net_id = None result = None if parsed_args.new_share_network: new_share_net_id = apiutils.find_resource( - share_client.share_networks, - parsed_args.new_share_network).id + share_client.share_networks, parsed_args.new_share_network + ).id if parsed_args.check_only: result = share_server.migration_check( - parsed_args.host, parsed_args.writable, - parsed_args.nondisruptive, parsed_args.preserve_snapshots, - new_share_net_id + parsed_args.host, + parsed_args.writable, + parsed_args.nondisruptive, + parsed_args.preserve_snapshots, + new_share_net_id, ) if result: if parsed_args.formatter == 'table': @@ -674,13 +748,16 @@ def take_action(self, parsed_args): result[k] = dict_values return self.dict2columns(result) else: - share_server.migration_start(parsed_args.host, - parsed_args.writable, - parsed_args.nondisruptive, - parsed_args.preserve_snapshots, - new_share_net_id) + share_server.migration_start( + parsed_args.host, + parsed_args.writable, + parsed_args.nondisruptive, + parsed_args.preserve_snapshots, + new_share_net_id, + ) return ({}, {}) else: raise exceptions.CommandError( "Share Server Migration is only available " - "with manila API version >= 2.57") + "with manila API version >= 2.57" + ) diff --git a/manilaclient/osc/v2/share_snapshot_instance_export_locations.py b/manilaclient/osc/v2/share_snapshot_instance_export_locations.py index 449987d8..01395b5b 100644 --- a/manilaclient/osc/v2/share_snapshot_instance_export_locations.py +++ b/manilaclient/osc/v2/share_snapshot_instance_export_locations.py @@ -19,16 +19,15 @@ class ShareSnapshotInstanceExportLocationList(command.Lister): """List export locations from a share snapshot instance.""" + _description = _("List export locations from a share snapshot instance.") def get_parser(self, prog_name): - parser = ( - super(ShareSnapshotInstanceExportLocationList, self).get_parser( - prog_name)) + parser = super().get_parser(prog_name) parser.add_argument( "instance", metavar="", - help=_("Name or ID of the share instance.") + help=_("Name or ID of the share instance."), ) return parser @@ -37,37 +36,42 @@ def take_action(self, parsed_args): share_client = self.app.client_manager.share snapshot_instance = apiutils.find_resource( - share_client.share_snapshot_instances, parsed_args.instance) + share_client.share_snapshot_instances, parsed_args.instance + ) share_snapshot_instance_export_locations = ( share_client.share_snapshot_instance_export_locations.list( - snapshot_instance=snapshot_instance)) + snapshot_instance=snapshot_instance + ) + ) columns = ["ID", "Path", "Is Admin only"] return ( columns, - (utils.get_item_properties(s, columns) for s in - share_snapshot_instance_export_locations)) + ( + utils.get_item_properties(s, columns) + for s in share_snapshot_instance_export_locations + ), + ) class ShareSnapshotInstanceExportLocationShow(command.ShowOne): """Show export location of the share snapshot instance.""" + _description = _("Show export location of the share snapshot instance.") def get_parser(self, prog_name): - parser = ( - super(ShareSnapshotInstanceExportLocationShow, self).get_parser( - prog_name)) + parser = super().get_parser(prog_name) parser.add_argument( 'snapshot_instance', metavar='', - help=_('ID of the share snapshot instance.') + help=_('ID of the share snapshot instance.'), ) parser.add_argument( 'export_location', metavar='', - help=_('ID of the share snapshot instance export location.') + help=_('ID of the share snapshot instance export location.'), ) return parser @@ -77,12 +81,15 @@ def take_action(self, parsed_args): snapshot_instance = apiutils.find_resource( share_client.share_snapshot_instances, - parsed_args.snapshot_instance) + parsed_args.snapshot_instance, + ) share_snapshot_instance_export_location = ( share_client.share_snapshot_instance_export_locations.get( parsed_args.export_location, - snapshot_instance=snapshot_instance)) + snapshot_instance=snapshot_instance, + ) + ) share_snapshot_instance_export_location._info.pop('links', None) diff --git a/manilaclient/osc/v2/share_snapshot_instances.py b/manilaclient/osc/v2/share_snapshot_instances.py index 2e44f9dd..ccb94fe0 100644 --- a/manilaclient/osc/v2/share_snapshot_instances.py +++ b/manilaclient/osc/v2/share_snapshot_instances.py @@ -20,29 +20,32 @@ class ListShareSnapshotInstance(command.Lister): """List all share snapshot instances.""" + _description = _("List all share snapshot instances") def get_parser(self, prog_name): - parser = super(ListShareSnapshotInstance, self).get_parser( - prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "--snapshot", metavar="", default=None, - help=_("Filter results by share snapshot ID.") + help=_("Filter results by share snapshot ID."), ) parser.add_argument( "--detailed", action="store_true", - help=_("Show detailed information about snapshot instances. ") + help=_("Show detailed information about snapshot instances. "), ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share - snapshot = (share_client.share_snapshots.get(parsed_args.snapshot) - if parsed_args.snapshot else None) + snapshot = ( + share_client.share_snapshots.get(parsed_args.snapshot) + if parsed_args.snapshot + else None + ) share_snapshot_instances = share_client.share_snapshot_instances.list( detailed=parsed_args.detailed, @@ -51,26 +54,36 @@ def take_action(self, parsed_args): list_of_keys = ['ID', 'Snapshot ID', 'Status'] - if (parsed_args.detailed): - list_of_keys += ['Created At', 'Updated At', 'Share ID', - 'Share Instance ID', 'Progress', - 'Provider Location'] - - return (list_of_keys, (utils.get_item_properties - (s, list_of_keys) for s in share_snapshot_instances)) + if parsed_args.detailed: + list_of_keys += [ + 'Created At', + 'Updated At', + 'Share ID', + 'Share Instance ID', + 'Progress', + 'Provider Location', + ] + + return ( + list_of_keys, + ( + utils.get_item_properties(s, list_of_keys) + for s in share_snapshot_instances + ), + ) class ShowShareSnapshotInstance(command.ShowOne): """Show details about a share snapshot instance.""" + _description = _("Show details about a share snapshot instance.") def get_parser(self, prog_name): - parser = super(ShowShareSnapshotInstance, self).get_parser( - prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "snapshot_instance", metavar="", - help=_("ID of the share snapshot instance.") + help=_("ID of the share snapshot instance."), ) return parser @@ -78,22 +91,28 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): share_client = self.app.client_manager.share snapshot_instance = share_client.share_snapshot_instances.get( - parsed_args.snapshot_instance) + parsed_args.snapshot_instance + ) snapshot_instance_export_locations = ( share_client.share_snapshot_instance_export_locations.list( - snapshot_instance=snapshot_instance)) + snapshot_instance=snapshot_instance + ) + ) snapshot_instance._info['export_locations'] = [] for element_location in snapshot_instance_export_locations: element_location._info.pop('links', None) snapshot_instance._info['export_locations'].append( - element_location._info) + element_location._info + ) if parsed_args.formatter == 'table': snapshot_instance._info['export_locations'] = ( cliutils.convert_dict_list_to_string( - snapshot_instance._info['export_locations'])) + snapshot_instance._info['export_locations'] + ) + ) snapshot_instance._info.pop('links', None) @@ -102,25 +121,33 @@ def take_action(self, parsed_args): class SetShareSnapshotInstance(command.Command): """Explicitly update the state of a share snapshot instance.""" - _description = _("Explicitly update the state of a share snapshot " - "instance.") + + _description = _( + "Explicitly update the state of a share snapshot instance." + ) def get_parser(self, prog_name): - parser = super(SetShareSnapshotInstance, self).get_parser( - prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "snapshot_instance", metavar="", - help=_("ID of the share snapshot instance to update.") + help=_("ID of the share snapshot instance to update."), ) parser.add_argument( '--status', metavar='', default='available', - choices=['available', 'error', 'creating', 'deleting', - 'error_deleting'], - help=_('Indicate state to update the snapshot instance to. ' - 'Default is available.') + choices=[ + 'available', + 'error', + 'creating', + 'deleting', + 'error_deleting', + ], + help=_( + 'Indicate state to update the snapshot instance to. ' + 'Default is available.' + ), ) return parser @@ -130,8 +157,8 @@ def take_action(self, parsed_args): try: share_client.share_snapshot_instances.reset_state( - parsed_args.snapshot_instance, parsed_args.status) + parsed_args.snapshot_instance, parsed_args.status + ) except Exception as e: - msg = _( - "Failed to update share snapshot instance status: %s" % e) - raise exceptions.CommandError(msg) + msg = _("Failed to update share snapshot instance status: %(e)s") + raise exceptions.CommandError(msg % {'e': e}) diff --git a/manilaclient/osc/v2/share_snapshots.py b/manilaclient/osc/v2/share_snapshots.py index bb4afa11..88bc7396 100644 --- a/manilaclient/osc/v2/share_snapshots.py +++ b/manilaclient/osc/v2/share_snapshots.py @@ -28,83 +28,87 @@ class CreateShareSnapshot(command.ShowOne): """Create a share snapshot.""" - _description = _( - "Create a snapshot of the given share") + + _description = _("Create a snapshot of the given share") def get_parser(self, prog_name): - parser = super(CreateShareSnapshot, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "share", metavar="", - help=_("Name or ID of the share to create snapshot of") + help=_("Name or ID of the share to create snapshot of"), ) parser.add_argument( "--force", action='store_true', default=False, - help=_("Optional flag to indicate whether to snapshot " - "a share even if it's busy. (Default=False)") + help=_( + "Optional flag to indicate whether to snapshot " + "a share even if it's busy. (Default=False)" + ), ) parser.add_argument( "--name", metavar="", default=None, - help=_("Add a name to the snapshot (Optional).") + help=_("Add a name to the snapshot (Optional)."), ) parser.add_argument( "--description", metavar="", default=None, - help=_("Add a description to the snapshot (Optional).") + help=_("Add a description to the snapshot (Optional)."), ) parser.add_argument( '--wait', action='store_true', default=False, - help=_('Wait for share snapshot creation') + help=_('Wait for share snapshot creation'), ) parser.add_argument( "--property", metavar="", default={}, action=parseractions.KeyValueAction, - help=_("Set a property to this snapshot " - "(repeat option to set multiple properties)." - "Available only for microversion >= 2.73"), + help=_( + "Set a property to this snapshot " + "(repeat option to set multiple properties)." + "Available only for microversion >= 2.73" + ), ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share - share = utils.find_resource(share_client.shares, - parsed_args.share) + share = utils.find_resource(share_client.shares, parsed_args.share) if share_client.api_version >= api_versions.APIVersion("2.73"): property = parsed_args.property or {} elif parsed_args.property: raise exceptions.CommandError( "Setting metadtaa is only available with manila API version " - ">= 2.73") + ">= 2.73" + ) share_snapshot = share_client.share_snapshots.create( share=share, force=parsed_args.force, name=parsed_args.name or None, description=parsed_args.description or None, - metadata=property + metadata=property, ) if parsed_args.wait: if not utils.wait_for_status( status_f=share_client.share_snapshots.get, res_id=share_snapshot.id, - success_status=['available'] + success_status=['available'], ): LOG.error(_("ERROR: Share snapshot is in error state.")) share_snapshot = utils.find_resource( - share_client.share_snapshots, - share_snapshot.id) + share_client.share_snapshots, share_snapshot.id + ) share_snapshot._info.pop('links', None) return self.dict2columns(share_snapshot._info) @@ -112,28 +116,28 @@ def take_action(self, parsed_args): class DeleteShareSnapshot(command.Command): """Delete one or more share snapshots""" - _description = _( - "Delete one or more share snapshots") + + _description = _("Delete one or more share snapshots") def get_parser(self, prog_name): - parser = super(DeleteShareSnapshot, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "snapshot", metavar="", nargs="+", - help=_("Name or ID of the snapshot(s) to delete") + help=_("Name or ID of the snapshot(s) to delete"), ) parser.add_argument( "--force", action='store_true', default=False, - help=_("Delete the snapshot(s) ignoring the current state.") + help=_("Delete the snapshot(s) ignoring the current state."), ) parser.add_argument( "--wait", action='store_true', default=False, - help=_("Wait for share snapshot deletion") + help=_("Wait for share snapshot deletion"), ) return parser @@ -144,44 +148,48 @@ def take_action(self, parsed_args): for snapshot in parsed_args.snapshot: try: snapshot_obj = utils.find_resource( - share_client.share_snapshots, - snapshot) + share_client.share_snapshots, snapshot + ) if parsed_args.force: - share_client.share_snapshots.force_delete( - snapshot_obj) + share_client.share_snapshots.force_delete(snapshot_obj) else: - share_client.share_snapshots.delete( - snapshot_obj) + share_client.share_snapshots.delete(snapshot_obj) if parsed_args.wait: if not utils.wait_for_delete( - manager=share_client.share_snapshots, - res_id=snapshot_obj.id): + manager=share_client.share_snapshots, + res_id=snapshot_obj.id, + ): result += 1 except Exception as e: result += 1 - LOG.error(_( - "Failed to delete snapshot with " - "name or ID '%(snapshot)s': %(e)s"), - {'snapshot': snapshot, 'e': e}) + LOG.error( + _( + "Failed to delete snapshot with " + "name or ID '%(snapshot)s': %(e)s" + ), + {'snapshot': snapshot, 'e': e}, + ) if result > 0: total = len(parsed_args.snapshot) - msg = (_("%(result)s of %(total)s snapshots failed " - "to delete.") % {'result': result, 'total': total}) + msg = _("%(result)s of %(total)s snapshots failed to delete.") % { + 'result': result, + 'total': total, + } raise exceptions.CommandError(msg) class ShowShareSnapshot(command.ShowOne): """Display a share snapshot""" - _description = _( - "Show details about a share snapshot") + + _description = _("Show details about a share snapshot") def get_parser(self, prog_name): - parser = super(ShowShareSnapshot, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "snapshot", metavar="", - help=_("Name or ID of the snapshot to display") + help=_("Name or ID of the snapshot to display"), ) return parser @@ -189,12 +197,12 @@ def take_action(self, parsed_args): share_client = self.app.client_manager.share share_snapshot = utils.find_resource( - share_client.share_snapshots, - parsed_args.snapshot) + share_client.share_snapshots, parsed_args.snapshot + ) - export_locations = ( - share_client.share_snapshot_export_locations.list( - share_snapshot)) + export_locations = share_client.share_snapshot_export_locations.list( + share_snapshot + ) locations = [] for location in export_locations: @@ -202,8 +210,7 @@ def take_action(self, parsed_args): locations.append(location._info) if parsed_args.formatter == 'table': - locations = cliutils.convert_dict_list_to_string( - locations) + locations = cliutils.convert_dict_list_to_string(locations) data = share_snapshot._info data['export_locations'] = locations @@ -211,8 +218,9 @@ def take_action(self, parsed_args): # 'metadata' --> 'properties' data.update( { - 'properties': - format_columns.DictColumn(data.pop('metadata', {})), + 'properties': format_columns.DictColumn( + data.pop('metadata', {}) + ), }, ) data.pop('links', None) @@ -222,46 +230,58 @@ def take_action(self, parsed_args): class SetShareSnapshot(command.Command): """Set share snapshot properties.""" + _description = _("Set share snapshot properties") def get_parser(self, prog_name): - parser = super(SetShareSnapshot, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "snapshot", metavar="", - help=_('Name or ID of the snapshot to set a property for') + help=_('Name or ID of the snapshot to set a property for'), ) parser.add_argument( "--name", metavar="", default=None, - help=_("Set a name to the snapshot.") + help=_("Set a name to the snapshot."), ) parser.add_argument( "--description", metavar="", default=None, - help=_("Set a description to the snapshot.") + help=_("Set a description to the snapshot."), ) parser.add_argument( "--status", metavar="", - choices=['available', 'error', 'creating', 'deleting', - 'manage_starting', 'manage_error', - 'unmanage_starting', 'unmanage_error', - 'error_deleting'], - help=_("Assign a status to the snapshot (Admin only). " - "Options include : available, error, creating, " - "deleting, manage_starting, manage_error, " - "unmanage_starting, unmanage_error, error_deleting.") + choices=[ + 'available', + 'error', + 'creating', + 'deleting', + 'manage_starting', + 'manage_error', + 'unmanage_starting', + 'unmanage_error', + 'error_deleting', + ], + help=_( + "Assign a status to the snapshot (Admin only). " + "Options include : available, error, creating, " + "deleting, manage_starting, manage_error, " + "unmanage_starting, unmanage_error, error_deleting." + ), ) parser.add_argument( "--property", metavar="", default={}, action=parseractions.KeyValueAction, - help=_("Set a property to this snapshot " - "(repeat option to set multiple properties)"), + help=_( + "Set a property to this snapshot " + "(repeat option to set multiple properties)" + ), ) return parser @@ -270,8 +290,8 @@ def take_action(self, parsed_args): result = 0 share_snapshot = utils.find_resource( - share_client.share_snapshots, - parsed_args.snapshot) + share_client.share_snapshots, parsed_args.snapshot + ) kwargs = {} @@ -281,54 +301,60 @@ def take_action(self, parsed_args): kwargs['display_description'] = parsed_args.description try: - share_client.share_snapshots.update( - share_snapshot, - **kwargs - ) + share_client.share_snapshots.update(share_snapshot, **kwargs) except Exception as e: result += 1 - LOG.error(_( - "Failed to set share snapshot properties " - "'%(properties)s': %(exception)s"), - {'properties': kwargs, - 'exception': e}) + LOG.error( + _( + "Failed to set share snapshot properties " + "'%(properties)s': %(exception)s" + ), + {'properties': kwargs, 'exception': e}, + ) if parsed_args.status: try: share_client.share_snapshots.reset_state( - share_snapshot, - parsed_args.status + share_snapshot, parsed_args.status ) except Exception as e: result += 1 - LOG.error(_( - "Failed to update snapshot status to " - "'%(status)s': %(e)s"), - {'status': parsed_args.status, 'e': e}) + LOG.error( + _( + "Failed to update snapshot status to " + "'%(status)s': %(e)s" + ), + {'status': parsed_args.status, 'e': e}, + ) if parsed_args.property: try: share_snapshot.set_metadata(parsed_args.property) except Exception as e: - LOG.error(_("Failed to set share snapshot properties " - "'%(properties)s': %(exception)s"), - {'properties': parsed_args.property, - 'exception': e}) + LOG.error( + _( + "Failed to set share snapshot properties " + "'%(properties)s': %(exception)s" + ), + {'properties': parsed_args.property, 'exception': e}, + ) result += 1 if result > 0: - raise exceptions.CommandError(_("One or more of the " - "set operations failed")) + raise exceptions.CommandError( + _("One or more of the set operations failed") + ) class UnsetShareSnapshot(command.Command): """Unset a share snapshot property.""" + _description = _("Unset a share snapshot property") def get_parser(self, prog_name): - parser = super(UnsetShareSnapshot, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "snapshot", metavar="", - help=_("Name or ID of the snapshot to set a property for") + help=_("Name or ID of the snapshot to set a property for"), ) parser.add_argument( "--name", @@ -344,8 +370,10 @@ def get_parser(self, prog_name): '--property', metavar='', action='append', - help=_('Remove a property from snapshot ' - '(repeat option to remove multiple properties)'), + help=_( + 'Remove a property from snapshot ' + '(repeat option to remove multiple properties)' + ), ) return parser @@ -353,8 +381,8 @@ def take_action(self, parsed_args): share_client = self.app.client_manager.share share_snapshot = utils.find_resource( - share_client.share_snapshots, - parsed_args.snapshot) + share_client.share_snapshots, parsed_args.snapshot + ) kwargs = {} if parsed_args.name: @@ -363,68 +391,70 @@ def take_action(self, parsed_args): kwargs['display_description'] = None if kwargs: try: - share_client.share_snapshots.update( - share_snapshot, - **kwargs - ) + share_client.share_snapshots.update(share_snapshot, **kwargs) except Exception as e: - raise exceptions.CommandError(_( - "Failed to unset snapshot display name " - "or display description : %s" % e)) + msg = _( + "Failed to unset snapshot display name or display " + "description: %(e)s" + ) + raise exceptions.CommandError(msg % {'e': e}) if parsed_args.property: for key in parsed_args.property: try: share_snapshot.delete_metadata([key]) except Exception as e: - raise exceptions.CommandError(_( - "Failed to unset snapshot property " - "'%(key)s': %(e)s"), - {'key': key, 'e': e}) + msg = _( + "Failed to unset snapshot property '%(key)s': %(e)s" + ) + raise exceptions.CommandError(msg % {'key': key, 'e': e}) class ListShareSnapshot(command.Lister): """List snapshots.""" + _description = _("List snapshots") def get_parser(self, prog_name): - parser = super(ListShareSnapshot, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "--all-projects", action='store_true', default=False, - help=_("Display snapshots from all projects (Admin only).") + help=_("Display snapshots from all projects (Admin only)."), ) parser.add_argument( "--name", metavar="", default=None, - help=_("Filter results by name.") + help=_("Filter results by name."), ) parser.add_argument( '--description', metavar="", default=None, - help=_("Filter results by description. Available only for " - "microversion >= 2.36.") + help=_( + "Filter results by description. Available only for " + "microversion >= 2.36." + ), ) parser.add_argument( '--status', metavar="", default=None, - help=_('Filter results by status') + help=_('Filter results by status'), ) parser.add_argument( '--share', metavar='', default=None, - help=_('Name or ID of a share to filter results by.') + help=_('Name or ID of a share to filter results by.'), ) parser.add_argument( '--usage', metavar='', default=None, choices=['used', 'unused'], - help=_("Option to filter snapshots by usage.") + help=_("Option to filter snapshots by usage."), ) parser.add_argument( "--limit", @@ -432,57 +462,67 @@ def get_parser(self, prog_name): type=int, default=None, action=parseractions.NonNegativeAction, - help=_("Limit the number of snapshots returned") + help=_("Limit the number of snapshots returned"), ) parser.add_argument( "--marker", metavar="", - help=_("The last share ID of the previous page") + help=_("The last share ID of the previous page"), ) parser.add_argument( '--sort', metavar="[:]", default='name:asc', - help=_("Sort output by selected keys and directions(asc or desc) " - "(default: name:asc), multiple keys and directions can be " - "specified separated by comma") + help=_( + "Sort output by selected keys and directions(asc or desc) " + "(default: name:asc), multiple keys and directions can be " + "specified separated by comma" + ), ) parser.add_argument( "--name~", metavar="", default=None, - help=_("Filter results matching a share snapshot name pattern. " - "Available only for microversion >= 2.36.") + help=_( + "Filter results matching a share snapshot name pattern. " + "Available only for microversion >= 2.36." + ), ) parser.add_argument( '--description~', metavar="", default=None, - help=_("Filter results matching a share snapshot description " - "pattern. Available only for microversion >= 2.36.") + help=_( + "Filter results matching a share snapshot description " + "pattern. Available only for microversion >= 2.36." + ), ) parser.add_argument( '--detail', action='store_true', default=False, - help=_("List share snapshots with details") + help=_("List share snapshots with details"), ) parser.add_argument( '--property', metavar='', action=parseractions.KeyValueAction, - help=_('Filter snapshots having a given metadata key=value ' - 'property. (repeat option to filter by multiple ' - 'properties)'), + help=_( + 'Filter snapshots having a given metadata key=value ' + 'property. (repeat option to filter by multiple ' + 'properties)' + ), ) parser.add_argument( '--count', action='store_true', default=False, - help=_("The total count of share snapshots before pagination is " - "applied. This parameter is useful when applying " - "pagination parameters '--limit' and '--offset'. Available " - "only for microversion >= 2.79.") + help=_( + "The total count of share snapshots before pagination is " + "applied. This parameter is useful when applying " + "pagination parameters '--limit' and '--offset'. Available " + "only for microversion >= 2.79." + ), ) return parser @@ -492,8 +532,9 @@ def take_action(self, parsed_args): share_id = None if parsed_args.share: - share_id = utils.find_resource(share_client.shares, - parsed_args.share).id + share_id = utils.find_resource( + share_client.shares, parsed_args.share + ).id columns = ['ID', 'Name'] search_opts = { @@ -505,39 +546,48 @@ def take_action(self, parsed_args): 'share_id': share_id, 'usage': parsed_args.usage, 'metadata': oscutils.extract_key_value_options( - parsed_args.property), + parsed_args.property + ), } if share_client.api_version >= api_versions.APIVersion("2.36"): search_opts['name~'] = getattr(parsed_args, 'name~') search_opts['description~'] = getattr(parsed_args, 'description~') search_opts['description'] = parsed_args.description - elif (parsed_args.description or getattr(parsed_args, 'name~') or - getattr(parsed_args, 'description~')): + elif ( + parsed_args.description + or getattr(parsed_args, 'name~') + or getattr(parsed_args, 'description~') + ): raise exceptions.CommandError( "Pattern based filtering (name~, description~ and description)" - " is only available with manila API version >= 2.36") + " is only available with manila API version >= 2.36" + ) if parsed_args.count: if share_client.api_version < api_versions.APIVersion("2.79"): raise exceptions.CommandError( "Displaying total number of share snapshots is only " - "available with manila API version >= 2.79") + "available with manila API version >= 2.79" + ) if parsed_args.formatter != 'table': raise exceptions.CommandError( - "Count can only be printed when using '--format table'") + "Count can only be printed when using '--format table'" + ) if parsed_args.detail: - columns.extend([ - 'Status', - 'Description', - 'Created At', - 'Size', - 'Share ID', - 'Share Proto', - 'Share Size', - 'User ID' - ]) + columns.extend( + [ + 'Status', + 'Description', + 'Created At', + 'Size', + 'Share ID', + 'Share Proto', + 'Share Size', + 'User ID', + ] + ) if parsed_args.all_projects: columns.append('Project ID') @@ -546,17 +596,21 @@ def take_action(self, parsed_args): if parsed_args.count: search_opts['with_count'] = True snapshots, total_count = share_client.share_snapshots.list( - search_opts=search_opts) + search_opts=search_opts + ) else: snapshots = share_client.share_snapshots.list( - search_opts=search_opts) + search_opts=search_opts + ) snapshots = utils.sort_items(snapshots, parsed_args.sort, str) if parsed_args.count: - print("Total number of snapshots: %s" % total_count) - return (columns, - (utils.get_item_properties(s, columns) for s in snapshots)) + print(f"Total number of snapshots: {total_count}") + return ( + columns, + (utils.get_item_properties(s, columns) for s in snapshots), + ) class AdoptShareSnapshot(command.ShowOne): @@ -565,29 +619,30 @@ class AdoptShareSnapshot(command.ShowOne): _description = _("Adopt a share snapshot") def get_parser(self, prog_name): - parser = super(AdoptShareSnapshot, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "share", metavar="", - help=_("Name or ID of the share that owns the snapshot " - "to be adopted.") + help=_( + "Name or ID of the share that owns the snapshot to be adopted." + ), ) parser.add_argument( "provider_location", metavar="", - help=_("Provider location of the snapshot on the backend.") + help=_("Provider location of the snapshot on the backend."), ) parser.add_argument( "--name", metavar="", default=None, - help=_("Optional snapshot name (Default=None).") + help=_("Optional snapshot name (Default=None)."), ) parser.add_argument( "--description", metavar="", default=None, - help=_("Optional snapshot description (Default=None).") + help=_("Optional snapshot description (Default=None)."), ) parser.add_argument( "--driver-option", @@ -596,27 +651,27 @@ def get_parser(self, prog_name): action=parseractions.KeyValueAction, help=_( "Set driver options as key=value pairs." - "(repeat option to set multiple key=value pairs)") + "(repeat option to set multiple key=value pairs)" + ), ) parser.add_argument( "--wait", action='store_true', - help=_("Wait until share snapshot is adopted") + help=_("Wait until share snapshot is adopted"), ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share - share = utils.find_resource(share_client.shares, - parsed_args.share) + share = utils.find_resource(share_client.shares, parsed_args.share) snapshot = share_client.share_snapshots.manage( share=share, provider_location=parsed_args.provider_location, driver_options=parsed_args.driver_option, name=parsed_args.name, - description=parsed_args.description + description=parsed_args.description, ) if parsed_args.wait: @@ -624,12 +679,13 @@ def take_action(self, parsed_args): status_f=share_client.share_snapshots.get, res_id=snapshot.id, success_status=['available'], - error_status=['manage_error', 'error'] + error_status=['manage_error', 'error'], ): LOG.error(_("ERROR: Share snapshot is in error state.")) - snapshot = utils.find_resource(share_client.share_snapshots, - snapshot.id) + snapshot = utils.find_resource( + share_client.share_snapshots, snapshot.id + ) snapshot._info.pop('links', None) @@ -642,17 +698,17 @@ class AbandonShareSnapshot(command.Command): _description = _("Abandon share snapshot(s)") def get_parser(self, prog_name): - parser = super(AbandonShareSnapshot, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "snapshot", metavar="", nargs='+', - help=_("Name or ID of the snapshot(s) to be abandoned.") + help=_("Name or ID of the snapshot(s) to be abandoned."), ) parser.add_argument( "--wait", action='store_true', - help=_("Wait until share snapshot is abandoned") + help=_("Wait until share snapshot is abandoned"), ) return parser @@ -662,26 +718,32 @@ def take_action(self, parsed_args): for snapshot in parsed_args.snapshot: snapshot_obj = utils.find_resource( - share_client.share_snapshots, - snapshot) + share_client.share_snapshots, snapshot + ) try: share_client.share_snapshots.unmanage(snapshot_obj) if parsed_args.wait: if not utils.wait_for_delete( - manager=share_client.share_snapshots, - res_id=snapshot_obj.id): + manager=share_client.share_snapshots, + res_id=snapshot_obj.id, + ): result += 1 except Exception as e: result += 1 - LOG.error(_( - "Failed to abandon share snapshot with " - "name or ID '%(snapshot)s': %(e)s"), - {'snapshot': snapshot, 'e': e}) + LOG.error( + _( + "Failed to abandon share snapshot with " + "name or ID '%(snapshot)s': %(e)s" + ), + {'snapshot': snapshot, 'e': e}, + ) if result > 0: total = len(parsed_args.snapshot) - msg = (_("%(result)s of %(total)s snapshots failed " - "to abandon.") % {'result': result, 'total': total}) + msg = _("%(result)s of %(total)s snapshots failed to abandon.") % { + 'result': result, + 'total': total, + } raise exceptions.CommandError(msg) @@ -691,22 +753,24 @@ class ShareSnapshotAccessAllow(command.ShowOne): _description = _("Allow access to a snapshot") def get_parser(self, prog_name): - parser = super(ShareSnapshotAccessAllow, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "snapshot", metavar="", - help=_("Name or ID of the snapshot") + help=_("Name or ID of the snapshot"), ) parser.add_argument( 'access_type', metavar="", - help=_('Access rule type (only "ip", "user" (user or group), ' - '"cert" or "cephx" are supported).') + help=_( + 'Access rule type (only "ip", "user" (user or group), ' + '"cert" or "cephx" are supported).' + ), ) parser.add_argument( 'access_to', metavar="", - help=_('Value that defines access.') + help=_('Value that defines access.'), ) return parser @@ -714,41 +778,41 @@ def take_action(self, parsed_args): share_client = self.app.client_manager.share snapshot_obj = utils.find_resource( - share_client.share_snapshots, - parsed_args.snapshot) + share_client.share_snapshots, parsed_args.snapshot + ) try: snapshot_access = share_client.share_snapshots.allow( snapshot=snapshot_obj, access_type=parsed_args.access_type, - access_to=parsed_args.access_to + access_to=parsed_args.access_to, ) return self.dict2columns(snapshot_access) except Exception as e: raise exceptions.CommandError( "Failed to create access to share snapshot " - "'%s': %s" % (snapshot_obj, e)) + f"'{snapshot_obj}': {e}" + ) class ShareSnapshotAccessDeny(command.Command): """Delete access to a snapshot""" - _description = _( - "Delete access to a snapshot") + _description = _("Delete access to a snapshot") def get_parser(self, prog_name): - parser = super(ShareSnapshotAccessDeny, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "snapshot", metavar="", - help=_("Name or ID of the share snapshot to deny access to.") + help=_("Name or ID of the share snapshot to deny access to."), ) parser.add_argument( "id", metavar="", nargs="+", - help=_("ID(s) of the access rule(s) to be deleted.") + help=_("ID(s) of the access rule(s) to be deleted."), ) return parser @@ -757,42 +821,46 @@ def take_action(self, parsed_args): result = 0 snapshot_obj = utils.find_resource( - share_client.share_snapshots, - parsed_args.snapshot) + share_client.share_snapshots, parsed_args.snapshot + ) for access_id in parsed_args.id: try: share_client.share_snapshots.deny( - snapshot=snapshot_obj, - id=access_id + snapshot=snapshot_obj, id=access_id ) except Exception as e: result += 1 - LOG.error(_( - "Failed to delete access to share snapshot " - "for an access rule with ID '%(access)s': %(e)s"), - {'access': access_id, 'e': e}) + LOG.error( + _( + "Failed to delete access to share snapshot " + "for an access rule with ID '%(access)s': %(e)s" + ), + {'access': access_id, 'e': e}, + ) if result > 0: total = len(parsed_args.id) - msg = (_("Failed to delete access to a share snapshot for " - "%(result)s out of %(total)s access rule ID's ") - % {'result': result, 'total': total}) + msg = _( + "Failed to delete access to a share snapshot for " + "%(result)s out of %(total)s access rule ID's " + ) % {'result': result, 'total': total} raise exceptions.CommandError(msg) class ShareSnapshotAccessList(command.Lister): """Show access list for a snapshot""" - _description = _( - "Show access list for a snapshot") + _description = _("Show access list for a snapshot") def get_parser(self, prog_name): - parser = super(ShareSnapshotAccessList, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "snapshot", metavar="", - help=_("Name or ID of the share snapshot to show access list for.") + help=_( + "Name or ID of the share snapshot to show access list for." + ), ) return parser @@ -800,36 +868,30 @@ def take_action(self, parsed_args): share_client = self.app.client_manager.share snapshot_obj = utils.find_resource( - share_client.share_snapshots, - parsed_args.snapshot) + share_client.share_snapshots, parsed_args.snapshot + ) - access_rules = share_client.share_snapshots.access_list( - snapshot_obj) + access_rules = share_client.share_snapshots.access_list(snapshot_obj) - columns = [ - "ID", - "Access Type", - "Access To", - "State" - ] + columns = ["ID", "Access Type", "Access To", "State"] - return (columns, - (utils.get_item_properties(s, columns) for s in access_rules)) + return ( + columns, + (utils.get_item_properties(s, columns) for s in access_rules), + ) class ShareSnapshotListExportLocation(command.Lister): """List export locations of a given snapshot""" - _description = _( - "List export locations of a given snapshot") + _description = _("List export locations of a given snapshot") def get_parser(self, prog_name): - parser = super(ShareSnapshotListExportLocation, self).get_parser( - prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "snapshot", metavar="", - help=_("Name or ID of the share snapshot.") + help=_("Name or ID of the share snapshot."), ) return parser @@ -837,37 +899,37 @@ def take_action(self, parsed_args): share_client = self.app.client_manager.share snapshot_obj = utils.find_resource( - share_client.share_snapshots, - parsed_args.snapshot) + share_client.share_snapshots, parsed_args.snapshot + ) export_locations = share_client.share_snapshot_export_locations.list( - snapshot=snapshot_obj) + snapshot=snapshot_obj + ) columns = ["ID", "Path"] return ( columns, - (utils.get_item_properties(s, columns) for s in export_locations)) + (utils.get_item_properties(s, columns) for s in export_locations), + ) class ShareSnapshotShowExportLocation(command.ShowOne): """Show export location of the share snapshot""" - _description = _( - "Show export location of the share snapshot") + _description = _("Show export location of the share snapshot") def get_parser(self, prog_name): - parser = super(ShareSnapshotShowExportLocation, self).get_parser( - prog_name) + parser = super().get_parser(prog_name) parser.add_argument( "snapshot", metavar="", - help=_("Name or ID of the share snapshot.") + help=_("Name or ID of the share snapshot."), ) parser.add_argument( "export_location", metavar="", - help=_("ID of the share snapshot export location.") + help=_("ID of the share snapshot export location."), ) return parser @@ -875,11 +937,11 @@ def take_action(self, parsed_args): share_client = self.app.client_manager.share snapshot_obj = utils.find_resource( - share_client.share_snapshots, - parsed_args.snapshot) + share_client.share_snapshots, parsed_args.snapshot + ) export_location = share_client.share_snapshot_export_locations.get( - export_location=parsed_args.export_location, - snapshot=snapshot_obj) + export_location=parsed_args.export_location, snapshot=snapshot_obj + ) return self.dict2columns(export_location._info) diff --git a/manilaclient/osc/v2/share_transfers.py b/manilaclient/osc/v2/share_transfers.py index 912a4b6a..a6aa059b 100644 --- a/manilaclient/osc/v2/share_transfers.py +++ b/manilaclient/osc/v2/share_transfers.py @@ -32,7 +32,7 @@ 'source_project_id', 'destination_project_id', 'accepted', - 'expires_at' + 'expires_at', ] TRANSFER_SUMMARY_ATTRIBUTES = [ @@ -45,27 +45,28 @@ class CreateShareTransfer(command.ShowOne): """Create a new share transfer.""" + _description = _("Create a new share transfer") def get_parser(self, prog_name): - parser = super(CreateShareTransfer, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( - 'share', - metavar='', - help='Name or ID of share to transfer.') + 'share', metavar='', help='Name or ID of share to transfer.' + ) parser.add_argument( '--name', metavar='', default=None, - help='Transfer name. Default=None.') + help='Transfer name. Default=None.', + ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share - share = osc_utils.find_resource(share_client.shares, - parsed_args.share) + share = osc_utils.find_resource(share_client.shares, parsed_args.share) transfer = share_client.transfers.create( - share.id, name=parsed_args.name) + share.id, name=parsed_args.name + ) transfer._info.pop('links', None) @@ -74,15 +75,17 @@ def take_action(self, parsed_args): class DeleteShareTransfer(command.Command): """Remove one or more transfers.""" + _description = _("Remove one or more transfers") def get_parser(self, prog_name): - parser = super(DeleteShareTransfer, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'transfer', metavar='', nargs='+', - help='Name(s) or ID(s) of the transfer(s).') + help='Name(s) or ID(s) of the transfer(s).', + ) return parser def take_action(self, parsed_args): @@ -92,86 +95,107 @@ def take_action(self, parsed_args): for transfer in parsed_args.transfer: try: transfer_obj = apiutils.find_resource( - share_client.transfers, - transfer) + share_client.transfers, transfer + ) share_client.transfers.delete(transfer_obj.id) except Exception as e: failure_count += 1 - LOG.error(_( - "Failed to delete %(transfer)s: %(e)s"), - {'transfer': transfer, 'e': e}) + LOG.error( + _("Failed to delete %(transfer)s: %(e)s"), + {'transfer': transfer, 'e': e}, + ) if failure_count > 0: - raise exceptions.CommandError(_( - "Unable to delete some or all of the specified transfers.")) + raise exceptions.CommandError( + _("Unable to delete some or all of the specified transfers.") + ) class ListShareTransfer(command.Lister): """Lists all transfers.""" + _description = _("Lists all transfers") def get_parser(self, prog_name): - parser = super(ListShareTransfer, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( '--all-projects', action='store_true', - help=_("Shows details for all tenants. (Admin only).") + help=_("Shows details for all tenants. (Admin only)."), ) parser.add_argument( '--name', metavar='', default=None, - help='Filter share transfers by name. Default=None.') + help='Filter share transfers by name. Default=None.', + ) parser.add_argument( '--id', metavar='', default=None, - help='Filter share transfers by ID. Default=None.') + help='Filter share transfers by ID. Default=None.', + ) parser.add_argument( - '--resource-type', '--resource_type', + '--resource-type', + '--resource_type', metavar='', default=None, help='Filter share transfers by resource type, ' - 'which can be share. Default=None.') + 'which can be share. Default=None.', + ) parser.add_argument( - '--resource-id', '--resource_id', + '--resource-id', + '--resource_id', metavar='', default=None, - help='Filter share transfers by resource ID. Default=None.') + help='Filter share transfers by resource ID. Default=None.', + ) parser.add_argument( - '--source-project-id', '--source_project_id', + '--source-project-id', + '--source_project_id', metavar='', default=None, help='Filter share transfers by ID of the Project that ' - 'initiated the transfer. Default=None.') + 'initiated the transfer. Default=None.', + ) parser.add_argument( '--limit', metavar='', type=int, default=None, help='Maximum number of transfer records to ' - 'return. (Default=None)') + 'return. (Default=None)', + ) parser.add_argument( '--offset', metavar="", default=None, - help='Start position of transfer records listing.') + help='Start position of transfer records listing.', + ) parser.add_argument( - '--sort-key', '--sort_key', + '--sort-key', + '--sort_key', metavar='', type=str, default=None, - help='Key to be sorted, available keys are %(keys)s. ' - 'Default=None.' - % {'keys': constants.SHARE_TRANSFER_SORT_KEY_VALUES}) + help=( + f'Key to be sorted, available keys are ' + f'{constants.SHARE_TRANSFER_SORT_KEY_VALUES}. ' + f'Default=None.' + ), + ) parser.add_argument( - '--sort-dir', '--sort_dir', + '--sort-dir', + '--sort_dir', metavar='', type=str, default=None, - help='Sort direction, available values are %(values)s. ' - 'OPTIONAL: Default=None.' % { - 'values': constants.SORT_DIR_VALUES}) + help=( + f'Sort direction, available values are ' + f'{constants.SORT_DIR_VALUES}. ' + f'OPTIONAL: Default=None.' + ), + ) parser.add_argument( '--detailed', dest='detailed', @@ -180,23 +204,25 @@ def get_parser(self, prog_name): type=int, const=1, default=0, - help="Show detailed information about filtered share transfers.") + help="Show detailed information about filtered share transfers.", + ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share - columns = [ - 'ID', - 'Name', - 'Resource Type', - 'Resource Id' - ] + columns = ['ID', 'Name', 'Resource Type', 'Resource Id'] if parsed_args.detailed: - columns.extend(['Created At', 'Source Project Id', - 'Destination Project Id', 'Accepted', - 'Expires At']) + columns.extend( + [ + 'Created At', + 'Source Project Id', + 'Destination Project Id', + 'Accepted', + 'Expires At', + ] + ) search_opts = { 'all_tenants': parsed_args.all_projects, @@ -210,50 +236,62 @@ def take_action(self, parsed_args): } transfers = share_client.transfers.list( - detailed=parsed_args.detailed, search_opts=search_opts, - sort_key=parsed_args.sort_key, sort_dir=parsed_args.sort_dir) + detailed=parsed_args.detailed, + search_opts=search_opts, + sort_key=parsed_args.sort_key, + sort_dir=parsed_args.sort_dir, + ) - return (columns, (osc_utils.get_item_properties - (m, columns) for m in transfers)) + return ( + columns, + (osc_utils.get_item_properties(m, columns) for m in transfers), + ) class ShowShareTransfer(command.ShowOne): """Show details about a share transfer.""" + _description = _("Show details about a share transfer") def get_parser(self, prog_name): - parser = super(ShowShareTransfer, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'transfer', metavar='', - help=_('Name or ID of transfer to show.')) + help=_('Name or ID of transfer to show.'), + ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share transfer = apiutils.find_resource( - share_client.transfers, - parsed_args.transfer) + share_client.transfers, parsed_args.transfer + ) - return (TRANSFER_DETAIL_ATTRIBUTES, osc_utils.get_dict_properties( - transfer._info, TRANSFER_DETAIL_ATTRIBUTES)) + return ( + TRANSFER_DETAIL_ATTRIBUTES, + osc_utils.get_dict_properties( + transfer._info, TRANSFER_DETAIL_ATTRIBUTES + ), + ) class AcceptShareTransfer(command.Command): """Accepts a share transfer.""" + _description = _("Accepts a share transfer") def get_parser(self, prog_name): - parser = super(AcceptShareTransfer, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( - 'transfer', - metavar='', - help='ID of transfer to accept.') + 'transfer', metavar='', help='ID of transfer to accept.' + ) parser.add_argument( 'auth_key', metavar='', - help='Authentication key of transfer to accept.') + help='Authentication key of transfer to accept.', + ) parser.add_argument( '--clear-rules', '--clear_rules', @@ -261,12 +299,15 @@ def get_parser(self, prog_name): action='store_true', default=False, help="Whether manila should clean up the access rules after the " - "transfer is complete. (Default=False)") + "transfer is complete. (Default=False)", + ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share share_client.transfers.accept( - parsed_args.transfer, parsed_args.auth_key, - clear_access_rules=parsed_args.clear_rules) + parsed_args.transfer, + parsed_args.auth_key, + clear_access_rules=parsed_args.clear_rules, + ) diff --git a/manilaclient/osc/v2/share_type_access.py b/manilaclient/osc/v2/share_type_access.py index b22ae13e..e93e6108 100644 --- a/manilaclient/osc/v2/share_type_access.py +++ b/manilaclient/osc/v2/share_type_access.py @@ -20,19 +20,20 @@ class ShareTypeAccessAllow(command.Command): """Add access for share type.""" + _description = _("Add access for share type") def get_parser(self, prog_name): - parser = super(ShareTypeAccessAllow, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'share_type', metavar="", - help=_("Share type name or ID to add access to") + help=_("Share type name or ID to add access to"), ) parser.add_argument( 'project_id', metavar="", - help=_("Project ID to add share type access for") + help=_("Project ID to add share type access for"), ) return parser @@ -40,28 +41,31 @@ def take_action(self, parsed_args): share_client = self.app.client_manager.share share_type = apiutils.find_resource( - share_client.share_types, parsed_args.share_type) + share_client.share_types, parsed_args.share_type + ) try: share_client.share_type_access.add_project_access( - share_type, - parsed_args.project_id) + share_type, parsed_args.project_id + ) except Exception as e: raise exceptions.CommandError( - "Failed to add access to share type : %s" % e) + f"Failed to add access to share type : {e}" + ) class ListShareTypeAccess(command.Lister): """Get access list for share type.""" + _description = _("Get access list for share type") def get_parser(self, prog_name): - parser = super(ListShareTypeAccess, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'share_type', metavar="", - help=_("Share type name or ID to get access list for") + help=_("Share type name or ID to get access list for"), ) return parser @@ -69,11 +73,13 @@ def take_action(self, parsed_args): share_client = self.app.client_manager.share share_type = apiutils.find_resource( - share_client.share_types, parsed_args.share_type) + share_client.share_types, parsed_args.share_type + ) if share_type._info.get('share_type_access:is_public'): raise exceptions.CommandError( - 'Forbidden to get access list for public share type.') + 'Forbidden to get access list for public share type.' + ) data = share_client.share_type_access.list(share_type) @@ -85,19 +91,20 @@ def take_action(self, parsed_args): class ShareTypeAccessDeny(command.Command): """Delete access from share type.""" + _description = _("Delete access from share type") def get_parser(self, prog_name): - parser = super(ShareTypeAccessDeny, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'share_type', metavar="", - help=_("Share type name or ID to delete access from") + help=_("Share type name or ID to delete access from"), ) parser.add_argument( 'project_id', metavar="", - help=_("Project ID to delete share type access for") + help=_("Project ID to delete share type access for"), ) return parser @@ -105,13 +112,15 @@ def take_action(self, parsed_args): share_client = self.app.client_manager.share share_type = apiutils.find_resource( - share_client.share_types, parsed_args.share_type) + share_client.share_types, parsed_args.share_type + ) try: share_client.share_type_access.remove_project_access( - share_type, - parsed_args.project_id) + share_type, parsed_args.project_id + ) except Exception as e: raise exceptions.CommandError( - "Failed to remove access from share type : %s" % e) + f"Failed to remove access from share type : {e}" + ) diff --git a/manilaclient/osc/v2/share_types.py b/manilaclient/osc/v2/share_types.py index daeacd41..d6ba8fbd 100644 --- a/manilaclient/osc/v2/share_types.py +++ b/manilaclient/osc/v2/share_types.py @@ -32,7 +32,7 @@ 'is_default', 'required_extra_specs', 'optional_extra_specs', - 'description' + 'description', ] @@ -53,9 +53,11 @@ def format_share_type(share_type, formatter='table'): { 'visibility': visibility, 'required_extra_specs': utils.format_properties( - share_type.required_extra_specs), + share_type.required_extra_specs + ), 'optional_extra_specs': utils.format_properties( - optional_extra_specs), + optional_extra_specs + ), } ) else: @@ -72,60 +74,69 @@ def format_share_type(share_type, formatter='table'): class CreateShareType(command.ShowOne): """Create new share type.""" - _description = _( - "Create new share type") + + _description = _("Create new share type") def get_parser(self, prog_name): - parser = super(CreateShareType, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( - 'name', - metavar="", - default=None, - help=_('Share type name') + 'name', metavar="", default=None, help=_('Share type name') ) parser.add_argument( 'spec_driver_handles_share_servers', metavar="", default=None, - help=_("Required extra specification. " - "Valid values are 'true' and 'false'") + help=_( + "Required extra specification. " + "Valid values are 'true' and 'false'" + ), ) parser.add_argument( "--description", metavar="", default=None, - help=_("Share type description. " - "Available only for microversion >= 2.41."), + help=_( + "Share type description. " + "Available only for microversion >= 2.41." + ), ) parser.add_argument( "--snapshot-support", metavar="", default=None, - help=_("Boolean extra spec used for filtering of back ends " - "by their capability to create share snapshots."), + help=_( + "Boolean extra spec used for filtering of back ends " + "by their capability to create share snapshots." + ), ) parser.add_argument( "--create-share-from-snapshot-support", metavar="", default=None, - help=_("Boolean extra spec used for filtering of back ends " - "by their capability to create shares from snapshots."), + help=_( + "Boolean extra spec used for filtering of back ends " + "by their capability to create shares from snapshots." + ), ) parser.add_argument( "--revert-to-snapshot-support", metavar="", default=False, - help=_("Boolean extra spec used for filtering of back ends " - "by their capability to revert shares to snapshots. " - "(Default is False)."), + help=_( + "Boolean extra spec used for filtering of back ends " + "by their capability to revert shares to snapshots. " + "(Default is False)." + ), ) parser.add_argument( "--mount-snapshot-support", metavar="", default=False, - help=_("Boolean extra spec used for filtering of back ends " - "by their capability to mount share snapshots. " - "(Default is False)."), + help=_( + "Boolean extra spec used for filtering of back ends " + "by their capability to mount share snapshots. " + "(Default is False)." + ), ) parser.add_argument( "--extra-specs", @@ -133,87 +144,99 @@ def get_parser(self, prog_name): nargs='*', metavar='', default=None, - help=_("Extra specs key and value of share type that will be" - " used for share type creation. OPTIONAL: Default=None." - " example --extra-specs thin_provisioning=' True', " - "replication_type=readable."), + help=_( + "Extra specs key and value of share type that will be" + " used for share type creation. OPTIONAL: Default=None." + " example --extra-specs thin_provisioning=' True', " + "replication_type=readable." + ), ) parser.add_argument( '--public', metavar="", default=True, - help=_('Make type accessible to the public (default true).') + help=_('Make type accessible to the public (default true).'), ) return parser def take_action(self, parsed_args): share_client = self.app.client_manager.share - kwargs = { - 'name': parsed_args.name - } + kwargs = {'name': parsed_args.name} try: kwargs['spec_driver_handles_share_servers'] = ( strutils.bool_from_string( - parsed_args.spec_driver_handles_share_servers, - strict=True)) + parsed_args.spec_driver_handles_share_servers, strict=True + ) + ) except ValueError as e: - msg = ("Argument spec_driver_handles_share_servers " - "argument is not valid: %s" % str(e)) + msg = ( + "Argument spec_driver_handles_share_servers " + f"argument is not valid: {str(e)}" + ) raise exceptions.CommandError(msg) if parsed_args.description: if share_client.api_version.matches( - api_versions.APIVersion("2.41"), - api_versions.APIVersion()): + api_versions.APIVersion("2.41"), api_versions.APIVersion() + ): kwargs['description'] = parsed_args.description else: raise exceptions.CommandError( "Adding description to share type " - "is only available with API microversion >= 2.41") + "is only available with API microversion >= 2.41" + ) if parsed_args.public: kwargs['is_public'] = strutils.bool_from_string( - parsed_args.public, default=True) + parsed_args.public, default=True + ) extra_specs = {} if parsed_args.extra_specs: for item in parsed_args.extra_specs: (key, value) = item.split('=', 1) if key == 'driver_handles_share_servers': - msg = ("'driver_handles_share_servers' " - "is already set via positional argument.") + msg = ( + "'driver_handles_share_servers' " + "is already set via positional argument." + ) raise exceptions.CommandError(msg) else: extra_specs = utils.extract_extra_specs( - extra_specs, [item]) + extra_specs, [item] + ) for key in constants.BOOL_SPECS: value = getattr(parsed_args, key) if value: extra_specs = utils.extract_extra_specs( - extra_specs, [key + '=' + value]) + extra_specs, [key + '=' + value] + ) kwargs['extra_specs'] = extra_specs share_type = share_client.share_types.create(**kwargs) formatted_type = format_share_type(share_type, parsed_args.formatter) - return (ATTRIBUTES, oscutils.get_dict_properties( - formatted_type._info, ATTRIBUTES)) + return ( + ATTRIBUTES, + oscutils.get_dict_properties(formatted_type._info, ATTRIBUTES), + ) class DeleteShareType(command.Command): """Delete a share type.""" + _description = _("Delete a share type") def get_parser(self, prog_name): - parser = super(DeleteShareType, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'share_types', metavar="", nargs="+", - help=_("Name or ID of the share type(s) to delete") + help=_("Name or ID of the share type(s) to delete"), ) return parser @@ -224,34 +247,39 @@ def take_action(self, parsed_args): for share_type in parsed_args.share_types: try: share_type_obj = apiutils.find_resource( - share_client.share_types, - share_type) + share_client.share_types, share_type + ) share_client.share_types.delete(share_type_obj) except Exception as e: result += 1 - LOG.error(_( - "Failed to delete share type with " - "name or ID '%(share_type)s': %(e)s"), - {'share_type': share_type, 'e': e}) + LOG.error( + _( + "Failed to delete share type with " + "name or ID '%(share_type)s': %(e)s" + ), + {'share_type': share_type, 'e': e}, + ) if result > 0: total = len(parsed_args.share_types) - msg = (_("%(result)s of %(total)s share types failed " - "to delete.") % {'result': result, 'total': total}) + msg = _( + "%(result)s of %(total)s share types failed to delete." + ) % {'result': result, 'total': total} raise exceptions.CommandError(msg) class SetShareType(command.Command): """Set share type properties.""" + _description = _("Set share type properties") def get_parser(self, prog_name): - parser = super(SetShareType, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'share_type', metavar="", - help=_("Name or ID of the share type to modify") + help=_("Name or ID of the share type to modify"), ) parser.add_argument( "--extra-specs", @@ -259,33 +287,41 @@ def get_parser(self, prog_name): nargs='*', metavar='', default=None, - help=_("Extra specs key and value of share type that will be" - " used for share type creation. OPTIONAL: Default=None." - " example --extra-specs thin_provisioning=' True', " - "replication_type=readable."), + help=_( + "Extra specs key and value of share type that will be" + " used for share type creation. OPTIONAL: Default=None." + " example --extra-specs thin_provisioning=' True', " + "replication_type=readable." + ), ) parser.add_argument( '--public', metavar="", default=None, - help=_('New visibility of the share type. If set to True, ' - 'share type will be available to all projects ' - 'in the cloud. ' - 'Available only for microversion >= 2.50') + help=_( + 'New visibility of the share type. If set to True, ' + 'share type will be available to all projects ' + 'in the cloud. ' + 'Available only for microversion >= 2.50' + ), ) parser.add_argument( "--description", metavar="", default=None, - help=_("New description of share type. " - "Available only for microversion >= 2.50"), + help=_( + "New description of share type. " + "Available only for microversion >= 2.50" + ), ) parser.add_argument( '--name', metavar="", default=None, - help=_('New name of share type. ' - 'Available only for microversion >= 2.50') + help=_( + 'New name of share type. ' + 'Available only for microversion >= 2.50' + ), ) return parser @@ -293,10 +329,12 @@ def take_action(self, parsed_args): share_client = self.app.client_manager.share share_type = apiutils.find_resource( - share_client.share_types, parsed_args.share_type) + share_client.share_types, parsed_args.share_type + ) - can_update = ( - share_client.api_version >= api_versions.APIVersion('2.50')) + can_update = share_client.api_version >= api_versions.APIVersion( + '2.50' + ) kwargs = {} if parsed_args.name is not None: @@ -305,46 +343,52 @@ def take_action(self, parsed_args): else: raise exceptions.CommandError( "Setting (new) name to share type " - "is only available with API microversion >= 2.50") + "is only available with API microversion >= 2.50" + ) if parsed_args.description is not None: if can_update: kwargs['description'] = parsed_args.description else: raise exceptions.CommandError( "Setting (new) description to share type " - "is only available with API microversion >= 2.50") + "is only available with API microversion >= 2.50" + ) if parsed_args.public is not None: if can_update: kwargs['is_public'] = strutils.bool_from_string( - parsed_args.public, default=True) + parsed_args.public, default=True + ) else: raise exceptions.CommandError( "Setting visibility to share type " - "is only available with API microversion >= 2.50") + "is only available with API microversion >= 2.50" + ) if kwargs: share_type.update(**kwargs) if parsed_args.extra_specs: extra_specs = utils.extract_extra_specs( - extra_specs={}, - specs_to_add=parsed_args.extra_specs) + extra_specs={}, specs_to_add=parsed_args.extra_specs + ) try: share_type.set_keys(extra_specs) except Exception as e: raise exceptions.CommandError( - "Failed to set share type key: %s" % e) + f"Failed to set share type key: {e}" + ) class UnsetShareType(command.Command): """Unset share type extra specs.""" + _description = _("Unset share type extra specs") def get_parser(self, prog_name): - parser = super(UnsetShareType, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'share_type', metavar="", - help=_("Name or ID of the share type to modify") + help=_("Name or ID of the share type to modify"), ) parser.add_argument( 'extra_specs', @@ -358,28 +402,33 @@ def take_action(self, parsed_args): share_client = self.app.client_manager.share share_type = apiutils.find_resource( - share_client.share_types, parsed_args.share_type) + share_client.share_types, parsed_args.share_type + ) if parsed_args.extra_specs: try: share_type.unset_keys(parsed_args.extra_specs) except Exception as e: raise exceptions.CommandError( - "Failed to remove share type extra spec: %s" % e) + f"Failed to remove share type extra spec: {e}" + ) class ListShareType(command.Lister): """List Share Types.""" + _description = _("List share types") def get_parser(self, prog_name): - parser = super(ListShareType, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( '--all', action='store_true', default=False, - help=_('Display all share types whatever public or private. ' - 'Default=False. (Admin only)'), + help=_( + 'Display all share types whatever public or private. ' + 'Default=False. (Admin only)' + ), ) parser.add_argument( '--extra-specs', @@ -387,9 +436,11 @@ def get_parser(self, prog_name): nargs='*', metavar='', default=None, - help=_('Filter share types with extra specs (key=value). ' - 'Available only for API microversion >= 2.43. ' - 'OPTIONAL: Default=None.'), + help=_( + 'Filter share types with extra specs (key=value). ' + 'Available only for API microversion >= 2.43. ' + 'OPTIONAL: Default=None.' + ), ) return parser @@ -401,25 +452,29 @@ def take_action(self, parsed_args): if share_client.api_version < api_versions.APIVersion("2.43"): raise exceptions.CommandError( "Filtering by 'extra_specs' is available only with " - "API microversion '2.43' and above.") + "API microversion '2.43' and above." + ) search_opts = { 'extra_specs': utils.extract_extra_specs( - extra_specs={}, - specs_to_add=parsed_args.extra_specs) + extra_specs={}, specs_to_add=parsed_args.extra_specs + ) } share_types = share_client.share_types.list( - search_opts=search_opts, - show_all=parsed_args.all) + search_opts=search_opts, show_all=parsed_args.all + ) formatted_types = [] for share_type in share_types: - formatted_types.append(format_share_type(share_type, - parsed_args.formatter)) + formatted_types.append( + format_share_type(share_type, parsed_args.formatter) + ) - values = (oscutils.get_dict_properties( - s._info, ATTRIBUTES) for s in formatted_types) + values = ( + oscutils.get_dict_properties(s._info, ATTRIBUTES) + for s in formatted_types + ) columns = utils.format_column_headers(ATTRIBUTES) @@ -428,14 +483,15 @@ def take_action(self, parsed_args): class ShowShareType(command.ShowOne): """Show a share type.""" + _description = _("Display share type details") def get_parser(self, prog_name): - parser = super(ShowShareType, self).get_parser(prog_name) + parser = super().get_parser(prog_name) parser.add_argument( 'share_type', metavar="", - help=_("Share type to display (name or ID)") + help=_("Share type to display (name or ID)"), ) return parser @@ -443,10 +499,12 @@ def take_action(self, parsed_args): share_client = self.app.client_manager.share share_type = apiutils.find_resource( - share_client.share_types, - parsed_args.share_type) + share_client.share_types, parsed_args.share_type + ) formatted_type = format_share_type(share_type, parsed_args.formatter) - return (ATTRIBUTES, oscutils.get_dict_properties( - formatted_type._info, ATTRIBUTES)) + return ( + ATTRIBUTES, + oscutils.get_dict_properties(formatted_type._info, ATTRIBUTES), + ) diff --git a/manilaclient/shell.py b/manilaclient/shell.py deleted file mode 100644 index d379f736..00000000 --- a/manilaclient/shell.py +++ /dev/null @@ -1,783 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# Copyright 2014 Mirantis, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Command-line interface to the OpenStack Manila API. -""" - -import argparse -import csv -import glob -from importlib import util as importlib_util -import itertools -import logging -import os -import pkgutil -import sys - -from oslo_utils import importutils - -from manilaclient import api_versions -from manilaclient import client -from manilaclient.common import cliutils -from manilaclient.common import constants -from manilaclient import exceptions as exc -import manilaclient.extension -from manilaclient.v2 import shell as shell_v2 - -DEFAULT_OS_SHARE_API_VERSION = api_versions.MAX_VERSION -DEFAULT_MANILA_ENDPOINT_TYPE = 'publicURL' -DEFAULT_MAJOR_OS_SHARE_API_VERSION = "2" -V1_MAJOR_VERSION = '1' -V2_MAJOR_VERSION = '2' - -try: - osprofiler_profiler = importutils.try_import("osprofiler.profiler") -except Exception: - pass - - -logger = logging.getLogger(__name__) - - -class AllowOnlyOneAliasAtATimeAction(argparse.Action): - """Allows only one alias of argument to be used at a time.""" - - def __call__(self, parser, namespace, values, option_string=None): - # NOTE(vponomaryov): this method is redefinition of - # argparse.Action.__call__ interface - - if not hasattr(self, 'calls'): - self.calls = {} - - if self.dest not in self.calls: - self.calls[self.dest] = set() - - local_values = sorted(values) if isinstance(values, list) else values - self.calls[self.dest].add(str(local_values)) - - if len(self.calls[self.dest]) == 1: - setattr(namespace, self.dest, local_values) - else: - msg = "Only one alias is allowed at a time." - raise argparse.ArgumentError(self, msg) - - -class ManilaClientArgumentParser(argparse.ArgumentParser): - - def __init__(self, *args, **kwargs): - super(ManilaClientArgumentParser, self).__init__(*args, **kwargs) - # NOTE(vponomaryov): Register additional action to be used by arguments - # with multiple aliases. - self.register('action', 'single_alias', AllowOnlyOneAliasAtATimeAction) - - def error(self, message): - """error(message: string) - - Prints a usage message incorporating the message to stderr and - exits. - """ - self.print_usage(sys.stderr) - # FIXME(lzyeval): if changes occur in argparse.ArgParser._check_value - choose_from = ' (choose from' - progparts = self.prog.partition(' ') - self.exit(2, "error: %(errmsg)s\nTry '%(mainp)s help %(subp)s'" - " for more information.\n" % - {'errmsg': message.split(choose_from)[0], - 'mainp': progparts[0], - 'subp': progparts[2]}) - - def _get_option_tuples(self, option_string): - """Avoid ambiguity in argument abbreviation. - - Manilaclient uses aliases for command parameters and this method - is used for avoiding parameter ambiguity alert. - """ - option_tuples = super( - ManilaClientArgumentParser, self)._get_option_tuples(option_string) - if len(option_tuples) > 1: - opt_strings_list = [] - opts = [] - for opt in option_tuples: - if opt[0].option_strings not in opt_strings_list: - opt_strings_list.append(opt[0].option_strings) - opts.append(opt) - return opts - return option_tuples - - -class OpenStackManilaShell(object): - - def get_base_parser(self): - parser = ManilaClientArgumentParser( - prog='manila', - description=__doc__.strip(), - epilog='See "manila help COMMAND" ' - 'for help on a specific command.', - add_help=False, - formatter_class=OpenStackHelpFormatter, - ) - - # Global arguments - parser.add_argument('-h', '--help', - action='store_true', - help=argparse.SUPPRESS) - - parser.add_argument('--version', - action='version', - version=manilaclient.__version__) - - parser.add_argument('-d', '--debug', - action='store_true', - default=cliutils.env('manilaclient_DEBUG', - 'MANILACLIENT_DEBUG', - default=False), - help="Print debugging output.") - - parser.add_argument('--os-cache', - default=cliutils.env('OS_CACHE', default=False), - action='store_true', - help='Use the auth token cache. ' - 'Defaults to env[OS_CACHE].') - - parser.add_argument('--os-reset-cache', - default=False, - action='store_true', - help='Delete cached password and auth token.') - - parser.add_argument('--os-user-id', - metavar='', - default=cliutils.env('OS_USER_ID'), - help=('Defaults to env [OS_USER_ID].')) - parser.add_argument('--os_user_id', - help=argparse.SUPPRESS) - - parser.add_argument('--os-username', - metavar='', - default=cliutils.env('OS_USERNAME', - 'MANILA_USERNAME'), - help='Defaults to env[OS_USERNAME].') - parser.add_argument('--os_username', - help=argparse.SUPPRESS) - - parser.add_argument('--os-password', - metavar='', - default=cliutils.env('OS_PASSWORD', - 'MANILA_PASSWORD'), - help='Defaults to env[OS_PASSWORD].') - parser.add_argument('--os_password', - help=argparse.SUPPRESS) - - parser.add_argument('--os-tenant-name', - metavar='', - default=cliutils.env('OS_TENANT_NAME', - 'MANILA_PROJECT_ID'), - help='Defaults to env[OS_TENANT_NAME].') - parser.add_argument('--os_tenant_name', - help=argparse.SUPPRESS) - - parser.add_argument('--os-project-name', - metavar='', - default=cliutils.env('OS_PROJECT_NAME'), - help=('Another way to specify tenant name. ' - 'This option is mutually exclusive with ' - '--os-tenant-name. ' - 'Defaults to env[OS_PROJECT_NAME].')) - parser.add_argument('--os_project_name', - help=argparse.SUPPRESS) - - parser.add_argument('--os-tenant-id', - metavar='', - default=cliutils.env('OS_TENANT_ID', - 'MANILA_TENANT_ID'), - help='Defaults to env[OS_TENANT_ID].') - parser.add_argument('--os_tenant_id', - help=argparse.SUPPRESS) - - parser.add_argument('--os-project-id', - metavar='', - default=cliutils.env('OS_PROJECT_ID'), - help=('Another way to specify tenant ID. ' - 'This option is mutually exclusive with ' - '--os-tenant-id. ' - 'Defaults to env[OS_PROJECT_ID].')) - parser.add_argument('--os_project_id', - help=argparse.SUPPRESS) - - parser.add_argument('--os-user-domain-id', - metavar='', - default=cliutils.env('OS_USER_DOMAIN_ID'), - help=('OpenStack user domain ID. ' - 'Defaults to env[OS_USER_DOMAIN_ID].')) - parser.add_argument('--os_user_domain_id', - help=argparse.SUPPRESS) - - parser.add_argument('--os-user-domain-name', - metavar='', - default=cliutils.env('OS_USER_DOMAIN_NAME'), - help=('OpenStack user domain name. ' - 'Defaults to env[OS_USER_DOMAIN_NAME].')) - parser.add_argument('--os_user_domain_name', - help=argparse.SUPPRESS) - - parser.add_argument('--os-project-domain-id', - metavar='', - default=cliutils.env('OS_PROJECT_DOMAIN_ID'), - help='Defaults to env[OS_PROJECT_DOMAIN_ID].') - parser.add_argument('--os_project_domain_id', - help=argparse.SUPPRESS) - - parser.add_argument('--os-project-domain-name', - metavar='', - default=cliutils.env('OS_PROJECT_DOMAIN_NAME'), - help='Defaults to env[OS_PROJECT_DOMAIN_NAME].') - parser.add_argument('--os_project_domain_name', - help=argparse.SUPPRESS) - - parser.add_argument('--os-auth-url', - metavar='', - default=cliutils.env('OS_AUTH_URL', - 'MANILA_URL'), - help='Defaults to env[OS_AUTH_URL].') - parser.add_argument('--os_auth_url', - help=argparse.SUPPRESS) - - parser.add_argument('--os-region-name', - metavar='', - default=cliutils.env('OS_REGION_NAME', - 'MANILA_REGION_NAME'), - help='Defaults to env[OS_REGION_NAME].') - parser.add_argument('--os_region_name', - help=argparse.SUPPRESS) - - parser.add_argument('--os-token', - metavar='', - default=cliutils.env('OS_TOKEN'), - help='Defaults to env[OS_TOKEN].') - parser.add_argument('--os_token', - help=argparse.SUPPRESS) - - parser.add_argument('--bypass-url', - metavar='', - default=cliutils.env('OS_MANILA_BYPASS_URL', - 'MANILACLIENT_BYPASS_URL'), - help=("Use this API endpoint instead of the " - "Service Catalog. Defaults to " - "env[OS_MANILA_BYPASS_URL].")) - parser.add_argument('--bypass_url', - help=argparse.SUPPRESS) - - parser.add_argument('--service-type', - metavar='', - help='Defaults to compute for most actions.') - parser.add_argument('--service_type', - help=argparse.SUPPRESS) - - parser.add_argument('--service-name', - metavar='', - default=cliutils.env('OS_MANILA_SERVICE_NAME', - 'MANILA_SERVICE_NAME'), - help='Defaults to env[OS_MANILA_SERVICE_NAME].') - parser.add_argument('--service_name', - help=argparse.SUPPRESS) - - parser.add_argument('--share-service-name', - metavar='', - default=cliutils.env( - 'OS_MANILA_SHARE_SERVICE_NAME', - 'MANILA_share_service_name'), - help='Defaults to env' - '[OS_MANILA_SHARE_SERVICE_NAME].') - parser.add_argument('--share_service_name', - help=argparse.SUPPRESS) - - parser.add_argument('--endpoint-type', - metavar='', - default=cliutils.env( - 'OS_MANILA_ENDPOINT_TYPE', - 'MANILA_ENDPOINT_TYPE', - default=DEFAULT_MANILA_ENDPOINT_TYPE), - help='Defaults to env[OS_MANILA_ENDPOINT_TYPE] or ' - + DEFAULT_MANILA_ENDPOINT_TYPE + '.') - parser.add_argument('--endpoint_type', - help=argparse.SUPPRESS) - - parser.add_argument('--os-share-api-version', - metavar='', - default=cliutils.env( - 'OS_SHARE_API_VERSION', - default=DEFAULT_OS_SHARE_API_VERSION), - help='Accepts 1.x to override default ' - 'to env[OS_SHARE_API_VERSION].') - parser.add_argument('--os_share_api_version', - help=argparse.SUPPRESS) - - parser.add_argument('--os-cacert', - metavar='', - default=cliutils.env('OS_CACERT', default=None), - help='Specify a CA bundle file to use in ' - 'verifying a TLS (https) server certificate. ' - 'Defaults to env[OS_CACERT].') - - parser.add_argument('--insecure', - default=cliutils.env('manilaclient_INSECURE', - 'MANILACLIENT_INSECURE', - default=False), - action='store_true', - help=argparse.SUPPRESS) - - parser.add_argument('--retries', - metavar='', - type=int, - default=0, - help='Number of retries.') - - parser.add_argument('--os-cert', - metavar='', - default=cliutils.env('OS_CERT'), - help='Defaults to env[OS_CERT].') - parser.add_argument('--os_cert', - help=argparse.SUPPRESS) - - parser.add_argument('--os-key', - metavar='', - default=cliutils.env('OS_KEY'), - help='Defaults to env[OS_KEY].') - parser.add_argument('--os_key', - help=argparse.SUPPRESS) - - if osprofiler_profiler: - parser.add_argument('--profile', - metavar='HMAC_KEY', - default=cliutils.env('OS_PROFILE'), - help='HMAC key to use for encrypting ' - 'context data for performance profiling ' - 'of operation. This key needs to match the ' - 'one configured on the manila api server. ' - 'Without key the profiling will not be ' - 'triggered even if osprofiler is enabled ' - 'on server side. Defaults to ' - 'env[OS_PROFILE].') - - parser.set_defaults(func=self.do_help) - parser.set_defaults(command='') - - return parser - - def get_subcommand_parser(self, version): - parser = self.get_base_parser() - - self.subcommands = {} - subparsers = parser.add_subparsers(metavar='') - - try: - actions_module = { - V2_MAJOR_VERSION: shell_v2, - }[version] - except KeyError: - actions_module = shell_v2 - - self._find_actions(subparsers, actions_module) - self._find_actions(subparsers, self) - - for extension in self.extensions: - self._find_actions(subparsers, extension.module) - - self._add_bash_completion_subparser(subparsers) - - return parser - - def _discover_extensions(self, api_version): - extensions = [] - for name, module in itertools.chain( - self._discover_via_python_path(), - self._discover_via_contrib_path(api_version)): - - extension = manilaclient.extension.Extension(name, module) - extensions.append(extension) - - return extensions - - def _discover_via_python_path(self): - for (module_loader, name, ispkg) in pkgutil.iter_modules(): - if name.endswith('python_manilaclient_ext'): - if not hasattr(module_loader, 'load_module'): - # Python 2.6 compat: actually get an ImpImporter obj - module_loader = module_loader.find_module(name) - - module = module_loader.load_module(name) - yield name, module - - def _load_module(self, name, path): - module_spec = importlib_util.spec_from_file_location( - name, path - ) - module = importlib_util.module_from_spec(module_spec) - module_spec.loader.exec_module(module) - return module - - def _discover_via_contrib_path(self, api_version): - module_path = os.path.dirname(os.path.abspath(__file__)) - version_str = 'v' + api_version.get_major_version() - ext_path = os.path.join(module_path, version_str, 'contrib') - ext_glob = os.path.join(ext_path, "*.py") - - for ext_path in glob.iglob(ext_glob): - name = os.path.basename(ext_path)[:-3] - - if name == "__init__": - continue - - module = self._load_module(name, ext_path) - yield name, module - - def _add_bash_completion_subparser(self, subparsers): - subparser = subparsers.add_parser( - 'bash_completion', - add_help=False, - formatter_class=OpenStackHelpFormatter) - - self.subcommands['bash_completion'] = subparser - subparser.set_defaults(func=self.do_bash_completion) - - def _find_actions(self, subparsers, actions_module): - for attr in (a for a in dir(actions_module) if a.startswith('do_')): - # I prefer to be hypen-separated instead of underscores. - command = attr[3:].replace('_', '-') - callback = getattr(actions_module, attr) - desc = callback.__doc__ or '' - help = desc.strip() - arguments = getattr(callback, 'arguments', []) - - subparser = subparsers.add_parser( - command, - help=help, - description=desc, - add_help=False, - formatter_class=OpenStackHelpFormatter) - - subparser.add_argument('-h', '--help', - action='help', - help=argparse.SUPPRESS,) - - self.subcommands[command] = subparser - for (args, kwargs) in arguments: - subparser.add_argument(*args, **kwargs) - subparser.set_defaults(func=callback) - - def setup_debugging(self, debug): - if not debug: - return - - streamformat = "%(levelname)s (%(module)s:%(lineno)d) %(message)s" - logging.basicConfig(level=logging.DEBUG, format=streamformat) - logging.getLogger('requests.packages.urllib3.connectionpool' - ).setLevel(logging.WARNING) - logging.getLogger('keystoneauth1.session').setLevel(logging.WARNING) - - def _build_subcommands_and_extensions(self, - os_api_version, - argv, - options): - - self.extensions = self._discover_extensions(os_api_version) - self._run_extension_hooks('__pre_parse_args__') - - self.parser = self.get_subcommand_parser( - os_api_version.get_major_version()) - - if argv and len(argv) > 1 and '--help' in argv: - argv = [x for x in argv if x != '--help'] - if argv[0] in self.subcommands: - self.subcommands[argv[0]].print_help() - return False - - if options.help or not argv: - self.parser.print_help() - return False - - args = self.parser.parse_args(argv) - self._run_extension_hooks('__post_parse_args__', args) - - return args - - def main(self, argv): - # Parse args once to find version and debug settings - parser = self.get_base_parser() - (options, args) = parser.parse_known_args(argv) - self.setup_debugging(options.debug) - - os_api_version = self._validate_input_api_version(options) - - # build available subcommands based on version - args = self._build_subcommands_and_extensions(os_api_version, - argv, - options) - if not args: - return 0 - - # Short-circuit and deal with help right away. - if args.func == self.do_help: - self.do_help(args) - return 0 - elif args.func == self.do_bash_completion: - self.do_bash_completion(args) - return 0 - - if not options.os_share_api_version: - api_version = api_versions.get_api_version( - DEFAULT_MAJOR_OS_SHARE_API_VERSION) - else: - api_version = api_versions.get_api_version( - options.os_share_api_version) - - major_version_string = str(api_version.ver_major) - os_service_type = args.service_type - if not os_service_type: - os_service_type = constants.SERVICE_TYPES[major_version_string] - - os_endpoint_type = args.endpoint_type or DEFAULT_MANILA_ENDPOINT_TYPE - cert = args.os_cert or None - if cert and args.os_key: - cert = cert, args.os_key - - client_args = dict( - username=args.os_username, - password=args.os_password, - project_name=args.os_project_name or args.os_tenant_name, - auth_url=args.os_auth_url, - insecure=args.insecure, - region_name=args.os_region_name, - tenant_id=args.os_project_id or args.os_tenant_id, - endpoint_type=os_endpoint_type, - extensions=self.extensions, - service_type=os_service_type, - service_name=args.service_name, - retries=options.retries, - http_log_debug=args.debug, - cacert=args.os_cacert, - use_keyring=args.os_cache, - force_new_token=args.os_reset_cache, - user_id=args.os_user_id, - user_domain_id=args.os_user_domain_id, - user_domain_name=args.os_user_domain_name, - project_domain_id=args.os_project_domain_id, - project_domain_name=args.os_project_domain_name, - cert=cert, - input_auth_token=args.os_token, - service_catalog_url=args.bypass_url, - ) - - # Handle deprecated parameters - if args.share_service_name: - client_args['share_service_name'] = args.share_service_name - - self._validate_required_options( - args.os_tenant_name, args.os_tenant_id, - args.os_project_name, args.os_project_id, - args.os_token, args.bypass_url, - client_args['auth_url']) - - # This client is needed to discover the server api version. - temp_client = client.Client(manilaclient.API_MAX_VERSION, - **client_args) - - self.cs, discovered_version = self._discover_client(temp_client, - os_api_version, - os_endpoint_type, - os_service_type, - client_args) - - args = self._build_subcommands_and_extensions(discovered_version, - argv, - options) - - profile = osprofiler_profiler and options.profile - if profile: - osprofiler_profiler.init(options.profile) - - try: - decoder_path = ( - '%s/%s' % (os.path.dirname(os.path.abspath(__file__)), - 'osc/v2/data/manila.csv') - ) - with open(decoder_path) as f: - decoder_data = { - r['manila command']: r['openstack command'] - for r in csv.DictReader(f, skipinitialspace=True) - } - except Exception: - # this is fine - decoder_data = {} - - deprecation_message = ("manila CLI is deprecated and will be removed " - "in the future. Use openstack CLI instead.") - cmd = args.func.__name__.lstrip('do_').replace("_", "-") - if decoder_data and cmd in decoder_data: - deprecation_message = " ".join([ - deprecation_message, - "The equivalent command is \" openstack", - f"{decoder_data[cmd]}", - "\"" - ]) - - print(deprecation_message, file=sys.stderr) - - args.func(self.cs, args) - - if profile: - trace_id = osprofiler_profiler.get().get_base_id() - print("Profiling trace ID: %s" % trace_id) - print("To display trace use next command:\n" - "osprofiler trace show --html %s " % trace_id) - - def _discover_client(self, - current_client, - os_api_version, - os_endpoint_type, - os_service_type, - client_args): - - if os_api_version == manilaclient.API_DEPRECATED_VERSION: - discovered_version = manilaclient.API_DEPRECATED_VERSION - os_service_type = constants.V1_SERVICE_TYPE - else: - discovered_version = api_versions.discover_version( - current_client, - os_api_version - ) - - if not os_endpoint_type: - os_endpoint_type = DEFAULT_MANILA_ENDPOINT_TYPE - - if not os_service_type: - os_service_type = self._discover_service_type(discovered_version) - - if (discovered_version != manilaclient.API_MAX_VERSION or - os_service_type != constants.V1_SERVICE_TYPE or - os_endpoint_type != DEFAULT_MANILA_ENDPOINT_TYPE): - client_args['version'] = discovered_version - client_args['service_type'] = os_service_type - client_args['endpoint_type'] = os_endpoint_type - - return (client.Client(discovered_version, **client_args), - discovered_version) - else: - return current_client, discovered_version - - def _discover_service_type(self, discovered_version): - major_version = discovered_version.get_major_version() - service_type = constants.SERVICE_TYPES[major_version] - return service_type - - def _validate_input_api_version(self, options): - if not options.os_share_api_version: - api_version = manilaclient.API_MAX_VERSION - else: - api_version = api_versions.get_api_version( - options.os_share_api_version) - return api_version - - def _validate_required_options(self, tenant_name, tenant_id, - project_name, project_id, - token, service_catalog_url, auth_url): - if token and not service_catalog_url: - raise exc.CommandError( - "bypass_url missing: When specifying a token the bypass_url " - "must be set via --bypass-url or env[OS_MANILA_BYPASS_URL]") - if service_catalog_url and not token: - raise exc.CommandError( - "Token missing: When specifying a bypass_url a token must be " - "set via --os-token or env[OS_TOKEN]") - if token and service_catalog_url: - return - - if not (tenant_name or tenant_id or project_name or project_id): - raise exc.CommandError( - "You must provide a tenant_name, tenant_id, " - "project_id or project_name (with " - "project_domain_name or project_domain_id) via " - "--os-tenant-name or env[OS_TENANT_NAME], " - "--os-tenant-id or env[OS_TENANT_ID], " - "--os-project-id or env[OS_PROJECT_ID], " - "--os-project-name or env[OS_PROJECT_NAME], " - "--os-project-domain-id or env[OS_PROJECT_DOMAIN_ID] and " - "--os-project-domain-name or env[OS_PROJECT_DOMAIN_NAME]." - ) - - if not auth_url: - raise exc.CommandError( - "You must provide an auth url " - "via either --os-auth-url or env[OS_AUTH_URL]") - - def _run_extension_hooks(self, hook_type, *args, **kwargs): - """Run hooks for all registered extensions.""" - for extension in self.extensions: - extension.run_hooks(hook_type, *args, **kwargs) - - def do_bash_completion(self, args): - """Print arguments for bash_completion. - - Prints all of the commands and options to stdout so that the - manila.bash_completion script doesn't have to hard code them. - """ - commands = set() - options = set() - for sc_str, sc in list(self.subcommands.items()): - commands.add(sc_str) - for option in sc._optionals._option_string_actions: - options.add(option) - - commands.remove('bash-completion') - commands.remove('bash_completion') - print(' '.join(commands | options)) - - @cliutils.arg('command', metavar='', nargs='?', - help='Display help for ') - def do_help(self, args): - """Display help about this program or one of its subcommands.""" - if args.command: - if args.command in self.subcommands: - self.subcommands[args.command].print_help() - else: - raise exc.CommandError("'%s' is not a valid subcommand" % - args.command) - else: - self.parser.print_help() - - -# I'm picky about my shell help. -class OpenStackHelpFormatter(argparse.HelpFormatter): - def start_section(self, heading): - # Title-case the headings - heading = '%s%s' % (heading[0].upper(), heading[1:]) - super(OpenStackHelpFormatter, self).start_section(heading) - - -def main(): - try: - OpenStackManilaShell().main(sys.argv[1:]) - except KeyboardInterrupt: - print("... terminating manila client", file=sys.stderr) - sys.exit(130) - except Exception as e: - logger.debug(e, exc_info=1) - print("ERROR: %s" % str(e), file=sys.stderr) - sys.exit(1) - - -if __name__ == "__main__": - main() diff --git a/manilaclient/tests/functional/base.py b/manilaclient/tests/functional/base.py deleted file mode 100644 index 97709731..00000000 --- a/manilaclient/tests/functional/base.py +++ /dev/null @@ -1,538 +0,0 @@ -# Copyright 2014 Mirantis Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import re -import traceback - -from oslo_log import log -from tempest.lib.cli import base -from tempest.lib.common.utils import data_utils -from tempest.lib import exceptions as lib_exc - -from manilaclient.common import constants -from manilaclient import config -from manilaclient.tests.functional import client -from manilaclient.tests.functional import utils - -CONF = config.CONF -LOG = log.getLogger(__name__) - - -class handle_cleanup_exceptions(object): - """Handle exceptions raised with cleanup operations. - - Always suppress errors when lib_exc.NotFound or lib_exc.Forbidden - are raised. - Suppress all other exceptions only in case config opt - 'suppress_errors_in_cleanup' is True. - """ - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_value, exc_traceback): - if isinstance(exc_value, (lib_exc.NotFound, lib_exc.Forbidden)): - return True - elif CONF.suppress_errors_in_cleanup: - LOG.error("Suppressed cleanup error: \n%s", traceback.format_exc()) - return True - return False # Don't suppress cleanup errors - - -class BaseTestCase(base.ClientTestBase): - - # Will be cleaned up after test suite run - class_resources = [] - - # Will be cleaned up after single test run - method_resources = [] - - def setUp(self): - super(BaseTestCase, self).setUp() - self.addCleanup(self.clear_resources) - - @classmethod - def tearDownClass(cls): - super(BaseTestCase, cls).tearDownClass() - cls.clear_resources(cls.class_resources) - - @classmethod - def clear_resources(cls, resources=None): - """Deletes resources, that were created in test suites. - - This method tries to remove resources from resource list, - if it is not found, assume it was deleted in test itself. - It is expected, that all resources were added as LIFO - due to restriction of deletion resources, that are in the chain. - :param resources: dict with keys 'type','id','client', - 'deletion_params' and 'deleted'. Optional 'deletion_params' - contains additional data needed to delete some type of resources. - Ex: - params = { - 'type': 'share_network_subnet', - 'id': 'share-network-subnet-id', - 'client': None, - 'deletion_params': { - 'share_network': 'share-network-id', - }, - 'deleted': False, - } - """ - - if resources is None: - resources = cls.method_resources - for res in resources: - if "deleted" not in res: - res["deleted"] = False - if "client" not in res: - res["client"] = cls.get_cleanup_client() - if not res["deleted"]: - res_id = res["id"] - client = res["client"] - deletion_params = res.get("deletion_params") - with handle_cleanup_exceptions(): - # TODO(vponomaryov): add support for other resources - if res["type"] == "share_type": - client.delete_share_type( - res_id, microversion=res["microversion"]) - client.wait_for_share_type_deletion( - res_id, microversion=res["microversion"]) - elif res["type"] == "share_network": - client.delete_share_network( - res_id, microversion=res["microversion"]) - client.wait_for_share_network_deletion( - res_id, microversion=res["microversion"]) - elif res["type"] == "share_network_subnet": - client.delete_share_network_subnet( - share_network_subnet=res_id, - share_network=deletion_params["share_network"], - microversion=res["microversion"]) - client.wait_for_share_network_subnet_deletion( - share_network_subnet=res_id, - share_network=deletion_params["share_network"], - microversion=res["microversion"]) - elif res["type"] == "share": - client.delete_share( - res_id, microversion=res["microversion"]) - client.wait_for_share_deletion( - res_id, microversion=res["microversion"]) - elif res["type"] == "snapshot": - client.delete_snapshot( - res_id, microversion=res["microversion"]) - client.wait_for_snapshot_deletion( - res_id, microversion=res["microversion"]) - elif res["type"] == "share_replica": - client.delete_share_replica( - res_id, microversion=res["microversion"]) - client.wait_for_share_replica_deletion( - res_id, microversion=res["microversion"]) - else: - LOG.warning("Provided unsupported resource type for " - "cleanup '%s'. Skipping.", res["type"]) - res["deleted"] = True - - @classmethod - def get_admin_client(cls): - manilaclient = client.ManilaCLIClient( - username=CONF.admin_username, - password=CONF.admin_password, - tenant_name=CONF.admin_tenant_name, - project_domain_name=CONF.admin_project_domain_name or None, - project_domain_id=CONF.admin_project_domain_id or None, - user_domain_name=CONF.admin_user_domain_name or None, - user_domain_id=CONF.admin_user_domain_id or None, - uri=CONF.admin_auth_url or CONF.auth_url, - insecure=CONF.insecure, - cli_dir=CONF.manila_exec_dir) - # Set specific for admin project share network - manilaclient.share_network = CONF.admin_share_network - return manilaclient - - @classmethod - def get_user_client(cls): - manilaclient = client.ManilaCLIClient( - username=CONF.username, - password=CONF.password, - tenant_name=CONF.tenant_name, - project_domain_name=CONF.project_domain_name or None, - project_domain_id=CONF.project_domain_id or None, - user_domain_name=CONF.user_domain_name or None, - user_domain_id=CONF.user_domain_id or None, - uri=CONF.auth_url, - insecure=CONF.insecure, - cli_dir=CONF.manila_exec_dir) - # Set specific for user project share network - manilaclient.share_network = CONF.share_network - return manilaclient - - @property - def admin_client(self): - if not hasattr(self, '_admin_client'): - self._admin_client = self.get_admin_client() - return self._admin_client - - @property - def user_client(self): - if not hasattr(self, '_user_client'): - self._user_client = self.get_user_client() - return self._user_client - - def _get_clients(self): - return {'admin': self.admin_client, 'user': self.user_client} - - def skip_if_microversion_not_supported(self, microversion): - if not utils.is_microversion_supported(microversion): - raise self.skipException( - "Microversion '%s' is not supported." % microversion) - - @classmethod - def create_share_type(cls, name=None, driver_handles_share_servers=True, - snapshot_support=None, - create_share_from_snapshot=None, - revert_to_snapshot=None, mount_snapshot=None, - is_public=True, client=None, cleanup_in_class=False, - microversion=None, extra_specs=None, - description=None): - if client is None: - client = cls.get_admin_client() - data = { - "name": name, - "driver_handles_share_servers": driver_handles_share_servers, - "snapshot_support": snapshot_support, - "is_public": is_public, - "microversion": microversion, - "extra_specs": extra_specs, - "create_share_from_snapshot": create_share_from_snapshot, - "revert_to_snapshot": revert_to_snapshot, - "mount_snapshot": mount_snapshot, - } - if description: - data["description"] = description - share_type = client.create_share_type(**data) - resource = { - "type": "share_type", - "id": share_type["ID"], - "client": client, - "microversion": microversion, - } - if cleanup_in_class: - cls.class_resources.insert(0, resource) - else: - cls.method_resources.insert(0, resource) - return share_type - - @classmethod - def update_share_type(cls, share_type_id, name=None, - is_public=None, client=None, - microversion=None, description=None): - if client is None: - client = cls.get_admin_client() - data = { - "share_type_id": share_type_id, - "microversion": microversion, - } - if name is not None: - data["name"] = name - if description is not None: - data["description"] = description - if is_public is not None: - data["is_public"] = is_public - share_type = client.update_share_type(**data) - return share_type - - @classmethod - def create_share_network(cls, name=None, description=None, - neutron_net_id=None, - neutron_subnet_id=None, - availability_zone=None, client=None, - cleanup_in_class=False, microversion=None): - if client is None: - client = cls.get_admin_client() - share_network = client.create_share_network( - name=name, - description=description, - neutron_net_id=neutron_net_id, - neutron_subnet_id=neutron_subnet_id, - availability_zone=availability_zone, - microversion=microversion, - ) - resource = { - "type": "share_network", - "id": share_network["id"], - "client": client, - "microversion": microversion, - } - if cleanup_in_class: - cls.class_resources.insert(0, resource) - else: - cls.method_resources.insert(0, resource) - return share_network - - @classmethod - def add_share_network_subnet(cls, share_network, - neutron_net_id=None, neutron_subnet_id=None, - availability_zone=None, client=None, - cleanup_in_class=False, microversion=None): - if client is None: - client = cls.get_admin_client() - share_network_subnet = client.add_share_network_subnet( - share_network, neutron_net_id, neutron_subnet_id, - availability_zone) - resource = { - "type": "share_network_subnet", - "id": share_network_subnet["id"], - "client": client, - "deletion_params": { - "share_network": share_network, - }, - "microversion": microversion, - } - if cleanup_in_class: - cls.class_resources.insert(0, resource) - else: - cls.method_resources.insert(0, resource) - return share_network_subnet - - @classmethod - def create_share(cls, share_protocol=None, size=None, share_network=None, - share_type=None, name=None, description=None, - public=False, snapshot=None, metadata=None, - client=None, use_wait_option=False, - cleanup_in_class=False, wait_for_creation=True, - microversion=None): - client = client or cls.get_admin_client() - data = { - 'share_protocol': share_protocol or client.share_protocol, - 'size': size or 1, - 'name': name, - 'description': description, - 'public': public, - 'snapshot': snapshot, - 'metadata': metadata or {}, - 'microversion': microversion, - 'wait': use_wait_option, - } - - share_type = share_type or CONF.share_type - share_network = share_network or cls._determine_share_network_to_use( - client, share_type, microversion=microversion) - - data['share_type'] = share_type - data['share_network'] = share_network - share = client.create_share(**data) - resource = { - "type": "share", - "id": share["id"], - "client": client, - "microversion": microversion, - } - if cleanup_in_class: - cls.class_resources.insert(0, resource) - else: - cls.method_resources.insert(0, resource) - if wait_for_creation and not use_wait_option: - client.wait_for_resource_status(share['id'], - constants.STATUS_AVAILABLE) - return share - - @classmethod - def delete_share(cls, shares_to_delete, share_group_id=None, - wait=False, client=None, microversion=None): - client = client or cls.get_admin_client() - client.delete_share(shares_to_delete, share_group_id=share_group_id, - wait=wait, microversion=microversion) - - @classmethod - def soft_delete_share(cls, shares_to_soft_delete, - client=None, microversion=None): - client = client or cls.get_admin_client() - client.soft_delete_share(shares_to_soft_delete, - microversion=microversion) - - @classmethod - def restore_share(cls, shares_to_restore, - client=None, microversion=None): - client = client or cls.get_admin_client() - client.restore_share(shares_to_restore, - microversion=microversion) - - @classmethod - def create_share_transfer(cls, share_id, name=None, - client=None, microversion=None): - client = client or cls.get_admin_client() - return client.create_share_transfer(share_id, name=name, - microversion=microversion) - - @classmethod - def delete_share_transfer(cls, transfer, client=None, - microversion=None): - client = client or cls.get_admin_client() - client.delete_share_transfer(transfer, microversion=microversion) - - @classmethod - def get_share_transfer(cls, transfer, client=None, microversion=None): - client = client or cls.get_admin_client() - return client.get_share_transfer(transfer, microversion=microversion) - - @classmethod - def list_share_transfer(cls, client=None, microversion=None): - client = client or cls.get_admin_client() - return client.list_share_transfer(microversion=microversion) - - @classmethod - def accept_share_transfer(cls, transfer, auth_key, - client=None, microversion=None): - client = client or cls.get_admin_client() - client.accept_share_transfer(transfer, auth_key, - microversion=microversion) - - @classmethod - def _determine_share_network_to_use(cls, client, share_type, - microversion=None): - """Determine what share network we need from the share type.""" - - # Get share type, determine if we need the share network - share_type = client.get_share_type(share_type, - microversion=microversion) - dhss_pattern = re.compile('driver_handles_share_servers : ([a-zA-Z]+)') - dhss = dhss_pattern.search(share_type['required_extra_specs']).group(1) - return client.share_network if dhss.lower() == 'true' else None - - @classmethod - def create_security_service(cls, type='ldap', name=None, description=None, - dns_ip=None, ou=None, server=None, domain=None, - user=None, password=None, default_ad_site=None, - client=None, cleanup_in_class=False, - microversion=None): - if client is None: - client = cls.get_admin_client() - data = { - 'type': type, - 'name': name, - 'description': description, - 'user': user, - 'password': password, - 'server': server, - 'domain': domain, - 'dns_ip': dns_ip, - 'ou': ou, - 'microversion': microversion, - 'default_ad_site': default_ad_site, - } - ss = client.create_security_service(**data) - resource = { - "type": "share", - "id": ss["id"], - "client": client, - "microversion": microversion, - } - if cleanup_in_class: - cls.class_resources.insert(0, resource) - else: - cls.method_resources.insert(0, resource) - return ss - - @classmethod - def create_snapshot(cls, share, name=None, description=None, - force=False, client=None, wait_for_creation=True, - cleanup_in_class=False, microversion=None): - if client is None: - client = cls.get_admin_client() - data = { - 'share': share, - 'name': name, - 'description': description, - 'force': force, - 'microversion': microversion, - } - snapshot = client.create_snapshot(**data) - resource = { - "type": "snapshot", - "id": snapshot["id"], - "client": client, - "microversion": microversion, - } - if cleanup_in_class: - cls.class_resources.insert(0, resource) - else: - cls.method_resources.insert(0, resource) - if wait_for_creation: - client.wait_for_snapshot_status(snapshot['id'], 'available') - return snapshot - - @classmethod - def create_message(cls, client=None, wait_for_creation=True, - cleanup_in_class=False, microversion=None): - """Trigger a 'no valid host' situation to generate a message.""" - if client is None: - client = cls.get_admin_client() - - extra_specs = { - 'vendor_name': 'foobar', - } - share_type_name = data_utils.rand_name("share-type") - cls.create_share_type( - name=share_type_name, extra_specs=extra_specs, - driver_handles_share_servers=False, client=client, - cleanup_in_class=cleanup_in_class, microversion=microversion) - - share_name = data_utils.rand_name("share") - share = cls.create_share( - name=share_name, share_type=share_type_name, - cleanup_in_class=cleanup_in_class, microversion=microversion, - wait_for_creation=False, client=client) - - client.wait_for_resource_status(share['id'], constants.STATUS_ERROR) - message = client.wait_for_message(share['id']) - - resource = { - "type": "message", - "id": message["ID"], - "client": client, - "microversion": microversion, - } - if cleanup_in_class: - cls.class_resources.insert(0, resource) - else: - cls.method_resources.insert(0, resource) - return message - - @classmethod - def create_share_replica(cls, share_id, client=None, - wait_for_creation=True, cleanup_in_class=False, - availability_zone=None, share_network=None, - microversion=None): - client = client or cls.get_user_client() - - share_replica = client.create_share_replica( - share_id, - availability_zone=availability_zone, - share_network=share_network, - microversion=microversion) - if wait_for_creation: - share_replica = client.wait_for_share_replica_status( - share_replica['id']) - - resource = { - "type": "share_replica", - "id": share_replica["id"], - "client": client, - "microversion": microversion, - } - if cleanup_in_class: - cls.class_resources.insert(0, resource) - else: - cls.method_resources.insert(0, resource) - return share_replica diff --git a/manilaclient/tests/functional/client.py b/manilaclient/tests/functional/client.py deleted file mode 100644 index 7a3f0bfe..00000000 --- a/manilaclient/tests/functional/client.py +++ /dev/null @@ -1,2115 +0,0 @@ -# Copyright 2014 Mirantis Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import ast -import re -import time - -from oslo_utils import strutils -from tempest.lib.cli import base -from tempest.lib.cli import output_parser -from tempest.lib.common.utils import data_utils -from tempest.lib import exceptions as tempest_lib_exc - -from manilaclient.common import constants -from manilaclient import config -from manilaclient.tests.functional import exceptions -from manilaclient.tests.functional import utils - -CONF = config.CONF -MESSAGE = 'message' -SHARE = 'share' -SHARE_TYPE = 'share_type' -SHARE_NETWORK = 'share_network' -SHARE_NETWORK_SUBNET = 'share_network_subnet' -SHARE_SERVER = 'share_server' -SNAPSHOT = 'snapshot' -SHARE_REPLICA = 'share_replica' -TRANSFER = 'transfer' - - -def not_found_wrapper(f): - - def wrapped_func(self, *args, **kwargs): - try: - return f(self, *args, **kwargs) - except tempest_lib_exc.CommandFailed as e: - for regexp in (r'No (\w+) with a name or ID', - r'not(.*){0,5}found'): - if re.search(regexp, str(e.stderr)): - # Raise appropriate 'NotFound' error - raise tempest_lib_exc.NotFound() - raise - - return wrapped_func - - -def forbidden_wrapper(f): - - def wrapped_func(self, *args, **kwargs): - try: - return f(self, *args, **kwargs) - except tempest_lib_exc.CommandFailed as e: - if re.search('HTTP 403', str(e.stderr)): - # Raise appropriate 'Forbidden' error. - raise tempest_lib_exc.Forbidden() - raise - - return wrapped_func - - -class ManilaCLIClient(base.CLIClient): - - def __init__(self, *args, **kwargs): - super(ManilaCLIClient, self).__init__(*args, **kwargs) - if CONF.enable_protocols: - self.share_protocol = CONF.enable_protocols[0] - else: - msg = "Configuration option 'enable_protocols' is not defined." - raise exceptions.InvalidConfiguration(reason=msg) - self.build_interval = CONF.build_interval - self.build_timeout = CONF.build_timeout - - def manila(self, action, flags='', params='', fail_ok=False, - endpoint_type='publicURL', merge_stderr=False, - microversion=None): - """Executes manila command for the given action. - - :param action: the cli command to run using manila - :type action: string - :param flags: any optional cli flags to use. For specifying - microversion, please, use 'microversion' param - :type flags: string - :param params: any optional positional args to use - :type params: string - :param fail_ok: if True an exception is not raised when the - cli return code is non-zero - :type fail_ok: boolean - :param endpoint_type: the type of endpoint for the service - :type endpoint_type: string - :param merge_stderr: if True the stderr buffer is merged into stdout - :type merge_stderr: boolean - :param microversion: API microversion to be used for request - :type microversion: str - """ - flags += ' --endpoint-type %s' % endpoint_type - if not microversion: - # NOTE(vponomaryov): use max API version from config - microversion = CONF.max_api_microversion - - # NOTE(vponomaryov): it is possible that param 'flags' already - # can contain '--os-share-api-version' key. If it is so and we - # reached this part then value of 'microversion' param will be - # used and existing one in 'flags' param will be ignored. - flags += ' --os-share-api-version %s' % microversion - return self.cmd_with_auth( - 'manila', action, flags, params, fail_ok, merge_stderr) - - def wait_for_resource_deletion(self, res_type, res_id, interval=3, - timeout=180, microversion=None, **kwargs): - """Resource deletion waiter. - - :param res_type: text -- type of resource - :param res_id: text -- ID of resource to use for deletion check - :param interval: int -- interval between requests in seconds - :param timeout: int -- total time in seconds to wait for deletion - :param args: dict -- additional keyword arguments for deletion func - """ - if res_type == SHARE_TYPE: - func = self.is_share_type_deleted - elif res_type == SHARE_NETWORK: - func = self.is_share_network_deleted - elif res_type == SHARE_NETWORK_SUBNET: - func = self.is_share_network_subnet_deleted - elif res_type == SHARE_SERVER: - func = self.is_share_server_deleted - elif res_type == SHARE: - func = self.is_share_deleted - elif res_type == SNAPSHOT: - func = self.is_snapshot_deleted - elif res_type == MESSAGE: - func = self.is_message_deleted - elif res_type == SHARE_REPLICA: - func = self.is_share_replica_deleted - elif res_type == TRANSFER: - func = self.is_share_transfer_deleted - else: - raise exceptions.InvalidResource(message=res_type) - - end_loop_time = time.time() + timeout - deleted = func(res_id, microversion=microversion, **kwargs) - - while not (deleted or time.time() > end_loop_time): - time.sleep(interval) - deleted = func(res_id, microversion=microversion, **kwargs) - - if not deleted: - raise exceptions.ResourceReleaseFailed( - res_type=res_type, res_id=res_id) - - def list_availability_zones(self, columns=None, microversion=None): - """List availability zones. - - :param columns: comma separated string of columns. - Example, "--columns id,name" - :param microversion: API microversion that should be used. - """ - cmd = 'availability-zone-list' - if columns is not None: - cmd += ' --columns ' + columns - azs_raw = self.manila(cmd, microversion=microversion) - azs = output_parser.listing(azs_raw) - return azs - - # Share types - - def create_share_type(self, name=None, driver_handles_share_servers=True, - snapshot_support=None, - create_share_from_snapshot=None, - revert_to_snapshot=None, mount_snapshot=None, - is_public=True, microversion=None, extra_specs=None, - description=None): - """Creates share type. - - :param name: text -- name of share type to use, if not set then - autogenerated will be used - :param description: text -- description of share type to use. - Default is None. - :param driver_handles_share_servers: bool/str -- boolean or its - string alias. Default is True. - :param snapshot_support: bool/str -- boolean or its - string alias. Default is None. - :param is_public: bool/str -- boolean or its string alias. Default is - True. - :param extra_specs: -- dictionary of extra specs Default is None. - :param create_share_from_snapshot: -- boolean or its string - alias. Default is None. - :param revert_to_snapshot: -- boolean or its string alias. Default is - None. - :param mount_snapshot: -- boolean or its string alias. Default is None. - """ - if name is None: - name = data_utils.rand_name('manilaclient_functional_test') - dhss = driver_handles_share_servers - if not isinstance(dhss, str): - dhss = str(dhss) - if not isinstance(is_public, str): - is_public = str(is_public) - - cmd = ('type-create %(name)s %(dhss)s --is-public %(is_public)s ') % { - 'name': name, 'dhss': dhss, 'is_public': is_public} - - if description is not None: - cmd += " --description " + description - - if snapshot_support is not None: - if not isinstance(snapshot_support, str): - snapshot_support = str(snapshot_support) - cmd += " --snapshot-support " + snapshot_support - - if create_share_from_snapshot is not None: - if not isinstance(create_share_from_snapshot, str): - create_share_from_snapshot = str(create_share_from_snapshot) - cmd += (" --create-share-from-snapshot-support " + - create_share_from_snapshot) - - if revert_to_snapshot is not None: - if not isinstance(revert_to_snapshot, str): - revert_to_snapshot = str(revert_to_snapshot) - cmd += (" --revert-to-snapshot-support " + revert_to_snapshot) - - if mount_snapshot is not None: - if not isinstance(mount_snapshot, str): - mount_snapshot = str(mount_snapshot) - cmd += (" --mount-snapshot-support " + mount_snapshot) - - if extra_specs is not None: - extra_spec_str = '' - for k, v in extra_specs.items(): - if not isinstance(v, str): - extra_specs[k] = str(v) - extra_spec_str += "{}='{}' ".format(k, v) - cmd += " --extra_specs " + extra_spec_str - - share_type_raw = self.manila(cmd, microversion=microversion) - share_type = utils.details(share_type_raw) - return share_type - - def update_share_type(self, share_type_id, name=None, - is_public=None, microversion=None, - description=None): - """Update share type. - - :param share_type_id: text -- id of share type. - :param name: text -- new name of share type, if not set then - it will not be updated. - :param description: text -- new description of share type. - if not set then it will not be updated. - :param is_public: bool/str -- boolean or its string alias. - new visibility of the share type.If set to True, share - type will be available to all tenants in the cloud. - """ - - cmd = ('type-update %(share_type_id)s ') % { - 'share_type_id': share_type_id} - - if is_public is not None: - if not isinstance(is_public, str): - is_public = str(is_public) - cmd += " --is_public " + is_public - - if description: - cmd += " --description " + description - elif description == "": - cmd += ' --description "" ' - - if name: - cmd += " --name " + name - - share_type_raw = self.manila(cmd, microversion=microversion) - share_type = utils.details(share_type_raw) - return share_type - - @not_found_wrapper - def delete_share_type(self, share_type, microversion=None): - """Deletes share type by its Name or ID.""" - return self.manila( - 'type-delete %s' % share_type, microversion=microversion) - - def list_share_types(self, list_all=True, columns=None, search_opts=None, - microversion=None): - """List share types. - - :param list_all: bool -- whether to list all share types or only public - :param search_opts: dict search_opts for filter search. - :param columns: comma separated string of columns. - Example, "--columns id,name" - """ - cmd = 'type-list' - if list_all: - cmd += ' --all' - if search_opts is not None: - extra_specs = search_opts.get('extra_specs') - if extra_specs: - cmd += ' --extra_specs' - for spec_key in extra_specs.keys(): - cmd += ' ' + spec_key + '=' + extra_specs[spec_key] - if columns is not None: - cmd += ' --columns ' + columns - share_types_raw = self.manila(cmd, microversion=microversion) - share_types = output_parser.listing(share_types_raw) - return share_types - - def get_share_type(self, share_type, microversion=None): - """Get share type. - - :param share_type: str -- Name or ID of share type, or None to - retrieve default share type - """ - share_types = self.list_share_types(True, microversion=microversion) - for stype in share_types: - if share_type is None and stype["is_default"] == 'YES': - return stype - elif share_type in (stype['ID'], stype['Name']): - return stype - raise tempest_lib_exc.NotFound() - - def is_share_type_deleted(self, share_type, microversion=None): - """Says whether share type is deleted or not. - - :param share_type: text -- Name or ID of share type - """ - # NOTE(vponomaryov): we use 'list' operation because there is no - # 'get/show' operation for share-types available for CLI - share_types = self.list_share_types( - list_all=True, microversion=microversion) - for list_element in share_types: - if share_type in (list_element['ID'], list_element['Name']): - return False - return True - - def wait_for_share_type_deletion(self, share_type, microversion=None): - """Wait for share type deletion by its Name or ID. - - :param share_type: text -- Name or ID of share type - """ - self.wait_for_resource_deletion( - SHARE_TYPE, res_id=share_type, interval=2, timeout=6, - microversion=microversion) - - def get_project_id(self, name_or_id): - identity_api_version = '3' - flags = ( - "--os-username %(username)s " - "--os-project-name %(project_name)s " - "--os-password %(password)s " - "--os-identity-api-version %(identity_api_version)s " - ) % { - "username": CONF.admin_username, - "project_name": CONF.admin_tenant_name, - "password": CONF.admin_password, - "identity_api_version": identity_api_version, - } - - if identity_api_version == "3": - if CONF.admin_project_domain_name: - flags += ( - "--os-project-domain-name %s " % - CONF.admin_project_domain_name) - elif CONF.admin_project_domain_id: - flags += ( - "--os-project-domain-id %s " % - CONF.admin_project_domain_id) - - if CONF.admin_user_domain_name: - flags += ( - "--os-user-domain-name %s " % - CONF.admin_user_domain_name) - elif CONF.admin_user_domain_id: - flags += ( - "--os-user-domain-id %s " % - CONF.admin_user_domain_id) - - project_id = self.openstack( - 'project show -f value -c id %s' % name_or_id, flags=flags) - return project_id.strip() - - @not_found_wrapper - def add_share_type_access(self, share_type_name_or_id, project_id, - microversion=None): - data = dict(st=share_type_name_or_id, project=project_id) - self.manila('type-access-add %(st)s %(project)s' % data, - microversion=microversion) - - @not_found_wrapper - def remove_share_type_access(self, share_type_name_or_id, project_id, - microversion=None): - data = dict(st=share_type_name_or_id, project=project_id) - self.manila('type-access-remove %(st)s %(project)s' % data, - microversion=microversion) - - @not_found_wrapper - def list_share_type_access(self, share_type_id, microversion=None): - projects_raw = self.manila( - 'type-access-list %s' % share_type_id, microversion=microversion) - projects = output_parser.listing(projects_raw) - project_ids = [pr['Project_ID'] for pr in projects] - return project_ids - - @not_found_wrapper - def set_share_type_extra_specs(self, share_type_name_or_id, extra_specs, - microversion=None): - """Set key-value pair for share type.""" - if not (isinstance(extra_specs, dict) and extra_specs): - raise exceptions.InvalidData( - message='Provided invalid extra specs - %s' % extra_specs) - cmd = 'type-key %s set ' % share_type_name_or_id - for key, value in extra_specs.items(): - cmd += '%(key)s=%(value)s ' % {'key': key, 'value': value} - return self.manila(cmd, microversion=microversion) - - @not_found_wrapper - def unset_share_type_extra_specs(self, share_type_name_or_id, - extra_specs_keys, microversion=None): - """Unset key-value pair for share type.""" - if not (isinstance(extra_specs_keys, (list, tuple, set)) and - extra_specs_keys): - raise exceptions.InvalidData( - message='Provided invalid extra specs - %s' % extra_specs_keys) - cmd = 'type-key %s unset ' % share_type_name_or_id - for key in extra_specs_keys: - cmd += '%s ' % key - return self.manila(cmd, microversion=microversion) - - def list_all_share_type_extra_specs(self, microversion=None): - """List extra specs for all share types.""" - extra_specs_raw = self.manila( - 'extra-specs-list', microversion=microversion) - extra_specs = utils.listing(extra_specs_raw) - return extra_specs - - def list_share_type_extra_specs(self, share_type_name_or_id, - microversion=None): - """List extra specs for specific share type by its Name or ID.""" - all_share_types = self.list_all_share_type_extra_specs( - microversion=microversion) - for share_type in all_share_types: - if share_type_name_or_id in (share_type['ID'], share_type['Name']): - return share_type['all_extra_specs'] - raise exceptions.ShareTypeNotFound(share_type=share_type_name_or_id) - - # Share networks - - def create_share_network(self, name=None, description=None, - neutron_net_id=None, neutron_subnet_id=None, - availability_zone=None, - microversion=None): - """Creates share network. - - :param name: text -- desired name of new share network - :param description: text -- desired description of new share network - :param neutron_net_id: text -- ID of Neutron network - :param neutron_subnet_id: text -- ID of Neutron subnet - """ - params = self._combine_share_network_data( - name=name, - description=description, - neutron_net_id=neutron_net_id, - neutron_subnet_id=neutron_subnet_id, - availability_zone=availability_zone - ) - share_network_raw = self.manila( - 'share-network-create %s' % params, microversion=microversion) - share_network = output_parser.details(share_network_raw) - return share_network - - def _combine_share_network_data(self, name=None, description=None, - neutron_net_id=None, - neutron_subnet_id=None, - availability_zone=None): - """Combines params for share network operations 'create' and 'update'. - - :returns: text -- set of CLI parameters - """ - data = dict() - if name is not None: - data['--name'] = name - if description is not None: - data['--description'] = description - if neutron_net_id is not None: - data['--neutron_net_id'] = neutron_net_id - if neutron_subnet_id is not None: - data['--neutron_subnet_id'] = neutron_subnet_id - if availability_zone is not None: - data['--availability_zone'] = availability_zone - cmd = '' - for key, value in data.items(): - cmd += "%(k)s=%(v)s " % {'k': key, 'v': value} - return cmd - - @not_found_wrapper - def get_share_network(self, share_network, microversion=None): - """Returns share network by its Name or ID.""" - share_network_raw = self.manila( - 'share-network-show %s' % share_network, microversion=microversion) - share_network = output_parser.details(share_network_raw) - return share_network - - @not_found_wrapper - def update_share_network(self, share_network, name=None, description=None, - neutron_net_id=None, - neutron_subnet_id=None, microversion=None): - """Updates share-network by its name or ID. - - :param name: text -- new name for share network - :param description: text -- new description for share network - :param neutron_net_id: text -- ID of some Neutron network - :param neutron_subnet_id: text -- ID of some Neutron subnet - """ - sn_params = self._combine_share_network_data( - name=name, - description=description, - neutron_net_id=neutron_net_id, - neutron_subnet_id=neutron_subnet_id) - share_network_raw = self.manila( - 'share-network-update %(sn)s %(params)s' % dict( - sn=share_network, params=sn_params), - microversion=microversion) - share_network = output_parser.details(share_network_raw) - return share_network - - @not_found_wrapper - def delete_share_network(self, share_network, microversion=None): - """Deletes share network by its Name or ID.""" - return self.manila('share-network-delete %s' % share_network, - microversion=microversion) - - @staticmethod - def _stranslate_to_cli_optional_param(param): - if len(param) < 1 or not isinstance(param, str): - raise exceptions.InvalidData( - 'Provided wrong parameter for translation.') - while not param[0:2] == '--': - param = '-' + param - return param.replace('_', '-') - - def list_share_networks(self, all_tenants=False, filters=None, - columns=None, microversion=None): - """List share networks. - - :param all_tenants: bool -- whether to list share-networks that belong - only to current project or for all tenants. - :param filters: dict -- filters for listing of share networks. - Example, input: - {'project_id': 'foo'} - {'-project_id': 'foo'} - {'--project_id': 'foo'} - {'project-id': 'foo'} - will be transformed to filter parameter "--project-id=foo" - :param columns: comma separated string of columns. - Example, "--columns id" - """ - cmd = 'share-network-list ' - if columns is not None: - cmd += ' --columns ' + columns - if all_tenants: - cmd += ' --all-tenants ' - if filters and isinstance(filters, dict): - for k, v in filters.items(): - cmd += '%(k)s=%(v)s ' % { - 'k': self._stranslate_to_cli_optional_param(k), 'v': v} - share_networks_raw = self.manila(cmd, microversion=microversion) - share_networks = utils.listing(share_networks_raw) - return share_networks - - def share_network_reset_state(self, id=None, state=None, - microversion=None): - cmd = 'share-network-reset-state %s ' % id - if state: - cmd += '--state %s' % state - share_network_raw = self.manila(cmd, microversion=microversion) - share_network = utils.listing(share_network_raw) - return share_network - - def share_network_security_service_add( - self, share_network_id, security_service_id, microversion=None): - cmd = ('share-network-security-service-add %(network_id)s ' - '%(service_id)s' % {'network_id': share_network_id, - 'service_id': security_service_id}) - self.manila(cmd, microversion=microversion) - - def share_network_security_service_update( - self, share_network_id, current_security_service_id, - new_security_service_id, microversion=None): - cmd = ( - 'share-network-security-service-update %(network_id)s ' - '%(current_service_id)s %(new_security_service_id)s' % { - 'network_id': share_network_id, - 'current_service_id': current_security_service_id, - 'new_security_service_id': new_security_service_id}) - self.manila(cmd, microversion=microversion) - - def share_network_security_service_add_check( - self, share_network_id, security_service_id, - reset=False, microversion=None): - cmd = ( - 'share-network-security-service-add-check %(network_id)s ' - '%(security_service_id)s' % { - 'network_id': share_network_id, - 'security_service_id': security_service_id}) - - if reset: - cmd += '--reset %s' % reset - - return output_parser.details( - self.manila(cmd, microversion=microversion)) - - def share_network_security_service_update_check( - self, share_network_id, current_security_service_id, - new_security_service_id, reset=False, microversion=None): - cmd = ( - 'share-network-security-service-update-check %(network_id)s ' - '%(current_security_service_id)s %(new_security_service_id)s ' % { - 'network_id': share_network_id, - 'current_security_service_id': current_security_service_id, - 'new_security_service_id': new_security_service_id}) - - if reset: - cmd += '--reset %s' % reset - - return output_parser.details( - self.manila(cmd, microversion=microversion)) - - def share_network_security_service_list( - self, share_network_id, microversion=None): - cmd = ('share-network-security-service-list %s' % share_network_id) - share_networks_raw = self.manila(cmd, microversion=microversion) - network_services = utils.listing(share_networks_raw) - return network_services - - def is_share_network_deleted(self, share_network, microversion=None): - """Says whether share network is deleted or not. - - :param share_network: text -- Name or ID of share network - """ - share_types = self.list_share_networks(True, microversion=microversion) - for list_element in share_types: - if share_network in (list_element['id'], list_element['name']): - return False - return True - - def wait_for_share_network_deletion(self, share_network, - microversion=None): - """Wait for share network deletion by its Name or ID. - - :param share_network: text -- Name or ID of share network - """ - self.wait_for_resource_deletion( - SHARE_NETWORK, res_id=share_network, interval=2, timeout=6, - microversion=microversion) - - def share_network_subnet_create_check( - self, share_network_id, neutron_net_id=None, - neutron_subnet_id=None, availability_zone=None, reset=False, - microversion=None): - params = self._combine_share_network_subnet_data( - neutron_net_id=neutron_net_id, - neutron_subnet_id=neutron_subnet_id, - availability_zone=availability_zone) - cmd = ( - 'share-network-subnet-create-check %(network_id)s ' - '%(params)s' % { - 'network_id': share_network_id, - 'params': params}) - - if reset: - cmd += '--reset %s' % reset - - return output_parser.details( - self.manila(cmd, microversion=microversion)) - - # Share Network Subnets - - def _combine_share_network_subnet_data(self, neutron_net_id=None, - neutron_subnet_id=None, - availability_zone=None): - """Combines params for share network subnet 'create' operation. - - :returns: text -- set of CLI parameters - """ - data = dict() - if neutron_net_id is not None: - data['--neutron_net_id'] = neutron_net_id - if neutron_subnet_id is not None: - data['--neutron_subnet_id'] = neutron_subnet_id - if availability_zone is not None: - data['--availability_zone'] = availability_zone - cmd = '' - for key, value in data.items(): - cmd += "%(k)s=%(v)s " % dict(k=key, v=value) - return cmd - - def add_share_network_subnet(self, share_network, - neutron_net_id=None, neutron_subnet_id=None, - availability_zone=None, microversion=None): - """Create new share network subnet for the given share network.""" - params = self._combine_share_network_subnet_data( - neutron_net_id=neutron_net_id, - neutron_subnet_id=neutron_subnet_id, - availability_zone=availability_zone) - share_network_subnet_raw = self.manila( - 'share-network-subnet-create %(sn)s %(params)s' % - {'sn': share_network, 'params': params}, microversion=microversion) - share_network_subnet = output_parser.details(share_network_subnet_raw) - return share_network_subnet - - def get_share_network_subnet(self, share_network, share_network_subnet, - microversion=None): - """Returns share network subnet by share network ID and subnet ID.""" - - share_network_subnet_raw = self.manila( - 'share-network-subnet-show %(share_net)s %(share_subnet)s' % { - 'share_net': share_network, - 'share_subnet': share_network_subnet, - }) - share_network_subnet = output_parser.details(share_network_subnet_raw) - return share_network_subnet - - def get_share_network_subnets(self, share_network, microversion=None): - share_network = self.get_share_network(share_network, - microversion=microversion) - raw_subnets = share_network.get('share_network_subnets') - subnets = ast.literal_eval(raw_subnets) - # NOTE(lseki): convert literal None to string 'None' - for subnet in subnets: - for k, v in subnet.items(): - subnet[k] = str(v) if v is None else v - return subnets - - @not_found_wrapper - def delete_share_network_subnet(self, share_network, share_network_subnet, - microversion=None): - """Delete a share_network.""" - self.manila( - 'share-network-subnet-delete %(share_net)s %(share_subnet)s' % { - 'share_net': share_network, - 'share_subnet': share_network_subnet, - }, microversion=microversion) - - def is_share_network_subnet_deleted(self, share_network_subnet, - share_network, microversion=None): - # NOTE(lseki): the parameter share_network_subnet comes before - # share_network, because the wrapper method wait_for_resource_deletion - # expects the resource id in first place (subnet ID in this case). - """Says whether share network subnet is deleted or not. - - :param share_network_subnet: text -- Name or ID of share network subnet - :param share_network: text -- Name or ID of share network the subnet - belongs to - """ - subnets = self.get_share_network_subnets(share_network) - return not any(subnet['id'] == share_network_subnet - for subnet in subnets) - - def wait_for_share_network_subnet_deletion(self, share_network_subnet, - share_network, - microversion=None): - # NOTE(lseki): the parameter share_network_subnet comes before - # share_network, because the wrapper method wait_for_resource_deletion - # expects the resource id in first place (subnet ID in this case). - """Wait for share network subnet deletion by its Name or ID. - - :param share_network_subnet: text -- Name or ID of share network subnet - :param share_network: text -- Name or ID of share network the subnet - belongs to - """ - args = {'share_network': share_network} - self.wait_for_resource_deletion( - SHARE_NETWORK_SUBNET, res_id=share_network_subnet, - interval=2, timeout=6, microversion=microversion, **args) - - # Shares - - def create_share(self, share_protocol, size, share_network=None, - share_type=None, name=None, description=None, - public=False, snapshot=None, metadata=None, wait=False, - microversion=None): - """Creates a share. - - :param share_protocol: str -- share protocol of a share. - :param size: int/str -- desired size of a share. - :param share_network: str -- Name or ID of share network to use. - :param share_type: str -- Name or ID of share type to use. - :param name: str -- desired name of new share. - :param description: str -- desired description of new share. - :param public: bool -- should a share be public or not. - Default is False. - :param snapshot: str -- Name or ID of a snapshot to use as source. - :param metadata: dict -- key-value data to provide with share creation. - :param wait: bool - the client must wait for "available" state - :param microversion: str -- API microversion that should be used. - """ - cmd = 'create %(share_protocol)s %(size)s ' % { - 'share_protocol': share_protocol, 'size': size} - if share_network is not None: - cmd += '--share-network %s ' % share_network - if share_type is not None: - cmd += '--share-type %s ' % share_type - if name is None: - name = data_utils.rand_name('autotest_share_name') - cmd += '--name %s ' % name - if description is None: - description = data_utils.rand_name('autotest_share_description') - cmd += '--description %s ' % description - if public: - cmd += '--public ' - if snapshot is not None: - cmd += '--snapshot %s ' % snapshot - if metadata: - metadata_cli = '' - for k, v in metadata.items(): - metadata_cli += '%(k)s=%(v)s ' % {'k': k, 'v': v} - if metadata_cli: - cmd += '--metadata %s ' % metadata_cli - if wait: - cmd += '--wait ' - share_raw = self.manila(cmd, microversion=microversion) - share = output_parser.details(share_raw) - return share - - @not_found_wrapper - def get_share(self, share, microversion=None): - """Returns a share by its Name or ID.""" - share_raw = self.manila('show %s' % share, microversion=microversion) - share = output_parser.details(share_raw) - return share - - @not_found_wrapper - def update_share(self, share, name=None, description=None, - is_public=False, microversion=None): - """Updates a share. - - :param share: str -- name or ID of a share that should be updated. - :param name: str -- desired name of new share. - :param description: str -- desired description of new share. - :param is_public: bool -- should a share be public or not. - Default is False. - """ - cmd = 'update %s ' % share - if name: - cmd += '--name %s ' % name - if description: - cmd += '--description %s ' % description - is_public = strutils.bool_from_string(is_public, strict=True) - cmd += '--is-public %s ' % is_public - - return self.manila(cmd, microversion=microversion) - - @not_found_wrapper - @forbidden_wrapper - def delete_share(self, shares, share_group_id=None, wait=False, - microversion=None): - """Deletes share[s] by Names or IDs. - - :param shares: either str or list of str that can be either Name - or ID of a share(s) that should be deleted. - :param share_group_id: a common share group ID for the shares being - deleted - :param wait: bool -- whether to wait for the shares to be deleted - """ - if not isinstance(shares, list): - shares = [shares] - cmd = 'delete ' - for share in shares: - cmd += '%s ' % share - if share_group_id: - cmd += '--share-group-id %s ' % share_group_id - if wait: - cmd += '--wait ' - return self.manila(cmd, microversion=microversion) - - @not_found_wrapper - @forbidden_wrapper - def soft_delete_share(self, shares, microversion=None): - """Soft Delete share[s] by Names or IDs. - - :param shares: either str or list of str that can be either Name - or ID of a share(s) that should be soft deleted. - """ - if not isinstance(shares, list): - shares = [shares] - cmd = 'soft-delete ' - for share in shares: - cmd += '%s ' % share - return self.manila(cmd, microversion=microversion) - - @not_found_wrapper - @forbidden_wrapper - def restore_share(self, shares, microversion=None): - """Restore share[s] by Names or IDs. - - :param shares: either str or list of str that can be either Name - or ID of a share(s) that should be soft deleted. - """ - if not isinstance(shares, list): - shares = [shares] - cmd = 'restore ' - for share in shares: - cmd += '%s ' % share - return self.manila(cmd, microversion=microversion) - - def create_share_transfer(self, share_id, name=None, - microversion=None): - """Create a share transfer. - - :param share_id: ID of share. - ":param name: name of transfer. - """ - cmd = 'share-transfer-create %s ' % share_id - if name: - cmd += '--name %s' % name - transfer_raw = self.manila(cmd, microversion=microversion) - transfer = output_parser.details(transfer_raw) - return transfer - - def delete_share_transfer(self, transfer, microversion=None): - """Delete a share transfer. - - :param transfer: ID or name of share transfer. - """ - cmd = 'share-transfer-delete %s ' % transfer - self.manila(cmd, microversion=microversion) - - def get_share_transfer(self, transfer, microversion=None): - """Get a share transfer. - - :param transfer: ID or name of share transfer. - """ - cmd = 'share-transfer-show %s ' % transfer - transfer_raw = self.manila(cmd, microversion=microversion) - transfer = output_parser.details(transfer_raw) - return transfer - - def list_share_transfer(self, microversion=None): - """Get a share transfer.""" - - cmd = 'share-transfer-list ' - transfer_raw = self.manila(cmd, microversion=microversion) - transfers = utils.listing(transfer_raw) - return transfers - - def accept_share_transfer(self, transfer, auth_key, - microversion=None): - """Accept a share transfer. - - :param transfer: ID or name of share transfer. - """ - cmd = 'share-transfer-accept %s %s' % (transfer, auth_key) - self.manila(cmd, microversion=microversion) - - def list_shares(self, all_tenants=False, is_soft_deleted=False, - filters=None, columns=None, is_public=False, - microversion=None): - """List shares. - - :param all_tenants: bool -- whether to list shares that belong - only to current project or for all tenants. - :param is_soft_deleted: bool -- whether to list shares that has - been soft deleted to recycle bin. - :param filters: dict -- filters for listing of shares. - Example, input: - {'project_id': 'foo'} - {-'project_id': 'foo'} - {--'project_id': 'foo'} - {'project-id': 'foo'} - will be transformed to filter parameter "--project-id=foo" - :param columns: comma separated string of columns. - Example, "--columns Name,Size" - :param is_public: bool -- should list public shares or not. - Default is False. - :param microversion: str -- the request api version. - """ - cmd = 'list ' - if all_tenants: - cmd += '--all-tenants ' - if is_public: - cmd += '--public ' - if is_soft_deleted: - cmd += '--soft-deleted ' - if filters and isinstance(filters, dict): - for k, v in filters.items(): - cmd += '%(k)s=%(v)s ' % { - 'k': self._stranslate_to_cli_optional_param(k), 'v': v} - if columns is not None: - cmd += '--columns ' + columns - shares_raw = self.manila(cmd, microversion=microversion) - shares = utils.listing(shares_raw) - return shares - - def list_share_instances(self, share_id=None, filters=None, - microversion=None): - """List share instances. - - :param share_id: ID of a share to filter by. - :param filters: dict -- filters for listing of shares. - Example, input: - {'project_id': 'foo'} - {-'project_id': 'foo'} - {--'project_id': 'foo'} - {'project-id': 'foo'} - will be transformed to filter parameter "--export-location=foo" - :param microversion: API microversion to be used for request. - """ - cmd = 'share-instance-list ' - if share_id: - cmd += '--share-id %s' % share_id - if filters and isinstance(filters, dict): - for k, v in filters.items(): - cmd += '%(k)s=%(v)s ' % { - 'k': self._stranslate_to_cli_optional_param(k), 'v': v} - share_instances_raw = self.manila(cmd, microversion=microversion) - share_instances = utils.listing(share_instances_raw) - return share_instances - - def is_share_deleted(self, share, microversion=None): - """Says whether share is deleted or not. - - :param share: str -- Name or ID of share - """ - try: - self.get_share(share, microversion=microversion) - return False - except tempest_lib_exc.NotFound: - return True - - def wait_for_share_deletion(self, share, microversion=None): - """Wait for share deletion by its Name or ID. - - :param share: str -- Name or ID of share - """ - self.wait_for_resource_deletion( - SHARE, res_id=share, interval=5, timeout=300, - microversion=microversion) - - def is_share_transfer_deleted(self, transfer, microversion=None): - """Says whether transfer is deleted or not. - - :param transfer: str -- Name or ID of transfer - """ - try: - self.get_transfer(transfer, microversion=microversion) - return False - except tempest_lib_exc.NotFound: - return True - - def wait_for_transfer_deletion(self, transfer, microversion=None): - """Wait for transfer deletion by its Name or ID. - - :param transfer: str -- Name or ID of transfer. - """ - self.wait_for_resource_deletion( - SHARE, res_id=transfer, interval=5, timeout=300, - microversion=microversion) - - def wait_for_share_soft_deletion(self, share_id, microversion=None): - body = self.get_share(share_id, microversion=microversion) - is_soft_deleted = body['is_soft_deleted'] - start = int(time.time()) - - while is_soft_deleted == "False": - time.sleep(self.build_interval) - body = self.get_share(share_id, microversion=microversion) - is_soft_deleted = body['is_soft_deleted'] - - if is_soft_deleted == "True": - return - - if int(time.time()) - start >= self.build_timeout: - message = ("Share %(share_id)s failed to be soft deleted " - "within the required time %(build_timeout)s." % - {"share_id": share_id, - "build_timeout": self.build_timeout}) - raise tempest_lib_exc.TimeoutException(message) - - def wait_for_share_restore(self, share_id, microversion=None): - body = self.get_share(share_id, microversion=microversion) - is_soft_deleted = body['is_soft_deleted'] - start = int(time.time()) - - while is_soft_deleted == "True": - time.sleep(self.build_interval) - body = self.get_share(share_id, microversion=microversion) - is_soft_deleted = body['is_soft_deleted'] - - if is_soft_deleted == "False": - return - - if int(time.time()) - start >= self.build_timeout: - message = ("Share %(share_id)s failed to be restored " - "within the required time %(build_timeout)s." % - {"share_id": share_id, - "build_timeout": self.build_timeout}) - raise tempest_lib_exc.TimeoutException(message) - - def wait_for_resource_status(self, resource_id, status, microversion=None, - resource_type="share"): - """Waits for a share to reach a given status.""" - get_func = getattr(self, 'get_' + resource_type) - body = get_func(resource_id, microversion=microversion) - share_status = body['status'] - start = int(time.time()) - - while share_status != status: - time.sleep(self.build_interval) - body = get_func(resource_id, microversion=microversion) - share_status = body['status'] - - if share_status == status: - return - elif 'error' in share_status.lower(): - raise exceptions.ShareBuildErrorException(share=resource_id) - - if int(time.time()) - start >= self.build_timeout: - message = ("Resource %(resource_id)s failed to reach " - "%(status)s status within the required time " - "(%(build_timeout)s)." % - {"resource_id": resource_id, "status": status, - "build_timeout": self.build_timeout}) - raise tempest_lib_exc.TimeoutException(message) - - def wait_for_migration_task_state(self, share_id, dest_host, - task_state_to_wait, microversion=None): - """Waits for a share to migrate to a certain host.""" - statuses = ((task_state_to_wait,) - if not isinstance(task_state_to_wait, (tuple, list, set)) - else task_state_to_wait) - share = self.get_share(share_id, microversion=microversion) - start = int(time.time()) - while share['task_state'] not in statuses: - time.sleep(self.build_interval) - share = self.get_share(share_id, microversion=microversion) - if share['task_state'] in statuses: - break - elif share['task_state'] == constants.TASK_STATE_MIGRATION_ERROR: - raise exceptions.ShareMigrationException( - share_id=share['id'], src=share['host'], dest=dest_host) - elif int(time.time()) - start >= self.build_timeout: - message = ('Share %(share_id)s failed to reach a status in' - '%(status)s when migrating from host %(src)s to ' - 'host %(dest)s within the required time ' - '%(timeout)s.' % { - 'src': share['host'], - 'dest': dest_host, - 'share_id': share['id'], - 'timeout': self.build_timeout, - 'status': str(statuses), - }) - raise tempest_lib_exc.TimeoutException(message) - return share - - @not_found_wrapper - def _set_share_metadata(self, share, data, update_all=False, - microversion=None): - """Sets a share metadata. - - :param share: str -- Name or ID of a share. - :param data: dict -- key-value pairs to set as metadata. - :param update_all: bool -- if set True then all keys except provided - will be deleted. - """ - if not (isinstance(data, dict) and data): - msg = ('Provided invalid data for setting of share metadata - ' - '%s' % data) - raise exceptions.InvalidData(message=msg) - if update_all: - cmd = 'metadata-update-all %s ' % share - else: - cmd = 'metadata %s set ' % share - for k, v in data.items(): - cmd += '%(k)s=%(v)s ' % {'k': k, 'v': v} - return self.manila(cmd, microversion=microversion) - - def update_all_share_metadata(self, share, data, microversion=None): - metadata_raw = self._set_share_metadata( - share, data, True, microversion=microversion) - metadata = output_parser.details(metadata_raw) - return metadata - - def set_share_metadata(self, share, data, microversion=None): - return self._set_share_metadata( - share, data, False, microversion=microversion) - - @not_found_wrapper - def unset_share_metadata(self, share, keys, microversion=None): - """Unsets some share metadata by keys. - - :param share: str -- Name or ID of a share - :param keys: str/list -- key or list of keys to unset. - """ - if not (isinstance(keys, list) and keys): - msg = ('Provided invalid data for unsetting of share metadata - ' - '%s' % keys) - raise exceptions.InvalidData(message=msg) - cmd = 'metadata %s unset ' % share - for key in keys: - cmd += '%s ' % key - return self.manila(cmd, microversion=microversion) - - @not_found_wrapper - def get_share_metadata(self, share, microversion=None): - """Returns list of all share metadata. - - :param share: str -- Name or ID of a share. - """ - metadata_raw = self.manila( - 'metadata-show %s' % share, microversion=microversion) - metadata = output_parser.details(metadata_raw) - return metadata - - def create_snapshot(self, share, name=None, description=None, - force=False, microversion=None): - """Creates a snapshot.""" - cmd = 'snapshot-create %(share)s ' % {'share': share} - if name is None: - name = data_utils.rand_name('autotest_snapshot_name') - cmd += '--name %s ' % name - if description is None: - description = data_utils.rand_name('autotest_snapshot_description') - cmd += '--description %s ' % description - if force: - cmd += '--force %s' % force - snapshot_raw = self.manila(cmd, microversion=microversion) - snapshot = output_parser.details(snapshot_raw) - return snapshot - - @not_found_wrapper - def get_snapshot(self, snapshot, microversion=None): - """Retrieves a snapshot by its Name or ID.""" - snapshot_raw = self.manila('snapshot-show %s' % snapshot, - microversion=microversion) - snapshot = output_parser.details(snapshot_raw) - return snapshot - - @not_found_wrapper - def list_snapshot_export_locations(self, snapshot, columns=None, - microversion=None): - """List snapshot export locations. - - :param snapshot: str -- Name or ID of a snapshot. - :param columns: str -- comma separated string of columns. - Example, "--columns uuid,path". - :param microversion: API microversion to be used for request. - """ - cmd = "snapshot-export-location-list %s" % snapshot - if columns is not None: - cmd += " --columns " + columns - export_locations_raw = self.manila(cmd, microversion=microversion) - export_locations = utils.listing(export_locations_raw) - return export_locations - - @not_found_wrapper - @forbidden_wrapper - def list_snapshot_instance_export_locations(self, snapshot_instance, - columns=None, - microversion=None): - """List snapshot instance export locations. - - :param snapshot_instance: str -- Name or ID of a snapshot instance. - :param columns: str -- comma separated string of columns. - Example, "--columns uuid,path". - :param microversion: API microversion to be used for request. - """ - cmd = "snapshot-instance-export-location-list %s" % snapshot_instance - if columns is not None: - cmd += " --columns " + columns - export_locations_raw = self.manila(cmd, microversion=microversion) - export_locations = utils.listing(export_locations_raw) - return export_locations - - @not_found_wrapper - @forbidden_wrapper - def delete_snapshot(self, snapshot, microversion=None): - """Deletes snapshot by Names or IDs.""" - return self.manila( - "snapshot-delete %s" % snapshot, microversion=microversion) - - def list_snapshot_instances(self, snapshot_id=None, columns=None, - detailed=None, microversion=None): - """List snapshot instances.""" - cmd = 'snapshot-instance-list ' - if snapshot_id: - cmd += '--snapshot %s' % snapshot_id - if columns is not None: - cmd += ' --columns ' + columns - if detailed: - cmd += ' --detailed True ' - snapshot_instances_raw = self.manila(cmd, microversion=microversion) - snapshot_instances = utils.listing(snapshot_instances_raw) - return snapshot_instances - - def get_snapshot_instance(self, id=None, microversion=None): - """Get snapshot instance.""" - cmd = 'snapshot-instance-show %s ' % id - snapshot_instance_raw = self.manila(cmd, microversion=microversion) - snapshot_instance = output_parser.details(snapshot_instance_raw) - return snapshot_instance - - def reset_snapshot_instance(self, id=None, state=None, microversion=None): - """Reset snapshot instance status.""" - cmd = 'snapshot-instance-reset-state %s ' % id - if state: - cmd += '--state %s' % state - snapshot_instance_raw = self.manila(cmd, microversion=microversion) - snapshot_instance = utils.listing(snapshot_instance_raw) - return snapshot_instance - - def is_snapshot_deleted(self, snapshot, microversion=None): - """Indicates whether snapshot is deleted or not. - - :param snapshot: str -- Name or ID of snapshot - """ - try: - self.get_snapshot(snapshot, microversion=microversion) - return False - except tempest_lib_exc.NotFound: - return True - - def wait_for_snapshot_deletion(self, snapshot, microversion=None): - """Wait for snapshot deletion by its Name or ID. - - :param snapshot: str -- Name or ID of snapshot - """ - self.wait_for_resource_deletion( - SNAPSHOT, res_id=snapshot, interval=5, timeout=300, - microversion=microversion) - - def wait_for_snapshot_status(self, snapshot, status, microversion=None): - """Waits for a snapshot to reach a given status.""" - body = self.get_snapshot(snapshot, microversion=microversion) - snapshot_name = body['name'] - snapshot_status = body['status'] - start = int(time.time()) - - while snapshot_status != status: - time.sleep(self.build_interval) - body = self.get_snapshot(snapshot, microversion=microversion) - snapshot_status = body['status'] - - if snapshot_status == status: - return - elif 'error' in snapshot_status.lower(): - raise exceptions.SnapshotBuildErrorException(snapshot=snapshot) - - if int(time.time()) - start >= self.build_timeout: - message = ( - "Snapshot %(snapshot_name)s failed to reach %(status)s " - "status within the required time (%(timeout)s s)." % { - "snapshot_name": snapshot_name, "status": status, - "timeout": self.build_timeout}) - raise tempest_lib_exc.TimeoutException(message) - - @not_found_wrapper - def list_access(self, entity_id, columns=None, microversion=None, - is_snapshot=False, metadata=None): - """Returns list of access rules for a share. - - :param entity_id: str -- Name or ID of a share or snapshot. - :param columns: comma separated string of columns. - Example, "--columns access_type,access_to" - :param is_snapshot: Boolean value to determine if should list - access of a share or snapshot. - """ - if is_snapshot: - cmd = 'snapshot-access-list %s ' % entity_id - else: - cmd = 'access-list %s ' % entity_id - if columns is not None: - cmd += ' --columns ' + columns - if metadata: - metadata_cli = '' - for k, v in metadata.items(): - metadata_cli += '%(k)s=%(v)s ' % {'k': k, 'v': v} - if metadata_cli: - cmd += ' --metadata %s ' % metadata_cli - access_list_raw = self.manila(cmd, microversion=microversion) - return output_parser.listing(access_list_raw) - - @not_found_wrapper - def get_access(self, share_id, access_id, microversion=None, - is_snapshot=False): - for access in self.list_access(share_id, microversion=microversion, - is_snapshot=is_snapshot): - if access['id'] == access_id: - return access - raise tempest_lib_exc.NotFound() - - @not_found_wrapper - def access_show(self, access_id, microversion=None): - raw_access = self.manila("access-show %s" % access_id, - microversion=microversion) - return output_parser.details(raw_access) - - @not_found_wrapper - def access_set_metadata(self, access_id, metadata, microversion=None): - if not (isinstance(metadata, dict) and metadata): - msg = ('Provided invalid metadata for setting of access rule' - ' metadata - %s' % metadata) - raise exceptions.InvalidData(message=msg) - cmd = "access-metadata %s set " % access_id - for k, v in metadata.items(): - cmd += '%(k)s=%(v)s ' % {'k': k, 'v': v} - return self.manila(cmd, microversion=microversion) - - @not_found_wrapper - def access_unset_metadata(self, access_id, keys, microversion=None): - if not (isinstance(keys, (list, tuple, set)) and keys): - raise exceptions.InvalidData( - message='Provided invalid keys - %s' % keys) - cmd = 'access-metadata %s unset ' % access_id - for key in keys: - cmd += '%s ' % key - return self.manila(cmd, microversion=microversion) - - @not_found_wrapper - def snapshot_access_allow(self, snapshot_id, access_type, access_to, - microversion=None): - raw_access = self.manila( - 'snapshot-access-allow %(id)s %(type)s %(access_to)s' % { - 'id': snapshot_id, - 'type': access_type, - 'access_to': access_to, - }, - microversion=microversion) - return output_parser.details(raw_access) - - @not_found_wrapper - def snapshot_access_deny(self, snapshot_id, access_id, microversion=None): - return self.manila( - 'snapshot-access-deny %(share_id)s %(access_id)s' % { - 'share_id': snapshot_id, - 'access_id': access_id, - }, - microversion=microversion) - - @not_found_wrapper - def access_allow(self, share_id, access_type, access_to, access_level, - metadata=None, microversion=None): - cmd = ('access-allow --access-level %(level)s %(id)s %(type)s ' - '%(access_to)s' % { - 'level': access_level, - 'id': share_id, - 'type': access_type, - 'access_to': access_to}) - if metadata: - metadata_cli = '' - for k, v in metadata.items(): - metadata_cli += '%(k)s=%(v)s ' % {'k': k, 'v': v} - if metadata_cli: - cmd += ' --metadata %s ' % metadata_cli - raw_access = self.manila(cmd, microversion=microversion) - return output_parser.details(raw_access) - - @not_found_wrapper - def access_deny(self, share_id, access_id, microversion=None): - return self.manila( - 'access-deny %(share_id)s %(access_id)s' % { - 'share_id': share_id, - 'access_id': access_id, - }, - microversion=microversion) - - def wait_for_access_rule_status(self, share_id, access_id, state='active', - microversion=None, is_snapshot=False): - access = self.get_access( - share_id, access_id, microversion=microversion, - is_snapshot=is_snapshot) - - start = int(time.time()) - while access['state'] != state: - time.sleep(self.build_interval) - access = self.get_access( - share_id, access_id, microversion=microversion, - is_snapshot=is_snapshot) - - if access['state'] == state: - return - elif access['state'] == 'error': - raise exceptions.AccessRuleCreateErrorException( - access=access_id) - - if int(time.time()) - start >= self.build_timeout: - message = ( - "Access rule %(access)s failed to reach %(state)s state " - "within the required time (%(build_timeout)s s)." % { - "access": access_id, "state": state, - "build_timeout": self.build_timeout}) - raise tempest_lib_exc.TimeoutException(message) - - def wait_for_access_rule_deletion(self, share_id, access_id, - microversion=None, is_snapshot=False): - try: - access = self.get_access( - share_id, access_id, microversion=microversion, - is_snapshot=is_snapshot) - except tempest_lib_exc.NotFound: - return - - start = int(time.time()) - while True: - time.sleep(self.build_interval) - try: - access = self.get_access( - share_id, access_id, microversion=microversion, - is_snapshot=is_snapshot) - except tempest_lib_exc.NotFound: - return - - if access['state'] == 'error': - raise exceptions.AccessRuleDeleteErrorException( - access=access_id) - - if int(time.time()) - start >= self.build_timeout: - message = ( - "Access rule %(access)s failed to reach deleted state " - "within the required time (%(timeout)s s)." % - {"access": access_id, "timeout": self.build_timeout}) - raise tempest_lib_exc.TimeoutException(message) - - def reset_task_state(self, share_id, state, version=None): - state = '--task_state %s' % state if state else '' - return self.manila('reset-task-state %(state)s %(share)s' % { - 'state': state, - 'share': share_id, - }, microversion=version) - - def migration_start(self, share_id, dest_host, writable, nondisruptive, - preserve_metadata, preserve_snapshots, - force_host_assisted_migration, new_share_network=None, - new_share_type=None): - cmd = ('migration-start %(share)s %(host)s ' - '--writable %(writable)s --nondisruptive %(nondisruptive)s ' - '--preserve-metadata %(preserve_metadata)s ' - '--preserve-snapshots %(preserve_snapshots)s') % { - 'share': share_id, - 'host': dest_host, - 'writable': writable, - 'nondisruptive': nondisruptive, - 'preserve_metadata': preserve_metadata, - 'preserve_snapshots': preserve_snapshots, - } - if force_host_assisted_migration: - cmd += (' --force-host-assisted-migration %s' - % force_host_assisted_migration) - if new_share_network: - cmd += ' --new-share-network %s' % new_share_network - if new_share_type: - cmd += ' --new-share-type %s' % new_share_type - return self.manila(cmd) - - def migration_complete(self, share_id): - return self.manila('migration-complete %s' % share_id) - - def migration_cancel(self, share_id): - return self.manila('migration-cancel %s' % share_id) - - def migration_get_progress(self, share_id): - result = self.manila('migration-get-progress %s' % share_id) - return output_parser.details(result) - - def pool_list(self, detail=False): - cmd = 'pool-list' - if detail: - cmd += ' --column name,host,backend,pool,capabilities' - response = self.manila(cmd) - return output_parser.listing(response) - - def create_security_service(self, type='ldap', name=None, description=None, - dns_ip=None, ou=None, server=None, domain=None, - user=None, password=None, default_ad_site=None, - microversion=None): - """Creates security service. - - :param type: security service type (ldap, kerberos or active_directory) - :param name: desired name of new security service. - :param description: desired description of new security service. - :param dns_ip: DNS IP address inside tenant's network. - :param ou: security service organizational unit - :param server: security service IP address or hostname. - :param domain: security service domain. - :param user: user of the new security service. - :param password: password used by user. - :param default_ad_site: default AD site - """ - - cmd = 'security-service-create %s ' % type - cmd += self. _combine_security_service_data( - name=name, - description=description, - dns_ip=dns_ip, - ou=ou, - server=server, - domain=domain, - user=user, - password=password, - default_ad_site=default_ad_site) - - ss_raw = self.manila(cmd, microversion=microversion) - security_service = output_parser.details(ss_raw) - return security_service - - @not_found_wrapper - def update_security_service(self, security_service, name=None, - description=None, dns_ip=None, ou=None, - server=None, domain=None, user=None, - password=None, default_ad_site=None, - microversion=None): - cmd = 'security-service-update %s ' % security_service - cmd += self. _combine_security_service_data( - name=name, - description=description, - dns_ip=dns_ip, - ou=ou, - server=server, - domain=domain, - user=user, - password=password, - default_ad_site=default_ad_site) - return output_parser.details( - self.manila(cmd, microversion=microversion)) - - def _combine_security_service_data(self, name=None, description=None, - dns_ip=None, ou=None, server=None, - domain=None, user=None, password=None, - default_ad_site=None): - data = '' - if name is not None: - data += '--name %s ' % name - if description is not None: - data += '--description %s ' % description - if dns_ip is not None: - data += '--dns-ip %s ' % dns_ip - if ou is not None: - data += '--ou %s ' % ou - if server is not None: - data += '--server %s ' % server - if domain is not None: - data += '--domain %s ' % domain - if user is not None: - data += '--user %s ' % user - if password is not None: - data += '--password %s ' % password - if default_ad_site is not None: - data += '--default-ad-site %s ' % default_ad_site - return data - - @not_found_wrapper - def list_share_export_locations(self, share, columns=None, - microversion=None): - """List share export locations. - - :param share: str -- Name or ID of a share. - :param columns: str -- comma separated string of columns. - Example, "--columns uuid,path". - :param microversion: API microversion to be used for request. - """ - cmd = "share-export-location-list %s" % share - if columns is not None: - cmd += " --columns " + columns - export_locations_raw = self.manila(cmd, microversion=microversion) - export_locations = utils.listing(export_locations_raw) - return export_locations - - @not_found_wrapper - def get_snapshot_export_location(self, snapshot, export_location_uuid, - microversion=None): - """Returns an export location by snapshot and its UUID. - - :param snapshot: str -- Name or ID of a snapshot. - :param export_location_uuid: str -- UUID of an export location. - :param microversion: API microversion to be used for request. - """ - snapshot_raw = self.manila( - 'snapshot-export-location-show %(snapshot)s %(el_uuid)s' % { - 'snapshot': snapshot, - 'el_uuid': export_location_uuid, - }, - microversion=microversion) - snapshot = output_parser.details(snapshot_raw) - return snapshot - - @not_found_wrapper - def get_snapshot_instance_export_location( - self, snapshot, export_location_uuid, microversion=None): - """Returns an export location by snapshot instance and its UUID. - - :param snapshot: str -- Name or ID of a snapshot instance. - :param export_location_uuid: str -- UUID of an export location. - :param microversion: API microversion to be used for request. - """ - snapshot_raw = self.manila( - 'snapshot-instance-export-location-show %(snapshot)s %(el_uuid)s' - % {'snapshot': snapshot, 'el_uuid': export_location_uuid}, - microversion=microversion) - snapshot = output_parser.details(snapshot_raw) - return snapshot - - @not_found_wrapper - def get_share_export_location(self, share, export_location_uuid, - microversion=None): - """Returns an export location by share and its UUID. - - :param share: str -- Name or ID of a share. - :param export_location_uuid: str -- UUID of an export location. - :param microversion: API microversion to be used for request. - """ - share_raw = self.manila( - 'share-export-location-show %(share)s %(el_uuid)s' % { - 'share': share, - 'el_uuid': export_location_uuid, - }, - microversion=microversion) - share = output_parser.details(share_raw) - return share - - @not_found_wrapper - @forbidden_wrapper - def list_share_instance_export_locations(self, share_instance, - columns=None, microversion=None): - """List share instance export locations. - - :param share_instance: str -- Name or ID of a share instance. - :param columns: str -- comma separated string of columns. - Example, "--columns uuid,path". - :param microversion: API microversion to be used for request. - """ - cmd = "share-instance-export-location-list %s" % share_instance - if columns is not None: - cmd += " --columns " + columns - export_locations_raw = self.manila(cmd, microversion=microversion) - export_locations = utils.listing(export_locations_raw) - return export_locations - - @not_found_wrapper - @forbidden_wrapper - def get_share_instance_export_location(self, share_instance, - export_location_uuid, - microversion=None): - """Returns an export location by share instance and its UUID. - - :param share_instance: str -- Name or ID of a share instance. - :param export_location_uuid: str -- UUID of an export location. - :param microversion: API microversion to be used for request. - """ - share_raw = self.manila( - 'share-instance-export-location-show ' - '%(share_instance)s %(el_uuid)s' % { - 'share_instance': share_instance, - 'el_uuid': export_location_uuid, - }, - microversion=microversion) - share = output_parser.details(share_raw) - return share - - # Share servers - - @not_found_wrapper - def get_share_server(self, share_server, microversion=None): - """Returns share server by its Name or ID.""" - share_server_raw = self.manila( - 'share-server-show %s' % share_server, microversion=microversion) - share_server = output_parser.details(share_server_raw) - return share_server - - def list_share_servers(self, filters=None, columns=None, - microversion=None): - """List share servers. - - :param filters: dict -- filters for listing of share servers. - Example, input: - {'project_id': 'foo'} - {'-project_id': 'foo'} - {'--project_id': 'foo'} - {'project-id': 'foo'} - will be transformed to filter parameter "--project-id=foo" - :param columns: comma separated string of columns. - Example, "--columns id" - """ - cmd = 'share-server-list ' - if columns is not None: - cmd += ' --columns ' + columns - if filters and isinstance(filters, dict): - for k, v in filters.items(): - cmd += '%(k)s=%(v)s ' % { - 'k': self._stranslate_to_cli_optional_param(k), 'v': v} - share_servers_raw = self.manila(cmd, microversion=microversion) - share_servers = utils.listing(share_servers_raw) - return share_servers - - @not_found_wrapper - def delete_share_server(self, share_server, microversion=None): - """Deletes share server by its Name or ID.""" - return self.manila('share-server-delete %s' % share_server, - microversion=microversion) - - def is_share_server_deleted(self, share_server_id, microversion=None): - """Says whether share server is deleted or not. - - :param share_server: text -- ID of the share server - """ - servers = self.list_share_servers(microversion=microversion) - for list_element in servers: - if share_server_id == list_element['Id']: - return False - return True - - def wait_for_share_server_deletion(self, share_server, microversion=None): - """Wait for share server deletion by its Name or ID. - - :param share_server: text -- Name or ID of share server - """ - self.wait_for_resource_deletion( - SHARE_SERVER, res_id=share_server, interval=3, timeout=60, - microversion=microversion) - - def unmanage_share(self, server_id): - return self.manila('unmanage %s ' % server_id) - - def unmanage_server(self, share_server_id): - return self.manila('share-server-unmanage %s ' % share_server_id) - - def share_server_manage(self, host, share_network, identifier, - driver_options=None): - if driver_options: - command = ('share-server-manage %s %s %s %s' % - (host, share_network, identifier, driver_options)) - else: - command = ('share-server-manage %s %s %s' % (host, share_network, - identifier)) - managed_share_server_raw = self.manila(command) - managed_share_server = output_parser.details(managed_share_server_raw) - return managed_share_server['id'] - - def manage_share(self, host, protocol, export_location, share_server): - managed_share_raw = self.manila( - 'manage %s %s %s --share-server-id %s' % (host, protocol, - export_location, - share_server)) - managed_share = output_parser.details(managed_share_raw) - return managed_share['id'] - - def share_server_migration_check(self, server_id, dest_host, writable, - nondisruptive, preserve_snapshots, - new_share_network=None): - cmd = ('share-server-migration-check %(server_id)s %(host)s ' - '--writable %(writable)s --nondisruptive %(nondisruptive)s ' - '--preserve-snapshots %(preserve_snapshots)s') % { - 'server_id': server_id, - 'host': dest_host, - 'writable': writable, - 'nondisruptive': nondisruptive, - 'preserve_snapshots': preserve_snapshots, - } - if new_share_network: - cmd += ' --new-share-network %s' % new_share_network - result = self.manila(cmd) - return output_parser.details(result) - - def share_server_migration_start(self, server_id, dest_host, - writable=False, nondisruptive=False, - preserve_snapshots=False, - new_share_network=None): - cmd = ('share-server-migration-start %(server_id)s %(host)s ' - '--writable %(writable)s --nondisruptive %(nondisruptive)s ' - '--preserve-snapshots %(preserve_snapshots)s') % { - 'server_id': server_id, - 'host': dest_host, - 'writable': writable, - 'nondisruptive': nondisruptive, - 'preserve_snapshots': preserve_snapshots, - } - if new_share_network: - cmd += ' --new-share-network %s' % new_share_network - return self.manila(cmd) - - def share_server_migration_complete(self, server_id): - return self.manila('share-server-migration-complete %s' % server_id) - - def share_server_migration_cancel(self, server_id): - return self.manila('share-server-migration-cancel %s' % server_id) - - def share_server_migration_get_progress(self, server_id): - result = self.manila('share-server-migration-get-progress %s' - % server_id) - return output_parser.details(result) - - def wait_for_server_migration_task_state(self, share_server_id, dest_host, - task_state_to_wait, - microversion=None): - """Waits for a certain server task state. """ - statuses = ((task_state_to_wait,) - if not isinstance(task_state_to_wait, (tuple, list, set)) - else task_state_to_wait) - server = self.get_share_server(share_server=share_server_id, - microversion=microversion) - start = int(time.time()) - while server['task_state'] not in statuses: - time.sleep(self.build_interval) - server = self.get_share_server(share_server=share_server_id, - microversion=microversion) - if server['task_state'] in statuses: - return server - elif server['task_state'] == constants.TASK_STATE_MIGRATION_ERROR: - raise exceptions.ShareServerMigrationException( - server_id=server['id']) - elif int(time.time()) - start >= self.build_timeout: - message = ('Server %(share_server_id)s failed to reach the ' - 'status in %(status)s while migrating from host ' - '%(src)s to host %(dest)s within the required time ' - '%(timeout)s.' % { - 'src': server['host'], - 'dest': dest_host, - 'share_server_id': server['id'], - 'timeout': self.build_timeout, - 'status': str(statuses), - }) - raise tempest_lib_exc.TimeoutException(message) - - # user messages - - def wait_for_message(self, resource_id): - """Waits until a message for a resource with given id exists""" - start = int(time.time()) - message = None - - while not message: - time.sleep(self.build_interval) - for msg in self.list_messages(): - if msg['Resource ID'] == resource_id: - return msg - - if int(time.time()) - start >= self.build_timeout: - message = ('No message for resource with id %s was created in' - ' the required time (%s s).' % - (resource_id, self.build_timeout)) - raise tempest_lib_exc.TimeoutException(message) - - def list_messages(self, columns=None, microversion=None): - """List messages. - - :param columns: str -- comma separated string of columns. - Example, "--columns id,resource_id". - :param microversion: API microversion to be used for request. - """ - cmd = "message-list" - if columns is not None: - cmd += " --columns " + columns - messages_raw = self.manila(cmd, microversion=microversion) - messages = utils.listing(messages_raw) - return messages - - @not_found_wrapper - def get_message(self, message, microversion=None): - """Returns share server by its Name or ID.""" - message_raw = self.manila( - 'message-show %s' % message, microversion=microversion) - message = output_parser.details(message_raw) - return message - - @not_found_wrapper - def delete_message(self, message, microversion=None): - """Deletes message by its ID.""" - return self.manila('message-delete %s' % message, - microversion=microversion) - - def is_message_deleted(self, message, microversion=None): - """Indicates whether message is deleted or not. - - :param message: str -- ID of message - """ - try: - self.get_message(message, microversion=microversion) - return False - except tempest_lib_exc.NotFound: - return True - - def wait_for_message_deletion(self, message, microversion=None): - """Wait for message deletion by its ID. - - :param message: text -- ID of message - """ - self.wait_for_resource_deletion( - MESSAGE, res_id=message, interval=3, timeout=60, - microversion=microversion) - - # Share replicas - - def create_share_replica(self, share, availability_zone=None, - share_network=None, microversion=None): - """Create a share replica. - - :param share: str -- Name or ID of a share to create a replica of - """ - cmd = "share-replica-create %s" % share - if availability_zone is not None: - cmd += " --availability_zone " + availability_zone - if share_network is not None: - cmd += " --share_network " + share_network - - replica = self.manila(cmd, microversion=microversion) - return output_parser.details(replica) - - @not_found_wrapper - def get_share_replica(self, replica, microversion=None): - cmd = "share-replica-show %s" % replica - replica = self.manila(cmd, microversion=microversion) - return output_parser.details(replica) - - @not_found_wrapper - @forbidden_wrapper - def delete_share_replica(self, share_replica, microversion=None): - """Deletes share replica by ID.""" - return self.manila( - "share-replica-delete %s" % share_replica, - microversion=microversion) - - def is_share_replica_deleted(self, replica, microversion=None): - """Indicates whether a share replica is deleted or not. - - :param replica: str -- ID of share replica - """ - try: - self.get_share_replica(replica, microversion=microversion) - return False - except tempest_lib_exc.NotFound: - return True - - def wait_for_share_replica_deletion(self, replica, microversion=None): - """Wait for share replica deletion by its ID. - - :param replica: text -- ID of share replica - """ - self.wait_for_resource_deletion( - SHARE_REPLICA, res_id=replica, interval=3, timeout=60, - microversion=microversion) - - def wait_for_share_replica_status(self, share_replica, - status="available", - microversion=None): - """Waits for a share replica to reach a given status.""" - replica = self.get_share_replica(share_replica, - microversion=microversion) - share_replica_status = replica['status'] - start = int(time.time()) - - while share_replica_status != status: - time.sleep(self.build_interval) - replica = self.get_share_replica(share_replica, - microversion=microversion) - share_replica_status = replica['status'] - - if share_replica_status == status: - return replica - elif 'error' in share_replica_status.lower(): - raise exceptions.ShareReplicaBuildErrorException( - replica=share_replica) - - if int(time.time()) - start >= self.build_timeout: - message = ( - "Share replica %(id)s failed to reach %(status)s " - "status within the required time " - "(%(build_timeout)s s)." % { - "id": share_replica, "status": status, - "build_timeout": self.build_timeout}) - raise tempest_lib_exc.TimeoutException(message) - return replica - - @not_found_wrapper - @forbidden_wrapper - def list_share_replica_export_locations(self, share_replica, - columns=None, microversion=None): - """List share replica export locations. - - :param share_replica: str -- ID of share replica. - :param columns: str -- comma separated string of columns. - Example, "--columns id,path". - :param microversion: API microversion to be used for request. - """ - cmd = "share-replica-export-location-list %s" % share_replica - if columns is not None: - cmd += " --columns " + columns - export_locations_raw = self.manila(cmd, microversion=microversion) - export_locations = utils.listing(export_locations_raw) - return export_locations - - @not_found_wrapper - @forbidden_wrapper - def get_share_replica_export_location(self, share_replica, - export_location_uuid, - microversion=None): - """Returns an export location by share replica and export location ID. - - :param share_replica: str -- ID of share replica. - :param export_location_uuid: str -- UUID of an export location. - :param microversion: API microversion to be used for request. - """ - export_raw = self.manila( - 'share-replica-export-location-show ' - '%(share_replica)s %(el_uuid)s' % { - 'share_replica': share_replica, - 'el_uuid': export_location_uuid, - }, - microversion=microversion) - export = output_parser.details(export_raw) - return export diff --git a/manilaclient/tests/functional/exceptions.py b/manilaclient/tests/functional/exceptions.py index fd96a4da..e6398f99 100644 --- a/manilaclient/tests/functional/exceptions.py +++ b/manilaclient/tests/functional/exceptions.py @@ -45,8 +45,9 @@ class ShareBuildErrorException(exceptions.TempestException): class ShareReplicaBuildErrorException(exceptions.TempestException): - message = ("Share replica %(replica)s failed to build and is in ERROR " - "status.") + message = ( + "Share replica %(replica)s failed to build and is in ERROR status." + ) class SnapshotBuildErrorException(exceptions.TempestException): @@ -62,9 +63,11 @@ class AccessRuleDeleteErrorException(exceptions.TempestException): class ShareMigrationException(exceptions.TempestException): - message = ("Share %(share_id)s failed to migrate from " - "host %(src)s to host %(dest)s.") + message = ( + "Share %(share_id)s failed to migrate from " + "host %(src)s to host %(dest)s." + ) class ShareServerMigrationException(exceptions.TempestException): - message = ("Share server %(server_id)s failed to migrate.") + message = "Share server %(server_id)s failed to migrate." diff --git a/manilaclient/tests/functional/osc/base.py b/manilaclient/tests/functional/osc/base.py index d396657a..92c34a1a 100644 --- a/manilaclient/tests/functional/osc/base.py +++ b/manilaclient/tests/functional/osc/base.py @@ -36,7 +36,7 @@ def get_admin_client(cls): project_domain_name=CONF.admin_project_domain_name or None, project_domain_id=CONF.admin_project_domain_id or None, user_domain_name=CONF.admin_user_domain_name or None, - user_domain_id=CONF.admin_user_domain_id or None + user_domain_id=CONF.admin_user_domain_id or None, ) return admin_client @@ -52,7 +52,7 @@ def get_user_client(cls): project_domain_name=CONF.project_domain_name or None, project_domain_id=CONF.project_domain_id or None, user_domain_name=CONF.user_domain_name or None, - user_domain_id=CONF.user_domain_id or None + user_domain_id=CONF.user_domain_id or None, ) return user_client @@ -79,53 +79,79 @@ def _get_property_from_output(self, output): obj[item['Field']] = str(item['Value']) return obj - def _wait_for_object_status(self, object_name, object_id, status, - timeout=CONF.build_timeout, - interval=CONF.build_interval): + def _wait_for_object_status( + self, + object_name, + object_id, + status, + timeout=CONF.build_timeout, + interval=CONF.build_interval, + ): """Waits for a object to reach a given status.""" start_time = time.time() while time.time() - start_time < timeout: - if status == self.openstack( - '%(obj)s show -c status -f value %(id)s' - % {'obj': object_name, - 'id': object_id}).rstrip(): + if ( + status + == self.openstack( + f'{object_name} show -c status -f value {object_id}' + ).rstrip() + ): break time.sleep(interval) else: - self.fail("%s %s did not reach status %s after %d seconds." - % (object_name, object_id, status, timeout)) + self.fail( + f"{object_name} {object_id} did not reach status {status} " + f"after {timeout} seconds." + ) - def check_object_deleted(self, object_name, object_id, - timeout=CONF.build_timeout, - interval=CONF.build_interval): + def check_object_deleted( + self, + object_name, + object_id, + timeout=CONF.build_timeout, + interval=CONF.build_interval, + ): """Check that object deleted successfully""" - cmd = '%s list -c ID -f value' % object_name + cmd = f'{object_name} list -c ID -f value' start_time = time.time() while time.time() - start_time < timeout: if object_id not in self.openstack(cmd): break time.sleep(interval) else: - self.fail("%s %s not deleted after %d seconds." - % (object_name, object_id, timeout)) + self.fail( + f"{object_name} {object_id} not deleted after {timeout} " + f"seconds." + ) - def openstack(self, action, flags='', params='', fail_ok=False, - merge_stderr=False, client=None): + def openstack( + self, + action, + flags='', + params='', + fail_ok=False, + merge_stderr=False, + client=None, + ): """Executes openstack command for given action""" if '--os-share-api-version' not in flags: flags = ( - flags + '--os-share-api-version %s' - % CONF.max_api_microversion) + flags + f'--os-share-api-version {CONF.max_api_microversion}' + ) if client is None: client = self.admin_client - return client.openstack(action, flags=flags, params=params, - fail_ok=fail_ok, - merge_stderr=merge_stderr) + return client.openstack( + action, + flags=flags, + params=params, + fail_ok=fail_ok, + merge_stderr=merge_stderr, + ) def listing_result(self, object_name, command, client=None): """Returns output for the given command as list of dictionaries""" @@ -141,49 +167,61 @@ def dict_result(self, object_name, command, client=None): result_dict = self._get_property_from_output(output) return result_dict - def create_share(self, share_protocol=None, size=None, name=None, - snapshot_id=None, properties=None, share_network=None, - description=None, public=False, share_type=None, - availability_zone=None, share_group=None, - add_cleanup=True, client=None, wait=None, - wait_for_status='available'): - + def create_share( + self, + share_protocol=None, + size=None, + name=None, + snapshot_id=None, + properties=None, + share_network=None, + description=None, + public=False, + share_type=None, + availability_zone=None, + share_group=None, + add_cleanup=True, + client=None, + wait=None, + wait_for_status='available', + ): name = name or data_utils.rand_name('autotest_share_name') # share_type = dhss_false until we have implemented # share network commands for osc share_type = share_type or 'dhss_false' - cmd = ('create ' - '%(protocol)s %(size)s %(name)s %(desc)s %(public)s %(stype)s' - % {'protocol': share_protocol or 'NFS', - 'size': size or '1', - 'name': '--name %s' % name, - 'desc': '--description %s' % description, - 'public': '--public %s' % public, - 'stype': '--share-type %s' % share_type}) + cmd = 'create {protocol} {size} {name} {desc} {public} {stype}'.format( + protocol=share_protocol or 'NFS', + size=size or '1', + name=f'--name {name}', + desc=f'--description {description}', + public=f'--public {public}', + stype=f'--share-type {share_type}', + ) if snapshot_id: - cmd = cmd + ' --snapshot-id %s' % snapshot_id + cmd = cmd + f' --snapshot-id {snapshot_id}' if properties: for key, value in properties.items(): - cmd = (cmd + ' --property %(key)s=%(value)s' - % {'key': key, 'value': value}) + cmd = cmd + f' --property {key}={value}' if share_network: - cmd = cmd + ' --share-network %s' % share_network + cmd = cmd + f' --share-network {share_network}' if availability_zone: - cmd = cmd + ' --availability-zone %s' % availability_zone + cmd = cmd + f' --availability-zone {availability_zone}' if share_group: - cmd = cmd + ' --share-group %s' % share_group + cmd = cmd + f' --share-group {share_group}' if wait: cmd = cmd + ' --wait' share_object = self.dict_result('share', cmd, client=client) self._wait_for_object_status( - 'share', share_object['id'], wait_for_status) + 'share', share_object['id'], wait_for_status + ) if add_cleanup: self.addCleanup( - self.openstack, 'share delete %s --wait' % share_object['id'] + self.openstack, + 'share delete {} --wait'.format(share_object['id']), ) return share_object @@ -203,27 +241,37 @@ def list_pools(self, backend=None, host=None, pool=None, detail=False): return pools - def create_share_type(self, name=None, dhss=False, description=None, - snapshot_support=None, - create_share_from_snapshot_support=None, - revert_to_snapshot_support=False, - mount_snapshot_support=False, extra_specs={}, - public=True, add_cleanup=True, client=None, - formatter=None): - + def create_share_type( + self, + name=None, + dhss=False, + description=None, + snapshot_support=None, + create_share_from_snapshot_support=None, + revert_to_snapshot_support=False, + mount_snapshot_support=False, + extra_specs={}, + public=True, + add_cleanup=True, + client=None, + formatter=None, + ): name = name or data_utils.rand_name('autotest_share_type_name') - cmd = (f'create {name} {dhss} --public {public}') + cmd = f'create {name} {dhss} --public {public}' if description: cmd += f' --description {description}' if snapshot_support: cmd += f' --snapshot-support {snapshot_support}' if create_share_from_snapshot_support: - cmd += (' --create-share-from-snapshot-support ' - f'{create_share_from_snapshot_support}') + cmd += ( + ' --create-share-from-snapshot-support ' + f'{create_share_from_snapshot_support}' + ) if revert_to_snapshot_support: - cmd += (' --revert-to-snapshot-support ' - f' {revert_to_snapshot_support}') + cmd += ( + f' --revert-to-snapshot-support {revert_to_snapshot_support}' + ) if mount_snapshot_support: cmd += f' --mount-snapshot-support {mount_snapshot_support}' if extra_specs: @@ -259,13 +307,19 @@ def list_services(self, host=None, status=None, state=None, zone=None): services = self.listing_result('share', cmd) return services - def create_share_access_rule(self, share, access_type, - access_to, properties=None, - access_level=None, wait=False, - lock_visibility=False, - lock_deletion=False, - lock_reason=None, - add_cleanup=False): + def create_share_access_rule( + self, + share, + access_type, + access_to, + properties=None, + access_level=None, + wait=False, + lock_visibility=False, + lock_deletion=False, + lock_reason=None, + add_cleanup=False, + ): cmd = f'access create {share} {access_type} {access_to} ' if access_level: @@ -286,17 +340,23 @@ def create_share_access_rule(self, share, access_type, return access_rule def get_share_export_locations(self, share): - cmd = (f'export location list {share}') + cmd = f'export location list {share}' export_locations = json.loads(self.openstack(f'share {cmd} -f json')) return export_locations - def create_snapshot(self, share, name=None, - description=None, wait=True, force=None, - add_cleanup=True, client=None): - + def create_snapshot( + self, + share, + name=None, + description=None, + wait=True, + force=None, + add_cleanup=True, + client=None, + ): name = name or data_utils.rand_name('autotest_snapshot_name') - cmd = (f'snapshot create {share} --name {name} ') + cmd = f'snapshot create {share} --name {name} ' if description: cmd += f' --description {description}' @@ -310,24 +370,29 @@ def create_snapshot(self, share, name=None, if add_cleanup: self.addCleanup( self.openstack, - f'share snapshot delete {snapshot_object["id"]} --wait') + f'share snapshot delete {snapshot_object["id"]} --wait', + ) return snapshot_object def create_share_transfer(self, share, name=None, client=None): - name = name or data_utils.rand_name('autotest_share_transfer_name') - cmd = (f'transfer create {share} --name {name} ') + cmd = f'transfer create {share} --name {name} ' transfer_object = self.dict_result('share', cmd, client=client) return transfer_object - def create_share_network(self, neutron_net_id=None, - neutron_subnet_id=None, name=None, - description=None, availability_zone=None, - add_cleanup=True): + def create_share_network( + self, + neutron_net_id=None, + neutron_subnet_id=None, + name=None, + description=None, + availability_zone=None, + add_cleanup=True, + ): name = name or data_utils.rand_name('autotest_share_network_name') - cmd = (f'network create --name {name} --description {description}') + cmd = f'network create --name {name} --description {description}' if neutron_net_id: cmd = cmd + f' --neutron-net-id {neutron_net_id}' if neutron_subnet_id: @@ -337,52 +402,76 @@ def create_share_network(self, neutron_net_id=None, share_network_obj = self.dict_result('share', cmd) self._wait_for_object_status( - 'share network', share_network_obj['id'], 'active') + 'share network', share_network_obj['id'], 'active' + ) if add_cleanup: self.addCleanup( self.openstack, - f'share network delete {share_network_obj["id"]}' + f'share network delete {share_network_obj["id"]}', ) return share_network_obj - def create_share_replica(self, share, availability_zone=None, - share_network=None, wait=None, - add_cleanup=True): - cmd = (f'replica create {share}') + def create_share_replica( + self, + share, + availability_zone=None, + share_network=None, + wait=None, + properties=None, + add_cleanup=True, + ): + cmd = f'replica create {share}' if availability_zone: cmd = cmd + f' --availability-zone {availability_zone}' if wait: cmd = cmd + ' --wait' if share_network: - cmd = cmd + ' --share-network %s' % share_network + cmd = cmd + f' --share-network {share_network}' + if properties: + for key, value in properties.items(): + cmd = cmd + f' --property {key}={value}' replica_object = self.dict_result('share', cmd) self._wait_for_object_status( - 'share replica', replica_object['id'], 'available') + 'share replica', replica_object['id'], 'available' + ) if add_cleanup: self.addCleanup( - self.openstack, - f'share replica delete {replica_object["id"]} --wait' + self._delete_share_replica_and_wait, replica_object['id'] ) return replica_object + def _delete_share_replica_and_wait(self, replica_id): + """Delete a share replica and wait for it to be gone. + + Uses check_object_deleted (respects CONF.build_timeout) instead of + the CLI --wait flag which is limited to osc_lib's hardcoded 300s. + """ + self.openstack( + f'share replica delete {replica_id}', + fail_ok=True, + ) + self.check_object_deleted('share replica', replica_id) + def get_share_replica_export_locations(self, replica): - cmd = (f'replica export location list {replica}') + cmd = f'replica export location list {replica}' export_locations = self.listing_result('share', cmd) return export_locations - def create_share_group_type(self, name=None, share_types=None, - group_specs=None, public=True, - add_cleanup=True): - + def create_share_group_type( + self, + name=None, + share_types=None, + group_specs=None, + public=True, + add_cleanup=True, + ): name = name or data_utils.rand_name('autotest_share_group_types_name') share_types = share_types or 'None' - cmd = (f'group type create ' - f'{name} ' - f'{share_types} ') + cmd = f'group type create {name} {share_types} ' if group_specs: cmd = cmd + f' --group-specs {group_specs} ' @@ -394,27 +483,28 @@ def create_share_group_type(self, name=None, share_types=None, if add_cleanup: self.addCleanup( self.openstack, - 'share group type delete %s' % share_object['id']) + 'share group type delete {}'.format(share_object['id']), + ) return share_object def share_group_type_access_create(self, group_type, project): - cmd = (f'group type access create ' - f'{group_type} ' - f'{project} ') + cmd = f'group type access create {group_type} {project} ' self.dict_result('share', cmd) def share_group_type_access_delete(self, group_type, access_id): - cmd = (f'group type access delete ' - f'{group_type} ' - f'{access_id} ') + cmd = f'group type access delete {group_type} {access_id} ' self.dict_result('share', cmd) - def check_create_network_subnet(self, share_network, neutron_net_id=None, - neutron_subnet_id=None, - availability_zone=None, - restart_check=None): + def check_create_network_subnet( + self, + share_network, + neutron_net_id=None, + neutron_subnet_id=None, + availability_zone=None, + restart_check=None, + ): cmd = f'network subnet create {share_network} --check-only' if neutron_net_id: @@ -429,10 +519,15 @@ def check_create_network_subnet(self, share_network, neutron_net_id=None, check_result = self.dict_result('share', cmd) return check_result - def create_resource_lock(self, resource_id, resource_type='share', - resource_action='delete', lock_reason=None, - add_cleanup=True, client=None): - + def create_resource_lock( + self, + resource_id, + resource_type='share', + resource_action='delete', + lock_reason=None, + add_cleanup=True, + client=None, + ): cmd = f'lock create {resource_id} {resource_type}' cmd += f' --resource-action {resource_action}' @@ -442,17 +537,24 @@ def create_resource_lock(self, resource_id, resource_type='share', lock = self.dict_result('share', cmd, client=client) if add_cleanup: - self.addCleanup(self.openstack, - 'share lock delete %s' % lock['id'], - client=client) + self.addCleanup( + self.openstack, + 'share lock delete {}'.format(lock['id']), + client=client, + ) return lock - def create_backup(self, share_id, name=None, description=None, - backup_options=None, add_cleanup=True): - + def create_backup( + self, + share_id, + name=None, + description=None, + backup_options=None, + add_cleanup=True, + ): name = name or data_utils.rand_name('autotest_backup_name') - cmd = (f'backup create {share_id} ') + cmd = f'backup create {share_id} ' if name: cmd += f' --name {name}' @@ -466,11 +568,46 @@ def create_backup(self, share_id, name=None, description=None, backup_object = self.dict_result('share', cmd) self._wait_for_object_status( - 'share backup', backup_object['id'], 'available') + 'share backup', backup_object['id'], 'available' + ) if add_cleanup: self.addCleanup( self.openstack, - f'share backup delete {backup_object["id"]} --wait') + f'share backup delete {backup_object["id"]} --wait', + ) return backup_object + + def create_qos_type( + self, + name=None, + description=None, + specs=None, + add_cleanup=True, + client=None, + formatter=None, + ): + name = name or data_utils.rand_name('autotest_qos_type_name') + specs = specs or {} + + cmd = f'create {name} ' + if description: + cmd += f' --description {description}' + if specs: + q_specs = '' + for key, value in specs.items(): + q_specs += f' --spec {key}={value}' + cmd += q_specs + + if formatter == 'json': + cmd = f'share qos type {cmd} -f {formatter} ' + qos_type = json.loads(self.openstack(cmd, client=client)) + else: + qos_type = self.dict_result('share qos type', cmd, client=client) + + if add_cleanup: + self.addCleanup( + self.openstack, f'share qos type delete {qos_type["id"]}' + ) + return qos_type diff --git a/manilaclient/tests/functional/osc/test_availability_zones.py b/manilaclient/tests/functional/osc/test_availability_zones.py index 48717ad5..6c1c3305 100644 --- a/manilaclient/tests/functional/osc/test_availability_zones.py +++ b/manilaclient/tests/functional/osc/test_availability_zones.py @@ -15,13 +15,7 @@ class AvailabilityZonesCLITest(base.OSCClientTestBase): - def test_openstack_share_availability_zones_list(self): azs = self.listing_result('share', 'availability zone list') - self.assertTableStruct(azs, [ - 'Id', - 'Name', - 'Created At', - 'Updated At' - ]) + self.assertTableStruct(azs, ['Id', 'Name', 'Created At', 'Updated At']) self.assertTrue(len(azs) > 0) diff --git a/manilaclient/tests/functional/osc/test_messages.py b/manilaclient/tests/functional/osc/test_messages.py index 0e44d6b9..f9977991 100644 --- a/manilaclient/tests/functional/osc/test_messages.py +++ b/manilaclient/tests/functional/osc/test_messages.py @@ -11,48 +11,65 @@ # under the License. +from tempest.lib import exceptions + from manilaclient.tests.functional.osc import base class MessagesCLITest(base.OSCClientTestBase): - def setUp(self): - super(MessagesCLITest, self).setUp() + super().setUp() # cause a user message by using an invalid share type for provisioning st = self.create_share_type(extra_specs={'fake_key': 'fake_value'}) - self.share = self.create_share(share_type=st['name'], - wait_for_status='error', - client=self.user_client) + self.share = self.create_share( + share_type=st['name'], + wait_for_status='error', + client=self.user_client, + ) def test_list_and_show_messages(self): # Get all messages messages = self.listing_result( - 'share', 'message list', client=self.user_client) + 'share', 'message list', client=self.user_client + ) # We must have at least one message self.assertTrue(len(messages) > 0) - self.assertTableStruct(messages, [ - 'ID', - 'Resource Type', - 'Resource ID', - 'Action ID', - 'User Message', - 'Detail ID', - 'Created At', - ]) + self.assertTableStruct( + messages, + [ + 'ID', + 'Resource Type', + 'Resource ID', + 'Action ID', + 'User Message', + 'Detail ID', + 'Created At', + ], + ) # grab the message we created - message = [msg for msg in messages - if msg['Resource ID'] == self.share['id']] + message = [ + msg for msg in messages if msg['Resource ID'] == self.share['id'] + ] self.assertEqual(1, len(message)) - show_message = self.dict_result('share', - f'message show {message[0]["ID"]}') - self.addCleanup(self.openstack, - f'share message delete {show_message["id"]}') + show_message = self.dict_result( + 'share', f'message show {message[0]["ID"]}' + ) + self.addCleanup( + self.openstack, f'share message delete {show_message["id"]}' + ) self.assertEqual(message[0]['ID'], show_message['id']) expected_keys = ( - 'id', 'action_id', 'resource_id', 'detail_id', 'resource_type', - 'created_at', 'expires_at', 'message_level', 'user_message', + 'id', + 'action_id', + 'resource_id', + 'detail_id', + 'resource_type', + 'created_at', + 'expires_at', + 'message_level', + 'user_message', 'request_id', ) for key in expected_keys: @@ -64,40 +81,53 @@ def test_list_and_show_messages(self): filtered_messages = self.listing_result( 'share', f'message list --since {since} --before {before}', - client=self.user_client) + client=self.user_client, + ) self.assertTrue(len(filtered_messages) > 0) - self.assertIn(show_message['id'], - [m['ID'] for m in filtered_messages]) + self.assertIn(show_message['id'], [m['ID'] for m in filtered_messages]) # filtering by message level filtered_messages = self.listing_result( 'share', f'message list --message-level {show_message["message_level"]}', - client=self.user_client) + client=self.user_client, + ) self.assertTrue(len(filtered_messages) > 0) - self.assertIn(show_message['id'], - [m['ID'] for m in filtered_messages]) + self.assertIn(show_message['id'], [m['ID'] for m in filtered_messages]) # filtering by Resource ID filtered_messages = self.listing_result( 'share', f'message list --resource-id {self.share["id"]}', - client=self.user_client) + client=self.user_client, + ) self.assertEqual(1, len(filtered_messages)) self.assertEqual(show_message['resource_id'], self.share["id"]) def test_delete_message(self): messages = self.listing_result( - 'share', 'message list', client=self.user_client) - message = [msg for msg in messages - if msg['Resource ID'] == self.share['id']] + 'share', 'message list', client=self.user_client + ) + message = [ + msg for msg in messages if msg['Resource ID'] == self.share['id'] + ] self.assertEqual(1, len(message)) message = message[0] self.openstack(f'share message delete {message["ID"]}') messages = self.listing_result( - 'share', 'message list', client=self.user_client) - messages = [msg for msg in messages - if msg['ID'] == message["ID"]] + 'share', 'message list', client=self.user_client + ) + messages = [msg for msg in messages if msg['ID'] == message["ID"]] self.assertEqual(0, len(messages)) + + def test_delete_message_invalid_id(self): + self.assertRaises( + exceptions.CommandFailed, self.openstack, 'share message delete 0' + ) + + def test_show_message_missing_id(self): + self.assertRaises( + exceptions.CommandFailed, self.openstack, 'share message show' + ) diff --git a/manilaclient/tests/functional/osc/test_qos_types.py b/manilaclient/tests/functional/osc/test_qos_types.py new file mode 100644 index 00000000..83d61724 --- /dev/null +++ b/manilaclient/tests/functional/osc/test_qos_types.py @@ -0,0 +1,146 @@ +# Copyright (c) 2025 Cloudification GmbH. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import json + +from manilaclient.tests.functional.osc import base + + +class QosTypesCLITest(base.OSCClientTestBase): + def test_qos_type_create(self): + name = 'test_qos_type' + description = 'Description' + qos_type = self.create_qos_type(name=name, description=description) + + self.assertEqual(name, qos_type["name"]) + self.assertEqual(description, qos_type["description"]) + + qos_types_list = self.listing_result('share qos type', 'list') + self.assertIn(qos_type["id"], [item['ID'] for item in qos_types_list]) + + def test_qos_type_create_specs(self): + name = 'test_qos_type2' + qos_type = self.create_qos_type( + name=name, + specs={"foo": "bar", "manila": "gazpacho"}, + formatter='json', + ) + + specs = qos_type["specs"] + self.assertEqual("bar", specs["foo"]) + self.assertEqual("gazpacho", specs["manila"]) + + def test_qos_type_create_specs_using_command(self): + self.openstack( + 'share qos type create test_qos_type2_cli ' + '--description test_cli --spec foo1=bar1 --spec foo2=bar2' + ) + self.addCleanup( + self.openstack, 'share qos type delete test_qos_type2_cli' + ) + + qos_type = json.loads( + self.openstack('share qos type show test_qos_type2_cli -f json') + ) + + self.assertEqual('test_cli', qos_type["description"]) + self.assertEqual('bar1', qos_type["specs"]["foo1"]) + self.assertEqual('bar2', qos_type["specs"]["foo2"]) + + def test_qos_type_delete(self): + qos_type_1 = self.create_qos_type( + name='test_qos_type3', add_cleanup=False + ) + qos_type_2 = self.create_qos_type( + name='test_qos_type4', add_cleanup=False + ) + + self.openstack( + f'share qos type delete {qos_type_1["id"]} {qos_type_2["id"]}' + ) + + self.check_object_deleted('share qos type', qos_type_1["id"]) + self.check_object_deleted('share qos type', qos_type_2["id"]) + + def test_qos_type_set(self): + qos_type = self.create_qos_type(name='test_qos_type5') + + self.openstack( + f'share qos type set {qos_type["id"]} --description Description' + ' --spec foo=bar2' + ) + + qos_type = json.loads( + self.openstack(f'share qos type show {qos_type["id"]} -f json') + ) + + self.assertEqual('Description', qos_type["description"]) + self.assertEqual('bar2', qos_type["specs"]["foo"]) + + def test_qos_type_unset(self): + qos_type = self.create_qos_type( + name='test_qos_type6', specs={'foo': 'bar', 'foo1': 'bar1'} + ) + + self.openstack( + f'share qos type unset {qos_type["id"]} --spec foo --spec foo1' + ) + + qos_type = json.loads( + self.openstack(f'share qos type show {qos_type["id"]} -f json') + ) + + self.assertNotIn('foo', qos_type["specs"]) + self.assertNotIn('foo1', qos_type["specs"]) + + def test_qos_type_list(self): + qos_type_1 = self.create_qos_type(name='test_qos_type7') + qos_type_2 = self.create_qos_type( + name='test_qos_type8', specs={'foo': 'bar'} + ) + + types_list = self.listing_result( + 'share qos type', 'list', client=self.admin_client + ) + + self.assertTableStruct( + types_list, + [ + 'ID', + 'Name', + 'Description', + 'Specs', + ], + ) + id_list = [item['ID'] for item in types_list] + self.assertIn(qos_type_1['id'], id_list) + self.assertIn(qos_type_2['id'], id_list) + + types_list = self.listing_result('share qos type', 'list') + + id_list = [item['ID'] for item in types_list] + self.assertIn(qos_type_1['id'], id_list) + self.assertIn(qos_type_2['id'], id_list) + + def test_qos_type_show(self): + qos_type = self.create_qos_type( + name='test_qos_type10', specs={'foo': 'bar'} + ) + + result = json.loads( + self.openstack(f'share qos type show {qos_type["id"]} -f json') + ) + + self.assertEqual(qos_type["name"], result["name"]) + self.assertEqual('bar', result["specs"]["foo"]) diff --git a/manilaclient/tests/functional/osc/test_resource_locks.py b/manilaclient/tests/functional/osc/test_resource_locks.py index e7c9cd18..0be7dfa5 100644 --- a/manilaclient/tests/functional/osc/test_resource_locks.py +++ b/manilaclient/tests/functional/osc/test_resource_locks.py @@ -42,25 +42,26 @@ class ResourceLockTests(base.OSCClientTestBase): """Lock CLI test cases""" def setUp(self): - super(ResourceLockTests, self).setUp() + super().setUp() self.share_type = self.create_share_type( - name=data_utils.rand_name('lock_tests_type')) + name=data_utils.rand_name('lock_tests_type') + ) self.share = self.create_share(share_type=self.share_type['id']) def test_lock_create_show_use_delete(self): """Create a deletion lock on share, view it, try it and remove.""" - lock = self.create_resource_lock(self.share['id'], - lock_reason='tigers rule', - client=self.user_client, - add_cleanup=False) + lock = self.create_resource_lock( + self.share['id'], + lock_reason='tigers rule', + client=self.user_client, + add_cleanup=False, + ) client_user_id = self.openstack( - "token issue -c user_id -f value", - client=self.user_client + "token issue -c user_id -f value", client=self.user_client ).strip() client_project_id = self.openstack( - "token issue -c project_id -f value", - client=self.user_client + "token issue -c project_id -f value", client=self.user_client ).strip() self.assertEqual(self.share['id'], lock['resource_id']) @@ -75,60 +76,78 @@ def test_lock_create_show_use_delete(self): self.assertEqual(lock['lock_context'], lock_show['Lock Context']) # When a deletion lock exists, share deletion must fail - self.assertRaises(lib_exc.CommandFailed, - self.openstack, - f"share delete {self.share['id']}") + self.assertRaises( + lib_exc.CommandFailed, + self.openstack, + f"share delete {self.share['id']}", + ) # delete the lock, share will be deleted in cleanup stage - self.openstack(f"share lock delete {lock['id']}", - client=self.user_client) + self.openstack( + f"share lock delete {lock['id']}", client=self.user_client + ) - self.assertRaises(lib_exc.CommandFailed, - self.openstack, - f"share lock show {lock['id']}") + self.assertRaises( + lib_exc.CommandFailed, + self.openstack, + f"share lock show {lock['id']}", + ) def test_lock_list_filter_paginate(self): - lock_1 = self.create_resource_lock(self.share['id'], - lock_reason='tigers rule', - client=self.user_client) - lock_2 = self.create_resource_lock(self.share['id'], - lock_reason='tigers still rule', - client=self.user_client) - lock_3 = self.create_resource_lock(self.share['id'], - lock_reason='admins rule', - client=self.admin_client) - - locks = self.listing_result('share', - f'lock list --resource {self.share["id"]}') + lock_1 = self.create_resource_lock( + self.share['id'], + lock_reason='tigers rule', + client=self.user_client, + ) + lock_2 = self.create_resource_lock( + self.share['id'], + lock_reason='tigers still rule', + client=self.user_client, + ) + lock_3 = self.create_resource_lock( + self.share['id'], + lock_reason='admins rule', + client=self.admin_client, + ) + + locks = self.listing_result( + 'share', f'lock list --resource {self.share["id"]}' + ) self.assertEqual(3, len(locks)) - self.assertEqual(sorted(LOCK_SUMMARY_ATTRIBUTES), - sorted(locks[0].keys())) - - locks = self.listing_result('share', - 'lock list --lock-context user ' - f' --resource {self.share["id"]}') + self.assertEqual( + sorted(LOCK_SUMMARY_ATTRIBUTES), sorted(locks[0].keys()) + ) + + locks = self.listing_result( + 'share', + f'lock list --lock-context user --resource {self.share["id"]}', + ) self.assertEqual(2, len(locks)) self.assertNotIn(lock_3['id'], [lock['ID'] for lock in locks]) - locks = self.listing_result('share', - 'lock list --lock-context user' - f' --resource {self.share["id"]}' - ' --sort-key created_at ' - ' --sort-dir desc ' - ' --limit 1') + locks = self.listing_result( + 'share', + 'lock list --lock-context user' + f' --resource {self.share["id"]}' + ' --sort-key created_at ' + ' --sort-dir desc ' + ' --limit 1', + ) self.assertEqual(1, len(locks)) self.assertIn(lock_2['id'], [lock['ID'] for lock in locks]) self.assertNotIn(lock_1['id'], [lock['ID'] for lock in locks]) self.assertNotIn(lock_3['id'], [lock['ID'] for lock in locks]) def test_lock_set_unset_lock_reason(self): - lock = self.create_resource_lock(self.share['id'], - client=self.user_client) + lock = self.create_resource_lock( + self.share['id'], client=self.user_client + ) self.assertEqual('None', lock['lock_reason']) - self.openstack('share lock set ' - f"--lock-reason 'updated reason' {lock['id']}") + self.openstack( + f'share lock set --lock-reason \'updated reason\' {lock["id"]}' + ) lock_show = self.dict_result("share", f"lock show {lock['id']}") self.assertEqual('updated reason', lock_show['Lock Reason']) @@ -138,30 +157,35 @@ def test_lock_set_unset_lock_reason(self): def test_lock_restrictions(self): """A user can't update or delete a lock created by another user.""" - lock = self.create_resource_lock(self.share['id'], - client=self.admin_client, - add_cleanup=False) + lock = self.create_resource_lock( + self.share['id'], client=self.admin_client, add_cleanup=False + ) self.assertEqual('admin', lock['lock_context']) - self.assertRaises(lib_exc.CommandFailed, - self.openstack, - f"share lock set {lock['id']} " - f"--reason 'i cannot do this'", - client=self.user_client) - self.assertRaises(lib_exc.CommandFailed, - self.openstack, - f"share lock unset {lock['id']} --reason", - client=self.user_client) - self.assertRaises(lib_exc.CommandFailed, - self.openstack, - f"share lock delete {lock['id']} ", - client=self.user_client) - - self.openstack(f'share lock set ' - f'--lock-reason "I can do this" ' - f'{lock["id"]}', - client=self.admin_client) - - self.openstack(f'share lock delete ' - f'{lock["id"]}', - client=self.admin_client) + self.assertRaises( + lib_exc.CommandFailed, + self.openstack, + f"share lock set {lock['id']} --reason 'i cannot do this'", + client=self.user_client, + ) + self.assertRaises( + lib_exc.CommandFailed, + self.openstack, + f"share lock unset {lock['id']} --reason", + client=self.user_client, + ) + self.assertRaises( + lib_exc.CommandFailed, + self.openstack, + f"share lock delete {lock['id']} ", + client=self.user_client, + ) + + self.openstack( + f'share lock set --lock-reason "I can do this" {lock["id"]}', + client=self.admin_client, + ) + + self.openstack( + f'share lock delete {lock["id"]}', client=self.admin_client + ) diff --git a/manilaclient/tests/functional/osc/test_share_access_rules.py b/manilaclient/tests/functional/osc/test_share_access_rules.py index 334cde0b..b90e22ae 100644 --- a/manilaclient/tests/functional/osc/test_share_access_rules.py +++ b/manilaclient/tests/functional/osc/test_share_access_rules.py @@ -18,14 +18,14 @@ @ddt.ddt class ShareAccessAllowTestCase(base.OSCClientTestBase): - def test_share_access_allow(self): share = self.create_share() access_rule = self.create_share_access_rule( share=share['name'], access_type='ip', access_to='0.0.0.0/0', - wait=True) + wait=True, + ) self.assertEqual(access_rule['share_id'], share['id']) self.assertEqual(access_rule['state'], 'active') @@ -36,10 +36,10 @@ def test_share_access_allow(self): self.assertEqual(access_rule['properties'], '') self.assertEqual(access_rule['access_level'], 'rw') - access_rules = self.listing_result('share', - f'access list {share["id"]}') - self.assertIn(access_rule['id'], - [item['ID'] for item in access_rules]) + access_rules = self.listing_result( + 'share', f'access list {share["id"]}' + ) + self.assertIn(access_rule['id'], [item['ID'] for item in access_rules]) # create another access rule with different params access_rule = self.create_share_access_rule( @@ -47,7 +47,8 @@ def test_share_access_allow(self): access_type='ip', access_to='12.34.56.78', access_level='ro', - properties='foo=bar') + properties='foo=bar', + ) self.assertEqual(access_rule['access_type'], 'ip') self.assertEqual(access_rule['access_to'], '12.34.56.78') @@ -55,18 +56,23 @@ def test_share_access_allow(self): self.assertEqual(access_rule['access_level'], 'ro') @ddt.data( - {'lock_visibility': True, 'lock_deletion': True, - 'lock_reason': None}, - {'lock_visibility': False, 'lock_deletion': True, - 'lock_reason': None}, - {'lock_visibility': True, 'lock_deletion': False, - 'lock_reason': 'testing'}, - {'lock_visibility': True, 'lock_deletion': False, - 'lock_reason': 'testing'}, + {'lock_visibility': True, 'lock_deletion': True, 'lock_reason': None}, + {'lock_visibility': False, 'lock_deletion': True, 'lock_reason': None}, + { + 'lock_visibility': True, + 'lock_deletion': False, + 'lock_reason': 'testing', + }, + { + 'lock_visibility': True, + 'lock_deletion': False, + 'lock_reason': 'testing', + }, ) @ddt.unpack - def test_share_access_allow_restrict(self, lock_visibility, - lock_deletion, lock_reason): + def test_share_access_allow_restrict( + self, lock_visibility, lock_deletion, lock_reason + ): share = self.create_share() access_rule = self.create_share_access_rule( share=share['id'], @@ -75,19 +81,21 @@ def test_share_access_allow_restrict(self, lock_visibility, wait=True, lock_visibility=lock_visibility, lock_deletion=lock_deletion, - lock_reason=lock_reason) + lock_reason=lock_reason, + ) if lock_deletion: self.assertRaises( tempest_exc.CommandFailed, self.openstack, 'share', - params=f'access delete {share["id"]} {access_rule["id"]}' + params=f'access delete {share["id"]} {access_rule["id"]}', ) self.openstack( 'share', params=f'access delete {share["id"]} {access_rule["id"]} ' - f'--unrestrict --wait') + f'--unrestrict --wait', + ) @ddt.ddt @@ -100,26 +108,29 @@ def test_share_access_deny(self, lock_deletion): access_type='ip', access_to='0.0.0.0/0', wait=True, - lock_deletion=lock_deletion) + lock_deletion=lock_deletion, + ) - access_rules = self.listing_result('share', - f'access list {share["id"]}') + access_rules = self.listing_result( + 'share', f'access list {share["id"]}' + ) num_access_rules = len(access_rules) delete_params = ( - f'access delete {share["name"]} {access_rule["id"]} --wait') + f'access delete {share["name"]} {access_rule["id"]} --wait' + ) if lock_deletion: delete_params += ' --unrestrict' self.openstack('share', params=delete_params) - access_rules = self.listing_result('share', - f'access list {share["id"]}') + access_rules = self.listing_result( + 'share', f'access list {share["id"]}' + ) self.assertEqual(num_access_rules - 1, len(access_rules)) @ddt.data class ListShareAccessRulesTestCase(base.OSCClientTestBase): - @ddt.data("2.45", "2.33", "2.21") def test_share_access_list(self, microversion): share = self.create_share() @@ -127,25 +138,21 @@ def test_share_access_list(self, microversion): share=share['name'], access_type='ip', access_to='0.0.0.0/0', - wait=True) + wait=True, + ) output = self.openstack( 'share', params=f'access list {share["id"]}', - flags=f'--os-share-api-version {microversion}') + flags=f'--os-share-api-version {microversion}', + ) access_rule_list = self.parser.listing(output) - base_list = [ - 'ID', - 'Access Type', - 'Access To', - 'Access Level', - 'State'] + base_list = ['ID', 'Access Type', 'Access To', 'Access Level', 'State'] if microversion >= '2.33': base_list.append('Access Key') if microversion >= '2.45': - base_list.extend(['Created At', - 'Updated At']) + base_list.extend(['Created At', 'Updated At']) self.assertTableStruct(access_rule_list, base_list) self.assertTrue(len(access_rule_list) > 0) @@ -155,19 +162,21 @@ def test_share_access_list(self, microversion): access_type='ip', access_to='192.168.0.151', wait=True, - properties='foo=bar') + properties='foo=bar', + ) output = self.openstack( 'share', - params=f'access list {share["id"]} ' - f'--properties foo=bar', - flags=f'--os-share-api-version {microversion}') + params=f'access list {share["id"]} --properties foo=bar', + flags=f'--os-share-api-version {microversion}', + ) access_rule_properties = self.parser.listing(output) self.assertEqual(1, len(access_rule_properties)) - self.assertEqual(access_rule_properties['id'], - access_rule_properties[0]['ID']) + self.assertEqual( + access_rule_properties['id'], access_rule_properties[0]['ID'] + ) def test_share_access_list_with_filters(self): share = self.create_share() @@ -176,17 +185,20 @@ def test_share_access_list_with_filters(self): share=share['name'], access_type='ip', access_to='0.0.0.0/0', - wait=True) + wait=True, + ) self.create_share_access_rule( share=share['name'], access_type='ip', access_to=access_to_filter, - wait=True) + wait=True, + ) output = self.openstack( 'share', params=f'access list {share["id"]} --access-to {access_to_filter}', - flags='--os-share-api-version 2.82') + flags='--os-share-api-version 2.82', + ) access_rule_list = self.parser.listing(output) self.assertTrue(len(access_rule_list) == 1) @@ -199,11 +211,12 @@ def test_share_access_show(self): share=share['name'], access_type='ip', access_to='0.0.0.0/0', - wait=True) + wait=True, + ) access_rule_show = self.dict_result( - 'share', - f'access show {access_rule["id"]}') + 'share', f'access show {access_rule["id"]}' + ) self.assertEqual(access_rule_show['id'], access_rule['id']) self.assertEqual(access_rule_show['share_id'], share['id']) self.assertEqual(access_rule_show['access_level'], 'rw') @@ -211,8 +224,9 @@ def test_share_access_show(self): self.assertEqual(access_rule_show['access_type'], 'ip') self.assertEqual(access_rule_show['state'], 'active') self.assertEqual(access_rule_show['access_key'], 'None') - self.assertEqual(access_rule_show['created_at'], - access_rule['created_at']) + self.assertEqual( + access_rule_show['created_at'], access_rule['created_at'] + ) self.assertEqual(access_rule_show['properties'], '') self.assertIn('updated_at', access_rule_show) @@ -224,17 +238,19 @@ def test_set_share_access_metadata(self): share=share['name'], access_type='ip', access_to='0.0.0.0/0', - wait=True) + wait=True, + ) self.assertEqual(access_rule['properties'], '') - self.openstack('share', - params=f'access set {access_rule["id"]} ' - f'--property foo=bar') + self.openstack( + 'share', + params=f'access set {access_rule["id"]} --property foo=bar', + ) access_rule = self.dict_result( - 'share', - f'access show {access_rule["id"]}') + 'share', f'access show {access_rule["id"]}' + ) self.assertEqual(access_rule['properties'], 'foo : bar') def test_set_share_access_level(self): @@ -243,16 +259,17 @@ def test_set_share_access_level(self): share=share['name'], access_type='ip', access_to='0.0.0.0/0', - wait=True) + wait=True, + ) self.assertEqual(access_rule['access_level'], 'rw') - self.openstack('share', - params=f'access set {access_rule["id"]} ' - f'--access-level ro') + self.openstack( + 'share', params=f'access set {access_rule["id"]} --access-level ro' + ) access_rule = self.dict_result( - 'share', - f'access show {access_rule["id"]}') + 'share', f'access show {access_rule["id"]}' + ) self.assertEqual(access_rule['access_level'], 'ro') @@ -264,13 +281,14 @@ def test_unset_share_access(self): access_type='ip', access_to='192.168.0.101', wait=True, - properties='foo=bar') + properties='foo=bar', + ) - self.openstack('share', - params=f'access unset ' - f'--property foo {access_rule["id"]}') + self.openstack( + 'share', params=f'access unset --property foo {access_rule["id"]}' + ) access_rule_unset = self.dict_result( - 'share', - f'access show {access_rule["id"]}') + 'share', f'access show {access_rule["id"]}' + ) self.assertEqual(access_rule_unset['properties'], '') diff --git a/manilaclient/tests/functional/osc/test_share_backups.py b/manilaclient/tests/functional/osc/test_share_backups.py index 6c7ed6dd..bccfe4b8 100644 --- a/manilaclient/tests/functional/osc/test_share_backups.py +++ b/manilaclient/tests/functional/osc/test_share_backups.py @@ -25,11 +25,13 @@ def test_share_backup_create(self): share_id=share['id'], name='test_backup_create', description='Description', - backup_options={'dummy': True}) + backup_options={'dummy': True}, + ) # fetch latest after periodic callback updates status - backup = json.loads(self.openstack( - f'share backup show -f json {backup["id"]}')) + backup = json.loads( + self.openstack(f'share backup show -f json {backup["id"]}') + ) self.assertEqual(share["id"], backup["share_id"]) self.assertEqual('test_backup_create', backup["name"]) @@ -37,8 +39,7 @@ def test_share_backup_create(self): self.assertEqual('available', backup["status"]) backups_list = self.listing_result('share backup', 'list') - self.assertIn(backup['id'], - [item['ID'] for item in backups_list]) + self.assertIn(backup['id'], [item['ID'] for item in backups_list]) def test_share_backup_delete(self): share = self.create_share() @@ -46,10 +47,10 @@ def test_share_backup_delete(self): backup = self.create_backup( share_id=share['id'], backup_options={'dummy': True}, - add_cleanup=False) + add_cleanup=False, + ) - self.openstack( - f'share backup delete {backup["id"]} --wait') + self.openstack(f'share backup delete {backup["id"]} --wait') self.check_object_deleted('share backup', backup["id"]) @@ -60,27 +61,45 @@ def test_share_backup_show(self): share_id=share['id'], name='test_backup_show', description='Description', - backup_options={'dummy': True}) + backup_options={'dummy': True}, + ) - show_result = self.dict_result( - 'share backup', f'show {backup["id"]}') + show_result = self.dict_result('share backup', f'show {backup["id"]}') self.assertEqual(backup["id"], show_result["id"]) self.assertEqual('test_backup_show', show_result["name"]) self.assertEqual('Description', show_result["description"]) + def test_share_backup_restore(self): + share = self.create_share() + + backup = self.create_backup( + share_id=share['id'], backup_options={'dummy': True} + ) + + self.openstack(f'share backup restore {backup["id"]} --wait') + + backup = json.loads( + self.openstack(f'share backup show -f json {backup["id"]}') + ) + share = json.loads(self.openstack(f'share show -f json {share["id"]}')) + + self.assertEqual('available', backup['status']) + self.assertEqual('available', share['status']) + def test_share_backup_set(self): share = self.create_share() - backup = self.create_backup(share_id=share['id'], - backup_options={'dummy': True}) + backup = self.create_backup( + share_id=share['id'], backup_options={'dummy': True} + ) self.openstack( f'share backup set {backup["id"]} ' - f'--name test_backup_set --description Description') + f'--name test_backup_set --description Description' + ) - show_result = self.dict_result( - 'share backup ', f'show {backup["id"]}') + show_result = self.dict_result('share backup ', f'show {backup["id"]}') self.assertEqual(backup['id'], show_result["id"]) self.assertEqual('test_backup_set', show_result["name"]) @@ -93,13 +112,16 @@ def test_share_backup_unset(self): share_id=share['id'], name='test_backup_unset', description='Description', - backup_options={'dummy': True}) + backup_options={'dummy': True}, + ) self.openstack( - f'share backup unset {backup["id"]} --name --description') + f'share backup unset {backup["id"]} --name --description' + ) - show_result = json.loads(self.openstack( - f'share backup show -f json {backup["id"]}')) + show_result = json.loads( + self.openstack(f'share backup show -f json {backup["id"]}') + ) self.assertEqual(backup['id'], show_result["id"]) self.assertIsNone(show_result["name"]) @@ -109,44 +131,44 @@ def test_share_backup_list(self): share_1 = self.create_share() share_2 = self.create_share() - backup_1 = self.create_backup(share_id=share_1['id'], - backup_options={'dummy': True}) - backup_2 = self.create_backup(share_id=share_2['id'], - backup_options={'dummy': True}) + backup_1 = self.create_backup( + share_id=share_1['id'], backup_options={'dummy': True} + ) + backup_2 = self.create_backup( + share_id=share_2['id'], backup_options={'dummy': True} + ) backups_list = self.listing_result( 'share backup', f'list --name {backup_2["name"]} ' ) - self.assertTableStruct(backups_list, [ - 'ID', - 'Name', - 'Share ID', - 'Status' - ]) + self.assertTableStruct( + backups_list, ['ID', 'Name', 'Share ID', 'Status'] + ) self.assertEqual(1, len(backups_list)) - self.assertIn(backup_2['id'], - [item['ID'] for item in backups_list]) + self.assertIn(backup_2['id'], [item['ID'] for item in backups_list]) backups_list = self.listing_result( 'share backup', f'list --share {share_1["id"]} --detail' ) - self.assertTableStruct(backups_list, [ - 'ID', - 'Name', - 'Share ID', - 'Status', - 'Description', - 'Availability Zone', - 'Created At', - 'Updated At', - 'Size', - 'Progress', - 'Restore Progress', - 'Host', - 'Topic', - ]) + self.assertTableStruct( + backups_list, + [ + 'ID', + 'Name', + 'Share ID', + 'Status', + 'Description', + 'Availability Zone', + 'Created At', + 'Updated At', + 'Size', + 'Progress', + 'Restore Progress', + 'Host', + 'Topic', + ], + ) self.assertEqual(1, len(backups_list)) - self.assertIn(backup_1['id'], - [item['ID'] for item in backups_list]) + self.assertIn(backup_1['id'], [item['ID'] for item in backups_list]) diff --git a/manilaclient/tests/functional/osc/test_share_group_type_access.py b/manilaclient/tests/functional/osc/test_share_group_type_access.py index 2ea865e0..5537b61a 100644 --- a/manilaclient/tests/functional/osc/test_share_group_type_access.py +++ b/manilaclient/tests/functional/osc/test_share_group_type_access.py @@ -17,32 +17,37 @@ class SharesGroupTypeAccessCLITest(base.OSCClientTestBase): - def test_share_group_type_access_create(self): share_group_type_name = self.create_share_group_type( - share_types='dhss_false', public=False)['name'] + share_types='dhss_false', public=False + )['name'] access_list = self.listing_result( - 'share', f'group type access list {share_group_type_name}') + 'share', f'group type access list {share_group_type_name}' + ) self.assertEqual(0, len(access_list)) cmd_output = jsonutils.loads(self.openstack('token issue -f json ')) auth_project_id = cmd_output['project_id'] self.share_group_type_access_create( - share_group_type_name, auth_project_id) + share_group_type_name, auth_project_id + ) share_group_type_access_list = self.listing_result( - 'share', f'group type access list {share_group_type_name}') + 'share', f'group type access list {share_group_type_name}' + ) self.assertEqual(1, len(share_group_type_access_list)) def test_share_group_type_access_delete(self): share_group_type_name = self.create_share_group_type( - share_types='dhss_false', public=False)['name'] + share_types='dhss_false', public=False + )['name'] access_list = self.listing_result( - 'share', f'group type access list {share_group_type_name}') + 'share', f'group type access list {share_group_type_name}' + ) self.assertEqual(0, len(access_list)) cmd_output = jsonutils.loads(self.openstack('token issue -f json ')) @@ -51,38 +56,47 @@ def test_share_group_type_access_delete(self): # Create using name to ensure that we are "translating" the # name into the actual ID in the CLI self.share_group_type_access_create( - share_group_type_name, auth_project_id) + share_group_type_name, auth_project_id + ) share_group_type_access_list = self.listing_result( - 'share', f'group type access list {share_group_type_name}') + 'share', f'group type access list {share_group_type_name}' + ) self.assertEqual(1, len(share_group_type_access_list)) self.assertEqual( - share_group_type_access_list[0]['Project ID'], auth_project_id) + share_group_type_access_list[0]['Project ID'], auth_project_id + ) self.share_group_type_access_delete( - share_group_type_name, auth_project_id) + share_group_type_name, auth_project_id + ) access_list = self.listing_result( - 'share', f'group type access list {share_group_type_name}') + 'share', f'group type access list {share_group_type_name}' + ) self.assertEqual(0, len(access_list)) def test_share_group_type_access_list(self): share_group_type_name = self.create_share_group_type( - share_types='dhss_false', public=False)['name'] + share_types='dhss_false', public=False + )['name'] access_list = self.listing_result( - 'share', f'group type access list {share_group_type_name}') + 'share', f'group type access list {share_group_type_name}' + ) self.assertEqual(0, len(access_list)) cmd_output = jsonutils.loads(self.openstack('token issue -f json ')) auth_project_id = cmd_output['project_id'] self.share_group_type_access_create( - share_group_type_name, auth_project_id) + share_group_type_name, auth_project_id + ) share_group_type_access_list = self.listing_result( - 'share', f'group type access list {share_group_type_name}') + 'share', f'group type access list {share_group_type_name}' + ) self.assertEqual(1, len(share_group_type_access_list)) self.assertTableStruct(access_list, ['Project ID']) diff --git a/manilaclient/tests/functional/osc/test_share_instance_export_locations.py b/manilaclient/tests/functional/osc/test_share_instance_export_locations.py new file mode 100644 index 00000000..9917aaf6 --- /dev/null +++ b/manilaclient/tests/functional/osc/test_share_instance_export_locations.py @@ -0,0 +1,23 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +from tempest.lib import exceptions + +from manilaclient.tests.functional.osc import base + + +class ShareInstanceExportLocationsCLITest(base.OSCClientTestBase): + def test_share_instance_export_locations_list_invalid_id(self): + self.assertRaises( + exceptions.CommandFailed, + self.openstack, + 'share instance export location list wrong_ID', + ) diff --git a/manilaclient/tests/functional/osc/test_share_instances.py b/manilaclient/tests/functional/osc/test_share_instances.py new file mode 100644 index 00000000..b867e4de --- /dev/null +++ b/manilaclient/tests/functional/osc/test_share_instances.py @@ -0,0 +1,101 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from tempest.lib import exceptions + +from manilaclient.tests.functional.osc import base + + +class ShareInstancesCLITest(base.OSCClientTestBase): + def setUp(self): + super().setUp() + # Create a share to test with + self.share = self.create_share() + # Get share instances for testing + self.share_instances = self.listing_result('share instance', 'list') + self.share_instance = ( + self.share_instances[0] if self.share_instances else None + ) + self.non_existent_id = '76a7dd8e-7564-41d4-a184-06dc20e13d7a' + self.invalid_id = 'invalid-format' + + def test_share_instance_list(self): + # Test basic listing + instances = self.listing_result('share instance', 'list') + self.assertTableStruct( + instances, + [ + 'ID', + 'Share ID', + 'Host', + 'Status', + 'Availability Zone', + 'Share Network ID', + 'Share Server ID', + 'Share Type ID', + ], + ) + + def test_share_instance_show(self): + result = self.dict_result( + 'share instance', f'show {self.share_instance["ID"]}' + ) + self.assertEqual(self.share_instance['ID'], result['id']) + + def test_share_instance_delete_non_existent(self): + self.assertRaises( + exceptions.CommandFailed, + self.openstack, + f'share instance delete {self.non_existent_id}', + ) + + def test_share_instance_set_non_existent(self): + self.assertRaises( + exceptions.CommandFailed, + self.openstack, + f'share instance set {self.non_existent_id} --status available', + ) + + def test_share_instance_set_invalid_status(self): + self.assertRaises( + exceptions.CommandFailed, + self.openstack, + f'share instance set {self.invalid_id} --status available', + ) + + def test_share_instance_show_non_existent(self): + self.assertRaises( + exceptions.CommandFailed, + self.openstack, + f'share instance show {self.non_existent_id}', + ) + + def test_share_instance_show_invalid_id_format(self): + self.assertRaises( + exceptions.CommandFailed, + self.openstack, + f'share instance show {self.invalid_id}', + ) + + def test_share_instance_list_invalid_filter_share_id_format(self): + self.assertRaises( + exceptions.CommandFailed, + self.openstack, + f'share instance list --share {self.invalid_id}', + ) + + def test_share_instance_list_invalid_filter_non_existent(self): + self.assertRaises( + exceptions.CommandFailed, + self.openstack, + f'share instance list --share {self.non_existent_id}', + ) diff --git a/manilaclient/tests/functional/osc/test_share_limits.py b/manilaclient/tests/functional/osc/test_share_limits.py index 4176abe4..82d922ec 100644 --- a/manilaclient/tests/functional/osc/test_share_limits.py +++ b/manilaclient/tests/functional/osc/test_share_limits.py @@ -17,27 +17,25 @@ class ListSharePoolsTestCase(base.OSCClientTestBase): - def test_limits_show_absolute(self): - limits = self.listing_result('share', ' limits show --absolute') - self.assertTableStruct(limits, [ - 'Name', - 'Value' - ]) + self.assertTableStruct(limits, ['Name', 'Value']) def test_limits_show_rate(self): - - limits = self.listing_result('share', - ' limits show --rate --print-empty') - - self.assertTableStruct(limits, [ - 'Verb', - 'Regex', - 'URI', - 'Value', - 'Remaining', - 'Unit', - 'Next Available' - ]) + limits = self.listing_result( + 'share', ' limits show --rate --print-empty' + ) + + self.assertTableStruct( + limits, + [ + 'Verb', + 'Regex', + 'URI', + 'Value', + 'Remaining', + 'Unit', + 'Next Available', + ], + ) diff --git a/manilaclient/tests/functional/osc/test_share_network_subnets.py b/manilaclient/tests/functional/osc/test_share_network_subnets.py index 7f00c449..e9b77e2a 100644 --- a/manilaclient/tests/functional/osc/test_share_network_subnets.py +++ b/manilaclient/tests/functional/osc/test_share_network_subnets.py @@ -17,12 +17,10 @@ class ShareNetworkSubnetsCLITest(base.OSCClientTestBase): - def test_openstack_share_network_create_check(self): share_network = self.create_share_network() - check_result = self.check_create_network_subnet( - share_network['id']) + check_result = self.check_create_network_subnet(share_network['id']) self.assertEqual('True', check_result['compatible']) self.assertEqual('', check_result['hosts_check_result']) @@ -31,7 +29,8 @@ def test_openstack_share_network_create_check_restart(self): share_network = self.create_share_network() check_result = self.check_create_network_subnet( - share_network['id'], restart_check=True) + share_network['id'], restart_check=True + ) self.assertEqual('True', check_result['compatible']) self.assertEqual('', check_result['hosts_check_result']) diff --git a/manilaclient/tests/functional/osc/test_share_networks.py b/manilaclient/tests/functional/osc/test_share_networks.py index 7739078b..67c053c1 100644 --- a/manilaclient/tests/functional/osc/test_share_networks.py +++ b/manilaclient/tests/functional/osc/test_share_networks.py @@ -14,7 +14,6 @@ class ShareNetworksCLITest(base.OSCClientTestBase): - def test_openstack_share_network_create(self): share_network_name = 'test_create_share_network' share_network = self.create_share_network(name=share_network_name) @@ -22,68 +21,82 @@ def test_openstack_share_network_create(self): self.assertEqual(share_network['name'], share_network_name) share_network_list = self.listing_result('share network', 'list') - self.assertIn(share_network['id'], - [item['ID'] for item in share_network_list]) + self.assertIn( + share_network['id'], [item['ID'] for item in share_network_list] + ) def test_openstack_share_network_list(self): share_network = self.create_share_network() share_network_list = self.listing_result('share network', 'list') - self.assertTableStruct(share_network_list, [ - 'ID', - 'Name', - ]) - self.assertIn(share_network['id'], - [item['ID'] for item in share_network_list]) + self.assertTableStruct( + share_network_list, + [ + 'ID', + 'Name', + ], + ) + self.assertIn( + share_network['id'], [item['ID'] for item in share_network_list] + ) def test_openstack_share_network_show(self): share_network = self.create_share_network() - result = self.dict_result('share network', - 'show %s' % share_network['id']) + result = self.dict_result( + 'share network', 'show {}'.format(share_network['id']) + ) self.assertEqual(share_network['id'], result['id']) - listing_result = self.listing_result('share network', - 'show %s' % share_network['id']) - self.assertTableStruct(listing_result, [ - 'Field', - 'Value' - ]) + listing_result = self.listing_result( + 'share network', 'show {}'.format(share_network['id']) + ) + self.assertTableStruct(listing_result, ['Field', 'Value']) def test_openstack_share_network_delete(self): share_network = self.create_share_network(add_cleanup=False) share_network_list = self.listing_result('share network', 'list') - self.assertIn(share_network['id'], - [item['ID'] for item in share_network_list]) + self.assertIn( + share_network['id'], [item['ID'] for item in share_network_list] + ) - self.openstack('share network delete %s' % share_network['id']) + self.openstack('share network delete {}'.format(share_network['id'])) self.check_object_deleted('share network', share_network['id']) - share_network_list_after_delete = self.listing_result('share network', - 'list') + share_network_list_after_delete = self.listing_result( + 'share network', 'list' + ) self.assertNotIn( share_network['id'], - [item['ID'] for item in share_network_list_after_delete]) + [item['ID'] for item in share_network_list_after_delete], + ) def test_openstack_share_network_set(self): share_network = self.create_share_network() - self.openstack('share network set %s --name %s' - % (share_network['id'], 'new_name')) - result = self.dict_result('share network', 'show %s' % - share_network['id']) + self.openstack( + 'share network set {} --name {}'.format( + share_network['id'], 'new_name' + ) + ) + result = self.dict_result( + 'share network', 'show {}'.format(share_network['id']) + ) self.assertEqual(share_network['id'], result['id']) self.assertEqual('new_name', result['name']) def test_openstack_share_network_unset(self): share_network = self.create_share_network(name='test_name') - result1 = self.dict_result('share network', 'show %s' % - share_network['id']) + result1 = self.dict_result( + 'share network', 'show {}'.format(share_network['id']) + ) self.assertEqual(share_network['id'], result1['id']) self.assertEqual(share_network['name'], result1['name']) - self.openstack('share network unset %s --name' - % (share_network['id'])) - result2 = self.dict_result('share network', 'show %s' % - share_network['id']) + self.openstack( + 'share network unset {} --name'.format(share_network['id']) + ) + result2 = self.dict_result( + 'share network', 'show {}'.format(share_network['id']) + ) self.assertEqual(share_network['id'], result2['id']) self.assertEqual('None', result2['name']) diff --git a/manilaclient/tests/functional/osc/test_share_pools.py b/manilaclient/tests/functional/osc/test_share_pools.py index f086e5e4..1f1c638c 100644 --- a/manilaclient/tests/functional/osc/test_share_pools.py +++ b/manilaclient/tests/functional/osc/test_share_pools.py @@ -14,33 +14,25 @@ class ListSharePoolsTestCase(base.OSCClientTestBase): - def test_pool_list(self): pools = self.list_pools() - self.assertTableStruct(pools, [ - 'Name', - 'Host', - 'Backend', - 'Pool' - ]) + self.assertTableStruct(pools, ['Name', 'Host', 'Backend', 'Pool']) self.assertTrue(len(pools) > 0) # Filter results first_pool = pools[0] - pools = self.list_pools(backend=first_pool['Backend'], - host=first_pool['Host'], - pool=first_pool['Pool']) + pools = self.list_pools( + backend=first_pool['Backend'], + host=first_pool['Host'], + pool=first_pool['Pool'], + ) self.assertEqual(1, len(pools)) self.assertEqual(first_pool['Name'], pools[0]['Name']) def test_pool_list_detail(self): pools = self.list_pools(detail=True) - self.assertTableStruct(pools, [ - 'Name', - 'Host', - 'Backend', - 'Pool', - 'Capabilities' - ]) + self.assertTableStruct( + pools, ['Name', 'Host', 'Backend', 'Pool', 'Capabilities'] + ) self.assertTrue(len(pools) > 0) diff --git a/manilaclient/tests/functional/osc/test_share_replica_export_locations.py b/manilaclient/tests/functional/osc/test_share_replica_export_locations.py index 7e6f6a40..586275cb 100644 --- a/manilaclient/tests/functional/osc/test_share_replica_export_locations.py +++ b/manilaclient/tests/functional/osc/test_share_replica_export_locations.py @@ -16,44 +16,51 @@ class ShareReplicaExportLocationsCLITest(base.OSCClientTestBase): - def test_openstack_share_replica_export_location_list(self): slug = 'replica-supported' share_type = self.create_share_type( - data_utils.rand_name(slug), 'False', extra_specs={ - 'replication_type': 'readable'}) + data_utils.rand_name(slug), + 'False', + extra_specs={'replication_type': 'readable'}, + ) share = self.create_share(share_type=share_type['name']) replica = self.create_share_replica(share['id'], wait=True) rep_exp_loc_list = self.listing_result( - 'share replica export location', f'list {replica["id"]}') - self.assertTableStruct(rep_exp_loc_list, [ - 'ID', - 'Availability Zone', - 'Replica State', - 'Preferred', - 'Path' - ]) + 'share replica export location', f'list {replica["id"]}' + ) + self.assertTableStruct( + rep_exp_loc_list, + ['ID', 'Availability Zone', 'Replica State', 'Preferred', 'Path'], + ) exp_loc_list = self.openstack( - f'share replica show {replica["id"]} -f json') + f'share replica show {replica["id"]} -f json' + ) exp_loc_list = json.loads(exp_loc_list) - self.assertIn(exp_loc_list.get('export_locations')[0]['id'], - [item['ID'] for item in rep_exp_loc_list]) + self.assertIn( + exp_loc_list.get('export_locations')[0]['id'], + [item['ID'] for item in rep_exp_loc_list], + ) def test_openstack_share_replica_export_location_show(self): slug = 'replica-supported' share_type = self.create_share_type( - data_utils.rand_name(slug), 'False', extra_specs={ - 'replication_type': 'readable'}) + data_utils.rand_name(slug), + 'False', + extra_specs={'replication_type': 'readable'}, + ) share = self.create_share(share_type=share_type['name']) replica = self.create_share_replica(share['id'], wait=True) rep_exp_loc_obj = self.get_share_replica_export_locations( - replica['id'])[0] + replica['id'] + )[0] exp_loc_list = self.openstack( - f'share replica show {replica["id"]} -f json') + f'share replica show {replica["id"]} -f json' + ) exp_loc_list = json.loads(exp_loc_list) result = self.dict_result( 'share replica export location', - f'show {replica["id"]} {rep_exp_loc_obj["ID"]}') + f'show {replica["id"]} {rep_exp_loc_obj["ID"]}', + ) export_location = exp_loc_list['export_locations'][0] self.assertEqual(result['id'], export_location['id']) diff --git a/manilaclient/tests/functional/osc/test_share_replicas.py b/manilaclient/tests/functional/osc/test_share_replicas.py index 0658ccdd..c56066dc 100644 --- a/manilaclient/tests/functional/osc/test_share_replicas.py +++ b/manilaclient/tests/functional/osc/test_share_replicas.py @@ -18,36 +18,110 @@ class ShareReplicasCLITest(base.OSCClientTestBase): - - def _create_share_and_replica(self, add_cleanup=True): + def _create_share_and_replica(self, add_cleanup=True, properties=None): replication_type = CONF.replication_type share_type = self.create_share_type( data_utils.rand_name('test_share_type'), dhss=True, - extra_specs={'replication_type': replication_type}) + extra_specs={'replication_type': replication_type}, + ) share_network = self.create_share_network(name='test_share_network') - share = self.create_share(share_type=share_type['name'], - share_network=share_network['id']) - replica = self.create_share_replica(share['id'], - share_network=share_network['id'], - wait=True, - add_cleanup=add_cleanup) + share = self.create_share( + share_type=share_type['name'], share_network=share_network['id'] + ) + replica = self.create_share_replica( + share['id'], + share_network=share_network['id'], + wait=True, + properties=properties, + add_cleanup=add_cleanup, + ) return replica def test_share_replica_create(self): share_replica = self._create_share_and_replica() share_replica_list = self.listing_result('share replica', 'list') - self.assertTableStruct(share_replica_list, [ - 'ID', - 'Status', - 'Share ID', - ]) - self.assertIn(share_replica['id'], - [item['ID'] for item in share_replica_list]) + self.assertTableStruct( + share_replica_list, + [ + 'ID', + 'Status', + 'Share ID', + ], + ) + self.assertIn( + share_replica['id'], [item['ID'] for item in share_replica_list] + ) def test_share_replica_delete(self): share_replica = self._create_share_and_replica(add_cleanup=False) + self.openstack(f'share replica delete {share_replica["id"]}') + self.check_object_deleted('share replica', share_replica["id"]) + + def test_share_replica_create_with_metadata(self): + """Create a replica with --property and verify it appears in show.""" + share_replica = self._create_share_and_replica( + properties={'test_key': 'test_value'} + ) + show_result = self.dict_result( + 'share', f'replica show {share_replica["id"]}' + ) + self.assertEqual(share_replica['id'], show_result['id']) + self.assertIn('test_key', show_result['properties']) + self.assertIn('test_value', show_result['properties']) + + def test_share_replica_set_property(self): + """Set a property on a replica and verify it appears in show.""" + share_replica = self._create_share_and_replica() + self.openstack( - f'share replica delete {share_replica["id"]}' + f'share replica set {share_replica["id"]}' + ' --property custom_role=secondary' ) - self.check_object_deleted('share replica', share_replica["id"]) + + show_result = self.dict_result( + 'share', f'replica show {share_replica["id"]}' + ) + self.assertEqual(share_replica['id'], show_result['id']) + self.assertIn('custom_role', show_result['properties']) + self.assertIn('secondary', show_result['properties']) + + def test_share_replica_unset_property(self): + """Unset a property from a replica and verify it is removed.""" + share_replica = self._create_share_and_replica( + properties={ + 'custom_role': 'secondary', + 'custom_policy': 'async', + } + ) + + self.openstack( + f'share replica unset {share_replica["id"]} --property custom_role' + ) + + show_result = self.dict_result( + 'share', f'replica show {share_replica["id"]}' + ) + self.assertEqual(share_replica['id'], show_result['id']) + self.assertNotIn('custom_role', show_result['properties']) + self.assertIn('custom_policy', show_result['properties']) + self.assertIn('async', show_result['properties']) + + def test_share_replica_list_with_property_filter(self): + """List replicas filtered by property and verify correct results.""" + share_replica = self._create_share_and_replica( + properties={'filter_key': 'filter_value'} + ) + share_id = self.dict_result( + 'share', f'replica show {share_replica["id"]}' + )['share_id'] + + # List filtered by property; the replica should appear + filtered_list = self.listing_result( + 'share', + f'replica list --share {share_id}' + ' --property filter_key=filter_value', + ) + filtered_ids = [item['ID'] for item in filtered_list] + + self.assertIn(share_replica['id'], filtered_ids) diff --git a/manilaclient/tests/functional/osc/test_share_services.py b/manilaclient/tests/functional/osc/test_share_services.py index cd5286e6..a44fd7a8 100644 --- a/manilaclient/tests/functional/osc/test_share_services.py +++ b/manilaclient/tests/functional/osc/test_share_services.py @@ -14,45 +14,47 @@ class ShareServicesTestCase(base.OSCClientTestBase): - def test_services_list(self): services = self.list_services() - self.assertTableStruct(services, [ - 'ID', - 'Binary', - 'Host', - 'Zone', - 'Status', - 'State', - 'Updated At' - ]) + self.assertTableStruct( + services, + ['ID', 'Binary', 'Host', 'Zone', 'Status', 'State', 'Updated At'], + ) self.assertTrue(len(services) > 0) # Filter results first_service = services[0] - services = self.list_services(host=first_service['Host'], - status=first_service['Status'], - state=first_service['State']) + services = self.list_services( + host=first_service['Host'], + status=first_service['Status'], + state=first_service['State'], + ) self.assertEqual(1, len(services)) for attr in ('ID', 'Binary', 'Host', 'State', 'Status', 'Zone'): self.assertEqual(first_service[attr], services[0][attr]) def test_services_set(self): services = self.list_services() - service = [service for service in services if - service["Binary"] == "manila-data"] + service = [ + service + for service in services + if service["Binary"] == "manila-data" + ] first_service = service[0] - self.openstack(f'share service set {first_service["Host"]} ' - f'{first_service["Binary"]} ' - '--disable --disable-reason test') - result = self.listing_result('share service', - 'list --status disabled') + self.openstack( + f'share service set {first_service["Host"]} ' + f'{first_service["Binary"]} ' + '--disable --disable-reason test' + ) + result = self.listing_result('share service', 'list --status disabled') self.assertEqual(first_service['ID'], result[0]['ID']) self.assertEqual('disabled', result[0]['Status']) self.assertEqual('test', result[0]['Disabled Reason']) # enable the share service again - self.openstack(f'share service set {first_service["Host"]} ' - f'{first_service["Binary"]} ' - '--enable') + self.openstack( + f'share service set {first_service["Host"]} ' + f'{first_service["Binary"]} ' + '--enable' + ) diff --git a/manilaclient/tests/functional/osc/test_share_snapshot_instances.py b/manilaclient/tests/functional/osc/test_share_snapshot_instances.py index 1fa91811..39b63605 100644 --- a/manilaclient/tests/functional/osc/test_share_snapshot_instances.py +++ b/manilaclient/tests/functional/osc/test_share_snapshot_instances.py @@ -14,62 +14,75 @@ class ShareSnapshotInstancesCLITest(base.OSCClientTestBase): - def test_openstack_share_snapshot_instance_list(self): share = self.create_share() snapshot = self.create_snapshot(share['id']) share_snapshot_instances_list = self.listing_result( - 'share snapshot instance', 'list --detailed') - self.assertTableStruct(share_snapshot_instances_list, [ - 'ID', - 'Snapshot ID', - 'Status', - 'Created At', - 'Updated At', - 'Share ID', - 'Share Instance ID', - 'Progress', - 'Provider Location' - ]) - self.assertIn(snapshot['id'], - [item['Snapshot ID'] for item in ( - share_snapshot_instances_list)]) + 'share snapshot instance', 'list --detailed' + ) + self.assertTableStruct( + share_snapshot_instances_list, + [ + 'ID', + 'Snapshot ID', + 'Status', + 'Created At', + 'Updated At', + 'Share ID', + 'Share Instance ID', + 'Progress', + 'Provider Location', + ], + ) + self.assertIn( + snapshot['id'], + [item['Snapshot ID'] for item in (share_snapshot_instances_list)], + ) def test_openstack_share_snapshot_instance_show(self): share = self.create_share() snapshot = self.create_snapshot(share['id'], wait=True) share_snapshot_instance = self.listing_result( - "share snapshot instance", f'list --snapshot {snapshot["id"]}') - result = self.dict_result('share snapshot instance', - f'show {share_snapshot_instance[0]["ID"]}') + "share snapshot instance", f'list --snapshot {snapshot["id"]}' + ) + result = self.dict_result( + 'share snapshot instance', + f'show {share_snapshot_instance[0]["ID"]}', + ) self.assertEqual(share_snapshot_instance[0]['ID'], result['id']) - self.assertEqual(share_snapshot_instance[0]['Snapshot ID'], - result['snapshot_id']) + self.assertEqual( + share_snapshot_instance[0]['Snapshot ID'], result['snapshot_id'] + ) listing_result = self.listing_result( - 'share snapshot instance', f'show ' - f'{share_snapshot_instance[0]["ID"]}') - self.assertTableStruct(listing_result, [ - 'Field', - 'Value' - ]) + 'share snapshot instance', + f'show {share_snapshot_instance[0]["ID"]}', + ) + self.assertTableStruct(listing_result, ['Field', 'Value']) def test_openstack_share_snapshot_instance_set(self): share = self.create_share() snapshot = self.create_snapshot(share['id'], wait=True) share_snapshot_instance = self.listing_result( - "share snapshot instance", f'list --snapshot {snapshot["id"]}') - result1 = self.dict_result('share snapshot instance', - f'show {share_snapshot_instance[0]["ID"]}') + "share snapshot instance", f'list --snapshot {snapshot["id"]}' + ) + result1 = self.dict_result( + 'share snapshot instance', + f'show {share_snapshot_instance[0]["ID"]}', + ) self.assertEqual(share_snapshot_instance[0]['ID'], result1['id']) self.assertEqual(snapshot['id'], result1['snapshot_id']) self.assertEqual('available', result1['status']) - self.openstack('share snapshot instance set ' - f'{share_snapshot_instance[0]["ID"]} --status error') - result2 = self.dict_result('share snapshot instance', - f'show {share_snapshot_instance[0]["ID"]}') + self.openstack( + 'share snapshot instance set ' + f'{share_snapshot_instance[0]["ID"]} --status error' + ) + result2 = self.dict_result( + 'share snapshot instance', + f'show {share_snapshot_instance[0]["ID"]}', + ) self.assertEqual(share_snapshot_instance[0]["ID"], result2['id']) self.assertEqual('error', result2['status']) diff --git a/manilaclient/tests/functional/osc/test_share_snapshots.py b/manilaclient/tests/functional/osc/test_share_snapshots.py index 127ae648..4af5cc6b 100644 --- a/manilaclient/tests/functional/osc/test_share_snapshots.py +++ b/manilaclient/tests/functional/osc/test_share_snapshots.py @@ -22,9 +22,8 @@ def test_share_snapshot_create(self): share = self.create_share() snapshot = self.create_snapshot( - share=share['id'], - name='Snap', - description='Description') + share=share['id'], name='Snap', description='Description' + ) self.assertEqual(share["id"], snapshot["share_id"]) self.assertEqual('Snap', snapshot["name"]) @@ -32,33 +31,31 @@ def test_share_snapshot_create(self): self.assertEqual('available', snapshot["status"]) snapshots_list = self.listing_result('share snapshot', 'list') - self.assertIn(snapshot['id'], - [item['ID'] for item in snapshots_list]) + self.assertIn(snapshot['id'], [item['ID'] for item in snapshots_list]) def test_share_snapshot_delete(self): share = self.create_share() - snapshot_1 = self.create_snapshot( - share=share['id'], add_cleanup=False) - snapshot_2 = self.create_snapshot( - share=share['id'], add_cleanup=False) + snapshot_1 = self.create_snapshot(share=share['id'], add_cleanup=False) + snapshot_2 = self.create_snapshot(share=share['id'], add_cleanup=False) self.openstack( f'share snapshot delete {snapshot_1["id"]} {snapshot_2["id"]} ' - '--wait') + '--wait' + ) self.check_object_deleted('share snapshot', snapshot_1["id"]) self.check_object_deleted('share snapshot', snapshot_2["id"]) - snapshot_3 = self.create_snapshot( - share=share['id'], add_cleanup=False) + snapshot_3 = self.create_snapshot(share=share['id'], add_cleanup=False) self.openstack( - f'share snapshot set {snapshot_3["id"]} ' - '--status creating') + f'share snapshot set {snapshot_3["id"]} --status creating' + ) self.openstack( - f'share snapshot delete {snapshot_3["id"]} --wait --force') + f'share snapshot delete {snapshot_3["id"]} --wait --force' + ) self.check_object_deleted('share snapshot', snapshot_3["id"]) @@ -66,12 +63,12 @@ def test_share_snapshot_show(self): share = self.create_share() snapshot = self.create_snapshot( - share=share['id'], - name='Snap', - description='Description') + share=share['id'], name='Snap', description='Description' + ) show_result = self.dict_result( - 'share snapshot', f'show {snapshot["id"]}') + 'share snapshot', f'show {snapshot["id"]}' + ) self.assertEqual(snapshot["id"], show_result["id"]) self.assertEqual('Snap', show_result["name"]) @@ -84,10 +81,12 @@ def test_share_snapshot_set(self): self.openstack( f'share snapshot set {snapshot["id"]} ' - f'--name Snap --description Description') + f'--name Snap --description Description' + ) show_result = self.dict_result( - 'share snapshot ', f'show {snapshot["id"]}') + 'share snapshot ', f'show {snapshot["id"]}' + ) self.assertEqual(snapshot['id'], show_result["id"]) self.assertEqual('Snap', show_result["name"]) @@ -97,15 +96,16 @@ def test_share_snapshot_unset(self): share = self.create_share() snapshot = self.create_snapshot( - share=share['id'], - name='Snap', - description='Description') + share=share['id'], name='Snap', description='Description' + ) self.openstack( - f'share snapshot unset {snapshot["id"]} --name --description') + f'share snapshot unset {snapshot["id"]} --name --description' + ) - show_result = json.loads(self.openstack( - f'share snapshot show -f json {snapshot["id"]}')) + show_result = json.loads( + self.openstack(f'share snapshot show -f json {snapshot["id"]}') + ) self.assertEqual(snapshot['id'], show_result["id"]) self.assertIsNone(show_result["name"]) @@ -116,31 +116,27 @@ def test_share_snapshot_list(self): snapshot_1 = self.create_snapshot(share=share['id']) snapshot_2 = self.create_snapshot( - share=share['id'], - description='Description') + share=share['id'], description='Description' + ) snapshots_list = self.listing_result( - 'share snapshot', f'list --name {snapshot_2["name"]} ' - f'--description {snapshot_2["description"]} --all-projects' + 'share snapshot', + f'list --name {snapshot_2["name"]} ' + f'--description {snapshot_2["description"]} --all-projects', ) - self.assertTableStruct(snapshots_list, [ - 'ID', - 'Name', - 'Project ID' - ]) + self.assertTableStruct(snapshots_list, ['ID', 'Name', 'Project ID']) - self.assertIn(snapshot_2["name"], - [snap["Name"] for snap in snapshots_list]) + self.assertIn( + snapshot_2["name"], [snap["Name"] for snap in snapshots_list] + ) self.assertEqual(1, len(snapshots_list)) snapshots_list = self.listing_result( - 'share snapshot', f'list --share {share["name"]}') + 'share snapshot', f'list --share {share["name"]}' + ) - self.assertTableStruct(snapshots_list, [ - 'ID', - 'Name' - ]) + self.assertTableStruct(snapshots_list, ['ID', 'Name']) id_list = [snap["ID"] for snap in snapshots_list] self.assertIn(snapshot_1["id"], id_list) @@ -149,25 +145,31 @@ def test_share_snapshot_list(self): snapshots_list = self.listing_result( 'share snapshot', f'list --name~ {snapshot_2["name"][-3:]} ' - '--description~ Des --detail') - - self.assertTableStruct(snapshots_list, [ - 'ID', - 'Name', - 'Status', - 'Description', - 'Created At', - 'Size', - 'Share ID', - 'Share Proto', - 'Share Size', - 'User ID' - ]) - - self.assertIn(snapshot_2["name"], - [snap["Name"] for snap in snapshots_list]) + '--description~ Des --detail', + ) + + self.assertTableStruct( + snapshots_list, + [ + 'ID', + 'Name', + 'Status', + 'Description', + 'Created At', + 'Size', + 'Share ID', + 'Share Proto', + 'Share Size', + 'User ID', + ], + ) + + self.assertIn( + snapshot_2["name"], [snap["Name"] for snap in snapshots_list] + ) self.assertEqual( - snapshot_2["description"], snapshots_list[0]['Description']) + snapshot_2["description"], snapshots_list[0]['Description'] + ) self.assertEqual(1, len(snapshots_list)) def test_share_snapshot_export_location_list(self): @@ -176,12 +178,10 @@ def test_share_snapshot_export_location_list(self): snapshot = self.create_snapshot(share=share['id']) export_location_list = self.listing_result( - 'share snapshot export location', f' list {snapshot["id"]}') + 'share snapshot export location', f' list {snapshot["id"]}' + ) - self.assertTableStruct(export_location_list, [ - 'ID', - 'Path' - ]) + self.assertTableStruct(export_location_list, ['ID', 'Path']) def test_share_snapshot_export_location_show(self): share = self.create_share() @@ -189,11 +189,13 @@ def test_share_snapshot_export_location_show(self): snapshot = self.create_snapshot(share=share['id']) export_location_list = self.listing_result( - 'share snapshot export location', f'list {snapshot["id"]}') + 'share snapshot export location', f'list {snapshot["id"]}' + ) export_location = self.dict_result( 'share snapshot export location', - f'show {snapshot["id"]} {export_location_list[0]["ID"]}') + f'show {snapshot["id"]} {export_location_list[0]["ID"]}', + ) self.assertIn('id', export_location) self.assertIn('created_at', export_location) @@ -205,25 +207,25 @@ def test_share_snapshot_export_location_show(self): def test_share_snapshot_abandon_adopt(self): share = self.create_share() - snapshot = self.create_snapshot( - share=share['id'], add_cleanup=False) + snapshot = self.create_snapshot(share=share['id'], add_cleanup=False) - self.openstack( - f'share snapshot abandon {snapshot["id"]} --wait') + self.openstack(f'share snapshot abandon {snapshot["id"]} --wait') snapshots_list = self.listing_result('share snapshot', 'list') - self.assertNotIn(snapshot['id'], - [item['ID'] for item in snapshots_list]) + self.assertNotIn( + snapshot['id'], [item['ID'] for item in snapshots_list] + ) snapshot = self.dict_result( 'share snapshot', f'adopt {share["id"]} 10.0.0.1:/foo/path ' - f'--name Snap --description Zorilla --wait') + f'--name Snap --description Zorilla --wait', + ) snapshots_list = self.listing_result('share snapshot', 'list') - self.assertIn(snapshot['id'], - [item['ID'] for item in snapshots_list]) + self.assertIn(snapshot['id'], [item['ID'] for item in snapshots_list]) self.addCleanup( self.openstack, - f'share snapshot delete {snapshot["id"]} --force --wait') + f'share snapshot delete {snapshot["id"]} --force --wait', + ) diff --git a/manilaclient/tests/functional/osc/test_share_transfers.py b/manilaclient/tests/functional/osc/test_share_transfers.py index 41bfb0e3..bdfa2a4b 100644 --- a/manilaclient/tests/functional/osc/test_share_transfers.py +++ b/manilaclient/tests/functional/osc/test_share_transfers.py @@ -17,42 +17,57 @@ class TransfersCLITest(base.OSCClientTestBase): - def setUp(self): - super(TransfersCLITest, self).setUp() + super().setUp() self.share_type = self.create_share_type() def test_transfer_create_list_show_delete(self): - share = self.create_share(share_type=self.share_type['name'], - wait_for_status='available', - client=self.user_client) + share = self.create_share( + share_type=self.share_type['name'], + wait_for_status='available', + client=self.user_client, + ) # create share transfer self.create_share_transfer(share['id'], name='transfer_test') self._wait_for_object_status('share', share['id'], 'awaiting_transfer') # Get all transfers transfers = self.listing_result( - 'share', 'transfer list', client=self.user_client) + 'share', 'transfer list', client=self.user_client + ) # We must have at least one transfer self.assertTrue(len(transfers) > 0) - self.assertTableStruct(transfers, [ - 'ID', - 'Name', - 'Resource Type', - 'Resource Id', - ]) + self.assertTableStruct( + transfers, + [ + 'ID', + 'Name', + 'Resource Type', + 'Resource Id', + ], + ) # grab the transfer we created - transfer = [transfer for transfer in transfers - if transfer['Resource Id'] == share['id']] + transfer = [ + transfer + for transfer in transfers + if transfer['Resource Id'] == share['id'] + ] self.assertEqual(1, len(transfer)) - show_transfer = self.dict_result('share', - f'transfer show {transfer[0]["ID"]}') + show_transfer = self.dict_result( + 'share', f'transfer show {transfer[0]["ID"]}' + ) self.assertEqual(transfer[0]['ID'], show_transfer['id']) expected_keys = ( - 'id', 'created_at', 'name', 'resource_type', 'resource_id', - 'source_project_id', 'destination_project_id', 'accepted', + 'id', + 'created_at', + 'name', + 'resource_type', + 'resource_id', + 'source_project_id', + 'destination_project_id', + 'accepted', 'expires_at', ) for key in expected_keys: @@ -62,7 +77,8 @@ def test_transfer_create_list_show_delete(self): filtered_transfers = self.listing_result( 'share', f'transfer list --resource-id {share["id"]}', - client=self.user_client) + client=self.user_client, + ) self.assertEqual(1, len(filtered_transfers)) self.assertEqual(show_transfer['resource_id'], share["id"]) @@ -71,15 +87,19 @@ def test_transfer_create_list_show_delete(self): self._wait_for_object_status('share', share['id'], 'available') def test_transfer_accept(self): - share = self.create_share(share_type=self.share_type['name'], - wait_for_status='available', - client=self.user_client) + share = self.create_share( + share_type=self.share_type['name'], + wait_for_status='available', + client=self.user_client, + ) # create share transfer - transfer = self.create_share_transfer(share['id'], - name='transfer_test') + transfer = self.create_share_transfer( + share['id'], name='transfer_test' + ) self._wait_for_object_status('share', share['id'], 'awaiting_transfer') # accept share transfer self.openstack( - f'share transfer accept {transfer["id"]} {transfer["auth_key"]}') + f'share transfer accept {transfer["id"]} {transfer["auth_key"]}' + ) self._wait_for_object_status('share', share['id'], 'available') diff --git a/manilaclient/tests/functional/osc/test_share_types.py b/manilaclient/tests/functional/osc/test_share_types.py index 010c07cc..abd3a530 100644 --- a/manilaclient/tests/functional/osc/test_share_types.py +++ b/manilaclient/tests/functional/osc/test_share_types.py @@ -15,12 +15,10 @@ class ShareTypesCLITest(base.OSCClientTestBase): - def test_share_type_create(self): name = 'test_share_type' description = 'Description' - share_type = self.create_share_type( - name=name, description=description) + share_type = self.create_share_type(name=name, description=description) self.assertEqual(name, share_type["name"]) self.assertEqual(description, share_type["description"]) @@ -28,7 +26,8 @@ def test_share_type_create(self): share_types_list = self.listing_result('share type', 'list') self.assertIn( - share_type["id"], [item['ID'] for item in share_types_list]) + share_type["id"], [item['ID'] for item in share_types_list] + ) def test_share_type_create_specs(self): share_type = self.create_share_type( @@ -36,22 +35,19 @@ def test_share_type_create_specs(self): create_share_from_snapshot_support=True, revert_to_snapshot_support=True, mount_snapshot_support=True, - extra_specs={ - "foo": "bar", - "manila": "zorilla" - }, - formatter='json') + extra_specs={"foo": "bar", "manila": "zorilla"}, + formatter='json', + ) required_specs = share_type["required_extra_specs"] optional_specs = share_type["optional_extra_specs"] - self.assertEqual( - False, required_specs["driver_handles_share_servers"]) + self.assertEqual(False, required_specs["driver_handles_share_servers"]) self.assertEqual('True', optional_specs["snapshot_support"]) self.assertEqual( - 'True', optional_specs["create_share_from_snapshot_support"]) - self.assertEqual( - 'True', optional_specs["revert_to_snapshot_support"]) + 'True', optional_specs["create_share_from_snapshot_support"] + ) + self.assertEqual('True', optional_specs["revert_to_snapshot_support"]) self.assertEqual('True', optional_specs["mount_snapshot_support"]) self.assertEqual("bar", optional_specs["foo"]) self.assertEqual("zorilla", optional_specs["manila"]) @@ -75,72 +71,73 @@ def test_share_type_set(self): ' --name Name --public false --extra-specs foo=bar' ) - share_type = json.loads(self.openstack( - f'share type show {share_type["id"]} -f json' - )) + share_type = json.loads( + self.openstack(f'share type show {share_type["id"]} -f json') + ) self.assertEqual('Description', share_type["description"]) self.assertEqual('Name', share_type["name"]) self.assertEqual('private', share_type["visibility"]) - self.assertEqual( - 'bar', share_type["optional_extra_specs"]["foo"]) + self.assertEqual('bar', share_type["optional_extra_specs"]["foo"]) def test_share_type_unset(self): share_type = self.create_share_type( - snapshot_support=True, - extra_specs={'foo': 'bar'}) + snapshot_support=True, extra_specs={'foo': 'bar'} + ) self.openstack( - f'share type unset {share_type["id"]} ' - 'snapshot_support foo') + f'share type unset {share_type["id"]} snapshot_support foo' + ) - share_type = json.loads(self.openstack( - f'share type show {share_type["id"]} -f json' - )) + share_type = json.loads( + self.openstack(f'share type show {share_type["id"]} -f json') + ) self.assertNotIn('foo', share_type["optional_extra_specs"]) self.assertNotIn( - 'snapshot_support', share_type["optional_extra_specs"]) + 'snapshot_support', share_type["optional_extra_specs"] + ) def test_share_type_list(self): share_type_1 = self.create_share_type(public=False) - share_type_2 = self.create_share_type( - extra_specs={'foo': 'bar'}) + share_type_2 = self.create_share_type(extra_specs={'foo': 'bar'}) types_list = self.listing_result( - 'share type', 'list --all', client=self.admin_client) - - self.assertTableStruct(types_list, [ - 'ID', - 'Name', - 'Visibility', - 'Is Default', - 'Required Extra Specs', - 'Optional Extra Specs', - 'Description' - ]) + 'share type', 'list --all', client=self.admin_client + ) + + self.assertTableStruct( + types_list, + [ + 'ID', + 'Name', + 'Visibility', + 'Is Default', + 'Required Extra Specs', + 'Optional Extra Specs', + 'Description', + ], + ) id_list = [item['ID'] for item in types_list] self.assertIn(share_type_1['id'], id_list) self.assertIn(share_type_2['id'], id_list) types_list = self.listing_result( - 'share type', 'list --extra-specs foo=bar') + 'share type', 'list --extra-specs foo=bar' + ) id_list = [item['ID'] for item in types_list] self.assertNotIn(share_type_1['id'], id_list) self.assertIn(share_type_2['id'], id_list) def test_share_type_show(self): - share_type = self.create_share_type( - extra_specs={'foo': 'bar'}) + share_type = self.create_share_type(extra_specs={'foo': 'bar'}) - result = json.loads(self.openstack( - f'share type show {share_type["id"]} -f json')) + result = json.loads( + self.openstack(f'share type show {share_type["id"]} -f json') + ) self.assertEqual(share_type["name"], result["name"]) - self.assertEqual( - share_type["visibility"], result["visibility"]) - self.assertEqual( - share_type["is_default"], str(result["is_default"])) - self.assertEqual( - 'bar', result["optional_extra_specs"]["foo"]) + self.assertEqual(share_type["visibility"], result["visibility"]) + self.assertEqual(share_type["is_default"], str(result["is_default"])) + self.assertEqual('bar', result["optional_extra_specs"]["foo"]) diff --git a/manilaclient/tests/functional/osc/test_shares.py b/manilaclient/tests/functional/osc/test_shares.py index 524fbeb4..69fcff4e 100644 --- a/manilaclient/tests/functional/osc/test_shares.py +++ b/manilaclient/tests/functional/osc/test_shares.py @@ -15,7 +15,6 @@ class SharesCLITest(base.OSCClientTestBase): - def test_openstack_share_create(self): share_name = 'test_create_share' share = self.create_share(name=share_name) @@ -30,30 +29,32 @@ def test_openstack_share_create(self): def test_openstack_share_list(self): share = self.create_share() shares_list = self.listing_result('share', 'list') - self.assertTableStruct(shares_list, [ - 'ID', - 'Name', - 'Size', - 'Share Proto', - 'Status', - 'Is Public', - 'Share Type Name', - 'Host', - 'Availability Zone' - ]) + self.assertTableStruct( + shares_list, + [ + 'ID', + 'Name', + 'Size', + 'Share Proto', + 'Status', + 'Is Public', + 'Share Type Name', + 'Host', + 'Availability Zone', + ], + ) self.assertIn(share['id'], [item['ID'] for item in shares_list]) def test_openstack_share_show(self): share = self.create_share() - result = self.dict_result('share', 'show %s' % share['id']) + result = self.dict_result('share', 'show {}'.format(share['id'])) self.assertEqual(share['id'], result['id']) - listing_result = self.listing_result('share', 'show %s' % share['id']) - self.assertTableStruct(listing_result, [ - 'Field', - 'Value' - ]) + listing_result = self.listing_result( + 'share', 'show {}'.format(share['id']) + ) + self.assertTableStruct(listing_result, ['Field', 'Value']) def test_openstack_share_delete(self): share = self.create_share(add_cleanup=False) @@ -61,30 +62,35 @@ def test_openstack_share_delete(self): self.assertIn(share['id'], [item['ID'] for item in shares_list]) - self.openstack('share delete %s' % share['id']) + self.openstack('share delete {}'.format(share['id'])) self.check_object_deleted('share', share['id']) shares_list_after_delete = self.listing_result('share', 'list') self.assertNotIn( - share['id'], [item['ID'] for item in shares_list_after_delete]) + share['id'], [item['ID'] for item in shares_list_after_delete] + ) def test_openstack_share_set(self): share = self.create_share() - self.openstack(f'share set {share["id"]} --name new_name ' - f'--property key=value') + self.openstack( + f'share set {share["id"]} --name new_name --property key=value' + ) result = self.dict_result('share', f'show {share["id"]}') self.assertEqual(share['id'], result['id']) self.assertEqual('new_name', result['name']) self.assertEqual("key='value'", result['properties']) def test_openstack_share_unset(self): - share = self.create_share(name='test_name', properties={ - 'foo': 'bar', 'test_key': 'test_value'}) + share = self.create_share( + name='test_name', + properties={'foo': 'bar', 'test_key': 'test_value'}, + ) result1 = self.dict_result('share', f'show {share["id"]}') self.assertEqual(share['id'], result1['id']) self.assertEqual(share['name'], result1['name']) - self.assertEqual("foo='bar', test_key='test_value'", - result1['properties']) + self.assertEqual( + "foo='bar', test_key='test_value'", result1['properties'] + ) self.openstack(f'share unset {share["id"]} --name --property test_key') result2 = self.dict_result('share', f'show {share["id"]}') @@ -100,10 +106,12 @@ def test_openstack_share_soft_delete(self): self.openstack(f'share delete {share["id"]} --soft') self.check_object_deleted('share', share['id']) - shares_list_after_delete = self.listing_result('share', 'list ' - '--soft-deleted') + shares_list_after_delete = self.listing_result( + 'share', 'list --soft-deleted' + ) self.assertIn( - share['id'], [item['ID'] for item in shares_list_after_delete]) + share['id'], [item['ID'] for item in shares_list_after_delete] + ) def test_openstack_share_resize(self): share = self.create_share() @@ -116,7 +124,8 @@ def test_openstack_share_revert(self): share_type = self.create_share_type( name=data_utils.rand_name(slug), snapshot_support=True, - revert_to_snapshot_support=True) + revert_to_snapshot_support=True, + ) share = self.create_share(share_type=share_type['id'], size=10) snapshot = self.create_snapshot(share['id'], wait=True) self.assertEqual(snapshot['size'], share['size']) @@ -146,11 +155,14 @@ def test_openstack_share_abandon_adopt(self): self.check_object_deleted('share', share['id']) shares_list_after_delete = self.listing_result('share', 'list') self.assertNotIn( - share['id'], [item['ID'] for item in shares_list_after_delete]) + share['id'], [item['ID'] for item in shares_list_after_delete] + ) result = self.dict_result( - 'share', f'adopt {host} {protocol} {export_location} ' - f'--share-type {share_type} --wait') + 'share', + f'adopt {host} {protocol} {export_location} ' + f'--share-type {share_type} --wait', + ) # verify adopted self.assertEqual(host, result['host']) @@ -161,24 +173,26 @@ def test_openstack_share_export_location_show(self): share = self.create_share() share_export_locations = self.get_share_export_locations(share["id"]) result_export_locations = self.listing_result( - 'share', f'export location list {share["id"]}') + 'share', f'export location list {share["id"]}' + ) for share_export in share_export_locations: export_location = self.dict_result( - 'share', f'export location show {share["id"]} ' - f'{share_export["ID"]}') - self.assertIn(export_location["id"], [item["ID"] for item in - result_export_locations]) + 'share', + f'export location show {share["id"]} {share_export["ID"]}', + ) + self.assertIn( + export_location["id"], + [item["ID"] for item in result_export_locations], + ) def test_openstack_share_export_location_list(self): share = self.create_share() share_export_locations = self.get_share_export_locations(share["id"]) result_export_locations = self.listing_result( - 'share', f'export location list {share["id"]}') + 'share', f'export location list {share["id"]}' + ) - self.assertTableStruct(result_export_locations, [ - 'ID', - 'Path' - ]) + self.assertTableStruct(result_export_locations, ['ID', 'Path']) export_location_ids = [el['ID'] for el in share_export_locations] for share_export in result_export_locations: self.assertIn(share_export["ID"], export_location_ids) @@ -193,10 +207,12 @@ def test_openstack_share_restore(self): self.check_object_deleted('share', share['id']) shares_list_after_delete = self.listing_result('share', 'list') self.assertNotIn( - share['id'], [item['ID'] for item in shares_list_after_delete]) + share['id'], [item['ID'] for item in shares_list_after_delete] + ) self.openstack(f'share restore {share["id"]} ') shares_list_after_restore = self.listing_result('share', 'list') self.assertIn( - share['id'], [item['ID'] for item in shares_list_after_restore]) + share['id'], [item['ID'] for item in shares_list_after_restore] + ) diff --git a/manilaclient/tests/functional/osc/test_shares_group_type.py b/manilaclient/tests/functional/osc/test_shares_group_type.py index 2268253a..062423bf 100644 --- a/manilaclient/tests/functional/osc/test_shares_group_type.py +++ b/manilaclient/tests/functional/osc/test_shares_group_type.py @@ -18,52 +18,65 @@ class SharesGroupTypesCLITest(base.OSCClientTestBase): - def test_share_group_type_create(self): share_group_type_name = 'test_share_group_type_create' share_group_type = self.create_share_group_type( - name=share_group_type_name, share_types='dhss_false') + name=share_group_type_name, share_types='dhss_false' + ) self.assertEqual(share_group_type['name'], share_group_type_name) self.assertIsNotNone(share_group_type['share_types']) shares_group_type_list = self.listing_result( - 'share', 'group type list') + 'share', 'group type list' + ) self.assertIn( share_group_type['id'], - [item['ID'] for item in shares_group_type_list]) + [item['ID'] for item in shares_group_type_list], + ) def test_openstack_share_group_type_list(self): share_group_type_name = data_utils.rand_name( - 'test_share_group_type_create') + 'test_share_group_type_create' + ) share_group_type = self.create_share_group_type( - name=share_group_type_name, share_types='dhss_false') + name=share_group_type_name, share_types='dhss_false' + ) shares_group_type_list = self.listing_result( - 'share', 'group type list') - self.assertTableStruct(shares_group_type_list, [ - 'ID', - 'Name', - 'Share Types', - 'Visibility', - 'Is Default', - 'Group Specs' - ]) + 'share', 'group type list' + ) + self.assertTableStruct( + shares_group_type_list, + [ + 'ID', + 'Name', + 'Share Types', + 'Visibility', + 'Is Default', + 'Group Specs', + ], + ) self.assertIn( share_group_type['id'], - [item['ID'] for item in shares_group_type_list]) + [item['ID'] for item in shares_group_type_list], + ) def test_openstack_share_group_type_show(self): share_group_type_name = data_utils.rand_name( - 'test_share_group_type_create') + 'test_share_group_type_create' + ) share_type_name = 'dhss_false' share_group_type = self.create_share_group_type( - name=share_group_type_name, share_types=share_type_name) + name=share_group_type_name, share_types=share_type_name + ) shares_group_type_show = self.dict_result( - 'share', f'group type show {share_group_type_name}') + 'share', f'group type show {share_group_type_name}' + ) share_type_id = self.dict_result( - 'share', f'type show {share_type_name}')['id'] + 'share', f'type show {share_type_name}' + )['id'] expected_sgt_values = { 'id': share_group_type['id'], @@ -71,7 +84,7 @@ def test_openstack_share_group_type_show(self): 'share_types': share_type_id, 'visibility': 'public', 'is_default': 'False', - 'group_specs': '' + 'group_specs': '', } for k, v in shares_group_type_show.items(): @@ -79,22 +92,21 @@ def test_openstack_share_group_type_show(self): def test_openstack_share_group_type_set(self): share_group_type_name = data_utils.rand_name( - 'test_share_group_type_create') + 'test_share_group_type_create' + ) share_type_name = 'dhss_false' share_group_type = self.create_share_group_type( - name=share_group_type_name, share_types=share_type_name) + name=share_group_type_name, share_types=share_type_name + ) shares_group_type_show = self.openstack( - f'share group type show {share_group_type_name} -f json') + f'share group type show {share_group_type_name} -f json' + ) shares_group_type_show = jsonutils.loads(shares_group_type_show) - expected_sgt_values = { - 'id': share_group_type['id'], - 'group_specs': {} - } + expected_sgt_values = {'id': share_group_type['id'], 'group_specs': {}} for k, v in expected_sgt_values.items(): - self.assertEqual(expected_sgt_values[k], shares_group_type_show[k] - ) + self.assertEqual(expected_sgt_values[k], shares_group_type_show[k]) group_snap_key = 'snapshot_support' group_snap_value = 'False' @@ -103,17 +115,17 @@ def test_openstack_share_group_type_set(self): self.dict_result( 'share', f'group type set {share_group_type_name} ' - f'--group-specs {group_specs}') + f'--group-specs {group_specs}', + ) shares_group_type_show = self.openstack( - f'share group type show {share_group_type_name} -f json') + f'share group type show {share_group_type_name} -f json' + ) shares_group_type_show = jsonutils.loads(shares_group_type_show) expected_sgt_values = { 'id': share_group_type['id'], - 'group_specs': { - group_snap_key: group_snap_value - } + 'group_specs': {group_snap_key: group_snap_value}, } for k, v in expected_sgt_values.items(): @@ -121,41 +133,40 @@ def test_openstack_share_group_type_set(self): def test_openstack_share_group_type_unset(self): share_group_type_name = data_utils.rand_name( - 'test_share_group_type_create') + 'test_share_group_type_create' + ) group_snap_key = 'snapshot_support' group_snap_value = 'False' group_specs = f"{group_snap_key}={group_snap_value}" share_group_type = self.create_share_group_type( - name=share_group_type_name, share_types='dhss_false', - group_specs=group_specs) + name=share_group_type_name, + share_types='dhss_false', + group_specs=group_specs, + ) shares_group_type_show = self.openstack( - f'share group type show {share_group_type_name} -f json') + f'share group type show {share_group_type_name} -f json' + ) shares_group_type_show = jsonutils.loads(shares_group_type_show) expected_sgt_values = { 'id': share_group_type['id'], - 'group_specs': { - group_snap_key: group_snap_value - } + 'group_specs': {group_snap_key: group_snap_value}, } for k, v in expected_sgt_values.items(): - self.assertEqual(expected_sgt_values[k], shares_group_type_show[k] - ) + self.assertEqual(expected_sgt_values[k], shares_group_type_show[k]) self.dict_result( 'share', - f'group type unset {share_group_type_name} ' - f'{group_snap_key}') + f'group type unset {share_group_type_name} {group_snap_key}', + ) shares_group_type_show = self.openstack( - f'share group type show {share_group_type_name} -f json') + f'share group type show {share_group_type_name} -f json' + ) shares_group_type_show = jsonutils.loads(shares_group_type_show) - expected_sgt_values = { - 'id': share_group_type['id'], - 'group_specs': {} - } + expected_sgt_values = {'id': share_group_type['id'], 'group_specs': {}} for k, v in expected_sgt_values.items(): self.assertEqual(expected_sgt_values[k], shares_group_type_show[k]) diff --git a/manilaclient/tests/functional/test_availability_zones.py b/manilaclient/tests/functional/test_availability_zones.py deleted file mode 100644 index 190774bd..00000000 --- a/manilaclient/tests/functional/test_availability_zones.py +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright 2016 Mirantis Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import ddt -from oslo_utils import uuidutils - -from manilaclient.tests.functional import base - - -@ddt.ddt -class ManilaClientTestAvailabilityZonesReadOnly(base.BaseTestCase): - - @ddt.data("2.6", "2.7", "2.22") - def test_availability_zone_list(self, microversion): - self.skip_if_microversion_not_supported(microversion) - - azs = self.user_client.list_availability_zones( - microversion=microversion) - - for az in azs: - self.assertEqual(4, len(az)) - for key in ('Id', 'Name', 'Created_At', 'Updated_At'): - self.assertIn(key, az) - self.assertTrue(uuidutils.is_uuid_like(az['Id'])) - self.assertIsNotNone(az['Name']) - self.assertIsNotNone(az['Created_At']) - - @ddt.data( - ('name', ['Name']), - ('name,id', ['Name', 'Id']), - ('name,created_at', ['Name', 'Created_At']), - ('name,id,created_at', ['Name', 'Id', 'Created_At']), - ) - @ddt.unpack - def test_availability_zone_list_with_columns(self, columns_arg, expected): - azs = self.user_client.list_availability_zones(columns=columns_arg) - - for az in azs: - self.assertEqual(len(expected), len(az)) - for key in expected: - self.assertIn(key, az) - if 'Id' in expected: - self.assertTrue(uuidutils.is_uuid_like(az['Id'])) - if 'Name' in expected: - self.assertIsNotNone(az['Name']) - if 'Created_At' in expected: - self.assertIsNotNone(az['Created_At']) diff --git a/manilaclient/tests/functional/test_common.py b/manilaclient/tests/functional/test_common.py deleted file mode 100644 index 06fa77f3..00000000 --- a/manilaclient/tests/functional/test_common.py +++ /dev/null @@ -1,67 +0,0 @@ -# Copyright 2015 Mirantis Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import re - -import ddt - -from manilaclient.tests.functional import base - - -@ddt.ddt -class ManilaClientTestCommonReadOnly(base.BaseTestCase): - - @ddt.data('admin', 'user') - def test_manila_version(self, role): - self.clients[role].manila('', flags='--version') - - @ddt.data('admin', 'user') - def test_help(self, role): - help_text = self.clients[role].manila('help') - lines = help_text.split('\n') - self.assertFirstLineStartsWith(lines, 'usage: manila') - - commands = [] - cmds_start = lines.index('Positional arguments:') - try: - # TODO(gouthamr): Drop when py3.10 becomes min supported version - cmds_end = lines.index('Optional arguments:') - except ValueError: - cmds_end = lines.index('Options:') - command_pattern = re.compile(r'^ {4}([a-z0-9\-\_]+)') - for line in lines[cmds_start:cmds_end]: - match = command_pattern.match(line) - if match: - commands.append(match.group(1)) - commands = set(commands) - wanted_commands = set(( - 'absolute-limits', 'list', 'help', 'quota-show', 'access-list', - 'snapshot-list', 'access-allow', 'access-deny', - 'share-network-list', 'security-service-list')) - self.assertFalse(wanted_commands - commands) - - @ddt.data('admin', 'user') - def test_credentials(self, role): - self.clients[role].manila('credentials') - - @ddt.data('admin', 'user') - def test_list_extensions(self, role): - roles = self.parser.listing( - self.clients[role].manila('list-extensions')) - self.assertTableStruct(roles, ['Name', 'Summary', 'Alias', 'Updated']) - - @ddt.data('admin', 'user') - def test_endpoints(self, role): - self.clients[role].manila('endpoints') diff --git a/manilaclient/tests/functional/test_export_locations.py b/manilaclient/tests/functional/test_export_locations.py deleted file mode 100644 index 374322e8..00000000 --- a/manilaclient/tests/functional/test_export_locations.py +++ /dev/null @@ -1,162 +0,0 @@ -# Copyright 2015 Mirantis Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import ddt -from oslo_utils import uuidutils - -from manilaclient.tests.functional import base - - -@ddt.ddt -class ExportLocationReadWriteTest(base.BaseTestCase): - - def setUp(self): - super(ExportLocationReadWriteTest, self).setUp() - self.share = self.create_share( - client=self.get_user_client()) - - @ddt.data('admin', 'user') - def test_list_share_export_locations(self, role): - self.skip_if_microversion_not_supported('2.14') - - client = self.admin_client if role == 'admin' else self.user_client - export_locations = client.list_share_export_locations( - self.share['id']) - - self.assertGreater(len(export_locations), 0) - expected_keys = ('ID', 'Path', 'Preferred') - for el in export_locations: - for key in expected_keys: - self.assertIn(key, el) - self.assertTrue(uuidutils.is_uuid_like(el['ID'])) - self.assertIn(el['Preferred'], ('True', 'False')) - - @ddt.data('admin', 'user') - def test_list_share_export_locations_with_columns(self, role): - self.skip_if_microversion_not_supported('2.9') - - client = self.admin_client if role == 'admin' else self.user_client - export_locations = client.list_share_export_locations( - self.share['id'], columns='id,path') - - self.assertGreater(len(export_locations), 0) - expected_keys = ('Id', 'Path') - unexpected_keys = ('Updated At', 'Created At') - for el in export_locations: - for key in expected_keys: - self.assertIn(key, el) - for key in unexpected_keys: - self.assertNotIn(key, el) - self.assertTrue(uuidutils.is_uuid_like(el['Id'])) - - @ddt.data('admin', 'user') - def test_get_share_export_location(self, role): - self.skip_if_microversion_not_supported('2.14') - - client = self.admin_client if role == 'admin' else self.user_client - export_locations = client.list_share_export_locations( - self.share['id']) - - el = client.get_share_export_location( - self.share['id'], export_locations[0]['ID']) - - expected_keys = ['path', 'updated_at', 'created_at', 'id', 'preferred'] - if role == 'admin': - expected_keys.extend(['is_admin_only', 'share_instance_id']) - for key in expected_keys: - self.assertIn(key, el) - if role == 'admin': - self.assertTrue(uuidutils.is_uuid_like(el['share_instance_id'])) - self.assertIn(el['is_admin_only'], ('True', 'False')) - self.assertTrue(uuidutils.is_uuid_like(el['id'])) - self.assertIn(el['preferred'], ('True', 'False')) - for list_k, get_k in ( - ('ID', 'id'), ('Path', 'path'), ('Preferred', 'preferred')): - self.assertEqual( - export_locations[0][list_k], el[get_k]) - - def test_list_share_instance_export_locations(self): - self.skip_if_microversion_not_supported('2.14') - - client = self.admin_client - share_instances = client.list_share_instances(self.share['id']) - self.assertGreater(len(share_instances), 0) - self.assertIn('ID', share_instances[0]) - self.assertTrue(uuidutils.is_uuid_like(share_instances[0]['ID'])) - share_instance_id = share_instances[0]['ID'] - - export_locations = client.list_share_instance_export_locations( - share_instance_id) - - self.assertGreater(len(export_locations), 0) - expected_keys = ('ID', 'Path', 'Is Admin only', 'Preferred') - for el in export_locations: - for key in expected_keys: - self.assertIn(key, el) - self.assertTrue(uuidutils.is_uuid_like(el['ID'])) - - def test_list_share_instance_export_locations_with_columns(self): - self.skip_if_microversion_not_supported('2.9') - - client = self.admin_client - share_instances = client.list_share_instances(self.share['id']) - self.assertGreater(len(share_instances), 0) - self.assertIn('ID', share_instances[0]) - self.assertTrue(uuidutils.is_uuid_like(share_instances[0]['ID'])) - share_instance_id = share_instances[0]['ID'] - - export_locations = client.list_share_instance_export_locations( - share_instance_id, columns='id,path') - - self.assertGreater(len(export_locations), 0) - expected_keys = ('Id', 'Path') - unexpected_keys = ('Updated At', 'Created At', 'Is Admin only') - for el in export_locations: - for key in expected_keys: - self.assertIn(key, el) - for key in unexpected_keys: - self.assertNotIn(key, el) - self.assertTrue(uuidutils.is_uuid_like(el['Id'])) - - def test_get_share_instance_export_location(self): - self.skip_if_microversion_not_supported('2.14') - - client = self.admin_client - share_instances = client.list_share_instances(self.share['id']) - self.assertGreater(len(share_instances), 0) - self.assertIn('ID', share_instances[0]) - self.assertTrue(uuidutils.is_uuid_like(share_instances[0]['ID'])) - share_instance_id = share_instances[0]['ID'] - - export_locations = client.list_share_instance_export_locations( - share_instance_id) - - el = client.get_share_instance_export_location( - share_instance_id, export_locations[0]['ID']) - - expected_keys = ( - 'path', 'updated_at', 'created_at', 'id', 'preferred', - 'is_admin_only', 'share_instance_id', - ) - for key in expected_keys: - self.assertIn(key, el) - self.assertIn(el['is_admin_only'], ('True', 'False')) - self.assertIn(el['preferred'], ('True', 'False')) - self.assertTrue(uuidutils.is_uuid_like(el['id'])) - for list_k, get_k in ( - ('ID', 'id'), ('Path', 'path'), ('Preferred', 'preferred'), - ('Is Admin only', 'is_admin_only')): - self.assertEqual( - export_locations[0][list_k], el[get_k]) diff --git a/manilaclient/tests/functional/test_limits.py b/manilaclient/tests/functional/test_limits.py deleted file mode 100644 index 8308b8a4..00000000 --- a/manilaclient/tests/functional/test_limits.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2015 Mirantis Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import ddt - -from manilaclient.tests.functional import base - - -@ddt.ddt -class ManilaClientTestLimitsReadOnly(base.BaseTestCase): - - @ddt.data('admin', 'user') - def test_rate_limits(self, role): - self.clients[role].manila('rate-limits') - - @ddt.data('admin', 'user') - def test_absolute_limits(self, role): - self.clients[role].manila('absolute-limits') diff --git a/manilaclient/tests/functional/test_messages.py b/manilaclient/tests/functional/test_messages.py deleted file mode 100644 index e7a8380c..00000000 --- a/manilaclient/tests/functional/test_messages.py +++ /dev/null @@ -1,70 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import ddt - -from manilaclient.tests.functional import base - - -@ddt.ddt -class MessagesReadOnlyTest(base.BaseTestCase): - - @ddt.data( - ("admin", "2.37"), - ("user", "2.37"), - ) - @ddt.unpack - def test_message_list(self, role, microversion): - self.skip_if_microversion_not_supported(microversion) - self.clients[role].manila("message-list", microversion=microversion) - - -@ddt.ddt -class MessagesReadWriteTest(base.BaseTestCase): - - def setUp(self): - super(MessagesReadWriteTest, self).setUp() - self.message = self.create_message() - - def test_list_messages(self): - self.skip_if_microversion_not_supported('2.37') - messages = self.admin_client.list_messages() - self.assertTrue(any(m['ID'] is not None for m in messages)) - self.assertTrue(any(m['User Message'] is not None for m in messages)) - self.assertTrue(any(m['Resource ID'] is not None for m in messages)) - self.assertTrue(any(m['Action ID'] is not None for m in messages)) - self.assertTrue(any(m['Detail ID'] is not None for m in messages)) - self.assertTrue(any(m['Resource Type'] is not None for m in messages)) - - @ddt.data( - 'id', 'action_id', 'resource_id', 'action_id', 'detail_id', - 'resource_type', 'created_at', 'action_id,detail_id,resource_id', - ) - def test_list_share_type_select_column(self, columns): - self.skip_if_microversion_not_supported('2.37') - self.admin_client.list_messages(columns=columns) - - def test_get_message(self): - self.skip_if_microversion_not_supported('2.37') - message = self.admin_client.get_message(self.message['ID']) - expected_keys = ( - 'id', 'action_id', 'resource_id', 'action_id', 'detail_id', - 'resource_type', 'created_at', 'created_at', - ) - for key in expected_keys: - self.assertIn(key, message) - - def test_delete_message(self): - self.skip_if_microversion_not_supported('2.37') - message = self.create_message(cleanup_in_class=False) - self.admin_client.delete_message(message['ID']) - self.admin_client.wait_for_message_deletion(message['ID']) diff --git a/manilaclient/tests/functional/test_quotas.py b/manilaclient/tests/functional/test_quotas.py deleted file mode 100644 index 9e5cf736..00000000 --- a/manilaclient/tests/functional/test_quotas.py +++ /dev/null @@ -1,330 +0,0 @@ -# Copyright 2015 Mirantis Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from random import randint - -import ddt -from tempest.lib.cli import output_parser -from tempest.lib.common.utils import data_utils -from tempest.lib import exceptions - -from manilaclient import api_versions -from manilaclient.tests.functional import base -from manilaclient.tests.functional import utils - -REPLICA_QUOTAS_MICROVERSION = '2.53' - - -def _get_share_type_quota_values(project_quota_value): - project_quota_value = int(project_quota_value) - if project_quota_value == -1: - return randint(1, 999) - elif project_quota_value == 0: - return 0 - else: - return project_quota_value - 1 - - -@ddt.ddt -@utils.skip_if_microversion_not_supported("2.39") -class QuotasReadWriteTest(base.BaseTestCase): - - def setUp(self): - super(self.__class__, self).setUp() - self.microversion = "2.39" - self.project_id = self.admin_client.get_project_id( - self.admin_client.tenant_name) - - # Create share type - self.share_type = self.create_share_type( - name=data_utils.rand_name("manilaclient_functional_test"), - driver_handles_share_servers=False, - is_public=True, - microversion=self.microversion - ) - self.st_id = self.share_type["ID"] - - def _verify_current_st_quotas_equal_to(self, quotas, microversion): - # Read share type quotas - cmd = 'quota-show --tenant-id %s --share-type %s' % ( - self.project_id, self.st_id) - st_quotas_raw = self.admin_client.manila( - cmd, microversion=microversion) - st_quotas = output_parser.details(st_quotas_raw) - - # Verify that quotas - self.assertGreater(len(st_quotas), 3) - for key, value in st_quotas.items(): - if key not in ('shares', 'gigabytes', 'snapshots', - 'snapshot_gigabytes'): - continue - self.assertIn(key, quotas) - self.assertEqual(int(quotas[key]), int(value)) - - def _verify_current_quotas_equal_to(self, quotas, microversion): - # Read quotas - cmd = 'quota-show --tenant-id %s' % self.project_id - quotas_raw = self.admin_client.manila( - cmd, microversion=microversion) - quotas = output_parser.details(quotas_raw) - - # Verify that quotas - self.assertGreater(len(quotas), 3) - for key, value in quotas.items(): - if key not in ('shares', 'gigabytes', 'snapshots', - 'snapshot_gigabytes', - 'share_groups', 'share_group_snapshots'): - continue - self.assertIn(key, quotas) - self.assertEqual(int(quotas[key]), int(value)) - - @ddt.data(*set([ - "2.40", api_versions.MAX_VERSION, - ])) - def test_update_quotas_for_share_groups(self, microversion): - if not utils.is_microversion_supported(microversion): - msg = "Microversion '%s' not supported." % microversion - raise self.skipException(msg) - - # Get default quotas - cmd = 'quota-defaults' - quotas_raw = self.admin_client.manila(cmd, microversion=microversion) - default_quotas = output_parser.details(quotas_raw) - - # Get project quotas - cmd = 'quota-show --tenant-id %s ' % self.project_id - quotas_raw = self.admin_client.manila(cmd, microversion=microversion) - p_quotas = output_parser.details(quotas_raw) - - # Define custom share group quotas for project - p_custom_quotas = { - 'share_groups': -1 if int(p_quotas['share_groups']) != -1 else 999, - 'share_group_snapshots': -1 if int( - p_quotas['share_group_snapshots']) != -1 else 999, - } - - # Update share group quotas for project - cmd = ('quota-update %s --share-groups %s ' - '--share-group-snapshots %s') % ( - self.project_id, - p_custom_quotas['share_groups'], - p_custom_quotas['share_group_snapshots'], - ) - self.admin_client.manila(cmd, microversion=microversion) - - # Verify quotas - self._verify_current_quotas_equal_to(p_custom_quotas, microversion) - - # Reset quotas - cmd = 'quota-delete --tenant-id %s --share-type %s' % ( - self.project_id, self.st_id) - self.admin_client.manila(cmd, microversion=microversion) - - # Verify quotas after reset - self._verify_current_quotas_equal_to(default_quotas, microversion) - - # Return project quotas back - cmd = ('quota-update %s --share-groups %s ' - '--share-group-snapshots %s') % ( - self.project_id, - p_quotas['share_groups'], p_quotas['share_group_snapshots']) - self.admin_client.manila(cmd, microversion=microversion) - - # Verify quotas after reset - self._verify_current_quotas_equal_to(p_quotas, microversion) - - @ddt.data('--share-groups', '--share-group-snapshots') - @utils.skip_if_microversion_not_supported("2.39") - def test_update_quotas_for_share_groups_using_too_old_microversion(self, - arg): - cmd = 'quota-update %s %s 13' % (self.project_id, arg) - self.assertRaises( - exceptions.CommandFailed, - self.admin_client.manila, - cmd, microversion='2.39') - - @ddt.data('--share-replicas', '--replica-gigabytes') - @utils.skip_if_microversion_not_supported("2.52") - def test_update_quotas_for_share_replicas_using_too_old_microversion(self, - arg): - cmd = 'quota-update %s %s 10' % (self.project_id, arg) - self.assertRaises( - exceptions.CommandFailed, - self.admin_client.manila, - cmd, microversion='2.52') - - @ddt.data('--share-groups', '--share-group-snapshots') - @utils.skip_if_microversion_not_supported("2.40") - def test_update_share_type_quotas_for_share_groups(self, arg): - cmd = 'quota-update %s --share-type %s %s 13' % ( - self.project_id, self.st_id, arg) - self.assertRaises( - exceptions.CommandFailed, - self.admin_client.manila, - cmd, microversion='2.40') - - @ddt.data(*set([ - "2.39", "2.40", REPLICA_QUOTAS_MICROVERSION, api_versions.MAX_VERSION, - ])) - def test_update_share_type_quotas_positive(self, microversion): - if not utils.is_microversion_supported(microversion): - msg = "Microversion '%s' not supported." % microversion - raise self.skipException(msg) - - # Get project quotas - cmd = 'quota-show --tenant-id %s ' % self.project_id - quotas_raw = self.admin_client.manila(cmd, microversion=microversion) - p_quotas = output_parser.details(quotas_raw) - - # Define share type quotas - st_custom_quotas = { - 'shares': _get_share_type_quota_values(p_quotas['shares']), - 'snapshots': _get_share_type_quota_values(p_quotas['snapshots']), - 'gigabytes': _get_share_type_quota_values(p_quotas['gigabytes']), - 'snapshot_gigabytes': _get_share_type_quota_values( - p_quotas['snapshot_gigabytes']), - } - supports_share_replica_quotas = ( - api_versions.APIVersion(microversion) >= api_versions.APIVersion( - REPLICA_QUOTAS_MICROVERSION)) - - if supports_share_replica_quotas: - st_custom_quotas['share_replicas'] = _get_share_type_quota_values( - p_quotas['share_replicas'] - ) - st_custom_quotas['replica_gigabytes'] = ( - _get_share_type_quota_values(p_quotas['replica_gigabytes'])) - replica_params = (' --share-replicas %s ' - '--replica-gigabytes %s') % ( - st_custom_quotas['share_replicas'], - st_custom_quotas['replica_gigabytes']) - - # Update quotas for share type - cmd = ('quota-update %s --share-type %s ' - '--shares %s --gigabytes %s --snapshots %s ' - '--snapshot-gigabytes %s') % ( - self.project_id, self.st_id, - st_custom_quotas['shares'], - st_custom_quotas['gigabytes'], - st_custom_quotas['snapshots'], - st_custom_quotas['snapshot_gigabytes']) - - if supports_share_replica_quotas: - cmd += replica_params - self.admin_client.manila(cmd, microversion=microversion) - - # Verify share type quotas - self._verify_current_st_quotas_equal_to(st_custom_quotas, microversion) - - # Reset share type quotas - cmd = 'quota-delete --tenant-id %s --share-type %s' % ( - self.project_id, self.st_id) - self.admin_client.manila(cmd, microversion=microversion) - - # Verify share type quotas after reset - self._verify_current_st_quotas_equal_to(p_quotas, microversion) - - @utils.skip_if_microversion_not_supported("2.38") - def test_read_share_type_quotas_with_too_old_microversion(self): - cmd = 'quota-show --tenant-id %s --share-type %s' % ( - self.project_id, self.st_id) - self.assertRaises( - exceptions.CommandFailed, - self.admin_client.manila, - cmd, microversion='2.38') - - @utils.skip_if_microversion_not_supported("2.38") - def test_update_share_type_quotas_with_too_old_microversion(self): - cmd = 'quota-update --tenant-id %s --share-type %s --shares %s' % ( - self.project_id, self.st_id, '0') - self.assertRaises( - exceptions.CommandFailed, - self.admin_client.manila, - cmd, microversion='2.38') - - @utils.skip_if_microversion_not_supported("2.38") - def test_delete_share_type_quotas_with_too_old_microversion(self): - cmd = 'quota-delete --tenant-id %s --share-type %s' % ( - self.project_id, self.st_id) - self.assertRaises( - exceptions.CommandFailed, - self.admin_client.manila, - cmd, microversion='2.38') - - -@ddt.ddt -class ManilaClientTestQuotasReadOnly(base.BaseTestCase): - - def test_quota_class_show_by_admin(self): - roles = self.parser.listing( - self.clients['admin'].manila('quota-class-show', params='abc')) - self.assertTableStruct(roles, ('Property', 'Value')) - - def test_quota_class_show_by_user(self): - self.assertRaises( - exceptions.CommandFailed, - self.clients['user'].manila, - 'quota-class-show', - params='abc') - - def _get_quotas(self, role, operation, microversion): - roles = self.parser.listing(self.clients[role].manila( - 'quota-%s' % operation, microversion=microversion)) - self.assertTableStruct(roles, ('Property', 'Value')) - - @ddt.data('admin', 'user') - @utils.skip_if_microversion_not_supported("1.0") - def test_quota_defaults_api_1_0(self, role): - self._get_quotas(role, "defaults", "1.0") - - @ddt.data('admin', 'user') - @utils.skip_if_microversion_not_supported("2.0") - def test_quota_defaults_api_2_0(self, role): - self._get_quotas(role, "defaults", "2.0") - - @ddt.data('admin', 'user') - @utils.skip_if_microversion_not_supported("2.6") - def test_quota_defaults_api_2_6(self, role): - self._get_quotas(role, "defaults", "2.6") - - @ddt.data('admin', 'user') - @utils.skip_if_microversion_not_supported("2.7") - def test_quota_defaults_api_2_7(self, role): - self._get_quotas(role, "defaults", "2.7") - - @ddt.data('admin', 'user') - @utils.skip_if_microversion_not_supported("1.0") - def test_quota_show_api_1_0(self, role): - self._get_quotas(role, "show", "1.0") - - @ddt.data('admin', 'user') - @utils.skip_if_microversion_not_supported("2.0") - def test_quota_show_api_2_0(self, role): - self._get_quotas(role, "show", "2.0") - - @ddt.data('admin', 'user') - @utils.skip_if_microversion_not_supported("2.6") - def test_quota_show_api_2_6(self, role): - self._get_quotas(role, "show", "2.6") - - @ddt.data('admin', 'user') - @utils.skip_if_microversion_not_supported("2.7") - def test_quota_show_api_2_7(self, role): - self._get_quotas(role, "show", "2.7") - - @ddt.data('admin', 'user') - @utils.skip_if_microversion_not_supported("2.25") - def test_quota_show_api_2_25(self, role): - self._get_quotas(role, "show --detail", "2.25") diff --git a/manilaclient/tests/functional/test_scheduler_stats.py b/manilaclient/tests/functional/test_scheduler_stats.py deleted file mode 100644 index 6c78e718..00000000 --- a/manilaclient/tests/functional/test_scheduler_stats.py +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright (c) 2015 Clinton Knight. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from tempest.lib.common.utils import data_utils -from tempest.lib import exceptions - -from manilaclient.tests.functional import base - - -class ManilaClientTestSchedulerStatsReadOnly(base.BaseTestCase): - - def test_pools_list(self): - self.clients['admin'].manila('pool-list') - - def test_pools_list_with_debug_flag(self): - self.clients['admin'].manila('pool-list', flags='--debug') - - def test_pools_list_with_detail(self): - self.clients['admin'].manila('pool-list', params='--detail') - - def test_pools_list_with_share_type_filter(self): - share_type = self.create_share_type( - name=data_utils.rand_name('manilaclient_functional_test'), - snapshot_support=True, - ) - self.clients['admin'].manila('pool-list', - params='--share_type ' + - share_type['ID']) - - def test_pools_list_with_filters(self): - self.clients['admin'].manila( - 'pool-list', - params='--host myhost --backend mybackend --pool mypool') - - def test_pools_list_by_user(self): - self.assertRaises(exceptions.CommandFailed, - self.clients['user'].manila, - 'pool-list') diff --git a/manilaclient/tests/functional/test_security_services.py b/manilaclient/tests/functional/test_security_services.py deleted file mode 100644 index ab68dfba..00000000 --- a/manilaclient/tests/functional/test_security_services.py +++ /dev/null @@ -1,81 +0,0 @@ -# Copyright 2015 Mirantis Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import ddt -from tempest.lib.common.utils import data_utils - -from manilaclient.tests.functional import base - - -@ddt.ddt -class SecurityServiceReadWriteTest(base.BaseTestCase): - - def setUp(self): - super(SecurityServiceReadWriteTest, self).setUp() - self.name = data_utils.rand_name('autotest') - self.description = 'fake_description' - self.user = 'fake_user' - self.password = 'fake_password' - self.server = 'fake_server' - self.domain = 'fake_domain' - self.dns_ip = '1.2.3.4' - self.ou = 'fake_ou' - self.default_ad_site = 'fake_default_ad_site' - - @ddt.data( - {'name': 'test_name'}, - {'description': 'test_description'}, - {'user': 'test_username'}, - {'password': 'test_password'}, - {'server': 'test_server'}, - {'default_ad_site': 'test_default_ad_site'}, - {'domain': 'test_domain'}, - {'dns_ip': 'test_dns_ip'}, - {'ou': 'test_ou'}, - {'name': '""'}, - {'description': '""'}, - {'user': '""'}, - {'password': '""'}, - {'server': '""'}, - {'default_ad_site': '""'}, - {'domain': '""'}, - {'dns_ip': '""'}, - {'ou': '""'}, - ) - def test_create_update_security_service(self, ss_data): - expected_data = { - 'name': self.name, - 'description': self.description, - 'user': self.user, - 'password': self.password, - 'server': self.server, - 'domain': self.domain, - 'dns_ip': self.dns_ip, - 'ou': self.ou, - } - - if 'default_ad_site' in ss_data: - expected_data.pop('server') - expected_data['default_ad_site'] = self.default_ad_site - - ss = self.create_security_service(**expected_data) - update = self.admin_client.update_security_service(ss['id'], **ss_data) - expected_data.update(ss_data) - - for k, v in expected_data.items(): - if v == '""': - self.assertEqual('None', update[k]) - else: - self.assertEqual(v, update[k]) diff --git a/manilaclient/tests/functional/test_services.py b/manilaclient/tests/functional/test_services.py deleted file mode 100644 index 1d02765a..00000000 --- a/manilaclient/tests/functional/test_services.py +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright 2015 Mirantis Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import ddt - -from manilaclient.tests.functional import base - - -@ddt.ddt -class ManilaClientTestServicesReadOnly(base.BaseTestCase): - - @ddt.data("1.0", "2.0", "2.6", "2.7") - def test_services_list(self, microversion): - self.skip_if_microversion_not_supported(microversion) - self.admin_client.manila('service-list', microversion=microversion) - - def test_list_with_debug_flag(self): - self.clients['admin'].manila('service-list', flags='--debug') - - def test_shares_list_filter_by_host(self): - self.clients['admin'].manila('service-list', params='--host host') - - def test_shares_list_filter_by_binary(self): - self.clients['admin'].manila('service-list', params='--binary binary') - - def test_shares_list_filter_by_zone(self): - self.clients['admin'].manila('service-list', params='--zone zone') - - def test_shares_list_filter_by_status(self): - self.clients['admin'].manila('service-list', params='--status status') - - def test_shares_list_filter_by_state(self): - self.clients['admin'].manila('service-list', params='--state state') diff --git a/manilaclient/tests/functional/test_share_access.py b/manilaclient/tests/functional/test_share_access.py deleted file mode 100644 index 1d3bd387..00000000 --- a/manilaclient/tests/functional/test_share_access.py +++ /dev/null @@ -1,323 +0,0 @@ -# Copyright 2015 Mirantis Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import ast - -import ddt -from tempest.lib import exceptions as tempest_lib_exc - -from manilaclient import api_versions -from manilaclient import config -from manilaclient.tests.functional import base - -CONF = config.CONF - - -@ddt.ddt -class ShareAccessReadWriteBase(base.BaseTestCase): - protocol = None - access_level = None - - def setUp(self): - super(ShareAccessReadWriteBase, self).setUp() - if self.protocol not in CONF.enable_protocols: - message = "%s tests are disabled." % self.protocol - raise self.skipException(message) - if self.access_level not in CONF.access_levels_mapping.get( - self.protocol, '').split(' '): - raise self.skipException("%(level)s tests for %(protocol)s share " - "access are disabled." % { - 'level': self.access_level, - 'protocol': self.protocol - }) - self.access_types = CONF.access_types_mapping.get( - self.protocol, '').split(' ') - if not self.access_types: - raise self.skipException("No access levels were provided for %s " - "share access tests." % self.protocol) - - self.share = self.create_share(share_protocol=self.protocol, - public=True) - self.share_id = self.share['id'] - - # NOTE(vponomaryov): increase following int range when significant - # amount of new tests is added. - int_range = range(20, 50) - self.access_to = { - # NOTE(vponomaryov): list of unique values is required for ability - # to create lots of access rules for one share using different - # API microversions. - 'ip': ['99.88.77.%d' % i for i in int_range], - # NOTE(vponomaryov): following users are fakes and access rules - # that use it are expected to fail, but they are used only for - # API testing. - 'user': ['foo_user_%d' % i for i in int_range], - 'cert': ['tenant_%d.example.com' % i for i in int_range], - 'ipv6': ['2001:db8::%d' % i for i in int_range], - } - - def _test_create_list_access_rule_for_share( - self, microversion, metadata=None): - access_type = self.access_types[0] - - access = self.user_client.access_allow( - self.share['id'], access_type, self.access_to[access_type].pop(), - self.access_level, metadata=metadata, microversion=microversion) - - return access - - @ddt.data(*set([ - "1.0", "2.0", "2.6", "2.7", "2.21", "2.33", "2.44", "2.45", - api_versions.MAX_VERSION])) - def test_create_list_access_rule_for_share(self, microversion): - self.skip_if_microversion_not_supported(microversion) - access = self._test_create_list_access_rule_for_share( - microversion=microversion) - access_list = self.user_client.list_access( - self.share['id'], - microversion=microversion - ) - self.assertTrue(any( - [item for item in access_list if access['id'] == item['id']])) - self.assertTrue(any(a['access_type'] is not None for a in access_list)) - self.assertTrue(any(a['access_to'] is not None for a in access_list)) - self.assertTrue(any(a['access_level'] is not None - for a in access_list)) - if (api_versions.APIVersion(microversion) >= - api_versions.APIVersion("2.33")): - self.assertTrue( - all(all(key in access for key in ( - 'access_key', 'created_at', 'updated_at')) - for access in access_list)) - elif (api_versions.APIVersion(microversion) >= - api_versions.APIVersion("2.21")): - self.assertTrue(all('access_key' in a for a in access_list)) - else: - self.assertTrue(all('access_key' not in a for a in access_list)) - - @ddt.data("1.0", "2.0", "2.6", "2.7") - def test_create_list_access_rule_for_share_select_column( - self, - microversion): - self.skip_if_microversion_not_supported(microversion) - self._test_create_list_access_rule_for_share( - microversion=microversion) - access_list = self.user_client.list_access( - self.share['id'], - columns="access_type,access_to", - microversion=microversion - ) - self.assertTrue(any(a['Access_Type'] is not None for a in access_list)) - self.assertTrue(any(a['Access_To'] is not None for a in access_list)) - self.assertTrue(all('Access_Level' not in a for a in access_list)) - self.assertTrue(all('access_level' not in a for a in access_list)) - - def _create_delete_access_rule(self, share_id, access_type, access_to, - microversion=None): - self.skip_if_microversion_not_supported(microversion) - if access_type not in self.access_types: - raise self.skipException( - "'%(access_type)s' access rules is disabled for protocol " - "'%(protocol)s'." % {"access_type": access_type, - "protocol": self.protocol}) - - access = self.user_client.access_allow( - share_id, access_type, access_to, self.access_level, - microversion=microversion) - - self.assertEqual(share_id, access.get('share_id')) - self.assertEqual(access_type, access.get('access_type')) - self.assertEqual(access_to.replace('\\\\', '\\'), - access.get('access_to')) - self.assertEqual(self.access_level, access.get('access_level')) - if (api_versions.APIVersion(microversion) >= - api_versions.APIVersion("2.33")): - self.assertIn('access_key', access) - self.assertIn('created_at', access) - self.assertIn('updated_at', access) - elif (api_versions.APIVersion(microversion) >= - api_versions.APIVersion("2.21")): - self.assertIn('access_key', access) - else: - self.assertNotIn('access_key', access) - - self.user_client.wait_for_access_rule_status(share_id, access['id']) - self.user_client.access_deny(share_id, access['id']) - self.user_client.wait_for_access_rule_deletion(share_id, access['id']) - - self.assertRaises(tempest_lib_exc.NotFound, - self.user_client.get_access, share_id, access['id']) - - @ddt.data(*set(["2.45", api_versions.MAX_VERSION])) - def test_create_list_access_rule_with_metadata(self, microversion): - self.skip_if_microversion_not_supported(microversion) - - md1 = {"key1": "value1", "key2": "value2"} - md2 = {"key3": "value3", "key4": "value4"} - self._test_create_list_access_rule_for_share( - metadata=md1, microversion=microversion) - access = self._test_create_list_access_rule_for_share( - metadata=md2, microversion=microversion) - access_list = self.user_client.list_access( - self.share['id'], metadata={"key4": "value4"}, - microversion=microversion) - self.assertEqual(1, len(access_list)) - # Verify share metadata - get_access = self.user_client.access_show( - access_list[0]['id'], microversion=microversion) - metadata = ast.literal_eval(get_access['metadata']) - self.assertEqual(2, len(metadata)) - self.assertIn('key3', metadata) - self.assertIn('key4', metadata) - self.assertEqual(md2['key3'], metadata['key3']) - self.assertEqual(md2['key4'], metadata['key4']) - self.assertEqual(access['id'], access_list[0]['id']) - - self.user_client.access_deny(access['share_id'], access['id']) - self.user_client.wait_for_access_rule_deletion(access['share_id'], - access['id']) - - @ddt.data(*set(["2.45", api_versions.MAX_VERSION])) - def test_create_update_show_access_rule_with_metadata(self, microversion): - self.skip_if_microversion_not_supported(microversion) - - md1 = {"key1": "value1", "key2": "value2"} - md2 = {"key3": "value3", "key2": "value4"} - # create a access rule with metadata - access = self._test_create_list_access_rule_for_share( - metadata=md1, microversion=microversion) - # get the access rule - get_access = self.user_client.access_show( - access['id'], microversion=microversion) - # verify access rule - self.assertEqual(access['id'], get_access['id']) - self.assertEqual(md1, ast.literal_eval(get_access['metadata'])) - - # update access rule metadata - self.user_client.access_set_metadata( - access['id'], metadata=md2, microversion=microversion) - get_access = self.user_client.access_show( - access['id'], microversion=microversion) - - # verify access rule after update access rule metadata - self.assertEqual( - {"key1": "value1", "key2": "value4", "key3": "value3"}, - ast.literal_eval(get_access['metadata'])) - self.assertEqual(access['id'], get_access['id']) - - @ddt.data(*set(["2.45", api_versions.MAX_VERSION])) - def test_delete_access_rule_metadata(self, microversion): - self.skip_if_microversion_not_supported(microversion) - - md = {"key1": "value1", "key2": "value2"} - # create a access rule with metadata - access = self._test_create_list_access_rule_for_share( - metadata=md, microversion=microversion) - # get the access rule - get_access = self.user_client.access_show( - access['id'], microversion=microversion) - - # verify access rule - self.assertEqual(access['id'], get_access['id']) - self.assertEqual(md, ast.literal_eval(get_access['metadata'])) - - # delete access rule metadata - self.user_client.access_unset_metadata( - access['id'], keys=["key1", "key2"], microversion=microversion) - get_access = self.user_client.access_show( - access['id'], microversion=microversion) - - # verify access rule after delete access rule metadata - self.assertEqual({}, ast.literal_eval(get_access['metadata'])) - self.assertEqual(access['id'], get_access['id']) - - @ddt.data("1.0", "2.0", "2.6", "2.7", "2.21", "2.33") - def test_create_delete_ip_access_rule(self, microversion): - self._create_delete_access_rule( - self.share_id, 'ip', self.access_to['ip'].pop(), microversion) - - @ddt.data("1.0", "2.0", "2.6", "2.7", "2.21", "2.33") - def test_create_delete_user_access_rule(self, microversion): - self._create_delete_access_rule( - self.share_id, 'user', CONF.username_for_user_rules, microversion) - - @ddt.data("1.0", "2.0", "2.6", "2.7", "2.21", "2.33") - def test_create_delete_cert_access_rule(self, microversion): - self._create_delete_access_rule( - self.share_id, 'cert', self.access_to['cert'].pop(), microversion) - - @ddt.data("2.38", api_versions.MAX_VERSION) - def test_create_delete_ipv6_access_rule(self, microversion): - self._create_delete_access_rule( - self.share_id, 'ip', self.access_to['ipv6'].pop(), microversion) - - -class NFSShareRWAccessReadWriteTest(ShareAccessReadWriteBase): - protocol = 'nfs' - access_level = 'rw' - - -class NFSShareROAccessReadWriteTest(ShareAccessReadWriteBase): - protocol = 'nfs' - access_level = 'ro' - - -class CIFSShareRWAccessReadWriteTest(ShareAccessReadWriteBase): - protocol = 'cifs' - access_level = 'rw' - - -class CIFSShareROAccessReadWriteTest(ShareAccessReadWriteBase): - protocol = 'cifs' - access_level = 'ro' - - -class GlusterFSShareRWAccessReadWriteTest(ShareAccessReadWriteBase): - protocol = 'glusterfs' - access_level = 'rw' - - -class GlusterFSShareROAccessReadWriteTest(ShareAccessReadWriteBase): - protocol = 'glusterfs' - access_level = 'ro' - - -class HDFSShareRWAccessReadWriteTest(ShareAccessReadWriteBase): - protocol = 'hdfs' - access_level = 'rw' - - -class HDFSShareROAccessReadWriteTest(ShareAccessReadWriteBase): - protocol = 'hdfs' - access_level = 'ro' - - -class MAPRFSShareRWAccessReadWriteTest(ShareAccessReadWriteBase): - protocol = 'maprfs' - access_level = 'rw' - - -class MAPRFSShareROAccessReadWriteTest(ShareAccessReadWriteBase): - protocol = 'maprfs' - access_level = 'ro' - - -def load_tests(loader, tests, _): - result = [] - for test_case in tests: - if type(test_case._tests[0]) is ShareAccessReadWriteBase: - continue - result.append(test_case) - return loader.suiteClass(result) diff --git a/manilaclient/tests/functional/test_share_network_subnets.py b/manilaclient/tests/functional/test_share_network_subnets.py deleted file mode 100644 index 49c790fd..00000000 --- a/manilaclient/tests/functional/test_share_network_subnets.py +++ /dev/null @@ -1,119 +0,0 @@ -# Copyright 2019 NetApp -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import ddt -from manilaclient.tests.functional import base -from manilaclient.tests.functional import utils -from tempest.lib.common.utils import data_utils -from tempest.lib import exceptions - - -@ddt.ddt -@utils.skip_if_microversion_not_supported('2.51') -class ShareNetworkSubnetsReadWriteTest(base.BaseTestCase): - - def setUp(self): - super(ShareNetworkSubnetsReadWriteTest, self).setUp() - self.name = data_utils.rand_name('autotest') - self.description = 'fake_description' - self.neutron_net_id = 'fake_neutron_net_id' - self.neutron_subnet_id = 'fake_neutron_subnet_id' - - self.sn = self.create_share_network( - name=self.name, - description=self.description, - neutron_net_id=self.neutron_net_id, - neutron_subnet_id=self.neutron_subnet_id, - ) - - def test_get_share_network_subnet(self): - default_subnet = utils.get_default_subnet(self.user_client, - self.sn['id']) - - subnet = self.user_client.get_share_network_subnet( - self.sn['id'], default_subnet['id']) - - self.assertEqual(self.neutron_net_id, subnet['neutron_net_id']) - self.assertEqual(self.neutron_subnet_id, subnet['neutron_subnet_id']) - - def test_get_invalid_share_network_subnet(self): - self.assertRaises( - exceptions.CommandFailed, - self.user_client.get_share_network_subnet, - self.sn['id'], 'invalid_subnet_id') - - def _get_availability_zone(self): - availability_zones = self.user_client.list_availability_zones() - return availability_zones[0]['Name'] - - def test_add_share_network_subnet_to_share_network(self): - neutron_net_id = 'new_neutron_net_id' - neutron_subnet_id = 'new_neutron_subnet_id' - availability_zone = self._get_availability_zone() - - subnet = self.add_share_network_subnet( - self.sn['id'], - neutron_net_id, neutron_subnet_id, - availability_zone, - cleanup_in_class=False) - - self.assertEqual(neutron_net_id, subnet['neutron_net_id']) - self.assertEqual(neutron_subnet_id, subnet['neutron_subnet_id']) - self.assertEqual(availability_zone, subnet['availability_zone']) - - @ddt.data( - {'neutron_net_id': None, 'neutron_subnet_id': 'fake_subnet_id'}, - {'neutron_net_id': 'fake_net_id', 'neutron_subnet_id': None}, - {'availability_zone': 'invalid_availability_zone'}, - ) - def test_add_invalid_share_network_subnet_to_share_network(self, params): - self.assertRaises( - exceptions.CommandFailed, - self.add_share_network_subnet, - self.sn['id'], - **params) - - def test_add_share_network_subnet_to_invalid_share_network(self): - self.assertRaises( - exceptions.CommandFailed, - self.add_share_network_subnet, - 'invalid_share_network', - self.neutron_net_id, - self.neutron_subnet_id) - - def test_add_delete_share_network_subnet_from_share_network(self): - neutron_net_id = 'new_neutron_net_id' - neutron_subnet_id = 'new_neutron_subnet_id' - availability_zone = self._get_availability_zone() - - subnet = self.add_share_network_subnet( - self.sn['id'], - neutron_net_id, neutron_subnet_id, - availability_zone, - cleanup_in_class=False) - self.user_client.delete_share_network_subnet( - share_network_subnet=subnet['id'], - share_network=self.sn['id']) - - self.user_client.wait_for_share_network_subnet_deletion( - share_network_subnet=subnet['id'], - share_network=self.sn['id']) - - def test_delete_invalid_share_network_subnet(self): - self.assertRaises( - exceptions.NotFound, - self.user_client.delete_share_network_subnet, - share_network_subnet='invalid_subnet_id', - share_network=self.sn['id']) diff --git a/manilaclient/tests/functional/test_share_networks.py b/manilaclient/tests/functional/test_share_networks.py deleted file mode 100644 index 49d49277..00000000 --- a/manilaclient/tests/functional/test_share_networks.py +++ /dev/null @@ -1,587 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2015 Mirantis Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import ast -import ddt -from tempest.lib.common.utils import data_utils -from tempest.lib import exceptions as tempest_lib_exc -import time - -from manilaclient import config -from manilaclient import exceptions -from manilaclient.tests.functional import base -from manilaclient.tests.functional import utils - -SECURITY_SERVICE_UPDATE_VERSION = '2.63' -CONF = config.CONF - - -@ddt.ddt -class ShareNetworksReadWriteTest(base.BaseTestCase): - - def setUp(self): - super(ShareNetworksReadWriteTest, self).setUp() - self.name = data_utils.rand_name('autotest') - self.description = 'fake_description' - self.neutron_net_id = 'fake_neutron_net_id' - self.neutron_subnet_id = 'fake_neutron_subnet_id' - - self.sn = self.create_share_network( - name=self.name, - description=self.description, - neutron_net_id=self.neutron_net_id, - neutron_subnet_id=self.neutron_subnet_id, - ) - - @ddt.data( - {'name': data_utils.rand_name('autotest_share_network_name')}, - {'description': 'fake_description'}, - {'neutron_net_id': 'fake_neutron_net_id', - 'neutron_subnet_id': 'fake_neutron_subnet_id'}, - ) - def test_create_delete_share_network(self, net_data): - share_subnet_support = utils.share_network_subnets_are_supported() - share_subnet_fields = ( - ['neutron_net_id', 'neutron_subnet_id', 'availability_zone'] - if share_subnet_support else []) - sn = self.create_share_network(cleanup_in_class=False, **net_data) - default_subnet = (utils.get_default_subnet(self.user_client, sn['id']) - if share_subnet_support - else None) - - expected_data = { - 'name': 'None', - 'description': 'None', - 'neutron_net_id': 'None', - 'neutron_subnet_id': 'None', - } - expected_data.update(net_data) - share_network_expected_data = [ - (k, v) for k, v in expected_data.items() - if k not in share_subnet_fields] - share_subnet_expected_data = [ - (k, v) for k, v in expected_data.items() - if k in share_subnet_fields] - - for k, v in share_network_expected_data: - self.assertEqual(v, sn[k]) - for k, v in share_subnet_expected_data: - self.assertEqual(v, default_subnet[k]) - - self.admin_client.delete_share_network(sn['id']) - self.admin_client.wait_for_share_network_deletion(sn['id']) - - @utils.skip_if_microversion_not_supported('2.51') - def test_create_delete_share_network_with_az(self): - share_subnet_fields = ( - ['neutron_net_id', 'neutron_subnet_id', 'availability_zone']) - az = self.user_client.list_availability_zones()[0] - net_data = { - 'neutron_net_id': 'fake_neutron_net_id', - 'neutron_subnet_id': 'fake_neutron_subnet_id', - 'availability_zone': az['Name'] - } - sn = self.create_share_network(cleanup_in_class=False, **net_data) - default_subnet = utils.get_subnet_by_availability_zone_name( - self.user_client, sn['id'], az['Name']) - - expected_data = { - 'name': 'None', - 'description': 'None', - 'neutron_net_id': 'None', - 'neutron_subnet_id': 'None', - 'availability_zone': 'None', - } - expected_data.update(net_data) - share_network_expected_data = [ - (k, v) for k, v in expected_data.items() - if k not in share_subnet_fields] - share_subnet_expected_data = [ - (k, v) for k, v in expected_data.items() - if k in share_subnet_fields] - - for k, v in share_network_expected_data: - self.assertEqual(v, sn[k]) - for k, v in share_subnet_expected_data: - self.assertEqual(v, default_subnet[k]) - - self.admin_client.delete_share_network(sn['id']) - self.admin_client.wait_for_share_network_deletion(sn['id']) - - def test_get_share_network_with_neutron_data(self): - get = self.admin_client.get_share_network(self.sn['id']) - - self.assertEqual(self.name, get['name']) - self.assertEqual(self.description, get['description']) - if not utils.share_network_subnets_are_supported(): - self.assertEqual(self.neutron_net_id, get['neutron_net_id']) - self.assertEqual(self.neutron_subnet_id, get['neutron_subnet_id']) - - def _get_expected_update_data(self, net_data, net_creation_data): - # NOTE(dviroel): When subnets are supported, the outputs are converted - # from string to literal structures in order to process the content of - # 'share_network_subnets' field. - default_return_value = ( - None if utils.share_network_subnets_are_supported() else 'None') - - expected_nn_id = ( - default_return_value - if net_data.get('neutron_net_id') - else net_creation_data.get('neutron_net_id', default_return_value)) - expected_nsn_id = ( - default_return_value - if net_data.get('neutron_subnet_id') - else net_creation_data.get('neutron_subnet_id', - default_return_value)) - return expected_nn_id, expected_nsn_id - - @ddt.data( - ({'name': data_utils.rand_name('autotest_share_network_name')}, {}), - ({'description': 'fake_description'}, {}), - ({'neutron_net_id': 'fake_neutron_net_id', - 'neutron_subnet_id': 'fake_neutron_subnet_id'}, {}), - ({'name': '""'}, {}), - ({'description': '""'}, {}), - ({'neutron_net_id': '""'}, - {'neutron_net_id': 'fake_nn_id', 'neutron_subnet_id': 'fake_nsn_id'}), - ({'neutron_subnet_id': '""'}, - {'neutron_net_id': 'fake_nn_id', 'neutron_subnet_id': 'fake_nsn_id'}) - ) - @ddt.unpack - def test_create_update_share_network(self, net_data, net_creation_data): - sn = self.create_share_network( - cleanup_in_class=False, **net_creation_data) - - update = self.admin_client.update_share_network(sn['id'], **net_data) - - expected_nn_id, expected_nsn_id = self._get_expected_update_data( - net_data, net_creation_data) - - expected_data = { - 'name': 'None', - 'description': 'None', - 'neutron_net_id': expected_nn_id, - 'neutron_subnet_id': expected_nsn_id, - } - subnet_keys = [] - if utils.share_network_subnets_are_supported(): - subnet_keys = ['neutron_net_id', 'neutron_subnet_id'] - subnet = ast.literal_eval(update['share_network_subnets']) - - update_values = dict([(k, v) for k, v in net_data.items() - if v != '""']) - expected_data.update(update_values) - - for k, v in expected_data.items(): - if k in subnet_keys: - self.assertEqual(v, subnet[0][k]) - else: - self.assertEqual(v, update[k]) - - self.admin_client.delete_share_network(sn['id']) - self.admin_client.wait_for_share_network_deletion(sn['id']) - - @ddt.data(True, False) - def test_list_share_networks(self, all_tenants): - share_networks = self.admin_client.list_share_networks(all_tenants) - - self.assertTrue( - any(self.sn['id'] == sn['id'] for sn in share_networks)) - for sn in share_networks: - self.assertEqual(2, len(sn)) - self.assertIn('id', sn) - self.assertIn('name', sn) - - def test_list_share_networks_select_column(self): - share_networks = self.admin_client.list_share_networks(columns="id") - self.assertTrue(any(s['Id'] is not None for s in share_networks)) - self.assertTrue(all('Name' not in s for s in share_networks)) - self.assertTrue(all('name' not in s for s in share_networks)) - - def _list_share_networks_with_filters(self, filters): - assert_subnet_fields = utils.share_network_subnets_are_supported() - share_subnet_fields = (['neutron_subnet_id', 'neutron_net_id'] - if assert_subnet_fields - else []) - share_network_filters = [(k, v) for k, v in filters.items() - if k not in share_subnet_fields] - share_network_subnet_filters = [(k, v) for k, v in filters.items() - if k in share_subnet_fields] - share_networks = self.admin_client.list_share_networks(filters=filters) - - self.assertGreater(len(share_networks), 0) - self.assertTrue( - any(self.sn['id'] == sn['id'] for sn in share_networks)) - for sn in share_networks: - try: - share_network = self.admin_client.get_share_network(sn['id']) - default_subnet = ( - utils.get_default_subnet(self.user_client, sn['id']) - if assert_subnet_fields - else None) - except tempest_lib_exc.NotFound: - # NOTE(vponomaryov): Case when some share network was deleted - # between our 'list' and 'get' requests. Skip such case. - continue - for k, v in share_network_filters: - self.assertIn(k, share_network) - self.assertEqual(v, share_network[k]) - for k, v in share_network_subnet_filters: - self.assertIn(k, default_subnet) - self.assertEqual(v, default_subnet[k]) - - def test_list_share_networks_filter_by_project_id(self): - project_id = self.admin_client.get_project_id( - self.admin_client.tenant_name) - filters = {'project_id': project_id} - self._list_share_networks_with_filters(filters) - - def test_list_share_networks_filter_by_name(self): - filters = {'name': self.name} - self._list_share_networks_with_filters(filters) - - def test_list_share_networks_filter_by_description(self): - filters = {'description': self.description} - self._list_share_networks_with_filters(filters) - - def test_list_share_networks_filter_by_neutron_net_id(self): - filters = {'neutron_net_id': self.neutron_net_id} - self._list_share_networks_with_filters(filters) - - def test_list_share_networks_filter_by_neutron_subnet_id(self): - filters = {'neutron_subnet_id': self.neutron_subnet_id} - self._list_share_networks_with_filters(filters) - - @ddt.data('name', 'description') - def test_list_share_networks_filter_by_inexact(self, option): - self.create_share_network( - name=data_utils.rand_name('autotest_inexact'), - description='fake_description_inexact', - neutron_net_id='fake_neutron_net_id', - neutron_subnet_id='fake_neutron_subnet_id', - ) - - filters = {option + '~': 'inexact'} - share_networks = self.admin_client.list_share_networks( - filters=filters) - - self.assertGreater(len(share_networks), 0) - - def test_list_share_networks_by_inexact_unicode_option(self): - self.create_share_network( - name=u'网络名称', - description=u'网络描述', - neutron_net_id='fake_neutron_net_id', - neutron_subnet_id='fake_neutron_subnet_id', - ) - - filters = {'name~': u'名称'} - share_networks = self.admin_client.list_share_networks( - filters=filters) - - self.assertGreater(len(share_networks), 0) - - filters = {'description~': u'描述'} - share_networks = self.admin_client.list_share_networks( - filters=filters) - - self.assertGreater(len(share_networks), 0) - - def test_share_network_reset_status(self): - share_network = self.create_share_network( - client=self.user_client, - name='cool_net_name', - description='fakedescription', - neutron_net_id='fake_neutron_net_id', - neutron_subnet_id='fake_neutron_subnet_id', - ) - - # Admin operation - self.admin_client.share_network_reset_state( - share_network['id'], 'error', - microversion=SECURITY_SERVICE_UPDATE_VERSION) - - self.user_client.wait_for_resource_status( - share_network['id'], 'error', - microversion=SECURITY_SERVICE_UPDATE_VERSION, - resource_type="share_network") - - def test_share_network_security_service_add(self): - share_network = self.create_share_network( - client=self.user_client, - name='cool_net_name', - description='fakedescription', - neutron_net_id='fake_neutron_net_id', - neutron_subnet_id='fake_neutron_subnet_id', - ) - new_security_service = self.create_security_service( - client=self.user_client) - - check_result = ( - self.user_client.share_network_security_service_add_check( - share_network['id'], - security_service_id=new_security_service['id'])) - - self.assertEqual(check_result['compatible'], 'True') - - self.user_client.share_network_security_service_add( - share_network['id'], new_security_service['id']) - - network_services = ( - self.user_client.share_network_security_service_list( - share_network['id'])) - - self.assertEqual(len(network_services), 1) - self.assertEqual( - network_services[0]['id'], new_security_service['id']) - - def test_share_network_security_service_update(self): - share_network = self.create_share_network( - client=self.user_client, - name='cool_net_name', - description='fakedescription', - neutron_net_id='fake_neutron_net_id', - neutron_subnet_id='fake_neutron_subnet_id', - ) - current_name = 'current' - new_name = 'new' - current_security_service = self.create_security_service( - client=self.user_client, name=current_name) - new_security_service = self.create_security_service( - client=self.user_client, name=new_name) - - check_result = ( - self.user_client.share_network_security_service_add_check( - share_network['id'], current_security_service['id'])) - - self.assertEqual(check_result['compatible'], 'True') - - self.user_client.share_network_security_service_add( - share_network['id'], current_security_service['id']) - - network_services = ( - self.user_client.share_network_security_service_list( - share_network['id'])) - - self.assertEqual(len(network_services), 1) - self.assertEqual(network_services[0]['name'], current_name) - - check_result = ( - self.user_client.share_network_security_service_update_check( - share_network['id'], current_security_service['id'], - new_security_service['id'])) - - self.assertEqual(check_result['compatible'], 'True') - - self.user_client.share_network_security_service_update( - share_network['id'], current_security_service['id'], - new_security_service['id']) - - network_services = ( - self.user_client.share_network_security_service_list( - share_network['id'])) - - self.assertEqual(len(network_services), 1) - self.assertEqual(network_services[0]['name'], new_name) - - def test_share_network_subnet_create_check(self): - share_network = self.create_share_network( - client=self.user_client, - description='fakedescription', - ) - - check_result = ( - self.user_client.share_network_subnet_create_check( - share_network['id'], neutron_net_id='fake_neutron_net_id', - neutron_subnet_id='fake_neutron_subnet_id')) - - self.assertEqual(check_result['compatible'], 'True') - - @ddt.data( - {'neutron_net_id': None, 'neutron_subnet_id': 'fake_subnet_id'}, - {'neutron_net_id': 'fake_net_id', 'neutron_subnet_id': None}, - {'availability_zone': 'invalid_availability_zone'}, - ) - def test_check_add_share_network_subnet_with_invalid_params(self, params): - self.assertRaises( - tempest_lib_exc.CommandFailed, - self.user_client.share_network_subnet_create_check, - self.sn['id'], - **params) - - def test_check_add_share_network_subnet_to_invalid_share_network(self): - self.assertRaises( - tempest_lib_exc.CommandFailed, - self.user_client.share_network_subnet_create_check, - 'invalid_share_network', - self.neutron_net_id, - self.neutron_subnet_id) - - -class ShareNetworkSecurityServiceCheckReadWriteTests(base.BaseTestCase): - protocol = None - - def setUp(self): - super(ShareNetworkSecurityServiceCheckReadWriteTests, self).setUp() - if self.protocol not in CONF.enable_protocols: - message = "%s tests are disabled." % self.protocol - raise self.skipException(message) - self.client = self.get_user_client() - if not self.client.share_network: - message = "Can run only with DHSS=True mode" - raise self.skipException(message) - - def _wait_for_update_security_service_compatible_result( - self, share_network, current_security_service, - new_security_service=None): - compatible_expected_result = 'True' - check_is_compatible = 'None' - tentatives = 0 - - # There might be a delay from the time the check is requested until - # the backend has performed all checks - while check_is_compatible != compatible_expected_result: - tentatives += 1 - if not new_security_service: - check_is_compatible = ( - self.user_client.share_network_security_service_add_check( - share_network['id'], - current_security_service['id']))['compatible'] - else: - check_is_compatible = ( - (self.user_client. - share_network_security_service_update_check( - share_network['id'], - current_security_service['id'], - new_security_service['id'])))['compatible'] - if tentatives > 3: - timeout_message = ( - "Share network security service add/update check did not " - "reach 'compatible=True' within 15 seconds.") - raise exceptions.TimeoutException(message=timeout_message) - time.sleep(5) - - def test_check_if_security_service_can_be_added_to_share_network_in_use( - self): - share_network = self.create_share_network( - client=self.user_client, - description='fakedescription', - neutron_net_id='fake_neutron_net_id', - neutron_subnet_id='fake_neutron_subnet_id', - ) - # Create a share so we can be sure that a share server will exist and - # the check will be performed in the backends - self.create_share( - self.protocol, client=self.user_client, - share_network=share_network['id']) - - current_security_service = self.create_security_service( - client=self.user_client) - - check_result = ( - self.user_client.share_network_security_service_add_check( - share_network['id'], - current_security_service['id'])) - - self.assertEqual(check_result['compatible'], 'None') - - self._wait_for_update_security_service_compatible_result( - share_network, current_security_service) - - def test_add_and_update_security_service_when_share_network_is_in_use( - self): - share_network = self.create_share_network( - client=self.user_client, - name='cool_net_name', - description='fakedescription', - neutron_net_id='fake_neutron_net_id', - neutron_subnet_id='fake_neutron_subnet_id', - ) - - # Create a share so we can be sure that a share server will exist and - # the check will be performed in the backends - self.create_share( - self.protocol, name='fake_share_name', - share_network=share_network['id'], client=self.user_client) - - current_security_service = self.create_security_service( - client=self.user_client, name='current_security_service') - new_security_service = self.create_security_service( - client=self.user_client, name='new_security_service') - - check_result = ( - self.user_client.share_network_security_service_add_check( - share_network['id'], current_security_service['id'])) - - self.assertEqual(check_result['compatible'], 'None') - - self._wait_for_update_security_service_compatible_result( - share_network, current_security_service) - - self.user_client.share_network_security_service_add( - share_network['id'], current_security_service['id']) - - network_services = ( - self.user_client.share_network_security_service_list( - share_network['id'])) - - self.assertEqual(len(network_services), 1) - self.assertEqual( - network_services[0]['name'], current_security_service['name']) - - self.user_client.wait_for_resource_status( - share_network['id'], 'active', - microversion=SECURITY_SERVICE_UPDATE_VERSION, - resource_type="share_network") - - check_result = ( - self.user_client.share_network_security_service_update_check( - share_network['id'], current_security_service['id'], - new_security_service['id'])) - - self.assertEqual(check_result['compatible'], 'None') - - self._wait_for_update_security_service_compatible_result( - share_network, current_security_service, - new_security_service=new_security_service) - - self.user_client.share_network_security_service_update( - share_network['id'], current_security_service['id'], - new_security_service['id']) - - network_services = ( - self.user_client.share_network_security_service_list( - share_network['id'])) - - self.assertEqual(len(network_services), 1) - self.assertEqual( - network_services[0]['name'], new_security_service['name']) - - self.user_client.wait_for_resource_status( - share_network['id'], 'active', - microversion=SECURITY_SERVICE_UPDATE_VERSION, - resource_type="share_network") - - -base_security_service_check = ShareNetworkSecurityServiceCheckReadWriteTests - - -class ShareNetworkSecServiceCheckRWNFSTest(base_security_service_check): - protocol = 'nfs' - - -class ShareNetworkSecServiceCheckRWTestsCIFSTest(base_security_service_check): - protocol = 'cifs' diff --git a/manilaclient/tests/functional/test_share_replica_export_locations.py b/manilaclient/tests/functional/test_share_replica_export_locations.py deleted file mode 100644 index 3f35364e..00000000 --- a/manilaclient/tests/functional/test_share_replica_export_locations.py +++ /dev/null @@ -1,102 +0,0 @@ -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import ddt -from oslo_utils import uuidutils -import testtools - -from manilaclient import config -from manilaclient.tests.functional import base -from manilaclient.tests.functional import utils - -CONF = config.CONF - - -@ddt.ddt -@testtools.skipUnless(CONF.run_replication_tests, - "Replication tests are disabled.") -@utils.skip_if_microversion_not_supported('2.47') -class ShareReplicaExportLocationsTest(base.BaseTestCase): - - def _create_share_and_replica(self): - replication_type = CONF.replication_type - share_type = self.create_share_type( - driver_handles_share_servers=False, - extra_specs={'replication_type': replication_type}) - share = self.create_share(share_type=share_type['ID'], - client=self.get_user_client()) - share_replica = self.create_share_replica(share['id']) - return share, share_replica - - @ddt.data('admin', 'user') - def test_list_share_export_locations(self, role): - share, share_replica = self._create_share_and_replica() - client = self.admin_client if role == 'admin' else self.user_client - export_locations = client.list_share_replica_export_locations( - share_replica['id']) - - self.assertGreater(len(export_locations), 0) - expected_keys = ['ID', 'Path', 'Preferred', 'Replica State', - 'Availability Zone'] - - for el in export_locations: - for key in expected_keys: - self.assertIn(key, el) - self.assertTrue(uuidutils.is_uuid_like(el['ID'])) - self.assertIn(el['Preferred'], ('True', 'False')) - - @ddt.data('admin', 'user') - def test_list_share_export_locations_with_columns(self, role): - share, share_replica = self._create_share_and_replica() - client = self.admin_client if role == 'admin' else self.user_client - export_locations = client.list_share_replica_export_locations( - share_replica['id'], columns='id,path') - - self.assertGreater(len(export_locations), 0) - expected_keys = ('Id', 'Path') - unexpected_keys = ('Updated At', 'Created At') - for el in export_locations: - for key in expected_keys: - self.assertIn(key, el) - for key in unexpected_keys: - self.assertNotIn(key, el) - self.assertTrue(uuidutils.is_uuid_like(el['Id'])) - - @ddt.data('admin', 'user') - def test_get_share_replica_export_location(self, role): - share, share_replica = self._create_share_and_replica() - client = self.admin_client if role == 'admin' else self.user_client - export_locations = client.list_share_replica_export_locations( - share_replica['id']) - - el = client.get_share_replica_export_location( - share_replica['id'], export_locations[0]['ID']) - - expected_keys = ['path', 'updated_at', 'created_at', 'id', - 'preferred', 'replica_state', 'availability_zone'] - if role == 'admin': - expected_keys.extend(['is_admin_only', 'share_instance_id']) - for key in expected_keys: - self.assertIn(key, el) - if role == 'admin': - self.assertTrue(uuidutils.is_uuid_like(el['share_instance_id'])) - self.assertIn(el['is_admin_only'], ('True', 'False')) - self.assertTrue(uuidutils.is_uuid_like(el['id'])) - self.assertIn(el['preferred'], ('True', 'False')) - for list_k, get_k in ( - ('ID', 'id'), ('Path', 'path'), ('Preferred', 'preferred'), - ('Replica State', 'replica_state'), - ('Availability Zone', 'availability_zone')): - self.assertEqual( - export_locations[0][list_k], el[get_k]) diff --git a/manilaclient/tests/functional/test_share_replicas.py b/manilaclient/tests/functional/test_share_replicas.py deleted file mode 100644 index 96e42cfd..00000000 --- a/manilaclient/tests/functional/test_share_replicas.py +++ /dev/null @@ -1,49 +0,0 @@ -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from manilaclient import config -from manilaclient.tests.functional import base -from manilaclient.tests.functional import utils - -CONF = config.CONF - - -@utils.skip_if_microversion_not_supported('2.72') -class ShareReplicasTest(base.BaseTestCase): - - def _create_share_and_replica(self): - replication_type = CONF.replication_type - share_type = self.create_share_type( - driver_handles_share_servers=True, - extra_specs={'replication_type': replication_type}) - share_network = self.create_share_network() - share = self.create_share( - share_type=share_type['ID'], - share_network=share_network['id'], - client=self.get_user_client()) - share_replica = self.create_share_replica( - share['id'], - share_network=share_network['id'], - wait_for_creation=True, - client=self.get_user_client()) - return share, share_replica - - def test_share_replica_create(self): - share, share_replica = self._create_share_and_replica() - self.assertEqual(share['id'], share_replica['share_id']) - - def test_share_replica_delete(self): - share, share_replica = self._create_share_and_replica() - self.user_client.delete_share_replica(share_replica['id']) - self.user_client.wait_for_share_replica_deletion(share_replica['id']) diff --git a/manilaclient/tests/functional/test_share_servers.py b/manilaclient/tests/functional/test_share_servers.py deleted file mode 100644 index e71ac00d..00000000 --- a/manilaclient/tests/functional/test_share_servers.py +++ /dev/null @@ -1,364 +0,0 @@ -# Copyright 2015 Mirantis Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import ast -import ddt -import testtools - -from tempest.lib.common.utils import data_utils -from tempest.lib import exceptions - -from manilaclient.common import constants -from manilaclient import config -from manilaclient.tests.functional import base -from manilaclient.tests.functional import utils - -CONF = config.CONF - - -@ddt.ddt -class ShareServersReadOnlyTest(base.BaseTestCase): - - def setUp(self): - super(ShareServersReadOnlyTest, self).setUp() - self.client = self.get_admin_client() - - def test_share_server_list(self): - self.client.list_share_servers() - - def test_share_server_list_with_host_param(self): - self.client.list_share_servers(filters={'host': 'fake_host'}) - - def test_share_server_list_with_status_param(self): - self.client.list_share_servers(filters={'status': 'fake_status'}) - - def test_share_server_list_with_share_network_param(self): - self.client.list_share_servers(filters={'share_network': 'fake_sn'}) - - def test_share_server_list_with_project_id_param(self): - self.client.list_share_servers( - filters={'project_id': 'fake_project_id'}) - - @ddt.data( - 'host', 'status', 'project_id', 'share_network', - 'host,status,project_id,share_network', - ) - def test_share_server_list_with_specified_columns(self, columns): - self.client.list_share_servers(columns=columns) - - def test_share_server_list_by_user(self): - self.assertRaises( - exceptions.CommandFailed, self.user_client.list_share_servers) - - -@ddt.ddt -class ShareServersReadWriteBase(base.BaseTestCase): - - protocol = None - - def setUp(self): - super(ShareServersReadWriteBase, self).setUp() - if not CONF.run_share_servers_tests: - message = "share-server tests are disabled." - raise self.skipException(message) - if self.protocol not in CONF.enable_protocols: - message = "%s tests are disabled." % self.protocol - raise self.skipException(message) - self.client = self.get_admin_client() - if not self.client.share_network: - message = "Can run only with DHSS=True mode" - raise self.skipException(message) - - def _create_share_and_share_network(self): - name = data_utils.rand_name('autotest_share_name') - description = data_utils.rand_name('autotest_share_description') - - common_share_network = self.client.get_share_network( - self.client.share_network) - share_net_info = ( - utils.get_default_subnet(self.user_client, - common_share_network['id']) - if utils.share_network_subnets_are_supported() - else common_share_network) - neutron_net_id = ( - share_net_info['neutron_net_id'] - if 'none' not in share_net_info['neutron_net_id'].lower() - else None) - neutron_subnet_id = ( - share_net_info['neutron_subnet_id'] - if 'none' not in share_net_info['neutron_subnet_id'].lower() - else None) - share_network = self.client.create_share_network( - neutron_net_id=neutron_net_id, - neutron_subnet_id=neutron_subnet_id, - ) - - self.share = self.create_share( - share_protocol=self.protocol, - size=1, - name=name, - description=description, - share_network=share_network['id'], - client=self.client, - wait_for_creation=True - ) - self.share = self.client.get_share(self.share['id']) - return self.share, share_network - - def _delete_share_and_share_server(self, share_id, share_server_id): - # Delete share - self.client.delete_share(share_id) - self.client.wait_for_share_deletion(share_id) - - # Delete share server - self.client.delete_share_server(share_server_id) - self.client.wait_for_share_server_deletion(share_server_id) - - def test_get_and_delete_share_server(self): - self.share, share_network = self._create_share_and_share_network() - share_server_id = self.client.get_share( - self.share['id'])['share_server_id'] - - # Get share server - server = self.client.get_share_server(share_server_id) - expected_keys = ( - 'id', 'host', 'status', 'created_at', 'updated_at', - 'share_network_id', 'share_network_name', 'project_id', - ) - - if utils.is_microversion_supported('2.49'): - expected_keys += ('identifier', 'is_auto_deletable') - - for key in expected_keys: - self.assertIn(key, server) - - self._delete_share_and_share_server(self.share['id'], share_server_id) - self.client.delete_share_network(share_network['id']) - - @testtools.skipUnless( - CONF.run_manage_tests, 'Share Manage/Unmanage tests are disabled.') - @utils.skip_if_microversion_not_supported('2.49') - def test_manage_and_unmanage_share_server(self): - share, share_network = self._create_share_and_share_network() - share_server_id = self.client.get_share( - self.share['id'])['share_server_id'] - server = self.client.get_share_server(share_server_id) - server_host = server['host'] - export_location = self.client.list_share_export_locations( - self.share['id'])[0]['Path'] - share_host = share['host'] - identifier = server['identifier'] - - self.assertEqual('True', server['is_auto_deletable']) - - # Unmanages share - self.client.unmanage_share(share['id']) - self.client.wait_for_share_deletion(share['id']) - - server = self.client.get_share_server(share_server_id) - self.assertEqual('False', server['is_auto_deletable']) - - # Unmanages share server - self.client.unmanage_server(share_server_id) - self.client.wait_for_share_server_deletion(share_server_id) - - # Manage share server - managed_share_server_id = self.client.share_server_manage( - server_host, share_network['id'], identifier) - self.client.wait_for_resource_status( - managed_share_server_id, constants.STATUS_ACTIVE, - resource_type='share_server') - - managed_server = self.client.get_share_server(managed_share_server_id) - self.assertEqual('False', managed_server['is_auto_deletable']) - - # Manage share - managed_share_id = self.client.manage_share( - share_host, self.protocol, export_location, - managed_share_server_id) - self.client.wait_for_resource_status(managed_share_id, - constants.STATUS_AVAILABLE) - - self._delete_share_and_share_server(managed_share_id, - managed_share_server_id) - self.client.delete_share_network(share_network['id']) - - -class ShareServersReadWriteNFSTest(ShareServersReadWriteBase): - protocol = 'nfs' - - -class ShareServersReadWriteCIFSTest(ShareServersReadWriteBase): - protocol = 'cifs' - - -@ddt.ddt -@utils.skip_if_microversion_not_supported('2.57') -class ShareServersMigrationBase(base.BaseTestCase): - - protocol = None - - def setUp(self): - super(ShareServersMigrationBase, self).setUp() - if not CONF.run_share_servers_tests: - message = "Share-server tests are disabled." - raise self.skipException(message) - if self.protocol not in CONF.enable_protocols: - message = "%s tests are disabled." % self.protocol - raise self.skipException(message) - self.client = self.get_admin_client() - if not self.client.share_network: - message = "Can run only with DHSS=True mode" - raise self.skipException(message) - if not CONF.run_share_servers_migration_tests: - message = "Share server migration tests are disabled." - raise self.skipException(message) - - def _create_share_and_share_network(self): - name = data_utils.rand_name('autotest_share_name') - description = data_utils.rand_name('autotest_share_description') - - common_share_network = self.client.get_share_network( - self.client.share_network) - share_net_info = utils.get_default_subnet(self.client, - common_share_network['id']) - - neutron_net_id = ( - share_net_info['neutron_net_id'] - if 'none' not in share_net_info['neutron_net_id'].lower() - else None) - neutron_subnet_id = ( - share_net_info['neutron_subnet_id'] - if 'none' not in share_net_info['neutron_subnet_id'].lower() - else None) - share_network = self.client.create_share_network( - neutron_net_id=neutron_net_id, - neutron_subnet_id=neutron_subnet_id, - ) - share_type = self.create_share_type( - data_utils.rand_name('test_share_type'), - driver_handles_share_servers=True) - - share = self.create_share( - share_protocol=self.protocol, - size=1, - name=name, - description=description, - share_type=share_type['ID'], - share_network=share_network['id'], - client=self.client, - wait_for_creation=True - ) - share = self.client.get_share(share['id']) - return share, share_network - - @ddt.data('cancel', 'complete') - def test_share_server_migration(self, operation): - - # Create a share and share network to be used in the tests. - share, share_network = self._create_share_and_share_network() - share_server_id = share['share_server_id'] - src_host = share['host'].split('#')[0] - pools = self.admin_client.pool_list(detail=True) - - host_list = list() - # Filter the backends DHSS True and different - # than the source host. - for hosts in pools: - host_name = hosts['Name'].split('#')[0] - if (ast.literal_eval(hosts['Capabilities']).get( - 'driver_handles_share_servers') and - host_name != src_host): - host_list.append(host_name) - - host_list = list(set(host_list)) - # If not found any host we need skip the test. - if len(host_list) == 0: - raise self.skipException("No hosts available for " - "share server migration.") - - dest_backend = None - # If found at least one host, we still need to verify the - # share server migration compatibility with the destination host. - for host in host_list: - compatibility = self.admin_client.share_server_migration_check( - server_id=share_server_id, dest_host=host, - writable=False, nondisruptive=False, preserve_snapshots=False, - new_share_network=None) - # If found at least one compatible host, we will use it. - if compatibility['compatible']: - dest_host = host - # If not found, we need skip the test. - if dest_backend is not None: - raise self.skipException("No hosts compatible to perform a " - "share server migration.") - - # Start the share server migration - self.admin_client.share_server_migration_start( - share_server_id, dest_host) - - server = self.admin_client.get_share_server(share_server_id) - share = self.admin_client.get_share(share['id']) - self.assertEqual(constants.STATUS_SERVER_MIGRATING, share['status']) - - # Wait for the share server migration driver phase 1 done. - task_state = constants.TASK_STATE_MIGRATION_DRIVER_PHASE1_DONE - server = self.admin_client.wait_for_server_migration_task_state( - share_server_id, dest_host, task_state) - migration_progress = ( - self.admin_client.share_server_migration_get_progress( - share_server_id)) - dest_share_server_id = migration_progress.get( - 'destination_share_server_id') - - # Call share server migration complete or cancel operations - # according the ddt. - if operation == 'complete': - task_state = constants.TASK_STATE_MIGRATION_SUCCESS - self.admin_client.share_server_migration_complete( - share_server_id) - server = self.admin_client.wait_for_server_migration_task_state( - dest_share_server_id, dest_host, task_state) - - self.admin_client.wait_for_share_server_deletion(share_server_id) - else: - self.admin_client.share_server_migration_cancel(server['id']) - task_state = constants.TASK_STATE_MIGRATION_CANCELLED - # Wait for the respectives task state for each operation above. - server = self.admin_client.wait_for_server_migration_task_state( - server['id'], dest_host, task_state) - - # Check if the share is available again. - share = self.admin_client.get_share(share['id']) - self.assertEqual('available', share['status']) - - -class ShareServersMigrationNFSTest(ShareServersMigrationBase): - protocol = 'nfs' - - -class ShareServersMigrationCIFSTest(ShareServersMigrationBase): - protocol = 'cifs' - - -def load_tests(loader, tests, _): - result = [] - for test_case in tests: - if type(test_case._tests[0]) is ShareServersReadWriteBase: - continue - if type(test_case._tests[0]) is ShareServersMigrationBase: - continue - result.append(test_case) - return loader.suiteClass(result) diff --git a/manilaclient/tests/functional/test_share_transfers.py b/manilaclient/tests/functional/test_share_transfers.py deleted file mode 100644 index 84621398..00000000 --- a/manilaclient/tests/functional/test_share_transfers.py +++ /dev/null @@ -1,95 +0,0 @@ -# Copyright (c) 2022 China Telecom Digital Intelligence. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from tempest.lib.common.utils import data_utils - -from manilaclient.tests.functional import base - - -class ShareTransferTests(base.BaseTestCase): - """Check of base share transfers command""" - - def setUp(self): - super(ShareTransferTests, self).setUp() - self.share_type = self.create_share_type( - name=data_utils.rand_name('test_share_type'), - driver_handles_share_servers=False) - - def test_transfer_create_list_show_delete(self): - """Create, list, show and delete a share transfer""" - self.skip_if_microversion_not_supported('2.77') - share = self.create_share( - share_protocol='nfs', - size=1, - name=data_utils.rand_name('autotest_share_name'), - client=self.user_client, - share_type=self.share_type['ID'], - use_wait_option=True) - self.assertEqual("available", share['status']) - # create share transfer - transfer = self.create_share_transfer(share['id'], - name='test_share_transfer') - self.assertIn('auth_key', transfer) - - # list share transfers - transfers = self.list_share_transfer() - # We must have at least one transfer - self.assertTrue(len(transfers) > 0) - - # show the share transfer - transfer_show = self.get_share_transfer(transfer['id']) - self.assertEqual(transfer_show['name'], transfer['name']) - self.assertNotIn('auth_key', transfer_show) - - # delete share transfer - self.delete_share_transfer(transfer['id']) - self.user_client.wait_for_transfer_deletion(transfer['id']) - share = self.user_client.get_share(share['id']) - self.assertEqual("available", share['status']) - # finally delete the share - self.user_client.delete_share(share['id']) - self.user_client.wait_for_share_deletion(share['id']) - - def test_transfer_accept(self): - """Show share transfer accept""" - self.skip_if_microversion_not_supported('2.77') - share = self.create_share( - share_protocol='nfs', - size=1, - name=data_utils.rand_name('autotest_share_name'), - client=self.user_client, - share_type=self.share_type['ID'], - use_wait_option=True) - self.assertEqual("available", share['status']) - # create share transfer - transfer = self.create_share_transfer(share['id'], - name='test_share_transfer') - share = self.user_client.get_share(share['id']) - transfer_id = transfer['id'] - auth_key = transfer['auth_key'] - self.assertEqual("share", transfer['resource_type']) - self.assertEqual('test_share_transfer', transfer['name']) - self.assertEqual("awaiting_transfer", share['status']) - - # accept the share transfer - self.accept_share_transfer(transfer_id, auth_key) - # after accept complete, the transfer will be deleted. - self.user_client.wait_for_transfer_deletion(transfer_id) - share = self.user_client.get_share(share['id']) - # check share status roll back to available - self.assertEqual("available", share['status']) - # finally delete the share - self.user_client.delete_share(share['id']) - self.user_client.wait_for_share_deletion(share['id']) diff --git a/manilaclient/tests/functional/test_share_types.py b/manilaclient/tests/functional/test_share_types.py deleted file mode 100644 index f268aaad..00000000 --- a/manilaclient/tests/functional/test_share_types.py +++ /dev/null @@ -1,514 +0,0 @@ -# Copyright 2015 Mirantis Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import ddt -from tempest.lib.common.utils import data_utils - -from manilaclient import api_versions -from manilaclient.tests.functional import base -from manilaclient.tests.unit.v2 import test_types as unit_test_types - - -@ddt.ddt -class ShareTypesReadOnlyTest(base.BaseTestCase): - - @ddt.data( - ("admin", "1.0"), - ("admin", "2.0"), - ("admin", "2.6"), - ("admin", "2.7"), - ("user", "1.0"), - ("user", "2.0"), - ("user", "2.6"), - ("user", "2.7"), - ) - @ddt.unpack - def test_share_type_list(self, role, microversion): - self.skip_if_microversion_not_supported(microversion) - self.clients[role].manila("type-list", microversion=microversion) - - @ddt.data("1.0", "2.0", "2.6", "2.7") - def test_extra_specs_list(self, microversion): - self.skip_if_microversion_not_supported(microversion) - self.admin_client.manila("extra-specs-list", microversion=microversion) - - -@ddt.ddt -class ShareTypesReadWriteTest(base.BaseTestCase): - - create_keys = ( - 'ID', 'Name', 'Visibility', 'is_default', 'required_extra_specs', - 'optional_extra_specs') - - def _share_type_listed_by(self, share_type_id, by_admin=False, - list_all=False, microversion=None): - client = self.admin_client if by_admin else self.user_client - share_types = client.list_share_types( - list_all=list_all, microversion=microversion) - return any(share_type_id == st['ID'] for st in share_types) - - def _verify_access(self, share_type_id, is_public, microversion=None): - if is_public: - # Verify that it is listed with common 'type-list' operation. - share_types = self.admin_client.list_share_types( - list_all=False, microversion=microversion) - self.assertTrue( - any(share_type_id == st['ID'] for st in share_types)) - else: - # Verify that it is not listed for user - self.assertFalse(self._share_type_listed_by( - share_type_id=share_type_id, by_admin=False, list_all=True, - microversion=microversion)) - - # Verify it is listed for admin - self.assertTrue(self._share_type_listed_by( - share_type_id=share_type_id, by_admin=True, list_all=True, - microversion=microversion)) - - # Verify it is not listed by default - self.assertFalse(self._share_type_listed_by( - share_type_id=share_type_id, by_admin=True, list_all=False, - microversion=microversion)) - - @ddt.data(*unit_test_types.get_valid_type_create_data_2_0()) - @ddt.unpack - def test_create_delete_share_type( - self, is_public, dhss, spec_snapshot_support, extra_specs): - - self.skip_if_microversion_not_supported('2.0') - self._test_create_delete_share_type( - '2.0', is_public, dhss, spec_snapshot_support, - None, None, None, extra_specs) - - @ddt.data(*unit_test_types.get_valid_type_create_data_2_24()) - @ddt.unpack - def test_create_delete_share_type_2_24( - self, is_public, dhss, spec_snapshot_support, - spec_create_share_from_snapshot, extra_specs): - - self.skip_if_microversion_not_supported('2.24') - self._test_create_delete_share_type( - '2.24', is_public, dhss, spec_snapshot_support, - spec_create_share_from_snapshot, None, None, extra_specs) - - @ddt.data(*unit_test_types.get_valid_type_create_data_2_27()) - @ddt.unpack - def test_create_delete_share_type_2_27( - self, is_public, dhss, spec_snapshot_support, - spec_create_share_from_snapshot, spec_revert_to_snapshot_support, - extra_specs): - - self.skip_if_microversion_not_supported('2.27') - self._test_create_delete_share_type( - '2.27', is_public, dhss, spec_snapshot_support, - spec_create_share_from_snapshot, spec_revert_to_snapshot_support, - None, extra_specs) - - def test_create_delete_share_type_with_description(self): - self.skip_if_microversion_not_supported('2.41') - self._test_create_delete_share_type( - '2.41', True, False, None, None, None, None, None, - description=data_utils.rand_name('test_share_type_description')) - - @ddt.data( - ('name_updated_1', 'description_updated', True), - ('name_updated_2', 'description_updated', False), - ('name_updated_3', None, None), - (None, 'description_updated', None), - (None, None, True), - (None, None, False), - ) - @ddt.unpack - def test_create_update_delete_share_type_2_50(self, new_name, - new_description, - new_is_public): - self.skip_if_microversion_not_supported('2.50') - microversion = '2.50' - share_type_name = data_utils.rand_name('share_type_update_test') - - # Create share type - share_type = self.create_share_type( - name=share_type_name, - driver_handles_share_servers=False, - snapshot_support=None, - create_share_from_snapshot=None, - revert_to_snapshot=None, - mount_snapshot=None, - is_public=True, - microversion=microversion, - extra_specs={}, - description="share_type_description") - - st_id = share_type['ID'] - - # Update share type - st_updated = self.update_share_type(st_id, name=new_name, - description=new_description, - is_public=new_is_public, - microversion=microversion) - # Verify type name - if new_name: - self.assertEqual(new_name, st_updated['Name']) - - # Verify type description - if new_description: - self.assertEqual(new_description, st_updated['Description']) - - # Verify public - if new_is_public is not None: - self.assertEqual('public' if new_is_public else 'private', - st_updated['Visibility'].lower()) - - # Delete share type - self.admin_client.delete_share_type(st_id, microversion=microversion) - - # Wait for share type deletion - self.admin_client.wait_for_share_type_deletion( - st_id, microversion=microversion) - - # Verify that it is not listed with common 'type-list' operation. - share_types = self.admin_client.list_share_types( - list_all=False, microversion=microversion) - self.assertFalse(any(st_id == st['ID'] for st in share_types)) - - def test_unset_share_type_description_2_50(self): - self.skip_if_microversion_not_supported('2.50') - microversion = '2.50' - share_type_name = data_utils.rand_name('share_type_update_test') - - # Create share type - share_type = self.create_share_type( - name=share_type_name, - driver_handles_share_servers=False, - snapshot_support=None, - create_share_from_snapshot=None, - revert_to_snapshot=None, - mount_snapshot=None, - is_public=True, - microversion=microversion, - extra_specs={}, - description="share_type_description") - - st_id = share_type['ID'] - - # Update share type - new_description = "" - st_updated = self.update_share_type(st_id, - description=new_description, - microversion=microversion) - - # Verify type description - self.assertEqual('None', st_updated['Description']) - - # Delete share type - self.admin_client.delete_share_type(st_id, microversion=microversion) - - # Wait for share type deletion - self.admin_client.wait_for_share_type_deletion( - st_id, microversion=microversion) - - # Verify that it is not listed with common 'type-list' operation. - share_types = self.admin_client.list_share_types( - list_all=False, microversion=microversion) - self.assertFalse(any(st_id == st['ID'] for st in share_types)) - - def _test_create_delete_share_type(self, microversion, is_public, dhss, - spec_snapshot_support, - spec_create_share_from_snapshot, - spec_revert_to_snapshot_support, - spec_mount_snapshot_support, - extra_specs, - description=None): - - share_type_name = data_utils.rand_name('manilaclient_functional_test') - - if extra_specs is None: - extra_specs = {} - - # Create share type - share_type = self.create_share_type( - name=share_type_name, - driver_handles_share_servers=dhss, - snapshot_support=spec_snapshot_support, - create_share_from_snapshot=spec_create_share_from_snapshot, - revert_to_snapshot=spec_revert_to_snapshot_support, - mount_snapshot=spec_mount_snapshot_support, - is_public=is_public, - microversion=microversion, - extra_specs=extra_specs, - description=description) - - # Verify response body - for key in self.create_keys: - self.assertIn(key, share_type) - - # Verify type name - self.assertEqual(share_type_name, share_type['Name']) - - # Verify type description - if (api_versions.APIVersion(microversion) >= - api_versions.APIVersion('2.41')): - self.assertEqual(description, share_type['Description']) - else: - self.assertNotIn('description', share_type) - - # Verify required DHSS extra spec - dhss_expected = 'driver_handles_share_servers : %s' % dhss - self.assertEqual(dhss_expected, share_type['required_extra_specs']) - - # Determine expected extra specs. Note that prior to 2.24, - # the standard 'snapshot_support' extra spec was required. - expected_extra_specs = [] - for key, val in extra_specs.items(): - expected_extra_specs.append(('{} : {}'.format(key, val)).strip()) - - if (api_versions.APIVersion(microversion) < - api_versions.APIVersion('2.24')): - if 'snapshot_support' not in extra_specs: - if spec_snapshot_support is None: - expected_extra_specs.append( - ('{} : {}'.format('snapshot_support', True)).strip()) - else: - expected_extra_specs.append( - ('{} : {}'.format( - 'snapshot_support', - spec_snapshot_support)).strip()) - else: - if spec_snapshot_support is not None: - expected_extra_specs.append( - ('{} : {}'.format( - 'snapshot_support', - spec_snapshot_support)).strip()) - - if spec_create_share_from_snapshot is not None: - expected_extra_specs.append( - ('{} : {}'.format( - 'create_share_from_snapshot_support', - spec_create_share_from_snapshot)).strip()) - if spec_revert_to_snapshot_support is not None: - expected_extra_specs.append( - ('{} : {}'.format( - 'revert_to_snapshot_support', - spec_revert_to_snapshot_support)).strip()) - if spec_mount_snapshot_support is not None: - expected_extra_specs.append( - ('{} : {}'.format( - 'mount_snapshot_support', - spec_mount_snapshot_support)).strip()) - - # Verify optional extra specs - optional_extra_specs = share_type['optional_extra_specs'] - if optional_extra_specs == '': - optional_extra_specs = [] - elif not isinstance(optional_extra_specs, list): - optional_extra_specs = [optional_extra_specs] - - self.assertEqual(len(expected_extra_specs), len(optional_extra_specs)) - for e in optional_extra_specs: - self.assertIn(e.strip(), expected_extra_specs) - - # Verify public & default attributes - self.assertEqual('public' if is_public else 'private', - share_type['Visibility'].lower()) - self.assertEqual('-', share_type['is_default']) - - # Verify its access - st_id = share_type['ID'] - self._verify_access(share_type_id=st_id, - is_public=is_public, - microversion=microversion) - - # Delete share type - self.admin_client.delete_share_type(st_id, microversion=microversion) - - # Wait for share type deletion - self.admin_client.wait_for_share_type_deletion( - st_id, microversion=microversion) - - # Verify that it is not listed with common 'type-list' operation. - share_types = self.admin_client.list_share_types( - list_all=False, microversion=microversion) - self.assertFalse(any(st_id == st['ID'] for st in share_types)) - - @ddt.data("2.6", "2.7") - def test_add_remove_access_to_private_share_type(self, microversion): - self.skip_if_microversion_not_supported(microversion) - - share_type_name = data_utils.rand_name('manilaclient_functional_test') - is_public = False - - # Create share type - share_type = self.create_share_type( - name=share_type_name, - driver_handles_share_servers='False', - is_public=is_public, - microversion=microversion, - ) - - st_id = share_type['ID'] - user_project_id = self.admin_client.get_project_id( - self.user_client.tenant_name) - - self._verify_access( - share_type_id=st_id, - is_public=is_public, - microversion=microversion, - ) - - # Project ID is in access list - false - st_access_list = self.admin_client.list_share_type_access( - st_id, microversion=microversion) - self.assertNotIn(user_project_id, st_access_list) - - # Add access for project of user - self.admin_client.add_share_type_access( - st_id, user_project_id, microversion=microversion) - - # Verify it is listed for user as well as for admin - self.assertTrue(self._share_type_listed_by( - share_type_id=st_id, by_admin=False, list_all=True)) - self.assertTrue(self._share_type_listed_by( - share_type_id=st_id, by_admin=True, list_all=True)) - - # Project ID is in access list - true - st_access_list = self.admin_client.list_share_type_access( - st_id, microversion=microversion) - self.assertIn(user_project_id, st_access_list) - - # Remove access - self.admin_client.remove_share_type_access( - st_id, user_project_id, microversion=microversion) - - self._verify_access( - share_type_id=st_id, - is_public=is_public, - microversion=microversion, - ) - - # Project ID is in access list - false - st_access_list = self.admin_client.list_share_type_access( - st_id, microversion=microversion) - self.assertNotIn(user_project_id, st_access_list) - - @ddt.data("2.6", "2.7") - def test_list_share_type(self, microversion): - share_type_name = data_utils.rand_name('manilaclient_functional_test') - - # Create share type - self.create_share_type( - name=share_type_name, - driver_handles_share_servers='False') - share_types = self.admin_client.list_share_types( - list_all=True, - microversion=microversion - ) - self.assertTrue(any(s['ID'] is not None for s in share_types)) - self.assertTrue(any(s['Name'] is not None for s in share_types)) - self.assertTrue(any(s['visibility'] is not None for s in share_types)) - - @ddt.data("2.6", "2.7") - def test_list_share_type_select_column(self, microversion): - share_type_name = data_utils.rand_name('manilaclient_functional_test') - - # Create share type - self.create_share_type( - name=share_type_name, - driver_handles_share_servers='False') - share_types = self.admin_client.list_share_types( - list_all=True, - columns="id,name", - microversion=microversion - ) - self.assertTrue(any(s['id'] is not None for s in share_types)) - self.assertTrue(any(s['name'] is not None for s in share_types)) - self.assertTrue(all('visibility' not in s for s in share_types)) - self.assertTrue(all('Visibility' not in s for s in share_types)) - - def test_list_share_type_filter_search(self): - # Fake extra spec and type name - extra_specs = {'aaaa': 'bbbb'} - # Create share type - name1 = data_utils.rand_name('manilaclient_functional_test1') - self.create_share_type( - name=name1, - driver_handles_share_servers='False') - # Create share type - name2 = data_utils.rand_name('manilaclient_functional_test2') - self.create_share_type( - name=name2, - extra_specs=extra_specs, - driver_handles_share_servers='True') - - # List type by extra_specs - list_all = False - search_opts = {'extra_specs': extra_specs} - share_types = self.admin_client.list_share_types( - list_all=list_all, - search_opts=search_opts, - microversion='2.43' - ) - self.assertTrue(share_types is not None) - - expect = 'aaaa : bbbb' - self.assertTrue(len(share_types) == 1) - self.assertTrue(all('optional_extra_specs' in s for s in share_types)) - self.assertTrue(all(s['Name'] == name2 for s in share_types)) - self.assertTrue(all(s['optional_extra_specs'] == - expect for s in share_types)) - - -@ddt.ddt -class ShareTypeExtraSpecsReadWriteTest(base.BaseTestCase): - - @ddt.data( - (True, False), - (True, True), - (False, True), - (False, False), - (False, False, "2.6"), - (False, False, "2.7"), - ) - @ddt.unpack - def test_share_type_extra_specs_life_cycle(self, is_public, dhss, - microversion=None): - if microversion: - self.skip_if_microversion_not_supported(microversion) - - # Create share type - st = self.create_share_type( - driver_handles_share_servers=dhss, is_public=is_public, - microversion=microversion) - - # Add extra specs to share type - st_extra_specs = dict(foo_key='foo_value', bar_key='bar_value') - self.admin_client.set_share_type_extra_specs( - st['ID'], st_extra_specs, microversion=microversion) - - # View list of extra specs - extra_specs = self.admin_client.list_share_type_extra_specs( - st['ID'], microversion=microversion) - for k, v in st_extra_specs.items(): - self.assertIn('%s : %s' % (k, v), extra_specs) - - # Remove one extra spec - self.admin_client.unset_share_type_extra_specs( - st['ID'], ('foo_key', ), microversion=microversion) - - # Verify that removed extra spec is absent - extra_specs = self.admin_client.list_share_type_extra_specs( - st['ID'], microversion=microversion) - self.assertNotIn('foo_key : foo_value', extra_specs) - self.assertIn('bar_key : bar_value', extra_specs) - self.assertIn('driver_handles_share_servers : %s' % dhss, extra_specs) diff --git a/manilaclient/tests/functional/test_shares.py b/manilaclient/tests/functional/test_shares.py deleted file mode 100644 index f0849a8d..00000000 --- a/manilaclient/tests/functional/test_shares.py +++ /dev/null @@ -1,306 +0,0 @@ -# Copyright 2015 Mirantis Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import ddt -import testtools - -from tempest.lib.common.utils import data_utils -from tempest.lib import exceptions - -from manilaclient.common import constants -from manilaclient import config -from manilaclient.tests.functional import base -from manilaclient.tests.functional import utils - -CONF = config.CONF - - -@ddt.ddt -class SharesReadWriteBase(base.BaseTestCase): - protocol = None - - def setUp(self): - super(SharesReadWriteBase, self).setUp() - if self.protocol not in CONF.enable_protocols: - message = "%s tests are disabled" % self.protocol - raise self.skipException(message) - self.name = data_utils.rand_name('autotest_share_name') - self.description = data_utils.rand_name('autotest_share_description') - - # NOTE(vponomaryov): following share is used only in one test - # until tests for snapshots appear. - self.share = self.create_share( - share_protocol=self.protocol, - size=1, - name=self.name, - description=self.description, - client=self.get_user_client()) - - def test_create_delete_share(self): - name = data_utils.rand_name('autotest_share_name') - - create = self.create_share( - self.protocol, name=name, client=self.user_client) - - self.assertEqual("creating", create['status']) - self.assertEqual(name, create['name']) - self.assertEqual('1', create['size']) - self.assertEqual(self.protocol.upper(), create['share_proto']) - - self.user_client.delete_share(create['id']) - - self.user_client.wait_for_share_deletion(create['id']) - - def test_create_update_share(self): - name = data_utils.rand_name('autotest_share_name') - new_name = 'new_' + name - description = data_utils.rand_name('autotest_share_description') - new_description = 'new_' + description - - create = self.create_share( - self.protocol, name=name, description=description, - client=self.user_client) - - self.assertEqual(name, create['name']) - self.assertEqual(description, create['description']) - self.assertEqual('False', create['is_public']) - - self.user_client.update_share( - create['id'], name=new_name, description=new_description) - get = self.user_client.get_share(create['id']) - - self.assertEqual(new_name, get['name']) - self.assertEqual(new_description, get['description']) - self.assertEqual('False', get['is_public']) - - # only admins operating at system scope can set a share to be public - self.admin_client.update_share(create['id'], is_public=True) - get = self.user_client.get_share(create['id']) - - self.assertEqual(new_name, get['name']) - self.assertEqual(new_description, get['description']) - self.assertEqual('True', get['is_public']) - - def test_get_share(self): - get = self.user_client.get_share(self.share['id']) - - self.assertEqual(self.name, get['name']) - self.assertEqual(self.description, get['description']) - self.assertEqual('1', get['size']) - self.assertEqual(self.protocol.upper(), get['share_proto']) - - def test_create_delete_with_wait(self): - name = data_utils.rand_name('share-with-wait-%s') - description = data_utils.rand_name('we-wait-until-share-is-ready') - - share_1, share_2 = ( - self.create_share(self.protocol, name=(name % num), - description=description, - use_wait_option=True, - client=self.user_client) - for num in range(0, 2) - ) - - self.assertEqual("available", share_1['status']) - self.assertEqual("available", share_2['status']) - - self.delete_share([share_1['id'], share_2['id']], - wait=True, - client=self.user_client) - - for share in (share_1, share_2): - self.assertRaises(exceptions.NotFound, - self.user_client.get_share, - share['id']) - - def test_create_soft_delete_and_restore_share(self): - self.skip_if_microversion_not_supported('2.69') - microversion = '2.69' - description = data_utils.rand_name('we-wait-until-share-is-ready') - - share = self.create_share(self.protocol, - name='share_name', - description=description, - use_wait_option=True, - client=self.user_client) - - self.assertEqual("available", share['status']) - - # soft delete the share to recycle bin - self.soft_delete_share([share['id']], client=self.user_client, - microversion=microversion) - self.user_client.wait_for_share_soft_deletion(share['id']) - - # get shares list in recycle bin - result = self.user_client.list_shares(is_soft_deleted=True, - microversion=microversion) - share_ids = [sh['ID'] for sh in result] - # check share is in recycle bin - self.assertIn(share['id'], share_ids) - - # restore the share from recycle bin - self.restore_share([share['id']], client=self.user_client, - microversion=microversion) - self.user_client.wait_for_share_restore(share['id']) - - result1 = self.user_client.list_shares(is_soft_deleted=True, - microversion=microversion) - share_ids1 = [sh['ID'] for sh in result1] - # check share not in recycle bin - self.assertNotIn(share['id'], share_ids1) - - -@ddt.ddt -class SharesTestMigration(base.BaseTestCase): - - def setUp(self): - super(SharesTestMigration, self).setUp() - - self.old_type = self.create_share_type( - data_utils.rand_name('test_share_type'), - driver_handles_share_servers=True) - self.new_type = self.create_share_type( - data_utils.rand_name('test_share_type'), - driver_handles_share_servers=True) - self.error_type = self.create_share_type( - data_utils.rand_name('test_share_type'), - driver_handles_share_servers=True, - extra_specs={'cause_error': 'no_valid_host'}) - - self.old_share_net = self.get_user_client().get_share_network( - self.get_user_client().share_network) - share_net_info = ( - utils.get_default_subnet(self.get_user_client(), - self.old_share_net['id']) - if utils.share_network_subnets_are_supported() - else self.old_share_net) - self.new_share_net = self.create_share_network( - neutron_net_id=share_net_info['neutron_net_id'], - neutron_subnet_id=share_net_info['neutron_subnet_id']) - - @utils.skip_if_microversion_not_supported('2.22') - @ddt.data('migration_error', 'migration_success', 'None') - def test_reset_task_state(self, state): - - share = self.create_share( - share_protocol='nfs', - size=1, - name=data_utils.rand_name('autotest_share_name'), - client=self.get_user_client(), - share_type=self.old_type['ID'], - share_network=self.old_share_net['id'], - wait_for_creation=True) - share = self.user_client.get_share(share['id']) - - self.admin_client.reset_task_state(share['id'], state) - share = self.user_client.get_share(share['id']) - self.assertEqual(state, share['task_state']) - - @utils.skip_if_microversion_not_supported('2.29') - @testtools.skipUnless( - CONF.run_migration_tests, 'Share migration tests are disabled.') - @ddt.data('cancel', 'success', 'error') - def test_full_migration(self, test_type): - # We are testing with DHSS=True only because it allows us to specify - # new_share_network. - - share = self.create_share( - share_protocol='nfs', - size=1, - name=data_utils.rand_name('autotest_share_name'), - client=self.get_user_client(), - share_type=self.old_type['ID'], - share_network=self.old_share_net['id'], - wait_for_creation=True) - share = self.admin_client.get_share(share['id']) - - pools = self.admin_client.pool_list(detail=True) - - dest_pool = utils.choose_matching_backend( - share, pools, self.new_type) - - self.assertIsNotNone(dest_pool) - - source_pool = share['host'] - - new_type = self.new_type - if test_type == 'error': - statuses = constants.TASK_STATE_MIGRATION_ERROR - new_type = self.error_type - else: - statuses = (constants.TASK_STATE_MIGRATION_DRIVER_PHASE1_DONE, - constants.TASK_STATE_DATA_COPYING_COMPLETED) - - self.admin_client.migration_start( - share['id'], dest_pool, writable=True, nondisruptive=False, - preserve_metadata=True, preserve_snapshots=True, - force_host_assisted_migration=False, - new_share_network=self.new_share_net['id'], - new_share_type=new_type['ID']) - - share = self.admin_client.wait_for_migration_task_state( - share['id'], dest_pool, statuses) - - progress = self.admin_client.migration_get_progress(share['id']) - self.assertEqual('100', progress['total_progress']) - - self.assertEqual(source_pool, share['host']) - self.assertEqual(self.old_type['ID'], share['share_type']) - self.assertEqual(self.old_share_net['id'], share['share_network_id']) - - if test_type == 'error': - self.assertEqual(statuses, progress['task_state']) - else: - if test_type == 'success': - self.admin_client.migration_complete(share['id']) - statuses = constants.TASK_STATE_MIGRATION_SUCCESS - elif test_type == 'cancel': - self.admin_client.migration_cancel(share['id']) - statuses = constants.TASK_STATE_MIGRATION_CANCELLED - - share = self.admin_client.wait_for_migration_task_state( - share['id'], dest_pool, statuses) - progress = self.admin_client.migration_get_progress(share['id']) - self.assertEqual(statuses, progress['task_state']) - if test_type == 'success': - self.assertEqual(dest_pool, share['host']) - self.assertEqual(new_type['ID'], share['share_type']) - self.assertEqual(self.new_share_net['id'], - share['share_network_id']) - else: - self.assertEqual(source_pool, share['host']) - self.assertEqual(self.old_type['ID'], share['share_type']) - self.assertEqual(self.old_share_net['id'], - share['share_network_id']) - - -class NFSSharesReadWriteTest(SharesReadWriteBase): - protocol = 'nfs' - - -class CIFSSharesReadWriteTest(SharesReadWriteBase): - protocol = 'cifs' - - -class GlusterFSSharesReadWriteTest(SharesReadWriteBase): - protocol = 'glusterfs' - - -class HDFSSharesReadWriteTest(SharesReadWriteBase): - protocol = 'hdfs' - - -class MAPRFSSharesReadWriteTest(SharesReadWriteBase): - protocol = 'maprfs' diff --git a/manilaclient/tests/functional/test_shares_listing.py b/manilaclient/tests/functional/test_shares_listing.py deleted file mode 100644 index 83cdf228..00000000 --- a/manilaclient/tests/functional/test_shares_listing.py +++ /dev/null @@ -1,370 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2015 Mirantis Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import ddt -from tempest.lib.common.utils import data_utils -from tempest.lib import exceptions -import testtools - -from manilaclient.common import constants -from manilaclient import config -from manilaclient.tests.functional import base - -CONF = config.CONF - - -@ddt.ddt -class SharesListReadOnlyTest(base.BaseTestCase): - - @ddt.data('admin', 'user') - def test_shares_list(self, role): - self.clients[role].manila('list') - - @ddt.data('admin', 'user') - def test_list_with_debug_flag(self, role): - self.clients[role].manila('list', flags='--debug') - - @ddt.data('admin', 'user') - def test_shares_list_all_tenants(self, role): - self.clients[role].manila('list', params='--all-tenants') - - @ddt.data('admin', 'user') - def test_shares_list_filter_by_name(self, role): - self.clients[role].manila('list', params='--name name') - - @ddt.data('admin', 'user') - def test_shares_list_filter_by_export_location(self, role): - self.clients[role].manila('list', params='--export_location fake') - - @ddt.data('admin', 'user') - def test_shares_list_filter_by_inexact_name(self, role): - self.clients[role].manila('list', params='--name~ na') - - @ddt.data('admin', 'user') - def test_shares_list_filter_by_inexact_description(self, role): - self.clients[role].manila('list', params='--description~ des') - - @ddt.data('admin', 'user') - def test_shares_list_filter_by_status(self, role): - self.clients[role].manila('list', params='--status status') - - def test_shares_list_filter_by_share_server_as_admin(self): - self.clients['admin'].manila('list', params='--share-server fake') - - def test_shares_list_filter_by_share_server_as_user(self): - self.assertRaises( - exceptions.CommandFailed, - self.clients['user'].manila, - 'list', - params='--share-server fake') - - @ddt.data('admin', 'user') - def test_shares_list_filter_by_project_id(self, role): - self.clients[role].manila('list', params='--project-id fake') - - def test_shares_list_filter_by_host(self): - self.clients['admin'].manila('list', params='--host fake') - - @ddt.data('admin', 'user') - def test_shares_list_with_limit_and_offset(self, role): - self.clients[role].manila('list', params='--limit 1 --offset 1') - - @ddt.data( - {'role': 'admin', 'direction': 'asc'}, - {'role': 'admin', 'direction': 'desc'}, - {'role': 'user', 'direction': 'asc'}, - {'role': 'user', 'direction': 'desc'}) - @ddt.unpack - def test_shares_list_with_sorting(self, role, direction): - self.clients[role].manila( - 'list', params='--sort-key host --sort-dir ' + direction) - - @ddt.data('admin', 'user') - def test_snapshot_list(self, role): - self.clients[role].manila('snapshot-list') - - @ddt.data('admin', 'user') - def test_snapshot_list_all_tenants(self, role): - self.clients[role].manila('snapshot-list', params='--all-tenants') - - @ddt.data('admin', 'user') - def test_snapshot_list_filter_by_name(self, role): - self.clients[role].manila('snapshot-list', params='--name name') - - @ddt.data('admin', 'user') - def test_snapshot_list_filter_by_status(self, role): - self.clients[role].manila('snapshot-list', params='--status status') - - -@ddt.ddt -class SharesListReadWriteTest(base.BaseTestCase): - - def setUp(self): - super(SharesListReadWriteTest, self).setUp() - self.private_name = data_utils.rand_name('autotest_share_name') - self.private_description = data_utils.rand_name( - 'autotest_share_description') - self.public_name = data_utils.rand_name('autotest_public_share_name') - self.public_description = data_utils.rand_name( - 'autotest_public_share_description') - - self.admin_private_name = data_utils.rand_name( - 'autotest_admin_private_share_name') - self.admin_private_description = data_utils.rand_name( - 'autotest_admin_private_share_description') - - self.soft_name = data_utils.rand_name('soft_delete_share_name') - - self.admin_private_share = self.create_share( - name=self.admin_private_name, - description=self.admin_private_description, - public=False, - client=None, - wait_for_creation=False) - - self.private_share = self.create_share( - name=self.private_name, - description=self.private_description, - public=False, - client=self.get_user_client(), - wait_for_creation=False) - - self.public_share = self.create_share( - name=self.public_name, - description=self.public_description, - public=True, - client=self.admin_client) - - self.wait_soft_delete_share = self.create_share( - name=self.soft_name, - public=False, - client=self.get_user_client(), - wait_for_creation=False) - - self.shares_created = (self.private_share['id'], - self.public_share['id'], - self.admin_private_share['id'], - self.wait_soft_delete_share['id']) - - for share_id in self.shares_created: - self.admin_client.wait_for_resource_status( - share_id, constants.STATUS_AVAILABLE) - - self.soft_delete_share([self.wait_soft_delete_share['id']], - client=self.get_user_client(), - microversion='2.69') - - def _list_shares(self, filters=None): - filters = filters or dict() - shares = self.user_client.list_shares(filters=filters) - - self.assertGreater(len(shares), 0) - if filters: - for share in shares: - try: - share_get = self.user_client.get_share(share['ID']) - except exceptions.NotFound: - # NOTE(vponomaryov): Case when some share was deleted - # between our 'list' and 'get' requests. Skip such case. - # It occurs with concurrently running tests. - continue - if 'migrating' in share_get['status']: - # all bets are off, a fair chance share migration - # started between the 'list' and 'get' requests. No need - # to verify these shares. - continue - for filter_key, expected_value in filters.items(): - if filter_key in ('share_network', 'share-network'): - filter_key = 'share_network_id' - if share_get[filter_key] != expected_value: - # Possibly a mismatch because the share was - # migrated to a new network in the time that - # elapsed between the 'list' and 'get' requests. - # If this isn't one of the shares created in - # this class, don't worry about such mismatches - self.assertNotIn(share_get['id'], - self.shares_created) - continue - - if (expected_value != 'deleting' and - share_get[filter_key] == 'deleting'): - continue - self.assertEqual(expected_value, share_get[filter_key]) - - def test_list_shares(self): - self._list_shares() - - @ddt.data(1, 0) - def test_list_shares_for_all_tenants(self, all_tenants): - shares = self.admin_client.list_shares(all_tenants=all_tenants) - self.assertLessEqual(1, len(shares)) - - if all_tenants: - self.assertTrue(all('Project ID' in s for s in shares)) - for s_id in (self.private_share['id'], self.public_share['id'], - self.admin_private_share['id']): - self.assertTrue(any(s_id == s['ID'] for s in shares)) - else: - self.assertTrue(all('Project ID' not in s for s in shares)) - self.assertTrue(any(self.admin_private_share['id'] == s['ID'] - for s in shares)) - if self.private_share['project_id'] != ( - self.admin_private_share['project_id']): - for s_id in ( - self.private_share['id'], self.public_share['id']): - self.assertFalse(any(s_id == s['ID'] for s in shares)) - - @ddt.data(True, False) - def test_list_shares_with_public(self, public): - shares = self.user_client.list_shares(is_public=public) - self.assertGreater(len(shares), 1) - if public: - self.assertTrue(all('Project ID' in s for s in shares)) - else: - self.assertTrue(all('Project ID' not in s for s in shares)) - - def test_list_shares_by_name(self): - shares = self.user_client.list_shares( - filters={'name': self.private_name}) - - self.assertEqual(1, len(shares)) - self.assertTrue( - any(self.private_share['id'] == s['ID'] for s in shares)) - for share in shares: - get = self.user_client.get_share(share['ID']) - self.assertEqual(self.private_name, get['name']) - - def test_list_shares_by_share_type(self): - share_type_id = self.user_client.get_share_type( - self.private_share['share_type'])['ID'] - # NOTE(vponomaryov): this is API 2.6+ specific - self._list_shares({'share_type': share_type_id}) - - def test_list_shares_by_status(self): - self._list_shares({'status': 'available'}) - - def test_list_shares_by_project_id(self): - project_id = self.user_client.get_project_id( - self.user_client.tenant_name) - self._list_shares({'project_id': project_id}) - - @testtools.skipUnless( - CONF.share_network, "Usage of Share networks is disabled") - def test_list_shares_by_share_network(self): - share_network_id = self.user_client.get_share_network( - CONF.share_network)['id'] - self._list_shares({'share_network': share_network_id}) - - @ddt.data( - {'limit': 1}, - {'limit': 2}, - {'limit': 1, 'offset': 1}, - {'limit': 2, 'offset': 0}, - ) - def test_list_shares_with_limit(self, filters): - shares = self.user_client.list_shares(filters=filters) - self.assertEqual(filters['limit'], len(shares)) - - def test_list_share_select_column(self): - shares = self.user_client.list_shares(columns="Name,Size") - self.assertTrue(any(s['Name'] is not None for s in shares)) - self.assertTrue(any(s['Size'] is not None for s in shares)) - self.assertTrue(all('Description' not in s for s in shares)) - - @ddt.data('ID', 'Path') - def test_list_shares_by_export_location(self, option): - export_locations = self.admin_client.list_share_export_locations( - self.public_share['id']) - shares = self.admin_client.list_shares( - filters={'export_location': export_locations[0][option]}) - - self.assertEqual(1, len(shares)) - self.assertTrue( - any(self.public_share['id'] == s['ID'] for s in shares)) - for share in shares: - get = self.admin_client.get_share(share['ID']) - self.assertEqual(self.public_name, get['name']) - - @ddt.data('ID', 'Path') - def test_list_share_instances_by_export_location(self, option): - export_locations = self.admin_client.list_share_export_locations( - self.public_share['id']) - share_instances = self.admin_client.list_share_instances( - filters={'export_location': export_locations[0][option]}) - - self.assertEqual(1, len(share_instances)) - - share_instance_id = share_instances[0]['ID'] - except_export_locations = ( - self.admin_client.list_share_instance_export_locations( - share_instance_id)) - self.assertGreater(len(except_export_locations), 0) - self.assertTrue( - any(export_locations[0][option] == e[option] for e in - except_export_locations)) - - def test_list_share_by_export_location_with_invalid_version(self): - self.assertRaises( - exceptions.CommandFailed, - self.admin_client.list_shares, - filters={'export_location': 'fake'}, - microversion='2.34') - - def test_list_share_instance_by_export_location_invalid_version(self): - self.assertRaises( - exceptions.CommandFailed, - self.admin_client.list_share_instances, - filters={'export_location': 'fake'}, - microversion='2.34') - - @ddt.data('name', 'description') - def test_list_shares_by_inexact_option(self, option): - shares = self.user_client.list_shares( - filters={option + '~': option}) - - # We know we have to have atleast three shares. - # Due to test concurrency, there can be - # more than three shares (some created by other tests). - self.assertGreaterEqual(len(shares), 3) - self.assertTrue( - any(self.private_share['id'] == s['ID'] for s in shares)) - - def test_list_shares_by_inexact_unicode_option(self): - self.create_share( - name=u'共享名称', - description=u'共享描述', - client=self.user_client) - filters = {'name~': u'名称'} - shares = self.user_client.list_shares(filters=filters) - self.assertGreater(len(shares), 0) - - filters = {'description~': u'描述'} - shares = self.user_client.list_shares(filters=filters) - self.assertGreater(len(shares), 0) - - def test_list_shares_by_description(self): - shares = self.user_client.list_shares( - filters={'description': self.private_description}) - - self.assertEqual(1, len(shares)) - self.assertTrue( - any(self.private_share['id'] == s['ID'] for s in shares)) - - def test_list_shares_in_recycle_bin(self): - shares = self.user_client.list_shares(is_soft_deleted=True) - - self.assertTrue( - any(self.wait_soft_delete_share['id'] == s['ID'] for s in shares)) diff --git a/manilaclient/tests/functional/test_shares_metadata.py b/manilaclient/tests/functional/test_shares_metadata.py deleted file mode 100644 index e9cf356a..00000000 --- a/manilaclient/tests/functional/test_shares_metadata.py +++ /dev/null @@ -1,155 +0,0 @@ -# Copyright 2015 Mirantis Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import ddt - -from manilaclient.tests.functional import base - - -@ddt.ddt -class SharesMetadataReadWriteTest(base.BaseTestCase): - - def setUp(self): - super(SharesMetadataReadWriteTest, self).setUp() - self.share = self.create_share(client=self.get_user_client()) - - def test_set_metadata_in_share_creation(self): - md = {"key1": "value1", "key2": "value2"} - - # Create share with metadata - share = self.create_share(metadata=md, client=self.get_user_client()) - - # Read share metadata - metadata = self.user_client.get_share_metadata(share["id"]) - - # Verify share metadata - self.assertEqual(2, len(metadata)) - self.assertIn('key1', metadata) - self.assertIn('key2', metadata) - self.assertEqual(md['key1'], metadata['key1']) - self.assertEqual(md['key2'], metadata['key2']) - - def test_set_and_get_metadata(self): - # Create share - share = self.create_share( - cleanup_in_class=False, client=self.get_user_client()) - - # Set share metadata - md = {"key3": "value3", "key4": "value4"} - self.user_client.set_share_metadata(share["id"], md) - - # Read share metadata - metadata = self.user_client.get_share_metadata(share["id"]) - - # Verify share metadata - self.assertEqual(2, len(metadata)) - self.assertIn('key3', metadata) - self.assertIn('key4', metadata) - self.assertEqual(md['key3'], metadata['key3']) - self.assertEqual(md['key4'], metadata['key4']) - - def test_set_and_delete_metadata(self): - # Create share - share = self.create_share( - cleanup_in_class=False, client=self.get_user_client()) - - # Set share metadata - md = {"key3": "value3", "key4": "value4"} - self.user_client.set_share_metadata(share["id"], md) - - # Unset share metadata - self.user_client.unset_share_metadata(share["id"], list(md.keys())) - - # Verify deletion of share metadata - metadata = self.user_client.get_share_metadata(share["id"]) - self.assertEqual({}, metadata) - - def test_set_and_add_metadata(self): - md = {'key5': 'value5'} - - # Create share with metadata - share = self.create_share( - metadata=md, cleanup_in_class=False, client=self.get_user_client()) - - # Set share metadata - self.user_client.set_share_metadata(share["id"], {'key6': 'value6'}) - self.user_client.set_share_metadata(share["id"], {'key7': 'value7'}) - - # Read share metadata - metadata = self.user_client.get_share_metadata(share["id"]) - - # Verify share metadata - self.assertEqual(3, len(metadata)) - for i in (5, 6, 7): - key = 'key%s' % i - self.assertIn(key, metadata) - self.assertEqual('value%s' % i, metadata[key]) - - def test_set_and_replace_metadata(self): - md = {'key8': 'value8'} - - # Create share with metadata - share = self.create_share( - metadata=md, cleanup_in_class=False, client=self.get_user_client()) - - # Set share metadata - self.user_client.set_share_metadata(share["id"], {'key9': 'value9'}) - - # Replace all existing share metadata - self.user_client.update_all_share_metadata( - share["id"], {'key10': 'value10'}) - - # Read share metadata - metadata = self.user_client.get_share_metadata(share["id"]) - - # Verify share metadata - self.assertEqual(1, len(metadata)) - self.assertIn('key10', metadata) - self.assertEqual('value10', metadata['key10']) - - @ddt.data( - {"k": "value"}, - {"k" * 255: "value"}, - {"key": "v"}, - {"key": "v" * 1023}) - def test_set_metadata_min_max_sizes_of_keys_and_values(self, metadata): - # Set share metadata - self.user_client.set_share_metadata(self.share["id"], metadata) - - # Read share metadata - get = self.user_client.get_share_metadata(self.share["id"]) - - # Verify share metadata - key = list(metadata.keys())[0] - self.assertIn(key, get) - self.assertEqual(metadata[key], get[key]) - - @ddt.data( - {"k": "value"}, - {"k" * 255: "value"}, - {"key": "v"}, - {"key": "v" * 1023}) - def test_update_metadata_min_max_sizes_of_keys_and_values(self, metadata): - # Update share metadata - self.user_client.update_all_share_metadata(self.share["id"], metadata) - - # Read share metadata - get = self.user_client.get_share_metadata(self.share["id"]) - - # Verify share metadata - self.assertEqual(len(metadata), len(get)) - for key in metadata: - self.assertIn(key, get) - self.assertEqual(metadata[key], get[key]) diff --git a/manilaclient/tests/functional/test_snapshot_access.py b/manilaclient/tests/functional/test_snapshot_access.py deleted file mode 100644 index ec297dee..00000000 --- a/manilaclient/tests/functional/test_snapshot_access.py +++ /dev/null @@ -1,184 +0,0 @@ -# Copyright (c) 2017 Hitachi Data Systems -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -from tempest.lib import exceptions as tempest_lib_exc -import testtools - -from manilaclient import config -from manilaclient.tests.functional import base -from manilaclient.tests.functional import utils - -CONF = config.CONF - - -@utils.skip_if_microversion_not_supported('2.32') -class SnapshotAccessReadBase(base.BaseTestCase): - protocol = None - - def setUp(self): - super(SnapshotAccessReadBase, self).setUp() - if self.protocol not in CONF.enable_protocols: - message = "%s tests are disabled." % self.protocol - raise self.skipException(message) - self.access_types = CONF.access_types_mapping.get( - self.protocol, '').split(' ') - if not self.access_types: - raise self.skipException("No access types were provided for %s " - "snapshot access tests." % self.protocol) - - self.share = self.create_share(share_protocol=self.protocol, - client=self.get_user_client()) - int_range = range(0, 10) - - self.access_to = { - 'ip': ['99.88.77.%d' % i for i in int_range], - 'user': ['foo_user_%d' % i for i in int_range], - 'cert': ['tenant_%d.example.com' % i for i in int_range], - } - - def _test_create_list_access_rule_for_snapshot(self, snapshot_id): - access = [] - access_type = self.access_types[0] - - for i in range(5): - access_ = self.user_client.snapshot_access_allow( - snapshot_id, access_type, - self.access_to[access_type][i]) - access.append(access_) - - return access - - def test_create_list_access_rule_for_snapshot(self): - snapshot = self.create_snapshot(share=self.share['id'], - client=self.get_user_client(), - cleanup_in_class=False) - - access = self._test_create_list_access_rule_for_snapshot( - snapshot['id']) - - access_list = self.user_client.list_access( - snapshot['id'], is_snapshot=True) - - for i in range(5): - self.assertIn(access[i]['id'], - [access_list[j]['id'] for j in range(5)]) - self.assertIn(access[i]['access_type'], - [access_list[j]['access_type'] for j in range(5)]) - self.assertIn(access[i]['access_to'], - [access_list[j]['access_to'] for j in range(5)]) - self.assertIsNotNone(access_list[i]['access_type']) - self.assertIsNotNone(access_list[i]['access_to']) - - def test_create_list_access_rule_for_snapshot_select_column(self): - snapshot = self.create_snapshot(share=self.share['id'], - client=self.get_user_client(), - cleanup_in_class=False) - - self._test_create_list_access_rule_for_snapshot(snapshot['id']) - - access_list = self.user_client.list_access( - snapshot['id'], columns="access_type,access_to", is_snapshot=True) - - self.assertTrue(any(x['Access_Type'] is not None for x in access_list)) - self.assertTrue(any(x['Access_To'] is not None for x in access_list)) - - def _create_delete_access_rule(self, snapshot_id, access_type, access_to): - - if access_type not in self.access_types: - raise self.skipException( - "'%(access_type)s' access rules is disabled for protocol " - "'%(protocol)s'." % {"access_type": access_type, - "protocol": self.protocol}) - - access = self.user_client.snapshot_access_allow( - snapshot_id, access_type, access_to) - - self.assertEqual(access_type, access.get('access_type')) - self.assertEqual(access_to.replace('\\\\', '\\'), - access.get('access_to')) - - self.user_client.wait_for_access_rule_status( - snapshot_id, access['id'], is_snapshot=True) - self.user_client.snapshot_access_deny(snapshot_id, access['id']) - self.user_client.wait_for_access_rule_deletion( - snapshot_id, access['id'], is_snapshot=True) - - self.assertRaises(tempest_lib_exc.NotFound, - self.user_client.get_access, snapshot_id, - access['id'], is_snapshot=True) - - def test_create_delete_snapshot_ip_access_rule(self): - snapshot = self.create_snapshot(share=self.share['id'], - client=self.get_user_client(), - cleanup_in_class=False) - self._create_delete_access_rule( - snapshot['id'], 'ip', self.access_to['ip'][0]) - - def test_create_delete_snapshot_user_access_rule(self): - snapshot = self.create_snapshot(share=self.share['id'], - client=self.get_user_client(), - cleanup_in_class=False) - self._create_delete_access_rule( - snapshot['id'], 'user', CONF.username_for_user_rules) - - def test_create_delete_snapshot_cert_access_rule(self): - snapshot = self.create_snapshot(share=self.share['id'], - client=self.get_user_client(), - cleanup_in_class=False) - self._create_delete_access_rule( - snapshot['id'], 'cert', self.access_to['cert'][0]) - - -@testtools.skipUnless(CONF.run_snapshot_tests and - CONF.run_mount_snapshot_tests, - "Snapshots or mountable snapshots tests are disabled.") -class NFSSnapshotAccessTest(SnapshotAccessReadBase): - protocol = 'nfs' - - -@testtools.skipUnless(CONF.run_snapshot_tests and - CONF.run_mount_snapshot_tests, - "Snapshots or mountable snapshots tests are disabled.") -class CIFSSnapshotAccessTest(SnapshotAccessReadBase): - protocol = 'cifs' - - -@testtools.skipUnless(CONF.run_snapshot_tests and - CONF.run_mount_snapshot_tests, - "Snapshots or mountable snapshots tests are disabled.") -class GlusterFSSnapshotAccessTest(SnapshotAccessReadBase): - protocol = 'glusterfs' - - -@testtools.skipUnless(CONF.run_snapshot_tests and - CONF.run_mount_snapshot_tests, - "Snapshots or mountable snapshots tests are disabled.") -class HDFSSnapshotAccessTest(SnapshotAccessReadBase): - protocol = 'hdfs' - - -@testtools.skipUnless(CONF.run_snapshot_tests and - CONF.run_mount_snapshot_tests, - "Snapshots or mountable snapshots tests are disabled.") -class MAPRFSSnapshotAccessTest(SnapshotAccessReadBase): - protocol = 'maprfs' - - -def load_tests(loader, tests, _): - result = [] - for test_case in tests: - if type(test_case._tests[0]) is SnapshotAccessReadBase: - continue - result.append(test_case) - return loader.suiteClass(result) diff --git a/manilaclient/tests/functional/test_snapshot_instances.py b/manilaclient/tests/functional/test_snapshot_instances.py deleted file mode 100644 index d5c9c14b..00000000 --- a/manilaclient/tests/functional/test_snapshot_instances.py +++ /dev/null @@ -1,119 +0,0 @@ -# Copyright 2016 Huawei inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import ddt -from oslo_utils import uuidutils -import testtools - -from manilaclient import config -from manilaclient.tests.functional import base -from manilaclient.tests.functional import utils - -CONF = config.CONF - - -@ddt.ddt -@testtools.skipUnless(CONF.run_snapshot_tests, - 'Snapshot tests disabled.') -@utils.skip_if_microversion_not_supported('2.19') -class SnapshotInstancesTest(base.BaseTestCase): - - def setUp(self): - super(SnapshotInstancesTest, self).setUp() - self.share = self.create_share( - client=self.get_user_client()) - self.snapshot = self.create_snapshot(share=self.share['id'], - client=self.get_user_client()) - - def test_list_all_snapshot_instances(self): - snapshot_instances = self.admin_client.list_snapshot_instances() - - self.assertGreater(len(snapshot_instances), 0) - expected_keys = ('ID', 'Snapshot ID', 'Status') - for si in snapshot_instances: - for key in expected_keys: - self.assertIn(key, si) - self.assertTrue(uuidutils.is_uuid_like(si['ID'])) - self.assertTrue(uuidutils.is_uuid_like(si['Snapshot ID'])) - - def test_list_all_snapshot_instances_details(self): - snapshot_instances = self.admin_client.list_snapshot_instances( - detailed=True) - - self.assertGreater(len(snapshot_instances), 0) - expected_keys = ('ID', 'Snapshot ID', 'Status', 'Created_at', - 'Updated_at', 'Share_id', 'Share_instance_id', - 'Progress', 'Provider_location') - for si in snapshot_instances: - for key in expected_keys: - self.assertIn(key, si) - for key in ('ID', 'Snapshot ID', 'Share_id', 'Share_instance_id'): - self.assertTrue( - uuidutils.is_uuid_like(si[key])) - - def test_list_snapshot_instance_with_snapshot(self): - snapshot_instances = self.admin_client.list_snapshot_instances( - snapshot_id=self.snapshot['id']) - - self.assertEqual(1, len(snapshot_instances)) - expected_keys = ('ID', 'Snapshot ID', 'Status') - for si in snapshot_instances: - for key in expected_keys: - self.assertIn(key, si) - self.assertTrue(uuidutils.is_uuid_like(si['ID'])) - self.assertTrue(uuidutils.is_uuid_like(si['Snapshot ID'])) - - def test_list_snapshot_instance_with_columns(self): - snapshot_instances = self.admin_client.list_snapshot_instances( - self.snapshot['id'], columns='id,status') - - self.assertGreater(len(snapshot_instances), 0) - expected_keys = ('Id', 'Status') - unexpected_keys = ('Snapshot ID', ) - for si in snapshot_instances: - for key in expected_keys: - self.assertIn(key, si) - for key in unexpected_keys: - self.assertNotIn(key, si) - self.assertTrue(uuidutils.is_uuid_like(si['Id'])) - - def test_get_snapshot_instance(self): - snapshot_instances = self.admin_client.list_snapshot_instances( - self.snapshot['id']) - - snapshot_instance = self.admin_client.get_snapshot_instance( - snapshot_instances[0]['ID']) - self.assertGreater(len(snapshot_instance), 0) - expected_keys = ('id', 'snapshot_id', 'status', 'created_at', - 'updated_at', 'share_id', 'share_instance_id', - 'progress', 'provider_location') - - for key in expected_keys: - self.assertIn(key, snapshot_instance) - for key in ('id', 'snapshot_id', 'share_id', 'share_instance_id'): - self.assertTrue( - uuidutils.is_uuid_like(snapshot_instance[key])) - - def test_snapshot_instance_reset_state(self): - snapshot_instances = self.admin_client.list_snapshot_instances( - self.snapshot['id']) - self.admin_client.reset_snapshot_instance( - snapshot_instances[0]['ID'], 'error') - snapshot_instance = self.admin_client.get_snapshot_instance( - snapshot_instances[0]['ID']) - - self.assertEqual('error', snapshot_instance['status']) - self.admin_client.reset_snapshot_instance(snapshot_instance['id'], - 'available') diff --git a/manilaclient/tests/functional/test_snapshot_instances_export_locations.py b/manilaclient/tests/functional/test_snapshot_instances_export_locations.py deleted file mode 100644 index 704cd9ee..00000000 --- a/manilaclient/tests/functional/test_snapshot_instances_export_locations.py +++ /dev/null @@ -1,117 +0,0 @@ -# Copyright (c) 2017 Hitachi Data Systems -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import ddt -from oslo_utils import uuidutils -import testtools - -from manilaclient import config -from manilaclient.tests.functional import base -from manilaclient.tests.functional import utils - -CONF = config.CONF - - -@ddt.ddt -@testtools.skipUnless(CONF.run_snapshot_tests and - CONF.run_mount_snapshot_tests, - "Snapshots or mountable snapshots tests are disabled.") -@utils.skip_if_microversion_not_supported('2.32') -class SnapshotInstanceExportLocationReadWriteTest(base.BaseTestCase): - - def setUp(self): - super(SnapshotInstanceExportLocationReadWriteTest, self).setUp() - self.share = self.create_share( - client=self.get_user_client()) - self.snapshot = self.create_snapshot(share=self.share['id'], - client=self.get_user_client()) - - def test_get_snapshot_instance_export_location(self): - client = self.admin_client - snapshot_instances = client.list_snapshot_instances( - self.snapshot['id']) - - self.assertGreater(len(snapshot_instances), 0) - self.assertIn('ID', snapshot_instances[0]) - self.assertTrue(uuidutils.is_uuid_like( - snapshot_instances[0]['ID'])) - - snapshot_instance_id = snapshot_instances[0]['ID'] - - export_locations = client.list_snapshot_instance_export_locations( - snapshot_instance_id) - - el = client.get_snapshot_instance_export_location( - snapshot_instance_id, export_locations[0]['ID']) - expected_keys = ['path', 'id', 'is_admin_only', - 'share_snapshot_instance_id', 'updated_at', - 'created_at'] - - for key in expected_keys: - self.assertIn(key, el) - for key, key_el in ( - ('ID', 'id'), ('Path', 'path'), - ('Is Admin only', 'is_admin_only')): - self.assertEqual(export_locations[0][key], el[key_el]) - self.assertTrue(uuidutils.is_uuid_like( - el['share_snapshot_instance_id'])) - self.assertTrue(uuidutils.is_uuid_like(el['id'])) - self.assertIn(el['is_admin_only'], ('True', 'False')) - - def test_list_snapshot_instance_export_locations(self): - client = self.admin_client - snapshot_instances = client.list_snapshot_instances( - self.snapshot['id']) - - self.assertGreater(len(snapshot_instances), 0) - self.assertIn('ID', snapshot_instances[0]) - self.assertTrue(uuidutils.is_uuid_like(snapshot_instances[0]['ID'])) - - snapshot_instance_id = snapshot_instances[0]['ID'] - - export_locations = client.list_snapshot_instance_export_locations( - snapshot_instance_id) - - self.assertGreater(len(export_locations), 0) - - expected_keys = ('ID', 'Path', 'Is Admin only') - for el in export_locations: - for key in expected_keys: - self.assertIn(key, el) - self.assertTrue(uuidutils.is_uuid_like(el['ID'])) - - def test_list_snapshot_instance_export_locations_with_columns(self): - client = self.admin_client - snapshot_instances = client.list_snapshot_instances( - self.snapshot['id']) - - self.assertGreater(len(snapshot_instances), 0) - self.assertIn('ID', snapshot_instances[0]) - self.assertTrue(uuidutils.is_uuid_like(snapshot_instances[0]['ID'])) - snapshot_instance_id = snapshot_instances[0]['ID'] - - export_locations = client.list_snapshot_instance_export_locations( - snapshot_instance_id, columns='id,path') - - self.assertGreater(len(export_locations), 0) - expected_keys = ('Id', 'Path') - unexpected_keys = ('Updated At', 'Created At', 'Is Admin only') - - for el in export_locations: - for key in expected_keys: - self.assertIn(key, el) - for key in unexpected_keys: - self.assertNotIn(key, el) - self.assertTrue(uuidutils.is_uuid_like(el['Id'])) diff --git a/manilaclient/tests/functional/test_snapshots_export_locations.py b/manilaclient/tests/functional/test_snapshots_export_locations.py deleted file mode 100644 index 547ad241..00000000 --- a/manilaclient/tests/functional/test_snapshots_export_locations.py +++ /dev/null @@ -1,90 +0,0 @@ -# Copyright (c) 2017 Hitachi Data Systems -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import ddt -from oslo_utils import uuidutils -import testtools - -from manilaclient import config -from manilaclient.tests.functional import base -from manilaclient.tests.functional import utils - -CONF = config.CONF - - -@ddt.ddt -@testtools.skipUnless(CONF.run_snapshot_tests and - CONF.run_mount_snapshot_tests, - "Snapshots or mountable snapshots tests are disabled.") -@utils.skip_if_microversion_not_supported('2.32') -class SnapshotExportLocationReadWriteTest(base.BaseTestCase): - - def setUp(self): - super(SnapshotExportLocationReadWriteTest, self).setUp() - self.share = self.create_share( - client=self.get_user_client()) - self.snapshot = self.create_snapshot(share=self.share['id'], - client=self.get_user_client()) - - @ddt.data('admin', 'user') - def test_get_snapshot_export_location(self, role): - client = self.admin_client if role == 'admin' else self.user_client - - export_locations = client.list_snapshot_export_locations( - self.snapshot['id']) - - el = client.get_snapshot_export_location( - self.snapshot['id'], export_locations[0]['ID']) - - expected_keys = ['path', 'id', 'updated_at', 'created_at'] - if role == 'admin': - expected_keys.extend(['is_admin_only', - 'share_snapshot_instance_id']) - self.assertTrue(uuidutils.is_uuid_like( - el['share_snapshot_instance_id'])) - self.assertIn(el['is_admin_only'], ('True', 'False')) - self.assertTrue(uuidutils.is_uuid_like(el['id'])) - for key in expected_keys: - self.assertIn(key, el) - - @ddt.data('admin', 'user') - def test_list_snapshot_export_locations(self, role): - client = self.admin_client if role == 'admin' else self.user_client - export_locations = client.list_snapshot_export_locations( - self.snapshot['id']) - - self.assertGreater(len(export_locations), 0) - expected_keys = ('ID', 'Path') - - for el in export_locations: - for key in expected_keys: - self.assertIn(key, el) - self.assertTrue(uuidutils.is_uuid_like(el['ID'])) - - @ddt.data('admin', 'user') - def test_list_snapshot_export_locations_with_columns(self, role): - client = self.admin_client if role == 'admin' else self.user_client - export_locations = client.list_snapshot_export_locations( - self.snapshot['id'], columns='id,path') - - self.assertGreater(len(export_locations), 0) - expected_keys = ('Id', 'Path') - unexpected_keys = ('Updated At', 'Created At') - for el in export_locations: - for key in expected_keys: - self.assertIn(key, el) - for key in unexpected_keys: - self.assertNotIn(key, el) - self.assertTrue(uuidutils.is_uuid_like(el['Id'])) diff --git a/manilaclient/tests/functional/utils.py b/manilaclient/tests/functional/utils.py index 4c37c5d0..9ebea8ce 100644 --- a/manilaclient/tests/functional/utils.py +++ b/manilaclient/tests/functional/utils.py @@ -32,21 +32,24 @@ def multi_line_row_table(output_lines, group_by_column_index=0): def get_column_index(column_name, headers, default): return next( (i for i, h in enumerate(headers) if h.lower() == column_name), - default + default, ) if group_by_column_index is None: group_by_column_index = get_column_index( - 'id', parsed_table['headers'], 0) + 'id', parsed_table['headers'], 0 + ) def is_embedded_table(parsed_rows): def is_table_border(t): return str(t).startswith('+') - return (isinstance(parsed_rows, list) - and len(parsed_rows) > 3 - and is_table_border(parsed_rows[0]) - and is_table_border(parsed_rows[-1])) + return ( + isinstance(parsed_rows, list) + and len(parsed_rows) > 3 + and is_table_border(parsed_rows[0]) + and is_table_border(parsed_rows[-1]) + ) def merge_cells(master_cell, value_cell): if value_cell: @@ -71,9 +74,9 @@ def is_empty_row(row): line_with_value = row_index > 0 and row[group_by_column_index] == '' if line_with_value and not is_empty_row(row): - rows[row_index - 1] = list(map(merge_cells, - rows[row_index - 1], - rows.pop(row_index))) + rows[row_index - 1] = list( + map(merge_cells, rows[row_index - 1], rows.pop(row_index)) + ) else: row_index += 1 @@ -104,17 +107,19 @@ def details(output_lines): def is_microversion_supported(microversion): return ( - api_versions.APIVersion(CONF.min_api_microversion) <= - api_versions.APIVersion(microversion) <= - api_versions.APIVersion(CONF.max_api_microversion) + api_versions.APIVersion(CONF.min_api_microversion) + <= api_versions.APIVersion(microversion) + <= api_versions.APIVersion(CONF.max_api_microversion) ) def skip_if_microversion_not_supported(microversion): """Decorator for tests that are microversion-specific.""" if not is_microversion_supported(microversion): - reason = ("Skipped. Test requires microversion %s that is not " - "allowed to be used by configuration." % microversion) + reason = ( + f"Skipped. Test requires microversion {microversion} that is not " + "allowed to be used by configuration." + ) return testtools.skip(reason) return lambda f: f @@ -125,16 +130,29 @@ def choose_matching_backend(share, pools, share_type): # convert extra-specs in provided type to dict format pair = [x.strip() for x in share_type['required_extra_specs'].split(':')] if len(pair) == 2: - value = (True if str(pair[1]).lower() == 'true' - else False if str(pair[1]).lower() == 'false' - else pair[1]) + value = ( + True + if str(pair[1]).lower() == 'true' + else False + if str(pair[1]).lower() == 'false' + else pair[1] + ) extra_specs[pair[0]] = value selected_pool = next( - (x for x in pools if (x['Name'] != share['host'] and all( - y in ast.literal_eval(x['Capabilities']).items() for y in - extra_specs.items()))), - None) + ( + x + for x in pools + if ( + x['Name'] != share['host'] + and all( + y in ast.literal_eval(x['Capabilities']).items() + for y in extra_specs.items() + ) + ) + ), + None, + ) return selected_pool['Name'] @@ -145,10 +163,17 @@ def share_network_subnets_are_supported(): def get_subnet_by_availability_zone_name(client, share_network_id, az_name): subnets = client.get_share_network_subnets(share_network_id) - return next((subnet for subnet in subnets - if subnet['availability_zone'] == az_name), None) + return next( + ( + subnet + for subnet in subnets + if subnet['availability_zone'] == az_name + ), + None, + ) def get_default_subnet(client, share_network_id): - return get_subnet_by_availability_zone_name(client, share_network_id, - 'None') + return get_subnet_by_availability_zone_name( + client, share_network_id, 'None' + ) diff --git a/manilaclient/tests/unit/common/test_httpclient.py b/manilaclient/tests/unit/common/test_httpclient.py index c03e2f47..474f22ca 100644 --- a/manilaclient/tests/unit/common/test_httpclient.py +++ b/manilaclient/tests/unit/common/test_httpclient.py @@ -23,69 +23,85 @@ fake_user_agent = "fake" -fake_response = utils.TestResponse({ - "status_code": 200, - "text": '{"hi": "there"}', -}) +fake_response = utils.TestResponse( + { + "status_code": 200, + "text": '{"hi": "there"}', + } +) mock_request = mock.Mock(return_value=(fake_response)) -bad_400_response = utils.TestResponse({ - "status_code": 400, - "text": '{"error": {"message": "n/a", "details": "Terrible!"}}', -}) +bad_400_response = utils.TestResponse( + { + "status_code": 400, + "text": '{"error": {"message": "n/a", "details": "Terrible!"}}', + } +) bad_400_request = mock.Mock(return_value=(bad_400_response)) -bad_401_response = utils.TestResponse({ - "status_code": 401, - "text": '{"error": {"message": "FAILED!", "details": "DETAILS!"}}', -}) +bad_401_response = utils.TestResponse( + { + "status_code": 401, + "text": '{"error": {"message": "FAILED!", "details": "DETAILS!"}}', + } +) bad_401_request = mock.Mock(return_value=(bad_401_response)) -bad_500_response = utils.TestResponse({ - "status_code": 500, - "text": '{"error": {"message": "FAILED!", "details": "DETAILS!"}}', -}) +bad_500_response = utils.TestResponse( + { + "status_code": 500, + "text": '{"error": {"message": "FAILED!", "details": "DETAILS!"}}', + } +) bad_500_request = mock.Mock(return_value=(bad_500_response)) -retry_after_response = utils.TestResponse({ - "status_code": 413, - "text": '', - "headers": { - "retry-after": "5" - }, -}) +retry_after_response = utils.TestResponse( + { + "status_code": 413, + "text": '', + "headers": {"retry-after": "5"}, + } +) retry_after_mock_request = mock.Mock(return_value=retry_after_response) -retry_after_no_headers_response = utils.TestResponse({ - "status_code": 413, - "text": '', -}) +retry_after_no_headers_response = utils.TestResponse( + { + "status_code": 413, + "text": '', + } +) retry_after_no_headers_mock_request = mock.Mock( - return_value=retry_after_no_headers_response) - -retry_after_non_supporting_response = utils.TestResponse({ - "status_code": 403, - "text": '', - "headers": { - "retry-after": "5" - }, -}) + return_value=retry_after_no_headers_response +) + +retry_after_non_supporting_response = utils.TestResponse( + { + "status_code": 403, + "text": '', + "headers": {"retry-after": "5"}, + } +) retry_after_non_supporting_mock_request = mock.Mock( - return_value=retry_after_non_supporting_response) + return_value=retry_after_non_supporting_response +) def get_authed_client(endpoint_url="http://example.com", retries=0): - cl = httpclient.HTTPClient(endpoint_url, "token", fake_user_agent, - retries=retries, http_log_debug=True, - api_version=manilaclient.API_MAX_VERSION) + cl = httpclient.HTTPClient( + endpoint_url, + "token", + fake_user_agent, + retries=retries, + http_log_debug=True, + api_version=manilaclient.API_MAX_VERSION, + ) return cl @ddt.ddt class ClientTest(utils.TestCase): - def setUp(self): - super(ClientTest, self).setUp() + super().setUp() self.max_version = manilaclient.API_MAX_VERSION self.max_version_str = self.max_version.get_string() @@ -99,7 +115,8 @@ def setUp(self): "http://10.10.10.10:3366/v2/b2d18606-2673-4965-885a-4f5a8b955b9b", "http://manila.example.com:3366/v1.1/", "http://manila.example.com:3366/v2/" - "b2d18606-2673-4965-885a-4f5a8b955b9b") + "b2d18606-2673-4965-885a-4f5a8b955b9b", + ) def test_get(self, endpoint_url): cl = get_authed_client(endpoint_url) @@ -117,11 +134,14 @@ def test_get_call(): "GET", endpoint_url + "/hi", headers=headers, - **self.TEST_REQUEST_BASE) + **self.TEST_REQUEST_BASE, + ) # Automatic JSON parsing self.assertEqual(body, {"hi": "there"}) - self.assertEqual(re.split(r'/v[0-9]+[\.0-9]*', - endpoint_url)[0] + "/", cl.base_url) + self.assertEqual( + re.split(r'/v[0-9]+[\.0-9]*', endpoint_url)[0] + "/", + cl.base_url, + ) test_get_call() @@ -212,7 +232,8 @@ def test_get_call(): "http://10.10.10.10:3366/v2/b2d18606-2673-4965-885a-4f5a8b955b9b", "http://manila.example.com:3366/v2.22/", "http://manila.example.com:3366/v1/" - "b2d18606-2673-4965-885a-4f5a8b955b9b") + "b2d18606-2673-4965-885a-4f5a8b955b9b", + ) def test_post(self, endpoint_url): cl = get_authed_client(endpoint_url) @@ -224,15 +245,18 @@ def test_post_call(): "Content-Type": "application/json", 'Accept': 'application/json', "X-Openstack-Manila-Api-Version": self.max_version_str, - "User-Agent": fake_user_agent + "User-Agent": fake_user_agent, } mock_request.assert_called_with( "POST", endpoint_url + "/hi", headers=headers, data='[1, 2, 3]', - **self.TEST_REQUEST_BASE) - self.assertEqual(re.split(r'/v[0-9]+[\.0-9]*', - endpoint_url)[0] + "/", cl.base_url) + **self.TEST_REQUEST_BASE, + ) + self.assertEqual( + re.split(r'/v[0-9]+[\.0-9]*', endpoint_url)[0] + "/", + cl.base_url, + ) test_post_call() diff --git a/manilaclient/tests/unit/fakes.py b/manilaclient/tests/unit/fakes.py index 01c29972..d8d469e2 100644 --- a/manilaclient/tests/unit/fakes.py +++ b/manilaclient/tests/unit/fakes.py @@ -29,34 +29,36 @@ def assert_has_keys(dictonary, required=None, optional=None): assert k in dictonary except AssertionError: extra_keys = set(dictonary).difference(set(required + optional)) - raise AssertionError("found unexpected keys: %s" % - list(extra_keys)) + raise AssertionError(f"found unexpected keys: {list(extra_keys)}") -class FakeClient(object): - +class FakeClient: def assert_called(self, method, url, body=None, pos=-1, **kwargs): """Assert than an API method was just called.""" expected = (method, url) called = self.client.callstack[pos][0:2] - assert self.client.callstack, ("Expected %s %s but no calls " - "were made." % expected) + assert self.client.callstack, ( + "Expected {} {} but no calls were made.".format(*expected) + ) assert expected == called, 'Expected %s %s; got %s %s' % ( - expected + called) + expected + called + ) if body is not None: actual = self.client.callstack[pos][2] - assert actual == body, "Expected %s; got %s" % (body, actual) + assert actual == body, f"Expected {body}; got {actual}" - def assert_called_anytime(self, method, url, body=None, - clear_callstack=True): + def assert_called_anytime( + self, method, url, body=None, clear_callstack=True + ): """Assert than an API method was called anytime in the test.""" expected = (method, url) - assert self.client.callstack, ("Expected %s %s but no calls " - "were made." % expected) + assert self.client.callstack, ( + "Expected {} {} but no calls were made.".format(*expected) + ) found = False for entry in self.client.callstack: @@ -64,8 +66,10 @@ def assert_called_anytime(self, method, url, body=None, found = True break - assert found, 'Expected %s %s; got %s' % ( - expected[0], expected[1], self.client.callstack) + assert found, ( + f'Expected {expected[0]} {expected[1]}; ' + f'got {self.client.callstack}' + ) if body is not None: try: diff --git a/manilaclient/tests/unit/osc/osc_fakes.py b/manilaclient/tests/unit/osc/osc_fakes.py index 07beb4af..1b90708a 100644 --- a/manilaclient/tests/unit/osc/osc_fakes.py +++ b/manilaclient/tests/unit/osc/osc_fakes.py @@ -27,8 +27,7 @@ INTERFACE = "catchy" VERSION = "3" -TEST_RESPONSE_DICT = fixture.V2Token(token_id=AUTH_TOKEN, - user_name=USERNAME) +TEST_RESPONSE_DICT = fixture.V2Token(token_id=AUTH_TOKEN, user_name=USERNAME) _s = TEST_RESPONSE_DICT.add_service('identity', name='keystone') _s.add_endpoint(AUTH_URL + ':5000/v2.0') _s = TEST_RESPONSE_DICT.add_service('network', name='neutron') @@ -46,8 +45,7 @@ TEST_VERSIONS = fixture.DiscoveryList(href=AUTH_URL) -class FakeStdout(object): - +class FakeStdout: def __init__(self): self.content = [] @@ -61,8 +59,7 @@ def make_string(self): return result -class FakeLog(object): - +class FakeLog: def __init__(self): self.messages = {} @@ -82,8 +79,7 @@ def critical(self, msg): self.messages['critical'] = msg -class FakeApp(object): - +class FakeApp: def __init__(self, _stdout, _log): self.stdout = _stdout self.client_manager = None @@ -93,19 +89,18 @@ def __init__(self, _stdout, _log): self.log = _log -class FakeOptions(object): +class FakeOptions: def __init__(self, **kwargs): self.os_beta_command = False -class FakeClient(object): - +class FakeClient: def __init__(self, **kwargs): self.endpoint = kwargs['endpoint'] self.token = kwargs['token'] -class FakeClientManager(object): +class FakeClientManager: _api_version = { 'image': '2', } @@ -137,8 +132,7 @@ def is_network_endpoint_enabled(self): return self.network_endpoint_enabled -class FakeResource(object): - +class FakeResource: def __init__(self, manager=None, info=None, loaded=False, methods=None): """Set attributes and methods for a resource. @@ -162,7 +156,7 @@ def __init__(self, manager=None, info=None, loaded=False, methods=None): self._loaded = loaded def _add_details(self, info): - for (k, v) in info.items(): + for k, v in info.items(): setattr(self, k, v) def _add_methods(self, methods): @@ -173,15 +167,16 @@ def _add_methods(self, methods): @value. When users access the attribute with (), @value will be returned, which looks like a function call. """ - for (name, ret) in methods.items(): + for name, ret in methods.items(): method = mock.Mock(return_value=ret) setattr(self, name, method) def __repr__(self): - reprkeys = sorted(k for k in self.__dict__.keys() if k[0] != '_' and - k != 'manager') - info = ", ".join("%s=%s" % (k, getattr(self, k)) for k in reprkeys) - return "<%s %s>" % (self.__class__.__name__, info) + reprkeys = sorted( + k for k in self.__dict__.keys() if k[0] != '_' and k != 'manager' + ) + info = ", ".join(f"{k}={getattr(self, k)}" for k in reprkeys) + return f"<{self.__class__.__name__} {info}>" def keys(self): return self._info.keys() @@ -201,15 +196,15 @@ def get(self, item, default=None): class FakeLimitsResource(FakeResource): - class AbsoluteLimit: def __init__(self, name, value): self.name = name self.value = value class RateLimit: - def __init__(self, verb, uri, regex, value, remaining, - unit, next_available): + def __init__( + self, verb, uri, regex, value, remaining, unit, next_available + ): self.verb = verb self.uri = uri self.regex = regex @@ -236,5 +231,6 @@ def rate(self): rate['value'], rate['remaining'], rate['unit'], - rate['next-available']) + rate['next-available'], + ) ] diff --git a/manilaclient/tests/unit/osc/osc_utils.py b/manilaclient/tests/unit/osc/osc_utils.py index 3c5c8683..c7a75b6b 100644 --- a/manilaclient/tests/unit/osc/osc_utils.py +++ b/manilaclient/tests/unit/osc/osc_utils.py @@ -26,17 +26,20 @@ class ParserException(Exception): class TestCase(testtools.TestCase): - def setUp(self): testtools.TestCase.setUp(self) - if (os.environ.get("OS_STDOUT_CAPTURE") == "True" or - os.environ.get("OS_STDOUT_CAPTURE") == "1"): + if ( + os.environ.get("OS_STDOUT_CAPTURE") == "True" + or os.environ.get("OS_STDOUT_CAPTURE") == "1" + ): stdout = self.useFixture(fixtures.StringStream("stdout")).stream self.useFixture(fixtures.MonkeyPatch("sys.stdout", stdout)) - if (os.environ.get("OS_STDERR_CAPTURE") == "True" or - os.environ.get("OS_STDERR_CAPTURE") == "1"): + if ( + os.environ.get("OS_STDERR_CAPTURE") == "True" + or os.environ.get("OS_STDERR_CAPTURE") == "1" + ): stderr = self.useFixture(fixtures.StringStream("stderr")).stream self.useFixture(fixtures.MonkeyPatch("sys.stderr", stderr)) @@ -45,7 +48,7 @@ def assertNotCalled(self, m, msg=None): if m.called: if not msg: - msg = 'method %s should not have been called' % m + msg = f'method {m} should not have been called' self.fail(msg) @@ -53,7 +56,7 @@ class TestCommand(TestCase): """Test cliff command classes""" def setUp(self): - super(TestCommand, self).setUp() + super().setUp() # Build up a fake app self.fake_stdout = fakes.FakeStdout() self.fake_log = fakes.FakeLog() diff --git a/manilaclient/tests/unit/osc/v2/fakes.py b/manilaclient/tests/unit/osc/v2/fakes.py index 15bc79e1..d8e0ad57 100644 --- a/manilaclient/tests/unit/osc/v2/fakes.py +++ b/manilaclient/tests/unit/osc/v2/fakes.py @@ -18,15 +18,15 @@ import uuid from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes +from osc_lib.cli import format_columns from manilaclient.tests.unit.osc import osc_fakes from manilaclient.tests.unit.osc import osc_utils -class FakeShareClient(object): - +class FakeShareClient: def __init__(self, **kwargs): - super(FakeShareClient, self).__init__() + super().__init__() self.auth_token = kwargs['token'] self.management_url = kwargs['endpoint'] self.shares = mock.Mock() @@ -51,8 +51,9 @@ def __init__(self, **kwargs): self.share_instance_export_locations = mock.Mock() self.share_export_locations = mock.Mock() self.share_snapshot_instance_export_locations = mock.Mock() - self.share_export_locations.resource_class = ( - osc_fakes.FakeResource(None, {})) + self.share_export_locations.resource_class = osc_fakes.FakeResource( + None, {} + ) self.messages = mock.Mock() self.availability_zones = mock.Mock() self.services = mock.Mock() @@ -63,36 +64,23 @@ def __init__(self, **kwargs): self.share_group_type_access = mock.Mock() self.share_servers = mock.Mock() self.resource_locks = mock.Mock() - - -class ManilaParseException(Exception): - """The base exception class for all exceptions this library raises.""" - - def __init__(self, message=None, details=None): - self.message = message or "Argument parse exception" - self.details = details or None - - def __str__(self): - return self.message + self.qos_types = mock.Mock() class TestShare(osc_utils.TestCommand): - def setUp(self): - super(TestShare, self).setUp() + super().setUp() self.app.client_manager.share = FakeShareClient( - endpoint=osc_fakes.AUTH_URL, - token=osc_fakes.AUTH_TOKEN + endpoint=osc_fakes.AUTH_URL, token=osc_fakes.AUTH_TOKEN ) self.app.client_manager.identity = identity_fakes.FakeIdentityv3Client( - endpoint=osc_fakes.AUTH_URL, - token=osc_fakes.AUTH_TOKEN + endpoint=osc_fakes.AUTH_URL, token=osc_fakes.AUTH_TOKEN ) -class FakeShare(object): +class FakeShare: """Fake one or more shares.""" @staticmethod @@ -140,14 +128,15 @@ def create_one_share(attrs=None, methods=None): "source_share_group_snapshot_member_id": None, "scheduler_hints": {}, "mount_point_name": None, + "encryption_key_ref": None, } # Overwrite default attributes. share_info.update(attrs) - share = osc_fakes.FakeResource(info=copy.deepcopy(share_info), - methods=methods, - loaded=True) + share = osc_fakes.FakeResource( + info=copy.deepcopy(share_info), methods=methods, loaded=True + ) return share @staticmethod @@ -219,13 +208,14 @@ def get_share_data(share=None): if x == 'tags': # The 'tags' should be format_list data_list.append( - format_columns.ListColumn(share.info.get(x))) + format_columns.ListColumn(share.info.get(x)) + ) else: data_list.append(share.info.get(x)) return tuple(data_list) -class FakeShareType(object): +class FakeShareType: """Fake one or more share types""" @staticmethod @@ -242,9 +232,7 @@ def create_one_sharetype(attrs=None, methods=None): methods = methods or {} share_type_info = { - "required_extra_specs": { - "driver_handles_share_servers": True - }, + "required_extra_specs": {"driver_handles_share_servers": True}, "share_type_access:is_public": True, "extra_specs": { "replication_type": "readable", @@ -252,19 +240,18 @@ def create_one_sharetype(attrs=None, methods=None): "mount_snapshot_support": False, "revert_to_snapshot_support": False, "create_share_from_snapshot_support": True, - "snapshot_support": True + "snapshot_support": True, }, "id": 'share-type-id-' + uuid.uuid4().hex, "name": 'share-type-name-' + uuid.uuid4().hex, "is_default": False, - "description": 'share-type-description-' + uuid.uuid4().hex + "description": 'share-type-description-' + uuid.uuid4().hex, } share_type_info.update(attrs) - share_type = osc_fakes.FakeResource(info=copy.deepcopy( - share_type_info), - methods=methods, - loaded=True) + share_type = osc_fakes.FakeResource( + info=copy.deepcopy(share_type_info), methods=methods, loaded=True + ) return share_type @staticmethod @@ -307,7 +294,7 @@ def get_share_types(share_types=None, count=2): return mock.Mock(side_effect=share_types) -class FakeShareExportLocation(object): +class FakeShareExportLocation: """Fake one or more export locations""" @staticmethod @@ -335,9 +322,9 @@ def create_one_export_location(attrs=None): } share_export_location_info.update(attrs) - share_export_location = osc_fakes.FakeResource(info=copy.deepcopy( - share_export_location_info), - loaded=True) + share_export_location = osc_fakes.FakeResource( + info=copy.deepcopy(share_export_location_info), loaded=True + ) return share_export_location @staticmethod @@ -357,12 +344,12 @@ def create_share_export_locations(attrs=None, count=2): share_export_locations = [] for n in range(0, count): share_export_locations.append( - FakeShareExportLocation. - create_one_export_location(attrs)) + FakeShareExportLocation.create_one_export_location(attrs) + ) return share_export_locations -class FakeShareAccessRule(object): +class FakeShareAccessRule: """Fake one or more share access rules""" @staticmethod @@ -385,17 +372,17 @@ def create_one_access_rule(attrs=None): 'access_key': None, 'created_at': datetime.datetime.now().isoformat(), 'updated_at': None, - 'properties': {} + 'properties': {}, } share_access_rule.update(attrs) - share_access_rule = osc_fakes.FakeResource(info=copy.deepcopy( - share_access_rule), - loaded=True) + share_access_rule = osc_fakes.FakeResource( + info=copy.deepcopy(share_access_rule), loaded=True + ) return share_access_rule -class FakeQuotaSet(object): +class FakeQuotaSet: """Fake quota set""" @staticmethod @@ -420,16 +407,17 @@ def create_fake_quotas(attrs=None): 'shapshot_gigabytes': 1000, 'snapshots': 50, 'per_share_gigabytes': -1, + 'encryption_keys': 100, } quotas_info.update(attrs) - quotas = osc_fakes.FakeResource(info=copy.deepcopy( - quotas_info), - loaded=True) + quotas = osc_fakes.FakeResource( + info=copy.deepcopy(quotas_info), loaded=True + ) return quotas -class FakeShareSnapshotIntances(object): +class FakeShareSnapshotIntances: """Fake a share snapshot instance""" @staticmethod @@ -453,14 +441,15 @@ def create_one_snapshot_instance(attrs=None, methods=None): 'share_id': 'share-id-' + uuid.uuid4().hex, 'share_instance_id': 'share-instance-id-' + uuid.uuid4().hex, 'progress': None, - 'provider_location': None + 'provider_location': None, } share_snapshot_instance.update(attrs) - share_snapshot_instance = osc_fakes.FakeResource(info=copy.deepcopy( - share_snapshot_instance), + share_snapshot_instance = osc_fakes.FakeResource( + info=copy.deepcopy(share_snapshot_instance), methods=methods, - loaded=True) + loaded=True, + ) return share_snapshot_instance @staticmethod @@ -478,12 +467,13 @@ def create_share_snapshot_instances(attrs=None, count=2): share_snapshot_instances = [] for n in range(0, count): share_snapshot_instances.append( - FakeShareSnapshot.create_one_snapshot(attrs)) + FakeShareSnapshot.create_one_snapshot(attrs) + ) return share_snapshot_instances -class FakeShareSnapshotInstancesExportLocations(object): +class FakeShareSnapshotInstancesExportLocations: """Fake a share snapshot instance Export Locations""" @staticmethod @@ -506,10 +496,10 @@ def create_one_snapshot_instance(attrs=None, methods=None): share_snapshot_instance_export_location.update(attrs) share_snapshot_instance_export_location = osc_fakes.FakeResource( - info=copy.deepcopy( - share_snapshot_instance_export_location), + info=copy.deepcopy(share_snapshot_instance_export_location), methods=methods, - loaded=True) + loaded=True, + ) return share_snapshot_instance_export_location @staticmethod @@ -527,12 +517,13 @@ def create_share_snapshot_instances(attrs=None, count=2): share_snapshot_instances = [] for n in range(0, count): share_snapshot_instances.append( - FakeShareSnapshot.create_one_snapshot(attrs)) + FakeShareSnapshot.create_one_snapshot(attrs) + ) return share_snapshot_instances -class FakeShareSnapshot(object): +class FakeShareSnapshot: """Fake a share snapshot""" @staticmethod @@ -560,14 +551,13 @@ def create_one_snapshot(attrs=None, methods=None): 'share_size': 1, 'size': 1, 'status': None, - 'user_id': 'user-id-' + uuid.uuid4().hex + 'user_id': 'user-id-' + uuid.uuid4().hex, } share_snapshot.update(attrs) - share_snapshot = osc_fakes.FakeResource(info=copy.deepcopy( - share_snapshot), - methods=methods, - loaded=True) + share_snapshot = osc_fakes.FakeResource( + info=copy.deepcopy(share_snapshot), methods=methods, loaded=True + ) return share_snapshot @staticmethod @@ -585,12 +575,13 @@ def create_share_snapshots(attrs=None, count=2): share_snapshots = [] for n in range(0, count): share_snapshots.append( - FakeShareSnapshot.create_one_snapshot(attrs)) + FakeShareSnapshot.create_one_snapshot(attrs) + ) return share_snapshots -class FakeShareTransfer(object): +class FakeShareTransfer: """Fake a share transfer""" @staticmethod @@ -618,14 +609,13 @@ def create_one_transfer(attrs=None, methods=None): 'name': 'name-' + uuid.uuid4().hex, 'resource_id': 'resource-id-' + uuid.uuid4().hex, 'resource_type': 'share', - 'source_project_id': 'source-project-id-' + uuid.uuid4().hex + 'source_project_id': 'source-project-id-' + uuid.uuid4().hex, } share_transfer.update(attrs) - share_transfer = osc_fakes.FakeResource(info=copy.deepcopy( - share_transfer), - methods=methods, - loaded=True) + share_transfer = osc_fakes.FakeResource( + info=copy.deepcopy(share_transfer), methods=methods, loaded=True + ) return share_transfer @staticmethod @@ -643,12 +633,13 @@ def create_share_transfers(attrs=None, count=2): share_transfers = [] for n in range(0, count): share_transfers.append( - FakeShareSnapshot.create_one_snapshot(attrs)) + FakeShareSnapshot.create_one_snapshot(attrs) + ) return share_transfers -class FakeSnapshotAccessRule(object): +class FakeSnapshotAccessRule: """Fake one or more snapshot access rules""" @staticmethod @@ -665,13 +656,13 @@ def create_one_access_rule(attrs={}): 'access_to': 'demo', 'access_type': 'user', 'id': 'access_rule-id-' + uuid.uuid4().hex, - 'state': 'queued_to_apply' + 'state': 'queued_to_apply', } snapshot_access_rule.update(attrs) - snapshot_access_rule = osc_fakes.FakeResource(info=copy.deepcopy( - snapshot_access_rule), - loaded=True) + snapshot_access_rule = osc_fakes.FakeResource( + info=copy.deepcopy(snapshot_access_rule), loaded=True + ) return snapshot_access_rule @staticmethod @@ -689,12 +680,13 @@ def create_access_rules(attrs={}, count=2): access_rules = [] for n in range(0, count): access_rules.append( - FakeSnapshotAccessRule.create_one_access_rule(attrs)) + FakeSnapshotAccessRule.create_one_access_rule(attrs) + ) return access_rules -class FakeSnapshotExportLocation(object): +class FakeSnapshotExportLocation: """Fake one or more export locations""" @staticmethod @@ -720,9 +712,9 @@ def create_one_export_location(attrs=None): } snapshot_export_location_info.update(attrs) - snapshot_export_location = osc_fakes.FakeResource(info=copy.deepcopy( - snapshot_export_location_info), - loaded=True) + snapshot_export_location = osc_fakes.FakeResource( + info=copy.deepcopy(snapshot_export_location_info), loaded=True + ) return snapshot_export_location @staticmethod @@ -740,13 +732,13 @@ def create_export_locations(attrs={}, count=2): export_locations = [] for n in range(0, count): export_locations.append( - FakeSnapshotExportLocation.create_one_export_location( - attrs)) + FakeSnapshotExportLocation.create_one_export_location(attrs) + ) return export_locations -class FakeMessage(object): +class FakeMessage: """Fake message""" @staticmethod @@ -777,9 +769,9 @@ def create_one_message(attrs=None): } message.update(attrs) - message = osc_fakes.FakeResource(info=copy.deepcopy( - message), - loaded=True) + message = osc_fakes.FakeResource( + info=copy.deepcopy(message), loaded=True + ) return message @staticmethod @@ -796,13 +788,12 @@ def create_messages(attrs={}, count=2): messages = [] for n in range(0, count): - messages.append( - FakeMessage.create_one_message(attrs)) + messages.append(FakeMessage.create_one_message(attrs)) return messages -class FakeShareReplica(object): +class FakeShareReplica: """Fake a share replica""" @staticmethod @@ -829,14 +820,14 @@ def create_one_replica(attrs=None, methods=None): 'share_network_id': None, 'share_server_id': None, 'status': None, - 'updated_at': None + 'updated_at': None, + "properties": format_columns.DictColumn({}), } share_replica.update(attrs) - share_replica = osc_fakes.FakeResource(info=copy.deepcopy( - share_replica), - methods=methods, - loaded=True) + share_replica = osc_fakes.FakeResource( + info=copy.deepcopy(share_replica), methods=methods, loaded=True + ) return share_replica @staticmethod @@ -853,12 +844,11 @@ def create_share_replicas(attrs=None, count=2): share_replicas = [] for n in range(0, count): - share_replicas.append( - FakeShareReplica.create_one_replica(attrs)) + share_replicas.append(FakeShareReplica.create_one_replica(attrs)) return share_replicas -class FakeShareAvailabilityZones(object): +class FakeShareAvailabilityZones: """Fake one or more availability zones""" @staticmethod @@ -881,14 +871,13 @@ def create_one_availability_zone(attrs=None): } availability_zone.update(attrs) - availability_zone = osc_fakes.FakeResource(info=copy.deepcopy( - availability_zone), - loaded=True) + availability_zone = osc_fakes.FakeResource( + info=copy.deepcopy(availability_zone), loaded=True + ) return availability_zone @staticmethod def create_share_availability_zones(attrs=None, count=2): - """Create multiple availability zones. :param Dictionary attrs: @@ -902,11 +891,12 @@ def create_share_availability_zones(attrs=None, count=2): availability_zones = [] for n in range(0, count): availability_zones.append( - FakeShareAvailabilityZones.create_one_availability_zone(attrs)) + FakeShareAvailabilityZones.create_one_availability_zone(attrs) + ) return availability_zones -class FakeShareService(object): +class FakeShareService: """Fake one or more share service""" @staticmethod @@ -928,13 +918,13 @@ def create_fake_service(attrs=None): "status": "enabled", "state": "up", "updated_at": 'time-' + uuid.uuid4().hex, - "zone": "fake_zone" + "zone": "fake_zone", } share_service_info.update(attrs) - share_service = osc_fakes.FakeResource(info=copy.deepcopy( - share_service_info), - loaded=True) + share_service = osc_fakes.FakeResource( + info=copy.deepcopy(share_service_info), loaded=True + ) return share_service @staticmethod @@ -951,12 +941,11 @@ def create_fake_services(attrs=None, count=2): services = [] for n in range(count): - services.append( - FakeShareService.create_fake_service(attrs)) + services.append(FakeShareService.create_fake_service(attrs)) return services -class FakeShareSecurityService(object): +class FakeShareSecurityService: """Fake one or more share security service""" @staticmethod @@ -991,10 +980,11 @@ def create_fake_security_service(attrs=None, methods=None): } share_security_service_info.update(attrs) - share_security_service = osc_fakes.FakeResource(info=copy.deepcopy( - share_security_service_info), + share_security_service = osc_fakes.FakeResource( + info=copy.deepcopy(share_security_service_info), methods=methods, - loaded=True) + loaded=True, + ) return share_security_service @staticmethod @@ -1012,11 +1002,12 @@ def create_fake_security_services(attrs=None, count=2): security_services = [] for n in range(count): security_services.append( - FakeShareSecurityService.create_fake_security_service(attrs)) + FakeShareSecurityService.create_fake_security_service(attrs) + ) return security_services -class FakeSharePools(object): +class FakeSharePools: """Fake one or more share pool""" @staticmethod @@ -1036,13 +1027,13 @@ def create_one_share_pool(attrs=None): "host": 'fake_host_' + uuid.uuid4().hex, "backend": 'fake_backend_' + uuid.uuid4().hex, "pool": 'fake_pool_' + uuid.uuid4().hex, - "capabilities": {'fake_capability': uuid.uuid4().hex} + "capabilities": {'fake_capability': uuid.uuid4().hex}, } share_pool.update(attrs) - share_pool = osc_fakes.FakeResource(info=copy.deepcopy( - share_pool), - loaded=True) + share_pool = osc_fakes.FakeResource( + info=copy.deepcopy(share_pool), loaded=True + ) return share_pool @staticmethod @@ -1059,12 +1050,11 @@ def create_share_pools(attrs=None, count=2): share_pools = [] for n in range(count): - share_pools.append( - FakeSharePools.create_one_share_pool(attrs)) + share_pools.append(FakeSharePools.create_one_share_pool(attrs)) return share_pools -class FakeShareInstance(object): +class FakeShareInstance: """Fake a share instance""" @staticmethod @@ -1091,14 +1081,13 @@ def create_one_share_instance(attrs=None, methods=None): 'share_server_id': 'ss-id-' + uuid.uuid4().hex, 'host': None, 'access_rules_status': None, - 'id': 'instance-id-' + uuid.uuid4().hex + 'id': 'instance-id-' + uuid.uuid4().hex, } share_instance.update(attrs) - share_instance = osc_fakes.FakeResource(info=copy.deepcopy( - share_instance), - methods=methods, - loaded=True) + share_instance = osc_fakes.FakeResource( + info=copy.deepcopy(share_instance), methods=methods, loaded=True + ) return share_instance @staticmethod @@ -1115,22 +1104,23 @@ def create_share_instances(attrs=None, count=2): share_instances = [] for n in range(count): share_instances.append( - FakeShareInstance.create_one_share_instance(attrs)) + FakeShareInstance.create_one_share_instance(attrs) + ) return share_instances -class FakeShareLimits(object): +class FakeShareLimits: """Fake one or more share limits""" @staticmethod def create_one_share_limit(attrs=None): """Create a fake share limit dict - :param Dictionary attrs: - A dictionary with all attributes - :return: - A FakeLimitsResource object, with share limits. - """ + :param Dictionary attrs: + A dictionary with all attributes + :return: + A FakeLimitsResource object, with share limits. + """ attrs = attrs or {} @@ -1146,16 +1136,17 @@ def create_one_share_limit(attrs=None): "unit": "MINUTE", "value": "3", "remaining": "1", - } + }, } share_limits.update(attrs) share_limits = osc_fakes.FakeLimitsResource( - info=copy.deepcopy(share_limits), loaded=True) + info=copy.deepcopy(share_limits), loaded=True + ) return share_limits -class FakeShareNetwork(object): +class FakeShareNetwork: """Fake a share network""" @staticmethod @@ -1192,16 +1183,15 @@ def create_one_share_network(attrs=None, methods=None): "cidr": "10.0.0.0/24", "network_type": "vlan", "mtu": "1500", - "gateway": "10.0.0.1" + "gateway": "10.0.0.1", }, ], } share_network.update(attrs) - share_network = osc_fakes.FakeResource(info=copy.deepcopy( - share_network), - methods=methods, - loaded=True) + share_network = osc_fakes.FakeResource( + info=copy.deepcopy(share_network), methods=methods, loaded=True + ) return share_network @staticmethod @@ -1220,12 +1210,13 @@ def create_share_networks(attrs=None, count=2): share_networks = [] for n in range(count): share_networks.append( - FakeShareNetwork.create_one_share_network(attrs)) + FakeShareNetwork.create_one_share_network(attrs) + ) return share_networks -class FakeShareNetworkSubnet(object): +class FakeShareNetworkSubnet: """Fake a share network subnet""" @staticmethod @@ -1259,9 +1250,9 @@ def create_one_share_subnet(attrs=None): } share_network_subnet.update(attrs) - share_network_subnet = osc_fakes.FakeResource(info=copy.deepcopy( - share_network_subnet), - loaded=True) + share_network_subnet = osc_fakes.FakeResource( + info=copy.deepcopy(share_network_subnet), loaded=True + ) return share_network_subnet @staticmethod @@ -1279,12 +1270,13 @@ def create_share_network_subnets(attrs=None, count=2): share_network_subnets = [] for n in range(count): share_network_subnets.append( - FakeShareNetworkSubnet.create_one_share_subnet(attrs)) + FakeShareNetworkSubnet.create_one_share_subnet(attrs) + ) return share_network_subnets -class FakeShareGroup(object): +class FakeShareGroup: """Fake a share group""" @staticmethod @@ -1314,14 +1306,13 @@ def create_one_share_group(attrs=None, methods=None): 'share_network_id': None, 'share_server_id': None, 'share_types': ['share-types-id-' + uuid.uuid4().hex], - 'consistent_snapshot_support': None + 'consistent_snapshot_support': None, } share_group.update(attrs) - share_group = osc_fakes.FakeResource(info=copy.deepcopy( - share_group), - methods=methods, - loaded=True) + share_group = osc_fakes.FakeResource( + info=copy.deepcopy(share_group), methods=methods, loaded=True + ) return share_group @staticmethod @@ -1338,12 +1329,11 @@ def create_share_groups(attrs=None, count=2): share_groups = [] for n in range(0, count): - share_groups.append( - FakeShareGroup.create_one_share_group(attrs)) + share_groups.append(FakeShareGroup.create_one_share_group(attrs)) return share_groups -class FakeShareGroupType(object): +class FakeShareGroupType: """Fake one or more share group types""" @staticmethod @@ -1361,20 +1351,19 @@ def create_one_share_group_type(attrs=None, methods=None): share_group_type_info = { "is_public": True, - "group_specs": { - "snapshot_support": True - }, + "group_specs": {"snapshot_support": True}, "share_types": ['share-types-id-' + uuid.uuid4().hex], "id": 'share-group-type-id-' + uuid.uuid4().hex, "name": 'share-group-type-name-' + uuid.uuid4().hex, - "is_default": False + "is_default": False, } share_group_type_info.update(attrs) - share_group_type = osc_fakes.FakeResource(info=copy.deepcopy( - share_group_type_info), - methods=methods, - loaded=True) + share_group_type = osc_fakes.FakeResource( + info=copy.deepcopy(share_group_type_info), + methods=methods, + loaded=True, + ) return share_group_type @staticmethod @@ -1392,7 +1381,8 @@ def create_share_group_types(attrs=None, count=2): share_group_types = [] for n in range(0, count): share_group_types.append( - FakeShareGroupType.create_one_share_group_type(attrs)) + FakeShareGroupType.create_one_share_group_type(attrs) + ) return share_group_types @@ -1418,7 +1408,7 @@ def get_share_group_types(share_group_types=None, count=2): return mock.Mock(side_effect=share_group_types) -class FakeShareGroupSnapshot(object): +class FakeShareGroupSnapshot: """Fake a share group snapshot""" @staticmethod @@ -1441,14 +1431,15 @@ def create_one_share_group_snapshot(attrs=None, methods=None): 'created_at': datetime.datetime.now().isoformat(), "project_id": 'project-id-' + uuid.uuid4().hex, 'id': 'share-group-snapshot-id-' + uuid.uuid4().hex, - 'description': None + 'description': None, } share_group_snapshot.update(attrs) - share_group_snapshot = osc_fakes.FakeResource(info=copy.deepcopy( - share_group_snapshot), + share_group_snapshot = osc_fakes.FakeResource( + info=copy.deepcopy(share_group_snapshot), methods=methods, - loaded=True) + loaded=True, + ) return share_group_snapshot @staticmethod @@ -1466,11 +1457,12 @@ def create_share_group_snapshots(attrs=None, count=2): share_group_snapshots = [] for n in range(0, count): share_group_snapshots.append( - FakeShareGroupSnapshot.create_one_share_group_snapshot(attrs)) + FakeShareGroupSnapshot.create_one_share_group_snapshot(attrs) + ) return share_group_snapshots -class FakeShareServer(object): +class FakeShareServer: """Fake a share server""" @staticmethod @@ -1499,14 +1491,13 @@ def create_one_server(attrs=None, methods=None): 'source_share_server_id': str(uuid.uuid4()), 'created_at': datetime.datetime.now().isoformat(), 'is_auto_deletable': False, - 'identifier': str(uuid.uuid4()) + 'identifier': str(uuid.uuid4()), } share_server.update(attrs) - share_server = osc_fakes.FakeResource(info=copy.deepcopy( - share_server), - methods=methods, - loaded=True) + share_server = osc_fakes.FakeResource( + info=copy.deepcopy(share_server), methods=methods, loaded=True + ) return share_server @staticmethod @@ -1523,12 +1514,11 @@ def create_share_servers(attrs=None, count=2): attrs = attrs or {} share_servers = [] for n in range(count): - share_servers.append( - FakeShareServer.create_one_server(attrs)) + share_servers.append(FakeShareServer.create_one_server(attrs)) return share_servers -class FakeResourceLock(object): +class FakeResourceLock: """Fake a resource lock""" @staticmethod @@ -1560,10 +1550,9 @@ def create_one_lock(attrs=None, methods=None): } lock.update(attrs) - lock = osc_fakes.FakeResource(info=copy.deepcopy( - lock), - methods=methods, - loaded=True) + lock = osc_fakes.FakeResource( + info=copy.deepcopy(lock), methods=methods, loaded=True + ) return lock @staticmethod @@ -1580,13 +1569,12 @@ def create_locks(attrs=None, count=2): resource_locks = [] for n in range(0, count): - resource_locks.append( - FakeResourceLock.create_one_lock(attrs)) + resource_locks.append(FakeResourceLock.create_one_lock(attrs)) return resource_locks -class FakeShareBackup(object): +class FakeShareBackup: """Fake a share Backup""" @staticmethod @@ -1619,10 +1607,9 @@ def create_one_backup(attrs=None, methods=None): } share_backup.update(attrs) - share_backup = osc_fakes.FakeResource(info=copy.deepcopy( - share_backup), - methods=methods, - loaded=True) + share_backup = osc_fakes.FakeResource( + info=copy.deepcopy(share_backup), methods=methods, loaded=True + ) return share_backup @staticmethod @@ -1639,6 +1626,79 @@ def create_share_backups(attrs=None, count=2): share_backups = [] for n in range(0, count): - share_backups.append( - FakeShareBackup.create_one_backup(attrs)) + share_backups.append(FakeShareBackup.create_one_backup(attrs)) return share_backups + + +class FakeQosType: + """Fake one or more qos types""" + + @staticmethod + def create_one_qostype(attrs=None, methods=None): + """Create a fake qos type + + :param Dictionary attrs: + A dictionary with all attributes + :return: + A FakeResource object, with project_id, resource and so on + """ + + attrs = attrs or {} + methods = methods or {} + + qos_type_info = { + "id": 'qos-type-id-' + uuid.uuid4().hex, + "name": 'qos-type-name-' + uuid.uuid4().hex, + "description": 'qos-type-description-' + uuid.uuid4().hex, + "specs": { + "expected_iops": "2000", + "peak_iops": "5000", + }, + "created_at": 'time-' + uuid.uuid4().hex, + "updated_at": 'time-' + uuid.uuid4().hex, + } + + qos_type_info.update(attrs) + qos_type = osc_fakes.FakeResource( + info=copy.deepcopy(qos_type_info), methods=methods, loaded=True + ) + return qos_type + + @staticmethod + def create_qos_types(attrs=None, count=2): + """Create multiple fake qos types. + + :param Dictionary attrs: + A dictionary with all attributes + :param Integer count: + The number of qos types to be faked + :return: + A list of FakeResource objects + """ + + qos_types = [] + for n in range(0, count): + qos_types.append(FakeQosType.create_one_qostype(attrs)) + + return qos_types + + @staticmethod + def get_qos_types(qos_types=None, count=2): + """Get an iterable MagicMock object with a list of faked types. + + If types list is provided, then initialize the Mock object with the + list. Otherwise create one. + + :param List types: + A list of FakeResource objects faking types + :param Integer count: + The number of types to be faked + :return + An iterable Mock object with side_effect set to a list of faked + types + """ + + if qos_types is None: + qos_types = FakeQosType.create_qos_types(count) + + return mock.Mock(side_effect=qos_types) diff --git a/manilaclient/tests/unit/osc/v2/test_availability_zones.py b/manilaclient/tests/unit/osc/v2/test_availability_zones.py index 02b5cebf..90de3c18 100644 --- a/manilaclient/tests/unit/osc/v2/test_availability_zones.py +++ b/manilaclient/tests/unit/osc/v2/test_availability_zones.py @@ -18,31 +18,31 @@ class TestAvailabilityZones(manila_fakes.TestShare): - def setUp(self): - super(TestAvailabilityZones, self).setUp() + super().setUp() self.zones_mock = self.app.client_manager.share.availability_zones self.zones_mock.reset_mock() class TestShareAvailabilityZoneList(TestAvailabilityZones): - - availability_zones = manila_fakes.FakeShareAvailabilityZones.\ - create_share_availability_zones() + availability_zones = manila_fakes.FakeShareAvailabilityZones.create_share_availability_zones() # noqa: E501 COLUMNS = ("Id", "Name", "Created At", "Updated At") def setUp(self): - super(TestShareAvailabilityZoneList, self).setUp() + super().setUp() self.zones_mock.list.return_value = self.availability_zones # Get the command object to test self.cmd = osc_availability_zones.ShareAvailabilityZoneList( - self.app, None) + self.app, None + ) - self.values = (oscutils.get_dict_properties( - s._info, self.COLUMNS) for s in self.availability_zones) + self.values = ( + oscutils.get_dict_properties(s._info, self.COLUMNS) + for s in self.availability_zones + ) def test_share_list_availability_zone(self): arglist = [] diff --git a/manilaclient/tests/unit/osc/v2/test_messages.py b/manilaclient/tests/unit/osc/v2/test_messages.py index dbfef9bd..855cd93d 100644 --- a/manilaclient/tests/unit/osc/v2/test_messages.py +++ b/manilaclient/tests/unit/osc/v2/test_messages.py @@ -31,24 +31,22 @@ class TestMessage(manila_fakes.TestShare): - def setUp(self): - super(TestMessage, self).setUp() + super().setUp() self.messages_mock = self.app.client_manager.share.messages self.messages_mock.reset_mock() self.app.client_manager.share.api_version = api_versions.APIVersion( - api_versions.MAX_VERSION) + api_versions.MAX_VERSION + ) class TestMessageDelete(TestMessage): - def setUp(self): - super(TestMessageDelete, self).setUp() + super().setUp() - self.message = ( - manila_fakes.FakeMessage.create_one_message()) + self.message = manila_fakes.FakeMessage.create_one_message() self.messages_mock.get.return_value = self.message @@ -58,16 +56,17 @@ def test_message_delete_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_message_delete(self): - arglist = [ - self.message.id - ] - verifylist = [ - ('message', [self.message.id]) - ] + arglist = [self.message.id] + verifylist = [('message', [self.message.id])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -77,47 +76,33 @@ def test_message_delete(self): self.assertIsNone(result) def test_message_delete_multiple(self): - messages = ( - manila_fakes.FakeMessage.create_messages( - count=2)) - arglist = [ - messages[0].id, - messages[1].id - ] - verifylist = [ - ('message', [messages[0].id, messages[1].id]) - ] + messages = manila_fakes.FakeMessage.create_messages(count=2) + arglist = [messages[0].id, messages[1].id] + verifylist = [('message', [messages[0].id, messages[1].id])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.assertEqual(self.messages_mock.delete.call_count, - len(messages)) + self.assertEqual(self.messages_mock.delete.call_count, len(messages)) self.assertIsNone(result) def test_message_delete_exception(self): - arglist = [ - self.message.id - ] - verifylist = [ - ('message', [self.message.id]) - ] + arglist = [self.message.id] + verifylist = [('message', [self.message.id])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.messages_mock.delete.side_effect = exceptions.CommandError() - self.assertRaises(exceptions.CommandError, - self.cmd.take_action, - parsed_args) + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestMessageShow(TestMessage): - def setUp(self): - super(TestMessageShow, self).setUp() + super().setUp() - self.message = ( - manila_fakes.FakeMessage.create_one_message()) + self.message = manila_fakes.FakeMessage.create_one_message() self.messages_mock.get.return_value = self.message self.cmd = osc_messages.ShowMessage(self.app, None) @@ -129,16 +114,17 @@ def test_message_show_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_message_show(self): - arglist = [ - self.message.id - ] - verifylist = [ - ('message', self.message.id) - ] + arglist = [self.message.id] + verifylist = [('message', self.message.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) @@ -148,18 +134,17 @@ def test_message_show(self): class TestMessageList(TestMessage): - def setUp(self): - super(TestMessageList, self).setUp() + super().setUp() - self.messages = ( - manila_fakes.FakeMessage.create_messages( - count=2)) + self.messages = manila_fakes.FakeMessage.create_messages(count=2) self.messages_mock.list.return_value = self.messages - self.values = (oscutils.get_dict_properties( - m._info, COLUMNS) for m in self.messages) + self.values = ( + oscutils.get_dict_properties(m._info, COLUMNS) + for m in self.messages + ) self.cmd = osc_messages.ListMessage(self.app, None) @@ -181,28 +166,31 @@ def test_list_messages(self): 'detail_id': None, 'message_level': None, 'created_since': None, - 'created_before': None - }) + 'created_before': None, + } + ) self.assertEqual(COLUMNS, columns) self.assertEqual(list(self.values), list(data)) def test_list_messages_api_version_exception(self): self.app.client_manager.share.api_version = api_versions.APIVersion( - "2.50") + "2.50" + ) arglist = [ - '--before', '2021-02-06T09:49:58-05:00', - '--since', '2021-02-05T09:49:58-05:00' + '--before', + '2021-02-06T09:49:58-05:00', + '--since', + '2021-02-05T09:49:58-05:00', ] verifylist = [ ('before', '2021-02-06T09:49:58-05:00'), - ('since', '2021-02-05T09:49:58-05:00') + ('since', '2021-02-05T09:49:58-05:00'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) diff --git a/manilaclient/tests/unit/osc/v2/test_qos_types.py b/manilaclient/tests/unit/osc/v2/test_qos_types.py new file mode 100644 index 00000000..d23b6cc5 --- /dev/null +++ b/manilaclient/tests/unit/osc/v2/test_qos_types.py @@ -0,0 +1,440 @@ +# Copyright (c) 2025 Cloudification GmbH. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +from unittest import mock + +from osc_lib import exceptions +from osc_lib import utils as oscutils + +from manilaclient import api_versions +from manilaclient.common.apiclient.exceptions import BadRequest +from manilaclient.common.apiclient.exceptions import NotFound +from manilaclient.osc import utils +from manilaclient.osc.v2 import qos_types as osc_qos_types +from manilaclient.tests.unit.osc import osc_utils +from manilaclient.tests.unit.osc.v2 import fakes as manila_fakes + +COLUMNS = [ + 'id', + 'name', + 'description', + 'specs', + 'created_at', + 'updated_at', +] + + +class TestQosType(manila_fakes.TestShare): + def setUp(self): + super().setUp() + + self.qos_types_mock = self.app.client_manager.share.qos_types + self.qos_types_mock.reset_mock() + self.app.client_manager.share.api_version = api_versions.APIVersion( + api_versions.MAX_VERSION + ) + + +class TestQosTypeCreate(TestQosType): + def setUp(self): + super().setUp() + + self.new_qos_type = manila_fakes.FakeQosType.create_one_qostype() + self.qos_types_mock.create.return_value = self.new_qos_type + + # Get the command object to test + self.cmd = osc_qos_types.CreateQosType(self.app, None) + + self.data = [ + self.new_qos_type.id, + self.new_qos_type.name, + self.new_qos_type.description, + ('expected_iops : 2000\npeak_iops : 5000'), + self.new_qos_type.created_at, + self.new_qos_type.updated_at, + ] + + self.raw_data = [ + self.new_qos_type.id, + self.new_qos_type.name, + self.new_qos_type.description, + { + 'expected_iops': '2000', + 'peak_iops': '5000', + }, + self.new_qos_type.created_at, + self.new_qos_type.updated_at, + ] + + def test_qos_type_create_required_args(self): + """Verifies required arguments.""" + + arglist = [self.new_qos_type.name] + verifylist = [ + ('name', self.new_qos_type.name), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + + self.qos_types_mock.create.assert_called_with( + name=self.new_qos_type.name, + ) + + self.assertCountEqual(COLUMNS, columns) + self.assertCountEqual(self.data, data) + + def test_qos_type_create_json_format(self): + """Verifies --format json.""" + + arglist = [self.new_qos_type.name, '-f', 'json'] + verifylist = [ + ('name', self.new_qos_type.name), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + + self.qos_types_mock.create.assert_called_with( + name=self.new_qos_type.name, + ) + + self.assertCountEqual(COLUMNS, columns) + self.assertCountEqual(self.raw_data, data) + + def test_qos_type_create_missing_required_arg(self): + """Verifies missing required arguments.""" + + arglist = [] + verifylist = [] + + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) + + def test_qos_type_create_specs(self): + arglist = [ + self.new_qos_type.name, + '--spec', + 'peak_iops=100', + '--spec', + 'expected_iops=20', + ] + verifylist = [ + ('name', self.new_qos_type.name), + ('spec', ['peak_iops=100', 'expected_iops=20']), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + + self.qos_types_mock.create.assert_called_with( + name=self.new_qos_type.name, + specs={'peak_iops': '100', 'expected_iops': '20'}, + ) + + self.assertCountEqual(COLUMNS, columns) + self.assertCountEqual(self.data, data) + + +class TestQosTypeDelete(TestQosType): + qos_types = manila_fakes.FakeQosType.create_qos_types(count=2) + + def setUp(self): + super().setUp() + + self.qos_types_mock.get = manila_fakes.FakeQosType.get_qos_types( + self.qos_types + ) + self.qos_types_mock.delete.return_value = None + + # Get the command object to test + self.cmd = osc_qos_types.DeleteQosType(self.app, None) + + def test_qos_type_delete_one(self): + arglist = [self.qos_types[0].id] + + verifylist = [('qos_types', [self.qos_types[0].id])] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + result = self.cmd.take_action(parsed_args) + self.qos_types_mock.delete.assert_called_with(self.qos_types[0]) + self.assertIsNone(result) + + def test_qos_type_delete_multiple(self): + arglist = [] + for t in self.qos_types: + arglist.append(t.id) + verifylist = [ + ('qos_types', arglist), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + result = self.cmd.take_action(parsed_args) + + calls = [] + for t in self.qos_types: + calls.append(mock.call(t)) + self.qos_types_mock.delete.assert_has_calls(calls) + self.assertIsNone(result) + + def test_delete_qos_type_with_exception(self): + arglist = [ + 'non_existing_type', + ] + verifylist = [ + ('qos_types', arglist), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.qos_types_mock.delete.side_effect = exceptions.CommandError() + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) + + +class TestQosTypeSet(TestQosType): + def setUp(self): + super().setUp() + + self.qos_type = manila_fakes.FakeQosType.create_one_qostype( + methods={'set_keys': None, 'update': None} + ) + self.qos_types_mock.get.return_value = self.qos_type + + # Get the command object to test + self.cmd = osc_qos_types.SetQosType(self.app, None) + + def test_qos_type_set_specs(self): + arglist = [ + self.qos_type.id, + '--spec', + 'peak_iops=100', + ] + verifylist = [ + ('qos_type', self.qos_type.id), + ('spec', ['peak_iops=100']), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + result = self.cmd.take_action(parsed_args) + self.qos_type.set_keys.assert_called_with({'peak_iops': '100'}) + self.assertIsNone(result) + + def test_qos_type_set_description(self): + arglist = [self.qos_type.id, '--description', 'new description'] + verifylist = [ + ('qos_type', self.qos_type.id), + ('description', 'new description'), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + result = self.cmd.take_action(parsed_args) + self.qos_type.update.assert_called_with(description='new description') + self.assertIsNone(result) + + def test_qos_type_set_specs_exception(self): + arglist = [ + self.qos_type.id, + '--spec', + 'peak_iops=100', + ] + verifylist = [ + ('qos_type', self.qos_type.id), + ('spec', ['peak_iops=100']), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.qos_type.set_keys.side_effect = BadRequest() + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) + + +class TestQosTypeUnset(TestQosType): + def setUp(self): + super().setUp() + + self.qos_type = manila_fakes.FakeQosType.create_one_qostype( + methods={'unset_keys': None, 'update': None} + ) + + self.qos_types_mock.get.return_value = self.qos_type + + # Get the command object to test + self.cmd = osc_qos_types.UnsetQosType(self.app, None) + + def test_qos_type_unset_description(self): + arglist = [self.qos_type.id, '--description'] + verifylist = [ + ('qos_type', self.qos_type.id), + ('description', True), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + result = self.cmd.take_action(parsed_args) + self.qos_type.update.assert_called_with(description=None) + self.assertIsNone(result) + + def test_qos_type_unset_specs(self): + arglist = [self.qos_type.id, '--spec', 'peak_iops'] + verifylist = [ + ('qos_type', self.qos_type.id), + ('spec', ['peak_iops']), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + result = self.cmd.take_action(parsed_args) + self.qos_type.unset_keys.assert_called_with(['peak_iops']) + self.assertIsNone(result) + + def test_qos_type_unset_exception(self): + arglist = [self.qos_type.id, '--spec', 'peak_iops'] + verifylist = [ + ('qos_type', self.qos_type.id), + ('spec', ['peak_iops']), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.qos_type.unset_keys.side_effect = NotFound() + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) + + +class TestQosTypeList(TestQosType): + qos_types = manila_fakes.FakeQosType.create_qos_types() + columns = utils.format_column_headers(COLUMNS) + + def setUp(self): + super().setUp() + + self.qos_types_mock.list.return_value = self.qos_types + + # Get the command object to test + self.cmd = osc_qos_types.ListQosType(self.app, None) + + self.values = ( + oscutils.get_dict_properties(s._info, COLUMNS) + for s in self.qos_types + ) + + def test_qos_type_list(self): + arglist = [] + verifylist = [] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + self.qos_types_mock.list.assert_called_once_with( + search_opts={ + 'offset': None, + 'limit': None, + 'name': None, + 'description': None, + 'name~': None, + 'description~': None, + }, + sort_key=None, + sort_dir=None, + ) + self.assertEqual(self.columns, columns) + self.assertEqual(list(self.values), list(data)) + + def test_qos_type_list_by_name(self): + arglist = ['--name', 'fake_name'] + verifylist = [('name', 'fake_name')] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + columns, data = self.cmd.take_action(parsed_args) + self.qos_types_mock.list.assert_called_with( + search_opts={ + 'offset': None, + 'limit': None, + 'name': 'fake_name', + 'description': None, + 'name~': None, + 'description~': None, + }, + sort_key=None, + sort_dir=None, + ) + self.assertEqual(self.columns, columns) + self.assertEqual(list(self.values), list(data)) + + +class TestQosTypeShow(TestQosType): + def setUp(self): + super().setUp() + + self.qos_type = manila_fakes.FakeQosType.create_one_qostype() + + self.qos_types_mock.get.return_value = self.qos_type + + # Get the command object to test + self.cmd = osc_qos_types.ShowQosType(self.app, None) + + self.data = [ + self.qos_type.id, + self.qos_type.name, + self.qos_type.description, + ('expected_iops : 2000\npeak_iops : 5000'), + self.qos_type.created_at, + self.qos_type.updated_at, + ] + + self.raw_data = [ + self.qos_type.id, + self.qos_type.name, + self.qos_type.description, + { + 'expected_iops': '2000', + 'peak_iops': '5000', + }, + self.qos_type.created_at, + self.qos_type.updated_at, + ] + + def test_qos_type_show(self): + arglist = [self.qos_type.id] + verifylist = [("qos_type", self.qos_type.id)] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + self.qos_types_mock.get.assert_called_with(self.qos_type.id) + + self.assertCountEqual(COLUMNS, columns) + self.assertCountEqual(self.data, data) + + def test_qos_type_show_json_format(self): + arglist = [ + self.qos_type.id, + '-f', + 'json', + ] + verifylist = [("qos_type", self.qos_type.id)] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + self.qos_types_mock.get.assert_called_with(self.qos_type.id) + + self.assertCountEqual(COLUMNS, columns) + self.assertCountEqual(self.raw_data, data) diff --git a/manilaclient/tests/unit/osc/v2/test_quotas.py b/manilaclient/tests/unit/osc/v2/test_quotas.py index 3de79469..17aa9f97 100644 --- a/manilaclient/tests/unit/osc/v2/test_quotas.py +++ b/manilaclient/tests/unit/osc/v2/test_quotas.py @@ -23,9 +23,8 @@ class TestQuotas(manila_fakes.TestShare): - def setUp(self): - super(TestQuotas, self).setUp() + super().setUp() self.quotas_mock = self.app.client_manager.share.quotas self.quotas_mock.reset_mock() @@ -43,7 +42,7 @@ class TestQuotaSet(TestQuotas): user = identity_fakes.FakeUser.create_one_user() def setUp(self): - super(TestQuotaSet, self).setUp() + super().setUp() self.quotas = manila_fakes.FakeQuotaSet.create_fake_quotas() self.quotas_mock.update = mock.Mock() @@ -55,15 +54,11 @@ def setUp(self): self.cmd = osc_quotas.QuotaSet(self.app, None) def test_quota_set_default_class_shares(self): - arglist = [ - 'default', - '--class', - '--shares', '40' - ] + arglist = ['default', '--class', '--shares', '40'] verifylist = [ ('project', 'default'), ('quota_class', True), - ('shares', 40) + ('shares', 40), ] with mock.patch('osc_lib.utils.find_resource') as mock_find_resource: @@ -78,20 +73,15 @@ def test_quota_set_default_class_shares(self): share_networks=None, shares=40, snapshot_gigabytes=None, - snapshots=None) + snapshots=None, + ) self.assertIsNone(result) mock_find_resource.assert_not_called() self.quotas_mock.assert_not_called() def test_quota_set_shares(self): - arglist = [ - self.project.id, - '--shares', '40' - ] - verifylist = [ - ('project', self.project.id), - ('shares', 40) - ] + arglist = [self.project.id, '--shares', '40'] + verifylist = [('project', self.project.id), ('shares', 40)] with mock.patch('osc_lib.utils.find_resource') as mock_find_resource: mock_find_resource.return_value = self.project @@ -107,18 +97,13 @@ def test_quota_set_shares(self): snapshot_gigabytes=None, snapshots=None, tenant_id=self.project.id, - user_id=None) + user_id=None, + ) self.assertIsNone(result) def test_quota_set_gigabytes(self): - arglist = [ - self.project.id, - '--gigabytes', '1100' - ] - verifylist = [ - ('project', self.project.id), - ('gigabytes', 1100) - ] + arglist = [self.project.id, '--gigabytes', '1100'] + verifylist = [('project', self.project.id), ('gigabytes', 1100)] with mock.patch('osc_lib.utils.find_resource') as mock_find_resource: mock_find_resource.return_value = self.project @@ -134,18 +119,13 @@ def test_quota_set_gigabytes(self): snapshot_gigabytes=None, snapshots=None, tenant_id=self.project.id, - user_id=None) + user_id=None, + ) self.assertIsNone(result) def test_quota_set_share_type(self): - arglist = [ - self.project.id, - '--share-type', 'default' - ] - verifylist = [ - ('project', self.project.id), - ('share_type', 'default') - ] + arglist = [self.project.id, '--share-type', 'default'] + verifylist = [('project', self.project.id), ('share_type', 'default')] with mock.patch('osc_lib.utils.find_resource') as mock_find_resource: mock_find_resource.return_value = self.project @@ -162,19 +142,16 @@ def test_quota_set_share_type(self): snapshot_gigabytes=None, snapshots=None, tenant_id=self.project.id, - user_id=None) + user_id=None, + ) self.assertIsNone(result) def test_quota_set_force(self): - arglist = [ - self.project.id, - '--force', - '--shares', '40' - ] + arglist = [self.project.id, '--force', '--shares', '40'] verifylist = [ ('project', self.project.id), ('force', True), - ('shares', 40) + ('shares', 40), ] with mock.patch('osc_lib.utils.find_resource') as mock_find_resource: @@ -191,7 +168,8 @@ def test_quota_set_force(self): snapshot_gigabytes=None, snapshots=None, tenant_id=self.project.id, - user_id=None) + user_id=None, + ) self.assertIsNone(result) def test_quota_set_api_version_exception(self): @@ -199,63 +177,54 @@ def test_quota_set_api_version_exception(self): '2.39' ) - arglist = [ - self.project.id, - '--share-groups', '40' - ] - verifylist = [ - ('project', self.project.id), - ('share_groups', 40) - ] + arglist = [self.project.id, '--share-groups', '40'] + verifylist = [('project', self.project.id), ('share_groups', 40)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_quota_set_update_project_exception(self): arglist = [ self.project.id, - '--share-groups', '40', - '--share-group-snapshots', '40' + '--share-groups', + '40', + '--share-group-snapshots', + '40', ] verifylist = [ ('project', self.project.id), ('share_groups', 40), - ('share_group_snapshots', 40) + ('share_group_snapshots', 40), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.quotas_mock.update.side_effect = BadRequest() self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_quota_set_update_class_exception(self): - arglist = [ - 'default', - '--class', - '--gigabytes', '40' - ] - verifylist = [ - ('project', 'default'), - ('gigabytes', 40) - ] + arglist = ['default', '--class', '--gigabytes', '40'] + verifylist = [('project', 'default'), ('gigabytes', 40)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.quota_classes_mock.update.side_effect = BadRequest() self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_quota_set_nothing_to_set_exception(self): arglist = [ self.project.id, ] - verifylist = [ - ('project', self.project.id) - ] + verifylist = [('project', self.project.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_quota_set_share_replicas(self): self.app.client_manager.share.api_version = api_versions.APIVersion( @@ -264,12 +233,10 @@ def test_quota_set_share_replicas(self): arglist = [ self.project.id, - '--share-replicas', '2', - ] - verifylist = [ - ('project', self.project.id), - ('share_replicas', 2) + '--share-replicas', + '2', ] + verifylist = [('project', self.project.id), ('share_replicas', 2)] with mock.patch('osc_lib.utils.find_resource') as mock_find_resource: mock_find_resource.return_value = self.project @@ -286,49 +253,54 @@ def test_quota_set_share_replicas(self): snapshot_gigabytes=None, snapshots=None, tenant_id=self.project.id, - user_id=None) + user_id=None, + ) self.assertIsNone(result) def test_quota_set_replica_gigabytes_exception(self): self.app.client_manager.share.api_version = api_versions.APIVersion( - '2.51') + '2.51' + ) arglist = [ self.project.id, - '--replica-gigabytes', '10', - ] - verifylist = [ - ('project', self.project.id), - ('replica_gigabytes', 10) + '--replica-gigabytes', + '10', ] + verifylist = [('project', self.project.id), ('replica_gigabytes', 10)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_quota_set_per_share_gigabytes_exception(self): self.app.client_manager.share.api_version = api_versions.APIVersion( - '2.61') + '2.61' + ) arglist = [ self.project.id, - '--per-share-gigabytes', '10', + '--per-share-gigabytes', + '10', ] verifylist = [ ('project', self.project.id), - ('per_share_gigabytes', 10) + ('per_share_gigabytes', 10), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_quota_set_per_share_gigabytes(self): arglist = [ self.project.id, - '--per-share-gigabytes', '10', + '--per-share-gigabytes', + '10', ] verifylist = [ ('project', self.project.id), - ('per_share_gigabytes', 10) + ('per_share_gigabytes', 10), ] with mock.patch('osc_lib.utils.find_resource') as mock_find_resource: @@ -346,7 +318,51 @@ def test_quota_set_per_share_gigabytes(self): snapshots=None, per_share_gigabytes=10, tenant_id=self.project.id, - user_id=None) + user_id=None, + ) + self.assertIsNone(result) + + def test_quota_set_encryption_keys_exception(self): + self.app.client_manager.share.api_version = api_versions.APIVersion( + '2.89' + ) + arglist = [ + self.project.id, + '--encryption-keys', + '10', + ] + verifylist = [('project', self.project.id), ('encryption_keys', 10)] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) + + def test_quota_set_encryption_keys(self): + arglist = [ + self.project.id, + '--encryption-keys', + '10', + ] + verifylist = [('project', self.project.id), ('encryption_keys', 10)] + + with mock.patch('osc_lib.utils.find_resource') as mock_find_resource: + mock_find_resource.return_value = self.project + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + result = self.cmd.take_action(parsed_args) + self.quotas_mock.update.assert_called_with( + force=None, + gigabytes=None, + share_networks=None, + shares=None, + snapshot_gigabytes=None, + snapshots=None, + encryption_keys=10, + tenant_id=self.project.id, + user_id=None, + ) self.assertIsNone(result) @@ -355,19 +371,15 @@ class TestQuotaShow(TestQuotas): user = identity_fakes.FakeUser.create_one_user() def setUp(self): - super(TestQuotaShow, self).setUp() + super().setUp() self.quotas = manila_fakes.FakeQuotaSet.create_fake_quotas() self.quotas_mock.get.return_value = self.quotas self.cmd = osc_quotas.QuotaShow(self.app, None) def test_quota_show(self): - arglist = [ - self.project.id - ] - verifylist = [ - ('project', self.project.id) - ] + arglist = [self.project.id] + verifylist = [('project', self.project.id)] with mock.patch('osc_lib.utils.find_resource') as mock_find_resource: mock_find_resource.return_value = self.project @@ -376,9 +388,7 @@ def test_quota_show(self): columns, data = self.cmd.take_action(parsed_args) self.quotas_mock.get.assert_called_with( - detail=False, - tenant_id=self.project.id, - user_id=None + detail=False, tenant_id=self.project.id, user_id=None ) self.assertCountEqual(columns, self.quotas.keys()) @@ -389,28 +399,17 @@ def test_quota_show_api_version_exception(self): '2.38' ) - arglist = [ - self.project.id, - '--share-type', 'default' - ] - verifylist = [ - ('project', self.project.id), - ('share_type', 'default') - ] + arglist = [self.project.id, '--share-type', 'default'] + verifylist = [('project', self.project.id), ('share_type', 'default')] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_quota_show_defaults(self): - arglist = [ - self.project.id, - '--defaults' - ] - verifylist = [ - ('project', self.project.id), - ('defaults', True) - ] + arglist = [self.project.id, '--defaults'] + verifylist = [('project', self.project.id), ('defaults', True)] self.quotas_mock.defaults = mock.Mock() self.quotas_mock.defaults.return_value = self.quotas @@ -432,19 +431,15 @@ class TestQuotaDelete(TestQuotas): user = identity_fakes.FakeUser.create_one_user() def setUp(self): - super(TestQuotaDelete, self).setUp() + super().setUp() self.quotas = manila_fakes.FakeQuotaSet.create_fake_quotas() self.quotas_mock.delete.return_value = None self.cmd = osc_quotas.QuotaDelete(self.app, None) def test_quota_delete(self): - arglist = [ - self.project.id - ] - verifylist = [ - ('project', self.project.id) - ] + arglist = [self.project.id] + verifylist = [('project', self.project.id)] with mock.patch('osc_lib.utils.find_resource') as mock_find_resource: mock_find_resource.return_value = self.project @@ -453,19 +448,13 @@ def test_quota_delete(self): result = self.cmd.take_action(parsed_args) self.quotas_mock.delete.assert_called_with( - tenant_id=self.project.id, - user_id=None) + tenant_id=self.project.id, user_id=None + ) self.assertIsNone(result) def test_quota_delete_share_type(self): - arglist = [ - self.project.id, - '--share-type', 'default' - ] - verifylist = [ - ('project', self.project.id), - ('share_type', 'default') - ] + arglist = [self.project.id, '--share-type', 'default'] + verifylist = [('project', self.project.id), ('share_type', 'default')] with mock.patch('osc_lib.utils.find_resource') as mock_find_resource: mock_find_resource.return_value = self.project @@ -474,9 +463,8 @@ def test_quota_delete_share_type(self): result = self.cmd.take_action(parsed_args) self.quotas_mock.delete.assert_called_with( - share_type='default', - tenant_id=self.project.id, - user_id=None) + share_type='default', tenant_id=self.project.id, user_id=None + ) self.assertIsNone(result) def test_quota_delete_api_version_exception(self): @@ -484,15 +472,10 @@ def test_quota_delete_api_version_exception(self): '2.38' ) - arglist = [ - self.project.id, - '--share-type', 'default' - ] - verifylist = [ - ('project', self.project.id), - ('share_type', 'default') - ] + arglist = [self.project.id, '--share-type', 'default'] + verifylist = [('project', self.project.id), ('share_type', 'default')] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) diff --git a/manilaclient/tests/unit/osc/v2/test_resource_locks.py b/manilaclient/tests/unit/osc/v2/test_resource_locks.py index 6c5ca06f..c1a2ee3b 100644 --- a/manilaclient/tests/unit/osc/v2/test_resource_locks.py +++ b/manilaclient/tests/unit/osc/v2/test_resource_locks.py @@ -42,9 +42,8 @@ class TestResourceLock(manila_fakes.TestShare): - def setUp(self): - super(TestResourceLock, self).setUp() + super().setUp() self.shares_mock = self.app.client_manager.share.shares self.shares_mock.reset_mock() @@ -53,13 +52,13 @@ def setUp(self): self.locks_mock.reset_mock() self.app.client_manager.share.api_version = api_versions.APIVersion( - api_versions.MAX_VERSION) + api_versions.MAX_VERSION + ) class TestResourceLockCreate(TestResourceLock): - def setUp(self): - super(TestResourceLockCreate, self).setUp() + super().setUp() self.share = manila_fakes.FakeShare.create_one_share() self.shares_mock.create.return_value = self.share @@ -67,7 +66,8 @@ def setUp(self): self.shares_mock.get.return_value = self.share self.lock = manila_fakes.FakeResourceLock.create_one_lock( - attrs={'resource_id': self.share.id}) + attrs={'resource_id': self.share.id} + ) self.locks_mock.get.return_value = self.lock self.locks_mock.create.return_value = self.lock @@ -80,13 +80,20 @@ def test_share_lock_create_missing_required_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_lock_create(self): arglist = [ - '--resource-action', 'revert_to_snapshot', - '--lock-reason', "you cannot go back in time", + '--resource-action', + 'revert_to_snapshot', + '--lock-reason', + "you cannot go back in time", self.share.id, 'share', ] @@ -94,7 +101,7 @@ def test_share_lock_create(self): ('resource', self.share.id), ('resource_type', 'share'), ('resource_action', 'revert_to_snapshot'), - ('lock_reason', 'you cannot go back in time') + ('lock_reason', 'you cannot go back in time'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -113,9 +120,8 @@ def test_share_lock_create(self): class TestResourceLockDelete(TestResourceLock): - def setUp(self): - super(TestResourceLockDelete, self).setUp() + super().setUp() self.lock = manila_fakes.FakeResourceLock.create_one_lock() @@ -128,16 +134,17 @@ def test_share_lock_delete_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_lock_delete(self): - arglist = [ - self.lock.id - ] - verifylist = [ - ('lock', [self.lock.id]) - ] + arglist = [self.lock.id] + verifylist = [('lock', [self.lock.id])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -148,41 +155,30 @@ def test_share_lock_delete(self): def test_share_lock_delete_multiple(self): locks = manila_fakes.FakeResourceLock.create_locks(count=2) - arglist = [ - locks[0].id, - locks[1].id - ] - verifylist = [ - ('lock', [locks[0].id, locks[1].id]) - ] + arglist = [locks[0].id, locks[1].id] + verifylist = [('lock', [locks[0].id, locks[1].id])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.assertEqual(self.lock.delete.call_count, - len(locks)) + self.assertEqual(self.lock.delete.call_count, len(locks)) self.assertIsNone(result) def test_share_lock_delete_exception(self): - arglist = [ - self.lock.id - ] - verifylist = [ - ('lock', [self.lock.id]) - ] + arglist = [self.lock.id] + verifylist = [('lock', [self.lock.id])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.lock.delete.side_effect = exceptions.CommandError() - self.assertRaises(exceptions.CommandError, - self.cmd.take_action, - parsed_args) + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestResourceLockShow(TestResourceLock): - def setUp(self): - super(TestResourceLockShow, self).setUp() + super().setUp() self.lock = manila_fakes.FakeResourceLock.create_one_lock() self.locks_mock.get.return_value = self.lock @@ -196,16 +192,19 @@ def test_share_lock_show_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_lock_show(self): arglist = [ self.lock.id, ] - verifylist = [ - ('lock', self.lock.id) - ] + verifylist = [('lock', self.lock.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) @@ -216,26 +215,23 @@ def test_share_lock_show(self): class TestResourceLockList(TestResourceLock): - def setUp(self): - super(TestResourceLockList, self).setUp() + super().setUp() self.locks = manila_fakes.FakeResourceLock.create_locks(count=2) self.locks_mock.list.return_value = self.locks - self.values = (oscutils.get_dict_properties( - m._info, DETAIL_COLUMNS) for m in self.locks) + self.values = ( + oscutils.get_dict_properties(m._info, DETAIL_COLUMNS) + for m in self.locks + ) self.cmd = osc_resource_locks.ListResourceLock(self.app, None) def test_share_lock_list(self): - arglist = [ - '--detailed' - ] - verifylist = [ - ('detailed', True) - ] + arglist = ['--detailed'] + verifylist = [('detailed', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -257,7 +253,7 @@ def test_share_lock_list(self): 'offset': None, }, sort_key=None, - sort_dir=None + sort_dir=None, ) self.assertEqual(sorted(DETAIL_COLUMNS), sorted(columns)) @@ -267,9 +263,8 @@ def test_share_lock_list(self): class TestResourceLockSet(TestResourceLock): - def setUp(self): - super(TestResourceLockSet, self).setUp() + super().setUp() self.lock = manila_fakes.FakeResourceLock.create_one_lock() self.lock.update = mock.Mock() @@ -282,32 +277,35 @@ def test_share_lock_set_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_lock_set(self): arglist = [ self.lock.id, - '--resource-action', 'unmanage', - ] - verifylist = [ - ('lock', self.lock.id), - ('resource_action', 'unmanage') + '--resource-action', + 'unmanage', ] + verifylist = [('lock', self.lock.id), ('resource_action', 'unmanage')] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.assertIsNone(result) - self.locks_mock.update.assert_called_with(self.lock.id, - resource_action='unmanage') + self.locks_mock.update.assert_called_with( + self.lock.id, resource_action='unmanage' + ) class TestResourceLockUnSet(TestResourceLock): - def setUp(self): - super(TestResourceLockUnSet, self).setUp() + super().setUp() self.lock = manila_fakes.FakeResourceLock.create_one_lock() self.lock.update = mock.Mock() @@ -320,23 +318,23 @@ def test_share_lock_unset_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_lock_unset(self): - arglist = [ - self.lock.id, - '--lock-reason' - ] - verifylist = [ - ('lock', self.lock.id), - ('lock_reason', True) - ] + arglist = [self.lock.id, '--lock-reason'] + verifylist = [('lock', self.lock.id), ('lock_reason', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.assertIsNone(result) - self.locks_mock.update.assert_called_with(self.lock.id, - lock_reason=None) + self.locks_mock.update.assert_called_with( + self.lock.id, lock_reason=None + ) diff --git a/manilaclient/tests/unit/osc/v2/test_security_services.py b/manilaclient/tests/unit/osc/v2/test_security_services.py index 7b6a0e11..cdd707c2 100644 --- a/manilaclient/tests/unit/osc/v2/test_security_services.py +++ b/manilaclient/tests/unit/osc/v2/test_security_services.py @@ -21,12 +21,12 @@ class TestShareSecurityService(manila_fakes.TestShare): - def setUp(self): - super(TestShareSecurityService, self).setUp() + super().setUp() self.security_services_mock = ( - self.app.client_manager.share.security_services) + self.app.client_manager.share.security_services + ) self.security_services_mock.reset_mock() self.share_networks_mock = self.app.client_manager.share.share_networks @@ -39,15 +39,14 @@ def setUp(self): @ddt.ddt class TestShareSecurityServiceCreate(TestShareSecurityService): - def setUp(self): - super(TestShareSecurityServiceCreate, self).setUp() + super().setUp() - self.security_service = manila_fakes.FakeShareSecurityService \ - .create_fake_security_service() + self.security_service = manila_fakes.FakeShareSecurityService.create_fake_security_service() # noqa: E501 self.security_services_mock.create.return_value = self.security_service self.cmd = osc_security_services.CreateShareSecurityService( - self.app, None) + self.app, None + ) self.data = self.security_service._info.values() self.columns = self.security_service._info.keys() @@ -56,21 +55,35 @@ def test_share_security_service_create_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_security_service_create(self): arglist = [ self.security_service.type, - '--dns-ip', self.security_service.dns_ip, - '--ou', self.security_service.ou, - '--server', self.security_service.server, - '--domain', self.security_service.domain, - '--user', self.security_service.user, - '--password', self.security_service.password, - '--name', self.security_service.name, - '--description', self.security_service.description, - '--default-ad-site', self.security_service.default_ad_site + '--dns-ip', + self.security_service.dns_ip, + '--ou', + self.security_service.ou, + '--server', + self.security_service.server, + '--domain', + self.security_service.domain, + '--user', + self.security_service.user, + '--password', + self.security_service.password, + '--name', + self.security_service.name, + '--description', + self.security_service.description, + '--default-ad-site', + self.security_service.default_ad_site, ] verifylist = [ ('type', self.security_service.type), @@ -82,7 +95,7 @@ def test_share_security_service_create(self): ('password', self.security_service.password), ('name', self.security_service.name), ('description', self.security_service.description), - ('default_ad_site', self.security_service.default_ad_site) + ('default_ad_site', self.security_service.default_ad_site), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -98,15 +111,16 @@ def test_share_security_service_create(self): name=self.security_service.name, description=self.security_service.description, ou=self.security_service.ou, - default_ad_site=self.security_service.default_ad_site + default_ad_site=self.security_service.default_ad_site, ) self.assertCountEqual(self.columns, columns) self.assertCountEqual(self.data, data) @ddt.data('2.43', '2.75') - def test_share_security_service_create_api_version_exception(self, - version): + def test_share_security_service_create_api_version_exception( + self, version + ): self.app.client_manager.share.api_version = api_versions.APIVersion( version ) @@ -123,37 +137,43 @@ def test_share_security_service_create_api_version_exception(self, verifylist.append(('ou', self.security_service.ou)) if api_versions.APIVersion(version) <= api_versions.APIVersion("2.75"): - arglist.extend(['--default-ad-site', - self.security_service.default_ad_site]) - verifylist.append(('default_ad_site', - self.security_service.default_ad_site)) + arglist.extend( + ['--default-ad-site', self.security_service.default_ad_site] + ) + verifylist.append( + ('default_ad_site', self.security_service.default_ad_site) + ) parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestShareSecurityServiceDelete(TestShareSecurityService): - def setUp(self): - super(TestShareSecurityServiceDelete, self).setUp() + super().setUp() - self.security_service = manila_fakes.FakeShareSecurityService \ - .create_fake_security_service() + self.security_service = manila_fakes.FakeShareSecurityService.create_fake_security_service() # noqa: E501 self.security_services_mock.get.return_value = self.security_service - self.security_services = manila_fakes.FakeShareSecurityService \ - .create_fake_security_services() + self.security_services = manila_fakes.FakeShareSecurityService.create_fake_security_services() # noqa: E501 self.cmd = osc_security_services.DeleteShareSecurityService( - self.app, None) + self.app, None + ) def test_share_security_service_delete_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_security_service_delete(self): arglist = [ @@ -161,15 +181,19 @@ def test_share_security_service_delete(self): self.security_services[1].id, ] verifylist = [ - ('security_service', [self.security_services[0].id, - self.security_services[1].id]), + ( + 'security_service', + [self.security_services[0].id, self.security_services[1].id], + ), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.assertEqual(self.security_services_mock.delete.call_count, - len(self.security_services)) + self.assertEqual( + self.security_services_mock.delete.call_count, + len(self.security_services), + ) self.assertIsNone(result) def test_share_security_service_delete_exception(self): @@ -182,24 +206,24 @@ def test_share_security_service_delete_exception(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) - self.security_services_mock.delete.side_effect = \ + self.security_services_mock.delete.side_effect = ( exceptions.CommandError() - self.assertRaises(exceptions.CommandError, - self.cmd.take_action, - parsed_args) + ) + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestShareSecurityServiceShow(TestShareSecurityService): - def setUp(self): - super(TestShareSecurityServiceShow, self).setUp() + super().setUp() - self.security_service = manila_fakes.FakeShareSecurityService \ - .create_fake_security_service() + self.security_service = manila_fakes.FakeShareSecurityService.create_fake_security_service() # noqa: E501 self.security_services_mock.get.return_value = self.security_service self.cmd = osc_security_services.ShowShareSecurityService( - self.app, None) + self.app, None + ) self.data = self.security_service._info.values() self.columns = self.security_service._info.keys() @@ -208,16 +232,17 @@ def test_share_security_service_show_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_security_service_show(self): - arglist = [ - self.security_service.id - ] - verifylist = [ - ('security_service', self.security_service.id) - ] + arglist = [self.security_service.id] + verifylist = [('security_service', self.security_service.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) @@ -232,35 +257,52 @@ def test_share_security_service_show(self): @ddt.ddt class TestShareSecurityServiceSet(TestShareSecurityService): - def setUp(self): - super(TestShareSecurityServiceSet, self).setUp() + super().setUp() - self.security_service = manila_fakes.FakeShareSecurityService \ - .create_fake_security_service(methods={'update': None}) + self.security_service = ( + manila_fakes.FakeShareSecurityService.create_fake_security_service( + methods={'update': None} + ) + ) self.security_services_mock.get.return_value = self.security_service self.cmd = osc_security_services.SetShareSecurityService( - self.app, None) + self.app, None + ) def test_share_security_service_set_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_security_service_set(self): arglist = [ self.security_service.id, - '--dns-ip', self.security_service.dns_ip, - '--ou', self.security_service.ou, - '--server', self.security_service.server, - '--domain', self.security_service.domain, - '--user', self.security_service.user, - '--password', self.security_service.password, - '--name', self.security_service.name, - '--description', self.security_service.description, - '--default-ad-site', self.security_service.default_ad_site + '--dns-ip', + self.security_service.dns_ip, + '--ou', + self.security_service.ou, + '--server', + self.security_service.server, + '--domain', + self.security_service.domain, + '--user', + self.security_service.user, + '--password', + self.security_service.password, + '--name', + self.security_service.name, + '--description', + self.security_service.description, + '--default-ad-site', + self.security_service.default_ad_site, ] verifylist = [ ('security_service', self.security_service.id), @@ -272,7 +314,7 @@ def test_share_security_service_set(self): ('password', self.security_service.password), ('name', self.security_service.name), ('description', self.security_service.description), - ('default_ad_site', self.security_service.default_ad_site) + ('default_ad_site', self.security_service.default_ad_site), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -294,7 +336,8 @@ def test_share_security_service_set(self): def test_share_security_service_set_exception(self): arglist = [ self.security_service.id, - '--name', self.security_service.name, + '--name', + self.security_service.name, ] verifylist = [ ('security_service', self.security_service.id), @@ -303,10 +346,10 @@ def test_share_security_service_set_exception(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) - self.security_service.update.side_effect = \ - exceptions.CommandError() + self.security_service.update.side_effect = exceptions.CommandError() self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) @ddt.data('2.43', '2.75') def test_share_security_service_set_api_version_exception(self, version): @@ -326,34 +369,45 @@ def test_share_security_service_set_api_version_exception(self, version): verifylist.append(('ou', self.security_service.ou)) if api_versions.APIVersion(version) <= api_versions.APIVersion("2.75"): - arglist.extend(['--default-ad-site', - self.security_service.default_ad_site]) - verifylist.append(('default_ad_site', - self.security_service.default_ad_site)) + arglist.extend( + ['--default-ad-site', self.security_service.default_ad_site] + ) + verifylist.append( + ('default_ad_site', self.security_service.default_ad_site) + ) parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) @ddt.ddt class TestShareSecurityServiceUnset(TestShareSecurityService): - def setUp(self): - super(TestShareSecurityServiceUnset, self).setUp() + super().setUp() - self.security_service = manila_fakes.FakeShareSecurityService \ - .create_fake_security_service(methods={'update': None}) + self.security_service = ( + manila_fakes.FakeShareSecurityService.create_fake_security_service( + methods={'update': None} + ) + ) self.security_services_mock.get.return_value = self.security_service self.cmd = osc_security_services.UnsetShareSecurityService( - self.app, None) + self.app, None + ) def test_share_security_service_unset_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_security_service_unset(self): arglist = [ @@ -378,7 +432,7 @@ def test_share_security_service_unset(self): ('password', True), ('name', True), ('description', True), - ('default_ad_site', True) + ('default_ad_site', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -393,7 +447,7 @@ def test_share_security_service_unset(self): name='', description='', ou='', - default_ad_site='' + default_ad_site='', ) self.assertIsNone(result) @@ -409,14 +463,13 @@ def test_share_security_service_unset_exception(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) - self.security_service.update.side_effect = \ - exceptions.CommandError() + self.security_service.update.side_effect = exceptions.CommandError() self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) @ddt.data('2.43', '2.75') - def test_share_security_service_unset_api_version_exception(self, - version): + def test_share_security_service_unset_api_version_exception(self, version): self.app.client_manager.share.api_version = api_versions.APIVersion( version ) @@ -433,16 +486,16 @@ def test_share_security_service_unset_api_version_exception(self, verifylist.append(('ou', True)) if api_versions.APIVersion(version) <= api_versions.APIVersion("2.75"): - arglist.extend(['--default-ad-site']), + (arglist.extend(['--default-ad-site']),) verifylist.append(('default_ad_site', True)) parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestShareSecurityServiceList(TestShareSecurityService): - columns = [ 'ID', 'Name', @@ -451,19 +504,22 @@ class TestShareSecurityServiceList(TestShareSecurityService): ] def setUp(self): - super(TestShareSecurityServiceList, self).setUp() + super().setUp() self.share_network = ( - manila_fakes.FakeShareNetwork.create_one_share_network()) + manila_fakes.FakeShareNetwork.create_one_share_network() + ) self.share_networks_mock.get.return_value = self.share_network - self.services_list = manila_fakes.FakeShareSecurityService \ - .create_fake_security_services() + self.services_list = manila_fakes.FakeShareSecurityService.create_fake_security_services() # noqa: E501 self.security_services_mock.list.return_value = self.services_list - self.values = (oscutils.get_dict_properties( - i._info, self.columns) for i in self.services_list) + self.values = ( + oscutils.get_dict_properties(i._info, self.columns) + for i in self.services_list + ) self.cmd = osc_security_services.ListShareSecurityService( - self.app, None) + self.app, None + ) def test_share_security_service_list_no_args(self): arglist = [] @@ -485,23 +541,35 @@ def test_share_security_service_list_no_args(self): 'offset': None, 'limit': None, }, - detailed=False) + detailed=False, + ) self.assertEqual(self.columns, columns) self.assertEqual(list(self.values), list(data)) def test_share_security_service_list(self): arglist = [ - '--share-network', self.share_network.id, - '--status', self.services_list[0].status, - '--name', self.services_list[0].name, - '--type', self.services_list[0].type, - '--user', self.services_list[0].user, - '--dns-ip', self.services_list[0].dns_ip, - '--ou', self.services_list[0].ou, - '--server', self.services_list[0].server, - '--domain', self.services_list[0].domain, - '--default-ad-site', self.services_list[0].default_ad_site, - '--limit', '1', + '--share-network', + self.share_network.id, + '--status', + self.services_list[0].status, + '--name', + self.services_list[0].name, + '--type', + self.services_list[0].type, + '--user', + self.services_list[0].user, + '--dns-ip', + self.services_list[0].dns_ip, + '--ou', + self.services_list[0].ou, + '--server', + self.services_list[0].server, + '--domain', + self.services_list[0].domain, + '--default-ad-site', + self.services_list[0].default_ad_site, + '--limit', + '1', ] verifylist = [ ('share_network', self.share_network.id), @@ -536,7 +604,8 @@ def test_share_security_service_list(self): 'ou': self.services_list[0].ou, 'share_network_id': self.share_network.id, }, - detailed=False) + detailed=False, + ) self.assertEqual(self.columns, columns) self.assertEqual(list(self.values), list(data)) @@ -546,7 +615,8 @@ def test_share_security_service_list_ou_api_version_exception(self): '2.43' ) arglist = [ - '--ou', self.services_list[0].ou, + '--ou', + self.services_list[0].ou, ] verifylist = [ ('ou', self.services_list[0].ou), @@ -554,14 +624,16 @@ def test_share_security_service_list_ou_api_version_exception(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_share_security_service_list_ad_site_api_version_exception(self): self.app.client_manager.share.api_version = api_versions.APIVersion( '2.75' ) arglist = [ - '--default-ad-site', self.services_list[0].default_ad_site, + '--default-ad-site', + self.services_list[0].default_ad_site, ] verifylist = [ ('default_ad_site', self.services_list[0].default_ad_site), @@ -569,13 +641,11 @@ def test_share_security_service_list_ad_site_api_version_exception(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_share_security_service_list_detail_all_projects(self): - arglist = [ - '--all-projects', - '--detail' - ] + arglist = ['--all-projects', '--detail'] verifylist = [ ('all_projects', True), ('detail', True), @@ -584,8 +654,10 @@ def test_share_security_service_list_detail_all_projects(self): columns_detail.append('Project ID') columns_detail.append('Share Networks') - values_detail = (oscutils.get_dict_properties( - i._info, columns_detail) for i in self.services_list) + values_detail = ( + oscutils.get_dict_properties(i._info, columns_detail) + for i in self.services_list + ) parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -604,6 +676,7 @@ def test_share_security_service_list_detail_all_projects(self): 'offset': None, 'limit': None, }, - detailed=True) + detailed=True, + ) self.assertEqual(columns_detail, columns) self.assertEqual(list(values_detail), list(data)) diff --git a/manilaclient/tests/unit/osc/v2/test_services.py b/manilaclient/tests/unit/osc/v2/test_services.py index f1525b9b..a7956f82 100644 --- a/manilaclient/tests/unit/osc/v2/test_services.py +++ b/manilaclient/tests/unit/osc/v2/test_services.py @@ -21,18 +21,16 @@ class TestShareService(manila_fakes.TestShare): - def setUp(self): - super(TestShareService, self).setUp() + super().setUp() self.services_mock = self.app.client_manager.share.services self.services_mock.reset_mock() class TestShareServiceSet(TestShareService): - def setUp(self): - super(TestShareServiceSet, self).setUp() + super().setUp() self.share_service = ( manila_fakes.FakeShareService.create_fake_service() @@ -43,68 +41,69 @@ def test_share_service_set_enable(self): arglist = [ self.share_service.host, self.share_service.binary, - '--enable' + '--enable', ] verifylist = [ ('host', self.share_service.host), ('binary', self.share_service.binary), - ('enable', True) + ('enable', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.services_mock.enable.assert_called_with( - self.share_service.host, - self.share_service.binary) + self.share_service.host, self.share_service.binary + ) self.assertIsNone(result) def test_share_service_set_enable_exception(self): arglist = [ self.share_service.host, self.share_service.binary, - '--enable' + '--enable', ] verifylist = [ ('host', self.share_service.host), ('binary', self.share_service.binary), - ('enable', True) + ('enable', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.services_mock.enable.side_effect = Exception() self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_share_service_set_disable(self): arglist = [ self.share_service.host, self.share_service.binary, - '--disable' + '--disable', ] verifylist = [ ('host', self.share_service.host), ('binary', self.share_service.binary), - ('disable', True) + ('disable', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.services_mock.disable.assert_called_with( - self.share_service.host, - self.share_service.binary) + self.share_service.host, self.share_service.binary + ) self.assertIsNone(result) def test_service_set_disable_with_reason(self): self.app.client_manager.share.api_version = api_versions.APIVersion( - "2.83") + "2.83" + ) reason = 'earthquake' arglist = [ '--disable', - '--disable-reason', reason, + '--disable-reason', + reason, self.share_service.host, self.share_service.binary, ] @@ -121,7 +120,7 @@ def test_service_set_disable_with_reason(self): self.services_mock.disable.assert_called_with( self.share_service.host, self.share_service.binary, - disable_reason=reason + disable_reason=reason, ) self.assertIsNone(result) @@ -129,59 +128,56 @@ def test_share_service_set_disable_exception(self): arglist = [ self.share_service.host, self.share_service.binary, - '--disable' + '--disable', ] verifylist = [ ('host', self.share_service.host), ('binary', self.share_service.binary), - ('disable', True) + ('disable', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.services_mock.disable.side_effect = Exception() self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) @ddt.ddt class TestShareServiceList(TestShareService): - - columns = [ - 'id', - 'binary', - 'host', - 'zone', - 'status', - 'state', - 'updated_at' - ] + columns = ['id', 'binary', 'host', 'zone', 'status', 'state', 'updated_at'] columns_with_reason = columns + ['disabled_reason'] column_headers = utils.format_column_headers(columns) column_headers_with_reason = utils.format_column_headers( - columns_with_reason) + columns_with_reason + ) def setUp(self): - super(TestShareServiceList, self).setUp() + super().setUp() self.services_list = ( manila_fakes.FakeShareService.create_fake_services( - {'disabled_reason': ''}) + {'disabled_reason': ''} + ) ) self.services_mock.list.return_value = self.services_list - self.values = (oscutils.get_dict_properties( - i._info, self.columns) for i in self.services_list) - self.values_with_reason = (oscutils.get_dict_properties( - i._info, self.columns_with_reason) for i in self.services_list) + self.values = ( + oscutils.get_dict_properties(i._info, self.columns) + for i in self.services_list + ) + self.values_with_reason = ( + oscutils.get_dict_properties(i._info, self.columns_with_reason) + for i in self.services_list + ) self.cmd = osc_services.ListShareService(self.app, None) @ddt.data('2.82', '2.83') def test_share_service_list(self, version): self.app.client_manager.share.api_version = api_versions.APIVersion( - version) + version + ) arglist = [] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -194,8 +190,9 @@ def test_share_service_list(self, version): 'binary': None, 'status': None, 'state': None, - 'zone': None - }) + 'zone': None, + } + ) if api_versions.APIVersion(version) >= api_versions.APIVersion("2.83"): self.assertEqual(self.column_headers_with_reason, columns) self.assertEqual(list(self.values_with_reason), list(data)) @@ -206,14 +203,17 @@ def test_share_service_list(self, version): @ddt.data('2.82', '2.83') def test_share_service_list_host_status(self, version): self.app.client_manager.share.api_version = api_versions.APIVersion( - version) + version + ) arglist = [ - '--host', self.services_list[0].host, - '--status', self.services_list[1].status + '--host', + self.services_list[0].host, + '--status', + self.services_list[1].status, ] verifylist = [ ('host', self.services_list[0].host), - ('status', self.services_list[1].status) + ('status', self.services_list[1].status), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -225,8 +225,9 @@ def test_share_service_list_host_status(self, version): 'binary': None, 'status': self.services_list[1].status, 'state': None, - 'zone': None - }) + 'zone': None, + } + ) if api_versions.APIVersion(version) >= api_versions.APIVersion("2.83"): self.assertEqual(self.column_headers_with_reason, columns) self.assertEqual(list(self.values_with_reason), list(data)) @@ -237,16 +238,20 @@ def test_share_service_list_host_status(self, version): @ddt.data('2.82', '2.83') def test_share_service_list_binary_state_zone(self, version): self.app.client_manager.share.api_version = api_versions.APIVersion( - version) + version + ) arglist = [ - '--binary', self.services_list[0].binary, - '--state', self.services_list[1].state, - '--zone', self.services_list[1].zone + '--binary', + self.services_list[0].binary, + '--state', + self.services_list[1].state, + '--zone', + self.services_list[1].zone, ] verifylist = [ ('binary', self.services_list[0].binary), ('state', self.services_list[1].state), - ('zone', self.services_list[1].zone) + ('zone', self.services_list[1].zone), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -258,8 +263,9 @@ def test_share_service_list_binary_state_zone(self, version): 'binary': self.services_list[0].binary, 'status': None, 'state': self.services_list[1].state, - 'zone': self.services_list[1].zone - }) + 'zone': self.services_list[1].zone, + } + ) if api_versions.APIVersion(version) >= api_versions.APIVersion("2.83"): self.assertEqual(self.column_headers_with_reason, columns) self.assertEqual(list(self.values_with_reason), list(data)) @@ -270,15 +276,15 @@ def test_share_service_list_binary_state_zone(self, version): @ddt.ddt class TestShareServiceEnsureShares(TestShareService): - def setUp(self): - super(TestShareServiceEnsureShares, self).setUp() + super().setUp() self.cmd = osc_services.EnsureShareService(self.app, None) def test_ensure_shares(self): self.app.client_manager.share.api_version = api_versions.APIVersion( - '2.86') + '2.86' + ) fake_host = 'fake_host@fakebackend' arglist = [ fake_host, @@ -294,7 +300,8 @@ def test_ensure_shares(self): def test_ensure_shares_invalid_version(self): self.app.client_manager.share.api_version = api_versions.APIVersion( - '2.85') + '2.85' + ) fake_host = 'fake_host@fakebackend' arglist = [ fake_host, @@ -304,13 +311,14 @@ def test_ensure_shares_invalid_version(self): ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) - self.assertRaises(exceptions.CommandError, - self.cmd.take_action, - parsed_args) + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_ensure_shares_command_error(self): self.app.client_manager.share.api_version = api_versions.APIVersion( - '2.86') + '2.86' + ) self.services_mock.ensure_shares.side_effect = Exception() fake_host = 'fake_host@fakebackend' arglist = [ @@ -321,6 +329,6 @@ def test_ensure_shares_command_error(self): ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) - self.assertRaises(exceptions.CommandError, - self.cmd.take_action, - parsed_args) + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) diff --git a/manilaclient/tests/unit/osc/v2/test_share.py b/manilaclient/tests/unit/osc/v2/test_share.py index 67647ee5..bd26b48a 100644 --- a/manilaclient/tests/unit/osc/v2/test_share.py +++ b/manilaclient/tests/unit/osc/v2/test_share.py @@ -32,9 +32,8 @@ class TestShare(manila_fakes.TestShare): - def setUp(self): - super(TestShare, self).setUp() + super().setUp() self.shares_mock = self.app.client_manager.share.shares self.shares_mock.reset_mock() @@ -59,14 +58,13 @@ def setUp(self): self.share_networks_mock.reset_mock() self.app.client_manager.share.api_version = api_versions.APIVersion( - MAX_VERSION) + MAX_VERSION + ) def setup_shares_mock(self, count): shares = manila_fakes.FakeShare.create_shares(count=count) - self.shares_mock.get = manila_fakes.FakeShare.get_shares( - shares, - 0) + self.shares_mock.get = manila_fakes.FakeShare.get_shares(shares, 0) return shares def setup_share_groups_mock(self): @@ -80,9 +78,8 @@ def setup_share_groups_mock(self): @ddt.ddt class TestShareCreate(TestShare): - def setUp(self): - super(TestShareCreate, self).setUp() + super().setUp() self.new_share = manila_fakes.FakeShare.create_one_share( attrs={'status': 'available'} @@ -91,7 +88,8 @@ def setUp(self): self.shares_mock.get.return_value = self.new_share self.share_snapshot = ( - manila_fakes.FakeShareSnapshot.create_one_snapshot()) + manila_fakes.FakeShareSnapshot.create_one_snapshot() + ) self.snapshots_mock.get.return_value = self.share_snapshot self.share_type = manila_fakes.FakeShareType.create_one_sharetype() self.share_types_mock.get.return_value = self.share_type @@ -108,12 +106,13 @@ def test_share_create_required_args(self): arglist = [ self.new_share.share_proto, str(self.new_share.size), - '--share-type', self.share_type.id, + '--share-type', + self.share_type.id, ] verifylist = [ ('share_proto', self.new_share.share_proto), ('size', self.new_share.size), - ('share_type', self.share_type.id) + ('share_type', self.share_type.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -133,6 +132,7 @@ def test_share_create_required_args(self): snapshot_id=None, scheduler_hints={}, mount_point_name=None, + encryption_key_ref=None, ) self.assertCountEqual(self.columns, columns) @@ -144,19 +144,25 @@ def test_share_create_missing_required_arg(self): arglist = [ self.new_share.share_proto, ] - verifylist = [ - ('share_proto', self.new_share.share_proto) - ] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + verifylist = [('share_proto', self.new_share.share_proto)] + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_create_metadata(self): arglist = [ self.new_share.share_proto, str(self.new_share.size), - '--share-type', self.share_type.id, - '--property', 'Manila=zorilla', - '--property', 'Zorilla=manila' + '--share-type', + self.share_type.id, + '--property', + 'Manila=zorilla', + '--property', + 'Zorilla=manila', ] verifylist = [ ('share_proto', self.new_share.share_proto), @@ -182,6 +188,7 @@ def test_share_create_metadata(self): snapshot_id=None, scheduler_hints={}, mount_point_name=None, + encryption_key_ref=None, ) self.assertCountEqual(self.columns, columns) @@ -190,7 +197,8 @@ def test_share_create_metadata(self): def test_share_create_scheduler_hints(self): """Verifies scheduler hints are parsed correctly.""" self.app.client_manager.share.api_version = api_versions.APIVersion( - "2.65") + "2.65" + ) shares = self.setup_shares_mock(count=2) share1_name = shares[0].name @@ -199,16 +207,21 @@ def test_share_create_scheduler_hints(self): arglist = [ self.new_share.share_proto, str(self.new_share.size), - '--share-type', self.share_type.id, - '--scheduler-hint', ('same_host=%s' % share1_name), - '--scheduler-hint', ('different_host=%s' % share2_name), + '--share-type', + self.share_type.id, + '--scheduler-hint', + (f'same_host={share1_name}'), + '--scheduler-hint', + (f'different_host={share2_name}'), ] verifylist = [ ('share_proto', self.new_share.share_proto), ('size', self.new_share.size), ('share_type', self.share_type.id), - ('scheduler_hint', - {'same_host': share1_name, 'different_host': share2_name}), + ( + 'scheduler_hint', + {'same_host': share1_name, 'different_host': share2_name}, + ), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -226,9 +239,12 @@ def test_share_create_scheduler_hints(self): share_type=self.share_type.id, size=self.new_share.size, snapshot_id=None, - scheduler_hints={'same_host': shares[0].id, - 'different_host': shares[1].id}, + scheduler_hints={ + 'same_host': shares[0].id, + 'different_host': shares[1].id, + }, mount_point_name=None, + encryption_key_ref=None, ) self.assertCountEqual(self.columns, columns) @@ -237,15 +253,18 @@ def test_share_create_scheduler_hints(self): def test_share_create_mount_point_name(self): """Verifies that the mount point name has been passed correctly.""" self.app.client_manager.share.api_version = api_versions.APIVersion( - "2.84") + "2.84" + ) mount_point_name = "fake_mp" arglist = [ self.new_share.share_proto, str(self.new_share.size), - '--share-type', self.share_type.id, - '--mount-point-name', mount_point_name, + '--share-type', + self.share_type.id, + '--mount-point-name', + mount_point_name, ] verifylist = [ ('share_proto', self.new_share.share_proto), @@ -271,6 +290,52 @@ def test_share_create_mount_point_name(self): snapshot_id=None, scheduler_hints={}, mount_point_name='fake_mp', + encryption_key_ref=None, + ) + + self.assertCountEqual(self.columns, columns) + self.assertCountEqual(self.datalist, data) + + def test_share_create_encryption_key_ref(self): + self.app.client_manager.share.api_version = api_versions.APIVersion( + "2.90" + ) + + encryption_key_ref = 'fake_ekr' + + arglist = [ + self.new_share.share_proto, + str(self.new_share.size), + '--share-type', + self.share_type.id, + '--encryption-key-ref', + encryption_key_ref, + ] + verifylist = [ + ('share_proto', self.new_share.share_proto), + ('size', self.new_share.size), + ('encryption_key_ref', encryption_key_ref), + ('share_type', self.share_type.id), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + + self.shares_mock.create.assert_called_with( + availability_zone=None, + description=None, + is_public=False, + metadata={}, + name=None, + share_group_id=None, + share_network=None, + share_proto=self.new_share.share_proto, + share_type=self.share_type.id, + size=self.new_share.size, + snapshot_id=None, + scheduler_hints={}, + mount_point_name=None, + encryption_key_ref=encryption_key_ref, ) self.assertCountEqual(self.columns, columns) @@ -282,24 +347,26 @@ def test_share_create_with_snapshot(self): arglist = [ self.new_share.share_proto, str(self.new_share.size), - '--snapshot-id', self.share_snapshot.id - + '--snapshot-id', + self.share_snapshot.id, ] verifylist = [ ('share_proto', self.new_share.share_proto), ('size', self.new_share.size), - ('snapshot_id', self.share_snapshot.id) + ('snapshot_id', self.share_snapshot.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch( - 'manilaclient.common.apiclient.utils.find_resource', - mock.Mock(return_value=self.share_snapshot)): + 'manilaclient.common.apiclient.utils.find_resource', + mock.Mock(return_value=self.share_snapshot), + ): columns, data = self.cmd.take_action(parsed_args) osc_shares.apiutils.find_resource.assert_called_once_with( - mock.ANY, self.share_snapshot.id) + mock.ANY, self.share_snapshot.id + ) self.shares_mock.create.assert_called_with( availability_zone=None, @@ -315,23 +382,24 @@ def test_share_create_with_snapshot(self): snapshot_id=self.share_snapshot.id, scheduler_hints={}, mount_point_name=None, + encryption_key_ref=None, ) self.assertCountEqual(self.columns, columns) self.assertCountEqual(self.datalist, data) def test_share_create_wait(self): - arglist = [ self.new_share.share_proto, str(self.new_share.size), - '--share-type', self.share_type.id, - '--wait' + '--share-type', + self.share_type.id, + '--wait', ] verifylist = [ ('share_proto', self.new_share.share_proto), ('size', self.new_share.size), ('share_type', self.share_type.id), - ('wait', True) + ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -352,6 +420,7 @@ def test_share_create_wait(self): snapshot_id=None, scheduler_hints={}, mount_point_name=None, + encryption_key_ref=None, ) self.shares_mock.get.assert_called_with(self.new_share.id) @@ -360,18 +429,18 @@ def test_share_create_wait(self): @mock.patch('manilaclient.osc.v2.share.LOG') def test_share_create_wait_error(self, mock_logger): - arglist = [ self.new_share.share_proto, str(self.new_share.size), - '--share-type', self.share_type.id, - '--wait' + '--share-type', + self.share_type.id, + '--wait', ] verifylist = [ ('share_proto', self.new_share.share_proto), ('size', self.new_share.size), ('share_type', self.share_type.id), - ('wait', True) + ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -393,10 +462,12 @@ def test_share_create_wait_error(self, mock_logger): snapshot_id=None, scheduler_hints={}, mount_point_name=None, + encryption_key_ref=None, ) mock_logger.error.assert_called_with( - "ERROR: Share is in error state.") + "ERROR: Share is in error state." + ) self.shares_mock.get.assert_called_with(self.new_share.id) self.assertCountEqual(self.columns, columns) @@ -416,19 +487,19 @@ def test_create_share_with_no_existing_share_type(self): self.share_types_mock.get.side_effect = osc_exceptions.CommandError() self.assertRaises( - osc_exceptions.CommandError, - self.cmd.take_action, - parsed_args) - self.share_types_mock.get.assert_called_once_with( - share_type='default') + osc_exceptions.CommandError, self.cmd.take_action, parsed_args + ) + self.share_types_mock.get.assert_called_once_with(share_type='default') @ddt.data('None', 'NONE', 'none') def test_create_share_with_the_name_none(self, name): arglist = [ - '--name', name, + '--name', + name, self.new_share.share_proto, str(self.new_share.size), - '--share-type', self.share_type.id, + '--share-type', + self.share_type.id, ] verifylist = [ ('name', name), @@ -440,15 +511,13 @@ def test_create_share_with_the_name_none(self, name): parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestShareDelete(TestShare): - def setUp(self): - super(TestShareDelete, self).setUp() + super().setUp() self.shares_mock.delete = mock.Mock() self.shares_mock.delete.return_value = None @@ -459,13 +528,11 @@ def setUp(self): def test_share_delete_one(self): shares = self.setup_shares_mock(count=1) - arglist = [ - shares[0].name - ] + arglist = [shares[0].name] verifylist = [ ("force", False), ("share_group", None), - ('shares', [shares[0].name]) + ('shares', [shares[0].name]), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -497,20 +564,18 @@ def test_share_delete_with_share_group(self): shares = self.setup_shares_mock(count=1) share_group = self.setup_share_groups_mock() - arglist = [ - shares[0].name, - '--share-group', share_group['id'] - ] + arglist = [shares[0].name, '--share-group', share_group['id']] verifylist = [ ("share_group", share_group['id']), - ('shares', [shares[0].name]) + ('shares', [shares[0].name]), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.shares_mock.delete.assert_called_with( - shares[0], share_group['id']) + shares[0], share_group['id'] + ) self.assertIsNone(result) def test_share_delete_with_force(self): @@ -558,13 +623,11 @@ def test_share_delete_with_soft(self): def test_share_delete_wrong_name(self): shares = self.setup_shares_mock(count=1) - arglist = [ - shares[0].name + '-wrong-name' - ] + arglist = [shares[0].name + '-wrong-name'] verifylist = [ ("force", False), ("share_group", None), - ('shares', [shares[0].name + '-wrong-name']) + ('shares', [shares[0].name + '-wrong-name']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -574,33 +637,32 @@ def test_share_delete_wrong_name(self): self.shares_mock.delete.side_effect = exceptions.CommandError() self.assertRaises( - osc_exceptions.CommandError, self.cmd.take_action, parsed_args) + osc_exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_share_delete_no_name(self): # self.setup_shares_mock(count=1) arglist = [] - verifylist = [ - ("force", False), - ("share_group", None), - ('shares', '') - ] + verifylist = [("force", False), ("share_group", None), ('shares', '')] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_delete_wait(self): shares = self.setup_shares_mock(count=1) - arglist = [ - shares[0].name, - '--wait' - ] + arglist = [shares[0].name, '--wait'] verifylist = [ ("force", False), ("share_group", None), ('shares', [shares[0].name]), - ('wait', True) + ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -614,29 +676,23 @@ def test_share_delete_wait(self): def test_share_delete_wait_error(self): shares = self.setup_shares_mock(count=1) - arglist = [ - shares[0].name, - '--wait' - ] + arglist = [shares[0].name, '--wait'] verifylist = [ ("force", False), ("share_group", None), ('shares', [shares[0].name]), - ('wait', True) + ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch('osc_lib.utils.wait_for_delete', return_value=False): self.assertRaises( - osc_exceptions.CommandError, - self.cmd.take_action, - parsed_args + osc_exceptions.CommandError, self.cmd.take_action, parsed_args ) class TestShareList(TestShare): - project = identity_fakes.FakeProject.create_one_project() user = identity_fakes.FakeUser.create_one_user() @@ -649,11 +705,11 @@ class TestShareList(TestShare): 'Is Public', 'Share Type Name', 'Host', - 'Availability Zone' + 'Availability Zone', ] def setUp(self): - super(TestShareList, self).setUp() + super().setUp() self.new_share = manila_fakes.FakeShare.create_one_share() self.shares_mock.list.return_value = [self.new_share] @@ -666,17 +722,19 @@ def setUp(self): self.cmd = osc_shares.ListShare(self.app, None) def _get_data(self): - data = (( - self.new_share.id, - self.new_share.name, - self.new_share.size, - self.new_share.share_proto, - self.new_share.status, - self.new_share.is_public, - self.new_share.share_type_name, - self.new_share.host, - self.new_share.availability_zone, - ),) + data = ( + ( + self.new_share.id, + self.new_share.name, + self.new_share.size, + self.new_share.share_proto, + self.new_share.status, + self.new_share.is_public, + self.new_share.share_type_name, + self.new_share.host, + self.new_share.availability_zone, + ), + ) return data def _get_search_opts(self): @@ -701,6 +759,7 @@ def _get_search_opts(self): 'export_location': None, 'name~': None, 'description~': None, + 'encryption_key_ref': None, } return search_opts @@ -730,7 +789,8 @@ def test_share_list_no_options(self): def test_share_list_project(self): arglist = [ - '--project', self.project.name, + '--project', + self.project.name, ] verifylist = [ ('project', self.project.name), @@ -759,8 +819,10 @@ def test_share_list_project(self): def test_share_list_project_domain(self): arglist = [ - '--project', self.project.name, - '--project-domain', self.project.domain_id, + '--project', + self.project.name, + '--project-domain', + self.project.domain_id, ] verifylist = [ ('project', self.project.name), @@ -790,7 +852,8 @@ def test_share_list_project_domain(self): def test_share_list_user(self): arglist = [ - '--user', self.user.name, + '--user', + self.user.name, ] verifylist = [ ('user', self.user.name), @@ -817,8 +880,10 @@ def test_share_list_user(self): def test_share_list_user_domain(self): arglist = [ - '--user', self.user.name, - '--user-domain', self.user.domain_id, + '--user', + self.user.name, + '--user-domain', + self.user.domain_id, ] verifylist = [ ('user', self.user.name), @@ -847,7 +912,8 @@ def test_share_list_user_domain(self): def test_share_list_name(self): arglist = [ - '--name', self.new_share.name, + '--name', + self.new_share.name, ] verifylist = [ ('long', False), @@ -875,7 +941,8 @@ def test_share_list_name(self): def test_share_list_status(self): arglist = [ - '--status', self.new_share.status, + '--status', + self.new_share.status, ] verifylist = [ ('long', False), @@ -977,46 +1044,52 @@ def test_share_list_long(self): 'Has Replicas', 'Created At', 'Properties', + 'Encryption Key Ref', ] self.assertEqual(collist, cmd_columns) - data = (( - self.new_share.id, - self.new_share.name, - self.new_share.size, - self.new_share.share_proto, - self.new_share.status, - self.new_share.is_public, - self.new_share.share_type_name, - self.new_share.availability_zone, - self.new_share.description, - self.new_share.share_network_id, - self.new_share.share_server_id, - self.new_share.share_type, - self.new_share.share_group_id, - self.new_share.host, - self.new_share.user_id, - self.new_share.project_id, - self.new_share.access_rules_status, - self.new_share.snapshot_id, - self.new_share.snapshot_support, - self.new_share.create_share_from_snapshot_support, - self.new_share.mount_snapshot_support, - self.new_share.revert_to_snapshot_support, - self.new_share.task_state, - self.new_share.source_share_group_snapshot_member_id, - self.new_share.replication_type, - self.new_share.has_replicas, - self.new_share.created_at, - self.new_share.metadata - ),) + data = ( + ( + self.new_share.id, + self.new_share.name, + self.new_share.size, + self.new_share.share_proto, + self.new_share.status, + self.new_share.is_public, + self.new_share.share_type_name, + self.new_share.availability_zone, + self.new_share.description, + self.new_share.share_network_id, + self.new_share.share_server_id, + self.new_share.share_type, + self.new_share.share_group_id, + self.new_share.host, + self.new_share.user_id, + self.new_share.project_id, + self.new_share.access_rules_status, + self.new_share.snapshot_id, + self.new_share.snapshot_support, + self.new_share.create_share_from_snapshot_support, + self.new_share.mount_snapshot_support, + self.new_share.revert_to_snapshot_support, + self.new_share.task_state, + self.new_share.source_share_group_snapshot_member_id, + self.new_share.replication_type, + self.new_share.has_replicas, + self.new_share.created_at, + self.new_share.metadata, + self.new_share.encryption_key_ref, + ), + ) self.assertEqual(data, tuple(cmd_data)) def test_share_list_with_marker_and_limit(self): arglist = [ - "--marker", self.new_share.id, - "--limit", "2", + "--marker", + self.new_share.id, + "--limit", + "2", ] verifylist = [ ('long', False), @@ -1039,25 +1112,31 @@ def test_share_list_with_marker_and_limit(self): data = self._get_data() - self.shares_mock.list.assert_called_once_with( - search_opts=search_opts - ) + self.shares_mock.list.assert_called_once_with(search_opts=search_opts) self.assertEqual(data, tuple(cmd_data)) def test_share_list_negative_limit(self): arglist = [ - "--limit", "-2", + "--limit", + "-2", ] verifylist = [ ("limit", -2), ] - self.assertRaises(osc_utils.ParserException, self.check_parser, - self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_list_name_description_filter(self): arglist = [ - '--name~', self.new_share.name, - '--description~', self.new_share.description, + '--name~', + self.new_share.name, + '--description~', + self.new_share.description, ] verifylist = [ @@ -1085,7 +1164,8 @@ def test_share_list_name_description_filter(self): def test_list_share_soft_deleted_api_version_exception(self): self.app.client_manager.share.api_version = api_versions.APIVersion( - "2.60") + "2.60" + ) arglist = [ '--soft-deleted', ] @@ -1099,17 +1179,37 @@ def test_list_share_soft_deleted_api_version_exception(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - osc_exceptions.CommandError, - self.cmd.take_action, - parsed_args) + osc_exceptions.CommandError, self.cmd.take_action, parsed_args + ) + + def test_list_share_encryption_key_ref_api_version_exception(self): + self.app.client_manager.share.api_version = api_versions.APIVersion( + "2.89" + ) + arglist = [ + '--encryption-key-ref', + 'fake', + ] + verifylist = [ + ('encryption_key_ref', 'fake'), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.assertRaises( + osc_exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_list_share_api_version_exception(self): self.app.client_manager.share.api_version = api_versions.APIVersion( - "2.35") + "2.35" + ) arglist = [ - '--name~', 'Name', - '--description~', 'Description', + '--name~', + 'Name', + '--description~', + 'Description', ] verifylist = [ ('name~', 'Name'), @@ -1119,55 +1219,55 @@ def test_list_share_api_version_exception(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - osc_exceptions.CommandError, - self.cmd.take_action, - parsed_args) + osc_exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestShareShow(TestShare): - def setUp(self): - super(TestShareShow, self).setUp() + super().setUp() self._share = manila_fakes.FakeShare.create_one_share() self.shares_mock.get.return_value = self._share self._export_location = ( - manila_fakes.FakeShareExportLocation.create_one_export_location()) + manila_fakes.FakeShareExportLocation.create_one_export_location() + ) # Get the command object to test self.cmd = osc_shares.ShowShare(self.app, None) def test_share_show(self): - arglist = [ - self._share.id - ] - verifylist = [ - ("share", self._share.id) - ] + arglist = [self._share.id] + verifylist = [("share", self._share.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) cliutils.convert_dict_list_to_string = mock.Mock() cliutils.convert_dict_list_to_string.return_value = dict( - self._export_location) + self._export_location + ) columns, data = self.cmd.take_action(parsed_args) self.shares_mock.get.assert_called_with(self._share.id) self.assertEqual( sorted(manila_fakes.FakeShare.get_share_columns(self._share)), - sorted(columns)) + sorted(columns), + ) self.assertCountEqual( - manila_fakes.FakeShare.get_share_data(self._share), data) + manila_fakes.FakeShare.get_share_data(self._share), data + ) class TestShareSet(TestShare): - def setUp(self): - super(TestShareSet, self).setUp() + super().setUp() self._share = manila_fakes.FakeShare.create_one_share( - methods={"reset_state": None, "reset_task_state": None, - "set_metadata": None} + methods={ + "reset_state": None, + "reset_task_state": None, + "set_metadata": None, + } ) self.shares_mock.get.return_value = self._share @@ -1176,127 +1276,118 @@ def setUp(self): def test_share_set_property(self): arglist = [ - '--property', 'Zorilla=manila', + '--property', + 'Zorilla=manila', self._share.id, ] verifylist = [ ('property', {'Zorilla': 'manila'}), - ('share', self._share.id) + ('share', self._share.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) - self._share.set_metadata.assert_called_with( - {'Zorilla': 'manila'}) + self._share.set_metadata.assert_called_with({'Zorilla': 'manila'}) def test_share_set_name(self): new_name = uuid.uuid4().hex arglist = [ - '--name', new_name, + '--name', + new_name, self._share.id, ] - verifylist = [ - ('name', new_name), - ('share', self._share.id) - ] + verifylist = [('name', new_name), ('share', self._share.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.shares_mock.update.assert_called_with( - self._share.id, - display_name=parsed_args.name) + self._share.id, display_name=parsed_args.name + ) def test_share_set_description(self): new_description = uuid.uuid4().hex arglist = [ - '--description', new_description, + '--description', + new_description, self._share.id, ] verifylist = [ ('description', new_description), - ('share', self._share.id) + ('share', self._share.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.shares_mock.update.assert_called_with( - self._share.id, - display_description=parsed_args.description) + self._share.id, display_description=parsed_args.description + ) def test_share_set_visibility(self): arglist = [ - '--public', 'true', + '--public', + 'true', self._share.id, ] - verifylist = [ - ('public', 'true'), - ('share', self._share.id) - ] + verifylist = [('public', 'true'), ('share', self._share.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.shares_mock.update.assert_called_with( - self._share.id, - is_public='true') + self._share.id, is_public='true' + ) def test_share_set_visibility_exception(self): arglist = [ - '--public', 'not_a_boolean_value', + '--public', + 'not_a_boolean_value', self._share.id, ] verifylist = [ ('public', 'not_a_boolean_value'), - ('share', self._share.id) + ('share', self._share.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.shares_mock.update.assert_called_with( - self._share.id, - is_public='not_a_boolean_value') + self._share.id, is_public='not_a_boolean_value' + ) # '--public' takes only boolean value, would raise a BadRequest self.shares_mock.update.side_effect = exceptions.BadRequest() self.assertRaises( - osc_exceptions.CommandError, self.cmd.take_action, parsed_args) + osc_exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_share_set_property_exception(self): arglist = [ - '--property', 'key=', + '--property', + 'key=', self._share.id, ] - verifylist = [ - ('property', {'key': ''}), - ('share', self._share.id) - ] + verifylist = [('property', {'key': ''}), ('share', self._share.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) - self._share.set_metadata.assert_called_with( - {'key': ''}) + self._share.set_metadata.assert_called_with({'key': ''}) # '--property' takes key=value arguments # missing a value would raise a BadRequest self._share.set_metadata.side_effect = exceptions.BadRequest self.assertRaises( - osc_exceptions.CommandError, self.cmd.take_action, parsed_args) + osc_exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_share_set_status(self): new_status = 'available' - arglist = [ - self._share.id, - '--status', new_status - ] - verifylist = [ - ('share', self._share.id), - ('status', new_status) - ] + arglist = [self._share.id, '--status', new_status] + verifylist = [('share', self._share.id), ('status', new_status)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -1306,30 +1397,22 @@ def test_share_set_status(self): def test_share_set_status_exception(self): new_status = 'available' - arglist = [ - self._share.id, - '--status', new_status - ] - verifylist = [ - ('share', self._share.id), - ('status', new_status) - ] + arglist = [self._share.id, '--status', new_status] + verifylist = [('share', self._share.id), ('status', new_status)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self._share.reset_state.side_effect = Exception() self.assertRaises( - osc_exceptions.CommandError, self.cmd.take_action, parsed_args) + osc_exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_share_set_task_state(self): new_task_state = 'migration_starting' - arglist = [ - self._share.id, - '--task-state', new_task_state - ] + arglist = [self._share.id, '--task-state', new_task_state] verifylist = [ ('share', self._share.id), - ('task_state', new_task_state) + ('task_state', new_task_state), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -1337,11 +1420,26 @@ def test_share_set_task_state(self): self._share.reset_task_state.assert_called_with(new_task_state) self.assertIsNone(result) + def test_share_set_task_state_none(self): + arglist = [self._share.id, '--task-state'] + verifylist = [('share', self._share.id), ('task_state', None)] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + result = self.cmd.take_action(parsed_args) + self._share.reset_task_state.assert_called_with(None) + self.assertIsNone(result) + + def test_share_set_task_state_string_none(self): + arglist = [self._share.id, '--task-state', 'None'] + verifylist = [('share', self._share.id), ('task_state', 'None')] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + result = self.cmd.take_action(parsed_args) + self._share.reset_task_state.assert_called_with(None) + self.assertIsNone(result) -class TestShareUnset(TestShare): +class TestShareUnset(TestShare): def setUp(self): - super(TestShareUnset, self).setUp() + super().setUp() self._share = manila_fakes.FakeShare.create_one_share( methods={"delete_metadata": None} @@ -1353,248 +1451,181 @@ def setUp(self): def test_share_unset_property(self): arglist = [ - '--property', 'Manila', + '--property', + 'Manila', self._share.id, ] - verifylist = [ - ('property', ['Manila']), - ('share', self._share.id) - ] + verifylist = [('property', ['Manila']), ('share', self._share.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) - self._share.delete_metadata.assert_called_with( - parsed_args.property) + self._share.delete_metadata.assert_called_with(parsed_args.property) def test_share_unset_name(self): arglist = [ '--name', self._share.id, ] - verifylist = [ - ('name', True), - ('share', self._share.id) - ] + verifylist = [('name', True), ('share', self._share.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.shares_mock.update.assert_called_with( - self._share.id, - display_name=None) + self._share.id, display_name=None + ) def test_share_unset_description(self): arglist = [ '--description', self._share.id, ] - verifylist = [ - ('description', True), - ('share', self._share.id) - ] + verifylist = [('description', True), ('share', self._share.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.shares_mock.update.assert_called_with( - self._share.id, - display_description=None) + self._share.id, display_description=None + ) def test_share_unset_name_exception(self): arglist = [ '--name', self._share.id, ] - verifylist = [ - ('name', True), - ('share', self._share.id) - ] + verifylist = [('name', True), ('share', self._share.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.shares_mock.update.side_effect = exceptions.BadRequest() self.assertRaises( - osc_exceptions.CommandError, self.cmd.take_action, parsed_args) + osc_exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_share_unset_property_exception(self): arglist = [ - '--property', 'Manila', + '--property', + 'Manila', self._share.id, ] - verifylist = [ - ('property', ['Manila']), - ('share', self._share.id) - ] + verifylist = [('property', ['Manila']), ('share', self._share.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) - self._share.delete_metadata.assert_called_with( - parsed_args.property) + self._share.delete_metadata.assert_called_with(parsed_args.property) # 404 Not Found would be raised, if property 'Manila' doesn't exist self._share.delete_metadata.side_effect = exceptions.NotFound self.assertRaises( - osc_exceptions.CommandError, self.cmd.take_action, parsed_args) + osc_exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestResizeShare(TestShare): - def setUp(self): - super(TestResizeShare, self).setUp() + super().setUp() self._share = manila_fakes.FakeShare.create_one_share( - attrs={'size': 2, - 'status': 'available'}) + attrs={'size': 2, 'status': 'available'} + ) self.shares_mock.get.return_value = self._share # Get the command objects to test self.cmd = osc_shares.ResizeShare(self.app, None) def test_share_shrink(self): - arglist = [ - self._share.id, - '1' - ] - verifylist = [ - ('share', self._share.id), - ('new_size', 1) - ] + arglist = [self._share.id, '1'] + verifylist = [('share', self._share.id), ('new_size', 1)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) - self.shares_mock.shrink.assert_called_with( - self._share, - 1 - ) + self.shares_mock.shrink.assert_called_with(self._share, 1) def test_share_shrink_exception(self): - arglist = [ - self._share.id, - '1' - ] - verifylist = [ - ('share', self._share.id), - ('new_size', 1) - ] + arglist = [self._share.id, '1'] + verifylist = [('share', self._share.id), ('new_size', 1)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.shares_mock.shrink.side_effect = Exception() self.assertRaises( - osc_exceptions.CommandError, - self.cmd.take_action, - parsed_args) + osc_exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_share_extend(self): - arglist = [ - self._share.id, - '3' - ] - verifylist = [ - ('share', self._share.id), - ('new_size', 3) - ] + arglist = [self._share.id, '3'] + verifylist = [('share', self._share.id), ('new_size', 3)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) - self.shares_mock.extend.assert_called_with( - self._share, - 3 - ) + self.shares_mock.extend.assert_called_with(self._share, 3) def test_share_extend_exception(self): - arglist = [ - self._share.id, - '3' - ] - verifylist = [ - ('share', self._share.id), - ('new_size', 3) - ] + arglist = [self._share.id, '3'] + verifylist = [('share', self._share.id), ('new_size', 3)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.shares_mock.extend.side_effect = Exception() self.assertRaises( - osc_exceptions.CommandError, - self.cmd.take_action, - parsed_args) + osc_exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_share_resize_already_required_size(self): - arglist = [ - self._share.id, - '2' - ] - verifylist = [ - ('share', self._share.id), - ('new_size', 2) - ] + arglist = [self._share.id, '2'] + verifylist = [('share', self._share.id), ('new_size', 2)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - osc_exceptions.CommandError, - self.cmd.take_action, - parsed_args + osc_exceptions.CommandError, self.cmd.take_action, parsed_args ) def test_share_missing_args(self): - arglist = [ - self._share.id - ] - verifylist = [ - ('share', self._share.id) - ] + arglist = [self._share.id] + verifylist = [('share', self._share.id)] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_resize_wait(self): - arglist = [ - self._share.id, - '3', - '--wait' - ] + arglist = [self._share.id, '3', '--wait'] verifylist = [ ('share', self._share.id), ('new_size', 3), - ('wait', True) + ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) - self.shares_mock.extend.assert_called_with( - self._share, - 3 - ) + self.shares_mock.extend.assert_called_with(self._share, 3) self.shares_mock.get.assert_called_with(self._share.id) def test_share_resize_wait_error(self): - arglist = [ - self._share.id, - '3', - '--wait' - ] + arglist = [self._share.id, '3', '--wait'] verifylist = [ ('share', self._share.id), ('new_size', 3), - ('wait', True) + ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch('osc_lib.utils.wait_for_status', return_value=False): self.assertRaises( - osc_exceptions.CommandError, - self.cmd.take_action, - parsed_args + osc_exceptions.CommandError, self.cmd.take_action, parsed_args ) class TestAdoptShare(TestShare): - def setUp(self): - super(TestAdoptShare, self).setUp() + super().setUp() self._share_type = manila_fakes.FakeShareType.create_one_sharetype() self.share_types_mock.get.return_value = self._share_type @@ -1603,7 +1634,9 @@ def setUp(self): attrs={ 'status': 'available', 'share_type': self._share_type.id, - 'share_server_id': 'server-id' + uuid.uuid4().hex}) + 'share_server_id': 'server-id' + uuid.uuid4().hex, + } + ) self.shares_mock.get.return_value = self._share self.shares_mock.manage.return_value = self._share @@ -1618,19 +1651,20 @@ def test_share_adopt_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_adopt_required_args(self): - arglist = [ - 'some.host@driver#pool', - 'NFS', - '10.0.0.1:/example_path' - ] + arglist = ['some.host@driver#pool', 'NFS', '10.0.0.1:/example_path'] verifylist = [ ('service_host', 'some.host@driver#pool'), ('protocol', 'NFS'), - ('export_path', '10.0.0.1:/example_path') + ('export_path', '10.0.0.1:/example_path'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) @@ -1639,7 +1673,7 @@ def test_share_adopt_required_args(self): export_path='10.0.0.1:/example_path', name=None, protocol='NFS', - service_host='some.host@driver#pool' + service_host='some.host@driver#pool', ) self.assertCountEqual(self.columns, columns) self.assertCountEqual(self.datalist, data) @@ -1649,14 +1683,19 @@ def test_share_adopt(self): 'some.host@driver#pool', 'NFS', '10.0.0.1:/example_path', - '--name', self._share.id, - '--description', self._share.description, - '--share-type', self._share.share_type, - '--driver-options', 'key1=value1', 'key2=value2', + '--name', + self._share.id, + '--description', + self._share.description, + '--share-type', + self._share.share_type, + '--driver-options', + 'key1=value1', + 'key2=value2', '--wait', '--public', - '--share-server-id', self._share.share_server_id - + '--share-server-id', + self._share.share_server_id, ] verifylist = [ ('service_host', 'some.host@driver#pool'), @@ -1668,8 +1707,7 @@ def test_share_adopt(self): ('driver_options', ['key1=value1', 'key2=value2']), ('wait', True), ('public', True), - ('share_server_id', self._share.share_server_id) - + ('share_server_id', self._share.share_server_id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -1683,7 +1721,7 @@ def test_share_adopt(self): service_host='some.host@driver#pool', share_server_id=self._share.share_server_id, share_type=self._share_type.id, - public=True + public=True, ) self.assertCountEqual(self.columns, columns) self.assertCountEqual(self.datalist, data) @@ -1694,13 +1732,13 @@ def test_share_adopt_wait_error(self, mock_logger): 'some.host@driver#pool', 'NFS', '10.0.0.1:/example_path', - '--wait' + '--wait', ] verifylist = [ ('service_host', 'some.host@driver#pool'), ('protocol', 'NFS'), ('export_path', '10.0.0.1:/example_path'), - ('wait', True) + ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -1712,11 +1750,12 @@ def test_share_adopt_wait_error(self, mock_logger): export_path='10.0.0.1:/example_path', name=None, protocol='NFS', - service_host='some.host@driver#pool' + service_host='some.host@driver#pool', ) mock_logger.error.assert_called_with( - "ERROR: Share is in error state.") + "ERROR: Share is in error state." + ) self.shares_mock.get.assert_called_with(self._share.id) self.assertCountEqual(self.columns, columns) @@ -1724,56 +1763,59 @@ def test_share_adopt_wait_error(self, mock_logger): def test_share_adopt_visibility_api_version_exception(self): self.app.client_manager.share.api_version = api_versions.APIVersion( - "2.7") + "2.7" + ) arglist = [ 'some.host@driver#pool', 'NFS', '10.0.0.1:/example_path', - '--public' - + '--public', ] verifylist = [ ('service_host', 'some.host@driver#pool'), ('protocol', 'NFS'), ('export_path', '10.0.0.1:/example_path'), - ('public', True) + ('public', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - osc_exceptions.CommandError, self.cmd.take_action, parsed_args) + osc_exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_share_adopt_share_server_api_version_exception(self): self.app.client_manager.share.api_version = api_versions.APIVersion( - "2.48") + "2.48" + ) arglist = [ 'some.host@driver#pool', 'NFS', '10.0.0.1:/example_path', - '--share-server-id', self._share.share_server_id - + '--share-server-id', + self._share.share_server_id, ] verifylist = [ ('service_host', 'some.host@driver#pool'), ('protocol', 'NFS'), ('export_path', '10.0.0.1:/example_path'), - ('share_server_id', self._share.share_server_id) + ('share_server_id', self._share.share_server_id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - osc_exceptions.CommandError, self.cmd.take_action, parsed_args) + osc_exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestAbandonShare(TestShare): - def setUp(self): - super(TestAbandonShare, self).setUp() + super().setUp() self._share = manila_fakes.FakeShare.create_one_share( - attrs={'status': 'available'}) + attrs={'status': 'available'} + ) self.shares_mock.get.return_value = self._share # Get the command objects to test @@ -1794,14 +1836,8 @@ def test_share_abandon(self): self.assertIsNone(result) def test_share_abandon_wait(self): - arglist = [ - self._share.id, - '--wait' - ] - verifylist = [ - ('share', [self._share.id]), - ('wait', True) - ] + arglist = [self._share.id, '--wait'] + verifylist = [('share', [self._share.id]), ('wait', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -1811,57 +1847,43 @@ def test_share_abandon_wait(self): self.assertIsNone(result) def test_share_abandon_wait_error(self): - arglist = [ - self._share.id, - '--wait' - ] - verifylist = [ - ('share', [self._share.id]), - ('wait', True) - ] + arglist = [self._share.id, '--wait'] + verifylist = [('share', [self._share.id]), ('wait', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch('osc_lib.utils.wait_for_delete', return_value=False): self.assertRaises( - osc_exceptions.CommandError, - self.cmd.take_action, - parsed_args + osc_exceptions.CommandError, self.cmd.take_action, parsed_args ) class TestShareExportLocationShow(TestShare): - def setUp(self): - super(TestShareExportLocationShow, self).setUp() + super().setUp() self._share = manila_fakes.FakeShare.create_one_share() self.shares_mock.get.return_value = self._share self._export_location = ( - manila_fakes.FakeShareExportLocation.create_one_export_location()) - - self.export_locations_mock.get.return_value = ( - self._export_location + manila_fakes.FakeShareExportLocation.create_one_export_location() ) + self.export_locations_mock.get.return_value = self._export_location + # Get the command object to test self.cmd = osc_shares.ShareExportLocationShow(self.app, None) def test_share_show_export_location(self): - arglist = [ - self._share.id, - self._export_location.fake_uuid - ] + arglist = [self._share.id, self._export_location.fake_uuid] verifylist = [ ('share', self._share.id), - ('export_location', self._export_location.fake_uuid) + ('export_location', self._export_location.fake_uuid), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.export_locations_mock.get.assert_called_with( - share=self._share, - export_location=self._export_location.fake_uuid + share=self._share, export_location=self._export_location.fake_uuid ) self.assertEqual(tuple(self._export_location._info.keys()), columns) @@ -1869,49 +1891,42 @@ def test_share_show_export_location(self): class TestShareExportLocationList(TestShare): - columns = ['ID', 'Path', 'Preferred'] def setUp(self): - super(TestShareExportLocationList, self).setUp() + super().setUp() self._share = manila_fakes.FakeShare.create_one_share() self.shares_mock.get.return_value = self._share self._export_locations = [ - manila_fakes.FakeShareExportLocation.create_one_export_location()] + manila_fakes.FakeShareExportLocation.create_one_export_location() + ] - self.export_locations_mock.list.return_value = ( - self._export_locations - ) + self.export_locations_mock.list.return_value = self._export_locations - self.values = (oscutils.get_dict_properties( - e._info, self.columns) for e in self._export_locations) + self.values = ( + oscutils.get_dict_properties(e._info, self.columns) + for e in self._export_locations + ) # Get the command object to test self.cmd = osc_shares.ShareExportLocationList(self.app, None) def test_share_list_export_location(self): - arglist = [ - self._share.id - ] - verifylist = [ - ('share', self._share.id) - ] + arglist = [self._share.id] + verifylist = [('share', self._share.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) - self.export_locations_mock.list.assert_called_with( - share=self._share - ) + self.export_locations_mock.list.assert_called_with(share=self._share) self.assertEqual(self.columns, columns) self.assertCountEqual(self.values, data) class TestExportLocationSet(TestShare): - def setUp(self): - super(TestExportLocationSet, self).setUp() + super().setUp() self._share = manila_fakes.FakeShare.create_one_share( methods={"set_metadata": None} @@ -1920,12 +1935,12 @@ def setUp(self): self._export_location = ( manila_fakes.FakeShareExportLocation.create_one_export_location( - {'fake_share_instance_id': self._share.id})) - - self.export_locations_mock.get.return_value = ( - self._export_location + {'fake_share_instance_id': self._share.id} + ) ) + self.export_locations_mock.get.return_value = self._export_location + self.cmd = osc_shares.ShareExportLocationSet(self.app, None) def test_share_set_export_location_property(self): @@ -1935,8 +1950,8 @@ def test_share_set_export_location_property(self): arglist = [ self._share.id, self._export_location.id, - '--property', 'Bobcat=manila', - + '--property', + 'Bobcat=manila', ] verifylist = [ ('share', self._share.id), @@ -1947,8 +1962,10 @@ def test_share_set_export_location_property(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.export_locations_mock.set_metadata.assert_called_once_with( - self._share.id, {'Bobcat': 'manila'}, - subresource=self._export_location.id) + self._share.id, + {'Bobcat': 'manila'}, + subresource=self._export_location.id, + ) def test_share_set_export_location_property_exception(self): self.app.client_manager.share.api_version = api_versions.APIVersion( @@ -1957,7 +1974,8 @@ def test_share_set_export_location_property_exception(self): arglist = [ self._share.id, self._export_location.id, - '--property', 'key=', + '--property', + 'key=', ] verifylist = [ ('share', self._share.id), @@ -1969,20 +1987,20 @@ def test_share_set_export_location_property_exception(self): self.cmd.take_action(parsed_args) self.export_locations_mock.set_metadata.assert_called_once_with( - self._share.id, {'key': ''}, - subresource=self._export_location.id) + self._share.id, {'key': ''}, subresource=self._export_location.id + ) self.export_locations_mock.set_metadata.side_effect = ( - exceptions.BadRequest) + exceptions.BadRequest + ) self.assertRaises( - osc_exceptions.CommandError, self.cmd.take_action, - parsed_args) + osc_exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestExportLocationUnset(TestShare): - def setUp(self): - super(TestExportLocationUnset, self).setUp() + super().setUp() self._share = manila_fakes.FakeShare.create_one_share( methods={"set_metadata": None} @@ -1991,12 +2009,12 @@ def setUp(self): self._export_location = ( manila_fakes.FakeShareExportLocation.create_one_export_location( - {'fake_share_instance_id': self._share.id})) - - self.export_locations_mock.get.return_value = ( - self._export_location + {'fake_share_instance_id': self._share.id} + ) ) + self.export_locations_mock.get.return_value = self._export_location + self.cmd = osc_shares.ShareExportLocationUnset(self.app, None) def test_share_unset_export_location_property(self): @@ -2006,8 +2024,8 @@ def test_share_unset_export_location_property(self): arglist = [ self._share.id, self._export_location.id, - '--property', 'Bobcat', - + '--property', + 'Bobcat', ] verifylist = [ ('share', self._share.id), @@ -2018,8 +2036,8 @@ def test_share_unset_export_location_property(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.export_locations_mock.delete_metadata.assert_called_once_with( - self._share.id, ['Bobcat'], - subresource=self._export_location.id) + self._share.id, ['Bobcat'], subresource=self._export_location.id + ) def test_share_unset_export_location_property_exception(self): self.app.client_manager.share.api_version = api_versions.APIVersion( @@ -2028,7 +2046,8 @@ def test_share_unset_export_location_property_exception(self): arglist = [ self._share.id, self._export_location.id, - '--property', 'key', + '--property', + 'key', ] verifylist = [ ('share', self._share.id), @@ -2039,33 +2058,33 @@ def test_share_unset_export_location_property_exception(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) - self.export_locations_mock.delete_metadata.assert_has_calls([ - mock.call(self._share.id, ['key'], - subresource=self._export_location.id)]) + self.export_locations_mock.delete_metadata.assert_has_calls( + [ + mock.call( + self._share.id, + ['key'], + subresource=self._export_location.id, + ) + ] + ) self.export_locations_mock.delete_metadata.side_effect = ( - exceptions.NotFound) + exceptions.NotFound + ) self.assertRaises( - osc_exceptions.CommandError, self.cmd.take_action, - parsed_args) + osc_exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestShowShareProperties(TestShare): - - properties = { - 'key1': 'value1', - 'key2': 'value2' - } + properties = {'key1': 'value1', 'key2': 'value2'} def setUp(self): - super(TestShowShareProperties, self).setUp() + super().setUp() self._share = manila_fakes.FakeShare.create_one_share( - attrs={ - 'metadata': osc_fakes.FakeResource( - info=self.properties) - }, - methods={'get_metadata': None} + attrs={'metadata': osc_fakes.FakeResource(info=self.properties)}, + methods={'get_metadata': None}, ) self.shares_mock.get.return_value = self._share self.shares_mock.get_metadata.return_value = self._share.metadata @@ -2077,12 +2096,8 @@ def setUp(self): self.columns = tuple(self._share.metadata._info.keys()) def test_share_show_properties(self): - arglist = [ - self._share.id - ] - verifylist = [ - ("share", self._share.id) - ] + arglist = [self._share.id] + verifylist = [("share", self._share.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.shares_mock.get.assert_called_with(self._share.id) @@ -2093,29 +2108,26 @@ def test_share_show_properties(self): class TestShareRevert(TestShare): - def setUp(self): - super(TestShareRevert, self).setUp() + super().setUp() self.share = manila_fakes.FakeShare.create_one_share( attrs={'revert_to_snapshot_support': True}, - methods={'revert_to_snapshot': None} + methods={'revert_to_snapshot': None}, ) self.share_snapshot = ( manila_fakes.FakeShareSnapshot.create_one_snapshot( - attrs={'share_id': self.share.id})) + attrs={'share_id': self.share.id} + ) + ) self.shares_mock.get.return_value = self.share self.snapshots_mock.get.return_value = self.share_snapshot self.cmd = osc_shares.RevertShare(self.app, None) def test_share_revert(self): - arglist = [ - self.share_snapshot.id - ] - verifylist = [ - ('snapshot', self.share_snapshot.id) - ] + arglist = [self.share_snapshot.id] + verifylist = [('snapshot', self.share_snapshot.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.shares_mock.get.assert_called_with(self.share_snapshot.share_id) @@ -2123,35 +2135,31 @@ def test_share_revert(self): self.assertIsNone(result) def test_share_revert_exception(self): - arglist = [ - self.share_snapshot.id - ] - verifylist = [ - ('snapshot', self.share_snapshot.id) - ] + arglist = [self.share_snapshot.id] + verifylist = [('snapshot', self.share_snapshot.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.share.revert_to_snapshot.side_effect = Exception() self.assertRaises( - osc_exceptions.CommandError, self.cmd.take_action, parsed_args) + osc_exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestShareMigrationStart(TestShare): - def setUp(self): - super(TestShareMigrationStart, self).setUp() + super().setUp() self.new_share_type = manila_fakes.FakeShareType.create_one_sharetype() self.share_types_mock.get.return_value = self.new_share_type - self.new_share_network = manila_fakes.FakeShareNetwork \ - .create_one_share_network() + self.new_share_network = ( + manila_fakes.FakeShareNetwork.create_one_share_network() + ) self.share_networks_mock.get.return_value = self.new_share_network self._share = manila_fakes.FakeShare.create_one_share( - attrs={ - 'status': 'available'}, - methods={'migration_start': None}) + attrs={'status': 'available'}, methods={'migration_start': None} + ) self.shares_mock.get.return_value = self._share self.shares_mock.manage.return_value = self._share @@ -2164,13 +2172,18 @@ def test_migration_start_with_new_share_type(self): arglist = [ self._share.id, 'host@driver#pool', - '--preserve-metadata', 'False', - '--preserve-snapshots', 'False', - '--writable', 'False', - '--nondisruptive', 'False', - '--new-share-type', self.new_share_type.id, - '--force-host-assisted-migration', 'False' - + '--preserve-metadata', + 'False', + '--preserve-snapshots', + 'False', + '--writable', + 'False', + '--nondisruptive', + 'False', + '--new-share-type', + self.new_share_type.id, + '--force-host-assisted-migration', + 'False', ] verifylist = [ ('share', self._share.id), @@ -2180,8 +2193,7 @@ def test_migration_start_with_new_share_type(self): ('writable', 'False'), ('nondisruptive', 'False'), ('new_share_type', self.new_share_type.id), - ('force_host_assisted_migration', 'False') - + ('force_host_assisted_migration', 'False'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) @@ -2193,7 +2205,7 @@ def test_migration_start_with_new_share_type(self): 'False', 'False', None, - self.new_share_type.id + self.new_share_type.id, ) self.assertIsNone(result) @@ -2203,13 +2215,18 @@ def test_migration_start_with_new_share_network(self): arglist = [ self._share.id, 'host@driver#pool', - '--preserve-metadata', 'False', - '--preserve-snapshots', 'False', - '--writable', 'False', - '--nondisruptive', 'False', - '--new-share-network', self.new_share_network.id, - '--force-host-assisted-migration', 'False' - + '--preserve-metadata', + 'False', + '--preserve-snapshots', + 'False', + '--writable', + 'False', + '--nondisruptive', + 'False', + '--new-share-network', + self.new_share_network.id, + '--force-host-assisted-migration', + 'False', ] verifylist = [ ('share', self._share.id), @@ -2219,8 +2236,7 @@ def test_migration_start_with_new_share_network(self): ('writable', 'False'), ('nondisruptive', 'False'), ('new_share_network', self.new_share_network.id), - ('force_host_assisted_migration', 'False') - + ('force_host_assisted_migration', 'False'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) @@ -2232,20 +2248,18 @@ def test_migration_start_with_new_share_network(self): 'False', 'False', self.new_share_network.id, - None + None, ) self.assertIsNone(result) class TestShareMigrationCancel(TestShare): - def setUp(self): - super(TestShareMigrationCancel, self).setUp() + super().setUp() self._share = manila_fakes.FakeShare.create_one_share( - attrs={ - 'status': 'migrating'}, - methods={'migration_cancel': None}) + attrs={'status': 'migrating'}, methods={'migration_cancel': None} + ) self.shares_mock.get.return_value = self._share self.shares_mock.manage.return_value = self._share @@ -2254,9 +2268,7 @@ def setUp(self): self.cmd = osc_shares.ShareMigrationCancel(self.app, None) def test_migration_cancel(self): - arglist = [ - self._share.id - ] + arglist = [self._share.id] verifylist = [ ('share', self._share.id), ] @@ -2267,14 +2279,12 @@ def test_migration_cancel(self): class TestShareMigrationComplete(TestShare): - def setUp(self): - super(TestShareMigrationComplete, self).setUp() + super().setUp() self._share = manila_fakes.FakeShare.create_one_share( - attrs={ - 'status': 'migrating'}, - methods={'migration_complete': None}) + attrs={'status': 'migrating'}, methods={'migration_complete': None} + ) self.shares_mock.get.return_value = self._share self.shares_mock.manage.return_value = self._share @@ -2283,9 +2293,7 @@ def setUp(self): self.cmd = osc_shares.ShareMigrationComplete(self.app, None) def test_migration_complete(self): - arglist = [ - self._share.id - ] + arglist = [self._share.id] verifylist = [ ('share', self._share.id), ] @@ -2296,19 +2304,25 @@ def test_migration_complete(self): class TestShareMigrationShow(TestShare): - def setUp(self): - super(TestShareMigrationShow, self).setUp() + super().setUp() self._share = manila_fakes.FakeShare.create_one_share( attrs={ 'status': 'available', - 'task_state': 'migration_in_progress'}, - methods={'migration_get_progress': ("", - {'total_progress': 0, 'task_state': - 'migration_in_progress', - 'details': {}}) - }) + 'task_state': 'migration_in_progress', + }, + methods={ + 'migration_get_progress': ( + "", + { + 'total_progress': 0, + 'task_state': 'migration_in_progress', + 'details': {}, + }, + ) + }, + ) self.shares_mock.get.return_value = self._share self.shares_mock.manage.return_value = self._share @@ -2317,9 +2331,7 @@ def setUp(self): self.cmd = osc_shares.ShareMigrationShow(self.app, None) def test_migration_show(self): - arglist = [ - self._share.id - ] + arglist = [self._share.id] verifylist = [ ('share', self._share.id), ] @@ -2329,9 +2341,8 @@ def test_migration_show(self): class TestShareRestore(TestShare): - def setUp(self): - super(TestShareRestore, self).setUp() + super().setUp() self.share = manila_fakes.FakeShare.create_one_share( methods={'restore': None} @@ -2340,12 +2351,8 @@ def setUp(self): self.cmd = osc_shares.RestoreShare(self.app, None) def test_share_restore(self): - arglist = [ - self.share.name - ] - verifylist = [ - ('share', [self.share.name]) - ] + arglist = [self.share.name] + verifylist = [('share', [self.share.name])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) @@ -2354,13 +2361,10 @@ def test_share_restore(self): self.assertIsNone(result) def test_share_restore_exception(self): - arglist = [ - self.share.name - ] - verifylist = [ - ('share', [self.share.name]) - ] + arglist = [self.share.name] + verifylist = [('share', [self.share.name])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.share.restore.side_effect = Exception() self.assertRaises( - osc_exceptions.CommandError, self.cmd.take_action, parsed_args) + osc_exceptions.CommandError, self.cmd.take_action, parsed_args + ) diff --git a/manilaclient/tests/unit/osc/v2/test_share_access_rules.py b/manilaclient/tests/unit/osc/v2/test_share_access_rules.py index 3447df19..2fe59883 100644 --- a/manilaclient/tests/unit/osc/v2/test_share_access_rules.py +++ b/manilaclient/tests/unit/osc/v2/test_share_access_rules.py @@ -31,38 +31,40 @@ 'access_key', 'created_at', 'updated_at', - 'properties' + 'properties', ] class TestShareAccess(manila_fakes.TestShare): - def setUp(self): - super(TestShareAccess, self).setUp() + super().setUp() self.shares_mock = self.app.client_manager.share.shares self.app.client_manager.share.api_version = api_versions.APIVersion( - api_versions.MAX_VERSION) + api_versions.MAX_VERSION + ) self.shares_mock.reset_mock() self.access_rules_mock = ( - self.app.client_manager.share.share_access_rules) + self.app.client_manager.share.share_access_rules + ) self.access_rules_mock.reset_mock() @ddt.ddt class TestShareAccessCreate(TestShareAccess): - def setUp(self): - super(TestShareAccessCreate, self).setUp() + super().setUp() self.share = manila_fakes.FakeShare.create_one_share( - attrs={"is_public": False}, - methods={'allow': None}) + attrs={"is_public": False}, methods={'allow': None} + ) self.shares_mock.get.return_value = self.share self.access_rule = ( manila_fakes.FakeShareAccessRule.create_one_access_rule( - attrs={"share_id": self.share.id})) + attrs={"share_id": self.share.id} + ) + ) self.share.allow.return_value = self.access_rule._info self.access_rules_mock.get.return_value = self.access_rule @@ -93,12 +95,7 @@ def test_share_access_create_user(self): self.assertCountEqual(self.access_rule._info.values(), data) def test_share_access_create_properties(self): - arglist = [ - self.share.id, - 'user', - 'demo', - '--properties', 'key=value' - ] + arglist = [self.share.id, 'user', 'demo', '--properties', 'key=value'] verifylist = [ ("share", self.share.id), ("access_type", "user"), @@ -118,20 +115,19 @@ def test_share_access_create_properties(self): self.assertCountEqual(self.access_rule._info.values(), data) @ddt.data( - {'lock_visibility': True, 'lock_deletion': True, - 'lock_reason': 'testing resource locks'}, + { + 'lock_visibility': True, + 'lock_deletion': True, + 'lock_reason': 'testing resource locks', + }, {'lock_visibility': False, 'lock_deletion': True, 'lock_reason': None}, {'lock_visibility': True, 'lock_deletion': False, 'lock_reason': None}, ) @ddt.unpack - def test_share_access_create_restrict(self, lock_visibility, - lock_deletion, lock_reason): - arglist = [ - self.share.id, - 'user', - 'demo', - '--properties', 'key=value' - ] + def test_share_access_create_restrict( + self, lock_visibility, lock_deletion, lock_reason + ): + arglist = [self.share.id, 'user', 'demo', '--properties', 'key=value'] verifylist = [ ("share", self.share.id), ("access_type", "user"), @@ -161,7 +157,7 @@ def test_share_access_create_restrict(self, lock_visibility, access="demo", access_level=None, metadata={'key': 'value'}, - **allow_call_kwargs + **allow_call_kwargs, ) self.assertEqual(ACCESS_RULE_ATTRIBUTES, columns) self.assertCountEqual(self.access_rule._info.values(), data) @@ -172,14 +168,16 @@ def test_share_access_create_restrict(self, lock_visibility, ) @ddt.unpack def test_share_access_create_restrict_not_available( - self, lock_visibility, lock_deletion): + self, lock_visibility, lock_deletion + ): arglist = [ self.share.id, 'user', 'demo', ] self.app.client_manager.share.api_version = api_versions.APIVersion( - "2.79") + "2.79" + ) verifylist = [ ("share", self.share.id), ("access_type", "user"), @@ -194,17 +192,11 @@ def test_share_access_create_restrict_not_available( arglist.append('--lock-deletion') parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_access_rule_create_access_level(self): - arglist = [ - self.share.id, - 'user', - 'demo', - '--access-level', 'ro' - ] + arglist = [self.share.id, 'user', 'demo', '--access-level', 'ro'] verifylist = [ ("share", self.share.id), ("access_type", "user"), @@ -224,12 +216,7 @@ def test_access_rule_create_access_level(self): self.assertCountEqual(self.access_rule._info.values(), data) def test_share_access_create_wait(self): - arglist = [ - self.share.id, - 'user', - 'demo', - '--wait' - ] + arglist = [self.share.id, 'user', 'demo', '--wait'] verifylist = [ ("share", self.share.id), ("access_type", "user"), @@ -250,12 +237,7 @@ def test_share_access_create_wait(self): @mock.patch('manilaclient.osc.v2.share_access_rules.LOG') def test_share_access_create_wait_error(self, mock_logger): - arglist = [ - self.share.id, - 'user', - 'demo', - '--wait' - ] + arglist = [self.share.id, 'user', 'demo', '--wait'] verifylist = [ ("share", self.share.id), ("access_type", "user"), @@ -276,7 +258,8 @@ def test_share_access_create_wait_error(self, mock_logger): ) mock_logger.error.assert_called_with( - "ERROR: Share access rule is in error state.") + "ERROR: Share access rule is in error state." + ) self.assertEqual(ACCESS_RULE_ATTRIBUTES, columns) self.assertCountEqual(self.access_rule._info.values(), data) @@ -284,26 +267,25 @@ def test_share_access_create_wait_error(self, mock_logger): @ddt.ddt class TestShareAccessDelete(TestShareAccess): - def setUp(self): - super(TestShareAccessDelete, self).setUp() + super().setUp() self.share = manila_fakes.FakeShare.create_one_share( - methods={'deny': None}) + methods={'deny': None} + ) self.shares_mock.get.return_value = self.share self.access_rule = ( manila_fakes.FakeShareAccessRule.create_one_access_rule( - attrs={"share_id": self.share.id})) + attrs={"share_id": self.share.id} + ) + ) # Get the command object to test self.cmd = osc_share_access_rules.ShareAccessDeny(self.app, None) @ddt.data(True, False) def test_share_access_delete(self, unrestrict): - arglist = [ - self.share.id, - self.access_rule.id - ] + arglist = [self.share.id, self.access_rule.id] verifylist = [ ("share", self.share.id), ("id", self.access_rule.id), @@ -316,35 +298,26 @@ def test_share_access_delete(self, unrestrict): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.shares_mock.get.assert_called_with(self.share.id) - self.share.deny.assert_called_with( - self.access_rule.id, **deny_kwargs) + self.share.deny.assert_called_with(self.access_rule.id, **deny_kwargs) self.assertIsNone(result) def test_share_access_delete_unrestrict_not_available(self): self.app.client_manager.share.api_version = api_versions.APIVersion( - "2.79") - arglist = [ - self.share.id, - self.access_rule.id, - "--unrestrict" - ] + "2.79" + ) + arglist = [self.share.id, self.access_rule.id, "--unrestrict"] verifylist = [ ("share", self.share.id), ("id", self.access_rule.id), - ("unrestrict", True) + ("unrestrict", True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_share_access_delete_wait(self): - arglist = [ - self.share.id, - self.access_rule.id, - '--wait' - ] + arglist = [self.share.id, self.access_rule.id, '--wait'] verifylist = [ ("share", self.share.id), ("id", self.access_rule.id), @@ -357,34 +330,26 @@ def test_share_access_delete_wait(self): result = self.cmd.take_action(parsed_args) self.shares_mock.get.assert_called_with(self.share.id) - self.share.deny.assert_called_with( - self.access_rule.id) + self.share.deny.assert_called_with(self.access_rule.id) self.assertIsNone(result) def test_share_access_delete_wait_error(self): - arglist = [ - self.share.id, - self.access_rule.id, - '--wait' - ] + arglist = [self.share.id, self.access_rule.id, '--wait'] verifylist = [ ("share", self.share.id), ("id", self.access_rule.id), - ('wait', True) + ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch('osc_lib.utils.wait_for_delete', return_value=False): self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args + exceptions.CommandError, self.cmd.take_action, parsed_args ) @ddt.ddt class TestShareAccessList(TestShareAccess): - access_rules_columns = [ 'ID', 'Access Type', @@ -393,62 +358,56 @@ class TestShareAccessList(TestShareAccess): 'State', 'Access Key', 'Created At', - 'Updated At' + 'Updated At', ] def setUp(self): - super(TestShareAccessList, self).setUp() + super().setUp() self.share = manila_fakes.FakeShare.create_one_share() self.access_rule_1 = ( manila_fakes.FakeShareAccessRule.create_one_access_rule( - attrs={"share_id": self.share.id})) + attrs={"share_id": self.share.id} + ) + ) self.access_rule_2 = ( manila_fakes.FakeShareAccessRule.create_one_access_rule( - attrs={"share_id": self.share.id, "access_to": "admin"})) + attrs={"share_id": self.share.id, "access_to": "admin"} + ) + ) self.access_rules = [self.access_rule_1, self.access_rule_2] self.shares_mock.get.return_value = self.share self.access_rules_mock.access_list.return_value = self.access_rules - self.values_list = (oscutils.get_dict_properties( - a._info, self.access_rules_columns) for a in self.access_rules) + self.values_list = ( + oscutils.get_dict_properties(a._info, self.access_rules_columns) + for a in self.access_rules + ) # Get the command object to test self.cmd = osc_share_access_rules.ListShareAccess(self.app, None) def test_access_rules_list(self): - arglist = [ - self.share.id - ] - verifylist = [ - ("share", self.share.id) - ] + arglist = [self.share.id] + verifylist = [("share", self.share.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.shares_mock.get.assert_called_with(self.share.id) - self.access_rules_mock.access_list.assert_called_with( - self.share, - {}) + self.access_rules_mock.access_list.assert_called_with(self.share, {}) self.assertEqual(self.access_rules_columns, columns) self.assertEqual(tuple(self.values_list), tuple(data)) def test_access_rules_list_filter_properties(self): - arglist = [ - self.share.id, - '--properties', 'key=value' - ] - verifylist = [ - ("share", self.share.id), - ('properties', ['key=value']) - ] + arglist = [self.share.id, '--properties', 'key=value'] + verifylist = [("share", self.share.id), ('properties', ['key=value'])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.shares_mock.get.assert_called_with(self.share.id) self.access_rules_mock.access_list.assert_called_with( - self.share, - {'metadata': {'key': 'value'}}) + self.share, {'metadata': {'key': 'value'}} + ) self.assertEqual(self.access_rules_columns, columns) self.assertEqual(tuple(self.values_list), tuple(data)) @@ -475,8 +434,8 @@ def test_access_rules_list_access_filters(self, filters): self.shares_mock.get.assert_called_with(self.share.id) self.access_rules_mock.access_list.assert_called_with( - self.share, - filters) + self.share, filters + ) self.assertEqual(self.access_rules_columns, columns) self.assertEqual(tuple(self.values_list), tuple(data)) @@ -486,7 +445,8 @@ def test_access_rules_list_access_filters(self, filters): ) def test_access_rules_list_access_filters_command_error(self, filters): self.app.client_manager.share.api_version = api_versions.APIVersion( - "2.81") + "2.81" + ) arglist = [ self.share.id, ] @@ -500,32 +460,28 @@ def test_access_rules_list_access_filters_command_error(self, filters): verifylist.append((filter_key, filter_value)) parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestShareAccessShow(TestShareAccess): - def setUp(self): - super(TestShareAccessShow, self).setUp() + super().setUp() self.share = manila_fakes.FakeShare.create_one_share() self.access_rule = ( manila_fakes.FakeShareAccessRule.create_one_access_rule( - attrs={"share_id": self.share.id})) + attrs={"share_id": self.share.id} + ) + ) self.access_rules_mock.get.return_value = self.access_rule # Get the command object to test self.cmd = osc_share_access_rules.ShowShareAccess(self.app, None) def test_access_rule_show(self): - arglist = [ - self.access_rule.id - ] - verifylist = [ - ("access_id", self.access_rule.id) - ] + arglist = [self.access_rule.id] + verifylist = [("access_id", self.access_rule.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) @@ -535,81 +491,74 @@ def test_access_rule_show(self): class TestShareAccessSet(TestShareAccess): - def setUp(self): - super(TestShareAccessSet, self).setUp() + super().setUp() self.share = manila_fakes.FakeShare.create_one_share() self.access_rule = ( manila_fakes.FakeShareAccessRule.create_one_access_rule( - attrs={"share_id": self.share.id})) + attrs={"share_id": self.share.id} + ) + ) self.access_rules_mock.get.return_value = self.access_rule # Get the command object to test self.cmd = osc_share_access_rules.SetShareAccess(self.app, None) def test_access_rule_set_metadata(self): - arglist = [ - self.access_rule.id, - '--property', 'key1=value1' - ] + arglist = [self.access_rule.id, '--property', 'key1=value1'] verifylist = [ ("access_id", self.access_rule.id), - ('property', {'key1': 'value1'}) + ('property', {'key1': 'value1'}), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.access_rules_mock.set_metadata.assert_called_with( - self.access_rule, - {'key1': 'value1'}) + self.access_rule, {'key1': 'value1'} + ) self.assertIsNone(result) def test_access_rule_set_access_level(self): - arglist = [ - self.access_rule.id, - '--access-level', 'ro' - ] + arglist = [self.access_rule.id, '--access-level', 'ro'] verifylist = [ ("access_id", self.access_rule.id), - ('access_level', 'ro') + ('access_level', 'ro'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.access_rules_mock.set_access_level.assert_called_with( - self.access_rule, - 'ro') + self.access_rule, 'ro' + ) self.assertIsNone(result) class TestShareAccessUnset(TestShareAccess): - def setUp(self): - super(TestShareAccessUnset, self).setUp() + super().setUp() self.share = manila_fakes.FakeShare.create_one_share() self.access_rule = ( manila_fakes.FakeShareAccessRule.create_one_access_rule( - attrs={"share_id": self.share.id})) + attrs={"share_id": self.share.id} + ) + ) self.access_rules_mock.get.return_value = self.access_rule # Get the command object to test self.cmd = osc_share_access_rules.UnsetShareAccess(self.app, None) def test_access_rule_unset(self): - arglist = [ - self.access_rule.id, - '--property', 'key1' - ] + arglist = [self.access_rule.id, '--property', 'key1'] verifylist = [ ("access_id", self.access_rule.id), - ('property', ['key1']) + ('property', ['key1']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.access_rules_mock.unset_metadata.assert_called_with( - self.access_rule, - ['key1']) + self.access_rule, ['key1'] + ) self.assertIsNone(result) diff --git a/manilaclient/tests/unit/osc/v2/test_share_backups.py b/manilaclient/tests/unit/osc/v2/test_share_backups.py index 5c8cdb65..c9ca24d1 100644 --- a/manilaclient/tests/unit/osc/v2/test_share_backups.py +++ b/manilaclient/tests/unit/osc/v2/test_share_backups.py @@ -21,9 +21,8 @@ class TestShareBackup(manila_fakes.TestShare): - def setUp(self): - super(TestShareBackup, self).setUp() + super().setUp() self.shares_mock = self.app.client_manager.share.shares self.shares_mock.reset_mock() @@ -31,21 +30,20 @@ def setUp(self): self.backups_mock = self.app.client_manager.share.share_backups self.backups_mock.reset_mock() self.app.client_manager.share.api_version = api_versions.APIVersion( - MAX_VERSION) + MAX_VERSION + ) class TestShareBackupCreate(TestShareBackup): - def setUp(self): - super(TestShareBackupCreate, self).setUp() + super().setUp() self.share = manila_fakes.FakeShare.create_one_share() self.shares_mock.get.return_value = self.share - self.share_backup = ( - manila_fakes.FakeShareBackup.create_one_backup( - attrs={'status': 'available'} - )) + self.share_backup = manila_fakes.FakeShareBackup.create_one_backup( + attrs={'status': 'available'} + ) self.backups_mock.create.return_value = self.share_backup self.backups_mock.get.return_value = self.share_backup self.cmd = osc_share_backups.CreateShareBackup(self.app, None) @@ -58,15 +56,15 @@ def test_share_backup_create_missing_args(self): self.assertRaises( osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_backup_create(self): - arglist = [ - self.share.id - ] - verifylist = [ - ('share', self.share.id) - ] + arglist = [self.share.id] + verifylist = [('share', self.share.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) @@ -78,13 +76,10 @@ def test_share_backup_create(self): self.assertCountEqual(self.data, data) def test_share_backup_create_name(self): - arglist = [ - self.share.id, - '--name', "FAKE_SHARE_BACKUP_NAME" - ] + arglist = [self.share.id, '--name', "FAKE_SHARE_BACKUP_NAME"] verifylist = [ ('share', self.share.id), - ('name', "FAKE_SHARE_BACKUP_NAME") + ('name', "FAKE_SHARE_BACKUP_NAME"), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -99,12 +94,10 @@ def test_share_backup_create_name(self): class TestShareBackupDelete(TestShareBackup): - def setUp(self): - super(TestShareBackupDelete, self).setUp() + super().setUp() - self.share_backup = ( - manila_fakes.FakeShareBackup.create_one_backup()) + self.share_backup = manila_fakes.FakeShareBackup.create_one_backup() self.backups_mock.get.return_value = self.share_backup self.cmd = osc_share_backups.DeleteShareBackup(self.app, None) @@ -113,16 +106,17 @@ def test_share_backup_delete_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_backup_delete(self): - arglist = [ - self.share_backup.id - ] - verifylist = [ - ('backup', [self.share_backup.id]) - ] + arglist = [self.share_backup.id] + verifylist = [('backup', [self.share_backup.id])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) @@ -130,39 +124,30 @@ def test_share_backup_delete(self): self.assertIsNone(result) def test_share_backup_delete_multiple(self): - share_backups = ( - manila_fakes.FakeShareBackup.create_share_backups( - count=2)) - arglist = [ - share_backups[0].id, - share_backups[1].id - ] - verifylist = [ - ('backup', [share_backups[0].id, share_backups[1].id]) - ] + share_backups = manila_fakes.FakeShareBackup.create_share_backups( + count=2 + ) + arglist = [share_backups[0].id, share_backups[1].id] + verifylist = [('backup', [share_backups[0].id, share_backups[1].id])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.assertEqual(self.backups_mock.delete.call_count, - len(share_backups)) + self.assertEqual( + self.backups_mock.delete.call_count, len(share_backups) + ) self.assertIsNone(result) def test_share_backup_delete_exception(self): - arglist = [ - self.share_backup.id - ] - verifylist = [ - ('backup', [self.share_backup.id]) - ] + arglist = [self.share_backup.id] + verifylist = [('backup', [self.share_backup.id])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.backups_mock.delete.side_effect = exceptions.CommandError() - self.assertRaises(exceptions.CommandError, - self.cmd.take_action, - parsed_args) + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestShareBackupList(TestShareBackup): - columns = [ 'ID', 'Name', @@ -186,18 +171,22 @@ class TestShareBackupList(TestShareBackup): ] def setUp(self): - super(TestShareBackupList, self).setUp() + super().setUp() self.share = manila_fakes.FakeShare.create_one_share() self.shares_mock.get.return_value = self.share - self.backups_list = ( - manila_fakes.FakeShareBackup.create_share_backups( - count=2)) + self.backups_list = manila_fakes.FakeShareBackup.create_share_backups( + count=2 + ) self.backups_mock.list.return_value = self.backups_list - self.values = (oscutils.get_dict_properties( - i._info, self.columns) for i in self.backups_list) - self.detailed_values = (oscutils.get_dict_properties( - i._info, self.detailed_columns) for i in self.backups_list) + self.values = ( + oscutils.get_dict_properties(i._info, self.columns) + for i in self.backups_list + ) + self.detailed_values = ( + oscutils.get_dict_properties(i._info, self.detailed_columns) + for i in self.backups_list + ) self.cmd = osc_share_backups.ListShareBackup(self.app, None) @@ -210,67 +199,74 @@ def test_share_backup_list(self): self.backups_mock.list.assert_called_with( detailed=0, search_opts={ - 'offset': None, 'limit': None, 'name': None, - 'description': None, 'name~': None, 'description~': None, - 'status': None, 'share_id': None + 'offset': None, + 'limit': None, + 'name': None, + 'description': None, + 'name~': None, + 'description~': None, + 'status': None, + 'share_id': None, }, - sort_key=None, sort_dir=None + sort_key=None, + sort_dir=None, ) self.assertEqual(self.columns, columns) self.assertEqual(list(self.values), list(data)) def test_share_backup_list_detail(self): - arglist = [ - '--detail' - ] - verifylist = [ - ('detail', True) - ] + arglist = ['--detail'] + verifylist = [('detail', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.backups_mock.list.assert_called_with( detailed=1, search_opts={ - 'offset': None, 'limit': None, 'name': None, - 'description': None, 'name~': None, 'description~': None, - 'status': None, 'share_id': None + 'offset': None, + 'limit': None, + 'name': None, + 'description': None, + 'name~': None, + 'description~': None, + 'status': None, + 'share_id': None, }, - sort_key=None, sort_dir=None + sort_key=None, + sort_dir=None, ) self.assertEqual(self.detailed_columns, columns) self.assertEqual(list(self.detailed_values), list(data)) def test_share_backup_list_for_share(self): - arglist = [ - '--share', self.share.id - ] - verifylist = [ - ('share', self.share.id) - ] + arglist = ['--share', self.share.id] + verifylist = [('share', self.share.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.backups_mock.list.assert_called_with( detailed=0, search_opts={ - 'offset': None, 'limit': None, 'name': None, - 'description': None, 'name~': None, 'description~': None, - 'status': None, 'share_id': self.share.id + 'offset': None, + 'limit': None, + 'name': None, + 'description': None, + 'name~': None, + 'description~': None, + 'status': None, + 'share_id': self.share.id, }, - sort_key=None, sort_dir=None + sort_key=None, + sort_dir=None, ) self.assertEqual(self.columns, columns) self.assertEqual(list(self.values), list(data)) class TestShareBackupShow(TestShareBackup): - def setUp(self): - super(TestShareBackupShow, self).setUp() - self.share_backup = ( - manila_fakes.FakeShareBackup.create_one_backup() - ) + super().setUp() + self.share_backup = manila_fakes.FakeShareBackup.create_one_backup() self.backups_mock.get.return_value = self.share_backup self.cmd = osc_share_backups.ShowShareBackup(self.app, None) self.data = tuple(self.share_backup._info.values()) @@ -282,36 +278,32 @@ def test_share_backup_show_missing_args(self): self.assertRaises( osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_backup_show(self): - arglist = [ - self.share_backup.id - ] - verifylist = [ - ('backup', self.share_backup.id) - ] + arglist = [self.share_backup.id] + verifylist = [('backup', self.share_backup.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) - self.backups_mock.get.assert_called_with( - self.share_backup.id - ) + self.backups_mock.get.assert_called_with(self.share_backup.id) self.assertCountEqual(self.columns, columns) self.assertCountEqual(self.data, data) class TestShareBackupRestore(TestShareBackup): - def setUp(self): - super(TestShareBackupRestore, self).setUp() - self.share_backup = ( - manila_fakes.FakeShareBackup.create_one_backup() - ) + super().setUp() + self.share_backup = manila_fakes.FakeShareBackup.create_one_backup() + self.target_share = manila_fakes.FakeShare.create_one_share() self.backups_mock.get.return_value = self.share_backup - self.cmd = osc_share_backups.RestoreShareBackup( - self.app, None) + self.shares_mock.get.return_value = self.target_share + self.cmd = osc_share_backups.RestoreShareBackup(self.app, None) def test_share_backup_restore(self): arglist = [ @@ -325,96 +317,91 @@ def test_share_backup_restore(self): self.backups_mock.restore.assert_called_with(self.share_backup.id) self.assertIsNone(result) + def test_share_backup_restore_to_target(self): + arglist = [ + self.share_backup.id, + '--target-share', + self.target_share.id, + ] + verifylist = [ + ('backup', self.share_backup.id), + ('target_share', self.target_share.id), + ] -class TestShareBackupSet(TestShareBackup): + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + result = self.cmd.take_action(parsed_args) + self.backups_mock.restore.assert_called_with( + self.share_backup.id, target_share_id=self.target_share.id + ) + self.assertIsNone(result) + +class TestShareBackupSet(TestShareBackup): def setUp(self): - super(TestShareBackupSet, self).setUp() - self.share_backup = ( - manila_fakes.FakeShareBackup.create_one_backup() - ) + super().setUp() + self.share_backup = manila_fakes.FakeShareBackup.create_one_backup() self.backups_mock.get.return_value = self.share_backup self.cmd = osc_share_backups.SetShareBackup(self.app, None) def test_set_share_backup_name(self): - arglist = [ - self.share_backup.id, - '--name', "FAKE_SHARE_BACKUP_NAME" - ] + arglist = [self.share_backup.id, '--name', "FAKE_SHARE_BACKUP_NAME"] verifylist = [ ('backup', self.share_backup.id), - ('name', "FAKE_SHARE_BACKUP_NAME") + ('name', "FAKE_SHARE_BACKUP_NAME"), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.backups_mock.update.assert_called_with(self.share_backup, - name=parsed_args.name) + self.backups_mock.update.assert_called_with( + self.share_backup, name=parsed_args.name + ) self.assertIsNone(result) def test_set_backup_status(self): - arglist = [ - self.share_backup.id, - '--status', 'available' - ] + arglist = [self.share_backup.id, '--status', 'available'] verifylist = [ ('backup', self.share_backup.id), - ('status', 'available') + ('status', 'available'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.backups_mock.reset_status.assert_called_with( - self.share_backup, - parsed_args.status) + self.share_backup, parsed_args.status + ) self.assertIsNone(result) class TestShareBackupUnset(TestShareBackup): - def setUp(self): - super(TestShareBackupUnset, self).setUp() + super().setUp() - self.share_backup = ( - manila_fakes.FakeShareBackup.create_one_backup() - ) + self.share_backup = manila_fakes.FakeShareBackup.create_one_backup() self.backups_mock.get.return_value = self.share_backup self.cmd = osc_share_backups.UnsetShareBackup(self.app, None) def test_unset_backup_name(self): - arglist = [ - self.share_backup.id, - '--name' - ] - verifylist = [ - ('backup', self.share_backup.id), - ('name', True) - ] + arglist = [self.share_backup.id, '--name'] + verifylist = [('backup', self.share_backup.id), ('name', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.backups_mock.update.assert_called_with( - self.share_backup, - name=None) + self.share_backup, name=None + ) self.assertIsNone(result) def test_unset_backup_description(self): - arglist = [ - self.share_backup.id, - '--description' - ] - verifylist = [ - ('backup', self.share_backup.id), - ('description', True) - ] + arglist = [self.share_backup.id, '--description'] + verifylist = [('backup', self.share_backup.id), ('description', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.backups_mock.update.assert_called_with( - self.share_backup, - description=None) + self.share_backup, description=None + ) self.assertIsNone(result) diff --git a/manilaclient/tests/unit/osc/v2/test_share_group_snapshots.py b/manilaclient/tests/unit/osc/v2/test_share_group_snapshots.py index ca7c233e..2860cf79 100644 --- a/manilaclient/tests/unit/osc/v2/test_share_group_snapshots.py +++ b/manilaclient/tests/unit/osc/v2/test_share_group_snapshots.py @@ -21,7 +21,8 @@ from manilaclient import api_versions from manilaclient.osc.v2 import ( - share_group_snapshots as osc_share_group_snapshots) + share_group_snapshots as osc_share_group_snapshots, +) from manilaclient.tests.unit.osc import osc_utils from manilaclient.tests.unit.osc.v2 import fakes as manila_fakes @@ -29,42 +30,38 @@ class TestShareGroupSnapshot(manila_fakes.TestShare): - def setUp(self): - super(TestShareGroupSnapshot, self).setUp() + super().setUp() self.groups_mock = self.app.client_manager.share.share_groups self.groups_mock.reset_mock() self.group_snapshot_mocks = ( - self.app.client_manager.share.share_group_snapshots) + self.app.client_manager.share.share_group_snapshots + ) self.group_snapshot_mocks.reset_mock() self.app.client_manager.share.api_version = api_versions.APIVersion( - api_versions.MAX_VERSION) + api_versions.MAX_VERSION + ) class TestCreateShareGroupSnapshot(TestShareGroupSnapshot): - def setUp(self): - super(TestCreateShareGroupSnapshot, self).setUp() + super().setUp() - self.share_group = ( - manila_fakes.FakeShareGroup.create_one_share_group() - ) + self.share_group = manila_fakes.FakeShareGroup.create_one_share_group() self.groups_mock.get.return_value = self.share_group - self.share_group_snapshot = ( - manila_fakes.FakeShareGroupSnapshot - .create_one_share_group_snapshot() - ) + self.share_group_snapshot = manila_fakes.FakeShareGroupSnapshot.create_one_share_group_snapshot() # noqa: E501 self.group_snapshot_mocks.create.return_value = ( - self.share_group_snapshot) - self.group_snapshot_mocks.get.return_value = ( - self.share_group_snapshot) + self.share_group_snapshot + ) + self.group_snapshot_mocks.get.return_value = self.share_group_snapshot self.cmd = osc_share_group_snapshots.CreateShareGroupSnapshot( - self.app, None) + self.app, None + ) self.data = tuple(self.share_group_snapshot._info.values()) self.columns = tuple(self.share_group_snapshot._info.keys()) @@ -75,24 +72,22 @@ def test_share_group_snapshot_create_missing_args(self): self.assertRaises( osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_group_snapshot_create(self): - arglist = [ - self.share_group.id - ] - verifylist = [ - ('share_group', self.share_group.id) - ] + arglist = [self.share_group.id] + verifylist = [('share_group', self.share_group.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.group_snapshot_mocks.create.assert_called_with( - self.share_group, - name=None, - description=None + self.share_group, name=None, description=None ) self.assertCountEqual(self.columns, columns) @@ -101,13 +96,15 @@ def test_share_group_snapshot_create(self): def test_share_group_snapshot_create_options(self): arglist = [ self.share_group.id, - '--name', self.share_group_snapshot.name, - '--description', self.share_group_snapshot.description + '--name', + self.share_group_snapshot.name, + '--description', + self.share_group_snapshot.description, ] verifylist = [ ('share_group', self.share_group.id), ('name', self.share_group_snapshot.name), - ('description', self.share_group_snapshot.description) + ('description', self.share_group_snapshot.description), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -124,14 +121,8 @@ def test_share_group_snapshot_create_options(self): self.assertCountEqual(self.data, data) def test_share_group_snapshot_create_wait(self): - arglist = [ - self.share_group.id, - '--wait' - ] - verifylist = [ - ('share_group', self.share_group.id), - ('wait', True) - ] + arglist = [self.share_group.id, '--wait'] + verifylist = [('share_group', self.share_group.id), ('wait', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -144,20 +135,15 @@ def test_share_group_snapshot_create_wait(self): description=None, ) self.group_snapshot_mocks.get.assert_called_with( - self.share_group_snapshot.id) + self.share_group_snapshot.id + ) self.assertCountEqual(self.columns, columns) self.assertCountEqual(self.data, data) @mock.patch('manilaclient.osc.v2.share_group_snapshots.LOG') def test_share_group_snapshot_create_wait_exception(self, mock_logger): - arglist = [ - self.share_group.id, - '--wait' - ] - verifylist = [ - ('share_group', self.share_group.id), - ('wait', True) - ] + arglist = [self.share_group.id, '--wait'] + verifylist = [('share_group', self.share_group.id), ('wait', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -171,60 +157,57 @@ def test_share_group_snapshot_create_wait_exception(self, mock_logger): ) mock_logger.error.assert_called_with( - "ERROR: Share group snapshot is in error state.") + "ERROR: Share group snapshot is in error state." + ) self.group_snapshot_mocks.get.assert_called_with( - self.share_group_snapshot.id) + self.share_group_snapshot.id + ) self.assertCountEqual(self.columns, columns) self.assertCountEqual(self.data, data) class TestDeleteShareGroupSnapshot(TestShareGroupSnapshot): - def setUp(self): - super(TestDeleteShareGroupSnapshot, self).setUp() + super().setUp() - self.share_group_snapshot = ( - manila_fakes.FakeShareGroupSnapshot - .create_one_share_group_snapshot()) - self.group_snapshot_mocks.get.return_value = ( - self.share_group_snapshot) + self.share_group_snapshot = manila_fakes.FakeShareGroupSnapshot.create_one_share_group_snapshot() # noqa: E501 + self.group_snapshot_mocks.get.return_value = self.share_group_snapshot self.cmd = osc_share_group_snapshots.DeleteShareGroupSnapshot( - self.app, None) + self.app, None + ) def test_share_group_snapshot_delete_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_group_snapshot_delete(self): - arglist = [ - self.share_group_snapshot.id - ] - verifylist = [ - ('share_group_snapshot', [self.share_group_snapshot.id]) - ] + arglist = [self.share_group_snapshot.id] + verifylist = [('share_group_snapshot', [self.share_group_snapshot.id])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.group_snapshot_mocks.delete.assert_called_with( - self.share_group_snapshot, - force=False) + self.share_group_snapshot, force=False + ) self.assertIsNone(result) def test_share_group_snapshot_delete_force(self): - arglist = [ - self.share_group_snapshot.id, - '--force' - ] + arglist = [self.share_group_snapshot.id, '--force'] verifylist = [ ('share_group_snapshot', [self.share_group_snapshot.id]), - ('force', True) + ('force', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -232,54 +215,51 @@ def test_share_group_snapshot_delete_force(self): result = self.cmd.take_action(parsed_args) self.group_snapshot_mocks.delete.assert_called_with( - self.share_group_snapshot, - force=True) + self.share_group_snapshot, force=True + ) self.assertIsNone(result) def test_share_group_snapshot_delete_multiple(self): share_group_snapshots = ( - manila_fakes.FakeShareGroupSnapshot. - create_share_group_snapshots(count=2)) - arglist = [ - share_group_snapshots[0].id, - share_group_snapshots[1].id - ] + manila_fakes.FakeShareGroupSnapshot.create_share_group_snapshots( + count=2 + ) + ) + arglist = [share_group_snapshots[0].id, share_group_snapshots[1].id] verifylist = [ - ('share_group_snapshot', [share_group_snapshots[0].id, ( - share_group_snapshots[1].id)]) + ( + 'share_group_snapshot', + [share_group_snapshots[0].id, (share_group_snapshots[1].id)], + ) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.assertEqual(self.group_snapshot_mocks.delete.call_count, - len(share_group_snapshots)) + self.assertEqual( + self.group_snapshot_mocks.delete.call_count, + len(share_group_snapshots), + ) self.assertIsNone(result) def test_share_group_snapshot_delete_exception(self): - arglist = [ - self.share_group_snapshot.id - ] - verifylist = [ - ('share_group_snapshot', [self.share_group_snapshot.id]) - ] + arglist = [self.share_group_snapshot.id] + verifylist = [('share_group_snapshot', [self.share_group_snapshot.id])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.group_snapshot_mocks.delete.side_effect = ( - exceptions.CommandError()) - self.assertRaises(exceptions.CommandError, - self.cmd.take_action, - parsed_args) + exceptions.CommandError() + ) + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_share_group_snapshot_delete_wait(self): - arglist = [ - self.share_group_snapshot.id, - '--wait' - ] + arglist = [self.share_group_snapshot.id, '--wait'] verifylist = [ ('share_group_snapshot', [self.share_group_snapshot.id]), - ('wait', True) + ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -288,45 +268,38 @@ def test_share_group_snapshot_delete_wait(self): result = self.cmd.take_action(parsed_args) self.group_snapshot_mocks.delete.assert_called_with( - self.share_group_snapshot, - force=False) + self.share_group_snapshot, force=False + ) self.group_snapshot_mocks.get.assert_called_with( - self.share_group_snapshot.id) + self.share_group_snapshot.id + ) self.assertIsNone(result) def test_share_group_snapshot_delete_wait_exception(self): - arglist = [ - self.share_group_snapshot.id, - '--wait' - ] + arglist = [self.share_group_snapshot.id, '--wait'] verifylist = [ ('share_group_snapshot', [self.share_group_snapshot.id]), - ('wait', True) + ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch('osc_lib.utils.wait_for_delete', return_value=False): self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args + exceptions.CommandError, self.cmd.take_action, parsed_args ) class TestShowShareGroupSnapshot(TestShareGroupSnapshot): - def setUp(self): - super(TestShowShareGroupSnapshot, self).setUp() + super().setUp() - self.share_group_snapshot = ( - manila_fakes.FakeShareGroupSnapshot - .create_one_share_group_snapshot()) - self.group_snapshot_mocks.get.return_value = ( - self.share_group_snapshot) + self.share_group_snapshot = manila_fakes.FakeShareGroupSnapshot.create_one_share_group_snapshot() # noqa: E501 + self.group_snapshot_mocks.get.return_value = self.share_group_snapshot self.cmd = osc_share_group_snapshots.ShowShareGroupSnapshot( - self.app, None) + self.app, None + ) self.data = tuple(self.share_group_snapshot._info.values()) self.columns = tuple(self.share_group_snapshot._info.keys()) @@ -337,15 +310,15 @@ def test_share_group_snapshot_show_missing_args(self): self.assertRaises( osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_group_show(self): - arglist = [ - self.share_group_snapshot.id - ] - verifylist = [ - ('share_group_snapshot', self.share_group_snapshot.id) - ] + arglist = [self.share_group_snapshot.id] + verifylist = [('share_group_snapshot', self.share_group_snapshot.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -360,18 +333,15 @@ def test_share_group_show(self): class TestSetShareGroupSnapshot(TestShareGroupSnapshot): - def setUp(self): - super(TestSetShareGroupSnapshot, self).setUp() + super().setUp() - self.share_group_snapshot = ( - manila_fakes.FakeShareGroupSnapshot - .create_one_share_group_snapshot()) - self.group_snapshot_mocks.get.return_value = ( - self.share_group_snapshot) + self.share_group_snapshot = manila_fakes.FakeShareGroupSnapshot.create_one_share_group_snapshot() # noqa: E501 + self.group_snapshot_mocks.get.return_value = self.share_group_snapshot self.cmd = osc_share_group_snapshots.SetShareGroupSnapshot( - self.app, None) + self.app, None + ) self.data = tuple(self.share_group_snapshot._info.values()) self.columns = tuple(self.share_group_snapshot._info.keys()) @@ -379,16 +349,19 @@ def setUp(self): def test_set_share_group_snapshot_name_description(self): group_snapshot_name = 'group-snapshot-name-' + uuid.uuid4().hex group_snapshot_description = ( - 'group-snapshot-description-' + uuid.uuid4().hex) + 'group-snapshot-description-' + uuid.uuid4().hex + ) arglist = [ self.share_group_snapshot.id, - '--name', group_snapshot_name, - '--description', group_snapshot_description + '--name', + group_snapshot_name, + '--description', + group_snapshot_description, ] verifylist = [ ('share_group_snapshot', self.share_group_snapshot.id), ('name', group_snapshot_name), - ('description', group_snapshot_description) + ('description', group_snapshot_description), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -397,79 +370,65 @@ def test_set_share_group_snapshot_name_description(self): self.group_snapshot_mocks.update.assert_called_with( self.share_group_snapshot, name=parsed_args.name, - description=parsed_args.description) + description=parsed_args.description, + ) self.assertIsNone(result) def test_set_share_group_snapshot_status(self): - arglist = [ - self.share_group_snapshot.id, - '--status', 'available' - ] + arglist = [self.share_group_snapshot.id, '--status', 'available'] verifylist = [ ('share_group_snapshot', self.share_group_snapshot.id), - ('status', 'available') + ('status', 'available'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.group_snapshot_mocks.reset_state.assert_called_with( - self.share_group_snapshot, - 'available') + self.share_group_snapshot, 'available' + ) self.assertIsNone(result) def test_set_share_group_snapshot_exception(self): - arglist = [ - self.share_group_snapshot.id, - '--status', 'available' - ] + arglist = [self.share_group_snapshot.id, '--status', 'available'] verifylist = [ ('share_group_snapshot', self.share_group_snapshot.id), - ('status', 'available') + ('status', 'available'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.group_snapshot_mocks.reset_state.side_effect = Exception() self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestUnsetShareGroupSnapshot(TestShareGroupSnapshot): - def setUp(self): - super(TestUnsetShareGroupSnapshot, self).setUp() + super().setUp() - self.share_group_snapshot = ( - manila_fakes.FakeShareGroupSnapshot - .create_one_share_group_snapshot()) - self.group_snapshot_mocks.get.return_value = ( - self.share_group_snapshot) + self.share_group_snapshot = manila_fakes.FakeShareGroupSnapshot.create_one_share_group_snapshot() # noqa: E501 + self.group_snapshot_mocks.get.return_value = self.share_group_snapshot self.cmd = osc_share_group_snapshots.UnsetShareGroupSnapshot( - self.app, None) + self.app, None + ) def test_unset_share_group_snapshot_name_description(self): - arglist = [ - self.share_group_snapshot.id, - '--name', - '--description' - ] + arglist = [self.share_group_snapshot.id, '--name', '--description'] verifylist = [ ('share_group_snapshot', self.share_group_snapshot.id), ('name', True), - ('description', True) + ('description', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.group_snapshot_mocks.update.assert_called_with( - self.share_group_snapshot, - name='', - description='') + self.share_group_snapshot, name='', description='' + ) self.assertIsNone(result) def test_unset_share_group_snapshot_name_exception(self): @@ -486,13 +445,11 @@ def test_unset_share_group_snapshot_name_exception(self): self.group_snapshot_mocks.update.side_effect = Exception() self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestListShareGroupSnapshot(TestShareGroupSnapshot): - columns = [ 'ID', 'Name', @@ -501,22 +458,19 @@ class TestListShareGroupSnapshot(TestShareGroupSnapshot): ] def setUp(self): - super(TestListShareGroupSnapshot, self).setUp() + super().setUp() - self.share_group = ( - manila_fakes.FakeShareGroup.create_one_share_group() - ) + self.share_group = manila_fakes.FakeShareGroup.create_one_share_group() self.groups_mock.get.return_value = self.share_group - self.share_group_snapshot = ( - manila_fakes.FakeShareGroupSnapshot - .create_one_share_group_snapshot({ - 'share_group_id': self.share_group.id - })) + self.share_group_snapshot = manila_fakes.FakeShareGroupSnapshot.create_one_share_group_snapshot( # noqa: E501 + {'share_group_id': self.share_group.id} + ) self.share_group_snapshots_list = [self.share_group_snapshot] self.group_snapshot_mocks.list.return_value = ( - self.share_group_snapshots_list) + self.share_group_snapshots_list + ) self.values = ( oscutils.get_dict_properties(s._info, self.columns) @@ -524,7 +478,8 @@ def setUp(self): ) self.cmd = osc_share_group_snapshots.ListShareGroupSnapshot( - self.app, None) + self.app, None + ) def test_share_group_snapshot_list_no_options(self): arglist = [] @@ -542,7 +497,8 @@ def test_share_group_snapshot_list_no_options(self): 'share_group_id': None, 'limit': None, 'offset': None, - }) + } + ) self.assertEqual(self.columns, columns) self.assertEqual(list(self.values), list(data)) @@ -555,12 +511,13 @@ def test_share_group_snapshot_list_detail_all_projects(self): 'Description', 'Created At', 'Share Group ID', - 'Project ID' + 'Project ID', ] values = ( oscutils.get_dict_properties(s._info, columns_detail) - for s in self.share_group_snapshots_list) + for s in self.share_group_snapshots_list + ) arglist = [ '--detailed', @@ -584,16 +541,20 @@ def test_share_group_snapshot_list_detail_all_projects(self): 'share_group_id': None, 'limit': None, 'offset': None, - }) + } + ) self.assertEqual(columns_detail, columns) self.assertEqual(list(values), list(data)) def test_share_group_snapshot_list_search_options(self): arglist = [ - '--name', self.share_group_snapshot.name, - '--status', self.share_group_snapshot.status, - '--share-group', self.share_group.id, + '--name', + self.share_group_snapshot.name, + '--status', + self.share_group_snapshot.status, + '--share-group', + self.share_group.id, ] verifylist = [ ('name', self.share_group_snapshot.name), @@ -614,35 +575,29 @@ def test_share_group_snapshot_list_search_options(self): 'share_group_id': self.share_group.id, 'limit': None, 'offset': None, - }) + } + ) self.assertEqual(self.columns, columns) self.assertEqual(list(self.values), list(data)) class TestListShareGroupSnapshotMembers(TestShareGroupSnapshot): - columns = [ 'Share ID', 'Size', ] def setUp(self): - super(TestListShareGroupSnapshotMembers, self).setUp() + super().setUp() self.share = manila_fakes.FakeShare.create_one_share() - self.share_group_snapshot = ( - manila_fakes.FakeShareGroupSnapshot - .create_one_share_group_snapshot({ - 'members': [{ - 'share_id': self.share.id, - 'size': self.share.size - }] - })) + self.share_group_snapshot = manila_fakes.FakeShareGroupSnapshot.create_one_share_group_snapshot( # noqa: E501 + {'members': [{'share_id': self.share.id, 'size': self.share.size}]} + ) - self.group_snapshot_mocks.get.return_value = ( - self.share_group_snapshot) + self.group_snapshot_mocks.get.return_value = self.share_group_snapshot self.values = ( oscutils.get_dict_properties(s, self.columns) @@ -650,22 +605,20 @@ def setUp(self): ) self.cmd = osc_share_group_snapshots.ListShareGroupSnapshotMembers( - self.app, None) + self.app, None + ) def test_share_group_snapshot_list_members(self): - arglist = [ - self.share_group_snapshot.id - ] - verifylist = [ - ('share_group_snapshot', self.share_group_snapshot.id) - ] + arglist = [self.share_group_snapshot.id] + verifylist = [('share_group_snapshot', self.share_group_snapshot.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.group_snapshot_mocks.get.assert_called_with( - self.share_group_snapshot.id) + self.share_group_snapshot.id + ) self.assertEqual(self.columns, columns) self.assertEqual(list(self.values), list(data)) diff --git a/manilaclient/tests/unit/osc/v2/test_share_group_type.py b/manilaclient/tests/unit/osc/v2/test_share_group_type.py index 2d311da1..4e56ea36 100644 --- a/manilaclient/tests/unit/osc/v2/test_share_group_type.py +++ b/manilaclient/tests/unit/osc/v2/test_share_group_type.py @@ -35,23 +35,23 @@ class TestShareGroupType(manila_fakes.TestShare): - def setUp(self): - super(TestShareGroupType, self).setUp() + super().setUp() self.sgt_mock = self.app.client_manager.share.share_group_types self.sgt_mock.reset_mock() self.app.client_manager.share.api_version = api_versions.APIVersion( - api_versions.MAX_VERSION) + api_versions.MAX_VERSION + ) class TestShareGroupTypeCreate(TestShareGroupType): - def setUp(self): - super(TestShareGroupTypeCreate, self).setUp() + super().setUp() - self.share_types = ( - manila_fakes.FakeShareType.create_share_types(count=2)) + self.share_types = manila_fakes.FakeShareType.create_share_types( + count=2 + ) formatted_share_types = [] @@ -60,22 +60,23 @@ def setUp(self): self.share_group_type = ( manila_fakes.FakeShareGroupType.create_one_share_group_type( - attrs={ - 'share_types': formatted_share_types - } - )) + attrs={'share_types': formatted_share_types} + ) + ) self.share_group_type_formatted = ( manila_fakes.FakeShareGroupType.create_one_share_group_type( attrs={ 'id': self.share_group_type['id'], 'name': self.share_group_type['name'], - 'share_types': formatted_share_types + 'share_types': formatted_share_types, } - )) + ) + ) formatted_sgt = utils.format_share_group_type( - self.share_group_type_formatted) + self.share_group_type_formatted + ) self.sgt_mock.create.return_value = self.share_group_type self.sgt_mock.get.return_value = self.share_group_type @@ -96,13 +97,16 @@ def test_share_group_type_create_required_args(self): ] verifylist = [ ('name', self.share_group_type.name), - ('share_types', [self.share_types[0].name, - self.share_types[1].name]) + ( + 'share_types', + [self.share_types[0].name, self.share_types[1].name], + ), ] with mock.patch( 'manilaclient.common.apiclient.utils.find_resource', - side_effect=[self.share_types[0], self.share_types[1]]): + side_effect=[self.share_types[0], self.share_types[1]], + ): parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) @@ -112,7 +116,9 @@ def test_share_group_type_create_required_args(self): is_public=True, name=self.share_group_type.name, share_types=[ - self.share_types[0].name, self.share_types[1].name] + self.share_types[0].name, + self.share_types[1].name, + ], ) self.assertCountEqual(self.columns, columns) @@ -124,31 +130,37 @@ def test_share_group_type_create_missing_required_arg(self): arglist = [ self.share_group_type.name, ] - verifylist = [ - ('name', self.share_group_type.name) - ] + verifylist = [('name', self.share_group_type.name)] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_group_type_create_private(self): arglist = [ self.share_group_type.name, self.share_types[0].name, self.share_types[1].name, - '--public', 'False' + '--public', + 'False', ] verifylist = [ ('name', self.share_group_type.name), - ('share_types', [self.share_types[0].name, - self.share_types[1].name]), - ('public', 'False') + ( + 'share_types', + [self.share_types[0].name, self.share_types[1].name], + ), + ('public', 'False'), ] with mock.patch( 'manilaclient.common.apiclient.utils.find_resource', - side_effect=[self.share_types[0], - self.share_types[1]]): + side_effect=[self.share_types[0], self.share_types[1]], + ): parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) @@ -157,32 +169,36 @@ def test_share_group_type_create_private(self): group_specs={}, is_public=False, name=self.share_group_type.name, - share_types=[self.share_types[0].name, - self.share_types[1].name] + share_types=[ + self.share_types[0].name, + self.share_types[1].name, + ], ) self.assertCountEqual(self.columns, columns) self.assertCountEqual(self.data, data) def test_share_group_type_create_group_specs(self): - arglist = [ self.share_group_type.name, self.share_types[0].name, self.share_types[1].name, - '--group-specs', 'consistent_snapshot_support=true' + '--group-specs', + 'consistent_snapshot_support=true', ] verifylist = [ ('name', self.share_group_type.name), - ('share_types', [self.share_types[0].name, - self.share_types[1].name]), - ('group_specs', ['consistent_snapshot_support=true']) + ( + 'share_types', + [self.share_types[0].name, self.share_types[1].name], + ), + ('group_specs', ['consistent_snapshot_support=true']), ] with mock.patch( 'manilaclient.common.apiclient.utils.find_resource', - side_effect=[self.share_types[0], - self.share_types[1]]): + side_effect=[self.share_types[0], self.share_types[1]], + ): parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) @@ -192,7 +208,9 @@ def test_share_group_type_create_group_specs(self): is_public=True, name=self.share_group_type.name, share_types=[ - self.share_types[0].name, self.share_types[1].name] + self.share_types[0].name, + self.share_types[1].name, + ], ) self.assertCountEqual(self.columns, columns) @@ -202,19 +220,24 @@ def test_create_share_group_type(self): arglist = [ self.share_group_type.name, self.share_types[0].name, - self.share_types[1].name + self.share_types[1].name, ] verifylist = [ ('name', self.share_group_type.name), - ('share_types', [self.share_types[0].name, - self.share_types[1].name]) + ( + 'share_types', + [self.share_types[0].name, self.share_types[1].name], + ), ] with mock.patch( 'manilaclient.common.apiclient.utils.find_resource', - side_effect=[self.share_types[0], - self.share_types[1], - self.share_group_type]): + side_effect=[ + self.share_types[0], + self.share_types[1], + self.share_group_type, + ], + ): parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) @@ -222,8 +245,10 @@ def test_create_share_group_type(self): group_specs={}, is_public=True, name=self.share_group_type.name, - share_types=[self.share_types[0].name, - self.share_types[1].name] + share_types=[ + self.share_types[0].name, + self.share_types[1].name, + ], ) self.assertCountEqual(self.columns, columns) @@ -231,34 +256,31 @@ def test_create_share_group_type(self): class TestShareGroupTypeDelete(TestShareGroupType): - def setUp(self): - super(TestShareGroupTypeDelete, self).setUp() + super().setUp() self.share_group_types = ( - manila_fakes.FakeShareGroupType.create_share_group_types(count=2)) + manila_fakes.FakeShareGroupType.create_share_group_types(count=2) + ) self.sgt_mock.delete.return_value = None self.sgt_mock.get = ( manila_fakes.FakeShareGroupType.get_share_group_types( - self.share_group_types)) + self.share_group_types + ) + ) # Get the command object to test self.cmd = osc_share_group_types.DeleteShareGroupType(self.app, None) def test_share_group_type_delete_one(self): - arglist = [ - self.share_group_types[0].name - ] + arglist = [self.share_group_types[0].name] - verifylist = [ - ('share_group_types', [self.share_group_types[0].name]) - ] + verifylist = [('share_group_types', [self.share_group_types[0].name])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.sgt_mock.delete.assert_called_with( - self.share_group_types[0]) + self.sgt_mock.delete.assert_called_with(self.share_group_types[0]) self.assertIsNone(result) def test_share_group_type_delete_multiple(self): @@ -289,16 +311,13 @@ def test_delete_share_group_type_with_exception(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.sgt_mock.delete.side_effect = exceptions.CommandError() self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_delete_share_group_type(self): - arglist = [ - self.share_group_types[0].name - ] + arglist = [self.share_group_types[0].name] - verifylist = [ - ('share_group_types', [self.share_group_types[0].name]) - ] + verifylist = [('share_group_types', [self.share_group_types[0].name])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -309,13 +328,14 @@ def test_delete_share_group_type(self): class TestShareGroupTypeSet(TestShareGroupType): - def setUp(self): - super(TestShareGroupTypeSet, self).setUp() + super().setUp() self.share_group_type = ( manila_fakes.FakeShareGroupType.create_one_share_group_type( - methods={'set_keys': None, 'update': None})) + methods={'set_keys': None, 'update': None} + ) + ) self.sgt_mock.get.return_value = self.share_group_type # Get the command object to test @@ -324,106 +344,106 @@ def setUp(self): def test_share_group_type_set_group_specs(self): arglist = [ self.share_group_type.id, - '--group-specs', 'consistent_snapshot_support=true' + '--group-specs', + 'consistent_snapshot_support=true', ] verifylist = [ ('share_group_type', self.share_group_type.id), - ('group_specs', ['consistent_snapshot_support=true']) + ('group_specs', ['consistent_snapshot_support=true']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.share_group_type.set_keys.assert_called_with( - {'consistent_snapshot_support': 'True'}) + {'consistent_snapshot_support': 'True'} + ) self.assertIsNone(result) def test_share_group_type_set_extra_specs_exception(self): arglist = [ self.share_group_type.id, - '--group-specs', 'snapshot_support=true' + '--group-specs', + 'snapshot_support=true', ] verifylist = [ ('share_group_type', self.share_group_type.id), - ('group_specs', ['snapshot_support=true']) + ('group_specs', ['snapshot_support=true']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.share_group_type.set_keys.side_effect = BadRequest() self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestShareGroupTypeUnset(TestShareGroupType): - def setUp(self): - super(TestShareGroupTypeUnset, self).setUp() + super().setUp() self.share_group_type = ( manila_fakes.FakeShareGroupType.create_one_share_group_type( - methods={'unset_keys': None})) + methods={'unset_keys': None} + ) + ) self.sgt_mock.get.return_value = self.share_group_type # Get the command object to test self.cmd = osc_share_group_types.UnsetShareGroupType(self.app, None) def test_share_group_type_unset_extra_specs(self): - arglist = [ - self.share_group_type.id, - 'consistent_snapshot_support' - ] + arglist = [self.share_group_type.id, 'consistent_snapshot_support'] verifylist = [ ('share_group_type', self.share_group_type.id), - ('group_specs', ['consistent_snapshot_support']) + ('group_specs', ['consistent_snapshot_support']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.share_group_type.unset_keys.assert_called_with( - ['consistent_snapshot_support']) + ['consistent_snapshot_support'] + ) self.assertIsNone(result) def test_share_group_type_unset_exception(self): - arglist = [ - self.share_group_type.id, - 'snapshot_support' - ] + arglist = [self.share_group_type.id, 'snapshot_support'] verifylist = [ ('share_group_type', self.share_group_type.id), - ('group_specs', ['snapshot_support']) + ('group_specs', ['snapshot_support']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.share_group_type.unset_keys.side_effect = NotFound() self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestShareGroupTypeList(TestShareGroupType): - def setUp(self): - super(TestShareGroupTypeList, self).setUp() + super().setUp() self.share_group_types = ( - manila_fakes.FakeShareGroupType.create_share_group_types()) + manila_fakes.FakeShareGroupType.create_share_group_types() + ) self.sgt_mock.list.return_value = self.share_group_types # Get the command object to test self.cmd = osc_share_group_types.ListShareGroupType(self.app, None) - self.values = (oscutils.get_dict_properties( - s._info, COLUMNS) for s in self.share_group_types) + self.values = ( + oscutils.get_dict_properties(s._info, COLUMNS) + for s in self.share_group_types + ) def test_share_group_type_list_no_options(self): arglist = [] - verifylist = [ - ('all', False) - ] + verifylist = [('all', False)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.sgt_mock.list.assert_called_once_with( - search_opts={}, - show_all=False + search_opts={}, show_all=False ) self.assertEqual(COLUMNS, columns) self.assertEqual(list(self.values), list(data)) @@ -432,45 +452,41 @@ def test_share_group_type_list_all(self): arglist = [ '--all', ] - verifylist = [ - ('all', True) - ] + verifylist = [('all', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.sgt_mock.list.assert_called_once_with( - search_opts={}, - show_all=True) + search_opts={}, show_all=True + ) self.assertEqual(COLUMNS, columns) self.assertEqual(list(self.values), list(data)) def test_share_group_type_list_group_specs(self): - arglist = [ - '--group-specs', 'consistent_snapshot_support=true' - ] - verifylist = [ - ('group_specs', ['consistent_snapshot_support=true']) - ] + arglist = ['--group-specs', 'consistent_snapshot_support=true'] + verifylist = [('group_specs', ['consistent_snapshot_support=true'])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.sgt_mock.list.assert_called_once_with( - search_opts={'group_specs': { - 'consistent_snapshot_support': 'True'}}, - show_all=False) + search_opts={ + 'group_specs': {'consistent_snapshot_support': 'True'} + }, + show_all=False, + ) self.assertEqual(COLUMNS, columns) self.assertEqual(list(self.values), list(data)) class TestShareGroupTypeShow(TestShareGroupType): - def setUp(self): - super(TestShareGroupTypeShow, self).setUp() + super().setUp() - self.share_types = ( - manila_fakes.FakeShareType.create_share_types(count=2)) + self.share_types = manila_fakes.FakeShareType.create_share_types( + count=2 + ) formatted_share_types = [] @@ -479,22 +495,23 @@ def setUp(self): self.share_group_type = ( manila_fakes.FakeShareGroupType.create_one_share_group_type( - attrs={ - 'share_types': formatted_share_types - } - )) + attrs={'share_types': formatted_share_types} + ) + ) self.share_group_type_formatted = ( manila_fakes.FakeShareGroupType.create_one_share_group_type( attrs={ 'id': self.share_group_type['id'], 'name': self.share_group_type['name'], - 'share_types': formatted_share_types + 'share_types': formatted_share_types, } - )) + ) + ) formatted_sgt = utils.format_share_group_type( - self.share_group_type_formatted) + self.share_group_type_formatted + ) self.sgt_mock.get.return_value = self.share_group_type @@ -505,12 +522,8 @@ def setUp(self): self.columns = tuple(formatted_sgt.keys()) def test_share_group_type_show(self): - arglist = [ - self.share_group_type.name - ] - verifylist = [ - ("share_group_type", self.share_group_type.name) - ] + arglist = [self.share_group_type.name] + verifylist = [("share_group_type", self.share_group_type.name)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) diff --git a/manilaclient/tests/unit/osc/v2/test_share_group_type_access.py b/manilaclient/tests/unit/osc/v2/test_share_group_type_access.py index fd2000de..95d2b691 100644 --- a/manilaclient/tests/unit/osc/v2/test_share_group_type_access.py +++ b/manilaclient/tests/unit/osc/v2/test_share_group_type_access.py @@ -21,16 +21,17 @@ class TestShareGroupTypeAccess(manila_fakes.TestShare): - def setUp(self): - super(TestShareGroupTypeAccess, self).setUp() + super().setUp() self.type_access_mock = ( - self.app.client_manager.share.share_group_type_access) + self.app.client_manager.share.share_group_type_access + ) self.type_access_mock.reset_mock() self.share_group_types_mock = ( - self.app.client_manager.share.share_group_types) + self.app.client_manager.share.share_group_types + ) self.share_group_types_mock.reset_mock() self.projects_mock = self.app.client_manager.identity.projects @@ -38,9 +39,8 @@ def setUp(self): class TestShareGroupTypeAccessAllow(TestShareGroupTypeAccess): - def setUp(self): - super(TestShareGroupTypeAccessAllow, self).setUp() + super().setUp() self.project = identity_fakes.FakeProject.create_one_project() @@ -58,13 +58,10 @@ def setUp(self): self.cmd = osc_sgta.ShareGroupTypeAccessAllow(self.app, None) def test_share_group_type_access_create(self): - arglist = [ - self.share_group_type.id, - self.project.id - ] + arglist = [self.share_group_type.id, self.project.id] verifylist = [ ('share_group_type', self.share_group_type.id), - ('projects', [self.project.id]) + ('projects', [self.project.id]), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -72,36 +69,33 @@ def test_share_group_type_access_create(self): result = self.cmd.take_action(parsed_args) self.type_access_mock.add_project_access.assert_called_with( - self.share_group_type, self.project.id) + self.share_group_type, self.project.id + ) self.assertIsNone(result) def test_share_group_type_access_create_invalid_project_exception(self): - arglist = [ - self.share_group_type.id, - 'invalid_project_format' - ] + arglist = [self.share_group_type.id, 'invalid_project_format'] verifylist = [ ('share_group_type', self.share_group_type.id), - ('projects', ['invalid_project_format']) + ('projects', ['invalid_project_format']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.type_access_mock.add_project_access.side_effect = BadRequest() self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestShareGroupTypeAccessList(TestShareGroupTypeAccess): - columns = ['Project ID'] data = (('',), ('',)) def setUp(self): - super(TestShareGroupTypeAccessList, self).setUp() + super().setUp() - self.type_access_mock.list.return_value = ( - self.columns, self.data) + self.type_access_mock.list.return_value = (self.columns, self.data) # Get the command object to test self.cmd = osc_sgta.ListShareGroupTypeAccess(self.app, None) @@ -117,15 +111,12 @@ def test_share_group_type_access_list(self): arglist = [ share_group_type.id, ] - verifylist = [ - ('share_group_type', share_group_type.id) - ] + verifylist = [('share_group_type', share_group_type.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) - self.type_access_mock.list.assert_called_once_with( - share_group_type) + self.type_access_mock.list.assert_called_once_with(share_group_type) self.assertEqual(self.columns, columns) self.assertEqual(self.data, tuple(data)) @@ -142,25 +133,25 @@ def test_share_group_type_access_list_public_type(self): arglist = [ share_group_type.id, ] - verifylist = [ - ('share_group_type', share_group_type.id) - ] + verifylist = [('share_group_type', share_group_type.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestShareGroupTypeAccessDeny(TestShareGroupTypeAccess): - def setUp(self): - super(TestShareGroupTypeAccessDeny, self).setUp() + super().setUp() self.project = identity_fakes.FakeProject.create_one_project() self.share_group_type = ( manila_fakes.FakeShareGroupType.create_one_share_group_type( - attrs={'is_public': False})) + attrs={'is_public': False} + ) + ) self.share_group_types_mock.get.return_value = self.share_group_type self.projects_mock.get.return_value = self.project @@ -170,13 +161,10 @@ def setUp(self): self.cmd = osc_sgta.ShareGroupTypeAccessDeny(self.app, None) def test_share_group_type_access_delete(self): - arglist = [ - self.share_group_type.id, - self.project.id - ] + arglist = [self.share_group_type.id, self.project.id] verifylist = [ ('share_group_type', self.share_group_type.id), - ('projects', [self.project.id]) + ('projects', [self.project.id]), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -184,21 +172,20 @@ def test_share_group_type_access_delete(self): result = self.cmd.take_action(parsed_args) self.type_access_mock.remove_project_access.assert_called_with( - self.share_group_type, self.project.id) + self.share_group_type, self.project.id + ) self.assertIsNone(result) def test_share_group_type_access_delete_exception(self): - arglist = [ - self.share_group_type.id, - 'invalid_project_format' - ] + arglist = [self.share_group_type.id, 'invalid_project_format'] verifylist = [ ('share_group_type', self.share_group_type.id), - ('projects', ['invalid_project_format']) + ('projects', ['invalid_project_format']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.type_access_mock.remove_project_access.side_effect = BadRequest() self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) diff --git a/manilaclient/tests/unit/osc/v2/test_share_groups.py b/manilaclient/tests/unit/osc/v2/test_share_groups.py index 1cf721f9..9e244128 100644 --- a/manilaclient/tests/unit/osc/v2/test_share_groups.py +++ b/manilaclient/tests/unit/osc/v2/test_share_groups.py @@ -26,9 +26,8 @@ class TestShareGroup(manila_fakes.TestShare): - def setUp(self): - super(TestShareGroup, self).setUp() + super().setUp() self.groups_mock = self.app.client_manager.share.share_groups self.groups_mock.reset_mock() @@ -37,17 +36,15 @@ def setUp(self): self.share_types_mock.reset_mock() self.app.client_manager.share.api_version = api_versions.APIVersion( - api_versions.MAX_VERSION) + api_versions.MAX_VERSION + ) class TestShareGroupCreate(TestShareGroup): - def setUp(self): - super(TestShareGroupCreate, self).setUp() + super().setUp() - self.share_group = ( - manila_fakes.FakeShareGroup.create_one_share_group() - ) + self.share_group = manila_fakes.FakeShareGroup.create_one_share_group() self.formatted_result = ( manila_fakes.FakeShareGroup.create_one_share_group( attrs={ @@ -55,9 +52,12 @@ def setUp(self): 'created_at': self.share_group.created_at, "project_id": self.share_group.project_id, 'share_group_type_id': ( - self.share_group.share_group_type_id), - 'share_types': '\n'.join(self.share_group.share_types) - })) + self.share_group.share_group_type_id + ), + 'share_types': '\n'.join(self.share_group.share_types), + } + ) + ) self.groups_mock.create.return_value = self.share_group self.groups_mock.get.return_value = self.share_group @@ -82,7 +82,7 @@ def test_share_group_create_no_args(self): share_group_type=None, share_network=None, source_share_group_snapshot=None, - availability_zone=None + availability_zone=None, ) self.assertCountEqual(self.columns, columns) @@ -90,12 +90,14 @@ def test_share_group_create_no_args(self): def test_share_group_create_with_options(self): arglist = [ - '--name', self.share_group.name, - '--description', self.share_group.description + '--name', + self.share_group.name, + '--description', + self.share_group.description, ] verifylist = [ ('name', self.share_group.name), - ('description', self.share_group.description) + ('description', self.share_group.description), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -109,16 +111,14 @@ def test_share_group_create_with_options(self): share_group_type=None, share_network=None, source_share_group_snapshot=None, - availability_zone=None + availability_zone=None, ) self.assertCountEqual(self.columns, columns) self.assertCountEqual(self.data, data) def test_share_group_create_az(self): - arglist = [ - '--availability-zone', self.share_group.availability_zone - ] + arglist = ['--availability-zone', self.share_group.availability_zone] verifylist = [ ('availability_zone', self.share_group.availability_zone) ] @@ -134,23 +134,19 @@ def test_share_group_create_az(self): share_group_type=None, share_network=None, source_share_group_snapshot=None, - availability_zone=self.share_group.availability_zone + availability_zone=self.share_group.availability_zone, ) self.assertCountEqual(self.columns, columns) self.assertCountEqual(self.data, data) def test_share_group_create_share_types(self): - share_types = manila_fakes.FakeShareType.create_share_types(count=2) self.share_types_mock.get = manila_fakes.FakeShareType.get_share_types( - share_types) - arglist = [ - '--share-types', share_types[0].id, share_types[1].id - ] - verifylist = [ - ('share_types', [share_types[0].id, share_types[1].id]) - ] + share_types + ) + arglist = ['--share-types', share_types[0].id, share_types[1].id] + verifylist = [('share_types', [share_types[0].id, share_types[1].id])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -163,19 +159,15 @@ def test_share_group_create_share_types(self): share_group_type=None, share_network=None, source_share_group_snapshot=None, - availability_zone=None + availability_zone=None, ) self.assertCountEqual(self.columns, columns) self.assertCountEqual(self.data, data) def test_share_group_create_wait(self): - arglist = [ - '--wait' - ] - verifylist = [ - ('wait', True) - ] + arglist = ['--wait'] + verifylist = [('wait', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -188,7 +180,7 @@ def test_share_group_create_wait(self): share_group_type=None, share_network=None, source_share_group_snapshot=None, - availability_zone=None + availability_zone=None, ) self.groups_mock.get.assert_called_with(self.share_group.id) @@ -201,60 +193,43 @@ def test_share_group_create_wait(self): class TestShareGroupDelete(TestShareGroup): - def setUp(self): - super(TestShareGroupDelete, self).setUp() + super().setUp() - self.share_group = ( - manila_fakes.FakeShareGroup.create_one_share_group()) + self.share_group = manila_fakes.FakeShareGroup.create_one_share_group() self.groups_mock.get.return_value = self.share_group self.cmd = osc_share_groups.DeleteShareGroup(self.app, None) def test_share_group_delete(self): - arglist = [ - self.share_group.id - ] - verifylist = [ - ('share_group', [self.share_group.id]) - ] + arglist = [self.share_group.id] + verifylist = [('share_group', [self.share_group.id])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.groups_mock.delete.assert_called_with( - self.share_group, - force=False) + self.share_group, force=False + ) self.assertIsNone(result) def test_share_group_delete_force(self): - arglist = [ - self.share_group.id, - '--force' - ] - verifylist = [ - ('share_group', [self.share_group.id]), - ('force', True) - ] + arglist = [self.share_group.id, '--force'] + verifylist = [('share_group', [self.share_group.id]), ('force', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.groups_mock.delete.assert_called_with( - self.share_group, - force=True) + self.share_group, force=True + ) self.assertIsNone(result) def test_share_group_delete_multiple(self): - share_groups = ( - manila_fakes.FakeShareGroup.create_share_groups( - count=2)) - arglist = [ - share_groups[0].id, - share_groups[1].id - ] + share_groups = manila_fakes.FakeShareGroup.create_share_groups(count=2) + arglist = [share_groups[0].id, share_groups[1].id] verifylist = [ ('share_group', [share_groups[0].id, share_groups[1].id]) ] @@ -262,34 +237,23 @@ def test_share_group_delete_multiple(self): result = self.cmd.take_action(parsed_args) - self.assertEqual(self.groups_mock.delete.call_count, - len(share_groups)) + self.assertEqual(self.groups_mock.delete.call_count, len(share_groups)) self.assertIsNone(result) def test_share_group_delete_exception(self): - arglist = [ - self.share_group.id - ] - verifylist = [ - ('share_group', [self.share_group.id]) - ] + arglist = [self.share_group.id] + verifylist = [('share_group', [self.share_group.id])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.groups_mock.delete.side_effect = exceptions.CommandError() - self.assertRaises(exceptions.CommandError, - self.cmd.take_action, - parsed_args) + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_share_group_delete_wait(self): - arglist = [ - self.share_group.id, - '--wait' - ] - verifylist = [ - ('share_group', [self.share_group.id]), - ('wait', True) - ] + arglist = [self.share_group.id, '--wait'] + verifylist = [('share_group', [self.share_group.id]), ('wait', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -297,39 +261,28 @@ def test_share_group_delete_wait(self): result = self.cmd.take_action(parsed_args) self.groups_mock.delete.assert_called_with( - self.share_group, - force=False) + self.share_group, force=False + ) self.groups_mock.get.assert_called_with(self.share_group.id) self.assertIsNone(result) def test_share_group_delete_wait_exception(self): - arglist = [ - self.share_group.id, - '--wait' - ] - verifylist = [ - ('share_group', [self.share_group.id]), - ('wait', True) - ] + arglist = [self.share_group.id, '--wait'] + verifylist = [('share_group', [self.share_group.id]), ('wait', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch('osc_lib.utils.wait_for_delete', return_value=False): self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args + exceptions.CommandError, self.cmd.take_action, parsed_args ) class TestShareGroupShow(TestShareGroup): - def setUp(self): - super(TestShareGroupShow, self).setUp() + super().setUp() - self.share_group = ( - manila_fakes.FakeShareGroup.create_one_share_group() - ) + self.share_group = manila_fakes.FakeShareGroup.create_one_share_group() self.formatted_result = ( manila_fakes.FakeShareGroup.create_one_share_group( attrs={ @@ -337,9 +290,12 @@ def setUp(self): 'created_at': self.share_group.created_at, "project_id": self.share_group.project_id, 'share_group_type_id': ( - self.share_group.share_group_type_id), - 'share_types': '\n'.join(self.share_group.share_types) - })) + self.share_group.share_group_type_id + ), + 'share_types': '\n'.join(self.share_group.share_types), + } + ) + ) self.groups_mock.get.return_value = self.share_group self.data = tuple(self.formatted_result._info.values()) @@ -348,33 +304,24 @@ def setUp(self): self.cmd = osc_share_groups.ShowShareGroup(self.app, None) def test_share_group_show(self): - arglist = [ - self.share_group.id - ] - verifylist = [ - ('share_group', self.share_group.id) - ] + arglist = [self.share_group.id] + verifylist = [('share_group', self.share_group.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) - self.groups_mock.get.assert_called_with( - self.share_group.id - ) + self.groups_mock.get.assert_called_with(self.share_group.id) self.assertCountEqual(self.columns, columns) self.assertCountEqual(self.data, data) class TestShareGroupSet(TestShareGroup): - def setUp(self): - super(TestShareGroupSet, self).setUp() + super().setUp() - self.share_group = ( - manila_fakes.FakeShareGroup.create_one_share_group() - ) + self.share_group = manila_fakes.FakeShareGroup.create_one_share_group() self.share_group = manila_fakes.FakeShare.create_one_share( methods={"reset_state": None} ) @@ -385,25 +332,23 @@ def setUp(self): def test_set_share_group_name(self): new_name = uuid.uuid4().hex arglist = [ - '--name', new_name, + '--name', + new_name, self.share_group.id, ] - verifylist = [ - ('name', new_name), - ('share_group', self.share_group.id) - - ] + verifylist = [('name', new_name), ('share_group', self.share_group.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.groups_mock.update.assert_called_with( - self.share_group.id, - name=parsed_args.name) + self.share_group.id, name=parsed_args.name + ) def test_set_share_group_description(self): new_description = uuid.uuid4().hex arglist = [ - '--description', new_description, + '--description', + new_description, self.share_group.id, ] verifylist = [ @@ -414,18 +359,15 @@ def test_set_share_group_description(self): self.cmd.take_action(parsed_args) self.groups_mock.update.assert_called_with( - self.share_group.id, - description=parsed_args.description) + self.share_group.id, description=parsed_args.description + ) def test_share_group_set_status(self): new_status = 'available' - arglist = [ - self.share_group.id, - '--status', new_status - ] + arglist = [self.share_group.id, '--status', new_status] verifylist = [ ('share_group', self.share_group.id), - ('status', new_status) + ('status', new_status), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -436,68 +378,52 @@ def test_share_group_set_status(self): def test_share_group_set_status_exception(self): new_status = 'available' - arglist = [ - self.share_group.id, - '--status', new_status - ] + arglist = [self.share_group.id, '--status', new_status] verifylist = [ ('share_group', self.share_group.id), - ('status', new_status) + ('status', new_status), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.share_group.reset_state.side_effect = Exception() self.assertRaises( - osc_exceptions.CommandError, self.cmd.take_action, parsed_args) + osc_exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestShareGroupUnset(TestShareGroup): - def setUp(self): - super(TestShareGroupUnset, self).setUp() + super().setUp() - self.share_group = ( - manila_fakes.FakeShareGroup.create_one_share_group() - ) + self.share_group = manila_fakes.FakeShareGroup.create_one_share_group() self.groups_mock.get.return_value = self.share_group self.cmd = osc_share_groups.UnsetShareGroup(self.app, None) def test_unset_share_group_name(self): - arglist = [ - self.share_group.id, - '--name' - ] - verifylist = [ - ('share_group', self.share_group.id), - ('name', True) - ] + arglist = [self.share_group.id, '--name'] + verifylist = [('share_group', self.share_group.id), ('name', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.groups_mock.update.assert_called_with( - self.share_group, - name=None) + self.groups_mock.update.assert_called_with(self.share_group, name=None) self.assertIsNone(result) def test_unset_share_group_description(self): - arglist = [ - self.share_group.id, - '--description' - ] + arglist = [self.share_group.id, '--description'] verifylist = [ ('share_group', self.share_group.id), - ('description', True) + ('description', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.groups_mock.update.assert_called_with( - self.share_group, - description=None) + self.share_group, description=None + ) self.assertIsNone(result) def test_unset_share_group_name_exception(self): @@ -514,41 +440,35 @@ def test_unset_share_group_name_exception(self): self.groups_mock.update.side_effect = Exception() self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestShareGroupList(TestShareGroup): - - columns = [ - 'id', - 'name', - 'status', - 'description' - ] + columns = ['id', 'name', 'status', 'description'] column_headers = utils.format_column_headers(columns) def setUp(self): - super(TestShareGroupList, self).setUp() + super().setUp() self.new_share_group = ( manila_fakes.FakeShareGroup.create_one_share_group() ) self.groups_mock.list.return_value = [self.new_share_group] - self.share_group = ( - manila_fakes.FakeShareGroup.create_one_share_group()) + self.share_group = manila_fakes.FakeShareGroup.create_one_share_group() self.groups_mock.get.return_value = self.share_group self.share_groups_list = ( - manila_fakes.FakeShareGroup.create_share_groups( - count=2)) + manila_fakes.FakeShareGroup.create_share_groups(count=2) + ) self.groups_mock.list.return_value = self.share_groups_list - self.values = (oscutils.get_dict_properties( - s._info, self.columns) for s in self.share_groups_list) + self.values = ( + oscutils.get_dict_properties(s._info, self.columns) + for s in self.share_groups_list + ) self.cmd = osc_share_groups.ListShareGroup(self.app, None) @@ -560,89 +480,83 @@ def test_share_group_list(self): columns, data = self.cmd.take_action(parsed_args) - self.groups_mock.list.assert_called_with(search_opts={ - 'all_tenants': False, - 'name': None, - 'status': None, - 'share_server_id': None, - 'share_group_type': None, - 'snapshot': None, - 'host': None, - 'share_network': None, - 'project_id': None, - 'limit': None, - 'offset': None, - 'name~': None, - 'description~': None, - 'description': None - }) + self.groups_mock.list.assert_called_with( + search_opts={ + 'all_tenants': False, + 'name': None, + 'status': None, + 'share_server_id': None, + 'share_group_type': None, + 'snapshot': None, + 'host': None, + 'share_network': None, + 'project_id': None, + 'limit': None, + 'offset': None, + 'name~': None, + 'description~': None, + 'description': None, + } + ) self.assertEqual(self.column_headers, columns) self.assertEqual(list(self.values), list(data)) def test_list_share_group_api_version_exception(self): self.app.client_manager.share.api_version = api_versions.APIVersion( - "2.35") + "2.35" + ) - arglist = [ - '--description', 'Description' - ] - verifylist = [ - ('description', 'Description') - ] + arglist = ['--description', 'Description'] + verifylist = [('description', 'Description')] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_list_share_groups_all_projects(self): all_tenants_list = self.column_headers.copy() all_tenants_list.append('Project ID') - list_values = (oscutils.get_dict_properties( - s._info, all_tenants_list) for s in self.share_groups_list) + list_values = ( + oscutils.get_dict_properties(s._info, all_tenants_list) + for s in self.share_groups_list + ) - arglist = [ - '--all-projects' - ] + arglist = ['--all-projects'] - verifylist = [ - ('all_projects', True) - ] + verifylist = [('all_projects', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) - self.groups_mock.list.assert_called_with(search_opts={ - 'all_tenants': True, - 'name': None, - 'status': None, - 'share_server_id': None, - 'share_group_type': None, - 'snapshot': None, - 'host': None, - 'share_network': None, - 'project_id': None, - 'limit': None, - 'offset': None, - 'name~': None, - 'description~': None, - 'description': None - }) + self.groups_mock.list.assert_called_with( + search_opts={ + 'all_tenants': True, + 'name': None, + 'status': None, + 'share_server_id': None, + 'share_group_type': None, + 'snapshot': None, + 'host': None, + 'share_network': None, + 'project_id': None, + 'limit': None, + 'offset': None, + 'name~': None, + 'description~': None, + 'description': None, + } + ) self.assertEqual(all_tenants_list, columns) self.assertEqual(list(list_values), list(data)) def test_share_group_list_name(self): - arglist = [ - '--name', self.new_share_group.name - ] - verifylist = [ - ('name', self.new_share_group.name) - ] + arglist = ['--name', self.new_share_group.name] + verifylist = [('name', self.new_share_group.name)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) @@ -661,7 +575,7 @@ def test_share_group_list_name(self): 'offset': None, 'name~': None, 'description~': None, - 'description': None + 'description': None, } search_opts['name'] = self.new_share_group.name @@ -674,12 +588,8 @@ def test_share_group_list_name(self): self.assertEqual(list(self.values), list(data)) def test_share_group_list_description(self): - arglist = [ - '--description', self.new_share_group.description - ] - verifylist = [ - ('description', self.new_share_group.description) - ] + arglist = ['--description', self.new_share_group.description] + verifylist = [('description', self.new_share_group.description)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) @@ -698,7 +608,7 @@ def test_share_group_list_description(self): 'offset': None, 'name~': None, 'description~': None, - 'description': None + 'description': None, } search_opts['description'] = self.new_share_group.description @@ -712,7 +622,8 @@ def test_share_group_list_description(self): def test_share_group_list_status(self): arglist = [ - '--status', self.new_share_group.status, + '--status', + self.new_share_group.status, ] verifylist = [ ('status', self.new_share_group.status), @@ -735,7 +646,7 @@ def test_share_group_list_status(self): 'offset': None, 'name~': None, 'description~': None, - 'description': None + 'description': None, } search_opts['status'] = self.new_share_group.status @@ -749,8 +660,10 @@ def test_share_group_list_status(self): def test_share_group_list_marker_and_limit(self): arglist = [ - "--marker", self.new_share_group.id, - "--limit", "2", + "--marker", + self.new_share_group.id, + "--limit", + "2", ] verifylist = [ ('marker', self.new_share_group.id), @@ -774,7 +687,7 @@ def test_share_group_list_marker_and_limit(self): 'offset': self.new_share_group.id, 'name~': None, 'description~': None, - 'description': None + 'description': None, } self.groups_mock.list.assert_called_once_with( @@ -786,13 +699,19 @@ def test_share_group_list_marker_and_limit(self): def test_share_group_list_negative_limit(self): arglist = [ - "--limit", "-2", + "--limit", + "-2", ] verifylist = [ ("limit", -2), ] - self.assertRaises(osc_utils.ParserException, self.check_parser, - self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) # TODO(archanaserver): Add test cases for share-server-id, # share-group-type, snapshot, share-network and source- diff --git a/manilaclient/tests/unit/osc/v2/test_share_instance_export_locations.py b/manilaclient/tests/unit/osc/v2/test_share_instance_export_locations.py index 7f5b82e3..1017b42d 100644 --- a/manilaclient/tests/unit/osc/v2/test_share_instance_export_locations.py +++ b/manilaclient/tests/unit/osc/v2/test_share_instance_export_locations.py @@ -15,18 +15,17 @@ from osc_lib import utils as osc_lib_utils -from manilaclient.osc.v2 \ - import share_instance_export_locations \ - as osc_share_instance_export_locations +from manilaclient.osc.v2 import ( + share_instance_export_locations as osc_share_instance_export_locations, +) from manilaclient.tests.unit.osc import osc_utils from manilaclient.tests.unit.osc.v2 import fakes as manila_fakes class TestShareInstanceExportLocation(manila_fakes.TestShare): - def setUp(self): - super(TestShareInstanceExportLocation, self).setUp() + super().setUp() self.instances_mock = self.app.client_manager.share.share_instances self.instances_mock.reset_mock() @@ -39,7 +38,6 @@ def setUp(self): class TestShareInstanceExportLocationList(TestShareInstanceExportLocation): - column_headers = [ 'ID', 'Path', @@ -48,27 +46,25 @@ class TestShareInstanceExportLocationList(TestShareInstanceExportLocation): ] def setUp(self): - super(TestShareInstanceExportLocationList, self).setUp() + super().setUp() self.instance = ( manila_fakes.FakeShareInstance.create_one_share_instance() ) self.instances_mock.get.return_value = self.instance - self.instance_export_locations = ( - manila_fakes.FakeShareExportLocation. - create_share_export_locations() - ) - self.instance_export_locations_mock.list.return_value = \ + self.instance_export_locations = manila_fakes.FakeShareExportLocation.create_share_export_locations() # noqa: E501 + self.instance_export_locations_mock.list.return_value = ( self.instance_export_locations + ) - self.data = (osc_lib_utils.get_dict_properties( - i._info, self.column_headers) - for i in self.instance_export_locations) + self.data = ( + osc_lib_utils.get_dict_properties(i._info, self.column_headers) + for i in self.instance_export_locations + ) - self.cmd = ( - osc_share_instance_export_locations. - ShareInstanceListExportLocation(self.app, None) + self.cmd = osc_share_instance_export_locations.ShareInstanceListExportLocation( # noqa: E501 + self.app, None ) def test_share_instance_export_locations_list_missing_args(self): @@ -77,28 +73,25 @@ def test_share_instance_export_locations_list_missing_args(self): self.assertRaises( osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_instance_export_locations_list(self): - arglist = [ - self.instance.id - ] + arglist = [self.instance.id] - verifylist = [ - ('instance', self.instance.id) - ] + verifylist = [('instance', self.instance.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) - self.instances_mock.get.assert_called_with( - self.instance.id - ) + self.instances_mock.get.assert_called_with(self.instance.id) self.instance_export_locations_mock.list.assert_called_with( - self.instance, - search_opts=None + self.instance, search_opts=None ) self.assertCountEqual(self.column_headers, columns) @@ -106,25 +99,23 @@ def test_share_instance_export_locations_list(self): class TestShareInstanceExportLocationShow(TestShareInstanceExportLocation): - def setUp(self): - super(TestShareInstanceExportLocationShow, self).setUp() + super().setUp() self.share_instance_export_locations = ( - manila_fakes.FakeShareExportLocation. - create_one_export_location() + manila_fakes.FakeShareExportLocation.create_one_export_location() ) - self.instance_export_locations_mock.get.return_value = \ + self.instance_export_locations_mock.get.return_value = ( self.share_instance_export_locations + ) self.instance = ( manila_fakes.FakeShareInstance.create_one_share_instance() ) self.instances_mock.get.return_value = self.instance - self.cmd = ( - osc_share_instance_export_locations. - ShareInstanceShowExportLocation(self.app, None) + self.cmd = osc_share_instance_export_locations.ShareInstanceShowExportLocation( # noqa: E501 + self.app, None ) self.data = tuple(self.share_instance_export_locations._info.values()) @@ -136,7 +127,11 @@ def test_share_instance_export_locations_show_missing_args(self): self.assertRaises( osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_instance_export_locations_show(self): arglist = [ @@ -146,20 +141,17 @@ def test_share_instance_export_locations_show(self): verifylist = [ ('instance', self.instance.id), - ('export_location', self.share_instance_export_locations.id) + ('export_location', self.share_instance_export_locations.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) - self.instances_mock.get.assert_called_with( - self.instance.id - ) + self.instances_mock.get.assert_called_with(self.instance.id) self.instance_export_locations_mock.get.assert_called_with( - self.instance.id, - self.share_instance_export_locations.id + self.instance.id, self.share_instance_export_locations.id ) self.assertCountEqual(self.columns, columns) diff --git a/manilaclient/tests/unit/osc/v2/test_share_instances.py b/manilaclient/tests/unit/osc/v2/test_share_instances.py index 62b2baf9..271c894f 100644 --- a/manilaclient/tests/unit/osc/v2/test_share_instances.py +++ b/manilaclient/tests/unit/osc/v2/test_share_instances.py @@ -25,9 +25,8 @@ class TestShareInstance(manila_fakes.TestShare): - def setUp(self): - super(TestShareInstance, self).setUp() + super().setUp() self.shares_mock = self.app.client_manager.share.shares self.shares_mock.reset_mock() @@ -36,11 +35,13 @@ def setUp(self): self.instances_mock.reset_mock() self.share_instance_export_locations_mock = ( - self.app.client_manager.share.share_instance_export_locations) + self.app.client_manager.share.share_instance_export_locations + ) self.share_instance_export_locations_mock.reset_mock() self.app.client_manager.share.api_version = api_versions.APIVersion( - api_versions.MAX_VERSION) + api_versions.MAX_VERSION + ) class TestShareInstanceList(TestShareInstance): @@ -57,10 +58,11 @@ class TestShareInstanceList(TestShareInstance): column_headers = utils.format_column_headers(columns) def setUp(self): - super(TestShareInstanceList, self).setUp() + super().setUp() self.instances_list = ( - manila_fakes.FakeShareInstance.create_share_instances(count=2)) + manila_fakes.FakeShareInstance.create_share_instances(count=2) + ) self.instances_mock.list.return_value = self.instances_list self.share = manila_fakes.FakeShare.create_one_share() @@ -69,8 +71,10 @@ def setUp(self): self.shares_mock.list_instances.return_value = self.instances_list self.shares_mock.list_instances.return_value = self.instances_list - self.instance_values = (oscutils.get_dict_properties( - instance._info, self.columns) for instance in self.instances_list) + self.instance_values = ( + oscutils.get_dict_properties(instance._info, self.columns) + for instance in self.instances_list + ) self.cmd = osc_share_instances.ShareInstanceList(self.app, None) @@ -88,12 +92,8 @@ def test_share_instance_list(self): self.assertEqual(list(self.instance_values), list(data)) def test_share_instance_list_by_share(self): - argslist = [ - '--share', self.share['id'] - ] - verifylist = [ - ('share', self.share.id) - ] + argslist = ['--share', self.share['id']] + verifylist = [('share', self.share.id)] parsed_args = self.check_parser(self.cmd, argslist, verifylist) @@ -106,48 +106,40 @@ def test_share_instance_list_by_share(self): def test_share_instance_list_by_export_location(self): fake_export_location = '10.1.1.0:/fake_share_el' - argslist = [ - '--export-location', fake_export_location - ] - verifylist = [ - ('export_location', fake_export_location) - ] + argslist = ['--export-location', fake_export_location] + verifylist = [('export_location', fake_export_location)] parsed_args = self.check_parser(self.cmd, argslist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.instances_mock.list.assert_called_with( - export_location=fake_export_location) + export_location=fake_export_location + ) self.assertEqual(self.column_headers, columns) self.assertEqual(list(self.instance_values), list(data)) def test_share_instance_list_by_export_location_invalid_version(self): fake_export_location = '10.1.1.0:/fake_share_el' - argslist = [ - '--export-location', fake_export_location - ] - verifylist = [ - ('export_location', fake_export_location) - ] - self.app.client_manager.share.api_version = api_versions.APIVersion( - '2.34') + argslist = ['--export-location', fake_export_location] + verifylist = [('export_location', fake_export_location)] + api_version = api_versions.APIVersion('2.34') + self.app.client_manager.share.api_version = api_version parsed_args = self.check_parser(self.cmd, argslist, verifylist) self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestShareInstanceDelete(TestShareInstance): - def setUp(self): - super(TestShareInstanceDelete, self).setUp() + super().setUp() self.share_instance = ( - manila_fakes.FakeShareInstance.create_one_share_instance()) + manila_fakes.FakeShareInstance.create_one_share_instance() + ) self.instances_mock.get.return_value = self.share_instance self.cmd = osc_share_instances.ShareInstanceDelete(self.app, None) @@ -156,70 +148,64 @@ def test_share_instance_delete_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_instance_delete(self): - arglist = [ - self.share_instance.id - ] - verifylist = [ - ('instance', [self.share_instance.id]) - ] + arglist = [self.share_instance.id] + verifylist = [('instance', [self.share_instance.id])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.instances_mock.force_delete.assert_called_with( - self.share_instance) + self.share_instance + ) self.assertIsNone(result) def test_share_instance_delete_multiple(self): share_instances = ( - manila_fakes.FakeShareInstance.create_share_instances(count=2)) + manila_fakes.FakeShareInstance.create_share_instances(count=2) + ) instance_ids = [instance.id for instance in share_instances] arglist = instance_ids verifylist = [('instance', instance_ids)] self.instances_mock.get.side_effect = share_instances - delete_calls = [ - mock.call(instance) for instance in share_instances] + delete_calls = [mock.call(instance) for instance in share_instances] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.instances_mock.force_delete.assert_has_calls(delete_calls) - self.assertEqual(self.instances_mock.force_delete.call_count, - len(share_instances)) + self.assertEqual( + self.instances_mock.force_delete.call_count, len(share_instances) + ) self.assertIsNone(result) def test_share_instance_delete_exception(self): - arglist = [ - self.share_instance.id - ] - verifylist = [ - ('instance', [self.share_instance.id]) - ] + arglist = [self.share_instance.id] + verifylist = [('instance', [self.share_instance.id])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.instances_mock.force_delete.side_effect = ( - exceptions.CommandError()) - self.assertRaises(exceptions.CommandError, - self.cmd.take_action, - parsed_args) + exceptions.CommandError() + ) + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_share_instance_delete_wait(self): - arglist = [ - self.share_instance.id, - '--wait' - ] - verifylist = [ - ('instance', [self.share_instance.id]), - ('wait', True) - ] + arglist = [self.share_instance.id, '--wait'] + verifylist = [('instance', [self.share_instance.id]), ('wait', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -227,46 +213,40 @@ def test_share_instance_delete_wait(self): result = self.cmd.take_action(parsed_args) self.instances_mock.force_delete.assert_called_with( - self.share_instance) + self.share_instance + ) self.instances_mock.get.assert_called_with(self.share_instance.id) self.assertIsNone(result) def test_share_instance_delete_wait_exception(self): - arglist = [ - self.share_instance.id, - '--wait' - ] - verifylist = [ - ('instance', [self.share_instance.id]), - ('wait', True) - ] + arglist = [self.share_instance.id, '--wait'] + verifylist = [('instance', [self.share_instance.id]), ('wait', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch('osc_lib.utils.wait_for_delete', return_value=False): self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args + exceptions.CommandError, self.cmd.take_action, parsed_args ) class TestShareInstanceShow(TestShareInstance): - def setUp(self): - super(TestShareInstanceShow, self).setUp() + super().setUp() self.share_instance = ( manila_fakes.FakeShareInstance.create_one_share_instance() ) self.instances_mock.get.return_value = self.share_instance - self.export_locations = ( - [manila_fakes.FakeShareExportLocation.create_one_export_location() - for i in range(2)]) + self.export_locations = [ + manila_fakes.FakeShareExportLocation.create_one_export_location() + for i in range(2) + ] self.share_instance_export_locations_mock.list.return_value = ( - self.export_locations) + self.export_locations + ) self.cmd = osc_share_instances.ShareInstanceShow(self.app, None) @@ -279,7 +259,11 @@ def test_share_instance_show_missing_args(self): self.assertRaises( osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_instance_show(self): expected_columns = tuple(self.share_instance._info.keys()) @@ -294,34 +278,29 @@ def test_share_instance_show(self): cliutils.convert_dict_list_to_string = mock.Mock() cliutils.convert_dict_list_to_string.return_value = dict( - self.export_locations[0]) + self.export_locations[0] + ) - arglist = [ - self.share_instance.id - ] - verifylist = [ - ('instance', self.share_instance.id) - ] + arglist = [self.share_instance.id] + verifylist = [('instance', self.share_instance.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) - self.instances_mock.get.assert_called_with( - self.share_instance.id - ) + self.instances_mock.get.assert_called_with(self.share_instance.id) self.assertCountEqual(expected_columns, columns) self.assertCountEqual(expected_data_dic, data) class TestShareInstanceSet(TestShareInstance): - def setUp(self): - super(TestShareInstanceSet, self).setUp() + super().setUp() self.share_instance = ( - manila_fakes.FakeShareInstance.create_one_share_instance()) + manila_fakes.FakeShareInstance.create_one_share_instance() + ) self.instances_mock.get.return_value = self.share_instance @@ -329,41 +308,34 @@ def setUp(self): def test_share_instance_set_status(self): new_status = 'available' - arglist = [ - self.share_instance.id, - '--status', new_status - ] + arglist = [self.share_instance.id, '--status', new_status] verifylist = [ ('instance', self.share_instance.id), - ('status', new_status) + ('status', new_status), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.instances_mock.reset_state.assert_called_with( - self.share_instance, - new_status) + self.share_instance, new_status + ) self.assertIsNone(result) def test_share_instance_set_status_exception(self): new_status = 'available' - arglist = [ - self.share_instance.id, - '--status', new_status - ] + arglist = [self.share_instance.id, '--status', new_status] verifylist = [ ('instance', self.share_instance.id), - ('status', new_status) + ('status', new_status), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.instances_mock.reset_state.side_effect = Exception() self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_share_instance_set_nothing_defined(self): arglist = [ @@ -375,6 +347,5 @@ def test_share_instance_set_nothing_defined(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) diff --git a/manilaclient/tests/unit/osc/v2/test_share_limits.py b/manilaclient/tests/unit/osc/v2/test_share_limits.py index d70cb5f8..4a80aa80 100644 --- a/manilaclient/tests/unit/osc/v2/test_share_limits.py +++ b/manilaclient/tests/unit/osc/v2/test_share_limits.py @@ -22,22 +22,21 @@ class TestShareLimits(manila_fakes.TestShare): - def setUp(self): - super(TestShareLimits, self).setUp() + super().setUp() self.share_limits_mock = self.app.client_manager.share.limits self.share_limits_mock.reset_mock() self.app.client_manager.share.api_version = api_versions.APIVersion( - MAX_VERSION) + MAX_VERSION + ) @ddt.ddt class TestShareLimitsShow(TestShareLimits): - def setUp(self): - super(TestShareLimitsShow, self).setUp() + super().setUp() # Get the command object to test self.cmd = osc_share_limits.ShareLimitsShow(self.app, None) @@ -54,9 +53,7 @@ def setUp(self): @ddt.data('absolute', 'rate') def test_limits(self, limit_type): - share_limits = ( - manila_fakes.FakeShareLimits.create_one_share_limit() - ) + share_limits = manila_fakes.FakeShareLimits.create_one_share_limit() self.share_limits_mock.get.return_value = share_limits expected_data = share_limits._info[f"{limit_type}_limit"] @@ -66,28 +63,23 @@ def test_limits(self, limit_type): if limit_type == 'absolute': arglist.append('--absolute') - verifylist.extend([ - ('absolute', True), - ('rate', False) - ]) + verifylist.extend([('absolute', True), ('rate', False)]) else: arglist.append('--rate') - verifylist.extend([ - ('absolute', False), - ('rate', True) - ]) + verifylist.extend([('absolute', False), ('rate', True)]) parsed_args = self.check_parser(self.cmd, arglist, verifylist) actual_columns, actual_data = self.cmd.take_action(parsed_args) - self.assertEqual(getattr(self, f"{limit_type}_limit_columns"), - actual_columns) + self.assertEqual( + getattr(self, f"{limit_type}_limit_columns"), actual_columns + ) if limit_type == 'rate': expected_data_tuple = tuple(expected_data.values()) - self.assertEqual(sorted(expected_data_tuple), - sorted(next(actual_data))) + self.assertEqual( + sorted(expected_data_tuple), sorted(next(actual_data)) + ) else: expected_data_tuple = tuple(expected_data.items()) - self.assertEqual(sorted(expected_data_tuple), - sorted(actual_data)) + self.assertEqual(sorted(expected_data_tuple), sorted(actual_data)) diff --git a/manilaclient/tests/unit/osc/v2/test_share_network_subnets.py b/manilaclient/tests/unit/osc/v2/test_share_network_subnets.py index 3fba08e4..a34757df 100644 --- a/manilaclient/tests/unit/osc/v2/test_share_network_subnets.py +++ b/manilaclient/tests/unit/osc/v2/test_share_network_subnets.py @@ -23,34 +23,34 @@ class TestShareNetworkSubnet(manila_fakes.TestShare): - def setUp(self): - super(TestShareNetworkSubnet, self).setUp() + super().setUp() self.share_networks_mock = self.app.client_manager.share.share_networks self.share_networks_mock.reset_mock() self.share_subnets_mock = ( - self.app.client_manager.share.share_network_subnets) + self.app.client_manager.share.share_network_subnets + ) self.share_subnets_mock.reset_mock() @ddt.ddt class TestShareNetworkSubnetCreate(TestShareNetworkSubnet): - def setUp(self): - super(TestShareNetworkSubnetCreate, self).setUp() + super().setUp() self.share_network = ( - manila_fakes.FakeShareNetwork.create_one_share_network()) + manila_fakes.FakeShareNetwork.create_one_share_network() + ) self.share_networks_mock.get.return_value = self.share_network self.share_network_subnet = ( - manila_fakes.FakeShareNetworkSubnet.create_one_share_subnet()) + manila_fakes.FakeShareNetworkSubnet.create_one_share_subnet() + ) self.share_subnets_mock.create.return_value = self.share_network_subnet - self.cmd = osc_share_subnets.CreateShareNetworkSubnet( - self.app, None) + self.cmd = osc_share_subnets.CreateShareNetworkSubnet(self.app, None) self.data = self.share_network_subnet._info.values() self.columns = self.share_network_subnet._info.keys() @@ -59,8 +59,13 @@ def test_share_network_subnet_create_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_network_subnet_create(self): fake_neutron_net_id = str(uuid.uuid4()) @@ -68,9 +73,12 @@ def test_share_network_subnet_create(self): arglist = [ self.share_network.id, - '--neutron-net-id', fake_neutron_net_id, - '--neutron-subnet-id', fake_neutron_subnet_id, - '--availability-zone', 'nova', + '--neutron-net-id', + fake_neutron_net_id, + '--neutron-subnet-id', + fake_neutron_subnet_id, + '--availability-zone', + 'nova', ] verifylist = [ ('share_network', self.share_network.id), @@ -87,35 +95,145 @@ def test_share_network_subnet_create(self): neutron_subnet_id=fake_neutron_subnet_id, availability_zone='nova', share_network_id=self.share_network.id, - metadata={} + metadata={}, ) self.assertCountEqual(self.columns, columns) self.assertCountEqual(self.data, data) + def test_share_network_subnet_create_valid_neutron_info(self): + fake_neutron_net_id = str(uuid.uuid4()) + fake_neutron_subnet_id = str(uuid.uuid4()) + + neutron_client = mock.Mock() + self.app.client_manager.network = neutron_client + neutron_client.find_network.return_value = mock.Mock( + id=fake_neutron_net_id + ) + neutron_client.find_subnet.return_value = mock.Mock( + id=fake_neutron_subnet_id + ) + + arglist = [ + self.share_network.id, + '--neutron-net-id', + fake_neutron_net_id, + '--neutron-subnet-id', + fake_neutron_subnet_id, + ] + verifylist = [ + ('share_network', self.share_network.id), + ('neutron_net_id', fake_neutron_net_id), + ('neutron_subnet_id', fake_neutron_subnet_id), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + columns, data = self.cmd.take_action(parsed_args) + + neutron_client.find_network.assert_called_once_with( + fake_neutron_net_id, ignore_missing=False + ) + neutron_client.find_subnet.assert_called_once_with( + fake_neutron_subnet_id, ignore_missing=False + ) + self.share_subnets_mock.create.assert_called_once_with( + share_network_id=self.share_network.id, + neutron_net_id=fake_neutron_net_id, + neutron_subnet_id=fake_neutron_subnet_id, + availability_zone=None, + metadata={}, + ) + self.assertCountEqual(self.columns, columns) + self.assertCountEqual(self.data, data) + + def test_share_network_subnet_create_invalid_neutron_network(self): + fake_neutron_net_id = str(uuid.uuid4()) + fake_neutron_net_id = str(uuid.uuid4()) + + neutron_client = mock.Mock() + self.app.client_manager.network = neutron_client + neutron_client.find_network.side_effect = Exception( + "Network not found." + ) + + arglist = [ + self.share_network.id, + '--neutron-net-id', + fake_neutron_net_id, + '--neutron-subnet-id', + fake_neutron_net_id, + ] + verifylist = [ + ('share_network', self.share_network.id), + ('neutron_net_id', fake_neutron_net_id), + ('neutron_subnet_id', fake_neutron_net_id), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) + neutron_client.find_network.assert_called_once_with( + fake_neutron_net_id, ignore_missing=False + ) + neutron_client.find_subnet.assert_not_called() + self.share_subnets_mock.create.assert_not_called() + + def test_share_network_subnet_create_invalid_neutron_subnet(self): + fake_neutron_net_id = str(uuid.uuid4()) + fake_neutron_subnet_id = str(uuid.uuid4()) + neutron_client = mock.Mock() + self.app.client_manager.network = neutron_client + neutron_client.find_subnet.side_effect = Exception("Subnet not found.") + arglist = [ + self.share_network.id, + '--neutron-net-id', + fake_neutron_net_id, + '--neutron-subnet-id', + fake_neutron_subnet_id, + ] + verifylist = [ + ('share_network', self.share_network.id), + ('neutron_net_id', fake_neutron_net_id), + ('neutron_subnet_id', fake_neutron_subnet_id), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) + neutron_client.find_network.assert_called_once_with( + fake_neutron_net_id, ignore_missing=False + ) + neutron_client.find_subnet.assert_called_once_with( + fake_neutron_subnet_id, ignore_missing=False + ) + self.share_subnets_mock.create.assert_not_called() + def test_share_network_subnet_create_arg_group_exception(self): fake_neutron_net_id = str(uuid.uuid4()) arglist = [ self.share_network.id, - '--neutron-net-id', fake_neutron_net_id + '--neutron-net-id', + fake_neutron_net_id, ] verifylist = [ ('share_network', self.share_network.id), - ('neutron_net_id', fake_neutron_net_id) + ('neutron_net_id', fake_neutron_net_id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) - self.assertRaises(exceptions.CommandError, - self.cmd.take_action, - parsed_args) + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) - @ddt.data({'check_only': False, 'restart_check': True}, - {'check_only': True, 'restart_check': True}, - {'check_only': True, 'restart_check': False}) + @ddt.data( + {'check_only': False, 'restart_check': True}, + {'check_only': True, 'restart_check': True}, + {'check_only': True, 'restart_check': False}, + ) @ddt.unpack def test_share_network_subnet_create_check_api_version_exception( - self, check_only, restart_check): + self, check_only, restart_check + ): self.app.client_manager.share.api_version = api_versions.APIVersion( '2.69' ) @@ -134,19 +252,18 @@ def test_share_network_subnet_create_check_api_version_exception( parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) @ddt.data(True, False) def test_share_network_subnet_create_check(self, restart_check): self.app.client_manager.share.api_version = api_versions.APIVersion( '2.70' ) - self.share_networks_mock.share_network_subnet_create_check = ( - mock.Mock(return_value=(200, {'compatible': True}))) - arglist = [ - self.share_network.id, - '--check-only' - ] + self.share_networks_mock.share_network_subnet_create_check = mock.Mock( + return_value=(200, {'compatible': True}) + ) + arglist = [self.share_network.id, '--check-only'] verifylist = [ ('share_network', self.share_network.id), ('check_only', True), @@ -158,11 +275,15 @@ def test_share_network_subnet_create_check(self, restart_check): self.cmd.take_action(parsed_args) - (self.share_networks_mock.share_network_subnet_create_check - .assert_called_once_with( - share_network_id=self.share_network.id, neutron_net_id=None, - neutron_subnet_id=None, availability_zone=None, - reset_operation=restart_check)) + ( + self.share_networks_mock.share_network_subnet_create_check.assert_called_once_with( + share_network_id=self.share_network.id, + neutron_net_id=None, + neutron_subnet_id=None, + availability_zone=None, + reset_operation=restart_check, + ) + ) def test_share_network_subnet_create_metadata(self): self.app.client_manager.share.api_version = api_versions.APIVersion( @@ -170,8 +291,10 @@ def test_share_network_subnet_create_metadata(self): ) arglist = [ self.share_network.id, - '--property', 'Manila=zorilla', - '--property', 'Zorilla=manila' + '--property', + 'Manila=zorilla', + '--property', + 'Zorilla=manila', ] verifylist = [ ('share_network', self.share_network.id), @@ -198,39 +321,46 @@ def test_share_network_subnet_create_metadata_api_version_exception(self): ) arglist = [ self.share_network.id, - '--property', 'Manila=zorilla', + '--property', + 'Manila=zorilla', ] verifylist = [ ('share_network', self.share_network.id), - ('property', {'Manila': 'zorilla'}) + ('property', {'Manila': 'zorilla'}), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestShareNetworkSubnetDelete(TestShareNetworkSubnet): - def setUp(self): - super(TestShareNetworkSubnetDelete, self).setUp() + super().setUp() self.share_network = ( - manila_fakes.FakeShareNetwork.create_one_share_network()) + manila_fakes.FakeShareNetwork.create_one_share_network() + ) self.share_networks_mock.get.return_value = self.share_network self.share_network_subnets = ( - manila_fakes.FakeShareNetworkSubnet.create_share_network_subnets()) + manila_fakes.FakeShareNetworkSubnet.create_share_network_subnets() + ) - self.cmd = osc_share_subnets.DeleteShareNetworkSubnet( - self.app, None) + self.cmd = osc_share_subnets.DeleteShareNetworkSubnet(self.app, None) def test_share_network_subnet_delete_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_network_subnets_delete(self): arglist = [ @@ -240,15 +370,22 @@ def test_share_network_subnets_delete(self): ] verifylist = [ ('share_network', self.share_network.id), - ('share_network_subnet', [self.share_network_subnets[0].id, - self.share_network_subnets[1].id]), + ( + 'share_network_subnet', + [ + self.share_network_subnets[0].id, + self.share_network_subnets[1].id, + ], + ), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.assertEqual(self.share_subnets_mock.delete.call_count, - len(self.share_network_subnets)) + self.assertEqual( + self.share_subnets_mock.delete.call_count, + len(self.share_network_subnets), + ) self.assertIsNone(result) def test_share_network_subnet_delete_exception(self): @@ -264,26 +401,26 @@ def test_share_network_subnet_delete_exception(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.share_subnets_mock.delete.side_effect = exceptions.CommandError() - self.assertRaises(exceptions.CommandError, - self.cmd.take_action, - parsed_args) + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestShareNetworkSubnetShow(TestShareNetworkSubnet): - def setUp(self): - super(TestShareNetworkSubnetShow, self).setUp() + super().setUp() self.share_network = ( - manila_fakes.FakeShareNetwork.create_one_share_network()) + manila_fakes.FakeShareNetwork.create_one_share_network() + ) self.share_networks_mock.get.return_value = self.share_network self.share_network_subnet = ( - manila_fakes.FakeShareNetworkSubnet.create_one_share_subnet()) + manila_fakes.FakeShareNetworkSubnet.create_one_share_subnet() + ) self.share_subnets_mock.get.return_value = self.share_network_subnet - self.cmd = osc_share_subnets.ShowShareNetworkSubnet( - self.app, None) + self.cmd = osc_share_subnets.ShowShareNetworkSubnet(self.app, None) self.data = self.share_network_subnet._info.values() self.columns = self.share_network_subnet._info.keys() @@ -292,8 +429,13 @@ def test_share_network_subnet_show_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_network_subnet_show(self): arglist = [ @@ -309,8 +451,7 @@ def test_share_network_subnet_show(self): columns, data = self.cmd.take_action(parsed_args) self.share_subnets_mock.get.assert_called_once_with( - self.share_network.id, - self.share_network_subnet.id + self.share_network.id, self.share_network_subnet.id ) self.assertCountEqual(self.columns, columns) @@ -318,19 +459,19 @@ def test_share_network_subnet_show(self): class TestShareNetworkSubnetSet(TestShareNetworkSubnet): - def setUp(self): - super(TestShareNetworkSubnetSet, self).setUp() + super().setUp() self.share_network = ( - manila_fakes.FakeShareNetwork.create_one_share_network()) + manila_fakes.FakeShareNetwork.create_one_share_network() + ) self.share_networks_mock.get.return_value = self.share_network self.share_network_subnet = ( - manila_fakes.FakeShareNetworkSubnet.create_one_share_subnet()) + manila_fakes.FakeShareNetworkSubnet.create_one_share_subnet() + ) - self.cmd = osc_share_subnets.SetShareNetworkSubnet( - self.app, None) + self.cmd = osc_share_subnets.SetShareNetworkSubnet(self.app, None) def test_set_share_network_subnet_property(self): self.app.client_manager.share.api_version = api_versions.APIVersion( @@ -339,8 +480,10 @@ def test_set_share_network_subnet_property(self): arglist = [ self.share_network.id, self.share_network_subnet.id, - '--property', 'Zorilla=manila', - '--property', 'test=my_test', + '--property', + 'Zorilla=manila', + '--property', + 'test=my_test', ] verifylist = [ ('share_network', self.share_network.id), @@ -352,8 +495,10 @@ def test_set_share_network_subnet_property(self): self.cmd.take_action(parsed_args) self.share_subnets_mock.set_metadata.assert_called_once_with( - self.share_network.id, {'Zorilla': 'manila', 'test': 'my_test'}, - subresource=self.share_network_subnet.id) + self.share_network.id, + {'Zorilla': 'manila', 'test': 'my_test'}, + subresource=self.share_network_subnet.id, + ) def test_set_share_network_subnet_property_exception(self): self.app.client_manager.share.api_version = api_versions.APIVersion( @@ -362,7 +507,8 @@ def test_set_share_network_subnet_property_exception(self): arglist = [ self.share_network.id, self.share_network_subnet.id, - '--property', 'key=1', + '--property', + 'key=1', ] verifylist = [ ('share_network', self.share_network.id), @@ -375,30 +521,33 @@ def test_set_share_network_subnet_property_exception(self): self.cmd.take_action(parsed_args) self.share_subnets_mock.set_metadata.assert_called_once_with( - self.share_network.id, {'key': '1'}, - subresource=self.share_network_subnet.id) + self.share_network.id, + {'key': '1'}, + subresource=self.share_network_subnet.id, + ) self.share_subnets_mock.set_metadata.side_effect = ( - exceptions.BadRequest) + exceptions.BadRequest + ) self.assertRaises( - exceptions.CommandError, self.cmd.take_action, - parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestShareNetworkSubnetUnset(TestShareNetworkSubnet): - def setUp(self): - super(TestShareNetworkSubnetUnset, self).setUp() + super().setUp() self.share_network = ( - manila_fakes.FakeShareNetwork.create_one_share_network()) + manila_fakes.FakeShareNetwork.create_one_share_network() + ) self.share_networks_mock.get.return_value = self.share_network self.share_network_subnet = ( - manila_fakes.FakeShareNetworkSubnet.create_one_share_subnet()) + manila_fakes.FakeShareNetworkSubnet.create_one_share_subnet() + ) - self.cmd = osc_share_subnets.UnsetShareNetworkSubnet( - self.app, None) + self.cmd = osc_share_subnets.UnsetShareNetworkSubnet(self.app, None) def test_unset_share_network_subnet_property(self): self.app.client_manager.share.api_version = api_versions.APIVersion( @@ -407,7 +556,8 @@ def test_unset_share_network_subnet_property(self): arglist = [ self.share_network.id, self.share_network_subnet.id, - '--property', 'Manila', + '--property', + 'Manila', ] verifylist = [ ('share_network', self.share_network.id), @@ -420,8 +570,10 @@ def test_unset_share_network_subnet_property(self): self.cmd.take_action(parsed_args) self.share_subnets_mock.delete_metadata.assert_called_once_with( - self.share_network.id, ['Manila'], - subresource=self.share_network_subnet.id) + self.share_network.id, + ['Manila'], + subresource=self.share_network_subnet.id, + ) def test_unset_share_network_subnet_property_exception(self): self.app.client_manager.share.api_version = api_versions.APIVersion( @@ -430,8 +582,10 @@ def test_unset_share_network_subnet_property_exception(self): arglist = [ self.share_network.id, self.share_network_subnet.id, - '--property', 'Manila', - '--property', 'test', + '--property', + 'Manila', + '--property', + 'test', ] verifylist = [ ('share_network', self.share_network.id), @@ -443,14 +597,25 @@ def test_unset_share_network_subnet_property_exception(self): self.cmd.take_action(parsed_args) - self.share_subnets_mock.delete_metadata.assert_has_calls([ - mock.call(self.share_network.id, ['Manila'], - subresource=self.share_network_subnet.id), - mock.call(self.share_network.id, ['test'], - subresource=self.share_network_subnet.id)]) + self.share_subnets_mock.delete_metadata.assert_has_calls( + [ + mock.call( + self.share_network.id, + ['Manila'], + subresource=self.share_network_subnet.id, + ), + mock.call( + self.share_network.id, + ['test'], + subresource=self.share_network_subnet.id, + ), + ] + ) # 404 Not Found would be raised, if property 'Manila' doesn't exist. self.share_subnets_mock.delete_metadata.side_effect = ( - exceptions.NotFound) + exceptions.NotFound + ) self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) diff --git a/manilaclient/tests/unit/osc/v2/test_share_networks.py b/manilaclient/tests/unit/osc/v2/test_share_networks.py index a66efb7a..d68cee9f 100644 --- a/manilaclient/tests/unit/osc/v2/test_share_networks.py +++ b/manilaclient/tests/unit/osc/v2/test_share_networks.py @@ -37,23 +37,23 @@ class TestShareNetwork(manila_fakes.TestShare): - def setUp(self): - super(TestShareNetwork, self).setUp() + super().setUp() self.share_networks_mock = self.app.client_manager.share.share_networks self.share_networks_mock.reset_mock() self.app.client_manager.share.api_version = api_versions.APIVersion( - api_versions.MAX_VERSION) + api_versions.MAX_VERSION + ) @ddt.ddt class TestShareNetworkCreate(TestShareNetwork): - def setUp(self): - super(TestShareNetworkCreate, self).setUp() + super().setUp() self.share_network = ( - manila_fakes.FakeShareNetwork.create_one_share_network()) + manila_fakes.FakeShareNetwork.create_one_share_network() + ) self.share_networks_mock.create.return_value = self.share_network self.cmd = osc_share_networks.CreateShareNetwork(self.app, None) @@ -64,7 +64,8 @@ def setUp(self): @ddt.data('table', 'yaml') def test_share_network_create_formatter(self, formatter): arglist = [ - '-f', formatter, + '-f', + formatter, ] verifylist = [ ('formatter', formatter), @@ -79,7 +80,8 @@ def test_share_network_create_formatter(self, formatter): name=None, description=None, neutron_net_id=None, - neutron_subnet_id=None) + neutron_subnet_id=None, + ) self.assertCountEqual(self.columns, columns) self.assertCountEqual(expected_data.values(), data) @@ -92,11 +94,16 @@ def test_share_network_create_with_args(self): fake_az.id = str(uuid.uuid4()) arglist = [ - '--name', 'zorilla-net', - '--description', 'fastest-backdoor-network-ever', - '--neutron-net-id', fake_neutron_net_id, - '--neutron-subnet-id', fake_neutron_subnet_id, - '--availability-zone', 'nova', + '--name', + 'zorilla-net', + '--description', + 'fastest-backdoor-network-ever', + '--neutron-net-id', + fake_neutron_net_id, + '--neutron-subnet-id', + fake_neutron_subnet_id, + '--availability-zone', + 'nova', ] verifylist = [ ('name', 'zorilla-net'), @@ -107,8 +114,7 @@ def test_share_network_create_with_args(self): ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) - with mock.patch('osc_lib.utils.find_resource', - return_value=fake_az): + with mock.patch('osc_lib.utils.find_resource', return_value=fake_az): columns, data = self.cmd.take_action(parsed_args) self.share_networks_mock.create.assert_called_once_with( @@ -122,15 +128,101 @@ def test_share_network_create_with_args(self): self.assertCountEqual(self.columns, columns) self.assertCountEqual(self.data, data) + def test_share_network_create_with_valid_neutron_info(self): + fake_neutron_net_id = str(uuid.uuid4()) + fake_neutron_subnet_id = str(uuid.uuid4()) + + neutron_client = mock.Mock() + self.app.client_manager.network = neutron_client + + neutron_client.find_network.return_value = mock.Mock( + id=fake_neutron_net_id + ) + neutron_client.find_subnet.return_value = mock.Mock( + id=fake_neutron_subnet_id + ) + + arglist = [ + '--neutron-net-id', + fake_neutron_net_id, + '--neutron-subnet-id', + fake_neutron_subnet_id, + ] + verifylist = [ + ('neutron_net_id', fake_neutron_net_id), + ('neutron_subnet_id', fake_neutron_subnet_id), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + columns, data = self.cmd.take_action(parsed_args) + + neutron_client.find_network.assert_called_once_with( + fake_neutron_net_id, ignore_missing=False + ) + neutron_client.find_subnet.assert_called_once_with( + fake_neutron_subnet_id, ignore_missing=False + ) + self.share_networks_mock.create.assert_called_once_with( + name=None, + description=None, + neutron_net_id=fake_neutron_net_id, + neutron_subnet_id=fake_neutron_subnet_id, + ) + self.assertCountEqual(self.columns, columns) + self.assertCountEqual(self.data, data) + + def test_share_network_create_with_invalid_neutron_network(self): + fake_neutron_net_id = str(uuid.uuid4()) + + neutron_client = mock.Mock() + self.app.client_manager.network = neutron_client + + neutron_client.find_network.side_effect = Exception( + "Network not found" + ) + + arglist = ['--neutron-net-id', fake_neutron_net_id] + verifylist = [('neutron_net_id', fake_neutron_net_id)] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) + + neutron_client.find_network.assert_called_once_with( + fake_neutron_net_id, ignore_missing=False + ) + self.share_networks_mock.create.assert_not_called() + + def test_share_network_create_with_invalid_neutron_subnet(self): + fake_neutron_subnet_id = str(uuid.uuid4()) + + neutron_client = mock.Mock() + self.app.client_manager.network = neutron_client + + neutron_client.find_subnet.side_effect = Exception("Subnet not found") + + arglist = ['--neutron-subnet-id', fake_neutron_subnet_id] + verifylist = [('neutron_subnet_id', fake_neutron_subnet_id)] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) + + neutron_client.find_subnet.assert_called_once_with( + fake_neutron_subnet_id, ignore_missing=False + ) + self.share_networks_mock.create.assert_not_called() + @ddt.ddt class TestShareNetworkDelete(TestShareNetwork): - def setUp(self): - super(TestShareNetworkDelete, self).setUp() + super().setUp() self.share_network = ( - manila_fakes.FakeShareNetwork.create_one_share_network()) + manila_fakes.FakeShareNetwork.create_one_share_network() + ) self.share_networks_mock.get.return_value = self.share_network @@ -140,15 +232,20 @@ def test_share_network_delete_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) @ddt.data(True, False) def test_share_network_delete_with_wait(self, wait): oscutils.wait_for_delete = mock.Mock(return_value=True) - share_networks = ( - manila_fakes.FakeShareNetwork.create_share_networks( - count=2)) + share_networks = manila_fakes.FakeShareNetwork.create_share_networks( + count=2 + ) arglist = [ share_networks[0].id, share_networks[1].name, @@ -163,19 +260,27 @@ def test_share_network_delete_with_wait(self, wait): parsed_args = self.check_parser(self.cmd, arglist, verifylist) - with mock.patch('osc_lib.utils.find_resource', - side_effect=share_networks): + with mock.patch( + 'osc_lib.utils.find_resource', side_effect=share_networks + ): result = self.cmd.take_action(parsed_args) - self.assertEqual(self.share_networks_mock.delete.call_count, - len(share_networks)) + self.assertEqual( + self.share_networks_mock.delete.call_count, len(share_networks) + ) if wait: - oscutils.wait_for_delete.assert_has_calls([ - mock.call(manager=self.share_networks_mock, - res_id=share_networks[0].id), - mock.call(manager=self.share_networks_mock, - res_id=share_networks[1].id) - ]) + oscutils.wait_for_delete.assert_has_calls( + [ + mock.call( + manager=self.share_networks_mock, + res_id=share_networks[0].id, + ), + mock.call( + manager=self.share_networks_mock, + res_id=share_networks[1].id, + ), + ] + ) self.assertIsNone(result) def test_share_network_delete_exception(self): @@ -189,9 +294,9 @@ def test_share_network_delete_exception(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.share_networks_mock.delete.side_effect = exceptions.CommandError() - self.assertRaises(exceptions.CommandError, - self.cmd.take_action, - parsed_args) + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_share_network_delete_wait_fails(self): oscutils.wait_for_delete = mock.Mock(return_value=False) @@ -204,28 +309,31 @@ def test_share_network_delete_wait_fails(self): ('wait', True), ] - with mock.patch('osc_lib.utils.find_resource', - return_value=self.share_network): + with mock.patch( + 'osc_lib.utils.find_resource', return_value=self.share_network + ): parsed_args = self.check_parser(self.cmd, arglist, verifylist) - self.assertRaises(exceptions.CommandError, - self.cmd.take_action, - parsed_args) + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) self.share_networks_mock.delete.assert_called_once_with( - self.share_network) + self.share_network + ) @ddt.ddt class TestShareNetworkShow(TestShareNetwork): - def setUp(self): - super(TestShareNetworkShow, self).setUp() + super().setUp() self.share_network = ( - manila_fakes.FakeShareNetwork.create_one_share_network()) + manila_fakes.FakeShareNetwork.create_one_share_network() + ) self.share_networks_mock.get.return_value = self.share_network self.security_services_mock = ( - self.app.client_manager.share.security_services) + self.app.client_manager.share.security_services + ) self.cmd = osc_share_networks.ShowShareNetwork(self.app, None) @@ -236,17 +344,23 @@ def test_share_network_show_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) @ddt.data('name', 'id') def test_share_network_show_by(self, attr): network_to_show = getattr(self.share_network, attr) fake_security_service = mock.Mock() fake_security_service.id = str(uuid.uuid4()) - fake_security_service.name = 'security-service-%s' % uuid.uuid4().hex + fake_security_service.name = f'security-service-{uuid.uuid4().hex}' self.security_services_mock.list = mock.Mock( - return_value=[fake_security_service]) + return_value=[fake_security_service] + ) arglist = [ network_to_show, @@ -257,34 +371,36 @@ def test_share_network_show_by(self, attr): parsed_args = self.check_parser(self.cmd, arglist, verifylist) - with mock.patch('osc_lib.utils.find_resource', - return_value=self.share_network) as find_resource: - + with mock.patch( + 'osc_lib.utils.find_resource', return_value=self.share_network + ) as find_resource: columns, data = self.cmd.take_action(parsed_args) find_resource.assert_called_once_with( - self.share_networks_mock, network_to_show) + self.share_networks_mock, network_to_show + ) self.assertCountEqual(self.columns, columns) self.assertCountEqual(self.data, data) @ddt.ddt class TestShareNetworkList(TestShareNetwork): - def setUp(self): - super(TestShareNetworkList, self).setUp() + super().setUp() self.share_networks = ( - manila_fakes.FakeShareNetwork.create_share_networks( - count=2)) - self.share_networks_list = oscutils.sort_items(self.share_networks, - 'name:asc', - str) + manila_fakes.FakeShareNetwork.create_share_networks(count=2) + ) + self.share_networks_list = oscutils.sort_items( + self.share_networks, 'name:asc', str + ) self.share_networks_mock.list.return_value = self.share_networks_list - self.values = (oscutils.get_dict_properties( - s._info, COLUMNS) for s in self.share_networks_list) + self.values = ( + oscutils.get_dict_properties(s._info, COLUMNS) + for s in self.share_networks_list + ) self.expected_search_opts = { 'all_tenants': False, 'project_id': None, @@ -309,20 +425,25 @@ def setUp(self): def test_list_share_networks_with_search_opts(self, with_search_opts): if with_search_opts: arglist = [ - '--name', 'foo', - '--ip-version', '4', - '--description~', 'foo-share-network', + '--name', + 'foo', + '--ip-version', + '4', + '--description~', + 'foo-share-network', ] verifylist = [ ('name', 'foo'), ('ip_version', '4'), ('description~', 'foo-share-network'), ] - self.expected_search_opts.update({ - 'name': 'foo', - 'ip_version': '4', - 'description~': 'foo-share-network', - }) + self.expected_search_opts.update( + { + 'name': 'foo', + 'ip_version': '4', + 'description~': 'foo-share-network', + } + ) else: arglist = [] verifylist = [] @@ -332,7 +453,8 @@ def test_list_share_networks_with_search_opts(self, with_search_opts): columns, data = self.cmd.take_action(parsed_args) self.share_networks_mock.list.assert_called_once_with( - search_opts=self.expected_search_opts) + search_opts=self.expected_search_opts + ) self.assertEqual(COLUMNS, columns) self.assertEqual(list(self.values), list(data)) @@ -340,8 +462,10 @@ def test_list_share_networks_all_projects(self): all_tenants_list = COLUMNS.copy() all_tenants_list.append('Project ID') self.expected_search_opts.update({'all_tenants': True}) - list_values = (oscutils.get_dict_properties( - s._info, all_tenants_list) for s in self.share_networks_list) + list_values = ( + oscutils.get_dict_properties(s._info, all_tenants_list) + for s in self.share_networks_list + ) arglist = [ '--all-projects', @@ -356,14 +480,17 @@ def test_list_share_networks_all_projects(self): columns, data = self.cmd.take_action(parsed_args) self.share_networks_mock.list.assert_called_once_with( - search_opts=self.expected_search_opts) + search_opts=self.expected_search_opts + ) self.assertEqual(all_tenants_list, columns) self.assertEqual(list(list_values), list(data)) def test_list_share_networks_detail(self): - values = (oscutils.get_dict_properties( - s._info, COLUMNS_DETAIL) for s in self.share_networks_list) + values = ( + oscutils.get_dict_properties(s._info, COLUMNS_DETAIL) + for s in self.share_networks_list + ) arglist = [ '--detail', @@ -378,13 +505,15 @@ def test_list_share_networks_detail(self): columns, data = self.cmd.take_action(parsed_args) self.share_networks_mock.list.assert_called_once_with( - search_opts=self.expected_search_opts) + search_opts=self.expected_search_opts + ) self.assertEqual(COLUMNS_DETAIL, columns) self.assertEqual(list(values), list(data)) def test_list_share_networks_api_version_exception(self): self.app.client_manager.share.api_version = api_versions.APIVersion( - "2.35") + "2.35" + ) arglist = [ '--description', @@ -397,19 +526,18 @@ def test_list_share_networks_api_version_exception(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) @ddt.ddt class TestShareNetworkUnset(TestShareNetwork): - def setUp(self): - super(TestShareNetworkUnset, self).setUp() + super().setUp() self.share_network = ( - manila_fakes.FakeShareNetwork.create_one_share_network()) + manila_fakes.FakeShareNetwork.create_one_share_network() + ) self.share_networks_mock.get.return_value = self.share_network self.cmd = osc_share_networks.UnsetShareNetwork(self.app, None) @@ -425,12 +553,14 @@ def test_unset_share_network_name(self): ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) - with mock.patch('osc_lib.utils.find_resource', - return_value=self.share_network): + with mock.patch( + 'osc_lib.utils.find_resource', return_value=self.share_network + ): result = self.cmd.take_action(parsed_args) self.share_networks_mock.update.assert_called_once_with( - self.share_network, name='') + self.share_network, name='' + ) self.assertIsNone(result) def test_unset_share_network_description(self): @@ -447,7 +577,8 @@ def test_unset_share_network_description(self): result = self.cmd.take_action(parsed_args) self.share_networks_mock.update.assert_called_once_with( - self.share_network, description='') + self.share_network, description='' + ) self.assertIsNone(result) @ddt.data('name', 'security_service') @@ -469,20 +600,23 @@ def test_unset_share_network_exception_while_updating(self, attr): self.share_networks_mock.update.side_effect = Exception() else: self.share_networks_mock.remove_security_service.side_effect = ( - Exception()) - - with mock.patch('osc_lib.utils.find_resource', - side_effect=[self.share_network, - 'fake-security-service']): - self.assertRaises(exceptions.CommandError, - self.cmd.take_action, - parsed_args) + Exception() + ) + + with mock.patch( + 'osc_lib.utils.find_resource', + side_effect=[self.share_network, 'fake-security-service'], + ): + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) self.share_networks_mock.update.assert_called_once_with( - self.share_network, name='') + self.share_network, name='' + ) if attr == 'security_service': - self.share_networks_mock.remove_security_service\ - .assert_called_once_with(self.share_network, - 'fake-security-service') + self.share_networks_mock.remove_security_service.assert_called_once_with( + self.share_network, 'fake-security-service' + ) def test_unset_share_network_security_service(self): arglist = [ @@ -496,51 +630,58 @@ def test_unset_share_network_security_service(self): ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) - with mock.patch('osc_lib.utils.find_resource', - side_effect=[self.share_network, - 'fake-security-service']): + with mock.patch( + 'osc_lib.utils.find_resource', + side_effect=[self.share_network, 'fake-security-service'], + ): result = self.cmd.take_action(parsed_args) self.assertIsNone(result) - self.share_networks_mock.remove_security_service\ - .assert_called_once_with(self.share_network, - 'fake-security-service') + self.share_networks_mock.remove_security_service.assert_called_once_with( + self.share_network, 'fake-security-service' + ) @ddt.ddt class TestShareNetworkSet(TestShareNetwork): - def setUp(self): - super(TestShareNetworkSet, self).setUp() + super().setUp() self.share_network = ( - manila_fakes.FakeShareNetwork.create_one_share_network()) + manila_fakes.FakeShareNetwork.create_one_share_network() + ) self.share_networks_mock.get.return_value = self.share_network self.cmd = osc_share_networks.SetShareNetwork(self.app, None) - @ddt.data({'status': 'error', - 'current_security_service': str(uuid.uuid4()), - 'check_only': True, - 'restart_check': True}, - {'status': None, - 'current_security_service': str(uuid.uuid4()), - 'check_only': True, - 'restart_check': None}, - {'status': None, - 'current_security_service': str(uuid.uuid4()), - 'check_only': True, - 'restart_check': True}, - ) + @ddt.data( + { + 'status': 'error', + 'current_security_service': str(uuid.uuid4()), + 'check_only': True, + 'restart_check': True, + }, + { + 'status': None, + 'current_security_service': str(uuid.uuid4()), + 'check_only': True, + 'restart_check': None, + }, + { + 'status': None, + 'current_security_service': str(uuid.uuid4()), + 'check_only': True, + 'restart_check': True, + }, + ) @ddt.unpack - def test_set_share_network_api_version_exception(self, - status, - current_security_service, - check_only, - restart_check): + def test_set_share_network_api_version_exception( + self, status, current_security_service, check_only, restart_check + ): self.app.client_manager.share.api_version = api_versions.APIVersion( - "2.62") + "2.62" + ) arglist = [self.share_network.id] verifylist = [('share_network', self.share_network.id)] @@ -548,10 +689,12 @@ def test_set_share_network_api_version_exception(self, arglist.extend(['--status', status]) verifylist.append(('status', status)) if current_security_service: - arglist.extend(['--current-security-service', - current_security_service]) - verifylist.append(('current_security_service', - current_security_service)) + arglist.extend( + ['--current-security-service', current_security_service] + ) + verifylist.append( + ('current_security_service', current_security_service) + ) if check_only and restart_check: arglist.extend(['--check-only', '--restart-check']) verifylist.extend([('check_only', True), ('restart_check', True)]) @@ -559,9 +702,8 @@ def test_set_share_network_api_version_exception(self, parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_set_network_properties(self): new_name = 'share-network-name-' + uuid.uuid4().hex @@ -570,9 +712,12 @@ def test_set_network_properties(self): arglist = [ self.share_network.id, - '--name', new_name, - '--description', new_description, - '--neutron-subnet-id', new_neutron_subnet_id, + '--name', + new_name, + '--description', + new_description, + '--neutron-subnet-id', + new_neutron_subnet_id, ] verifylist = [ ('share_network', self.share_network.id), @@ -582,8 +727,9 @@ def test_set_network_properties(self): ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) - with mock.patch('osc_lib.utils.find_resource', - return_value=self.share_network): + with mock.patch( + 'osc_lib.utils.find_resource', return_value=self.share_network + ): result = self.cmd.take_action(parsed_args) self.share_networks_mock.update.assert_called_once_with( @@ -595,79 +741,81 @@ def test_set_network_properties(self): self.assertIsNone(result) def test_set_share_network_status(self): - arglist = [ - self.share_network.id, - '--status', 'error' - ] + arglist = [self.share_network.id, '--status', 'error'] verifylist = [ ('share_network', self.share_network.id), - ('status', 'error') + ('status', 'error'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) - with mock.patch('osc_lib.utils.find_resource', - return_value=self.share_network): + with mock.patch( + 'osc_lib.utils.find_resource', return_value=self.share_network + ): result = self.cmd.take_action(parsed_args) self.share_networks_mock.reset_state.assert_called_once_with( - self.share_network, parsed_args.status) + self.share_network, parsed_args.status + ) self.assertIsNone(result) def test_set_network_update_exception(self): share_network_name = 'share-network-name-' + uuid.uuid4().hex - arglist = [ - self.share_network.id, - '--name', share_network_name - ] + arglist = [self.share_network.id, '--name', share_network_name] verifylist = [ ('share_network', self.share_network.id), - ('name', share_network_name) + ('name', share_network_name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.share_networks_mock.update.side_effect = Exception() - with mock.patch('osc_lib.utils.find_resource', - return_value=self.share_network): - self.assertRaises(exceptions.CommandError, - self.cmd.take_action, - parsed_args) + with mock.patch( + 'osc_lib.utils.find_resource', return_value=self.share_network + ): + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) self.share_networks_mock.update.assert_called_once_with( - self.share_network, name=parsed_args.name) + self.share_network, name=parsed_args.name + ) def test_set_share_network_status_exception(self): - arglist = [ - self.share_network.id, - '--status', 'error' - ] + arglist = [self.share_network.id, '--status', 'error'] verifylist = [ ('share_network', self.share_network.id), - ('status', 'error') + ('status', 'error'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.share_networks_mock.reset_state.side_effect = Exception() - with mock.patch('osc_lib.utils.find_resource', - return_value=self.share_network): - self.assertRaises(exceptions.CommandError, - self.cmd.take_action, - parsed_args) + with mock.patch( + 'osc_lib.utils.find_resource', return_value=self.share_network + ): + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) self.share_networks_mock.reset_state.assert_called_once_with( - self.share_network, parsed_args.status) + self.share_network, parsed_args.status + ) - @ddt.data({'check_only': False, 'restart_check': False}, - {'check_only': True, 'restart_check': True}, - {'check_only': True, 'restart_check': False}) + @ddt.data( + {'check_only': False, 'restart_check': False}, + {'check_only': True, 'restart_check': True}, + {'check_only': True, 'restart_check': False}, + ) @ddt.unpack def test_set_share_network_add_new_security_service_check_reset( - self, check_only, restart_check): - self.share_networks_mock .add_security_service_check = mock.Mock( - return_value=(200, {'compatible': True})) + self, check_only, restart_check + ): + self.share_networks_mock.add_security_service_check = mock.Mock( + return_value=(200, {'compatible': True}) + ) arglist = [ self.share_network.id, - '--new-security-service', 'new-security-service-name', + '--new-security-service', + 'new-security-service-name', ] verifylist = [ ('share_network', self.share_network.id), @@ -683,39 +831,45 @@ def test_set_share_network_add_new_security_service_check_reset( parsed_args = self.check_parser(self.cmd, arglist, verifylist) - with mock.patch('osc_lib.utils.find_resource', - side_effect=[self.share_network, - 'new-security-service']): + with mock.patch( + 'osc_lib.utils.find_resource', + side_effect=[self.share_network, 'new-security-service'], + ): result = self.cmd.take_action(parsed_args) if check_only: - self.share_networks_mock.add_security_service_check\ - .assert_called_once_with(self.share_network, - 'new-security-service', - reset_operation=restart_check) + self.share_networks_mock.add_security_service_check.assert_called_once_with( + self.share_network, + 'new-security-service', + reset_operation=restart_check, + ) self.share_networks_mock.add_security_service.assert_not_called() else: - self.share_networks_mock.add_security_service_check\ - .assert_not_called() - self.share_networks_mock.add_security_service\ - .assert_called_once_with(self.share_network, - 'new-security-service') + self.share_networks_mock.add_security_service_check.assert_not_called() + self.share_networks_mock.add_security_service.assert_called_once_with( + self.share_network, 'new-security-service' + ) self.assertIsNone(result) - @ddt.data({'check_only': False, 'restart_check': False}, - {'check_only': True, 'restart_check': True}, - {'check_only': True, 'restart_check': False}) + @ddt.data( + {'check_only': False, 'restart_check': False}, + {'check_only': True, 'restart_check': True}, + {'check_only': True, 'restart_check': False}, + ) @ddt.unpack def test_set_share_network_update_security_service_check_reset( - self, check_only, restart_check): - self.share_networks_mock\ - .update_share_network_security_service_check = mock.Mock( - return_value=(200, {'compatible': True})) + self, check_only, restart_check + ): + self.share_networks_mock.update_share_network_security_service_check = mock.Mock( # noqa: E501 + return_value=(200, {'compatible': True}) + ) arglist = [ self.share_network.id, - '--new-security-service', 'new-security-service-name', - '--current-security-service', 'current-security-service-name' + '--new-security-service', + 'new-security-service-name', + '--current-security-service', + 'current-security-service-name', ] verifylist = [ ('share_network', self.share_network.id), @@ -730,27 +884,29 @@ def test_set_share_network_update_security_service_check_reset( verifylist.append(('restart_check', True)) parsed_args = self.check_parser(self.cmd, arglist, verifylist) - with mock.patch('osc_lib.utils.find_resource', - side_effect=[self.share_network, - 'new-security-service', - 'current-security-service']): + with mock.patch( + 'osc_lib.utils.find_resource', + side_effect=[ + self.share_network, + 'new-security-service', + 'current-security-service', + ], + ): result = self.cmd.take_action(parsed_args) if check_only: - self.share_networks_mock\ - .update_share_network_security_service_check\ - .assert_called_once_with(self.share_network, - 'current-security-service', - 'new-security-service', - reset_operation=restart_check) - self.share_networks_mock.update_share_network_security_service\ - .assert_not_called() + self.share_networks_mock.update_share_network_security_service_check.assert_called_once_with( + self.share_network, + 'current-security-service', + 'new-security-service', + reset_operation=restart_check, + ) + self.share_networks_mock.update_share_network_security_service.assert_not_called() else: - self.share_networks_mock\ - .update_share_network_security_service_check\ - .assert_not_called() - self.share_networks_mock.update_share_network_security_service\ - .assert_called_once_with(self.share_network, - 'current-security-service', - 'new-security-service') + self.share_networks_mock.update_share_network_security_service_check.assert_not_called() + self.share_networks_mock.update_share_network_security_service.assert_called_once_with( + self.share_network, + 'current-security-service', + 'new-security-service', + ) self.assertIsNone(result) diff --git a/manilaclient/tests/unit/osc/v2/test_share_pools.py b/manilaclient/tests/unit/osc/v2/test_share_pools.py index e59d7921..9f09c1b5 100644 --- a/manilaclient/tests/unit/osc/v2/test_share_pools.py +++ b/manilaclient/tests/unit/osc/v2/test_share_pools.py @@ -19,9 +19,8 @@ class TestPool(manila_fakes.TestShare): - def setUp(self): - super(TestPool, self).setUp() + super().setUp() self.pools_mock = self.app.client_manager.share.pools self.pools_mock.reset_mock() @@ -30,15 +29,15 @@ def setUp(self): self.share_types_mock.reset_mock() self.app.client_manager.share.api_version = api_versions.APIVersion( - api_versions.MAX_VERSION) + api_versions.MAX_VERSION + ) class TestPoolList(TestPool): - columns = ['Name', 'Host', 'Backend', 'Pool'] def setUp(self): - super(TestPoolList, self).setUp() + super().setUp() self.share_type = manila_fakes.FakeShareType.create_one_sharetype() self.share_types_mock.get.return_value = self.share_type @@ -46,8 +45,10 @@ def setUp(self): self.share_pools = manila_fakes.FakeSharePools.create_share_pools() self.pools_mock.list.return_value = self.share_pools - self.values = (oscutils.get_dict_properties( - pool._info, self.columns) for pool in self.share_pools) + self.values = ( + oscutils.get_dict_properties(pool._info, self.columns) + for pool in self.share_pools + ) self.cmd = share_pools.ListSharePools(self.app, None) @@ -65,21 +66,25 @@ def test_list_share_pools(self): 'backend': None, 'pool': None, 'share_type': None, - }) + }, + ) self.assertEqual(self.columns, columns) self.assertEqual(list(self.values), list(data)) def test_list_share_pools_filters(self): arglist = [ - '--host', self.share_pools[0].host, - '--backend', self.share_pools[0].backend, - '--pool', self.share_pools[0].pool + '--host', + self.share_pools[0].host, + '--backend', + self.share_pools[0].backend, + '--pool', + self.share_pools[0].pool, ] verifylist = [ ('host', self.share_pools[0].host), ('backend', self.share_pools[0].backend), - ('pool', self.share_pools[0].pool) + ('pool', self.share_pools[0].pool), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -92,18 +97,15 @@ def test_list_share_pools_filters(self): 'backend': self.share_pools[0].backend, 'pool': self.share_pools[0].pool, 'share_type': None, - }) + }, + ) self.assertEqual(self.columns, columns) self.assertEqual(list(self.values), list(data)) def test_list_share_pools_share_type(self): - arglist = [ - '--share-type', self.share_type.id - ] - verifylist = [ - ('share_type', self.share_type.id) - ] + arglist = ['--share-type', self.share_type.id] + verifylist = [('share_type', self.share_type.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) @@ -114,35 +116,32 @@ def test_list_share_pools_share_type(self): 'backend': None, 'pool': None, 'share_type': self.share_type.id, - }) + }, + ) self.assertEqual(self.columns, columns) self.assertEqual(list(self.values), list(data)) def test_list_share_pools_share_type_api_version_exception(self): self.app.client_manager.share.api_version = api_versions.APIVersion( - "2.22") + "2.22" + ) - arglist = [ - '--share-type', self.share_type.id - ] - verifylist = [ - ('share_type', self.share_type.id) - ] + arglist = ['--share-type', self.share_type.id] + verifylist = [('share_type', self.share_type.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_list_share_pools_detail(self): detail_columns = ['Name', 'Host', 'Backend', 'Pool', 'Capabilities'] - detail_values = (oscutils.get_dict_properties( - pool._info, detail_columns) for pool in self.share_pools) - arglist = [ - '--detail' - ] - verifylist = [ - ('detail', True) - ] + detail_values = ( + oscutils.get_dict_properties(pool._info, detail_columns) + for pool in self.share_pools + ) + arglist = ['--detail'] + verifylist = [('detail', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) @@ -154,7 +153,8 @@ def test_list_share_pools_detail(self): 'backend': None, 'pool': None, 'share_type': None, - }) + }, + ) self.assertEqual(detail_columns, columns) self.assertEqual(list(detail_values), list(data)) diff --git a/manilaclient/tests/unit/osc/v2/test_share_replica_export_locations.py b/manilaclient/tests/unit/osc/v2/test_share_replica_export_locations.py index 956c751e..569286c2 100644 --- a/manilaclient/tests/unit/osc/v2/test_share_replica_export_locations.py +++ b/manilaclient/tests/unit/osc/v2/test_share_replica_export_locations.py @@ -13,100 +13,87 @@ from osc_lib import utils as oscutils from manilaclient.osc.v2 import ( - share_replica_export_locations as osc_replica_el + share_replica_export_locations as osc_replica_el, ) from manilaclient.tests.unit.osc.v2 import fakes as manila_fakes class TestShareReplica(manila_fakes.TestShare): - def setUp(self): - super(TestShareReplica, self).setUp() + super().setUp() self.replicas_mock = self.app.client_manager.share.share_replicas self.replicas_mock.reset_mock() self.export_locations_mock = ( - self.app.client_manager.share.share_replica_export_locations) + self.app.client_manager.share.share_replica_export_locations + ) self.export_locations_mock.reset_mock() class TestShareReplicaExportLocationList(TestShareReplica): - - columns = [ - 'ID', - 'Availability Zone', - 'Replica State', - 'Preferred', - 'Path' - ] + columns = ['ID', 'Availability Zone', 'Replica State', 'Preferred', 'Path'] def setUp(self): - super(TestShareReplicaExportLocationList, self).setUp() + super().setUp() - self.share_replica = ( - manila_fakes.FakeShareReplica.create_one_replica()) + self.share_replica = manila_fakes.FakeShareReplica.create_one_replica() self.replicas_mock.get.return_value = self.share_replica - self.export_locations = ([ + self.export_locations = [ manila_fakes.FakeShareExportLocation.create_one_export_location() - ]) + ] self.export_locations_mock.list.return_value = self.export_locations - self.values = (oscutils.get_dict_properties( - e._info, self.columns) for e in self.export_locations) + self.values = ( + oscutils.get_dict_properties(e._info, self.columns) + for e in self.export_locations + ) self.cmd = osc_replica_el.ShareReplicaListExportLocation( - self.app, None) + self.app, None + ) def test_replica_export_locations_list(self): - arglist = [ - self.share_replica.id - ] - verifylist = [ - ('replica', self.share_replica.id) - ] + arglist = [self.share_replica.id] + verifylist = [('replica', self.share_replica.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.replicas_mock.get.assert_called_with(self.share_replica.id) - self.export_locations_mock.list.assert_called_with( - self.share_replica) + self.export_locations_mock.list.assert_called_with(self.share_replica) self.assertEqual(self.columns, columns) self.assertCountEqual(self.values, data) class TestShareReplicaExportLocationShow(TestShareReplica): - def setUp(self): - super(TestShareReplicaExportLocationShow, self).setUp() + super().setUp() - self.share_replica = ( - manila_fakes.FakeShareReplica.create_one_replica()) + self.share_replica = manila_fakes.FakeShareReplica.create_one_replica() self.replicas_mock.get.return_value = self.share_replica self.export_location = ( - manila_fakes.FakeShareExportLocation.create_one_export_location()) + manila_fakes.FakeShareExportLocation.create_one_export_location() + ) self.export_locations_mock.get.return_value = self.export_location self.cmd = osc_replica_el.ShareReplicaShowExportLocation( - self.app, None) + self.app, None + ) def test_replica_export_locations_show(self): - arglist = [ - self.share_replica.id, - self.export_location.id - ] + arglist = [self.share_replica.id, self.export_location.id] verifylist = [ ('replica', self.share_replica.id), - ('export_location', self.export_location.id) + ('export_location', self.export_location.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -115,10 +102,10 @@ def test_replica_export_locations_show(self): self.replicas_mock.get.assert_called_with(self.share_replica.id) self.export_locations_mock.get.assert_called_with( - self.share_replica, - self.export_location.id) + self.share_replica, self.export_location.id + ) self.assertCountEqual( - tuple(self.export_location._info.keys()), - columns) + tuple(self.export_location._info.keys()), columns + ) self.assertCountEqual(self.export_location._info.values(), data) diff --git a/manilaclient/tests/unit/osc/v2/test_share_replicas.py b/manilaclient/tests/unit/osc/v2/test_share_replicas.py index 7da4b2c4..b29beddd 100644 --- a/manilaclient/tests/unit/osc/v2/test_share_replicas.py +++ b/manilaclient/tests/unit/osc/v2/test_share_replicas.py @@ -26,9 +26,8 @@ class TestShareReplica(manila_fakes.TestShare): - def setUp(self): - super(TestShareReplica, self).setUp() + super().setUp() self.shares_mock = self.app.client_manager.share.shares self.shares_mock.reset_mock() @@ -36,28 +35,25 @@ def setUp(self): self.replicas_mock = self.app.client_manager.share.share_replicas self.replicas_mock.reset_mock() self.app.client_manager.share.api_version = api_versions.APIVersion( - api_versions.MAX_VERSION) + api_versions.MAX_VERSION + ) self.replica_el_mock = ( - self.app.client_manager - .share.share_replica_export_locations) + self.app.client_manager.share.share_replica_export_locations + ) self.replica_el_mock.reset_mock() class TestShareReplicaCreate(TestShareReplica): - def setUp(self): - super(TestShareReplicaCreate, self).setUp() + super().setUp() self.share = manila_fakes.FakeShare.create_one_share() self.shares_mock.get.return_value = self.share - self.share_replica = ( - manila_fakes.FakeShareReplica.create_one_replica( - attrs={ - 'availability_zone': 'manila-zone-1', - 'status': 'available'} - )) + self.share_replica = manila_fakes.FakeShareReplica.create_one_replica( + attrs={'availability_zone': 'manila-zone-1', 'status': 'available'} + ) self.replicas_mock.create.return_value = self.share_replica self.replicas_mock.get.return_value = self.share_replica @@ -72,23 +68,22 @@ def test_share_replica_create_missing_args(self): self.assertRaises( osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_replica_create(self): - arglist = [ - self.share.id - ] - verifylist = [ - ('share', self.share.id) - ] + arglist = [self.share.id] + verifylist = [('share', self.share.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.replicas_mock.create.assert_called_with( - share=self.share, - availability_zone=None + share=self.share, availability_zone=None ) self.assertCountEqual(self.columns, columns) @@ -97,11 +92,12 @@ def test_share_replica_create(self): def test_share_replica_create_az(self): arglist = [ self.share.id, - '--availability-zone', self.share.availability_zone + '--availability-zone', + self.share.availability_zone, ] verifylist = [ ('share', self.share.id), - ('availability_zone', self.share.availability_zone) + ('availability_zone', self.share.availability_zone), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -109,8 +105,7 @@ def test_share_replica_create_az(self): columns, data = self.cmd.take_action(parsed_args) self.replicas_mock.create.assert_called_with( - share=self.share, - availability_zone=self.share.availability_zone + share=self.share, availability_zone=self.share.availability_zone ) self.assertCountEqual(self.columns, columns) @@ -119,13 +114,15 @@ def test_share_replica_create_az(self): def test_share_replica_create_scheduler_hint_valid(self): arglist = [ self.share.id, - '--availability-zone', self.share.availability_zone, - '--scheduler-hint', ('only_host=host1@backend1#pool1'), + '--availability-zone', + self.share.availability_zone, + '--scheduler-hint', + ('only_host=host1@backend1#pool1'), ] verifylist = [ ('share', self.share.id), ('availability_zone', self.share.availability_zone), - ('scheduler_hint', {'only_host': 'host1@backend1#pool1'}) + ('scheduler_hint', {'only_host': 'host1@backend1#pool1'}), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -135,7 +132,7 @@ def test_share_replica_create_scheduler_hint_valid(self): self.replicas_mock.create.assert_called_with( share=self.share, availability_zone=self.share.availability_zone, - scheduler_hints={'only_host': 'host1@backend1#pool1'} + scheduler_hints={'only_host': 'host1@backend1#pool1'}, ) self.assertCountEqual(self.columns, columns) @@ -144,53 +141,61 @@ def test_share_replica_create_scheduler_hint_valid(self): def test_share_replica_create_scheduler_hint_invalid_hint(self): arglist = [ self.share.id, - '--availability-zone', self.share.availability_zone, - '--scheduler-hint', 'fake_hint=host1@backend1#pool1' + '--availability-zone', + self.share.availability_zone, + '--scheduler-hint', + 'fake_hint=host1@backend1#pool1', ] verifylist = [ ('share', self.share.id), ('availability_zone', self.share.availability_zone), - ('scheduler_hint', {'fake_hint': 'host1@backend1#pool1'}) + ('scheduler_hint', {'fake_hint': 'host1@backend1#pool1'}), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) - self.assertRaises(exceptions.CommandError, - self.cmd.take_action, - parsed_args) + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_share_replica_create_scheduler_hint_invalid_version(self): self.app.client_manager.share.api_version = api_versions.APIVersion( - "2.66") + "2.66" + ) arglist = [ self.share.id, - '--availability-zone', self.share.availability_zone, - '--scheduler-hint', 'only_host=host1@backend1#pool1' + '--availability-zone', + self.share.availability_zone, + '--scheduler-hint', + 'only_host=host1@backend1#pool1', ] verifylist = [ ('share', self.share.id), ('availability_zone', self.share.availability_zone), - ('scheduler_hint', {'only_host': 'host1@backend1#pool1'}) + ('scheduler_hint', {'only_host': 'host1@backend1#pool1'}), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) - self.assertRaises(exceptions.CommandError, - self.cmd.take_action, - parsed_args) + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_share_replica_create_share_network(self): self.app.client_manager.share.api_version = api_versions.APIVersion( - "2.72") + "2.72" + ) arglist = [ self.share.id, - '--availability-zone', self.share.availability_zone, - '--share-network', self.share.share_network_id + '--availability-zone', + self.share.availability_zone, + '--share-network', + self.share.share_network_id, ] verifylist = [ ('share', self.share.id), ('availability_zone', self.share.availability_zone), - ('share_network', self.share.share_network_id) + ('share_network', self.share.share_network_id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -200,7 +205,7 @@ def test_share_replica_create_share_network(self): self.replicas_mock.create.assert_called_with( share=self.share, availability_zone=self.share.availability_zone, - share_network=self.share.share_network_id + share_network=self.share.share_network_id, ) else: self.replicas_mock.create.assert_called_with( @@ -211,14 +216,27 @@ def test_share_replica_create_share_network(self): self.assertCountEqual(self.columns, columns) self.assertCountEqual(self.data, data) - def test_share_replica_create_wait(self): + def test_share_replica_create_with_metadata(self): + self.app.client_manager.share.api_version = api_versions.APIVersion( + "2.95" + ) + arglist = [ self.share.id, - '--wait' + '--availability-zone', + self.share.availability_zone, + '--property', + 'fake_key1=fake_value1', + '--property', + 'fake_key2=fake_value2', ] verifylist = [ ('share', self.share.id), - ('wait', True) + ('availability_zone', self.share.availability_zone), + ( + 'property', + {'fake_key1': 'fake_value1', 'fake_key2': 'fake_value2'}, + ), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -227,23 +245,52 @@ def test_share_replica_create_wait(self): self.replicas_mock.create.assert_called_with( share=self.share, - availability_zone=None + availability_zone=self.share.availability_zone, + metadata={'fake_key1': 'fake_value1', 'fake_key2': 'fake_value2'}, ) - self.replicas_mock.get.assert_called_with(self.share_replica.id) self.assertCountEqual(self.columns, columns) self.assertCountEqual(self.data, data) - @mock.patch('manilaclient.osc.v2.share_replicas.LOG') - def test_share_replica_create_wait_exception(self, mock_logger): + def test_share_replica_create_metadata_api_version_exception(self): + self.app.client_manager.share.api_version = api_versions.APIVersion( + '2.91' + ) arglist = [ self.share.id, - '--wait' + '--property', + 'fake_key=fake_value', ] verifylist = [ ('share', self.share.id), - ('wait', True) + ('property', {'fake_key': 'fake_value'}), ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) + + def test_share_replica_create_wait(self): + arglist = [self.share.id, '--wait'] + verifylist = [('share', self.share.id), ('wait', True)] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + + self.replicas_mock.create.assert_called_with( + share=self.share, availability_zone=None + ) + + self.replicas_mock.get.assert_called_with(self.share_replica.id) + self.assertCountEqual(self.columns, columns) + self.assertCountEqual(self.data, data) + + @mock.patch('manilaclient.osc.v2.share_replicas.LOG') + def test_share_replica_create_wait_exception(self, mock_logger): + arglist = [self.share.id, '--wait'] + verifylist = [('share', self.share.id), ('wait', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -251,12 +298,12 @@ def test_share_replica_create_wait_exception(self, mock_logger): columns, data = self.cmd.take_action(parsed_args) self.replicas_mock.create.assert_called_with( - share=self.share, - availability_zone=None + share=self.share, availability_zone=None ) mock_logger.error.assert_called_with( - "ERROR: Share replica is in error state.") + "ERROR: Share replica is in error state." + ) self.replicas_mock.get.assert_called_with(self.share_replica.id) self.assertCountEqual(self.columns, columns) @@ -264,12 +311,10 @@ def test_share_replica_create_wait_exception(self, mock_logger): class TestShareReplicaDelete(TestShareReplica): - def setUp(self): - super(TestShareReplicaDelete, self).setUp() + super().setUp() - self.share_replica = ( - manila_fakes.FakeShareReplica.create_one_replica()) + self.share_replica = manila_fakes.FakeShareReplica.create_one_replica() self.replicas_mock.get.return_value = self.share_replica self.cmd = osc_share_replicas.DeleteShareReplica(self.app, None) @@ -278,53 +323,45 @@ def test_share_replica_delete_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_replica_delete(self): - arglist = [ - self.share_replica.id - ] - verifylist = [ - ('replica', [self.share_replica.id]) - ] + arglist = [self.share_replica.id] + verifylist = [('replica', [self.share_replica.id])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.replicas_mock.delete.assert_called_with( - self.share_replica, - force=False) + self.share_replica, force=False + ) self.assertIsNone(result) def test_share_replica_delete_force(self): - arglist = [ - self.share_replica.id, - '--force' - ] - verifylist = [ - ('replica', [self.share_replica.id]), - ('force', True) - ] + arglist = [self.share_replica.id, '--force'] + verifylist = [('replica', [self.share_replica.id]), ('force', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.replicas_mock.delete.assert_called_with( - self.share_replica, - force=True) + self.share_replica, force=True + ) self.assertIsNone(result) def test_share_replica_delete_multiple(self): - share_replicas = ( - manila_fakes.FakeShareReplica.create_share_replicas( - count=2)) - arglist = [ - share_replicas[0].id, - share_replicas[1].id - ] + share_replicas = manila_fakes.FakeShareReplica.create_share_replicas( + count=2 + ) + arglist = [share_replicas[0].id, share_replicas[1].id] verifylist = [ ('replica', [share_replicas[0].id, share_replicas[1].id]) ] @@ -332,34 +369,25 @@ def test_share_replica_delete_multiple(self): result = self.cmd.take_action(parsed_args) - self.assertEqual(self.replicas_mock.delete.call_count, - len(share_replicas)) + self.assertEqual( + self.replicas_mock.delete.call_count, len(share_replicas) + ) self.assertIsNone(result) def test_share_snapshot_delete_exception(self): - arglist = [ - self.share_replica.id - ] - verifylist = [ - ('replica', [self.share_replica.id]) - ] + arglist = [self.share_replica.id] + verifylist = [('replica', [self.share_replica.id])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.replicas_mock.delete.side_effect = exceptions.CommandError() - self.assertRaises(exceptions.CommandError, - self.cmd.take_action, - parsed_args) + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_share_replica_delete_wait(self): - arglist = [ - self.share_replica.id, - '--wait' - ] - verifylist = [ - ('replica', [self.share_replica.id]), - ('wait', True) - ] + arglist = [self.share_replica.id, '--wait'] + verifylist = [('replica', [self.share_replica.id]), ('wait', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -367,33 +395,24 @@ def test_share_replica_delete_wait(self): result = self.cmd.take_action(parsed_args) self.replicas_mock.delete.assert_called_with( - self.share_replica, - force=False) + self.share_replica, force=False + ) self.replicas_mock.get.assert_called_with(self.share_replica.id) self.assertIsNone(result) def test_share_replica_delete_wait_exception(self): - arglist = [ - self.share_replica.id, - '--wait' - ] - verifylist = [ - ('replica', [self.share_replica.id]), - ('wait', True) - ] + arglist = [self.share_replica.id, '--wait'] + verifylist = [('replica', [self.share_replica.id]), ('wait', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch('osc_lib.utils.wait_for_delete', return_value=False): self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args + exceptions.CommandError, self.cmd.take_action, parsed_args ) class TestShareReplicaList(TestShareReplica): - columns = [ 'id', 'status', @@ -407,18 +426,20 @@ class TestShareReplicaList(TestShareReplica): column_headers = utils.format_column_headers(columns) def setUp(self): - super(TestShareReplicaList, self).setUp() + super().setUp() self.share = manila_fakes.FakeShare.create_one_share() self.shares_mock.get.return_value = self.share self.replicas_list = ( - manila_fakes.FakeShareReplica.create_share_replicas( - count=2)) + manila_fakes.FakeShareReplica.create_share_replicas(count=2) + ) self.replicas_mock.list.return_value = self.replicas_list - self.values = (oscutils.get_dict_properties( - i._info, self.columns) for i in self.replicas_list) + self.values = ( + oscutils.get_dict_properties(i._info, self.columns) + for i in self.replicas_list + ) self.cmd = osc_share_replicas.ListShareReplica(self.app, None) @@ -430,52 +451,47 @@ def test_share_replica_list(self): columns, data = self.cmd.take_action(parsed_args) - self.replicas_mock.list.assert_called_with(share=None) + self.replicas_mock.list.assert_called_with(share=None, search_opts={}) self.assertEqual(self.column_headers, columns) self.assertEqual(list(self.values), list(data)) def test_share_replica_list_for_share(self): - arglist = [ - '--share', self.share.id - ] - verifylist = [ - ('share', self.share.id) - ] + arglist = ['--share', self.share.id] + verifylist = [('share', self.share.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) - self.replicas_mock.list.assert_called_with(share=self.share) + self.replicas_mock.list.assert_called_with( + share=self.share, search_opts={} + ) self.assertEqual(self.column_headers, columns) self.assertEqual(list(self.values), list(data)) class TestShareReplicaShow(TestShareReplica): - def setUp(self): - super(TestShareReplicaShow, self).setUp() + super().setUp() - self.share_replica = ( - manila_fakes.FakeShareReplica.create_one_replica() - ) + self.share_replica = manila_fakes.FakeShareReplica.create_one_replica() self.replicas_mock.get.return_value = self.share_replica self.replica_el_list = ( - manila_fakes.FakeShareExportLocation. - create_share_export_locations(count=2) + manila_fakes.FakeShareExportLocation.create_share_export_locations( + count=2 + ) ) - self.replica_el_mock.list.return_value = ( - self.replica_el_list) + self.replica_el_mock.list.return_value = self.replica_el_list self.cmd = osc_share_replicas.ShowShareReplica(self.app, None) self.share_replica._info['export_locations'] = ( - cliutils.convert_dict_list_to_string( - self.replica_el_list)) + cliutils.convert_dict_list_to_string(self.replica_el_list) + ) self.data = tuple(self.share_replica._info.values()) self.columns = tuple(self.share_replica._info.keys()) @@ -486,35 +502,32 @@ def test_share_replica_show_missing_args(self): self.assertRaises( osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_replica_show(self): - arglist = [ - self.share_replica.id - ] - verifylist = [ - ('replica', self.share_replica.id) - ] + arglist = [self.share_replica.id] + verifylist = [('replica', self.share_replica.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) - self.replicas_mock.get.assert_called_with( - self.share_replica.id - ) + self.replicas_mock.get.assert_called_with(self.share_replica.id) self.assertCountEqual(self.columns, columns) self.assertCountEqual(self.data, data) class TestShareReplicaSet(TestShareReplica): - def setUp(self): - super(TestShareReplicaSet, self).setUp() + super().setUp() - self.share_replica = ( - manila_fakes.FakeShareReplica.create_one_replica() + self.share_replica = manila_fakes.FakeShareReplica.create_one_replica( + methods={"set_metadata": None} ) self.replicas_mock.get.return_value = self.share_replica @@ -522,79 +535,65 @@ def setUp(self): def test_share_replica_set_replica_state(self): new_replica_state = 'in_sync' - arglist = [ - self.share_replica.id, - '--replica-state', new_replica_state - ] + arglist = [self.share_replica.id, '--replica-state', new_replica_state] verifylist = [ ('replica', self.share_replica.id), - ('replica_state', new_replica_state) + ('replica_state', new_replica_state), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.replicas_mock.reset_replica_state.assert_called_with( - self.share_replica, - new_replica_state) + self.share_replica, new_replica_state + ) self.assertIsNone(result) def test_share_replica_set_replica_state_exception(self): new_replica_state = 'in_sync' - arglist = [ - self.share_replica.id, - '--replica-state', new_replica_state - ] + arglist = [self.share_replica.id, '--replica-state', new_replica_state] verifylist = [ ('replica', self.share_replica.id), - ('replica_state', new_replica_state) + ('replica_state', new_replica_state), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.replicas_mock.reset_replica_state.side_effect = Exception() self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_share_replica_set_status(self): new_status = 'available' - arglist = [ - self.share_replica.id, - '--status', new_status - ] + arglist = [self.share_replica.id, '--status', new_status] verifylist = [ ('replica', self.share_replica.id), - ('status', new_status) + ('status', new_status), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.replicas_mock.reset_state.assert_called_with( - self.share_replica, - new_status) + self.share_replica, new_status + ) self.assertIsNone(result) def test_share_replica_set_status_exception(self): new_status = 'available' - arglist = [ - self.share_replica.id, - '--status', new_status - ] + arglist = [self.share_replica.id, '--status', new_status] verifylist = [ ('replica', self.share_replica.id), - ('status', new_status) + ('status', new_status), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.replicas_mock.reset_state.side_effect = Exception() self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_share_replica_set_nothing_defined(self): arglist = [ @@ -606,83 +605,197 @@ def test_share_replica_set_nothing_defined(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) + def test_share_replica_set_property(self): + self.app.client_manager.share.api_version = api_versions.APIVersion( + '2.95' + ) + arglist = [ + self.share_replica.id, + '--property', + 'fake_key=fake_value', + ] + verifylist = [ + ('replica', self.share_replica.id), + ('property', {'fake_key': 'fake_value'}), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) -class TestShareReplicaPromote(TestShareReplica): + self.cmd.take_action(parsed_args) + + self.share_replica.set_metadata.assert_called_once_with( + {'fake_key': 'fake_value'}, + ) + + def test_share_replica_set_property_exception(self): + self.app.client_manager.share.api_version = api_versions.APIVersion( + '2.95' + ) + arglist = [ + self.share_replica.id, + '--property', + 'fake_key=fake_value', + ] + verifylist = [ + ('replica', self.share_replica.id), + ('property', {'fake_key': 'fake_value'}), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.cmd.take_action(parsed_args) + + self.share_replica.set_metadata.assert_called_once_with( + {'fake_key': 'fake_value'}, + ) + self.share_replica.set_metadata.side_effect = exceptions.BadRequest + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) + + +class TestShareReplicaUnset(TestShareReplica): def setUp(self): - super(TestShareReplicaPromote, self).setUp() + super().setUp() - self.share_replica = ( - manila_fakes.FakeShareReplica.create_one_replica( - attrs={ - 'status': 'available'} - ) + self.share_replica = manila_fakes.FakeShareReplica.create_one_replica( + methods={"delete_metadata": None} ) self.replicas_mock.get.return_value = self.share_replica - self.cmd = osc_share_replicas.PromoteShareReplica( - self.app, None) + self.cmd = osc_share_replicas.UnsetShareReplica(self.app, None) - def test_share_replica_promote(self): + def test_share_replica_unset_property(self): + self.app.client_manager.share.api_version = api_versions.APIVersion( + '2.95' + ) arglist = [ + '--property', + 'test_key', self.share_replica.id, ] verifylist = [ + ('property', ['test_key']), ('replica', self.share_replica.id), - ('wait', False) ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) + self.cmd.take_action(parsed_args) - self.replicas_mock.promote.assert_called_with( - self.share_replica) - self.assertIsNone(result) + self.share_replica.delete_metadata.assert_called_once_with( + parsed_args.property + ) - def test_share_replica_promote_quiesce_wait_time(self): - wait_time = '5' + def test_share_replica_unset_multiple_properties(self): + self.app.client_manager.share.api_version = api_versions.APIVersion( + '2.95' + ) arglist = [ + '--property', + 'key1', + '--property', + 'key2', self.share_replica.id, - '--quiesce-wait-time', wait_time ] verifylist = [ + ('property', ['key1', 'key2']), ('replica', self.share_replica.id), - ('quiesce_wait_time', wait_time) ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) + self.cmd.take_action(parsed_args) - self.replicas_mock.promote.assert_called_with( - self.share_replica, - wait_time) - self.assertIsNone(result) + # Assert delete_metadata was called for each key + expected_calls = [mock.call(['key1']), mock.call(['key2'])] + self.share_replica.delete_metadata.assert_has_calls( + expected_calls, any_order=False + ) + self.assertEqual(self.share_replica.delete_metadata.call_count, 2) - @mock.patch.object(osc_share_replicas.osc_utils, 'wait_for_status', - mock.Mock()) - def test_share_replica_promote_wait(self): + def test_share_replica_unset_property_exception(self): + self.app.client_manager.share.api_version = api_versions.APIVersion( + '2.95' + ) + arglist = [ + self.share_replica.id, + '--property', + 'test_key', + ] + verifylist = [ + ('replica', self.share_replica.id), + ('property', ['test_key']), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # 404 Not Found would be raised, if property 'test_key' doesn't exist. + self.share_replica.delete_metadata.side_effect = exceptions.NotFound + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) + + +class TestShareReplicaPromote(TestShareReplica): + def setUp(self): + super().setUp() + + self.share_replica = manila_fakes.FakeShareReplica.create_one_replica( + attrs={'status': 'available'} + ) + self.replicas_mock.get.return_value = self.share_replica + + self.cmd = osc_share_replicas.PromoteShareReplica(self.app, None) + + def test_share_replica_promote(self): arglist = [ self.share_replica.id, - '--wait' ] + verifylist = [('replica', self.share_replica.id), ('wait', False)] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + result = self.cmd.take_action(parsed_args) + + self.replicas_mock.promote.assert_called_with(self.share_replica) + self.assertIsNone(result) + + def test_share_replica_promote_quiesce_wait_time(self): + wait_time = '5' + arglist = [self.share_replica.id, '--quiesce-wait-time', wait_time] verifylist = [ ('replica', self.share_replica.id), - ('wait', True) + ('quiesce_wait_time', wait_time), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.replicas_mock.promote.assert_called_with( - self.share_replica) + self.share_replica, wait_time + ) + self.assertIsNone(result) + + @mock.patch.object( + osc_share_replicas.osc_utils, 'wait_for_status', mock.Mock() + ) + def test_share_replica_promote_wait(self): + arglist = [self.share_replica.id, '--wait'] + verifylist = [('replica', self.share_replica.id), ('wait', True)] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + result = self.cmd.take_action(parsed_args) + + self.replicas_mock.promote.assert_called_with(self.share_replica) self.assertIsNone(result) osc_share_replicas.osc_utils.wait_for_status.assert_called_once_with( - status_f=self.replicas_mock.get, res_id=self.share_replica.id, - success_status=['active'], status_field='replica_state') + status_f=self.replicas_mock.get, + res_id=self.share_replica.id, + success_status=['active'], + status_field='replica_state', + ) def test_share_replica_promote_exception(self): arglist = [ @@ -696,23 +809,18 @@ def test_share_replica_promote_exception(self): self.replicas_mock.promote.side_effect = Exception() self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestShareReplicaResync(TestShareReplica): - def setUp(self): - super(TestShareReplicaResync, self).setUp() + super().setUp() - self.share_replica = ( - manila_fakes.FakeShareReplica.create_one_replica() - ) + self.share_replica = manila_fakes.FakeShareReplica.create_one_replica() self.replicas_mock.get.return_value = self.share_replica - self.cmd = osc_share_replicas.ResyncShareReplica( - self.app, None) + self.cmd = osc_share_replicas.ResyncShareReplica(self.app, None) def test_share_replica_resync(self): arglist = [ @@ -725,8 +833,7 @@ def test_share_replica_resync(self): result = self.cmd.take_action(parsed_args) - self.replicas_mock.resync.assert_called_with( - self.share_replica) + self.replicas_mock.resync.assert_called_with(self.share_replica) self.assertIsNone(result) def test_share_replica_resync_exception(self): @@ -741,6 +848,5 @@ def test_share_replica_resync_exception(self): self.replicas_mock.resync.side_effect = Exception() self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) diff --git a/manilaclient/tests/unit/osc/v2/test_share_servers.py b/manilaclient/tests/unit/osc/v2/test_share_servers.py index dcb2f12a..7ffd28a8 100644 --- a/manilaclient/tests/unit/osc/v2/test_share_servers.py +++ b/manilaclient/tests/unit/osc/v2/test_share_servers.py @@ -26,9 +26,8 @@ class TestShareServer(manila_fakes.TestShare): - def setUp(self): - super(TestShareServer, self).setUp() + super().setUp() self.servers_mock = self.app.client_manager.share.share_servers self.servers_mock.reset_mock() @@ -37,16 +36,15 @@ def setUp(self): self.share_networks_mock.reset_mock() self.app.client_manager.share.api_version = api_versions.APIVersion( - api_versions.MAX_VERSION) + api_versions.MAX_VERSION + ) class TestDeleteShareServer(TestShareServer): - def setUp(self): - super(TestDeleteShareServer, self).setUp() + super().setUp() - self.share_server = ( - manila_fakes.FakeShareServer.create_one_server()) + self.share_server = manila_fakes.FakeShareServer.create_one_server() self.servers_mock.get.return_value = self.share_server self.cmd = osc_share_servers.DeleteShareServer(self.app, None) @@ -55,33 +53,30 @@ def test_share_server_delete_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_server_delete(self): - arglist = [ - self.share_server.id - ] - verifylist = [ - ('share_servers', [self.share_server.id]) - ] + arglist = [self.share_server.id] + verifylist = [('share_servers', [self.share_server.id])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.servers_mock.delete.assert_called_once_with( - self.share_server) + self.servers_mock.delete.assert_called_once_with(self.share_server) self.assertIsNone(result) def test_share_server_delete_wait(self): - arglist = [ - self.share_server.id, - '--wait' - ] + arglist = [self.share_server.id, '--wait'] verifylist = [ ('share_servers', [self.share_server.id]), - ('wait', True) + ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -89,37 +84,29 @@ def test_share_server_delete_wait(self): with mock.patch('osc_lib.utils.wait_for_delete', return_value=True): result = self.cmd.take_action(parsed_args) - self.servers_mock.delete.assert_called_once_with( - self.share_server) + self.servers_mock.delete.assert_called_once_with(self.share_server) self.assertIsNone(result) def test_share_server_delete_wait_exception(self): - arglist = [ - self.share_server.id, - '--wait' - ] + arglist = [self.share_server.id, '--wait'] verifylist = [ ('share_servers', [self.share_server.id]), - ('wait', True) + ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch('osc_lib.utils.wait_for_delete', return_value=False): self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args + exceptions.CommandError, self.cmd.take_action, parsed_args ) class TestShowShareServer(TestShareServer): - def setUp(self): - super(TestShowShareServer, self).setUp() + super().setUp() - self.share_server = ( - manila_fakes.FakeShareServer.create_one_server()) + self.share_server = manila_fakes.FakeShareServer.create_one_server() self.servers_mock.get.return_value = self.share_server self.cmd = osc_share_servers.ShowShareServer(self.app, None) @@ -133,30 +120,27 @@ def test_share_server_show_missing_args(self): self.assertRaises( osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_server_show(self): - arglist = [ - self.share_server.id - ] - verifylist = [ - ('share_server', self.share_server.id) - ] + arglist = [self.share_server.id] + verifylist = [('share_server', self.share_server.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) - self.servers_mock.get.assert_called_with( - self.share_server.id - ) + self.servers_mock.get.assert_called_with(self.share_server.id) self.assertCountEqual(self.columns, columns) self.assertCountEqual(self.data, data) class TestListShareServer(TestShareServer): - columns = [ 'ID', 'Host', @@ -166,15 +150,17 @@ class TestListShareServer(TestShareServer): ] def setUp(self): - super(TestListShareServer, self).setUp() + super().setUp() - self.servers_list = ( - manila_fakes.FakeShareServer.create_share_servers( - count=2)) + self.servers_list = manila_fakes.FakeShareServer.create_share_servers( + count=2 + ) self.servers_mock.list.return_value = self.servers_list - self.values = (oscutils.get_dict_properties( - i._info, self.columns) for i in self.servers_list) + self.values = ( + oscutils.get_dict_properties(i._info, self.columns) + for i in self.servers_list + ) self.cmd = osc_share_servers.ListShareServer(self.app, None) @@ -186,18 +172,21 @@ def test_list_share_server(self): columns, data = self.cmd.take_action(parsed_args) - self.servers_mock.list.assert_called_with(search_opts={ - 'status': None, - 'host': None, - 'project_id': None, - }) + self.servers_mock.list.assert_called_with( + search_opts={ + 'status': None, + 'host': None, + 'project_id': None, + } + ) self.assertEqual(self.columns, columns) self.assertEqual(list(self.values), list(data)) def test_share_server_list_by_status(self): arglist = [ - '--status', self.servers_list[0].status, + '--status', + self.servers_list[0].status, ] verifylist = [ ('status', self.servers_list[0].status), @@ -220,11 +209,12 @@ def test_share_server_list_by_status(self): self.assertEqual(list(self.values), list(data)) def test_share_server_list_by_source_share_server(self): - expected_source_share_server_id = ( - self.servers_list[0].source_share_server_id - ) + expected_source_share_server_id = self.servers_list[ + 0 + ].source_share_server_id arglist = [ - '--source-share-server-id', expected_source_share_server_id, + '--source-share-server-id', + expected_source_share_server_id, ] verifylist = [ ('source_share_server_id', expected_source_share_server_id), @@ -249,8 +239,13 @@ def test_share_server_list_by_source_share_server(self): def test_share_server_list_by_identifier(self): expected_identifier = self.servers_list[0].identifier - arglist = ['--identifier', expected_identifier,] - verifylist = [('identifier', expected_identifier),] + arglist = [ + '--identifier', + expected_identifier, + ] + verifylist = [ + ('identifier', expected_identifier), + ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) @@ -271,29 +266,31 @@ def test_share_server_list_by_identifier(self): class TestAdoptShareServer(TestShareServer): - def setUp(self): - super(TestAdoptShareServer, self).setUp() + super().setUp() - self.share_server = ( - manila_fakes.FakeShareServer.create_one_server( - attrs={'status': 'available'} - )) + self.share_server = manila_fakes.FakeShareServer.create_one_server( + attrs={'status': 'available'} + ) self.servers_mock.get.return_value = self.share_server self.servers_mock.manage.return_value = self.share_server self.share_network_subnets_mock = ( - self.app.client_manager.share.share_network_subnets) + self.app.client_manager.share.share_network_subnets + ) self.share_network = ( manila_fakes.FakeShareNetwork.create_one_share_network( attrs={'status': 'available'} - )) + ) + ) self.share_network_subnet = ( - manila_fakes.FakeShareNetworkSubnet.create_one_share_subnet()) + manila_fakes.FakeShareNetworkSubnet.create_one_share_subnet() + ) self.share_networks_mock.get.return_value = self.share_network self.share_network_subnets_mock.get.return_value = ( - self.share_network_subnet) + self.share_network_subnet + ) self.cmd = osc_share_servers.AdoptShareServer(self.app, None) @@ -304,15 +301,21 @@ def test_share_server_adopt_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_server_adopt(self): arglist = [ 'somehost@backend', self.share_network['id'], 'share_server_identifier', - '--share-network-subnet', self.share_network_subnet['id'], + '--share-network-subnet', + self.share_network_subnet['id'], ] verifylist = [ ('host', 'somehost@backend'), @@ -338,15 +341,16 @@ def test_share_server_adopt_wait(self): 'somehost@backend', self.share_network['id'], 'share_server_identifier', - '--share-network-subnet', self.share_network_subnet['id'], - '--wait' + '--share-network-subnet', + self.share_network_subnet['id'], + '--wait', ] verifylist = [ ('host', 'somehost@backend'), ('share_network', self.share_network['id']), ('identifier', 'share_server_identifier'), ('share_network_subnet', self.share_network_subnet['id']), - ('wait', True) + ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -358,7 +362,7 @@ def test_share_server_adopt_wait(self): share_network_id=self.share_network['id'], identifier='share_server_identifier', driver_options={}, - share_network_subnet_id=self.share_network_subnet['id'] + share_network_subnet_id=self.share_network_subnet['id'], ) def test_share_server_adopt_subnet_not_supported(self): @@ -366,33 +370,33 @@ def test_share_server_adopt_subnet_not_supported(self): 'somehost@backend', self.share_network['id'], 'share_server_identifier', - '--share-network-subnet', self.share_network_subnet['id'], - '--wait' + '--share-network-subnet', + self.share_network_subnet['id'], + '--wait', ] verifylist = [ ('host', 'somehost@backend'), ('share_network', self.share_network['id']), ('identifier', 'share_server_identifier'), ('share_network_subnet', self.share_network_subnet['id']), - ('wait', True) + ('wait', True), ] self.app.client_manager.share.api_version = api_versions.APIVersion( - "2.50") + "2.50" + ) parsed_args = self.check_parser(self.cmd, arglist, verifylist) - self.assertRaises(exceptions.CommandError, - self.cmd.take_action, - parsed_args) + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestAbandonShareServer(TestShareServer): - def setUp(self): - super(TestAbandonShareServer, self).setUp() + super().setUp() - self.share_server = ( - manila_fakes.FakeShareServer.create_one_server()) + self.share_server = manila_fakes.FakeShareServer.create_one_server() self.servers_mock.get.return_value = self.share_server self.cmd = osc_share_servers.AbandonShareServer(self.app, None) @@ -404,33 +408,30 @@ def test_share_server_abandon_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_server_abandon(self): - arglist = [ - self.share_server.id - ] - verifylist = [ - ('share_server', [self.share_server.id]) - ] + arglist = [self.share_server.id] + verifylist = [('share_server', [self.share_server.id])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.servers_mock.unmanage.assert_called_with( - self.share_server) + self.servers_mock.unmanage.assert_called_with(self.share_server) self.assertIsNone(result) def test_share_server_abandon_multiple(self): - share_servers = ( - manila_fakes.FakeShareServer.create_share_servers( - count=2)) - arglist = [ - share_servers[0].id, - share_servers[1].id - ] + share_servers = manila_fakes.FakeShareServer.create_share_servers( + count=2 + ) + arglist = [share_servers[0].id, share_servers[1].id] verifylist = [ ('share_server', [share_servers[0].id, share_servers[1].id]) ] @@ -438,18 +439,16 @@ def test_share_server_abandon_multiple(self): result = self.cmd.take_action(parsed_args) - self.assertEqual(self.servers_mock.unmanage.call_count, - len(share_servers)) + self.assertEqual( + self.servers_mock.unmanage.call_count, len(share_servers) + ) self.assertIsNone(result) def test_share_server_abandon_force(self): - arglist = [ - self.share_server.id, - '--force' - ] + arglist = [self.share_server.id, '--force'] verifylist = [ ('share_server', [self.share_server.id]), - ('force', True) + ('force', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -457,8 +456,8 @@ def test_share_server_abandon_force(self): result = self.cmd.take_action(parsed_args) self.servers_mock.unmanage.assert_called_with( - self.share_server, - force=True) + self.share_server, force=True + ) self.assertIsNone(result) def test_share_server_abandon_force_exception(self): @@ -472,87 +471,68 @@ def test_share_server_abandon_force_exception(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.servers_mock.unmanage.side_effect = exceptions.CommandError() - self.assertRaises(exceptions.CommandError, - self.cmd.take_action, - parsed_args) + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_share_server_abandon_wait(self): - arglist = [ - self.share_server.id, - '--wait' - ] - verifylist = [ - ('share_server', [self.share_server.id]), - ('wait', True) - ] + arglist = [self.share_server.id, '--wait'] + verifylist = [('share_server', [self.share_server.id]), ('wait', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch('osc_lib.utils.wait_for_delete', return_value=True): result = self.cmd.take_action(parsed_args) - self.servers_mock.unmanage.assert_called_with( - self.share_server) + self.servers_mock.unmanage.assert_called_with(self.share_server) self.assertIsNone(result) def test_share_server_abandon_wait_error(self): - arglist = [ - self.share_server.id, - '--wait' - ] - verifylist = [ - ('share_server', [self.share_server.id]), - ('wait', True) - ] + arglist = [self.share_server.id, '--wait'] + verifylist = [('share_server', [self.share_server.id]), ('wait', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch('osc_lib.utils.wait_for_delete', return_value=False): self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestSetShareServer(TestShareServer): - def setUp(self): - super(TestSetShareServer, self).setUp() + super().setUp() - self.share_server = ( - manila_fakes.FakeShareServer.create_one_server( - methods={'reset_task_state': None} - ) + self.share_server = manila_fakes.FakeShareServer.create_one_server( + methods={'reset_task_state': None} ) self.servers_mock.get.return_value = self.share_server self.cmd = osc_share_servers.SetShareServer(self.app, None) def test_share_server_set_status(self): - arglist = [ - self.share_server.id, - '--status', 'active' - ] + arglist = [self.share_server.id, '--status', 'active'] verifylist = [ ('share_server', self.share_server.id), - ('status', 'active') + ('status', 'active'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.servers_mock.reset_state.assert_called_with( - self.share_server, - parsed_args.status) + self.share_server, parsed_args.status + ) self.assertIsNone(result) def test_share_server_set_task_state(self): arglist = [ self.share_server.id, - '--task-state', 'migration_in_progress' + '--task-state', + 'migration_in_progress', ] verifylist = [ ('share_server', self.share_server.id), - ('task_state', 'migration_in_progress') + ('task_state', 'migration_in_progress'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -560,41 +540,69 @@ def test_share_server_set_task_state(self): result = self.cmd.take_action(parsed_args) self.servers_mock.reset_task_state.assert_called_with( - self.share_server, - parsed_args.task_state) + self.share_server, parsed_args.task_state + ) self.assertIsNone(result) - def test_share_server_set_status_exception(self): + def test_share_server_set_task_state_none(self): arglist = [ self.share_server.id, - '--status', 'active' + '--task-state', + ] + verifylist = [ + ('share_server', self.share_server.id), + ('task_state', None), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + result = self.cmd.take_action(parsed_args) + + self.servers_mock.reset_task_state.assert_called_with( + self.share_server, None + ) + self.assertIsNone(result) + + def test_share_server_set_task_state_string_none(self): + arglist = [self.share_server.id, '--task-state', 'None'] + verifylist = [ + ('share_server', self.share_server.id), + ('task_state', 'None'), ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + result = self.cmd.take_action(parsed_args) + + self.servers_mock.reset_task_state.assert_called_with( + self.share_server, None + ) + self.assertIsNone(result) + + def test_share_server_set_status_exception(self): + arglist = [self.share_server.id, '--status', 'active'] verifylist = [ ('share_server', self.share_server.id), - ('status', 'active') + ('status', 'active'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.servers_mock.reset_state.side_effect = Exception() self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestShareServerMigrationCancel(TestShareServer): - def setUp(self): - super(TestShareServerMigrationCancel, self).setUp() - - self.share_server = ( - manila_fakes.FakeShareServer.create_one_server( - attrs={ - 'status': 'migrating', - }, - methods={'migration_cancel': None} - ) + super().setUp() + + self.share_server = manila_fakes.FakeShareServer.create_one_server( + attrs={ + 'status': 'migrating', + }, + methods={'migration_cancel': None}, ) self.servers_mock.get.return_value = self.share_server @@ -602,78 +610,71 @@ def setUp(self): self.cmd = osc_share_servers.ShareServerMigrationCancel(self.app, None) def test_share_server_migration_cancel(self): - arglist = [ - self.share_server.id - ] - verifylist = [ - ('share_server', self.share_server.id) - ] + arglist = [self.share_server.id] + verifylist = [('share_server', self.share_server.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.share_server.migration_cancel.assert_called class TestShareServerMigrationComplete(TestShareServer): - def setUp(self): - super(TestShareServerMigrationComplete, self).setUp() - - self.share_server = ( - manila_fakes.FakeShareServer.create_one_server( - attrs={ - 'status': 'migrating', - }, - methods={'migration_complete': None} - ) + super().setUp() + + self.share_server = manila_fakes.FakeShareServer.create_one_server( + attrs={ + 'status': 'migrating', + }, + methods={'migration_complete': None}, ) self.servers_mock.get.return_value = self.share_server # Get the command objects to test self.cmd = osc_share_servers.ShareServerMigrationComplete( - self.app, None) + self.app, None + ) def test_share_server_migration_complete(self): - arglist = [ - self.share_server.id - ] - verifylist = [ - ('share_server', self.share_server.id) - ] + arglist = [self.share_server.id] + verifylist = [('share_server', self.share_server.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.share_server.migration_complete.assert_called class TestShareServerMigrationShow(TestShareServer): - def setUp(self): - super(TestShareServerMigrationShow, self).setUp() + super().setUp() - self.new_share_network = manila_fakes.FakeShareNetwork \ - .create_one_share_network() + self.new_share_network = ( + manila_fakes.FakeShareNetwork.create_one_share_network() + ) self.share_networks_mock.get.return_value = self.new_share_network - self.share_server = ( - manila_fakes.FakeShareServer.create_one_server( - attrs={ - 'status': 'migrating', - 'task_state': 'migration_in_progress' - }, - methods={'migration_get_progress': None} - ) + migration_dict = { + 'total_progress': 'fake', + 'task_state': 'migration_in_progress', + 'destination_share_server_id': 'fake_id', + } + self.share_server = manila_fakes.FakeShareServer.create_one_server( + attrs={ + 'status': 'migrating', + 'task_state': 'migration_in_progress', + }, + methods={'migration_get_progress': None}, ) self.servers_mock.get.return_value = self.share_server + share_client = self.app.client_manager.share + share_client.share_servers.migration_get_progress.return_value = ( + migration_dict + ) # Get the command objects to test self.cmd = osc_share_servers.ShareServerMigrationShow(self.app, None) def test_share_server_migration_show(self): - arglist = [ - self.share_server.id - ] - verifylist = [ - ('share_server', self.share_server.id) - ] + arglist = [self.share_server.id] + verifylist = [('share_server', self.share_server.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.share_server.migration_get_progress.assert_called @@ -681,19 +682,19 @@ def test_share_server_migration_show(self): class TestShareServerMigrationStart(TestShareServer): def setUp(self): - super(TestShareServerMigrationStart, self).setUp() + super().setUp() - self.new_share_network = manila_fakes.FakeShareNetwork \ - .create_one_share_network() + self.new_share_network = ( + manila_fakes.FakeShareNetwork.create_one_share_network() + ) self.share_networks_mock.get.return_value = self.new_share_network - self.share_server = ( - manila_fakes.FakeShareServer.create_one_server( - attrs={ - 'check_only': 'False', - }, - methods={'migration_start': None, 'migration_check': None} - )) + self.share_server = manila_fakes.FakeShareServer.create_one_server( + attrs={ + 'check_only': 'False', + }, + methods={'migration_start': None, 'migration_check': None}, + ) self.servers_mock.get.return_value = self.share_server # Get the command objects to test @@ -705,10 +706,14 @@ def test_share_server_migration_start_with_new_share_network(self): arglist = [ '1234', 'host@backend', - '--preserve-snapshots', 'False', - '--writable', 'False', - '--nondisruptive', 'False', - '--new-share-network', self.new_share_network.id + '--preserve-snapshots', + 'False', + '--writable', + 'False', + '--nondisruptive', + 'False', + '--new-share-network', + self.new_share_network.id, ] verifylist = [ @@ -717,11 +722,12 @@ def test_share_server_migration_start_with_new_share_network(self): ('preserve_snapshots', 'False'), ('writable', 'False'), ('nondisruptive', 'False'), - ('new_share_network', self.new_share_network.id) + ('new_share_network', self.new_share_network.id), ] self.app.client_manager.share.api_version = api_versions.APIVersion( - "2.57") + "2.57" + ) parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) @@ -730,7 +736,7 @@ def test_share_server_migration_start_with_new_share_network(self): 'False', 'False', 'False', - self.new_share_network.id + self.new_share_network.id, ) self.assertEqual(result, ({}, {})) @@ -740,10 +746,14 @@ def test_share_server_migration_start_with_check_only(self): arglist = [ '1234', 'host@backend', - '--preserve-snapshots', 'True', - '--writable', 'True', - '--nondisruptive', 'False', - '--new-share-network', self.new_share_network.id, + '--preserve-snapshots', + 'True', + '--writable', + 'True', + '--nondisruptive', + 'False', + '--new-share-network', + self.new_share_network.id, '--check-only', ] @@ -754,7 +764,7 @@ def test_share_server_migration_start_with_check_only(self): ('writable', 'True'), ('nondisruptive', 'False'), ('new_share_network', self.new_share_network.id), - ('check_only', True) + ('check_only', True), ] expected_result = { @@ -764,7 +774,7 @@ def test_share_server_migration_start_with_check_only(self): 'nondisruptive': 'False', 'preserve_snapshots': 'True', 'share_network_id': None, - 'host': 'host@backend' + 'host': 'host@backend', }, 'supported_capabilities': { 'writable': True, @@ -772,14 +782,15 @@ def test_share_server_migration_start_with_check_only(self): 'preserve_snapshots': True, 'share_network_id': self.new_share_network.id, 'migration_cancel': True, - 'migration_get_progress': True - } + 'migration_get_progress': True, + }, } self.share_server.migration_check.return_value = expected_result self.app.client_manager.share.api_version = api_versions.APIVersion( - "2.57") + "2.57" + ) parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) @@ -789,7 +800,6 @@ def test_share_server_migration_start_with_check_only(self): 'False', 'True', self.new_share_network.id, - ) result_dict = {} for count, column in enumerate(columns): @@ -800,14 +810,19 @@ def test_share_server_migration_start_with_api_version_exception(self): """Test share server migration start with API microversion exception""" self.app.client_manager.share.api_version = api_versions.APIVersion( - "2.50") + "2.50" + ) arglist = [ '1234', 'host@backend', - '--preserve-snapshots', 'False', - '--writable', 'False', - '--nondisruptive', 'False', - '--new-share-network', self.new_share_network.id + '--preserve-snapshots', + 'False', + '--writable', + 'False', + '--nondisruptive', + 'False', + '--new-share-network', + self.new_share_network.id, ] verifylist = [ @@ -816,12 +831,11 @@ def test_share_server_migration_start_with_api_version_exception(self): ('preserve_snapshots', 'False'), ('writable', 'False'), ('nondisruptive', 'False'), - ('new_share_network', self.new_share_network.id) + ('new_share_network', self.new_share_network.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) diff --git a/manilaclient/tests/unit/osc/v2/test_share_snapshot_instance_export_locations.py b/manilaclient/tests/unit/osc/v2/test_share_snapshot_instance_export_locations.py index a368ad19..91c5a095 100644 --- a/manilaclient/tests/unit/osc/v2/test_share_snapshot_instance_export_locations.py +++ b/manilaclient/tests/unit/osc/v2/test_share_snapshot_instance_export_locations.py @@ -15,8 +15,7 @@ from osc_lib import utils as osc_lib_utils -from manilaclient.osc.v2 import (share_snapshot_instance_export_locations as - osc_snapshot_instance_locations) +from manilaclient.osc.v2 import share_snapshot_instance_export_locations from manilaclient.tests.unit.osc import osc_utils from manilaclient.tests.unit.osc.v2 import fakes as manila_fakes @@ -24,62 +23,63 @@ class TestShareSnapshotInstanceExportLocation(manila_fakes.TestShare): - def setUp(self): - super(TestShareSnapshotInstanceExportLocation, self).setUp() + super().setUp() self.share_snapshot_instances_mock = ( - self.app.client_manager.share.share_snapshot_instances) + self.app.client_manager.share.share_snapshot_instances + ) self.share_snapshot_instances_mock.reset_mock() self.share_snapshot_instances_el_mock = ( - self.app.client_manager - .share.share_snapshot_instance_export_locations) + self.app.client_manager.share.share_snapshot_instance_export_locations # noqa: E501 + ) self.share_snapshot_instances_el_mock.reset_mock() class TestShareSnapshotInstanceExportLocationList( - TestShareSnapshotInstanceExportLocation): - + TestShareSnapshotInstanceExportLocation +): def setUp(self): - super(TestShareSnapshotInstanceExportLocationList, self).setUp() + super().setUp() - self.share_snapshot_instance = ( - manila_fakes.FakeShareSnapshotIntances - .create_one_snapshot_instance()) + self.share_snapshot_instance = manila_fakes.FakeShareSnapshotIntances.create_one_snapshot_instance() # noqa: E501 - self.share_snapshot_instances_export_locations = ( - manila_fakes.FakeShareSnapshotInstancesExportLocations - .create_share_snapshot_instances(count=2) + self.share_snapshot_instances_export_locations = manila_fakes.FakeShareSnapshotInstancesExportLocations.create_share_snapshot_instances( # noqa: E501 + count=2 ) self.share_snapshot_instances_mock.get.return_value = ( - self.share_snapshot_instance) + self.share_snapshot_instance + ) self.share_snapshot_instances_el_mock.list.return_value = ( - self.share_snapshot_instances_export_locations) + self.share_snapshot_instances_export_locations + ) - self.cmd = (osc_snapshot_instance_locations - .ShareSnapshotInstanceExportLocationList(self.app, - None)) + self.cmd = share_snapshot_instance_export_locations.ShareSnapshotInstanceExportLocationList( # noqa: E501 + self.app, None + ) def test_share_snapshot_instance_export_location_list_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_snapshot_instance_export_location_list(self): - values = (osc_lib_utils.get_dict_properties( - s._info, COLUMNS) for s in - self.share_snapshot_instances_export_locations) - arglist = [ - self.share_snapshot_instance.id - ] - verifylist = [ - ('instance', self.share_snapshot_instance.id) - ] + values = ( + osc_lib_utils.get_dict_properties(s._info, COLUMNS) + for s in self.share_snapshot_instances_export_locations + ) + arglist = [self.share_snapshot_instance.id] + verifylist = [('instance', self.share_snapshot_instance.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) @@ -89,51 +89,59 @@ def test_share_snapshot_instance_export_location_list(self): class TestShareSnapshotInstanceExportLocationShow( - TestShareSnapshotInstanceExportLocation): - + TestShareSnapshotInstanceExportLocation +): def setUp(self): - super(TestShareSnapshotInstanceExportLocationShow, self).setUp() + super().setUp() - self.share_snapshot_instance = ( - manila_fakes.FakeShareSnapshotIntances - .create_one_snapshot_instance()) + self.share_snapshot_instance = manila_fakes.FakeShareSnapshotIntances.create_one_snapshot_instance() # noqa: E501 self.share_snapshot_instances_export_location = ( - manila_fakes.FakeShareSnapshotInstancesExportLocations - .create_one_snapshot_instance() + manila_fakes.FakeShareSnapshotInstancesExportLocations.create_one_snapshot_instance() # noqa: E501 ) self.share_snapshot_instances_mock.get.return_value = ( - self.share_snapshot_instance) + self.share_snapshot_instance + ) self.share_snapshot_instances_el_mock.get.return_value = ( - self.share_snapshot_instances_export_location) + self.share_snapshot_instances_export_location + ) - self.cmd = (osc_snapshot_instance_locations - .ShareSnapshotInstanceExportLocationShow(self.app, - None)) + self.cmd = share_snapshot_instance_export_locations.ShareSnapshotInstanceExportLocationShow( # noqa: E501 + self.app, None + ) - self.data = (self.share_snapshot_instances_export_location. - _info.values()) - self.columns = (self.share_snapshot_instances_export_location. - _info.keys()) + self.data = ( + self.share_snapshot_instances_export_location._info.values() + ) + self.columns = ( + self.share_snapshot_instances_export_location._info.keys() + ) def test_share_snapshot_instance_export_location_show_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_snapshot_instance_export_location_show(self): arglist = [ self.share_snapshot_instance.id, - self.share_snapshot_instances_export_location.id + self.share_snapshot_instances_export_location.id, ] verifylist = [ ('snapshot_instance', self.share_snapshot_instance.id), - ('export_location', - self.share_snapshot_instances_export_location.id) + ( + 'export_location', + self.share_snapshot_instances_export_location.id, + ), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -141,9 +149,11 @@ def test_share_snapshot_instance_export_location_show(self): columns, data = self.cmd.take_action(parsed_args) self.share_snapshot_instances_mock.get.assert_called_with( - self.share_snapshot_instance.id) + self.share_snapshot_instance.id + ) self.share_snapshot_instances_el_mock.get.assert_called_with( self.share_snapshot_instances_export_location.id, - snapshot_instance=self.share_snapshot_instance) + snapshot_instance=self.share_snapshot_instance, + ) self.assertCountEqual(self.columns, columns) self.assertCountEqual(self.data, data) diff --git a/manilaclient/tests/unit/osc/v2/test_share_snapshot_instances.py b/manilaclient/tests/unit/osc/v2/test_share_snapshot_instances.py index b846548b..58e9de07 100644 --- a/manilaclient/tests/unit/osc/v2/test_share_snapshot_instances.py +++ b/manilaclient/tests/unit/osc/v2/test_share_snapshot_instances.py @@ -19,7 +19,8 @@ from manilaclient.common.apiclient import exceptions as api_exceptions from manilaclient.common import cliutils from manilaclient.osc.v2 import ( - share_snapshot_instances as osc_share_snapshot_instances) + share_snapshot_instances as osc_share_snapshot_instances, +) from manilaclient.tests.unit.osc import osc_utils from manilaclient.tests.unit.osc.v2 import fakes as manila_fakes @@ -34,48 +35,51 @@ 'Share ID', 'Share Instance ID', 'Progress', - 'Provider Location' + 'Provider Location', ] class TestShareSnapshotInstance(manila_fakes.TestShare): - def setUp(self): - super(TestShareSnapshotInstance, self).setUp() + super().setUp() self.share_snapshots_mock = ( - self.app.client_manager.share.share_snapshots) + self.app.client_manager.share.share_snapshots + ) self.share_snapshots_mock.reset_mock() self.share_snapshot_instances_mock = ( - self.app.client_manager.share.share_snapshot_instances) + self.app.client_manager.share.share_snapshot_instances + ) self.share_snapshot_instances_mock.reset_mock() self.share_snapshot_instances_el_mock = ( - self.app.client_manager - .share.share_snapshot_instance_export_locations) + self.app.client_manager.share.share_snapshot_instance_export_locations # noqa: E501 + ) self.share_snapshot_instances_el_mock.reset_mock() class TestShareSnapshotInstanceList(TestShareSnapshotInstance): - def setUp(self): - super(TestShareSnapshotInstanceList, self).setUp() + super().setUp() - self.share_snapshot_instances = ( - manila_fakes.FakeShareSnapshotIntances - .create_share_snapshot_instances(count=2)) + self.share_snapshot_instances = manila_fakes.FakeShareSnapshotIntances.create_share_snapshot_instances( # noqa: E501 + count=2 + ) self.share_snapshot_instances_mock.list.return_value = ( - self.share_snapshot_instances) + self.share_snapshot_instances + ) - self.cmd = ( - osc_share_snapshot_instances.ListShareSnapshotInstance(self.app, - None)) + self.cmd = osc_share_snapshot_instances.ListShareSnapshotInstance( + self.app, None + ) def test_share_snapshot_instance_list(self): - values = (osc_lib_utils.get_dict_properties( - s._info, COLUMNS) for s in self.share_snapshot_instances) + values = ( + osc_lib_utils.get_dict_properties(s._info, COLUMNS) + for s in self.share_snapshot_instances + ) arglist = [] verifylist = [] @@ -88,16 +92,14 @@ def test_share_snapshot_instance_list(self): self.assertEqual(list(values), list(data)) def test_share_snapshot_instance_list_detail(self): - values = (osc_lib_utils.get_dict_properties( - s._info, COLUMNS_DETAIL) for s in self.share_snapshot_instances) + values = ( + osc_lib_utils.get_dict_properties(s._info, COLUMNS_DETAIL) + for s in self.share_snapshot_instances + ) - arglist = [ - '--detailed' - ] + arglist = ['--detailed'] - verifylist = [ - ('detailed', True) - ] + verifylist = [('detailed', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -108,21 +110,21 @@ def test_share_snapshot_instance_list_detail(self): def test_share_snapshot_instance_list_snapshot_id(self): self.share_snapshot = ( - manila_fakes.FakeShareSnapshot.create_one_snapshot()) + manila_fakes.FakeShareSnapshot.create_one_snapshot() + ) self.share_snapshots_mock.get.return_value = self.share_snapshot - self.share_snapshot_instances_mock.list.return_value = ( - [self.share_snapshot_instances[0]]) + self.share_snapshot_instances_mock.list.return_value = [ + self.share_snapshot_instances[0] + ] - values = (osc_lib_utils.get_dict_properties( - s._info, COLUMNS) for s in [self.share_snapshot_instances[0]]) + values = ( + osc_lib_utils.get_dict_properties(s._info, COLUMNS) + for s in [self.share_snapshot_instances[0]] + ) - arglist = [ - '--snapshot', self.share_snapshot.id - ] - verifylist = [ - ('snapshot', self.share_snapshot.id) - ] + arglist = ['--snapshot', self.share_snapshot.id] + verifylist = [('snapshot', self.share_snapshot.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -133,31 +135,32 @@ def test_share_snapshot_instance_list_snapshot_id(self): class TestShareSnapshotInstanceShow(TestShareSnapshotInstance): - def setUp(self): - super(TestShareSnapshotInstanceShow, self).setUp() + super().setUp() - self.share_snapshot_instance = ( - manila_fakes.FakeShareSnapshotIntances - .create_one_snapshot_instance()) + self.share_snapshot_instance = manila_fakes.FakeShareSnapshotIntances.create_one_snapshot_instance() # noqa: E501 self.share_snapshot_instances_mock.get.return_value = ( - self.share_snapshot_instance) + self.share_snapshot_instance + ) - self.share_snapshot_instances_el_list = ( - manila_fakes.FakeShareSnapshotInstancesExportLocations - .create_share_snapshot_instances(count=2) + self.share_snapshot_instances_el_list = manila_fakes.FakeShareSnapshotInstancesExportLocations.create_share_snapshot_instances( # noqa: E501 + count=2 ) self.share_snapshot_instances_el_mock.list.return_value = ( - self.share_snapshot_instances_el_list) + self.share_snapshot_instances_el_list + ) - self.cmd = (osc_share_snapshot_instances - .ShowShareSnapshotInstance(self.app, None)) + self.cmd = osc_share_snapshot_instances.ShowShareSnapshotInstance( + self.app, None + ) self.share_snapshot_instance._info['export_locations'] = ( cliutils.convert_dict_list_to_string( - self.share_snapshot_instances_el_list)) + self.share_snapshot_instances_el_list + ) + ) self.data = self.share_snapshot_instance._info.values() self.columns = self.share_snapshot_instance._info.keys() @@ -166,75 +169,85 @@ def test_share_snapshot_instance_show_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_snapshot_instance_show(self): - arglist = [ - self.share_snapshot_instance.id - ] - verifylist = [ - ('snapshot_instance', self.share_snapshot_instance.id) - ] + arglist = [self.share_snapshot_instance.id] + verifylist = [('snapshot_instance', self.share_snapshot_instance.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.share_snapshot_instances_mock.get.assert_called_with( - self.share_snapshot_instance.id) + self.share_snapshot_instance.id + ) self.assertCountEqual(self.columns, columns) self.assertCountEqual(self.data, data) class TestShareSnapshotInstanceSet(TestShareSnapshotInstance): - def setUp(self): - super(TestShareSnapshotInstanceSet, self).setUp() + super().setUp() - self.share_snapshot_instance = ( - manila_fakes.FakeShareSnapshotIntances - .create_one_snapshot_instance()) + self.share_snapshot_instance = manila_fakes.FakeShareSnapshotIntances.create_one_snapshot_instance() # noqa: E501 self.snapshot_instance_status = 'available' - self.cmd = (osc_share_snapshot_instances - .SetShareSnapshotInstance(self.app, None)) + self.cmd = osc_share_snapshot_instances.SetShareSnapshotInstance( + self.app, None + ) def test_share_snapshot_instance_set_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_snapshot_instance_set_instance_not_found(self): arglist = [ self.share_snapshot_instance.id, - '--status', self.snapshot_instance_status + '--status', + self.snapshot_instance_status, ] verifylist = [ ('snapshot_instance', self.share_snapshot_instance.id), - ('status', self.snapshot_instance_status) + ('status', self.snapshot_instance_status), ] self.share_snapshot_instances_mock.reset_state.side_effect = ( - api_exceptions.NotFound()) + api_exceptions.NotFound() + ) parsed_args = self.check_parser(self.cmd, arglist, verifylist) - self.assertRaises(osc_exceptions.CommandError, - self.cmd.take_action, parsed_args) + self.assertRaises( + osc_exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_share_snapshot_instance_set(self): arglist = [ self.share_snapshot_instance.id, - '--status', self.snapshot_instance_status + '--status', + self.snapshot_instance_status, ] verifylist = [ ('snapshot_instance', self.share_snapshot_instance.id), - ('status', self.snapshot_instance_status) + ('status', self.snapshot_instance_status), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.share_snapshot_instances_mock.reset_state.assert_called_with( - self.share_snapshot_instance.id, self.snapshot_instance_status) + self.share_snapshot_instance.id, self.snapshot_instance_status + ) diff --git a/manilaclient/tests/unit/osc/v2/test_share_snapshots.py b/manilaclient/tests/unit/osc/v2/test_share_snapshots.py index 2ffe50a1..59e6e9b1 100644 --- a/manilaclient/tests/unit/osc/v2/test_share_snapshots.py +++ b/manilaclient/tests/unit/osc/v2/test_share_snapshots.py @@ -39,14 +39,13 @@ 'Share ID', 'Share Proto', 'Share Size', - 'User ID' + 'User ID', ] class TestShareSnapshot(manila_fakes.TestShare): - def setUp(self): - super(TestShareSnapshot, self).setUp() + super().setUp() self.shares_mock = self.app.client_manager.share.shares self.shares_mock.reset_mock() @@ -54,20 +53,22 @@ def setUp(self): self.snapshots_mock = self.app.client_manager.share.share_snapshots self.snapshots_mock.reset_mock() self.app.client_manager.share.api_version = api_versions.APIVersion( - api_versions.MAX_VERSION) + api_versions.MAX_VERSION + ) self.export_locations_mock = ( - self.app.client_manager.share.share_snapshot_export_locations) + self.app.client_manager.share.share_snapshot_export_locations + ) self.export_locations_mock.reset_mock() self.app.client_manager.share.api_version = api_versions.APIVersion( - api_versions.MAX_VERSION) + api_versions.MAX_VERSION + ) class TestShareSnapshotCreate(TestShareSnapshot): - def setUp(self): - super(TestShareSnapshotCreate, self).setUp() + super().setUp() self.share = manila_fakes.FakeShare.create_one_share() self.shares_mock.create.return_value = self.share @@ -77,7 +78,8 @@ def setUp(self): self.share_snapshot = ( manila_fakes.FakeShareSnapshot.create_one_snapshot( attrs={'status': 'available'} - )) + ) + ) self.snapshots_mock.get.return_value = self.share_snapshot self.snapshots_mock.create.return_value = self.share_snapshot @@ -90,16 +92,17 @@ def test_share_snapshot_create_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_snapshot_create_required_args(self): - arglist = [ - self.share.id - ] - verifylist = [ - ('share', self.share.id) - ] + arglist = [self.share.id] + verifylist = [('share', self.share.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -110,21 +113,15 @@ def test_share_snapshot_create_required_args(self): force=False, name=None, description=None, - metadata={} + metadata={}, ) self.assertCountEqual(self.columns, columns) self.assertCountEqual(self.data, data) def test_share_snapshot_create_force(self): - arglist = [ - self.share.id, - '--force' - ] - verifylist = [ - ('share', self.share.id), - ('force', True) - ] + arglist = [self.share.id, '--force'] + verifylist = [('share', self.share.id), ('force', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -135,7 +132,7 @@ def test_share_snapshot_create_force(self): force=True, name=None, description=None, - metadata={} + metadata={}, ) self.assertCountEqual(columns, columns) @@ -144,13 +141,15 @@ def test_share_snapshot_create_force(self): def test_share_snapshot_create(self): arglist = [ self.share.id, - '--name', self.share_snapshot.name, - '--description', self.share_snapshot.description + '--name', + self.share_snapshot.name, + '--description', + self.share_snapshot.description, ] verifylist = [ ('share', self.share.id), ('name', self.share_snapshot.name), - ('description', self.share_snapshot.description) + ('description', self.share_snapshot.description), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -162,7 +161,7 @@ def test_share_snapshot_create(self): force=False, name=self.share_snapshot.name, description=self.share_snapshot.description, - metadata={} + metadata={}, ) self.assertCountEqual(self.columns, columns) @@ -171,10 +170,14 @@ def test_share_snapshot_create(self): def test_share_snapshot_create_metadata(self): arglist = [ self.share.id, - '--name', self.share_snapshot.name, - '--description', self.share_snapshot.description, - '--property', 'Manila=zorilla', - '--property', 'Zorilla=manila' + '--name', + self.share_snapshot.name, + '--description', + self.share_snapshot.description, + '--property', + 'Manila=zorilla', + '--property', + 'Zorilla=manila', ] verifylist = [ ('share', self.share.id), @@ -199,14 +202,8 @@ def test_share_snapshot_create_metadata(self): self.assertCountEqual(self.data, data) def test_share_snapshot_create_wait(self): - arglist = [ - self.share.id, - '--wait' - ] - verifylist = [ - ('share', self.share.id), - ('wait', True) - ] + arglist = [self.share.id, '--wait'] + verifylist = [('share', self.share.id), ('wait', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -217,24 +214,17 @@ def test_share_snapshot_create_wait(self): force=False, name=None, description=None, - metadata={} + metadata={}, ) - self.snapshots_mock.get.assert_called_with( - self.share_snapshot.id) + self.snapshots_mock.get.assert_called_with(self.share_snapshot.id) self.assertCountEqual(self.columns, columns) self.assertCountEqual(self.data, data) @mock.patch('manilaclient.osc.v2.share_snapshots.LOG') def test_share_snapshot_create_wait_error(self, mock_logger): - arglist = [ - self.share.id, - '--wait' - ] - verifylist = [ - ('share', self.share.id), - ('wait', True) - ] + arglist = [self.share.id, '--wait'] + verifylist = [('share', self.share.id), ('wait', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -246,25 +236,25 @@ def test_share_snapshot_create_wait_error(self, mock_logger): force=False, name=None, description=None, - metadata={} + metadata={}, ) mock_logger.error.assert_called_with( - "ERROR: Share snapshot is in error state.") + "ERROR: Share snapshot is in error state." + ) - self.snapshots_mock.get.assert_called_with( - self.share_snapshot.id) + self.snapshots_mock.get.assert_called_with(self.share_snapshot.id) self.assertCountEqual(self.columns, columns) self.assertCountEqual(self.data, data) class TestShareSnapshotDelete(TestShareSnapshot): - def setUp(self): - super(TestShareSnapshotDelete, self).setUp() + super().setUp() self.share_snapshot = ( - manila_fakes.FakeShareSnapshot.create_one_snapshot()) + manila_fakes.FakeShareSnapshot.create_one_snapshot() + ) self.snapshots_mock.get.return_value = self.share_snapshot @@ -274,16 +264,17 @@ def test_share_snapshot_delete_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_snapshot_delete(self): - arglist = [ - self.share_snapshot.id - ] - verifylist = [ - ('snapshot', [self.share_snapshot.id]) - ] + arglist = [self.share_snapshot.id] + verifylist = [('snapshot', [self.share_snapshot.id])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -293,31 +284,23 @@ def test_share_snapshot_delete(self): self.assertIsNone(result) def test_share_snapshot_delete_force(self): - arglist = [ - self.share_snapshot.id, - '--force' - ] - verifylist = [ - ('snapshot', [self.share_snapshot.id]), - ('force', True) - ] + arglist = [self.share_snapshot.id, '--force'] + verifylist = [('snapshot', [self.share_snapshot.id]), ('force', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.snapshots_mock.force_delete.assert_called_with( - self.share_snapshot) + self.share_snapshot + ) self.assertIsNone(result) def test_share_snapshot_delete_multiple(self): share_snapshots = ( - manila_fakes.FakeShareSnapshot.create_share_snapshots( - count=2)) - arglist = [ - share_snapshots[0].id, - share_snapshots[1].id - ] + manila_fakes.FakeShareSnapshot.create_share_snapshots(count=2) + ) + arglist = [share_snapshots[0].id, share_snapshots[1].id] verifylist = [ ('snapshot', [share_snapshots[0].id, share_snapshots[1].id]) ] @@ -325,34 +308,25 @@ def test_share_snapshot_delete_multiple(self): result = self.cmd.take_action(parsed_args) - self.assertEqual(self.snapshots_mock.delete.call_count, - len(share_snapshots)) + self.assertEqual( + self.snapshots_mock.delete.call_count, len(share_snapshots) + ) self.assertIsNone(result) def test_share_snapshot_delete_exception(self): - arglist = [ - self.share_snapshot.id - ] - verifylist = [ - ('snapshot', [self.share_snapshot.id]) - ] + arglist = [self.share_snapshot.id] + verifylist = [('snapshot', [self.share_snapshot.id])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.snapshots_mock.delete.side_effect = exceptions.CommandError() - self.assertRaises(exceptions.CommandError, - self.cmd.take_action, - parsed_args) + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_share_snapshot_delete_wait(self): - arglist = [ - self.share_snapshot.id, - '--wait' - ] - verifylist = [ - ('snapshot', [self.share_snapshot.id]), - ('wait', True) - ] + arglist = [self.share_snapshot.id, '--wait'] + verifylist = [('snapshot', [self.share_snapshot.id]), ('wait', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -363,38 +337,29 @@ def test_share_snapshot_delete_wait(self): self.assertIsNone(result) def test_share_snapshot_delete_wait_error(self): - arglist = [ - self.share_snapshot.id, - '--wait' - ] - verifylist = [ - ('snapshot', [self.share_snapshot.id]), - ('wait', True) - ] + arglist = [self.share_snapshot.id, '--wait'] + verifylist = [('snapshot', [self.share_snapshot.id]), ('wait', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch('osc_lib.utils.wait_for_delete', return_value=False): self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args + exceptions.CommandError, self.cmd.take_action, parsed_args ) class TestShareSnapshotShow(TestShareSnapshot): - def setUp(self): - super(TestShareSnapshotShow, self).setUp() + super().setUp() self.export_location = ( - manila_fakes.FakeShareExportLocation.create_one_export_location()) + manila_fakes.FakeShareExportLocation.create_one_export_location() + ) self.share_snapshot = ( manila_fakes.FakeShareSnapshot.create_one_snapshot( - attrs={ - 'export_locations': self.export_location - } - )) + attrs={'export_locations': self.export_location} + ) + ) self.snapshots_mock.get.return_value = self.share_snapshot self.cmd = osc_share_snapshots.ShowShareSnapshot(self.app, None) @@ -407,21 +372,23 @@ def test_share_snapshot_show_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_snapshot_show(self): - arglist = [ - self.share_snapshot.id - ] - verifylist = [ - ('snapshot', self.share_snapshot.id) - ] + arglist = [self.share_snapshot.id] + verifylist = [('snapshot', self.share_snapshot.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) cliutils.convert_dict_list_to_string = mock.Mock() cliutils.convert_dict_list_to_string.return_value = ( - self.export_location) + self.export_location + ) columns, data = self.cmd.take_action(parsed_args) self.snapshots_mock.get.assert_called_with(self.share_snapshot.id) @@ -430,14 +397,14 @@ def test_share_snapshot_show(self): class TestShareSnapshotSet(TestShareSnapshot): - def setUp(self): - super(TestShareSnapshotSet, self).setUp() + super().setUp() self.share_snapshot = ( manila_fakes.FakeShareSnapshot.create_one_snapshot( methods={"set_metadata": None} - )) + ) + ) self.snapshots_mock.get.return_value = self.share_snapshot @@ -445,64 +412,56 @@ def setUp(self): def test_set_snapshot_name(self): snapshot_name = 'snapshot-name-' + uuid.uuid4().hex - arglist = [ - self.share_snapshot.id, - '--name', snapshot_name - ] + arglist = [self.share_snapshot.id, '--name', snapshot_name] verifylist = [ ('snapshot', self.share_snapshot.id), - ('name', snapshot_name) + ('name', snapshot_name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.snapshots_mock.update.assert_called_with( - self.share_snapshot, - display_name=parsed_args.name) + self.share_snapshot, display_name=parsed_args.name + ) self.assertIsNone(result) def test_set_snapshot_description(self): description = 'snapshot-description-' + uuid.uuid4().hex - arglist = [ - self.share_snapshot.id, - '--description', description - ] + arglist = [self.share_snapshot.id, '--description', description] verifylist = [ ('snapshot', self.share_snapshot.id), - ('description', description) + ('description', description), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.snapshots_mock.update.assert_called_with( - self.share_snapshot, - display_description=parsed_args.description) + self.share_snapshot, display_description=parsed_args.description + ) self.assertIsNone(result) def test_set_snapshot_status(self): - arglist = [ - self.share_snapshot.id, - '--status', 'available' - ] + arglist = [self.share_snapshot.id, '--status', 'available'] verifylist = [ ('snapshot', self.share_snapshot.id), - ('status', 'available') + ('status', 'available'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.snapshots_mock.reset_state.assert_called_with( - self.share_snapshot, - parsed_args.status) + self.share_snapshot, parsed_args.status + ) self.assertIsNone(result) def test_set_snapshot_property(self): arglist = [ self.share_snapshot.id, - '--property', 'Zorilla=manila', + '--property', + 'Zorilla=manila', ] verifylist = [ ('snapshot', self.share_snapshot.id), @@ -513,193 +472,175 @@ def test_set_snapshot_property(self): self.cmd.take_action(parsed_args) self.share_snapshot.set_metadata.assert_called_with( - {'Zorilla': 'manila'}) + {'Zorilla': 'manila'} + ) def test_set_snapshot_update_exception(self): snapshot_name = 'snapshot-name-' + uuid.uuid4().hex - arglist = [ - self.share_snapshot.id, - '--name', snapshot_name - ] + arglist = [self.share_snapshot.id, '--name', snapshot_name] verifylist = [ ('snapshot', self.share_snapshot.id), - ('name', snapshot_name) + ('name', snapshot_name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.snapshots_mock.update.side_effect = Exception() self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_set_snapshot_status_exception(self): - arglist = [ - self.share_snapshot.id, - '--status', 'available' - ] + arglist = [self.share_snapshot.id, '--status', 'available'] verifylist = [ ('snapshot', self.share_snapshot.id), - ('status', 'available') + ('status', 'available'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.snapshots_mock.reset_state.side_effect = Exception() self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_set_snapshot_property_exception(self): arglist = [ - '--property', 'key=', + '--property', + 'key=', self.share_snapshot.id, ] verifylist = [ ('property', {'key': ''}), - ('snapshot', self.share_snapshot.id) + ('snapshot', self.share_snapshot.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) - self.share_snapshot.set_metadata.assert_called_with( - {'key': ''}) + self.share_snapshot.set_metadata.assert_called_with({'key': ''}) # '--property' takes key=value arguments # missing a value would raise a BadRequest self.share_snapshot.set_metadata.side_effect = exceptions.BadRequest self.assertRaises( - exceptions.CommandError, self.cmd.take_action, - parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestShareSnapshotUnset(TestShareSnapshot): - def setUp(self): - super(TestShareSnapshotUnset, self).setUp() + super().setUp() self.share_snapshot = ( manila_fakes.FakeShareSnapshot.create_one_snapshot( methods={"delete_metadata": None} - )) + ) + ) self.snapshots_mock.get.return_value = self.share_snapshot self.cmd = osc_share_snapshots.UnsetShareSnapshot(self.app, None) def test_unset_snapshot_name(self): - arglist = [ - self.share_snapshot.id, - '--name' - ] - verifylist = [ - ('snapshot', self.share_snapshot.id), - ('name', True) - ] + arglist = [self.share_snapshot.id, '--name'] + verifylist = [('snapshot', self.share_snapshot.id), ('name', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.snapshots_mock.update.assert_called_with( - self.share_snapshot, - display_name=None) + self.share_snapshot, display_name=None + ) self.assertIsNone(result) def test_unset_snapshot_description(self): - arglist = [ - self.share_snapshot.id, - '--description' - ] + arglist = [self.share_snapshot.id, '--description'] verifylist = [ ('snapshot', self.share_snapshot.id), - ('description', True) + ('description', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.snapshots_mock.update.assert_called_with( - self.share_snapshot, - display_description=None) + self.share_snapshot, display_description=None + ) self.assertIsNone(result) def test_unset_snapshot_property(self): arglist = [ - '--property', 'Manila', + '--property', + 'Manila', self.share_snapshot.id, ] verifylist = [ ('property', ['Manila']), - ('snapshot', self.share_snapshot.id) + ('snapshot', self.share_snapshot.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.share_snapshot.delete_metadata.assert_called_with( - parsed_args.property) + parsed_args.property + ) def test_unset_snapshot_name_exception(self): - arglist = [ - self.share_snapshot.id, - '--name' - ] - verifylist = [ - ('snapshot', self.share_snapshot.id), - ('name', True) - ] + arglist = [self.share_snapshot.id, '--name'] + verifylist = [('snapshot', self.share_snapshot.id), ('name', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.snapshots_mock.update.side_effect = Exception() self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_unset_snapshot_property_exception(self): arglist = [ - '--property', 'Manila', + '--property', + 'Manila', self.share_snapshot.id, ] verifylist = [ ('property', ['Manila']), - ('snapshot', self.share_snapshot.id) + ('snapshot', self.share_snapshot.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.share_snapshot.delete_metadata.assert_called_with( - parsed_args.property) + parsed_args.property + ) # 404 Not Found would be raised, if property 'Manila' doesn't exist self.share_snapshot.delete_metadata.side_effect = exceptions.NotFound self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) @ddt.ddt class TestShareSnapshotList(TestShareSnapshot): - def setUp(self): - super(TestShareSnapshotList, self).setUp() + super().setUp() self.share_snapshots = ( - manila_fakes.FakeShareSnapshot.create_share_snapshots( - count=2)) + manila_fakes.FakeShareSnapshot.create_share_snapshots(count=2) + ) self.snapshots_list = oscutils.sort_items( - self.share_snapshots, - 'name:asc', - str) + self.share_snapshots, 'name:asc', str + ) self.snapshots_mock.list.return_value = self.snapshots_list - self.values = (oscutils.get_dict_properties( - s._info, COLUMNS) for s in self.snapshots_list) + self.values = ( + oscutils.get_dict_properties(s._info, COLUMNS) + for s in self.snapshots_list + ) self.cmd = osc_share_snapshots.ListShareSnapshot(self.app, None) @@ -724,7 +665,8 @@ def test_list_snapshots(self): 'name~': None, 'description~': None, 'description': None, - }) + } + ) self.assertEqual(COLUMNS, columns) self.assertEqual(list(self.values), list(data)) @@ -732,16 +674,14 @@ def test_list_snapshots(self): def test_list_snapshots_all_projects(self): all_tenants_list = COLUMNS.copy() all_tenants_list.append('Project ID') - list_values = (oscutils.get_dict_properties( - s._info, all_tenants_list) for s in self.snapshots_list) + list_values = ( + oscutils.get_dict_properties(s._info, all_tenants_list) + for s in self.snapshots_list + ) - arglist = [ - '--all-projects' - ] + arglist = ['--all-projects'] - verifylist = [ - ('all_projects', True) - ] + verifylist = [('all_projects', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -760,22 +700,21 @@ def test_list_snapshots_all_projects(self): 'name~': None, 'description~': None, 'description': None, - }) + } + ) self.assertEqual(all_tenants_list, columns) self.assertEqual(list(list_values), list(data)) def test_list_snapshots_detail(self): - values = (oscutils.get_dict_properties( - s._info, COLUMNS_DETAIL) for s in self.snapshots_list) + values = ( + oscutils.get_dict_properties(s._info, COLUMNS_DETAIL) + for s in self.snapshots_list + ) - arglist = [ - '--detail' - ] + arglist = ['--detail'] - verifylist = [ - ('detail', True) - ] + verifylist = [('detail', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -793,8 +732,9 @@ def test_list_snapshots_detail(self): 'metadata': {}, 'name~': None, 'description~': None, - 'description': None - }) + 'description': None, + } + ) self.assertEqual(COLUMNS_DETAIL, columns) self.assertEqual(list(values), list(data)) @@ -804,43 +744,35 @@ def test_list_snapshots_api_version_exception(self, v): self.app.client_manager.share.api_version = api_versions.APIVersion(v) if v == "2.35": - arglist = [ - '--description', 'Description' - ] - verifylist = [ - ('description', 'Description') - ] + arglist = ['--description', 'Description'] + verifylist = [('description', 'Description')] elif v == "2.78": arglist = [ '--count', ] - verifylist = [ - ('count', True) - ] + verifylist = [('count', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_list_snapshots_share_id(self): self.share = manila_fakes.FakeShare.create_one_share( - attrs={'id': self.snapshots_list[0].id}) + attrs={'id': self.snapshots_list[0].id} + ) self.shares_mock.get.return_value = self.share self.snapshots_mock.list.return_value = [self.snapshots_list[0]] - values = (oscutils.get_dict_properties( - s._info, COLUMNS) for s in [self.snapshots_list[0]]) + values = ( + oscutils.get_dict_properties(s._info, COLUMNS) + for s in [self.snapshots_list[0]] + ) - arglist = [ - '--share', self.share.id - ] - verifylist = [ - ('share', self.share.id) - ] + arglist = ['--share', self.share.id] + verifylist = [('share', self.share.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -858,24 +790,24 @@ def test_list_snapshots_share_id(self): 'metadata': {}, 'name~': None, 'description~': None, - 'description': None - }) + 'description': None, + } + ) self.assertEqual(COLUMNS, columns) self.assertEqual(list(values), list(data)) def test_list_snapshots_with_count(self): self.app.client_manager.share.api_version = api_versions.APIVersion( - '2.79') + '2.79' + ) self.snapshots_mock.list.return_value = self.snapshots_list, 2 arglist = [ '--count', ] - verifylist = [ - ('count', True) - ] + verifylist = [('count', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -895,27 +827,27 @@ def test_list_snapshots_with_count(self): 'description~': None, 'description': None, 'with_count': True, - }) + } + ) class TestShareSnapshotAdopt(TestShareSnapshot): - def setUp(self): - super(TestShareSnapshotAdopt, self).setUp() + super().setUp() self.share = manila_fakes.FakeShare.create_one_share() self.shares_mock.get.return_value = self.share self.share_snapshot = ( manila_fakes.FakeShareSnapshot.create_one_snapshot( - attrs={ - 'status': 'available' - } - )) + attrs={'status': 'available'} + ) + ) self.snapshots_mock.get.return_value = self.share_snapshot self.export_location = ( - manila_fakes.FakeShareExportLocation.create_one_export_location()) + manila_fakes.FakeShareExportLocation.create_one_export_location() + ) self.snapshots_mock.manage.return_value = self.share_snapshot @@ -928,17 +860,19 @@ def test_share_snapshot_adopt_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_snapshot_adopt(self): - arglist = [ - self.share.id, - self.export_location.fake_path - ] + arglist = [self.share.id, self.export_location.fake_path] verifylist = [ ('share', self.share.id), - ('provider_location', self.export_location.fake_path) + ('provider_location', self.export_location.fake_path), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -950,7 +884,7 @@ def test_snapshot_adopt(self): provider_location=self.export_location.fake_path, driver_options={}, name=None, - description=None + description=None, ) self.assertCountEqual(self.columns, columns) @@ -961,12 +895,13 @@ def test_snapshot_adopt_name(self): arglist = [ self.share.id, self.export_location.fake_path, - '--name', name, + '--name', + name, ] verifylist = [ ('share', self.share.id), ('provider_location', self.export_location.fake_path), - ('name', name) + ('name', name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -978,7 +913,7 @@ def test_snapshot_adopt_name(self): provider_location=self.export_location.fake_path, driver_options={}, name=name, - description=None + description=None, ) self.assertCountEqual(self.columns, columns) @@ -988,13 +923,15 @@ def test_snapshot_adopt_driver_option(self): arglist = [ self.share.id, self.export_location.fake_path, - '--driver-option', 'key1=value1', - '--driver-option', 'key2=value2' + '--driver-option', + 'key1=value1', + '--driver-option', + 'key2=value2', ] verifylist = [ ('share', self.share.id), ('provider_location', self.export_location.fake_path), - ('driver_option', {'key1': 'value1', 'key2': 'value2'}) + ('driver_option', {'key1': 'value1', 'key2': 'value2'}), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -1004,27 +941,20 @@ def test_snapshot_adopt_driver_option(self): self.snapshots_mock.manage.assert_called_with( share=self.share, provider_location=self.export_location.fake_path, - driver_options={ - 'key1': 'value1', - 'key2': 'value2' - }, + driver_options={'key1': 'value1', 'key2': 'value2'}, name=None, - description=None + description=None, ) self.assertCountEqual(self.columns, columns) self.assertCountEqual(self.data, data) def test_snapshot_adopt_wait(self): - arglist = [ - self.share.id, - self.export_location.fake_path, - '--wait' - ] + arglist = [self.share.id, self.export_location.fake_path, '--wait'] verifylist = [ ('share', self.share.id), ('provider_location', self.export_location.fake_path), - ('wait', True) + ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -1036,22 +966,18 @@ def test_snapshot_adopt_wait(self): provider_location=self.export_location.fake_path, driver_options={}, name=None, - description=None + description=None, ) self.assertCountEqual(self.columns, columns) self.assertCountEqual(self.data, data) def test_snapshot_adopt_wait_error(self): - arglist = [ - self.share.id, - self.export_location.fake_path, - '--wait' - ] + arglist = [self.share.id, self.export_location.fake_path, '--wait'] verifylist = [ ('share', self.share.id), ('provider_location', self.export_location.fake_path), - ('wait', True) + ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -1064,21 +990,21 @@ def test_snapshot_adopt_wait_error(self): provider_location=self.export_location.fake_path, driver_options={}, name=None, - description=None + description=None, ) self.assertCountEqual(self.columns, columns) self.assertCountEqual(self.data, data) class TestShareSnapshotAbandon(TestShareSnapshot): - def setUp(self): - super(TestShareSnapshotAbandon, self).setUp() + super().setUp() self.share_snapshot = ( manila_fakes.FakeShareSnapshot.create_one_snapshot( attrs={'status': 'available'} - )) + ) + ) self.snapshots_mock.get.return_value = self.share_snapshot @@ -1088,16 +1014,17 @@ def test_share_snapshot_abandon_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_snapshot_abandon(self): - arglist = [ - self.share_snapshot.id - ] - verifylist = [ - ('snapshot', [self.share_snapshot.id]) - ] + arglist = [self.share_snapshot.id] + verifylist = [('snapshot', [self.share_snapshot.id])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -1108,12 +1035,9 @@ def test_share_snapshot_abandon(self): def test_share_snapshot_abandon_multiple(self): share_snapshots = ( - manila_fakes.FakeShareSnapshot.create_share_snapshots( - count=2)) - arglist = [ - share_snapshots[0].id, - share_snapshots[1].id - ] + manila_fakes.FakeShareSnapshot.create_share_snapshots(count=2) + ) + arglist = [share_snapshots[0].id, share_snapshots[1].id] verifylist = [ ('snapshot', [share_snapshots[0].id, share_snapshots[1].id]) ] @@ -1121,74 +1045,59 @@ def test_share_snapshot_abandon_multiple(self): result = self.cmd.take_action(parsed_args) - self.assertEqual(self.snapshots_mock.unmanage.call_count, - len(share_snapshots)) + self.assertEqual( + self.snapshots_mock.unmanage.call_count, len(share_snapshots) + ) self.assertIsNone(result) def test_share_snapshot_abandon_wait(self): - arglist = [ - self.share_snapshot.id, - '--wait' - ] - verifylist = [ - ('snapshot', [self.share_snapshot.id]), - ('wait', True) - ] + arglist = [self.share_snapshot.id, '--wait'] + verifylist = [('snapshot', [self.share_snapshot.id]), ('wait', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch('osc_lib.utils.wait_for_delete', return_value=True): result = self.cmd.take_action(parsed_args) self.snapshots_mock.unmanage.assert_called_with( - self.share_snapshot) + self.share_snapshot + ) self.assertIsNone(result) def test_share_snapshot_abandon_wait_error(self): - arglist = [ - self.share_snapshot.id, - '--wait' - ] - verifylist = [ - ('snapshot', [self.share_snapshot.id]), - ('wait', True) - ] + arglist = [self.share_snapshot.id, '--wait'] + verifylist = [('snapshot', [self.share_snapshot.id]), ('wait', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch('osc_lib.utils.wait_for_delete', return_value=False): self.assertRaises( - exceptions.CommandError, - self.cmd.take_action, - parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestShareSnapshotAccessAllow(TestShareSnapshot): - def setUp(self): - super(TestShareSnapshotAccessAllow, self).setUp() + super().setUp() self.share_snapshot = ( - manila_fakes.FakeShareSnapshot.create_one_snapshot()) + manila_fakes.FakeShareSnapshot.create_one_snapshot() + ) self.snapshots_mock.get.return_value = self.share_snapshot self.access_rule = ( - manila_fakes.FakeSnapshotAccessRule.create_one_access_rule()) + manila_fakes.FakeSnapshotAccessRule.create_one_access_rule() + ) self.snapshots_mock.allow.return_value = self.access_rule._info - self.cmd = osc_share_snapshots.ShareSnapshotAccessAllow( - self.app, None) + self.cmd = osc_share_snapshots.ShareSnapshotAccessAllow(self.app, None) def test_share_snapshot_access_allow(self): - arglist = [ - self.share_snapshot.id, - 'user', - 'demo' - ] + arglist = [self.share_snapshot.id, 'user', 'demo'] verifylist = [ ('snapshot', self.share_snapshot.id), ('access_type', 'user'), - ('access_to', 'demo') + ('access_to', 'demo'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -1196,48 +1105,42 @@ def test_share_snapshot_access_allow(self): columns, data = self.cmd.take_action(parsed_args) self.snapshots_mock.allow.assert_called_with( - snapshot=self.share_snapshot, - access_type='user', - access_to='demo' + snapshot=self.share_snapshot, access_type='user', access_to='demo' ) self.assertEqual(tuple(self.access_rule._info.keys()), columns) self.assertCountEqual(self.access_rule._info.values(), data) def test_share_snapshot_access_allow_exception(self): - arglist = [ - self.share_snapshot.id, - 'user', - 'demo' - ] + arglist = [self.share_snapshot.id, 'user', 'demo'] verifylist = [ ('snapshot', self.share_snapshot.id), ('access_type', 'user'), - ('access_to', 'demo') + ('access_to', 'demo'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.snapshots_mock.allow.side_effect = exceptions.CommandError() - self.assertRaises(exceptions.CommandError, - self.cmd.take_action, - parsed_args) + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestShareSnapshotAccessDeny(TestShareSnapshot): - def setUp(self): - super(TestShareSnapshotAccessDeny, self).setUp() + super().setUp() self.share_snapshot = ( - manila_fakes.FakeShareSnapshot.create_one_snapshot()) + manila_fakes.FakeShareSnapshot.create_one_snapshot() + ) self.snapshots_mock.get.return_value = self.share_snapshot self.access_rule = ( - manila_fakes.FakeSnapshotAccessRule.create_one_access_rule()) + manila_fakes.FakeSnapshotAccessRule.create_one_access_rule() + ) - self.cmd = osc_share_snapshots.ShareSnapshotAccessDeny( - self.app, None) + self.cmd = osc_share_snapshots.ShareSnapshotAccessDeny(self.app, None) def test_share_snapshot_access_deny(self): arglist = [ @@ -1254,15 +1157,14 @@ def test_share_snapshot_access_deny(self): result = self.cmd.take_action(parsed_args) self.snapshots_mock.deny.assert_called_with( - snapshot=self.share_snapshot, - id=self.access_rule.id + snapshot=self.share_snapshot, id=self.access_rule.id ) self.assertIsNone(result) def test_share_snapshot_access_deny_multiple(self): - access_rules = ( - manila_fakes.FakeSnapshotAccessRule.create_access_rules( - count=2)) + access_rules = manila_fakes.FakeSnapshotAccessRule.create_access_rules( + count=2 + ) arglist = [ self.share_snapshot.id, @@ -1278,8 +1180,9 @@ def test_share_snapshot_access_deny_multiple(self): result = self.cmd.take_action(parsed_args) - self.assertEqual(self.snapshots_mock.deny.call_count, - len(access_rules)) + self.assertEqual( + self.snapshots_mock.deny.call_count, len(access_rules) + ) self.assertIsNone(result) def test_share_snapshot_access_deny_exception(self): @@ -1295,13 +1198,12 @@ def test_share_snapshot_access_deny_exception(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.snapshots_mock.deny.side_effect = exceptions.CommandError() - self.assertRaises(exceptions.CommandError, - self.cmd.take_action, - parsed_args) + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestShareSnapshotAccessList(TestShareSnapshot): - access_rules_columns = [ 'ID', 'Access Type', @@ -1310,52 +1212,49 @@ class TestShareSnapshotAccessList(TestShareSnapshot): ] def setUp(self): - super(TestShareSnapshotAccessList, self).setUp() + super().setUp() self.share_snapshot = ( - manila_fakes.FakeShareSnapshot.create_one_snapshot()) + manila_fakes.FakeShareSnapshot.create_one_snapshot() + ) self.snapshots_mock.get.return_value = self.share_snapshot self.access_rules = ( - manila_fakes.FakeSnapshotAccessRule.create_access_rules( - count=2)) + manila_fakes.FakeSnapshotAccessRule.create_access_rules(count=2) + ) self.snapshots_mock.access_list.return_value = self.access_rules - self.cmd = osc_share_snapshots.ShareSnapshotAccessList( - self.app, None) + self.cmd = osc_share_snapshots.ShareSnapshotAccessList(self.app, None) - self.values = (oscutils.get_dict_properties( - a._info, self.access_rules_columns) for a in self.access_rules) + self.values = ( + oscutils.get_dict_properties(a._info, self.access_rules_columns) + for a in self.access_rules + ) def test_share_snapshot_access_list(self): - arglist = [ - self.share_snapshot.id - ] - verifylist = [ - ('snapshot', self.share_snapshot.id) - ] + arglist = [self.share_snapshot.id] + verifylist = [('snapshot', self.share_snapshot.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) - self.snapshots_mock.access_list.assert_called_with( - self.share_snapshot) + self.snapshots_mock.access_list.assert_called_with(self.share_snapshot) self.assertEqual(self.access_rules_columns, columns) self.assertCountEqual(self.values, data) class TestShareSnapshotExportLocationList(TestShareSnapshot): - columns = ["ID", "Path"] def setUp(self): - super(TestShareSnapshotExportLocationList, self).setUp() + super().setUp() self.share_snapshot = ( - manila_fakes.FakeShareSnapshot.create_one_snapshot()) + manila_fakes.FakeShareSnapshot.create_one_snapshot() + ) self.snapshots_mock.get.return_value = self.share_snapshot @@ -1364,38 +1263,38 @@ def setUp(self): ) self.export_locations_mock.list.return_value = self.export_locations - self.values = (oscutils.get_dict_properties( - e._info, self.columns) for e in self.export_locations) + self.values = ( + oscutils.get_dict_properties(e._info, self.columns) + for e in self.export_locations + ) self.cmd = osc_share_snapshots.ShareSnapshotListExportLocation( - self.app, None) + self.app, None + ) def test_snapshot_export_locations_list(self): - arglist = [ - self.share_snapshot.id - ] - verifylist = [ - ('snapshot', self.share_snapshot.id) - ] + arglist = [self.share_snapshot.id] + verifylist = [('snapshot', self.share_snapshot.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.export_locations_mock.list.assert_called_with( - snapshot=self.share_snapshot) + snapshot=self.share_snapshot + ) self.assertEqual(self.columns, columns) self.assertCountEqual(self.values, data) class TestShareSnapshotExportLocationShow(TestShareSnapshot): - def setUp(self): - super(TestShareSnapshotExportLocationShow, self).setUp() + super().setUp() self.share_snapshot = ( - manila_fakes.FakeShareSnapshot.create_one_snapshot()) + manila_fakes.FakeShareSnapshot.create_one_snapshot() + ) self.snapshots_mock.get.return_value = self.share_snapshot @@ -1406,16 +1305,14 @@ def setUp(self): self.export_locations_mock.get.return_value = self.export_location self.cmd = osc_share_snapshots.ShareSnapshotShowExportLocation( - self.app, None) + self.app, None + ) def test_snapshot_export_locations_list(self): - arglist = [ - self.share_snapshot.id, - self.export_location.id - ] + arglist = [self.share_snapshot.id, self.export_location.id] verifylist = [ ('snapshot', self.share_snapshot.id), - ('export_location', self.export_location.id) + ('export_location', self.export_location.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -1424,7 +1321,8 @@ def test_snapshot_export_locations_list(self): self.export_locations_mock.get.assert_called_with( export_location=self.export_location.id, - snapshot=self.share_snapshot) + snapshot=self.share_snapshot, + ) self.assertEqual(tuple(self.export_location._info.keys()), columns) self.assertCountEqual(self.export_location._info.values(), data) diff --git a/manilaclient/tests/unit/osc/v2/test_share_transfers.py b/manilaclient/tests/unit/osc/v2/test_share_transfers.py index 5a74dc98..b08a8c68 100644 --- a/manilaclient/tests/unit/osc/v2/test_share_transfers.py +++ b/manilaclient/tests/unit/osc/v2/test_share_transfers.py @@ -30,14 +30,13 @@ 'Source Project Id', 'Destination Project Id', 'Accepted', - 'Expires At' + 'Expires At', ] class TestShareTransfer(manila_fakes.TestShare): - def setUp(self): - super(TestShareTransfer, self).setUp() + super().setUp() self.shares_mock = self.app.client_manager.share.shares self.shares_mock.reset_mock() @@ -46,13 +45,13 @@ def setUp(self): self.transfers_mock.reset_mock() self.app.client_manager.share.api_version = api_versions.APIVersion( - api_versions.MAX_VERSION) + api_versions.MAX_VERSION + ) class TestShareTransferCreate(TestShareTransfer): - def setUp(self): - super(TestShareTransferCreate, self).setUp() + super().setUp() self.share = manila_fakes.FakeShare.create_one_share() self.shares_mock.create.return_value = self.share @@ -60,7 +59,8 @@ def setUp(self): self.shares_mock.get.return_value = self.share self.share_transfer = ( - manila_fakes.FakeShareTransfer.create_one_transfer()) + manila_fakes.FakeShareTransfer.create_one_transfer() + ) self.transfers_mock.get.return_value = self.share_transfer self.transfers_mock.create.return_value = self.share_transfer @@ -73,37 +73,33 @@ def test_share_transfer_create_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_transfer_create_required_args(self): - arglist = [ - self.share.id - ] - verifylist = [ - ('share', self.share.id) - ] + arglist = [self.share.id] + verifylist = [('share', self.share.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) - self.transfers_mock.create.assert_called_with( - self.share.id, - name=None - ) + self.transfers_mock.create.assert_called_with(self.share.id, name=None) self.assertCountEqual(self.columns, columns) self.assertCountEqual(self.data, data) class TestShareTransferDelete(TestShareTransfer): - def setUp(self): - super(TestShareTransferDelete, self).setUp() + super().setUp() - self.transfer = ( - manila_fakes.FakeShareTransfer.create_one_transfer()) + self.transfer = manila_fakes.FakeShareTransfer.create_one_transfer() self.transfers_mock.get.return_value = self.transfer @@ -113,16 +109,17 @@ def test_share_transfer_delete_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_transfer_delete(self): - arglist = [ - self.transfer.id - ] - verifylist = [ - ('transfer', [self.transfer.id]) - ] + arglist = [self.transfer.id] + verifylist = [('transfer', [self.transfer.id])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -132,47 +129,35 @@ def test_share_transfer_delete(self): self.assertIsNone(result) def test_share_transfer_delete_multiple(self): - transfers = ( - manila_fakes.FakeShareTransfer.create_share_transfers( - count=2)) - arglist = [ - transfers[0].id, - transfers[1].id - ] - verifylist = [ - ('transfer', [transfers[0].id, transfers[1].id]) - ] + transfers = manila_fakes.FakeShareTransfer.create_share_transfers( + count=2 + ) + arglist = [transfers[0].id, transfers[1].id] + verifylist = [('transfer', [transfers[0].id, transfers[1].id])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.assertEqual(self.transfers_mock.delete.call_count, - len(transfers)) + self.assertEqual(self.transfers_mock.delete.call_count, len(transfers)) self.assertIsNone(result) def test_share_transfer_delete_exception(self): - arglist = [ - self.transfer.id - ] - verifylist = [ - ('transfer', [self.transfer.id]) - ] + arglist = [self.transfer.id] + verifylist = [('transfer', [self.transfer.id])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.transfers_mock.delete.side_effect = exceptions.CommandError() - self.assertRaises(exceptions.CommandError, - self.cmd.take_action, - parsed_args) + self.assertRaises( + exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestShareTransferShow(TestShareTransfer): - def setUp(self): - super(TestShareTransferShow, self).setUp() + super().setUp() - self.transfer = ( - manila_fakes.FakeShareTransfer.create_one_transfer()) + self.transfer = manila_fakes.FakeShareTransfer.create_one_transfer() self.transfers_mock.get.return_value = self.transfer self.cmd = osc_share_transfers.ShowShareTransfer(self.app, None) @@ -185,16 +170,17 @@ def test_share_transfer_show_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_transfer_show(self): - arglist = [ - self.transfer.id - ] - verifylist = [ - ('transfer', self.transfer.id) - ] + arglist = [self.transfer.id] + verifylist = [('transfer', self.transfer.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) @@ -204,28 +190,25 @@ def test_share_transfer_show(self): class TestShareTransferList(TestShareTransfer): - def setUp(self): - super(TestShareTransferList, self).setUp() + super().setUp() - self.transfers = ( - manila_fakes.FakeShareTransfer.create_share_transfers( - count=2)) + self.transfers = manila_fakes.FakeShareTransfer.create_share_transfers( + count=2 + ) self.transfers_mock.list.return_value = self.transfers - self.values = (oscutils.get_dict_properties( - m._info, COLUMNS) for m in self.transfers) + self.values = ( + oscutils.get_dict_properties(m._info, COLUMNS) + for m in self.transfers + ) self.cmd = osc_share_transfers.ListShareTransfer(self.app, None) def test_list_transfers(self): - arglist = [ - '--detailed' - ] - verifylist = [ - ('detailed', True) - ] + arglist = ['--detailed'] + verifylist = [('detailed', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -241,9 +224,10 @@ def test_list_transfers(self): 'offset': None, 'resource_type': None, 'resource_id': None, - 'source_project_id': None}, + 'source_project_id': None, + }, sort_key=None, - sort_dir=None + sort_dir=None, ) self.assertEqual(COLUMNS, columns) @@ -251,12 +235,10 @@ def test_list_transfers(self): class TestShareTransferAccept(TestShareTransfer): - def setUp(self): - super(TestShareTransferAccept, self).setUp() + super().setUp() - self.transfer = ( - manila_fakes.FakeShareTransfer.create_one_transfer()) + self.transfer = manila_fakes.FakeShareTransfer.create_one_transfer() self.transfers_mock.get.return_value = self.transfer @@ -266,24 +248,26 @@ def test_share_transfer_accept_missing_args(self): arglist = [] verifylist = [] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_transfer_accept(self): - arglist = [ - self.transfer.id, - self.transfer.auth_key - ] + arglist = [self.transfer.id, self.transfer.auth_key] verifylist = [ ('transfer', self.transfer.id), - ('auth_key', self.transfer.auth_key) + ('auth_key', self.transfer.auth_key), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.transfers_mock.accept.assert_called_with(self.transfer.id, - self.transfer.auth_key, - clear_access_rules=False) + self.transfers_mock.accept.assert_called_with( + self.transfer.id, self.transfer.auth_key, clear_access_rules=False + ) self.assertIsNone(result) diff --git a/manilaclient/tests/unit/osc/v2/test_share_type.py b/manilaclient/tests/unit/osc/v2/test_share_type.py index 487eea05..be55ec0d 100644 --- a/manilaclient/tests/unit/osc/v2/test_share_type.py +++ b/manilaclient/tests/unit/osc/v2/test_share_type.py @@ -31,25 +31,24 @@ 'is_default', 'required_extra_specs', 'optional_extra_specs', - 'description' + 'description', ] class TestShareType(manila_fakes.TestShare): - def setUp(self): - super(TestShareType, self).setUp() + super().setUp() self.shares_mock = self.app.client_manager.share.share_types self.shares_mock.reset_mock() self.app.client_manager.share.api_version = api_versions.APIVersion( - api_versions.MAX_VERSION) + api_versions.MAX_VERSION + ) class TestShareTypeCreate(TestShareType): - def setUp(self): - super(TestShareTypeCreate, self).setUp() + super().setUp() self.new_share_type = manila_fakes.FakeShareType.create_one_sharetype() self.shares_mock.create.return_value = self.new_share_type @@ -63,11 +62,13 @@ def setUp(self): 'public', self.new_share_type.is_default, 'driver_handles_share_servers : True', - ('replication_type : readable\n' - 'mount_snapshot_support : False\n' - 'revert_to_snapshot_support : False\n' - 'create_share_from_snapshot_support : True\n' - 'snapshot_support : True'), + ( + 'replication_type : readable\n' + 'mount_snapshot_support : False\n' + 'revert_to_snapshot_support : False\n' + 'create_share_from_snapshot_support : True\n' + 'snapshot_support : True' + ), self.new_share_type.description, ] @@ -77,24 +78,23 @@ def setUp(self): 'public', self.new_share_type.is_default, {'driver_handles_share_servers': True}, - {'replication_type': 'readable', - 'mount_snapshot_support': False, - 'revert_to_snapshot_support': False, - 'create_share_from_snapshot_support': True, - 'snapshot_support': True}, + { + 'replication_type': 'readable', + 'mount_snapshot_support': False, + 'revert_to_snapshot_support': False, + 'create_share_from_snapshot_support': True, + 'snapshot_support': True, + }, self.new_share_type.description, ] def test_share_type_create_required_args(self): """Verifies required arguments.""" - arglist = [ - self.new_share_type.name, - 'True' - ] + arglist = [self.new_share_type.name, 'True'] verifylist = [ ('name', self.new_share_type.name), - ('spec_driver_handles_share_servers', 'True') + ('spec_driver_handles_share_servers', 'True'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -105,7 +105,7 @@ def test_share_type_create_required_args(self): extra_specs={}, is_public=True, name=self.new_share_type.name, - spec_driver_handles_share_servers=True + spec_driver_handles_share_servers=True, ) self.assertCountEqual(COLUMNS, columns) @@ -114,14 +114,10 @@ def test_share_type_create_required_args(self): def test_share_type_create_json_fomrat(self): """Verifies --format json.""" - arglist = [ - self.new_share_type.name, - 'True', - '-f', 'json' - ] + arglist = [self.new_share_type.name, 'True', '-f', 'json'] verifylist = [ ('name', self.new_share_type.name), - ('spec_driver_handles_share_servers', 'True') + ('spec_driver_handles_share_servers', 'True'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -132,7 +128,7 @@ def test_share_type_create_json_fomrat(self): extra_specs={}, is_public=True, name=self.new_share_type.name, - spec_driver_handles_share_servers=True + spec_driver_handles_share_servers=True, ) self.assertCountEqual(COLUMNS, columns) @@ -141,26 +137,23 @@ def test_share_type_create_json_fomrat(self): def test_share_type_create_missing_required_arg(self): """Verifies missing required arguments.""" - arglist = [ - self.new_share_type.name - ] - verifylist = [ - ('name', self.new_share_type.name) - ] + arglist = [self.new_share_type.name] + verifylist = [('name', self.new_share_type.name)] - self.assertRaises(osc_utils.ParserException, - self.check_parser, self.cmd, arglist, verifylist) + self.assertRaises( + osc_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist, + ) def test_share_type_create_private(self): - arglist = [ - self.new_share_type.name, - 'True', - '--public', 'False' - ] + arglist = [self.new_share_type.name, 'True', '--public', 'False'] verifylist = [ ('name', self.new_share_type.name), ('spec_driver_handles_share_servers', 'True'), - ('public', 'False') + ('public', 'False'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -171,7 +164,7 @@ def test_share_type_create_private(self): extra_specs={}, is_public=False, name=self.new_share_type.name, - spec_driver_handles_share_servers=True + spec_driver_handles_share_servers=True, ) self.assertCountEqual(COLUMNS, columns) @@ -181,12 +174,13 @@ def test_share_type_create_extra_specs(self): arglist = [ self.new_share_type.name, 'True', - '--extra-specs', 'snapshot_support=true' + '--extra-specs', + 'snapshot_support=true', ] verifylist = [ ('name', self.new_share_type.name), ('spec_driver_handles_share_servers', 'True'), - ('extra_specs', ['snapshot_support=true']) + ('extra_specs', ['snapshot_support=true']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -197,71 +191,75 @@ def test_share_type_create_extra_specs(self): extra_specs={'snapshot_support': 'True'}, is_public=True, name=self.new_share_type.name, - spec_driver_handles_share_servers=True + spec_driver_handles_share_servers=True, ) self.assertCountEqual(COLUMNS, columns) self.assertCountEqual(self.data, data) def test_share_type_create_dhss_invalid_value(self): - arglist = [ - self.new_share_type.name, - 'non_bool_value' - ] + arglist = [self.new_share_type.name, 'non_bool_value'] verifylist = [ ('name', self.new_share_type.name), - ('spec_driver_handles_share_servers', 'non_bool_value') + ('spec_driver_handles_share_servers', 'non_bool_value'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_share_type_create_api_version_exception(self): self.app.client_manager.share.api_version = api_versions.APIVersion( - "2.40") + "2.40" + ) arglist = [ self.new_share_type.name, 'True', - '--description', 'Description' + '--description', + 'Description', ] verifylist = [ ('name', self.new_share_type.name), ('spec_driver_handles_share_servers', 'True'), - ('description', 'Description') + ('description', 'Description'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_share_type_create_dhss_defined_twice(self): arglist = [ self.new_share_type.name, 'True', - '--extra-specs', 'driver_handles_share_servers=true' + '--extra-specs', + 'driver_handles_share_servers=true', ] verifylist = [ ('name', self.new_share_type.name), ('spec_driver_handles_share_servers', 'True'), - ('extra_specs', ['driver_handles_share_servers=true']) + ('extra_specs', ['driver_handles_share_servers=true']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_share_type_create_bool_args(self): arglist = [ self.new_share_type.name, 'True', - '--snapshot-support', 'true' + '--snapshot-support', + 'true', ] verifylist = [ ('name', self.new_share_type.name), ('spec_driver_handles_share_servers', 'True'), - ('snapshot_support', 'true') + ('snapshot_support', 'true'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -271,7 +269,7 @@ def test_share_type_create_bool_args(self): extra_specs={'snapshot_support': 'True'}, is_public=True, name=self.new_share_type.name, - spec_driver_handles_share_servers=True + spec_driver_handles_share_servers=True, ) self.assertCountEqual(COLUMNS, columns) @@ -279,27 +277,23 @@ def test_share_type_create_bool_args(self): class TestShareTypeDelete(TestShareType): - share_types = manila_fakes.FakeShareType.create_share_types(count=2) def setUp(self): - super(TestShareTypeDelete, self).setUp() + super().setUp() self.shares_mock.get = manila_fakes.FakeShareType.get_share_types( - self.share_types) + self.share_types + ) self.shares_mock.delete.return_value = None # Get the command object to test self.cmd = osc_share_types.DeleteShareType(self.app, None) def test_share_type_delete_one(self): - arglist = [ - self.share_types[0].id - ] + arglist = [self.share_types[0].id] - verifylist = [ - ('share_types', [self.share_types[0].id]) - ] + verifylist = [('share_types', [self.share_types[0].id])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -335,16 +329,17 @@ def test_delete_share_type_with_exception(self): parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.shares_mock.delete.side_effect = exceptions.CommandError() self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestShareTypeSet(TestShareType): - def setUp(self): - super(TestShareTypeSet, self).setUp() + super().setUp() self.share_type = manila_fakes.FakeShareType.create_one_sharetype( - methods={'set_keys': None, 'update': None}) + methods={'set_keys': None, 'update': None} + ) self.shares_mock.get.return_value = self.share_type # Get the command object to test @@ -353,88 +348,78 @@ def setUp(self): def test_share_type_set_extra_specs(self): arglist = [ self.share_type.id, - '--extra-specs', 'snapshot_support=true' + '--extra-specs', + 'snapshot_support=true', ] verifylist = [ ('share_type', self.share_type.id), - ('extra_specs', ['snapshot_support=true']) + ('extra_specs', ['snapshot_support=true']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.share_type.set_keys.assert_called_with( - {'snapshot_support': 'True'}) + {'snapshot_support': 'True'} + ) self.assertIsNone(result) def test_share_type_set_name(self): - arglist = [ - self.share_type.id, - '--name', 'new name' - ] - verifylist = [ - ('share_type', self.share_type.id), - ('name', 'new name') - ] + arglist = [self.share_type.id, '--name', 'new name'] + verifylist = [('share_type', self.share_type.id), ('name', 'new name')] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.share_type.update.assert_called_with( - name='new name') + self.share_type.update.assert_called_with(name='new name') self.assertIsNone(result) def test_share_type_set_description(self): - arglist = [ - self.share_type.id, - '--description', 'new description' - ] + arglist = [self.share_type.id, '--description', 'new description'] verifylist = [ ('share_type', self.share_type.id), - ('description', 'new description') + ('description', 'new description'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.share_type.update.assert_called_with( - description='new description') + description='new description' + ) self.assertIsNone(result) def test_share_type_set_visibility(self): - arglist = [ - self.share_type.id, - '--public', 'false' - ] - verifylist = [ - ('share_type', self.share_type.id), - ('public', 'false') - ] + arglist = [self.share_type.id, '--public', 'false'] + verifylist = [('share_type', self.share_type.id), ('public', 'false')] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.share_type.update.assert_called_with( - is_public=False) + self.share_type.update.assert_called_with(is_public=False) self.assertIsNone(result) def test_share_type_set_extra_specs_exception(self): arglist = [ self.share_type.id, - '--extra-specs', 'snapshot_support=true' + '--extra-specs', + 'snapshot_support=true', ] verifylist = [ ('share_type', self.share_type.id), - ('extra_specs', ['snapshot_support=true']) + ('extra_specs', ['snapshot_support=true']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.share_type.set_keys.side_effect = BadRequest() self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) def test_share_type_set_api_version_exception(self): self.app.client_manager.share.api_version = api_versions.APIVersion( - "2.49") + "2.49" + ) arglist = [ self.share_type.id, - '--name', 'new name', + '--name', + 'new name', ] verifylist = [ ('share_type', self.share_type.id), @@ -442,29 +427,27 @@ def test_share_type_set_api_version_exception(self): ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestShareTypeUnset(TestShareType): - def setUp(self): - super(TestShareTypeUnset, self).setUp() + super().setUp() self.share_type = manila_fakes.FakeShareType.create_one_sharetype( - methods={'unset_keys': None}) + methods={'unset_keys': None} + ) self.shares_mock.get.return_value = self.share_type # Get the command object to test self.cmd = osc_share_types.UnsetShareType(self.app, None) def test_share_type_unset_extra_specs(self): - arglist = [ - self.share_type.id, - 'snapshot_support' - ] + arglist = [self.share_type.id, 'snapshot_support'] verifylist = [ ('share_type', self.share_type.id), - ('extra_specs', ['snapshot_support']) + ('extra_specs', ['snapshot_support']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -473,48 +456,44 @@ def test_share_type_unset_extra_specs(self): self.assertIsNone(result) def test_share_type_unset_exception(self): - arglist = [ - self.share_type.id, - 'snapshot_support' - ] + arglist = [self.share_type.id, 'snapshot_support'] verifylist = [ ('share_type', self.share_type.id), - ('extra_specs', ['snapshot_support']) + ('extra_specs', ['snapshot_support']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.share_type.unset_keys.side_effect = NotFound() self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestShareTypeList(TestShareType): - share_types = manila_fakes.FakeShareType.create_share_types() columns = utils.format_column_headers(COLUMNS) def setUp(self): - super(TestShareTypeList, self).setUp() + super().setUp() self.shares_mock.list.return_value = self.share_types # Get the command object to test self.cmd = osc_share_types.ListShareType(self.app, None) - self.values = (oscutils.get_dict_properties( - s._info, COLUMNS) for s in self.share_types) + self.values = ( + oscutils.get_dict_properties(s._info, COLUMNS) + for s in self.share_types + ) def test_share_type_list_no_options(self): arglist = [] - verifylist = [ - ('all', False) - ] + verifylist = [('all', False)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.shares_mock.list.assert_called_once_with( - search_opts={}, - show_all=False + search_opts={}, show_all=False ) self.assertEqual(self.columns, columns) self.assertEqual(list(self.values), list(data)) @@ -523,56 +502,48 @@ def test_share_type_list_all(self): arglist = [ '--all', ] - verifylist = [ - ('all', True) - ] + verifylist = [('all', True)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.shares_mock.list.assert_called_once_with( - search_opts={}, - show_all=True) + search_opts={}, show_all=True + ) self.assertEqual(self.columns, columns) self.assertEqual(list(self.values), list(data)) def test_share_type_list_extra_specs(self): - arglist = [ - '--extra-specs', 'snapshot_support=true' - ] - verifylist = [ - ('extra_specs', ['snapshot_support=true']) - ] + arglist = ['--extra-specs', 'snapshot_support=true'] + verifylist = [('extra_specs', ['snapshot_support=true'])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.shares_mock.list.assert_called_once_with( search_opts={'extra_specs': {'snapshot_support': 'True'}}, - show_all=False) + show_all=False, + ) self.assertEqual(self.columns, columns) self.assertEqual(list(self.values), list(data)) def test_share_type_list_api_versions_exception(self): self.app.client_manager.share.api_version = api_versions.APIVersion( - "2.42") + "2.42" + ) - arglist = [ - '--extra-specs', 'snapshot_support=true' - ] - verifylist = [ - ('extra_specs', ['snapshot_support=true']) - ] + arglist = ['--extra-specs', 'snapshot_support=true'] + verifylist = [('extra_specs', ['snapshot_support=true'])] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestShareTypeShow(TestShareType): - def setUp(self): - super(TestShareTypeShow, self).setUp() + super().setUp() self.share_type = manila_fakes.FakeShareType.create_one_sharetype() @@ -587,11 +558,13 @@ def setUp(self): 'public', self.share_type.is_default, 'driver_handles_share_servers : True', - ('replication_type : readable\n' - 'mount_snapshot_support : False\n' - 'revert_to_snapshot_support : False\n' - 'create_share_from_snapshot_support : True\n' - 'snapshot_support : True'), + ( + 'replication_type : readable\n' + 'mount_snapshot_support : False\n' + 'revert_to_snapshot_support : False\n' + 'create_share_from_snapshot_support : True\n' + 'snapshot_support : True' + ), self.share_type.description, ] @@ -601,21 +574,19 @@ def setUp(self): 'public', self.share_type.is_default, {'driver_handles_share_servers': True}, - {'replication_type': 'readable', - 'mount_snapshot_support': False, - 'revert_to_snapshot_support': False, - 'create_share_from_snapshot_support': True, - 'snapshot_support': True}, + { + 'replication_type': 'readable', + 'mount_snapshot_support': False, + 'revert_to_snapshot_support': False, + 'create_share_from_snapshot_support': True, + 'snapshot_support': True, + }, self.share_type.description, ] def test_share_type_show(self): - arglist = [ - self.share_type.id - ] - verifylist = [ - ("share_type", self.share_type.id) - ] + arglist = [self.share_type.id] + verifylist = [("share_type", self.share_type.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) @@ -627,11 +598,10 @@ def test_share_type_show(self): def test_share_type_show_json_format(self): arglist = [ self.share_type.id, - '-f', 'json', - ] - verifylist = [ - ("share_type", self.share_type.id) + '-f', + 'json', ] + verifylist = [("share_type", self.share_type.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) diff --git a/manilaclient/tests/unit/osc/v2/test_share_type_access.py b/manilaclient/tests/unit/osc/v2/test_share_type_access.py index 00a7a2ba..506965e4 100644 --- a/manilaclient/tests/unit/osc/v2/test_share_type_access.py +++ b/manilaclient/tests/unit/osc/v2/test_share_type_access.py @@ -21,12 +21,10 @@ class TestShareTypeAccess(manila_fakes.TestShare): - def setUp(self): - super(TestShareTypeAccess, self).setUp() + super().setUp() - self.type_access_mock = ( - self.app.client_manager.share.share_type_access) + self.type_access_mock = self.app.client_manager.share.share_type_access self.type_access_mock.reset_mock() @@ -38,14 +36,14 @@ def setUp(self): class TestShareTypeAccessAllow(TestShareTypeAccess): - def setUp(self): - super(TestShareTypeAccessAllow, self).setUp() + super().setUp() self.project = identity_fakes.FakeProject.create_one_project() self.share_type = manila_fakes.FakeShareType.create_one_sharetype( - attrs={'share_type_access:is_public': False}) + attrs={'share_type_access:is_public': False} + ) self.share_types_mock.get.return_value = self.share_type self.type_access_mock.add_project_access.return_value = None @@ -54,13 +52,10 @@ def setUp(self): self.cmd = osc_share_type_access.ShareTypeAccessAllow(self.app, None) def test_share_type_access_create(self): - arglist = [ - self.share_type.id, - self.project.id - ] + arglist = [self.share_type.id, self.project.id] verifylist = [ ('share_type', self.share_type.id), - ('project_id', self.project.id) + ('project_id', self.project.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -68,89 +63,83 @@ def test_share_type_access_create(self): result = self.cmd.take_action(parsed_args) self.type_access_mock.add_project_access.assert_called_with( - self.share_type, - self.project.id) + self.share_type, self.project.id + ) self.assertIsNone(result) def test_share_type_access_create_throws_exception(self): - arglist = [ - self.share_type.id, - 'invalid_project_format' - ] + arglist = [self.share_type.id, 'invalid_project_format'] verifylist = [ ('share_type', self.share_type.id), - ('project_id', 'invalid_project_format') + ('project_id', 'invalid_project_format'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.type_access_mock.add_project_access.side_effect = BadRequest() self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestShareTypeAccessList(TestShareTypeAccess): - columns = ['Project ID'] data = (('',), ('',)) def setUp(self): - super(TestShareTypeAccessList, self).setUp() + super().setUp() - self.type_access_mock.list.return_value = ( - self.columns, self.data) + self.type_access_mock.list.return_value = (self.columns, self.data) # Get the command object to test self.cmd = osc_share_type_access.ListShareTypeAccess(self.app, None) def test_share_type_access_list(self): share_type = manila_fakes.FakeShareType.create_one_sharetype( - attrs={'share_type_access:is_public': False}) + attrs={'share_type_access:is_public': False} + ) self.share_types_mock.get.return_value = share_type arglist = [ share_type.id, ] - verifylist = [ - ('share_type', share_type.id) - ] + verifylist = [('share_type', share_type.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) - self.type_access_mock.list.assert_called_once_with( - share_type) + self.type_access_mock.list.assert_called_once_with(share_type) self.assertEqual(self.columns, columns) self.assertEqual(self.data, tuple(data)) def test_share_type_access_list_public_type(self): share_type = manila_fakes.FakeShareType.create_one_sharetype( - attrs={'share_type_access:is_public': True}) + attrs={'share_type_access:is_public': True} + ) self.share_types_mock.get.return_value = share_type arglist = [ share_type.id, ] - verifylist = [ - ('share_type', share_type.id) - ] + verifylist = [('share_type', share_type.id)] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) class TestShareTypeAccessDeny(TestShareTypeAccess): - def setUp(self): - super(TestShareTypeAccessDeny, self).setUp() + super().setUp() self.project = identity_fakes.FakeProject.create_one_project() self.share_type = manila_fakes.FakeShareType.create_one_sharetype( - attrs={'share_type_access:is_public': False}) + attrs={'share_type_access:is_public': False} + ) self.share_types_mock.get.return_value = self.share_type self.type_access_mock.remove_project_access.return_value = None @@ -159,13 +148,10 @@ def setUp(self): self.cmd = osc_share_type_access.ShareTypeAccessDeny(self.app, None) def test_share_type_access_delete(self): - arglist = [ - self.share_type.id, - self.project.id - ] + arglist = [self.share_type.id, self.project.id] verifylist = [ ('share_type', self.share_type.id), - ('project_id', self.project.id) + ('project_id', self.project.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -173,22 +159,20 @@ def test_share_type_access_delete(self): result = self.cmd.take_action(parsed_args) self.type_access_mock.remove_project_access.assert_called_with( - self.share_type, - self.project.id) + self.share_type, self.project.id + ) self.assertIsNone(result) def test_share_type_access_delete_exception(self): - arglist = [ - self.share_type.id, - 'invalid_project_format' - ] + arglist = [self.share_type.id, 'invalid_project_format'] verifylist = [ ('share_type', self.share_type.id), - ('project_id', 'invalid_project_format') + ('project_id', 'invalid_project_format'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.type_access_mock.remove_project_access.side_effect = BadRequest() self.assertRaises( - exceptions.CommandError, self.cmd.take_action, parsed_args) + exceptions.CommandError, self.cmd.take_action, parsed_args + ) diff --git a/manilaclient/tests/unit/test_api_versions.py b/manilaclient/tests/unit/test_api_versions.py index c853171c..2a1ce4bc 100644 --- a/manilaclient/tests/unit/test_api_versions.py +++ b/manilaclient/tests/unit/test_api_versions.py @@ -59,8 +59,9 @@ def test_null_version(self): "2.", ) def test_invalid_version_strings(self, version): - self.assertRaises(exceptions.UnsupportedVersion, - api_versions.APIVersion, version) + self.assertRaises( + exceptions.UnsupportedVersion, api_versions.APIVersion, version + ) def test_version_comparisons(self): v1 = api_versions.APIVersion("2.0") @@ -116,24 +117,17 @@ def test_get_string(self): v1 = api_versions.APIVersion(v1_string) self.assertEqual(v1_string, v1.get_string()) - self.assertRaises(ValueError, - api_versions.APIVersion().get_string) - - @ddt.data("2.0", - "2.5", - "2.45", - "3.3", - "3.23", - "2.0", - "3.3", - "4.0") + self.assertRaises(ValueError, api_versions.APIVersion().get_string) + + @ddt.data("2.0", "2.5", "2.45", "3.3", "3.23", "2.0", "3.3", "4.0") def test_representation(self, version): version_major, version_minor = version.split('.') api_version = api_versions.APIVersion(version) - self.assertEqual(str(api_version), - ("API Version Major: %s, Minor: %s" % - (version_major, version_minor))) - self.assertEqual(repr(api_version), "" % version) + self.assertEqual( + str(api_version), + (f"API Version Major: {version_major}, Minor: {version_minor}"), + ) + self.assertEqual(repr(api_version), f"") def test_is_latest(self): v1 = api_versions.APIVersion("1.0") @@ -143,25 +137,23 @@ def test_is_latest(self): class GetAPIVersionTestCase(utils.TestCase): - def test_wrong_format(self): - self.assertRaises(exceptions.UnsupportedVersion, - api_versions.get_api_version, "something_wrong") - - def test_wrong_major_version(self): - self.assertRaises(exceptions.UnsupportedVersion, - api_versions.get_api_version, "1") + self.assertRaises( + exceptions.UnsupportedVersion, + api_versions.get_api_version, + "something_wrong", + ) @mock.patch("manilaclient.api_versions.APIVersion") def test_major_and_minor_parts_is_presented(self, mock_apiversion): version = "2.7" - self.assertEqual(mock_apiversion.return_value, - api_versions.get_api_version(version)) + self.assertEqual( + mock_apiversion.return_value, api_versions.get_api_version(version) + ) mock_apiversion.assert_called_once_with(version) class WrapsTestCase(utils.TestCase): - def _get_obj_with_vers(self, vers): return mock.MagicMock(api_version=api_versions.APIVersion(vers)) @@ -184,13 +176,17 @@ def foo(*args, **kwargs): foo(self._get_obj_with_vers('2.4')) mock_versioned_method.assert_called_once_with( - func_name, api_versions.APIVersion('2.2'), - api_versions.APIVersion(api_versions.MAX_VERSION), mock.ANY) + func_name, + api_versions.APIVersion('2.2'), + api_versions.APIVersion(api_versions.MAX_VERSION), + mock.ANY, + ) @mock.patch("manilaclient.utils.get_function_name") @mock.patch("manilaclient.api_versions.VersionedMethod") - def test_start_and_end_version_are_presented(self, mock_versioned_method, - mock_name): + def test_start_and_end_version_are_presented( + self, mock_versioned_method, mock_name + ): func_name = "foo" mock_name.return_value = func_name mock_versioned_method.side_effect = self._side_effect_of_vers_method @@ -202,8 +198,11 @@ def foo(*args, **kwargs): foo(self._get_obj_with_vers("2.4")) mock_versioned_method.assert_called_once_with( - func_name, api_versions.APIVersion("2.2"), - api_versions.APIVersion("2.6"), mock.ANY) + func_name, + api_versions.APIVersion("2.2"), + api_versions.APIVersion("2.6"), + mock.ANY, + ) @mock.patch("manilaclient.utils.get_function_name") @mock.patch("manilaclient.api_versions.VersionedMethod") @@ -216,12 +215,16 @@ def test_api_version_doesnt_match(self, mock_versioned_method, mock_name): def foo(*args, **kwargs): pass - self.assertRaises(exceptions.UnsupportedVersion, - foo, self._get_obj_with_vers("2.1")) + self.assertRaises( + exceptions.UnsupportedVersion, foo, self._get_obj_with_vers("2.1") + ) mock_versioned_method.assert_called_once_with( - func_name, api_versions.APIVersion("2.2"), - api_versions.APIVersion("2.6"), mock.ANY) + func_name, + api_versions.APIVersion("2.2"), + api_versions.APIVersion("2.6"), + mock.ANY, + ) def test_define_method_is_actually_called(self): checker = mock.MagicMock() @@ -239,7 +242,6 @@ def some_func(*args, **kwargs): checker.assert_called_once_with(*((obj,) + some_args), **some_kwargs) def test_cli_args_are_copied(self): - @api_versions.wraps("2.2", "2.6") @cliutils.arg("name_1", help="Name of the something") @cliutils.arg("action_1", help="Some action") @@ -252,18 +254,22 @@ def some_func_1(cs, args): def some_func_2(cs, args): pass - args_1 = [(('name_1',), {'help': 'Name of the something'}), - (('action_1',), {'help': 'Some action'})] + args_1 = [ + (('name_1',), {'help': 'Name of the something'}), + (('action_1',), {'help': 'Some action'}), + ] self.assertEqual(args_1, some_func_1.arguments) - args_2 = [(('name_2',), {'help': 'Name of the something'}), - (('action_2',), {'help': 'Some action'})] + args_2 = [ + (('name_2',), {'help': 'Name of the something'}), + (('action_2',), {'help': 'Some action'}), + ] self.assertEqual(args_2, some_func_2.arguments) class DiscoverVersionTestCase(utils.TestCase): def setUp(self): - super(DiscoverVersionTestCase, self).setUp() + super().setUp() self.orig_max = manilaclient.API_MAX_VERSION self.orig_min = manilaclient.API_MIN_VERSION self.addCleanup(self._clear_fake_version) @@ -273,11 +279,14 @@ def _clear_fake_version(self): manilaclient.API_MAX_VERSION = self.orig_max manilaclient.API_MIN_VERSION = self.orig_min - def _mock_returned_server_version(self, server_version, - server_min_version): - version_mock = mock.MagicMock(version=server_version, - min_version=server_min_version, - status='CURRENT') + def _mock_returned_server_version( + self, server_version, server_min_version + ): + version_mock = mock.MagicMock( + version=server_version, + min_version=server_min_version, + status='CURRENT', + ) val = [version_mock] self.fake_client.services.server_api_version.return_value = val @@ -286,11 +295,13 @@ def test_server_is_too_new(self): manilaclient.API_MAX_VERSION = api_versions.APIVersion("2.3") manilaclient.API_MIN_VERSION = api_versions.APIVersion("2.1") - self.assertRaisesRegex(exceptions.UnsupportedVersion, - ".*range is '2.4' to '2.7'.*", - api_versions.discover_version, - self.fake_client, - api_versions.APIVersion("2.3")) + self.assertRaisesRegex( + exceptions.UnsupportedVersion, + ".*range is '2.4' to '2.7'.*", + api_versions.discover_version, + self.fake_client, + api_versions.APIVersion("2.3"), + ) self.assertTrue(self.fake_client.services.server_api_version.called) def test_server_is_too_old(self): @@ -298,10 +309,12 @@ def test_server_is_too_old(self): manilaclient.API_MAX_VERSION = api_versions.APIVersion("2.10") manilaclient.API_MIN_VERSION = api_versions.APIVersion("2.9") - self.assertRaises(exceptions.UnsupportedVersion, - api_versions.discover_version, - self.fake_client, - api_versions.APIVersion("2.10")) + self.assertRaises( + exceptions.UnsupportedVersion, + api_versions.discover_version, + self.fake_client, + api_versions.APIVersion("2.10"), + ) self.assertTrue(self.fake_client.services.server_api_version.called) def test_requested_version_is_less_than_server_max(self): @@ -329,8 +342,8 @@ def test_server_and_client_max_are_same(self): manilaclient.API_MIN_VERSION = api_versions.APIVersion("2.5") discovered_version = api_versions.discover_version( - self.fake_client, - manilaclient.API_MAX_VERSION) + self.fake_client, manilaclient.API_MAX_VERSION + ) self.assertEqual("2.5", discovered_version.get_string()) self.assertTrue(self.fake_client.services.server_api_version.called) @@ -339,8 +352,8 @@ def test_pre_microversion_server(self): manilaclient.API_MAX_VERSION = api_versions.APIVersion("2.5") manilaclient.API_MIN_VERSION = api_versions.APIVersion("2.5") discovered_version = api_versions.discover_version( - self.fake_client, - manilaclient.API_MAX_VERSION) + self.fake_client, manilaclient.API_MAX_VERSION + ) self.assertEqual("1.0", discovered_version.get_string()) self.assertTrue(self.fake_client.services.server_api_version.called) @@ -350,8 +363,8 @@ def test_requested_version_in_range(self): manilaclient.API_MIN_VERSION = api_versions.APIVersion("2.1") discovered_version = api_versions.discover_version( - self.fake_client, - api_versions.APIVersion('2.7')) + self.fake_client, api_versions.APIVersion('2.7') + ) self.assertEqual('2.7', discovered_version.get_string()) self.assertTrue(self.fake_client.services.server_api_version.called) @@ -361,10 +374,11 @@ def test_server_without_microversion(self): manilaclient.API_MIN_VERSION = api_versions.APIVersion("2.1") discovered_version = api_versions.discover_version( - self.fake_client, - api_versions.APIVersion('2.7')) - self.assertEqual(api_versions.DEPRECATED_VERSION, - discovered_version.get_string()) + self.fake_client, api_versions.APIVersion('2.7') + ) + self.assertEqual( + api_versions.DEPRECATED_VERSION, discovered_version.get_string() + ) self.assertTrue(self.fake_client.services.server_api_version.called) @@ -373,8 +387,10 @@ def test_requested_version_is_too_old(self): manilaclient.API_MAX_VERSION = api_versions.APIVersion("2.5") manilaclient.API_MIN_VERSION = api_versions.APIVersion("2.5") - self.assertRaisesRegex(exceptions.UnsupportedVersion, - ".*range is '2.0' to '2.5'.*", - api_versions.discover_version, - self.fake_client, - api_versions.APIVersion("1.0")) + self.assertRaisesRegex( + exceptions.UnsupportedVersion, + ".*range is '2.0' to '2.5'.*", + api_versions.discover_version, + self.fake_client, + api_versions.APIVersion("1.0"), + ) diff --git a/manilaclient/tests/unit/test_base.py b/manilaclient/tests/unit/test_base.py index bbb2ad9f..3158a7b7 100644 --- a/manilaclient/tests/unit/test_base.py +++ b/manilaclient/tests/unit/test_base.py @@ -23,7 +23,6 @@ class BaseTest(utils.TestCase): - def test_resource_repr(self): r = base.Resource(None, dict(foo="bar", baz="spam")) self.assertEqual(repr(r), "") @@ -59,12 +58,13 @@ def test_findall_invalid_attribute(self): cs.shares.findall(vegetable='carrot') # However, find() should raise an error - self.assertRaises(exceptions.NotFound, - cs.shares.find, - vegetable='carrot') + self.assertRaises( + exceptions.NotFound, cs.shares.find, vegetable='carrot' + ) def test_findall_with_all_tenants(self): cs.shares.list = mock.Mock(return_value=[]) cs.shares.findall() cs.shares.list.assert_called_with( - search_opts={'all_tenants': 1, 'is_soft_deleted': True}) + search_opts={'all_tenants': 1, 'is_soft_deleted': True} + ) diff --git a/manilaclient/tests/unit/test_client.py b/manilaclient/tests/unit/test_client.py index 9f5fbdac..9200c9db 100644 --- a/manilaclient/tests/unit/test_client.py +++ b/manilaclient/tests/unit/test_client.py @@ -24,14 +24,16 @@ @ddt.ddt class ClientTest(utils.TestCase): - def test_get_client_class_v2(self): output = manilaclient.client.get_client_class('2') self.assertEqual(output, manilaclient.v2.client.Client) def test_get_client_class_unknown(self): - self.assertRaises(manilaclient.exceptions.UnsupportedVersion, - manilaclient.client.get_client_class, '0') + self.assertRaises( + manilaclient.exceptions.UnsupportedVersion, + manilaclient.client.get_client_class, + '0', + ) @ddt.data('1', '1.0') def test_init_client_with_string_v1_version(self, version): @@ -43,7 +45,8 @@ def test_init_client_with_string_v1_version(self, version): manilaclient.client.Client(version, 'foo', bar='quuz') manilaclient.v1.client.Client.assert_called_once_with( - 'foo', api_version=api_instance, bar='quuz') + 'foo', api_version=api_instance, bar='quuz' + ) api_versions.APIVersion.assert_called_once_with('1.0') @ddt.data( @@ -61,17 +64,18 @@ def test_init_client_with_string_v2_version(self, provided, expected): manilaclient.client.Client(provided, 'foo', bar='quuz') manilaclient.v2.client.Client.assert_called_once_with( - 'foo', api_version=api_instance, bar='quuz') + 'foo', api_version=api_instance, bar='quuz' + ) api_versions.APIVersion.assert_called_once_with(expected) def test_init_client_with_api_version_instance(self): version = manilaclient.API_MAX_VERSION with mock.patch.object(manilaclient.v2.client, 'Client'): - manilaclient.client.Client(version, 'foo', bar='quuz') manilaclient.v2.client.Client.assert_called_once_with( - 'foo', api_version=version, bar='quuz') + 'foo', api_version=version, bar='quuz' + ) @ddt.data(None, '', '3', 'v1', 'v2', 'v1.0', 'v2.0') def test_init_client_with_unsupported_version(self, v): @@ -93,7 +97,6 @@ def test_init_client_with_unsupported_version(self, v): ) @ddt.unpack def test_init_client_with_version_parms(self, pos, kw): - major = int(float(pos)) pos_av = mock.Mock() kw_av = mock.Mock() @@ -114,21 +117,24 @@ def test_init_client_with_version_parms(self, pos, kw): if int(float(pos)) == 1: expected_client_ver = api_versions.DEPRECATED_VERSION self.assertFalse(manilaclient.v2.client.Client.called) - manilaclient.v1.client.Client.assert_has_calls([ - mock.call('foo', api_version=expected_av) - ]) + manilaclient.v1.client.Client.assert_has_calls( + [mock.call('foo', api_version=expected_av)] + ) else: expected_client_ver = api_versions.MIN_VERSION self.assertFalse(manilaclient.v1.client.Client.called) - manilaclient.v2.client.Client.assert_has_calls([ - mock.call('foo', api_version=expected_av) - ]) + manilaclient.v2.client.Client.assert_has_calls( + [mock.call('foo', api_version=expected_av)] + ) if kw is None: api_versions.APIVersion.assert_called_once_with( - expected_client_ver) + expected_client_ver + ) else: - api_versions.APIVersion.assert_has_calls([ - mock.call(expected_client_ver), - mock.call(kw), - ]) + api_versions.APIVersion.assert_has_calls( + [ + mock.call(expected_client_ver), + mock.call(kw), + ] + ) diff --git a/manilaclient/tests/unit/test_functional_utils.py b/manilaclient/tests/unit/test_functional_utils.py index c8d79432..3ba09b12 100644 --- a/manilaclient/tests/unit/test_functional_utils.py +++ b/manilaclient/tests/unit/test_functional_utils.py @@ -21,7 +21,6 @@ @ddt.ddt class ShellTest(utils.TestCase): - OUTPUT_LINES_SIMPLE = """ +----+------+---------+ | ID | Name | Status | @@ -113,28 +112,32 @@ class ShellTest(utils.TestCase): +----------+--------+ """ - @ddt.data({'input': OUTPUT_LINES_SIMPLE, - 'valid_values': [ - ['11', 'foo', 'BUILD'], - ['21', 'bar', 'ERROR'] - ]}, - {'input': OUTPUT_LINES_ONE_MULTI_ROW, - 'valid_values': [ - ['11', 'foo', 'BUILD'], - ['21', 'bar', ['ERROR', 'ERROR2']], - ['31', 'bee', 'None'], - ]}, - {'input': OUTPUT_LINES_COMPLICATED_MULTI_ROW, - 'valid_values': [ - ['11', 'foo', 'BUILD'], - ['21', 'bar', ['ERROR', 'ERROR2', 'ERROR3']], - ['31', ['bee', 'bee2', 'bee3'], 'None'], - ['41', ['rand', 'rend'], ['None', 'None2']], - ['', '', ''] - ]}) + @ddt.data( + { + 'input': OUTPUT_LINES_SIMPLE, + 'valid_values': [['11', 'foo', 'BUILD'], ['21', 'bar', 'ERROR']], + }, + { + 'input': OUTPUT_LINES_ONE_MULTI_ROW, + 'valid_values': [ + ['11', 'foo', 'BUILD'], + ['21', 'bar', ['ERROR', 'ERROR2']], + ['31', 'bee', 'None'], + ], + }, + { + 'input': OUTPUT_LINES_COMPLICATED_MULTI_ROW, + 'valid_values': [ + ['11', 'foo', 'BUILD'], + ['21', 'bar', ['ERROR', 'ERROR2', 'ERROR3']], + ['31', ['bee', 'bee2', 'bee3'], 'None'], + ['41', ['rand', 'rend'], ['None', 'None2']], + ['', '', ''], + ], + }, + ) @ddt.unpack def test_multi_line_row_table(self, input, valid_values): - actual_result = func_utils.multi_line_row_table(input) self.assertEqual(['ID', 'Name', 'Status'], actual_result['headers']) @@ -147,44 +150,54 @@ def test_multi_line_row_table_shifted_id_column(self): ['', '21', 'bar', ['ERROR', 'ERROR2', 'ERROR3']], ['', '', '', ''], ['**', '31', ['bee', 'bee2'], 'None'], - ['', '', '', ''] + ['', '', '', ''], ] actual_result = func_utils.multi_line_row_table( - input, group_by_column_index=1) + input, group_by_column_index=1 + ) - self.assertEqual(['**', 'ID', 'Name', 'Status'], - actual_result['headers']) + self.assertEqual( + ['**', 'ID', 'Name', 'Status'], actual_result['headers'] + ) self.assertEqual(valid_values, actual_result['values']) - @ddt.data({'input': OUTPUT_LINES_NESTED_TABLE, - 'valid_nested': { - 'headers': ['aa', 'bb'], - 'values': [] - }}, - {'input': OUTPUT_LINES_NESTED_TABLE_MULTI_LINE, - 'valid_nested': { - 'headers': ['id', 'bb'], - 'values': [['01', ['a1', 'a2']]] - }},) + @ddt.data( + { + 'input': OUTPUT_LINES_NESTED_TABLE, + 'valid_nested': {'headers': ['aa', 'bb'], 'values': []}, + }, + { + 'input': OUTPUT_LINES_NESTED_TABLE_MULTI_LINE, + 'valid_nested': { + 'headers': ['id', 'bb'], + 'values': [['01', ['a1', 'a2']]], + }, + }, + ) @ddt.unpack def test_nested_tables(self, input, valid_nested): - actual_result = func_utils.multi_line_row_table( - input, group_by_column_index=1) + input, group_by_column_index=1 + ) - self.assertEqual(['**', 'ID', 'Name', 'Status'], - actual_result['headers']) + self.assertEqual( + ['**', 'ID', 'Name', 'Status'], actual_result['headers'] + ) self.assertEqual(2, len(actual_result['values'])) self.assertEqual(valid_nested, actual_result['values'][0][3]) - @ddt.data({'input': OUTPUT_LINES_DETAILS, - 'valid_values': [ - ['foo', 'BUILD'], - ['bar', ['ERROR', 'ERROR2', 'ERROR3']], - ['bee', 'None'], - ]}) + @ddt.data( + { + 'input': OUTPUT_LINES_DETAILS, + 'valid_values': [ + ['foo', 'BUILD'], + ['bar', ['ERROR', 'ERROR2', 'ERROR3']], + ['bee', 'None'], + ], + } + ) @ddt.unpack def test_details(self, input, valid_values): actual_result = func_utils.multi_line_row_table(input) @@ -192,33 +205,53 @@ def test_details(self, input, valid_values): self.assertEqual(['Property', 'Value'], actual_result['headers']) self.assertEqual(valid_values, actual_result['values']) - @ddt.data({'input_data': OUTPUT_LINES_DETAILS, - 'output_data': [ - {'Property': 'foo', 'Value': 'BUILD'}, - {'Property': 'bar', 'Value': ['ERROR', 'ERROR2', 'ERROR3']}, - {'Property': 'bee', 'Value': 'None'}]}, - {'input_data': OUTPUT_LINES_SIMPLE, - 'output_data': [ - {'ID': '11', 'Name': 'foo', 'Status': 'BUILD'}, - {'ID': '21', 'Name': 'bar', 'Status': 'ERROR'}, - ]}, - {'input_data': OUTPUT_LINES_ONE_MULTI_ROW, - 'output_data': [ - {'ID': '11', 'Name': 'foo', 'Status': 'BUILD'}, - {'ID': '21', 'Name': 'bar', 'Status': ['ERROR', 'ERROR2']}, - {'ID': '31', 'Name': 'bee', 'Status': 'None'}, - ]}, - {'input_data': OUTPUT_LINES_COMPLICATED_MULTI_ROW, - 'output_data': [ - {'ID': '11', 'Name': 'foo', 'Status': 'BUILD'}, - {'ID': '21', 'Name': 'bar', - 'Status': ['ERROR', 'ERROR2', 'ERROR3']}, - {'ID': '31', 'Name': ['bee', 'bee2', 'bee3'], - 'Status': 'None'}, - {'ID': '41', 'Name': ['rand', 'rend'], - 'Status': ['None', 'None2']}, - {'ID': '', 'Name': '', 'Status': ''}, - ]}) + @ddt.data( + { + 'input_data': OUTPUT_LINES_DETAILS, + 'output_data': [ + {'Property': 'foo', 'Value': 'BUILD'}, + {'Property': 'bar', 'Value': ['ERROR', 'ERROR2', 'ERROR3']}, + {'Property': 'bee', 'Value': 'None'}, + ], + }, + { + 'input_data': OUTPUT_LINES_SIMPLE, + 'output_data': [ + {'ID': '11', 'Name': 'foo', 'Status': 'BUILD'}, + {'ID': '21', 'Name': 'bar', 'Status': 'ERROR'}, + ], + }, + { + 'input_data': OUTPUT_LINES_ONE_MULTI_ROW, + 'output_data': [ + {'ID': '11', 'Name': 'foo', 'Status': 'BUILD'}, + {'ID': '21', 'Name': 'bar', 'Status': ['ERROR', 'ERROR2']}, + {'ID': '31', 'Name': 'bee', 'Status': 'None'}, + ], + }, + { + 'input_data': OUTPUT_LINES_COMPLICATED_MULTI_ROW, + 'output_data': [ + {'ID': '11', 'Name': 'foo', 'Status': 'BUILD'}, + { + 'ID': '21', + 'Name': 'bar', + 'Status': ['ERROR', 'ERROR2', 'ERROR3'], + }, + { + 'ID': '31', + 'Name': ['bee', 'bee2', 'bee3'], + 'Status': 'None', + }, + { + 'ID': '41', + 'Name': ['rand', 'rend'], + 'Status': ['None', 'None2'], + }, + {'ID': '', 'Name': '', 'Status': ''}, + ], + }, + ) @ddt.unpack def test_listing(self, input_data, output_data): actual_result = func_utils.listing(input_data) diff --git a/manilaclient/tests/unit/test_shell.py b/manilaclient/tests/unit/test_shell.py deleted file mode 100644 index 9ac524c0..00000000 --- a/manilaclient/tests/unit/test_shell.py +++ /dev/null @@ -1,469 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import io -import re -import sys -from unittest import mock - -import ddt -import fixtures -from tempest.lib.cli import output_parser -from testtools import matchers - -import manilaclient -from manilaclient.common import cliutils -from manilaclient.common import constants -from manilaclient import exceptions -from manilaclient import shell -from manilaclient.tests.unit import utils -from manilaclient.tests.unit.v2 import fakes - - -@ddt.ddt -class OpenstackManilaShellTest(utils.TestCase): - - FAKE_ENV = { - 'OS_USERNAME': 'username', - 'OS_PASSWORD': 'password', - 'OS_TENANT_NAME': 'tenant_name', - 'OS_AUTH_URL': 'http://no.where', - } - - # Patch os.environ to avoid required auth info. - def set_env_vars(self, env_vars): - for k, v in env_vars.items(): - self.useFixture(fixtures.EnvironmentVariable(k, v)) - - def shell_discover_client(self, - current_client, - os_api_version, - os_endpoint_type, - os_service_type, - client_args): - return current_client, manilaclient.API_MAX_VERSION - - def shell(self, argstr): - orig = sys.stdout - try: - sys.stdout = io.StringIO() - _shell = shell.OpenStackManilaShell() - _shell._discover_client = self.shell_discover_client - _shell.main(argstr.split()) - except SystemExit: - exc_type, exc_value, exc_traceback = sys.exc_info() - self.assertEqual(exc_value.code, 0) - finally: - out = sys.stdout.getvalue() - sys.stdout.close() - sys.stdout = orig - - return out - - @ddt.data( - {}, - {'OS_AUTH_URL': 'http://foo.bar'}, - {'OS_AUTH_URL': 'http://foo.bar', 'OS_USERNAME': 'foo'}, - {'OS_AUTH_URL': 'http://foo.bar', 'OS_USERNAME': 'foo_user', - 'OS_PASSWORD': 'foo_password'}, - {'OS_TENANT_NAME': 'foo_tenant', 'OS_USERNAME': 'foo_user', - 'OS_PASSWORD': 'foo_password'}, - {'OS_TOKEN': 'foo_token'}, - {'OS_MANILA_BYPASS_URL': 'http://foo.foo'}, - ) - def test_main_failure(self, env_vars): - self.set_env_vars(env_vars) - with mock.patch.object(shell, 'client') as mock_client: - self.assertRaises(exceptions.CommandError, self.shell, 'list') - self.assertFalse(mock_client.Client.called) - - @ddt.data(None, 'foo_key') - def test_main_success(self, os_key): - env_vars = { - 'OS_AUTH_URL': 'http://foo.bar', - 'OS_USERNAME': 'foo_username', - 'OS_USER_ID': 'foo_user_id', - 'OS_PASSWORD': 'foo_password', - 'OS_TENANT_NAME': 'foo_tenant', - 'OS_TENANT_ID': 'foo_tenant_id', - 'OS_PROJECT_NAME': 'foo_project', - 'OS_PROJECT_ID': 'foo_project_id', - 'OS_PROJECT_DOMAIN_ID': 'foo_project_domain_id', - 'OS_PROJECT_DOMAIN_NAME': 'foo_project_domain_name', - 'OS_PROJECT_DOMAIN_ID': 'foo_project_domain_id', - 'OS_USER_DOMAIN_NAME': 'foo_user_domain_name', - 'OS_USER_DOMAIN_ID': 'foo_user_domain_id', - 'OS_CERT': 'foo_cert', - 'OS_KEY': os_key, - } - self.set_env_vars(env_vars) - cert = env_vars['OS_CERT'] - if os_key: - cert = (cert, env_vars['OS_KEY']) - - with mock.patch.object(shell, 'client') as mock_client: - - self.shell('list') - - mock_client.Client.assert_called_with( - manilaclient.API_MAX_VERSION, - username=env_vars['OS_USERNAME'], - password=env_vars['OS_PASSWORD'], - project_name=env_vars['OS_PROJECT_NAME'], - auth_url=env_vars['OS_AUTH_URL'], - insecure=False, - region_name='', - tenant_id=env_vars['OS_PROJECT_ID'], - endpoint_type='publicURL', - extensions=mock.ANY, - service_type=constants.V2_SERVICE_TYPE, - service_name='', - retries=0, - http_log_debug=False, - cacert=None, - use_keyring=False, - force_new_token=False, - user_id=env_vars['OS_USER_ID'], - user_domain_id=env_vars['OS_USER_DOMAIN_ID'], - user_domain_name=env_vars['OS_USER_DOMAIN_NAME'], - project_domain_id=env_vars['OS_PROJECT_DOMAIN_ID'], - project_domain_name=env_vars['OS_PROJECT_DOMAIN_NAME'], - cert=cert, - input_auth_token='', - service_catalog_url='', - ) - - @ddt.data( - {"env_vars": {"OS_MANILA_BYPASS_URL": "http://foo.url", - "OS_TOKEN": "foo_token"}, - "kwargs": {"--os-token": "bar_token", - "--bypass-url": "http://bar.url"}, - "expected": {"input_auth_token": "bar_token", - "service_catalog_url": "http://bar.url"}}, - {"env_vars": {"OS_MANILA_BYPASS_URL": "http://foo.url", - "OS_TOKEN": "foo_token"}, - "kwargs": {}, - "expected": {"input_auth_token": "foo_token", - "service_catalog_url": "http://foo.url"}}, - {"env_vars": {}, - "kwargs": {"--os-token": "bar_token", - "--bypass-url": "http://bar.url"}, - "expected": {"input_auth_token": "bar_token", - "service_catalog_url": "http://bar.url"}}, - {"env_vars": {"MANILACLIENT_BYPASS_URL": "http://foo.url", - "OS_TOKEN": "foo_token"}, - "kwargs": {}, - "expected": {"input_auth_token": "foo_token", - "service_catalog_url": "http://foo.url"}}, - {"env_vars": {"OS_TOKEN": "foo_token"}, - "kwargs": {"--bypass-url": "http://bar.url"}, - "expected": {"input_auth_token": "foo_token", - "service_catalog_url": "http://bar.url"}}, - {"env_vars": {"MANILACLIENT_BYPASS_URL": "http://foo.url", - "OS_MANILA_BYPASS_URL": "http://bar.url", - "OS_TOKEN": "foo_token"}, - "kwargs": {"--os-token": "bar_token"}, - "expected": {"input_auth_token": "bar_token", - "service_catalog_url": "http://bar.url"}}, - ) - @ddt.unpack - def test_main_success_with_token(self, env_vars, kwargs, expected): - self.set_env_vars(env_vars) - with mock.patch.object(shell, "client") as mock_client: - cmd = "" - for k, v in kwargs.items(): - cmd += "%s=%s " % (k, v) - cmd += "list" - - self.shell(cmd) - - mock_client.Client.assert_called_with( - manilaclient.API_MAX_VERSION, - username="", - password="", - project_name="", - auth_url="", - insecure=False, - region_name="", - tenant_id="", - endpoint_type="publicURL", - extensions=mock.ANY, - service_type=constants.V2_SERVICE_TYPE, - service_name="", - retries=0, - http_log_debug=False, - cacert=None, - use_keyring=False, - force_new_token=False, - user_id="", - user_domain_id="", - user_domain_name="", - project_domain_id="", - project_domain_name="", - cert=None, - input_auth_token=expected["input_auth_token"], - service_catalog_url=expected["service_catalog_url"], - ) - - @ddt.data( - # default without any env var or kwargs - { - "env_vars": {"OS_TOKEN": "foo_token", - "OS_MANILA_BYPASS_URL": "http://bar.url"}, - "kwargs": {}, - "expected": {"input_auth_token": "foo_token", - "service_catalog_url": "http://bar.url", - "os_endpoint_type": "publicURL"} - }, - # only env var - { - "env_vars": {"OS_TOKEN": "foo_token", - "OS_MANILA_BYPASS_URL": "http://bar.url", - "OS_MANILA_ENDPOINT_TYPE": "custom-endpoint-type"}, - "kwargs": {}, - "expected": {"input_auth_token": "foo_token", - "service_catalog_url": "http://bar.url", - "os_endpoint_type": "custom-endpoint-type"}, - }, - # only kwargs - { - "env_vars": {"OS_TOKEN": "foo_token", - "OS_MANILA_BYPASS_URL": "http://bar.url"}, - "kwargs": {"--endpoint-type": "custom-kwargs-endpoint-type"}, - "expected": {"input_auth_token": "foo_token", - "service_catalog_url": "http://bar.url", - "os_endpoint_type": "custom-kwargs-endpoint-type"}, - }, - # env var *and* kwargs (kwargs should win) - { - "env_vars": {"OS_TOKEN": "foo_token", - "OS_MANILA_BYPASS_URL": "http://bar.url", - "os_endpoint_type": "custom-env-endpoint-type"}, - "kwargs": {"--endpoint-type": "custom-kwargs-endpoint-type"}, - "expected": {"input_auth_token": "foo_token", - "service_catalog_url": "http://bar.url", - "os_endpoint_type": "custom-kwargs-endpoint-type"}, - } - ) - @ddt.unpack - def test_main_success_with_os_endpoint(self, env_vars, kwargs, expected): - self.set_env_vars(env_vars) - with mock.patch.object(shell, "client") as mock_client: - cmd = "" - for k, v in kwargs.items(): - cmd += "%s=%s " % (k, v) - cmd += "list" - - self.shell(cmd) - - mock_client.Client.assert_called_with( - manilaclient.API_MAX_VERSION, - username="", - password="", - project_name="", - auth_url="", - insecure=False, - region_name="", - tenant_id="", - endpoint_type=expected["os_endpoint_type"], - extensions=mock.ANY, - service_type=constants.V2_SERVICE_TYPE, - service_name="", - retries=0, - http_log_debug=False, - cacert=None, - use_keyring=False, - force_new_token=False, - user_id="", - user_domain_id="", - user_domain_name="", - project_domain_id="", - project_domain_name="", - cert=None, - input_auth_token=expected["input_auth_token"], - service_catalog_url=expected["service_catalog_url"], - ) - - def test_help_unknown_command(self): - self.assertRaises(exceptions.CommandError, self.shell, 'help foofoo') - - @ddt.data('list --help', '--help list', 'help list') - def test_help_on_subcommand(self, cmd): - required = [ - '.*?^usage: manila list', - '.*?^List NAS shares with filters.', - ] - help_text = self.shell(cmd) - for r in required: - self.assertThat(help_text, - matchers.MatchesRegex(r, re.DOTALL | re.MULTILINE)) - - def test_common_args_in_help_message(self): - expected_args = ( - '--version', '', '--debug', '--os-cache', '--os-reset-cache', - '--os-user-id', '--os-username', '--os-password', - '--os-tenant-name', '--os-project-name', '--os-tenant-id', - '--os-project-id', '--os-user-domain-id', '--os-user-domain-name', - '--os-project-domain-id', '--os-project-domain-name', - '--os-auth-url', '--os-region-name', '--service-type', - '--service-name', '--share-service-name', '--endpoint-type', - '--os-share-api-version', '--os-cacert', '--retries', '--os-cert', - '--os-key', - ) - - help_text = self.shell('help') - - for expected_arg in expected_args: - self.assertIn(expected_arg, help_text) - - -class CustomOpenStackManilaShell(shell.OpenStackManilaShell): - - @staticmethod - @cliutils.arg( - '--default-is-none', - '--default_is_none', - type=str, - metavar='', - action='single_alias', - help='Default value is None and metavar set.', - default=None) - def do_foo(cs, args): - cliutils.print_dict({'key': args.default_is_none}) - - @staticmethod - @cliutils.arg( - '--default-is-not-none', - '--default_is_not_none', - type=str, - action='single_alias', - help='Default value is not None and metavar not set.', - default='bar') - def do_bar(cs, args): - cliutils.print_dict({'key': args.default_is_not_none}) - - @staticmethod - @cliutils.arg( - '--list-like', - '--list_like', - nargs='*', - action='single_alias', - help='Default value is None, metavar not set and result is list.', - default=None) - def do_quuz(cs, args): - cliutils.print_dict({'key': args.list_like}) - - -@ddt.ddt -class AllowOnlyOneAliasAtATimeActionTest(utils.TestCase): - FAKE_ENV = { - 'OS_USERNAME': 'username', - 'OS_PASSWORD': 'password', - 'OS_TENANT_NAME': 'tenant_name', - 'OS_AUTH_URL': 'http://no.where', - } - - def setUp(self): - super(self.__class__, self).setUp() - for k, v in self.FAKE_ENV.items(): - self.useFixture(fixtures.EnvironmentVariable(k, v)) - self.mock_object( - shell.client, 'get_client_class', - mock.Mock(return_value=fakes.FakeClient)) - - def shell_discover_client(self, - current_client, - os_api_version, - os_endpoint_type, - os_service_type, - client_args): - return current_client, manilaclient.API_MAX_VERSION - - def shell(self, argstr): - orig = sys.stdout - try: - sys.stdout = io.StringIO() - _shell = CustomOpenStackManilaShell() - _shell._discover_client = self.shell_discover_client - _shell.main(argstr.split()) - except SystemExit: - exc_type, exc_value, exc_traceback = sys.exc_info() - self.assertEqual(exc_value.code, 0) - finally: - out = sys.stdout.getvalue() - sys.stdout.close() - sys.stdout = orig - - return out - - @ddt.data( - ('--default-is-none foo', 'foo'), - ('--default-is-none foo --default-is-none foo', 'foo'), - ('--default-is-none foo --default_is_none foo', 'foo'), - ('--default_is_none None', 'None'), - ) - @ddt.unpack - def test_foo_success(self, options_str, expected_result): - output = self.shell('foo %s' % options_str) - parsed_output = output_parser.details(output) - self.assertEqual({'key': expected_result}, parsed_output) - - @ddt.data( - '--default-is-none foo --default-is-none bar', - '--default-is-none foo --default_is_none bar', - '--default-is-none foo --default_is_none FOO', - ) - def test_foo_error(self, options_str): - self.assertRaises( - matchers.MismatchError, self.shell, 'foo %s' % options_str) - - @ddt.data( - ('--default-is-not-none bar', 'bar'), - ('--default_is_not_none bar --default-is-not-none bar', 'bar'), - ('--default_is_not_none bar --default_is_not_none bar', 'bar'), - ('--default-is-not-none not_bar', 'not_bar'), - ('--default_is_not_none None', 'None'), - ) - @ddt.unpack - def test_bar_success(self, options_str, expected_result): - output = self.shell('bar %s' % options_str) - parsed_output = output_parser.details(output) - self.assertEqual({'key': expected_result}, parsed_output) - - @ddt.data( - '--default-is-not-none foo --default-is-not-none bar', - '--default-is-not-none foo --default_is_not_none bar', - '--default-is-not-none bar --default_is_not_none BAR', - ) - def test_bar_error(self, options_str): - self.assertRaises( - matchers.MismatchError, self.shell, 'bar %s' % options_str) - - @ddt.data( - ('--list-like q=w', "['q=w']"), - ('--list-like q=w --list_like q=w', "['q=w']"), - ('--list-like q=w e=r t=y --list_like e=r t=y q=w', - "['e=r', 'q=w', 't=y']"), - ('--list_like q=w e=r t=y', "['e=r', 'q=w', 't=y']"), - ) - @ddt.unpack - def test_quuz_success(self, options_str, expected_result): - output = self.shell('quuz %s' % options_str) - parsed_output = output_parser.details(output) - self.assertEqual({'key': expected_result}, parsed_output) - - @ddt.data( - '--list-like q=w --list_like e=r t=y', - ) - def test_quuz_error(self, options_str): - self.assertRaises( - matchers.MismatchError, self.shell, 'quuz %s' % options_str) diff --git a/manilaclient/tests/unit/utils.py b/manilaclient/tests/unit/utils.py index 0b642d43..f2f582bb 100644 --- a/manilaclient/tests/unit/utils.py +++ b/manilaclient/tests/unit/utils.py @@ -24,13 +24,17 @@ class TestCase(testtools.TestCase): } def setUp(self): - super(TestCase, self).setUp() - if (os.environ.get('OS_STDOUT_CAPTURE') == 'True' or - os.environ.get('OS_STDOUT_CAPTURE') == '1'): + super().setUp() + if ( + os.environ.get('OS_STDOUT_CAPTURE') == 'True' + or os.environ.get('OS_STDOUT_CAPTURE') == '1' + ): stdout = self.useFixture(fixtures.StringStream('stdout')).stream self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout)) - if (os.environ.get('OS_STDERR_CAPTURE') == 'True' or - os.environ.get('OS_STDERR_CAPTURE') == '1'): + if ( + os.environ.get('OS_STDERR_CAPTURE') == 'True' + or os.environ.get('OS_STDERR_CAPTURE') == '1' + ): stderr = self.useFixture(fixtures.StringStream('stderr')).stream self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr)) @@ -50,7 +54,8 @@ def mock_object(self, obj, attr_name, new_attr=None, **kwargs): def mock_completion(self): patcher = mock.patch( - 'manilaclient.base.Manager.write_to_completion_cache') + 'manilaclient.base.Manager.write_to_completion_cache' + ) patcher.start() self.addCleanup(patcher.stop) @@ -68,12 +73,13 @@ class TestResponse(requests.Response): def __init__(self, data): self._text = None - super(TestResponse, self) + super() if isinstance(data, dict): self.status_code = data.get('status_code', None) self.headers = data.get('headers', {}) self.headers['x-openstack-request-id'] = data.get( - 'x-openstack-request-id', 'fake-request-id') + 'x-openstack-request-id', 'fake-request-id' + ) # Fake the text attribute to streamline Response creation self._text = data.get('text', None) else: diff --git a/manilaclient/tests/unit/v1/test_limits.py b/manilaclient/tests/unit/v1/test_limits.py index 1ef77059..8140d11c 100644 --- a/manilaclient/tests/unit/v1/test_limits.py +++ b/manilaclient/tests/unit/v1/test_limits.py @@ -17,14 +17,15 @@ class LimitsV1Test(utils.TestCase): - def test_import_v1_limits_module(self): try: from manilaclient.v1 import limits except Exception as e: - msg = ("module 'manilaclient.v1.limits' cannot be imported " - "with error: %s") % str(e) + msg = ( + "module 'manilaclient.v1.limits' cannot be imported " + f"with error: {str(e)}" + ) assert False, msg for cls in ('Limits', 'RateLimit', 'AbsoluteLimit', 'LimitsManager'): - msg = "Module 'limits' has no '%s' attr." % cls + msg = f"Module 'limits' has no '{cls}' attr." self.assertTrue(hasattr(limits, cls), msg) diff --git a/manilaclient/tests/unit/v1/test_quota_classes.py b/manilaclient/tests/unit/v1/test_quota_classes.py index 498ddfb5..637675b4 100644 --- a/manilaclient/tests/unit/v1/test_quota_classes.py +++ b/manilaclient/tests/unit/v1/test_quota_classes.py @@ -17,14 +17,15 @@ class QuotaClassesV1Test(utils.TestCase): - def test_import_v1_quota_classes_module(self): try: from manilaclient.v1 import quota_classes except Exception as e: - msg = ("module 'manilaclient.v1.quota_classes' cannot be imported " - "with error: %s") % str(e) + msg = ( + "module 'manilaclient.v1.quota_classes' cannot be imported " + f"with error: {str(e)}" + ) assert False, msg for cls in ('QuotaClassSet', 'QuotaClassSetManager'): - msg = "Module 'quota_classes' has no '%s' attr." % cls + msg = f"Module 'quota_classes' has no '{cls}' attr." self.assertTrue(hasattr(quota_classes, cls), msg) diff --git a/manilaclient/tests/unit/v1/test_quotas.py b/manilaclient/tests/unit/v1/test_quotas.py index cb2058ce..1c2a299c 100644 --- a/manilaclient/tests/unit/v1/test_quotas.py +++ b/manilaclient/tests/unit/v1/test_quotas.py @@ -17,14 +17,15 @@ class QuotasV1Test(utils.TestCase): - def test_import_v1_quotas_module(self): try: from manilaclient.v1 import quotas except Exception as e: - msg = ("module 'manilaclient.v1.quotas' cannot be imported " - "with error: %s") % str(e) + msg = ( + "module 'manilaclient.v1.quotas' cannot be imported " + f"with error: {str(e)}" + ) assert False, msg for cls in ('QuotaSet', 'QuotaSetManager'): - msg = "Module 'quotas' has no '%s' attr." % cls + msg = f"Module 'quotas' has no '{cls}' attr." self.assertTrue(hasattr(quotas, cls), msg) diff --git a/manilaclient/tests/unit/v1/test_scheduler_stats.py b/manilaclient/tests/unit/v1/test_scheduler_stats.py index 777f1e59..8c863e1a 100644 --- a/manilaclient/tests/unit/v1/test_scheduler_stats.py +++ b/manilaclient/tests/unit/v1/test_scheduler_stats.py @@ -17,14 +17,15 @@ class SchedulerStatsV1Test(utils.TestCase): - def test_import_v1_scheduler_stats_module(self): try: from manilaclient.v1 import scheduler_stats except Exception as e: - msg = ("module 'manilaclient.v1.scheduler_stats' cannot be " - "imported with error: %s") % str(e) + msg = ( + "module 'manilaclient.v1.scheduler_stats' cannot be " + f"imported with error: {str(e)}" + ) assert False, msg for cls in ('Pool', 'PoolManager'): - msg = "Module 'scheduler_stats' has no '%s' attr." % cls + msg = f"Module 'scheduler_stats' has no '{cls}' attr." self.assertTrue(hasattr(scheduler_stats, cls), msg) diff --git a/manilaclient/tests/unit/v1/test_security_services.py b/manilaclient/tests/unit/v1/test_security_services.py index 49d9013d..a90862a6 100644 --- a/manilaclient/tests/unit/v1/test_security_services.py +++ b/manilaclient/tests/unit/v1/test_security_services.py @@ -17,14 +17,15 @@ class SecurityServicesV1Test(utils.TestCase): - def test_import_v1_security_services_module(self): try: from manilaclient.v1 import security_services except Exception as e: - msg = ("module 'manilaclient.v1.security_services' cannot be " - "imported with error: %s") % str(e) + msg = ( + "module 'manilaclient.v1.security_services' cannot be " + f"imported with error: {str(e)}" + ) assert False, msg for cls in ('SecurityService', 'SecurityServiceManager'): - msg = "Module 'security_services' has no '%s' attr." % cls + msg = f"Module 'security_services' has no '{cls}' attr." self.assertTrue(hasattr(security_services, cls), msg) diff --git a/manilaclient/tests/unit/v1/test_services.py b/manilaclient/tests/unit/v1/test_services.py index 81edd710..66910644 100644 --- a/manilaclient/tests/unit/v1/test_services.py +++ b/manilaclient/tests/unit/v1/test_services.py @@ -17,14 +17,15 @@ class ServicesV1Test(utils.TestCase): - def test_import_v1_services_module(self): try: from manilaclient.v1 import services except Exception as e: - msg = ("module 'manilaclient.v1.services' cannot be imported " - "with error: %s") % str(e) + msg = ( + "module 'manilaclient.v1.services' cannot be imported " + f"with error: {str(e)}" + ) assert False, msg for cls in ('Service', 'ServiceManager'): - msg = "Module 'services' has no '%s' attr." % cls + msg = f"Module 'services' has no '{cls}' attr." self.assertTrue(hasattr(services, cls), msg) diff --git a/manilaclient/tests/unit/v1/test_share_networks.py b/manilaclient/tests/unit/v1/test_share_networks.py index 7191e51b..5aef7d34 100644 --- a/manilaclient/tests/unit/v1/test_share_networks.py +++ b/manilaclient/tests/unit/v1/test_share_networks.py @@ -17,14 +17,15 @@ class ShareNetworksV1Test(utils.TestCase): - def test_import_v1_share_networks_module(self): try: from manilaclient.v1 import share_networks except Exception as e: - msg = ("module 'manilaclient.v1.share_networks' cannot be " - "imported with error: %s") % str(e) + msg = ( + "module 'manilaclient.v1.share_networks' cannot be " + f"imported with error: {str(e)}" + ) assert False, msg for cls in ('ShareNetwork', 'ShareNetworkManager'): - msg = "Module 'share_networks' has no '%s' attr." % cls + msg = f"Module 'share_networks' has no '{cls}' attr." self.assertTrue(hasattr(share_networks, cls), msg) diff --git a/manilaclient/tests/unit/v1/test_share_servers.py b/manilaclient/tests/unit/v1/test_share_servers.py index 0416032b..42e8c25f 100644 --- a/manilaclient/tests/unit/v1/test_share_servers.py +++ b/manilaclient/tests/unit/v1/test_share_servers.py @@ -17,14 +17,15 @@ class ShareServersV1Test(utils.TestCase): - def test_import_v1_share_servers_module(self): try: from manilaclient.v1 import share_servers except Exception as e: - msg = ("module 'manilaclient.v1.share_servers' cannot be imported " - "with error: %s") % str(e) + msg = ( + "module 'manilaclient.v1.share_servers' cannot be imported " + f"with error: {str(e)}" + ) assert False, msg for cls in ('ShareServer', 'ShareServerManager'): - msg = "Module 'share_servers' has no '%s' attr." % cls + msg = f"Module 'share_servers' has no '{cls}' attr." self.assertTrue(hasattr(share_servers, cls), msg) diff --git a/manilaclient/tests/unit/v1/test_share_snapshots.py b/manilaclient/tests/unit/v1/test_share_snapshots.py index 6205a6f3..2cfb5a3a 100644 --- a/manilaclient/tests/unit/v1/test_share_snapshots.py +++ b/manilaclient/tests/unit/v1/test_share_snapshots.py @@ -17,14 +17,15 @@ class ShareSnapshotsV1Test(utils.TestCase): - def test_import_v1_share_snapshots_module(self): try: from manilaclient.v1 import share_snapshots except Exception as e: - msg = ("module 'manilaclient.v1.share_snapshots' cannot be " - "imported with error: %s") % str(e) + msg = ( + "module 'manilaclient.v1.share_snapshots' cannot be " + f"imported with error: {str(e)}" + ) assert False, msg for cls in ('ShareSnapshot', 'ShareSnapshotManager'): - msg = "Module 'share_snapshots' has no '%s' attr." % cls + msg = f"Module 'share_snapshots' has no '{cls}' attr." self.assertTrue(hasattr(share_snapshots, cls), msg) diff --git a/manilaclient/tests/unit/v1/test_share_type_access.py b/manilaclient/tests/unit/v1/test_share_type_access.py index 839ec002..f2f8d504 100644 --- a/manilaclient/tests/unit/v1/test_share_type_access.py +++ b/manilaclient/tests/unit/v1/test_share_type_access.py @@ -17,14 +17,15 @@ class ShareTypeAccessV1Test(utils.TestCase): - def test_import_v1_share_type_access_module(self): try: from manilaclient.v1 import share_type_access except Exception as e: - msg = ("module 'manilaclient.v1.share_type_access' cannot be " - "imported with error: %s") % str(e) + msg = ( + "module 'manilaclient.v1.share_type_access' cannot be " + f"imported with error: {str(e)}" + ) assert False, msg for cls in ('ShareTypeAccess', 'ShareTypeAccessManager'): - msg = "Module 'share_type_access' has no '%s' attr." % cls + msg = f"Module 'share_type_access' has no '{cls}' attr." self.assertTrue(hasattr(share_type_access, cls), msg) diff --git a/manilaclient/tests/unit/v1/test_share_types.py b/manilaclient/tests/unit/v1/test_share_types.py index b55e530d..ac38ab83 100644 --- a/manilaclient/tests/unit/v1/test_share_types.py +++ b/manilaclient/tests/unit/v1/test_share_types.py @@ -17,14 +17,15 @@ class ShareTypesV1Test(utils.TestCase): - def test_import_v1_share_types_module(self): try: from manilaclient.v1 import share_types except Exception as e: - msg = ("module 'manilaclient.v1.share_types' cannot be imported " - "with error: %s") % str(e) + msg = ( + "module 'manilaclient.v1.share_types' cannot be imported " + f"with error: {str(e)}" + ) assert False, msg for cls in ('ShareType', 'ShareTypeManager'): - msg = "Module 'share_types' has no '%s' attr." % cls + msg = f"Module 'share_types' has no '{cls}' attr." self.assertTrue(hasattr(share_types, cls), msg) diff --git a/manilaclient/tests/unit/v1/test_shares.py b/manilaclient/tests/unit/v1/test_shares.py index 0e2a3c13..376462ae 100644 --- a/manilaclient/tests/unit/v1/test_shares.py +++ b/manilaclient/tests/unit/v1/test_shares.py @@ -17,14 +17,15 @@ class SharesV1Test(utils.TestCase): - def test_import_v1_shares_module(self): try: from manilaclient.v1 import shares except Exception as e: - msg = ("module 'manilaclient.v1.shares' cannot be imported " - "with error: %s") % str(e) + msg = ( + "module 'manilaclient.v1.shares' cannot be imported " + f"with error: {str(e)}" + ) assert False, msg for cls in ('Share', 'ShareManager'): - msg = "Module 'shares' has no '%s' attr." % cls + msg = f"Module 'shares' has no '{cls}' attr." self.assertTrue(hasattr(shares, cls), msg) diff --git a/manilaclient/tests/unit/v2/fake_clients.py b/manilaclient/tests/unit/v2/fake_clients.py index d6f7141e..0e48a6e4 100644 --- a/manilaclient/tests/unit/v2/fake_clients.py +++ b/manilaclient/tests/unit/v2/fake_clients.py @@ -22,18 +22,21 @@ class FakeClient(fakes.FakeClient, client.Client): - def __init__(self, *args, **kwargs): api_version = kwargs.get('version') or api_versions.MAX_VERSION - client.Client.__init__(self, 'username', 'password', - 'project_id', 'auth_url', - extensions=kwargs.get('extensions'), - version=api_version) + client.Client.__init__( + self, + 'username', + 'password', + 'project_id', + 'auth_url', + extensions=kwargs.get('extensions'), + version=api_version, + ) self.client = FakeHTTPClient(**kwargs) class FakeHTTPClient(httpclient.HTTPClient): - def __init__(self, **kwargs): api_version = kwargs.get('version') or api_versions.MAX_VERSION self.username = 'username' @@ -67,21 +70,24 @@ def _cs_request_with_retries(self, url, method, **kwargs): munged_url = munged_url.strip('/').replace('/', '_').replace('.', '_') munged_url = munged_url.replace('-', '_') - callback = "%s_%s" % (method.lower(), munged_url) + callback = f"{method.lower()}_{munged_url}" if not hasattr(self, callback): - raise AssertionError('Called unknown API method: %s %s, ' - 'expected fakes method name: %s' % - (method, url, callback)) + raise AssertionError( + f'Called unknown API method: {method} {url}, ' + f'expected fakes method name: {callback}' + ) # Note the call self.callstack.append((method, url, kwargs.get('body', None))) status, headers, body = getattr(self, callback)(**kwargs) - r = utils.TestResponse({ - "status_code": status, - "text": body, - "headers": headers, - }) + r = utils.TestResponse( + { + "status_code": status, + "text": body, + "headers": headers, + } + ) return r, body # @@ -122,8 +128,7 @@ def get_os_quota_sets_test_defaults(self): def put_os_quota_sets_test(self, body, **kw): assert list(body) == ['quota_set'] - fakes.assert_has_keys(body['quota_set'], - required=['tenant_id']) + fakes.assert_has_keys(body['quota_set'], required=['tenant_id']) quota_set = { 'quota_set': { 'tenant_id': 'test', @@ -161,8 +166,7 @@ def get_os_quota_class_sets_test(self, **kw): def put_os_quota_class_sets_test(self, body, **kw): assert list(body) == ['quota_class_set'] - fakes.assert_has_keys(body['quota_class_set'], - required=['class_name']) + fakes.assert_has_keys(body['quota_class_set'], required=['class_name']) quota_class_set = { 'quota_class_set': { 'class_name': 'test', @@ -194,18 +198,22 @@ def get_extensions(self, **kw): "description": "Fake extension number 1", "links": [], "name": "Fake1", - "namespace": ("http://docs.openstack.org/" - "/ext/fake1/api/v1.1"), - "updated": "2011-06-09T00:00:00+00:00" + "namespace": ("http://docs.openstack.org//ext/fake1/api/v1.1"), + "updated": "2011-06-09T00:00:00+00:00", }, { "alias": "FAKE-2", "description": "Fake extension number 2", "links": [], "name": "Fake2", - "namespace": ("http://docs.openstack.org/" - "/ext/fake1/api/v1.1"), - "updated": "2011-06-09T00:00:00+00:00" + "namespace": ("http://docs.openstack.org//ext/fake1/api/v1.1"), + "updated": "2011-06-09T00:00:00+00:00", }, ] - return (200, {}, {"extensions": exts, }) + return ( + 200, + {}, + { + "extensions": exts, + }, + ) diff --git a/manilaclient/tests/unit/v2/fakes.py b/manilaclient/tests/unit/v2/fakes.py index cf845291..52dee6e8 100644 --- a/manilaclient/tests/unit/v2/fakes.py +++ b/manilaclient/tests/unit/v2/fakes.py @@ -20,7 +20,6 @@ class FakeClient(fakes.FakeClient): - def __init__(self, *args, **kwargs): client.Client.__init__( self, @@ -32,7 +31,9 @@ def __init__(self, *args, **kwargs): input_auth_token='token', extensions=kwargs.get('extensions'), service_catalog_url='http://localhost:8786', - api_version=kwargs.get("api_version", manilaclient.API_MAX_VERSION) + api_version=kwargs.get( + "api_version", manilaclient.API_MAX_VERSION + ), ) self.client = FakeHTTPClient(**kwargs) @@ -70,7 +71,6 @@ def get_fake_snapshot_export_location(): class FakeHTTPClient(fakes.FakeHTTPClient): - def get_(self, **kw): body = { "versions": [ @@ -86,11 +86,12 @@ def get_(self, **kw): { "href": "http://localhost:8786/v2/", "rel": "self", - } + }, ], "min_version": "2.0", "version": self.default_headers[ - "X-Openstack-Manila-Api-Version"], + "X-Openstack-Manila-Api-Version" + ], "id": "v2.0", } ] @@ -100,14 +101,18 @@ def get_(self, **kw): def get_availability_zones(self): availability_zones = { "availability_zones": [ - {"id": "368c5780-ad72-4bcf-a8b6-19e45f4fafoo", - "name": "foo", - "created_at": "2016-07-08T14:13:12.000000", - "updated_at": "2016-07-08T15:14:13.000000"}, - {"id": "368c5780-ad72-4bcf-a8b6-19e45f4fabar", - "name": "bar", - "created_at": "2016-07-08T14:13:12.000000", - "updated_at": "2016-07-08T15:14:13.000000"}, + { + "id": "368c5780-ad72-4bcf-a8b6-19e45f4fafoo", + "name": "foo", + "created_at": "2016-07-08T14:13:12.000000", + "updated_at": "2016-07-08T15:14:13.000000", + }, + { + "id": "368c5780-ad72-4bcf-a8b6-19e45f4fabar", + "name": "bar", + "created_at": "2016-07-08T14:13:12.000000", + "updated_at": "2016-07-08T15:14:13.000000", + }, ] } return (200, {}, availability_zones) @@ -115,20 +120,24 @@ def get_availability_zones(self): def get_os_services(self, **kw): services = { "services": [ - {"status": "enabled", - "binary": "manila-scheduler", - "zone": "foozone", - "state": "up", - "updated_at": "2015-10-09T13:54:09.000000", - "host": "lucky-star", - "id": 1}, - {"status": "enabled", - "binary": "manila-share", - "zone": "foozone", - "state": "up", - "updated_at": "2015-10-09T13:54:05.000000", - "host": "lucky-star", - "id": 2}, + { + "status": "enabled", + "binary": "manila-scheduler", + "zone": "foozone", + "state": "up", + "updated_at": "2015-10-09T13:54:09.000000", + "host": "lucky-star", + "id": 1, + }, + { + "status": "enabled", + "binary": "manila-share", + "zone": "foozone", + "state": "up", + "updated_at": "2015-10-09T13:54:05.000000", + "host": "lucky-star", + "id": 2, + }, ] } return (200, {}, services) @@ -136,14 +145,20 @@ def get_os_services(self, **kw): get_services = get_os_services def put_os_services_enable(self, **kw): - return (200, {}, {'host': 'foo', 'binary': 'manila-share', - 'disabled': False}) + return ( + 200, + {}, + {'host': 'foo', 'binary': 'manila-share', 'disabled': False}, + ) put_services_enable = put_os_services_enable def put_os_services_disable(self, **kw): - return (200, {}, {'host': 'foo', 'binary': 'manila-share', - 'disabled': True}) + return ( + 200, + {}, + {'host': 'foo', 'binary': 'manila-share', 'disabled': True}, + ) put_services_disable = put_os_services_disable @@ -162,7 +177,7 @@ def get_v2(self, **kw): { "href": "http://localhost:8786/v2/", "rel": "self", - } + }, ], "min_version": "2.0", "version": "2.5", @@ -214,8 +229,12 @@ def get_shares(self, **kw): 'id': share_id, 'name': 'sharename', 'links': [ - {"href": endpoint + "/fake_project/shares/" + share_id, - "rel": "self"}, + { + "href": endpoint + + "/fake_project/shares/" + + share_id, + "rel": "self", + }, ], }, ] @@ -240,10 +259,14 @@ def get_shares_detail(self, **kw): 'export_location': 'fake_export_location', 'snapshot_id': 'fake_snapshot_id', 'links': [ - {"href": endpoint + "/fake_project/shares/" - + share_id1234, "rel": "self"}, + { + "href": endpoint + + "/fake_project/shares/" + + share_id1234, + "rel": "self", + }, ], - 'metadata': {} + 'metadata': {}, }, { 'id': share_id1111, @@ -254,10 +277,14 @@ def get_shares_detail(self, **kw): 'export_location': 'fake_export_location', 'snapshot_id': 'fake_snapshot_id', 'links': [ - {"href": endpoint + "/fake_project/shares/" - + share_id1111, "rel": "self"}, + { + "href": endpoint + + "/fake_project/shares/" + + share_id1111, + "rel": "self", + }, ], - 'metadata': {} + 'metadata': {}, }, { 'id': share_id2222, @@ -268,10 +295,14 @@ def get_shares_detail(self, **kw): 'export_location': 'fake_export_location', 'snapshot_id': 'fake_snapshot_id', 'links': [ - {"href": endpoint + "/fake_project/shares/" - + share_id2222, "rel": "self"}, + { + "href": endpoint + + "/fake_project/shares/" + + share_id2222, + "rel": "self", + }, ], - 'metadata': {'key1': 'value1'} + 'metadata': {'key1': 'value1'}, }, { 'id': share_id3333, @@ -282,10 +313,14 @@ def get_shares_detail(self, **kw): 'export_location': 'fake_export_location', 'snapshot_id': 'fake_snapshot_id', 'links': [ - {"href": endpoint + "/fake_project/shares/" - + share_id3333, "rel": "self"}, + { + "href": endpoint + + "/fake_project/shares/" + + share_id3333, + "rel": "self", + }, ], - 'metadata': {'key1': 'value1', 'key2': 'value2'} + 'metadata': {'key1': 'value1', 'key2': 'value2'}, }, ], } @@ -296,8 +331,13 @@ def get_shares_detail(self, **kw): return (200, {}, shares) def get_snapshots_1234(self, **kw): - snapshot = {'snapshot': {'id': 1234, 'name': 'sharename', - 'status': 'available'}} + snapshot = { + 'snapshot': { + 'id': 1234, + 'name': 'sharename', + 'status': 'available', + } + } return (200, {}, snapshot) def get_share_servers(self, **kw): @@ -324,10 +364,11 @@ def post_snapshots_1234_action(self, body, **kw): action = list(body)[0] if action in ('reset_status', 'os-reset_status'): assert 'status' in body.get( - 'reset_status', body.get('os-reset_status')) + 'reset_status', body.get('os-reset_status') + ) elif action in ('force_delete', 'os-force_delete'): assert body[action] is None - elif action in ('unmanage', ): + elif action in ('unmanage',): assert body[action] is None elif action in 'allow_access': assert 'access_type' in body['allow_access'] @@ -336,7 +377,7 @@ def post_snapshots_1234_action(self, body, **kw): elif action in 'deny_access': assert 'access_id' in body['deny_access'] else: - raise AssertionError("Unexpected action: %s" % action) + raise AssertionError(f"Unexpected action: {action}") return (resp, {}, _body) post_snapshots_5678_action = post_snapshots_1234_action @@ -345,20 +386,18 @@ def post_snapshots_manage(self, body, **kw): _body = {'snapshot': {'id': 'fake'}} resp = 202 - if not ('share_id' in body['snapshot'] - and 'provider_location' in body['snapshot'] - and 'driver_options' in body['snapshot']): + if not ( + 'share_id' in body['snapshot'] + and 'provider_location' in body['snapshot'] + and 'driver_options' in body['snapshot'] + ): resp = 422 result = (resp, {}, _body) return result def _share_instances(self): - instances = { - 'share_instances': [ - fake_share_instance - ] - } + instances = {'share_instances': [fake_share_instance]} return (200, {}, instances) def put_quota_sets_1234(self, *args, **kwargs): @@ -381,21 +420,15 @@ def get_quota_sets_1234_detail(self, *args, **kwargs): quota_set = { 'quota_set': { 'id': '1234', - 'shares': {'in_use': 0, - 'limit': 50, - 'reserved': 0}, - 'gigabytes': {'in_use': 0, - 'limit': 10000, - 'reserved': 0}, - 'snapshots': {'in_use': 0, - 'limit': 50, - 'reserved': 0}, - 'snapshot_gigabytes': {'in_use': 0, - 'limit': 1000, - 'reserved': 0}, - 'share_networks': {'in_use': 0, - 'limit': 10, - 'reserved': 0}, + 'shares': {'in_use': 0, 'limit': 50, 'reserved': 0}, + 'gigabytes': {'in_use': 0, 'limit': 10000, 'reserved': 0}, + 'snapshots': {'in_use': 0, 'limit': 50, 'reserved': 0}, + 'snapshot_gigabytes': { + 'in_use': 0, + 'limit': 1000, + 'reserved': 0, + }, + 'share_networks': {'in_use': 0, 'limit': 10, 'reserved': 0}, } } return (200, {}, quota_set) @@ -412,14 +445,16 @@ def get_share_instances_1234_export_locations(self, **kw): return (200, {}, export_locations) get_shares_1234_export_locations = ( - get_share_instances_1234_export_locations) + get_share_instances_1234_export_locations + ) def get_share_instances_1234_export_locations_fake_el_uuid(self, **kw): export_location = {'export_location': get_fake_export_location()} return (200, {}, export_location) get_shares_1234_export_locations_fake_el_uuid = ( - get_share_instances_1234_export_locations_fake_el_uuid) + get_share_instances_1234_export_locations_fake_el_uuid + ) def get_shares_fake_instances(self, **kw): return self._share_instances() @@ -437,11 +472,12 @@ def post_share_instances_1234_action(self, body, **kw): action = list(body)[0] if action in ('reset_status', 'os-reset_status'): assert 'status' in body.get( - 'reset_status', body.get('os-reset_status')) + 'reset_status', body.get('os-reset_status') + ) elif action == 'os-force_delete': assert body[action] is None else: - raise AssertionError("Unexpected share action: %s" % action) + raise AssertionError(f"Unexpected share action: {action}") return (resp, {}, _body) def get_snapshots(self, **kw): @@ -457,17 +493,21 @@ def get_snapshots(self, **kw): return (200, {}, snapshots) def get_snapshots_detail(self, **kw): - snapshots = {'snapshots': [{ - 'id': 1234, - 'created_at': '2012-08-27T00:00:00.000000', - 'share_size': 1, - 'share_id': 4321, - 'status': 'available', - 'name': 'sharename', - 'display_description': 'description', - 'share_proto': 'type', - 'export_location': 'location', - }]} + snapshots = { + 'snapshots': [ + { + 'id': 1234, + 'created_at': '2012-08-27T00:00:00.000000', + 'share_size': 1, + 'share_id': 4321, + 'status': 'available', + 'name': 'sharename', + 'display_description': 'description', + 'share_proto': 'type', + 'export_location': 'location', + } + ] + } if kw.get('with_count'): snapshots.update({'count': 2}) @@ -477,11 +517,13 @@ def post_os_share_manage(self, body, **kw): _body = {'share': {'id': 'fake'}} resp = 202 - if not ('service_host' in body['share'] - and 'share_type' in body['share'] - and 'export_path' in body['share'] - and 'protocol' in body['share'] - and 'driver_options' in body['share']): + if not ( + 'service_host' in body['share'] + and 'share_type' in body['share'] + and 'export_path' in body['share'] + and 'protocol' in body['share'] + and 'driver_options' in body['share'] + ): resp = 422 result = (resp, {}, _body) @@ -493,9 +535,11 @@ def post_share_servers_manage(self, body, **kw): _body = {'share_server': {'id': 'fake'}} resp = 202 - if not ('host' in body['share_server'] - and 'share_network' in body['share_server'] - and 'identifier' in body['share_server']): + if not ( + 'host' in body['share_server'] + and 'share_network' in body['share_server'] + and 'identifier' in body['share_server'] + ): resp = 422 result = (resp, {}, _body) @@ -506,28 +550,32 @@ def post_share_servers_1234_action(self, body, **kw): assert len(list(body)) == 1 action = list(body)[0] - if action in ('reset_status', ): + if action in ('reset_status',): assert 'status' in body.get( - 'reset_status', body.get('os-reset_status')) + 'reset_status', body.get('os-reset_status') + ) _body = { 'reset_status': {'status': body['reset_status']['status']} } - elif action in ('unmanage', ): + elif action in ('unmanage',): assert 'force' in body[action] elif action in ( - 'migration_cancel', 'migration_complete', - 'migration_get_progress'): + 'migration_cancel', + 'migration_complete', + 'migration_get_progress', + ): assert body[action] is None if 'migration_get_progress' == action: - _body = {'total_progress': 50, - 'task_state': 'fake_task_state', - 'destination_share_server_id': 'fake_dest_id'} + _body = { + 'total_progress': 50, + 'task_state': 'fake_task_state', + 'destination_share_server_id': 'fake_dest_id', + } return 200, {}, _body elif 'migration_complete' == action: _body = {'destination_share_server_id': 'fake_dest_id'} return 200, {}, _body - elif action in ( - 'migration_start', 'migration_check'): + elif action in ('migration_start', 'migration_check'): assert 'host' in body[action] if 'migration-check': _body = { @@ -560,7 +608,7 @@ def post_shares_1234_action(self, body, **kw): if action in ('os-allow_access', 'allow_access'): expected = ['access_to', 'access_type'] actual = sorted(list(body[action])) - err_msg = "expected '%s', actual is '%s'" % (expected, actual) + err_msg = f"expected '{expected}', actual is '{actual}'" assert expected == actual, err_msg _body = {'access': {}} elif action in ('os-deny_access', 'deny_access'): @@ -569,34 +617,39 @@ def post_shares_1234_action(self, body, **kw): assert body[action] is None elif action in ('os-reset_status', 'reset_status'): assert 'status' in body.get( - 'reset_status', body.get('os-reset_status')) + 'reset_status', body.get('os-reset_status') + ) elif action in ('os-force_delete', 'force_delete'): assert body[action] is None elif action in ('os-extend', 'os-shrink', 'extend', 'shrink'): assert body[action] is not None assert body[action]['new_size'] is not None - elif action in ('unmanage', ): + elif action in ('unmanage',): assert body[action] is None - elif action in ('revert', ): + elif action in ('revert',): assert body[action] is not None assert body[action]['snapshot_id'] is not None elif action in ( - 'migration_cancel', 'migration_complete', - 'migration_get_progress'): + 'migration_cancel', + 'migration_complete', + 'migration_get_progress', + ): assert body[action] is None if 'migration_get_progress' == action: _body = {'total_progress': 50} return 200, {}, _body elif action in ( - 'os-migrate_share', 'migrate_share', - 'migration_start'): + 'os-migrate_share', + 'migrate_share', + 'migration_start', + ): assert 'host' in body[action] elif action == 'reset_task_state': assert 'task_state' in body[action] elif action in ('soft_delete', 'restore'): assert body[action] is None else: - raise AssertionError("Unexpected share action: %s" % action) + raise AssertionError(f"Unexpected share action: {action}") return (resp, {}, _body) def post_shares_1111_action(self, body, **kw): @@ -607,34 +660,38 @@ def post_shares_1111_action(self, body, **kw): if action in ('allow_access', 'os-allow_access'): expected = ['access_level', 'access_to', 'access_type'] actual = sorted(list(body[action])) - err_msg = "expected '%s', actual is '%s'" % (expected, actual) + err_msg = f"expected '{expected}', actual is '{actual}'" assert expected == actual, err_msg _body = {'access': {}} elif action in ('access_list', 'os-access_list'): assert body[action] is None _body = { - 'access_list': [{ - 'access_level': 'rw', - 'state': 'active', - 'id': '1122', - 'access_type': 'ip', - 'access_to': '10.0.0.7' - }] + 'access_list': [ + { + 'access_level': 'rw', + 'state': 'active', + 'id': '1122', + 'access_type': 'ip', + 'access_to': '10.0.0.7', + } + ] } else: - raise AssertionError("Unexpected share action: %s" % action) + raise AssertionError(f"Unexpected share action: {action}") return (resp, {}, _body) def get_share_access_rules(self, **kw): access = { - 'access_list': [{ - 'access_level': 'rw', - 'state': 'active', - 'id': '1122', - 'access_type': 'ip', - 'access_to': '10.0.0.7', - 'metadata': {'key1': 'v1'} - }] + 'access_list': [ + { + 'access_level': 'rw', + 'state': 'active', + 'id': '1122', + 'access_type': 'ip', + 'access_to': '10.0.0.7', + 'metadata': {'key1': 'v1'}, + } + ] } return (200, {}, access) @@ -646,7 +703,7 @@ def get_share_access_rules_9999(self, **kw): 'id': '9999', 'access_type': 'ip', 'access_to': '10.0.0.7', - 'metadata': {'key1': 'v1'} + 'metadata': {'key1': 'v1'}, } } return (200, {}, access) @@ -832,7 +889,7 @@ def get_scheduler_stats_pools(self, **kw): 'host': 'host1', 'backend': 'backend1', 'pool': 'pool2', - } + }, ] } return (200, {}, pools) @@ -853,7 +910,7 @@ def get_scheduler_stats_pools_detail(self, **kw): 'backend': 'backend1', 'pool': 'pool2', 'capabilities': {'qos': False}, - } + }, ] } return (200, {}, pools) @@ -1008,7 +1065,7 @@ def post_share_replicas_1234_action(self, body, **kw): assert body[action] is None else: if action not in ('promote'): - raise AssertionError("Unexpected share action: %s" % action) + raise AssertionError(f"Unexpected share action: {action}") return (resp, {}, _body) # @@ -1036,27 +1093,40 @@ def get_types_default(self, **kw): return self.get_types_1(**kw) def get_types_1234(self, **kw): - return (200, {}, { - 'share_type': {'id': 1234, - 'name': 'test-type-1234', - 'share_type_access:is_public': True, - 'description': "test share type desc", - 'extra_specs': {'test': 'test'}, - 'required_extra_specs': {'test': 'test'}}}) + return ( + 200, + {}, + { + 'share_type': { + 'id': 1234, + 'name': 'test-type-1234', + 'share_type_access:is_public': True, + 'description': "test share type desc", + 'extra_specs': {'test': 'test'}, + 'required_extra_specs': {'test': 'test'}, + } + }, + ) def get_types(self, **kw): req_version = self.default_headers['X-Openstack-Manila-Api-Version'] if not isinstance(req_version, api_versions.APIVersion): req_version = api_versions.APIVersion(req_version) response_body = { - 'share_types': [{'id': 1, - 'name': 'test-type-1', - 'extra_specs': {'test1': 'test1'}, - 'required_extra_specs': {'test': 'test'}}, - {'id': 2, - 'name': 'test-type-2', - 'extra_specs': {'test1': 'test1'}, - 'required_extra_specs': {'test': 'test'}}] + 'share_types': [ + { + 'id': 1, + 'name': 'test-type-1', + 'extra_specs': {'test1': 'test1'}, + 'required_extra_specs': {'test': 'test'}, + }, + { + 'id': 2, + 'name': 'test-type-2', + 'extra_specs': {'test1': 'test1'}, + 'required_extra_specs': {'test': 'test'}, + }, + ] } if req_version >= api_versions.APIVersion('2.46'): @@ -1066,55 +1136,82 @@ def get_types(self, **kw): return 200, {}, response_body def get_types_1(self, **kw): - return (200, {}, {'share_type': { - 'id': 1, - 'name': 'test-type-1', - 'extra_specs': {'test': 'test'}, - 'required_extra_specs': {'test': 'test'}}}) + return ( + 200, + {}, + { + 'share_type': { + 'id': 1, + 'name': 'test-type-1', + 'extra_specs': {'test': 'test'}, + 'required_extra_specs': {'test': 'test'}, + } + }, + ) def get_types_2(self, **kw): - return (200, {}, {'share_type': { - 'id': 2, - 'name': 'test-type-2', - 'extra_specs': {'test': 'test'}, - 'required_extra_specs': {'test': 'test'}}}) + return ( + 200, + {}, + { + 'share_type': { + 'id': 2, + 'name': 'test-type-2', + 'extra_specs': {'test': 'test'}, + 'required_extra_specs': {'test': 'test'}, + } + }, + ) def get_types_3(self, **kw): - return (200, {}, { - 'share_type': { - 'id': 3, - 'name': 'test-type-3', - 'extra_specs': {}, - 'os-share-type-access:is_public': False - } - }) + return ( + 200, + {}, + { + 'share_type': { + 'id': 3, + 'name': 'test-type-3', + 'extra_specs': {}, + 'os-share-type-access:is_public': False, + } + }, + ) def get_types_4(self, **kw): - return (200, {}, { - 'share_type': { - 'id': 4, - 'name': 'test-type-3', - 'extra_specs': {}, - 'os-share-type-access:is_public': True - } - }) + return ( + 200, + {}, + { + 'share_type': { + 'id': 4, + 'name': 'test-type-3', + 'extra_specs': {}, + 'os-share-type-access:is_public': True, + } + }, + ) def post_types(self, body, **kw): share_type = body['share_type'] required_extra_specs = { - "driver_handles_share_servers": share_type[ - 'extra_specs']['driver_handles_share_servers'], + "driver_handles_share_servers": share_type['extra_specs'][ + 'driver_handles_share_servers' + ], } - return (202, {}, { - 'share_type': { - 'id': 3, - 'name': 'test-type-3', - 'is_default': False, - 'description': 'test description', - 'extra_specs': share_type['extra_specs'], - 'required_extra_specs': required_extra_specs, - } - }) + return ( + 202, + {}, + { + 'share_type': { + 'id': 3, + 'name': 'test-type-3', + 'is_default': False, + 'description': 'test description', + 'extra_specs': share_type['extra_specs'], + 'required_extra_specs': required_extra_specs, + } + }, + ) def post_types_3_action(self, body, **kw): _body = None @@ -1126,7 +1223,7 @@ def post_types_3_action(self, body, **kw): elif action == 'removeProjectAccess': assert 'project' in body['removeProjectAccess'] else: - raise AssertionError('Unexpected action: %s' % action) + raise AssertionError(f'Unexpected action: {action}') return (resp, {}, _body) def post_types_1_extra_specs(self, body, **kw): @@ -1139,11 +1236,77 @@ def delete_types_1_extra_specs_k(self, **kw): def delete_types_1(self, **kw): return (202, {}, None) + def get_qos_types(self, **kw): + response_body = { + 'qos_types': [ + { + 'id': 1, + 'name': 'test-type-1', + 'specs': {'test1': 'test1'}, + }, + { + 'id': 2, + 'name': 'test-type-2', + 'specs': {'test1': 'test1'}, + }, + ] + } + + return 200, {}, response_body + + def get_qos_types_1(self, **kw): + return ( + 200, + {}, + { + 'qos_type': { + 'id': 1, + 'name': 'test-qos-type-1', + 'specs': {'test1': 'test1'}, + } + }, + ) + + def post_qos_types(self, body, **kw): + qos_type = body['qos_type'] + return ( + 202, + {}, + { + 'qos_type': { + 'id': 3, + 'name': 'test-qos-type-3', + 'description': 'test description', + 'specs': qos_type['specs'], + } + }, + ) + + def post_qos_types_1_specs(self, body, **kw): + assert list(body) == ['specs'] + return (200, {}, {'specs': {'k': 'v'}}) + + def delete_qos_types_1_specs_k(self, **kw): + return (204, {}, None) + + def delete_qos_types_1(self, **kw): + return (202, {}, None) + def get_types_3_os_share_type_access(self, **kw): - return (200, {}, {'share_type_access': [ - {'share_type_id': '11111111-1111-1111-1111-111111111111', - 'project_id': '00000000-0000-0000-0000-000000000000'} - ]}) + return ( + 200, + {}, + { + 'share_type_access': [ + { + 'share_type_id': ( + '11111111-1111-1111-1111-111111111111' + ), + 'project_id': '00000000-0000-0000-0000-000000000000', + } + ] + }, + ) get_types_3_share_type_access = get_types_3_os_share_type_access @@ -1184,31 +1347,52 @@ def get_snapshot_instances_1234(self, **kw): return (200, {}, instances) def get_snapshot_instances_1234_export_locations_fake_el_id(self, **kw): - return (200, {}, {'share_snapshot_export_location': { - 'id': 'fake_id', 'path': '/fake_path'}}) + return ( + 200, + {}, + { + 'share_snapshot_export_location': { + 'id': 'fake_id', + 'path': '/fake_path', + } + }, + ) def get_snapshots_1234_export_locations_fake_el_id(self, **kw): - return (200, {}, {'share_snapshot_export_location': { - 'id': 'fake_id', 'path': '/fake_path'}}) + return ( + 200, + {}, + { + 'share_snapshot_export_location': { + 'id': 'fake_id', + 'path': '/fake_path', + } + }, + ) - def get_snapshot_instances_1234_export_locations( - self, **kw): - snapshot_export_location = {'share_snapshot_export_locations': - [get_fake_export_location()]} + def get_snapshot_instances_1234_export_locations(self, **kw): + snapshot_export_location = { + 'share_snapshot_export_locations': [get_fake_export_location()] + } return (200, {}, snapshot_export_location) def get_snapshots_1234_export_locations(self): - snapshot_export_location = {'share_snapshot_export_locations': - [get_fake_export_location()]} + snapshot_export_location = { + 'share_snapshot_export_locations': [get_fake_export_location()] + } return (200, {}, snapshot_export_location) def get_snapshots_1234_access_list(self, **kw): - access_list = {'snapshot_access_list': [{ - 'state': 'active', - 'id': '1234', - 'access_type': 'ip', - 'access_to': '6.6.6.6' - }]} + access_list = { + 'snapshot_access_list': [ + { + 'state': 'active', + 'id': '1234', + 'access_type': 'ip', + 'access_to': '6.6.6.6', + } + ] + } return (200, {}, access_list) def delete_snapshots_1234_metadata_test_key(self, **kw): @@ -1237,7 +1421,7 @@ def post_snapshot_instances_1234_action(self, body, **kw): if action == 'reset_status': assert 'status' in body.get(action) else: - raise AssertionError("Unexpected share action: %s" % action) + raise AssertionError(f"Unexpected share action: {action}") return (resp, {}, _body) def get_share_group_types_default(self, **kw): @@ -1257,7 +1441,8 @@ def get_share_group_types(self, **kw): 'type2', ], 'is_public': True, - }, { + }, + { 'id': 2, 'name': 'test-type-2', 'group_specs': { @@ -1332,7 +1517,7 @@ def post_share_group_types_1234_action(self, body, **kw): elif action == 'removeProjectAccess': assert 'project' in body['removeProjectAccess'] else: - raise AssertionError('Unexpected action: %s' % action) + raise AssertionError(f'Unexpected action: {action}') return 202, {}, None def post_share_group_types_1_specs(self, body, **kw): @@ -1347,10 +1532,12 @@ def delete_share_group_types_1234(self, **kw): def get_share_group_types_1234_access(self, **kw): sg_type_access = { - 'share_group_type_access': [{ - 'group_type_id': '11111111-1111-1111-1111-111111111111', - 'project_id': '00000000-0000-0000-0000-000000000000', - }], + 'share_group_type_access': [ + { + 'group_type_id': '11111111-1111-1111-1111-111111111111', + 'project_id': '00000000-0000-0000-0000-000000000000', + } + ], } return 200, {}, sg_type_access @@ -1424,8 +1611,7 @@ def fake_update(url, body, response_key): return {'url': url, 'body': body, 'resp_key': response_key} -class FakeQuotaSet(object): - +class FakeQuotaSet: def __init__(self, dictionary): self.dictionary = dictionary @@ -1433,29 +1619,29 @@ def to_dict(self): return self.dictionary -class ShareNetwork(object): +class ShareNetwork: id = 'fake share network id' name = 'fake share network name' -class ShareType(object): +class ShareType: id = 'fake share type id' name = 'fake share type name' -class ShareGroupType(object): +class ShareGroupType: id = 'fake group type id' name = 'fake group type name' share_types = [ShareType().id] is_public = False -class ShareGroupTypeAccess(object): +class ShareGroupTypeAccess: id = 'fake group type access id' name = 'fake group type access name' -class ShareGroup(object): +class ShareGroup: id = 'fake group id' share_types = [ShareType().id] group_type_id = ShareGroupType().id @@ -1465,15 +1651,15 @@ class ShareGroup(object): availability_zone = 'fake az' -class ShareGroupSnapshot(object): +class ShareGroupSnapshot: id = 'fake group snapshot id' - share_group_id = ShareGroup().id, + share_group_id = (ShareGroup().id,) share_network_id = ShareNetwork().id name = 'fake name' description = 'fake description' -class Message(object): +class Message: id = 'fake message id' action_id = '001' detail_id = '002' diff --git a/manilaclient/tests/unit/v2/test_availability_zones.py b/manilaclient/tests/unit/v2/test_availability_zones.py index d82ea461..4fe16b47 100644 --- a/manilaclient/tests/unit/v2/test_availability_zones.py +++ b/manilaclient/tests/unit/v2/test_availability_zones.py @@ -24,16 +24,17 @@ @ddt.ddt class AvailabilityZoneTest(utils.TestCase): - def _get_manager(self, microversion): version = api_versions.APIVersion(microversion) mock_microversion = mock.Mock(api_version=version) return availability_zones.AvailabilityZoneManager( - api=mock_microversion) + api=mock_microversion + ) def _get_resource_path(self, microversion): - if (api_versions.APIVersion(microversion) > - api_versions.APIVersion("2.6")): + if api_versions.APIVersion(microversion) > api_versions.APIVersion( + "2.6" + ): return availability_zones.RESOURCE_PATH return availability_zones.RESOURCE_PATH_LEGACY @@ -46,7 +47,8 @@ def test_list(self, microversion): result = manager.list() manager._list.assert_called_once_with( - resource_path, availability_zones.RESOURCE_NAME) + resource_path, availability_zones.RESOURCE_NAME + ) self.assertEqual(manager._list.return_value, result) def test_representation(self): diff --git a/manilaclient/tests/unit/v2/test_client.py b/manilaclient/tests/unit/v2/test_client.py index 04f13b4b..d3c38e9f 100644 --- a/manilaclient/tests/unit/v2/test_client.py +++ b/manilaclient/tests/unit/v2/test_client.py @@ -37,26 +37,35 @@ def test_adapter_properties(self): base_url = uuidutils.generate_uuid(dashed=False) s = client.session.Session() - c = client.Client(session=s, - api_version=manilaclient.API_MAX_VERSION, - service_catalog_url=base_url, retries=retries, - input_auth_token='token') + c = client.Client( + session=s, + api_version=manilaclient.API_MAX_VERSION, + service_catalog_url=base_url, + retries=retries, + input_auth_token='token', + ) self.assertEqual(base_url, c.client.endpoint_url) self.assertEqual(retries, c.client.retries) def test_auth_via_token_invalid(self): - self.assertRaises(exceptions.ClientException, client.Client, - api_version=manilaclient.API_MAX_VERSION, - input_auth_token="token") + self.assertRaises( + exceptions.ClientException, + client.Client, + api_version=manilaclient.API_MAX_VERSION, + input_auth_token="token", + ) def test_auth_via_token_and_session(self): s = client.session.Session() base_url = uuidutils.generate_uuid(dashed=False) - c = client.Client(input_auth_token='token', - service_catalog_url=base_url, session=s, - api_version=manilaclient.API_MAX_VERSION) + c = client.Client( + input_auth_token='token', + service_catalog_url=base_url, + session=s, + api_version=manilaclient.API_MAX_VERSION, + ) self.assertIsNotNone(c.client) self.assertIsNone(c.keystone_client) @@ -64,27 +73,41 @@ def test_auth_via_token_and_session(self): def test_auth_via_token(self): base_url = uuidutils.generate_uuid(dashed=False) - c = client.Client(input_auth_token='token', - service_catalog_url=base_url, - api_version=manilaclient.API_MAX_VERSION) + c = client.Client( + input_auth_token='token', + service_catalog_url=base_url, + api_version=manilaclient.API_MAX_VERSION, + ) self.assertIsNotNone(c.client) self.assertIsNone(c.keystone_client) - @mock.patch.object(client.Client, '_get_keystone_client', mock.Mock()) - def test_valid_region_name_v1(self): + @mock.patch.object(client.Client, '_get_keystone_auth_and_session') + def test_valid_region_name_v1(self, mock_get_auth): self.mock_object(client.httpclient, 'HTTPClient') - kc = client.Client._get_keystone_client.return_value - kc.service_catalog = mock.Mock() - kc.service_catalog.get_endpoints = mock.Mock(return_value=self.catalog) - c = client.Client(api_version=manilaclient.API_DEPRECATED_VERSION, - service_type="share", - region_name='TestRegion') - self.assertTrue(client.Client._get_keystone_client.called) - kc.service_catalog.get_endpoints.assert_called_with('share') + self.mock_object(client.adapter, 'LegacyJsonAdapter') + + # Mock the auth and session returned by _get_keystone_auth_and_session + mock_auth = mock.Mock() + mock_session = mock.Mock() + mock_get_auth.return_value = (mock_auth, mock_session) + + # Mock the adapter to return token and endpoint + mocked_adapter = client.adapter.LegacyJsonAdapter.return_value + mocked_adapter.session.get_token.return_value = 'fake_token' + mocked_adapter.session.get_endpoint.return_value = 'http://1.2.3.4' + mocked_adapter.auth = mock_auth + + c = client.Client( + api_version=manilaclient.API_DEPRECATED_VERSION, + service_type="share", + region_name='TestRegion', + ) + + self.assertTrue(mock_get_auth.called) client.httpclient.HTTPClient.assert_called_with( 'http://1.2.3.4', - mock.ANY, + 'fake_token', 'python-manilaclient', insecure=False, cacert=None, @@ -92,41 +115,71 @@ def test_valid_region_name_v1(self): timeout=None, retries=None, http_log_debug=False, - api_version=manilaclient.API_DEPRECATED_VERSION) + api_version=manilaclient.API_DEPRECATED_VERSION, + ) self.assertIsNotNone(c.client) - @mock.patch.object(client.Client, '_get_keystone_client', mock.Mock()) - def test_nonexistent_region_name(self): - kc = client.Client._get_keystone_client.return_value - kc.service_catalog = mock.Mock() - kc.service_catalog.get_endpoints = mock.Mock(return_value=self.catalog) - self.assertRaises(RuntimeError, client.Client, - api_version=manilaclient.API_MAX_VERSION, - region_name='FakeRegion') - self.assertTrue(client.Client._get_keystone_client.called) - kc.service_catalog.get_endpoints.assert_called_with('sharev2') - - @mock.patch.object(client.Client, '_get_keystone_client', mock.Mock()) - def test_regions_with_same_name(self): + @mock.patch.object(client.Client, '_get_keystone_auth_and_session') + def test_nonexistent_region_name(self, mock_get_auth): + self.mock_object(client.adapter, 'LegacyJsonAdapter') + + # Mock the auth and session returned by _get_keystone_auth_and_session + mock_auth = mock.Mock() + mock_session = mock.Mock() + mock_get_auth.return_value = (mock_auth, mock_session) + + # Mock the adapter to return token but no endpoint (None) + mocked_adapter = client.adapter.LegacyJsonAdapter.return_value + mocked_adapter.session.get_token.return_value = 'fake_token' + mocked_adapter.session.get_endpoint.return_value = None + mocked_adapter.auth = mock_auth + + self.assertRaises( + RuntimeError, + client.Client, + api_version=manilaclient.API_MAX_VERSION, + region_name='FakeRegion', + ) + self.assertTrue(mock_get_auth.called) + mocked_adapter.session.get_endpoint.assert_called_with( + mock_auth, + interface='publicURL', + service_type='sharev2', + region_name='FakeRegion', + ) + + @mock.patch.object(client.Client, '_get_keystone_auth_and_session') + def test_regions_with_same_name(self, mock_get_auth): self.mock_object(client.httpclient, 'HTTPClient') - catalog = { - 'sharev2': [ - {'region': 'FirstRegion', 'publicURL': 'http://1.2.3.4'}, - {'region': 'secondregion', 'publicURL': 'http://1.1.1.1'}, - {'region': 'SecondRegion', 'publicURL': 'http://2.2.2.2'}, - ], - } - kc = client.Client._get_keystone_client.return_value - kc.service_catalog = mock.Mock() - kc.service_catalog.get_endpoints = mock.Mock(return_value=catalog) - c = client.Client(api_version=manilaclient.API_MIN_VERSION, - service_type='sharev2', - region_name='SecondRegion') - self.assertTrue(client.Client._get_keystone_client.called) - kc.service_catalog.get_endpoints.assert_called_with('sharev2') + self.mock_object(client.adapter, 'LegacyJsonAdapter') + + # Mock the auth and session returned by _get_keystone_auth_and_session + mock_auth = mock.Mock() + mock_session = mock.Mock() + mock_get_auth.return_value = (mock_auth, mock_session) + + # Mock the adapter to return token and endpoint + mocked_adapter = client.adapter.LegacyJsonAdapter.return_value + mocked_adapter.session.get_token.return_value = 'fake_token' + mocked_adapter.session.get_endpoint.return_value = 'http://2.2.2.2' + mocked_adapter.auth = mock_auth + + c = client.Client( + api_version=manilaclient.API_MIN_VERSION, + service_type='sharev2', + region_name='SecondRegion', + ) + + self.assertTrue(mock_get_auth.called) + mocked_adapter.session.get_endpoint.assert_called_with( + mock_auth, + interface='publicURL', + service_type='sharev2', + region_name='SecondRegion', + ) client.httpclient.HTTPClient.assert_called_with( 'http://2.2.2.2', - mock.ANY, + 'fake_token', 'python-manilaclient', insecure=False, cacert=None, @@ -134,9 +187,29 @@ def test_regions_with_same_name(self): timeout=None, retries=None, http_log_debug=False, - api_version=manilaclient.API_MIN_VERSION) + api_version=manilaclient.API_MIN_VERSION, + ) self.assertIsNotNone(c.client) + def test_client_respects_region_name(self): + mock_session = mock.Mock() + mock_auth = mock.Mock() + region = 'region1' + mock_session.get_endpoint.return_value = 'http://fake-endpoint/' + client.Client( + session=mock_session, + auth=mock_auth, + service_type='sharev2', + endpoint_type='public', + region_name=region, + ) + mock_session.get_endpoint.assert_called_once_with( + mock_auth, + service_type='sharev2', + interface='public', + region_name=region, + ) + def _get_client_args(self, **kwargs): client_args = { 'auth_url': 'http://identity.example.com', @@ -160,12 +233,17 @@ def _get_client_args(self, **kwargs): return client_args @ddt.data( - {'auth_url': 'http://identity.example.com', - 'password': 'password_backward_compat', - 'endpoint_type': 'publicURL', - 'project_id': 'foo_tenant_project_id'}, - {'password': 'renamed_api_key', 'endpoint_type': 'public', - 'tenant_id': 'foo_tenant_project_id'}, + { + 'auth_url': 'http://identity.example.com', + 'password': 'password_backward_compat', + 'endpoint_type': 'publicURL', + 'project_id': 'foo_tenant_project_id', + }, + { + 'password': 'renamed_api_key', + 'endpoint_type': 'public', + 'tenant_id': 'foo_tenant_project_id', + }, ) def test_client_init_no_session_no_auth_token(self, kwargs): def fake_url_for(version): @@ -175,82 +253,96 @@ def fake_url_for(version): return None self.mock_object(client.httpclient, 'HTTPClient') - self.mock_object(client.ks_client, 'Client') + self.mock_object(client.identity.v3, 'Password') + self.mock_object(client.adapter, 'LegacyJsonAdapter') self.mock_object(client.session.discover, 'Discover') self.mock_object(client.session, 'Session') client_args = self._get_client_args(**kwargs) client_args['api_version'] = manilaclient.API_MIN_VERSION self.auth_url = client_args['auth_url'] - catalog = { - 'share': [ - {'region': 'SecondRegion', 'region_id': 'SecondRegion', - 'url': 'http://4.4.4.4', 'interface': 'public', - }, - ], - 'sharev2': [ - {'region': 'FirstRegion', 'interface': 'public', - 'region_id': 'SecondRegion', 'url': 'http://1.1.1.1'}, - {'region': 'secondregion', 'interface': 'public', - 'region_id': 'SecondRegion', 'url': 'http://2.2.2.2'}, - {'region': 'SecondRegion', 'interface': 'internal', - 'region_id': 'SecondRegion', 'url': 'http://3.3.3.1'}, - {'region': 'SecondRegion', 'interface': 'public', - 'region_id': 'SecondRegion', 'url': 'http://3.3.3.3'}, - {'region': 'SecondRegion', 'interface': 'admin', - 'region_id': 'SecondRegion', 'url': 'http://3.3.3.2'}, - ], - } + client.session.discover.Discover.return_value.url_for.side_effect = ( - fake_url_for) - client.ks_client.Client.return_value.auth_token.return_value = ( - 'fake_token') - mocked_ks_client = client.ks_client.Client.return_value - mocked_ks_client.service_catalog.get_endpoints.return_value = catalog + fake_url_for + ) + + # Mock the adapter to return token and endpoint + mocked_adapter = client.adapter.LegacyJsonAdapter.return_value + mocked_adapter.session.get_token.return_value = 'fake_token' + mocked_adapter.session.get_endpoint.return_value = 'http://3.3.3.3' + mocked_adapter.auth = client.identity.v3.Password.return_value client.Client(**client_args) client.httpclient.HTTPClient.assert_called_with( - 'http://3.3.3.3', mock.ANY, 'python-manilaclient', insecure=False, - cacert=None, cert=client_args['cert'], timeout=None, retries=None, - http_log_debug=False, api_version=manilaclient.API_MIN_VERSION) + 'http://3.3.3.3', + 'fake_token', + 'python-manilaclient', + insecure=False, + cacert=None, + cert=client_args['cert'], + timeout=None, + retries=None, + http_log_debug=False, + api_version=manilaclient.API_MIN_VERSION, + ) - client.ks_client.Client.assert_called_with( - session=mock.ANY, version=(3, 0), auth_url='url_v3.0', + # Verify identity.v3.Password was called with correct credentials + client.identity.v3.Password.assert_called_with( + auth_url='url_v3.0', username=client_args['username'], password=client_args.get('password'), user_id=client_args['user_id'], user_domain_name=client_args['user_domain_name'], user_domain_id=client_args['user_domain_id'], - project_id=client_args.get('tenant_id', - client_args.get('project_id')), + project_id=client_args.get( + 'tenant_id', client_args.get('project_id') + ), project_name=client_args['project_name'], project_domain_name=client_args['project_domain_name'], project_domain_id=client_args['project_domain_id'], + ) + + # Verify LegacyJsonAdapter was created + client.adapter.LegacyJsonAdapter.assert_called_with( + session=mock.ANY, + auth=mock.ANY, + interface=client_args['endpoint_type'], + service_type=client_args['service_type'], + service_name=None, + region_name=client_args['region_name'], + ) + + # Verify session.get_token() was called + mocked_adapter.session.get_token.assert_called_with(mock.ANY) + + # Verify session.get_endpoint() was called + mocked_adapter.session.get_endpoint.assert_called_with( + mock.ANY, + interface=client_args['endpoint_type'], + service_type=client_args['service_type'], region_name=client_args['region_name'], ) - mocked_ks_client.service_catalog.get_endpoints.assert_called_with( - client_args['service_type']) - mocked_ks_client.authenticate.assert_called_with() - @mock.patch.object(client.ks_client, 'Client', mock.Mock()) @mock.patch.object(client.session.discover, 'Discover', mock.Mock()) @mock.patch.object(client.session, 'Session', mock.Mock()) def test_client_init_no_session_no_auth_token_endpoint_not_found(self): self.mock_object(client.httpclient, 'HTTPClient') + self.mock_object(client.identity.v3, 'Password') + self.mock_object(client.adapter, 'LegacyJsonAdapter') client_args = self._get_client_args( auth_urli='fake_url', password='foo_password', - tenant_id='foo_tenant_id') + tenant_id='foo_tenant_id', + ) discover = client.session.discover.Discover discover.return_value.url_for.return_value = None - mocked_ks_client = client.ks_client.Client.return_value self.assertRaises( - exceptions.CommandError, client.Client, **client_args) + exceptions.CommandError, client.Client, **client_args + ) self.assertTrue(client.session.Session.called) self.assertTrue(client.session.discover.Discover.called) self.assertFalse(client.httpclient.HTTPClient.called) - self.assertFalse(client.ks_client.Client.called) - self.assertFalse(mocked_ks_client.service_catalog.get_endpoints.called) - self.assertFalse(mocked_ks_client.authenticate.called) + self.assertFalse(client.identity.v3.Password.called) + self.assertFalse(client.adapter.LegacyJsonAdapter.called) diff --git a/manilaclient/tests/unit/v2/test_limits.py b/manilaclient/tests/unit/v2/test_limits.py index 6e38aa40..17836b94 100644 --- a/manilaclient/tests/unit/v2/test_limits.py +++ b/manilaclient/tests/unit/v2/test_limits.py @@ -21,59 +21,72 @@ from manilaclient.v2 import limits -def _get_default_RateLimit(verb="verb1", uri="uri1", regex="regex1", - value="value1", - remain="remain1", unit="unit1", - next_available="next1"): - return limits.RateLimit(verb, uri, regex, value, remain, unit, - next_available) +def _get_default_RateLimit( + verb="verb1", + uri="uri1", + regex="regex1", + value="value1", + remain="remain1", + unit="unit1", + next_available="next1", +): + return limits.RateLimit( + verb, uri, regex, value, remain, unit, next_available + ) class TestLimits(utils.TestCase): - def test_repr(self): li = limits.Limits(None, {"foo": "bar"}) self.assertEqual("", repr(li)) def test_absolute(self): - li = limits.Limits(None, - {"absolute": {"name1": "value1", - "name2": "value2"}}) + li = limits.Limits( + None, {"absolute": {"name1": "value1", "name2": "value2"}} + ) l1 = limits.AbsoluteLimit("name1", "value1") l2 = limits.AbsoluteLimit("name2", "value2") for item in li.absolute: self.assertIn(item, [l1, l2]) def test_rate(self): - limit_param = { - "rate": [{ - "uri": "uri1", - "regex": "regex1", - "limit": [{ - "verb": "verb1", - "value": "value1", - "remaining": "remain1", - "unit": "unit1", - "next-available": "next1" - }] - }, { - "uri": "uri2", - "regex": "regex2", - "limit": [{ - "verb": "verb2", - "value": "value2", - "remaining": "remain2", - "unit": "unit2", - "next-available": "next2" - }] - }] + "rate": [ + { + "uri": "uri1", + "regex": "regex1", + "limit": [ + { + "verb": "verb1", + "value": "value1", + "remaining": "remain1", + "unit": "unit1", + "next-available": "next1", + } + ], + }, + { + "uri": "uri2", + "regex": "regex2", + "limit": [ + { + "verb": "verb2", + "value": "value2", + "remaining": "remain2", + "unit": "unit2", + "next-available": "next2", + } + ], + }, + ] } li = limits.Limits(None, limit_param) - l1 = limits.RateLimit("verb1", "uri1", "regex1", "value1", "remain1", - "unit1", "next1") - l2 = limits.RateLimit("verb2", "uri2", "regex2", "value2", "remain2", - "unit2", "next2") + l1 = limits.RateLimit( + "verb1", "uri1", "regex1", "value1", "remain1", "unit1", "next1" + ) + l2 = limits.RateLimit( + "verb2", "uri2", "regex2", "value2", "remain2", "unit2", "next2" + ) for item in li.rate: self.assertIn(item, [l1, l2]) @@ -151,8 +164,19 @@ def test_get(self): api = mock.Mock() api.client.get.return_value = ( None, - {"limits": {"absolute": {"name1": "value1", }}, - "no-limits": {"absolute": {"name2": "value2", }}}) + { + "limits": { + "absolute": { + "name1": "value1", + } + }, + "no-limits": { + "absolute": { + "name2": "value2", + } + }, + }, + ) l1 = limits.AbsoluteLimit("name1", "value1") limitsManager = limits.LimitsManager(api) diff --git a/manilaclient/tests/unit/v2/test_messages.py b/manilaclient/tests/unit/v2/test_messages.py index 77a3a24a..f4a3cb95 100644 --- a/manilaclient/tests/unit/v2/test_messages.py +++ b/manilaclient/tests/unit/v2/test_messages.py @@ -23,12 +23,10 @@ class MessageTest(utils.TestCase): - def setUp(self): - super(MessageTest, self).setUp() + super().setUp() self.manager = messages.MessageManager(fake.FakeClient()) - self.message = messages.Message( - self.manager, {'id': 'fake_id'}) + self.message = messages.Message(self.manager, {'id': 'fake_id'}) self.fake_kwargs = {'key': 'value'} def test_repr(self): @@ -46,69 +44,86 @@ def test_delete(self): @ddt.ddt class MessageManagerTest(utils.TestCase): - def setUp(self): - super(MessageManagerTest, self).setUp() + super().setUp() self.manager = messages.MessageManager(fake.FakeClient()) def test_get(self): fake_message = fake.Message() mock_get = self.mock_object( - self.manager, '_get', mock.Mock(return_value=fake_message)) + self.manager, '_get', mock.Mock(return_value=fake_message) + ) result = self.manager.get(fake.Message.id) self.assertIs(fake_message, result) mock_get.assert_called_once_with( - messages.RESOURCE_PATH % fake.Message.id, - messages.RESOURCE_NAME) + messages.RESOURCE_PATH % fake.Message.id, messages.RESOURCE_NAME + ) def test_list(self): fake_message = fake.Message() mock_list = self.mock_object( - self.manager, '_list', mock.Mock(return_value=[fake_message])) + self.manager, '_list', mock.Mock(return_value=[fake_message]) + ) result = self.manager.list() self.assertEqual([fake_message], result) mock_list.assert_called_once_with( - messages.RESOURCES_PATH, - messages.RESOURCES_NAME) + messages.RESOURCES_PATH, messages.RESOURCES_NAME + ) @ddt.data( - ({'action_id': 1, 'resource_type': 'share'}, - '?action_id=1&resource_type=share'), + ( + {'action_id': 1, 'resource_type': 'share'}, + '?action_id=1&resource_type=share', + ), ({'action_id': 1}, '?action_id=1'), ) @ddt.unpack def test_list_with_filters(self, filters, filters_path): fake_message = fake.Message() mock_list = self.mock_object( - self.manager, '_list', mock.Mock(return_value=[fake_message])) + self.manager, '_list', mock.Mock(return_value=[fake_message]) + ) result = self.manager.list(search_opts=filters) self.assertEqual([fake_message], result) - expected_path = (messages.RESOURCES_PATH + filters_path) + expected_path = messages.RESOURCES_PATH + filters_path mock_list.assert_called_once_with( - expected_path, messages.RESOURCES_NAME) + expected_path, messages.RESOURCES_NAME + ) - @ddt.data('id', 'project_id', 'request_id', 'resource_type', 'action_id', - 'detail_id', 'resource_id', 'message_level', 'expires_at', - 'request_id', 'created_at') + @ddt.data( + 'id', + 'project_id', + 'request_id', + 'resource_type', + 'action_id', + 'detail_id', + 'resource_id', + 'message_level', + 'expires_at', + 'request_id', + 'created_at', + ) def test_list_with_sorting(self, key): fake_message = fake.Message() mock_list = self.mock_object( - self.manager, '_list', mock.Mock(return_value=[fake_message])) + self.manager, '_list', mock.Mock(return_value=[fake_message]) + ) result = self.manager.list(sort_dir='asc', sort_key=key) self.assertEqual([fake_message], result) expected_path = ( - messages.RESOURCES_PATH + '?sort_dir=asc&sort_key=' + - key) + messages.RESOURCES_PATH + '?sort_dir=asc&sort_key=' + key + ) mock_list.assert_called_once_with( - expected_path, messages.RESOURCES_NAME) + expected_path, messages.RESOURCES_NAME + ) @ddt.data( ('name', 'invalid'), @@ -117,8 +132,8 @@ def test_list_with_sorting(self, key): @ddt.unpack def test_list_with_invalid_sorting(self, sort_key, sort_dir): self.assertRaises( - ValueError, - self.manager.list, sort_dir=sort_dir, sort_key=sort_key) + ValueError, self.manager.list, sort_dir=sort_dir, sort_key=sort_key + ) def test_delete(self): mock_delete = self.mock_object(self.manager, '_delete') @@ -127,5 +142,6 @@ def test_delete(self): self.manager.delete(fake.Message()) mock_delete.assert_called_once_with( - messages.RESOURCE_PATH % fake.Message.id) + messages.RESOURCE_PATH % fake.Message.id + ) self.assertFalse(mock_post.called) diff --git a/manilaclient/tests/unit/v2/test_qos_types.py b/manilaclient/tests/unit/v2/test_qos_types.py new file mode 100644 index 00000000..624b3660 --- /dev/null +++ b/manilaclient/tests/unit/v2/test_qos_types.py @@ -0,0 +1,180 @@ +# Copyright (c) 2025 Cloudification GmbH. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import copy +from unittest import mock + +import ddt + +from manilaclient import api_versions +from manilaclient.common import constants +from manilaclient import config +from manilaclient.tests.unit import utils +from manilaclient.tests.unit.v2 import fakes +from manilaclient.v2 import qos_types + +cs = fakes.FakeClient(api_versions.APIVersion(constants.QOS_TYPE_VERSION)) + +CONF = config.CONF + +LATEST_MICROVERSION = CONF.max_api_microversion + + +@ddt.ddt +class QosTypesTest(utils.TestCase): + def setUp(self): + super().setUp() + microversion = api_versions.APIVersion(constants.QOS_TYPE_VERSION) + mock_microversion = mock.Mock(api_version=microversion) + self.manager = qos_types.QosTypeManager(api=mock_microversion) + + @ddt.data( + {'expected_iops': '100'}, + {'peak_iops': '500', 'expected_iops': '100'}, + ) + def test_init(self, specs): + info = {'specs': specs} + + qos_type = qos_types.QosType(qos_types.QosTypeManager, info) + + self.assertTrue(hasattr(qos_type, '_specs')) + self.assertIsInstance(qos_type._specs, dict) + + def test_list_types(self): + tl = cs.qos_types.list() + cs.assert_called('GET', '/qos-types') + for t in tl: + t.api_version = api_versions.APIVersion(constants.QOS_TYPE_VERSION) + self.assertIsInstance(t, qos_types.QosType) + self.assertTrue(callable(getattr(t, 'get_keys', ''))) + self.assertEqual({'test1': 'test1'}, t.get_keys()) + + @ddt.data( + {'qos_type': 'fixed', 'max_iops': '100'}, + {'qos_type': 'adaptive', 'peak_iops': '200'}, + {'qos_type': 'fixed', 'max_iops': '100', 'expected_iops': '100'}, + ) + def test_create(self, specs): + specs = copy.copy(specs) + + self.mock_object( + self.manager, '_create', mock.Mock(return_value="fake") + ) + + result = self.manager.create( + 'test-qos-type-1', + specs=specs, + ) + + if specs is None: + specs = {} + + expected_specs = dict(specs) + + expected_body = { + "qos_type": { + "name": 'test-qos-type-1', + "specs": expected_specs, + } + } + + self.manager._create.assert_called_once_with( + "/qos-types", expected_body, "qos_type" + ) + self.assertEqual("fake", result) + + def test_set_key(self): + t = cs.qos_types.get(1) + t.api_version = api_versions.APIVersion(constants.QOS_TYPE_VERSION) + t.set_keys({'k': 'v'}) + cs.assert_called('POST', '/qos-types/1/specs', {'specs': {'k': 'v'}}) + + def test_unset_keys(self): + t = cs.qos_types.get(1) + t.api_version = api_versions.APIVersion(constants.QOS_TYPE_VERSION) + t.unset_keys(['k']) + cs.assert_called('DELETE', '/qos-types/1/specs/k') + + def test_update(self): + self.mock_object( + self.manager, '_update', mock.Mock(return_value="fake") + ) + qos_type = 1234 + body = dict(description="updated test description") + expected_body = { + "qos_type": dict(description="updated test description") + } + result = self.manager.update(qos_type, **body) + self.manager._update.assert_called_once_with( + f"/qos-types/{qos_type}", expected_body, "qos_type" + ) + self.assertEqual("fake", result) + + def test_delete(self): + cs.qos_types.delete(1) + cs.assert_called('DELETE', '/qos-types/1') + + def test_get_keys_from_resource_data(self): + version = api_versions.APIVersion(constants.QOS_TYPE_VERSION) + manager = mock.Mock() + manager.api = mock.Mock() + manager.api.client = mock.Mock(return_value=None) + manager.api.client.get = mock.Mock(return_value=(200, {})) + + valid_specs = {'test': 'test'} + qos_type = qos_types.QosType( + manager, + {'specs': valid_specs, 'name': 'test'}, + loaded=True, + ) + qos_type.api_version = version + + actual_result = qos_type.get_keys() + + self.assertEqual(actual_result, valid_specs) + self.assertEqual(manager.api.client.get.call_count, 0) + + @ddt.data( + {'prefer_resource_data': True, 'resource_specs': {}}, + { + 'prefer_resource_data': False, + 'resource_specs': {'fake': 'fake'}, + }, + {'prefer_resource_data': False, 'resource_specs': {}}, + ) + @ddt.unpack + def test_get_keys_from_api(self, prefer_resource_data, resource_specs): + version = api_versions.APIVersion(constants.QOS_TYPE_VERSION) + manager = mock.Mock() + manager.api = mock.Mock() + manager.api.client = mock.Mock(return_value=None) + + valid_specs = {'test': 'test'} + manager.api.client.get = mock.Mock( + return_value=(200, {'specs': valid_specs}) + ) + + info = { + 'name': 'test', + 'uuid': 'fake', + 'specs': resource_specs, + } + qos_type = qos_types.QosType(manager, info, loaded=True) + qos_type.api_version = version + + actual_result = qos_type.get_keys(prefer_resource_data) + + self.assertEqual(actual_result, valid_specs) + self.assertEqual(manager.api.client.get.call_count, 1) diff --git a/manilaclient/tests/unit/v2/test_quota_classes.py b/manilaclient/tests/unit/v2/test_quota_classes.py index 6fdff517..282c9c22 100644 --- a/manilaclient/tests/unit/v2/test_quota_classes.py +++ b/manilaclient/tests/unit/v2/test_quota_classes.py @@ -24,15 +24,15 @@ @ddt.ddt class QuotaClassSetsTest(utils.TestCase): - def _get_manager(self, microversion): version = api_versions.APIVersion(microversion) mock_microversion = mock.Mock(api_version=version) return quota_classes.QuotaClassSetManager(api=mock_microversion) def _get_resource_path(self, microversion): - if (api_versions.APIVersion(microversion) > - api_versions.APIVersion("2.6")): + if api_versions.APIVersion(microversion) > api_versions.APIVersion( + "2.6" + ): return quota_classes.RESOURCE_PATH return quota_classes.RESOURCE_PATH_LEGACY @@ -41,20 +41,22 @@ def test_class_quotas_get(self, microversion): class_name = 'test' manager = self._get_manager(microversion) resource_path = self._get_resource_path(microversion) - expected_url = "%s/test" % resource_path - with mock.patch.object(manager, '_get', - mock.Mock(return_value='fake_get')): + expected_url = f"{resource_path}/test" + with mock.patch.object( + manager, '_get', mock.Mock(return_value='fake_get') + ): manager.get(class_name) manager._get.assert_called_once_with( - expected_url, "quota_class_set") + expected_url, "quota_class_set" + ) @ddt.data("2.6", "2.7") def test_update_quota(self, microversion): class_name = 'test' manager = self._get_manager(microversion) resource_path = self._get_resource_path(microversion) - expected_url = "%s/test" % resource_path + expected_url = f"{resource_path}/test" expected_body = { 'quota_class_set': { 'class_name': class_name, @@ -65,11 +67,18 @@ def test_update_quota(self, microversion): 'share_networks': 5, }, } - with mock.patch.object(manager, '_update', - mock.Mock(return_value='fake_update')): + with mock.patch.object( + manager, '_update', mock.Mock(return_value='fake_update') + ): manager.update( - class_name, shares=1, snapshots=2, gigabytes=3, - snapshot_gigabytes=4, share_networks=5) + class_name, + shares=1, + snapshots=2, + gigabytes=3, + snapshot_gigabytes=4, + share_networks=5, + ) manager._update.assert_called_once_with( - expected_url, expected_body) + expected_url, expected_body + ) diff --git a/manilaclient/tests/unit/v2/test_quotas.py b/manilaclient/tests/unit/v2/test_quotas.py index 754362df..365b4970 100644 --- a/manilaclient/tests/unit/v2/test_quotas.py +++ b/manilaclient/tests/unit/v2/test_quotas.py @@ -26,15 +26,15 @@ @ddt.ddt class QuotaSetsTest(utils.TestCase): - def _get_manager(self, microversion): version = api_versions.APIVersion(microversion) mock_microversion = mock.Mock(api_version=version) return quotas.QuotaSetManager(api=mock_microversion) def _get_resource_path(self, microversion): - if (api_versions.APIVersion(microversion) > - api_versions.APIVersion("2.6")): + if api_versions.APIVersion(microversion) > api_versions.APIVersion( + "2.6" + ): return quotas.RESOURCE_PATH return quotas.RESOURCE_PATH_LEGACY @@ -45,13 +45,13 @@ def test_tenant_quotas_get(self, microversion): resource_path = self._get_resource_path(microversion) version = api_versions.APIVersion(microversion) if version >= api_versions.APIVersion('2.25'): - expected_url = "%s/test/detail" % resource_path + expected_url = f"{resource_path}/test/detail" else: - expected_url = ("%s/test" - % resource_path) + expected_url = f"{resource_path}/test" - with mock.patch.object(manager, '_get', - mock.Mock(return_value='fake_get')): + with mock.patch.object( + manager, '_get', mock.Mock(return_value='fake_get') + ): manager.get(tenant_id, detail=True) manager._get.assert_called_once_with(expected_url, "quota_set") @@ -64,14 +64,13 @@ def test_user_quotas_get(self, microversion): resource_path = self._get_resource_path(microversion) version = api_versions.APIVersion(microversion) if version >= api_versions.APIVersion('2.25'): - expected_url = ("%s/test/detail?user_id=fake_user" - % resource_path) + expected_url = f"{resource_path}/test/detail?user_id=fake_user" else: - expected_url = ("%s/test?user_id=fake_user" - % resource_path) + expected_url = f"{resource_path}/test?user_id=fake_user" - with mock.patch.object(manager, '_get', - mock.Mock(return_value='fake_get')): + with mock.patch.object( + manager, '_get', mock.Mock(return_value='fake_get') + ): manager.get(tenant_id, user_id=user_id, detail=True) manager._get.assert_called_once_with(expected_url, "quota_set") @@ -81,11 +80,13 @@ def test_share_type_quotas_get(self): share_type = 'fake_share_type' manager = self._get_manager('2.39') resource_path = self._get_resource_path('2.39') - expected_url = ("%s/%s/detail?share_type=%s" - % (resource_path, tenant_id, share_type)) + expected_url = ( + f"{resource_path}/{tenant_id}/detail?share_type={share_type}" + ) - with mock.patch.object(manager, '_get', - mock.Mock(return_value='fake_get')): + with mock.patch.object( + manager, '_get', mock.Mock(return_value='fake_get') + ): manager.get(tenant_id, share_type=share_type, detail=True) manager._get.assert_called_once_with(expected_url, "quota_set") @@ -95,27 +96,32 @@ def test_tenant_quotas_defaults(self, microversion): tenant_id = 'test' manager = self._get_manager(microversion) resource_path = self._get_resource_path(microversion) - expected_url = "%s/test/defaults" % resource_path - with mock.patch.object(manager, '_get', - mock.Mock(return_value='fake_get')): + expected_url = f"{resource_path}/test/defaults" + with mock.patch.object( + manager, '_get', mock.Mock(return_value='fake_get') + ): manager.defaults(tenant_id) manager._get.assert_called_once_with(expected_url, "quota_set") @ddt.data( - ("2.6", {}), ("2.6", {"force": True}), - ("2.7", {}), ("2.7", {"force": True}), - ("2.38", {}), ("2.38", {"force": True}), - ("2.39", {}), ("2.39", {"force": True}), - ("2.53", {}), ("2.53", {"force": True, "share_replicas": 8, - "replica_gigabytes": 9}), + ("2.6", {}), + ("2.6", {"force": True}), + ("2.7", {}), + ("2.7", {"force": True}), + ("2.38", {}), + ("2.38", {"force": True}), + ("2.39", {}), + ("2.39", {"force": True}), + ("2.53", {}), + ("2.53", {"force": True, "share_replicas": 8, "replica_gigabytes": 9}), ) @ddt.unpack def test_update_quota(self, microversion, extra_data): tenant_id = 'test' manager = self._get_manager(microversion) resource_path = self._get_resource_path(microversion) - expected_url = "%s/test" % resource_path + expected_url = f"{resource_path}/test" expected_body = { 'quota_set': { 'tenant_id': tenant_id, @@ -127,23 +133,32 @@ def test_update_quota(self, microversion, extra_data): }, } expected_body['quota_set'].update(extra_data) - with mock.patch.object(manager, '_update', - mock.Mock(return_value='fake_update')): + with mock.patch.object( + manager, '_update', mock.Mock(return_value='fake_update') + ): manager.update( - tenant_id, shares=1, snapshots=2, gigabytes=3, - snapshot_gigabytes=4, share_networks=5, **extra_data) + tenant_id, + shares=1, + snapshots=2, + gigabytes=3, + snapshot_gigabytes=4, + share_networks=5, + **extra_data, + ) manager._update.assert_called_once_with( - expected_url, expected_body, "quota_set") + expected_url, expected_body, "quota_set" + ) - @ddt.data("2.6", "2.7", "2.38", "2.39", "2.40", - REPLICA_QUOTAS_MICROVERSION) + @ddt.data( + "2.6", "2.7", "2.38", "2.39", "2.40", REPLICA_QUOTAS_MICROVERSION + ) def test_update_user_quota(self, microversion): tenant_id = 'test' user_id = 'fake_user' manager = self._get_manager(microversion) resource_path = self._get_resource_path(microversion) - expected_url = "%s/test?user_id=fake_user" % resource_path + expected_url = f"{resource_path}/test?user_id=fake_user" expected_body = { 'quota_set': { 'tenant_id': tenant_id, @@ -159,38 +174,47 @@ def test_update_user_quota(self, microversion): 'snapshots': expected_body['quota_set']['snapshots'], 'gigabytes': expected_body['quota_set']['gigabytes'], 'snapshot_gigabytes': expected_body['quota_set'][ - 'snapshot_gigabytes'], + 'snapshot_gigabytes' + ], 'share_networks': expected_body['quota_set']['share_networks'], 'user_id': user_id, } - if (api_versions.APIVersion(microversion) >= - api_versions.APIVersion('2.40')): + if api_versions.APIVersion(microversion) >= api_versions.APIVersion( + '2.40' + ): expected_body['quota_set']['share_groups'] = 6 expected_body['quota_set']['share_group_snapshots'] = 7 - kwargs['share_groups'] = expected_body['quota_set'][ - 'share_groups'] + kwargs['share_groups'] = expected_body['quota_set']['share_groups'] kwargs['share_group_snapshots'] = expected_body['quota_set'][ - 'share_group_snapshots'] - if (api_versions.APIVersion(microversion) >= - api_versions.APIVersion(REPLICA_QUOTAS_MICROVERSION)): + 'share_group_snapshots' + ] + if api_versions.APIVersion(microversion) >= api_versions.APIVersion( + REPLICA_QUOTAS_MICROVERSION + ): expected_body['quota_set']['share_replicas'] = 8 expected_body['quota_set']['replica_gigabytes'] = 9 kwargs['share_replicas'] = expected_body['quota_set'][ - 'share_replicas'] + 'share_replicas' + ] kwargs['replica_gigabytes'] = expected_body['quota_set'][ - 'replica_gigabytes'] - if (api_versions.APIVersion(microversion) >= - api_versions.APIVersion('2.62')): + 'replica_gigabytes' + ] + if api_versions.APIVersion(microversion) >= api_versions.APIVersion( + '2.62' + ): expected_body['quota_set']['per_share_gigabytes'] = 10 kwargs['per_share_gigabytes'] = expected_body['quota_set'][ - 'per_share_gigabytes'] + 'per_share_gigabytes' + ] - with mock.patch.object(manager, '_update', - mock.Mock(return_value='fake_update')): + with mock.patch.object( + manager, '_update', mock.Mock(return_value='fake_update') + ): manager.update(tenant_id, **kwargs) manager._update.assert_called_once_with( - expected_url, expected_body, "quota_set") + expected_url, expected_body, "quota_set" + ) @ddt.data('2.39', REPLICA_QUOTAS_MICROVERSION) def test_update_share_type_quota(self, microversion): @@ -198,8 +222,7 @@ def test_update_share_type_quota(self, microversion): share_type = 'fake_share_type' manager = self._get_manager(microversion) resource_path = self._get_resource_path(microversion) - expected_url = "%s/%s?share_type=%s" % ( - resource_path, tenant_id, share_type) + expected_url = f"{resource_path}/{tenant_id}?share_type={share_type}" expected_body = { 'quota_set': { 'tenant_id': tenant_id, @@ -217,24 +240,34 @@ def test_update_share_type_quota(self, microversion): if microversion >= '2.62': expected_body['quota_set']['per_share_gigabytes'] = 10 kwargs = {'per_share_gigabytes': 10} - with mock.patch.object(manager, '_update', - mock.Mock(return_value='fake_update')): + with mock.patch.object( + manager, '_update', mock.Mock(return_value='fake_update') + ): manager.update( - tenant_id, shares=1, snapshots=2, gigabytes=3, - snapshot_gigabytes=4, share_type=share_type, **kwargs) + tenant_id, + shares=1, + snapshots=2, + gigabytes=3, + snapshot_gigabytes=4, + share_type=share_type, + **kwargs, + ) manager._update.assert_called_once_with( - expected_url, expected_body, "quota_set") + expected_url, expected_body, "quota_set" + ) def test_update_share_type_quotas_for_share_networks(self): manager = self._get_manager("2.39") - with mock.patch.object(manager, '_update', - mock.Mock(return_value='fake_delete')): + with mock.patch.object( + manager, '_update', mock.Mock(return_value='fake_delete') + ): self.assertRaises( ValueError, manager.update, - 'fake_tenant_id', share_type='fake_share_type', + 'fake_tenant_id', + share_type='fake_share_type', share_networks=13, ) @@ -245,9 +278,10 @@ def test_quotas_delete(self, microversion): tenant_id = 'test' manager = self._get_manager(microversion) resource_path = self._get_resource_path(microversion) - expected_url = "%s/test" % resource_path - with mock.patch.object(manager, '_delete', - mock.Mock(return_value='fake_delete')): + expected_url = f"{resource_path}/test" + with mock.patch.object( + manager, '_delete', mock.Mock(return_value='fake_delete') + ): manager.delete(tenant_id) manager._delete.assert_called_once_with(expected_url) @@ -258,9 +292,10 @@ def test_user_quotas_delete(self, microversion): user_id = 'fake_user' manager = self._get_manager(microversion) resource_path = self._get_resource_path(microversion) - expected_url = "%s/test?user_id=fake_user" % resource_path - with mock.patch.object(manager, '_delete', - mock.Mock(return_value='fake_delete')): + expected_url = f"{resource_path}/test?user_id=fake_user" + with mock.patch.object( + manager, '_delete', mock.Mock(return_value='fake_delete') + ): manager.delete(tenant_id, user_id=user_id) manager._delete.assert_called_once_with(expected_url) @@ -270,9 +305,10 @@ def test_share_type_quotas_delete(self): share_type = 'fake_st' manager = self._get_manager("2.39") resource_path = self._get_resource_path("2.39") - expected_url = "%s/test?share_type=fake_st" % resource_path - with mock.patch.object(manager, '_delete', - mock.Mock(return_value='fake_delete')): + expected_url = f"{resource_path}/test?share_type=fake_st" + with mock.patch.object( + manager, '_delete', mock.Mock(return_value='fake_delete') + ): manager.delete(tenant_id, share_type=share_type) manager._delete.assert_called_once_with(expected_url) @@ -281,12 +317,14 @@ def test_share_type_quotas_delete(self): def test_share_type_quotas_using_old_microversion(self, operation): manager = self._get_manager("2.38") - with mock.patch.object(manager, '_%s' % operation, - mock.Mock(return_value='fake_delete')): + with mock.patch.object( + manager, f'_{operation}', mock.Mock(return_value='fake_delete') + ): self.assertRaises( TypeError, getattr(manager, operation), - 'fake_tenant_id', share_type='fake_share_type', + 'fake_tenant_id', + share_type='fake_share_type', ) - getattr(manager, '_%s' % operation).assert_not_called() + getattr(manager, f'_{operation}').assert_not_called() diff --git a/manilaclient/tests/unit/v2/test_scheduler_stats.py b/manilaclient/tests/unit/v2/test_scheduler_stats.py index 59c528a1..afd6a30b 100644 --- a/manilaclient/tests/unit/v2/test_scheduler_stats.py +++ b/manilaclient/tests/unit/v2/test_scheduler_stats.py @@ -20,9 +20,8 @@ class PoolTest(utils.TestCase): - def setUp(self): - super(PoolTest, self).setUp() + super().setUp() self.name = 'fake_host@fake_backend#fake_pool' info = { @@ -34,48 +33,50 @@ def setUp(self): self.resource_class = scheduler_stats.Pool(manager=self, info=info) def test_get_repr_of_share_server(self): - self.assertEqual('' % self.name, repr(self.resource_class)) + self.assertEqual(f'', repr(self.resource_class)) class PoolManagerTest(utils.TestCase): - def setUp(self): - super(PoolManagerTest, self).setUp() + super().setUp() self.manager = scheduler_stats.PoolManager(fakes.FakeClient()) @mock.patch.object(scheduler_stats.PoolManager, '_list', mock.Mock()) def test_list(self): self.manager.list(detailed=False) self.manager._list.assert_called_once_with( - scheduler_stats.RESOURCES_PATH, - scheduler_stats.RESOURCES_NAME) + scheduler_stats.RESOURCES_PATH, scheduler_stats.RESOURCES_NAME + ) @mock.patch.object(scheduler_stats.PoolManager, '_list', mock.Mock()) def test_list_detail(self): self.manager.list() self.manager._list.assert_called_once_with( scheduler_stats.RESOURCES_PATH + '/detail', - scheduler_stats.RESOURCES_NAME) + scheduler_stats.RESOURCES_NAME, + ) @mock.patch.object(scheduler_stats.PoolManager, '_list', mock.Mock()) def test_list_with_one_search_opt(self): host = 'fake_host' - query_string = "?host=%s" % host + query_string = f"?host={host}" self.manager.list(detailed=False, search_opts={'host': host}) self.manager._list.assert_called_once_with( scheduler_stats.RESOURCES_PATH + query_string, - scheduler_stats.RESOURCES_NAME) + scheduler_stats.RESOURCES_NAME, + ) @mock.patch.object(scheduler_stats.PoolManager, '_list', mock.Mock()) def test_list_detail_with_two_search_opts(self): host = 'fake_host' backend = 'fake_backend' - query_string = "?backend=%s&host=%s" % (backend, host) + query_string = f"?backend={backend}&host={host}" self.manager.list(search_opts={'host': host, 'backend': backend}) self.manager._list.assert_called_once_with( scheduler_stats.RESOURCES_PATH + '/detail' + query_string, - scheduler_stats.RESOURCES_NAME) + scheduler_stats.RESOURCES_NAME, + ) diff --git a/manilaclient/tests/unit/v2/test_security_services.py b/manilaclient/tests/unit/v2/test_security_services.py index c780df42..c56ebb73 100644 --- a/manilaclient/tests/unit/v2/test_security_services.py +++ b/manilaclient/tests/unit/v2/test_security_services.py @@ -25,14 +25,14 @@ @ddt.ddt class SecurityServiceTest(utils.TestCase): - - class _FakeSecurityService(object): + class _FakeSecurityService: id = 'fake_security_service_id' def setUp(self): - super(SecurityServiceTest, self).setUp() + super().setUp() self.manager = security_services.SecurityServiceManager( - fakes.FakeClient()) + fakes.FakeClient() + ) def test_create_all_fields(self): values = { @@ -51,14 +51,18 @@ def test_create_all_fields(self): result = self.manager.create(**values) self.assertEqual(result['url'], security_services.RESOURCES_PATH) - self.assertEqual(result['resp_key'], - security_services.RESOURCE_NAME) + self.assertEqual( + result['resp_key'], security_services.RESOURCE_NAME + ) self.assertIn(security_services.RESOURCE_NAME, result['body']) - self.assertEqual(result['body'][security_services.RESOURCE_NAME], - values) + self.assertEqual( + result['body'][security_services.RESOURCE_NAME], values + ) - @ddt.data({'server': 'fake.ad.server'}, - {'default_ad_site': 'fake.ad.default_ad_site'}) + @ddt.data( + {'server': 'fake.ad.server'}, + {'default_ad_site': 'fake.ad.default_ad_site'}, + ) def test_create_all_fields_active_directory(self, option): values = { 'type': 'active_directory', @@ -76,11 +80,13 @@ def test_create_all_fields_active_directory(self, option): result = self.manager.create(**values) self.assertEqual(result['url'], security_services.RESOURCES_PATH) - self.assertEqual(result['resp_key'], - security_services.RESOURCE_NAME) + self.assertEqual( + result['resp_key'], security_services.RESOURCE_NAME + ) self.assertIn(security_services.RESOURCE_NAME, result['body']) - self.assertEqual(result['body'][security_services.RESOURCE_NAME], - values) + self.assertEqual( + result['body'][security_services.RESOURCE_NAME], values + ) def test_create_some_fields(self): values = { @@ -95,25 +101,29 @@ def test_create_some_fields(self): result = self.manager.create(**values) self.assertEqual(result['url'], security_services.RESOURCES_PATH) - self.assertEqual(result['resp_key'], - security_services.RESOURCE_NAME) + self.assertEqual( + result['resp_key'], security_services.RESOURCE_NAME + ) self.assertIn(security_services.RESOURCE_NAME, result['body']) - self.assertEqual(result['body'][security_services.RESOURCE_NAME], - values) + self.assertEqual( + result['body'][security_services.RESOURCE_NAME], values + ) def test_delete(self): security_service = 'fake service' with mock.patch.object(self.manager, '_delete', mock.Mock()): self.manager.delete(security_service) self.manager._delete.assert_called_once_with( - security_services.RESOURCE_PATH % security_service) + security_services.RESOURCE_PATH % security_service + ) def test_delete_by_object(self): security_service = self._FakeSecurityService() with mock.patch.object(self.manager, '_delete', mock.Mock()): self.manager.delete(security_service) self.manager._delete.assert_called_once_with( - security_services.RESOURCE_PATH % security_service.id) + security_services.RESOURCE_PATH % security_service.id + ) def test_get(self): security_service = 'fake service' @@ -121,7 +131,8 @@ def test_get(self): self.manager.get(security_service) self.manager._get.assert_called_once_with( security_services.RESOURCE_PATH % security_service, - security_services.RESOURCE_NAME) + security_services.RESOURCE_NAME, + ) def test_get_by_object(self): security_service = self._FakeSecurityService() @@ -129,41 +140,50 @@ def test_get_by_object(self): self.manager.get(security_service) self.manager._get.assert_called_once_with( security_services.RESOURCE_PATH % security_service.id, - security_services.RESOURCE_NAME) + security_services.RESOURCE_NAME, + ) def test_list_summary(self): - with mock.patch.object(self.manager, '_list', - mock.Mock(return_value=None)): + with mock.patch.object( + self.manager, '_list', mock.Mock(return_value=None) + ): self.manager.list(detailed=False) self.manager._list.assert_called_once_with( security_services.RESOURCES_PATH, - security_services.RESOURCES_NAME) + security_services.RESOURCES_NAME, + ) def test_list_detail(self): - with mock.patch.object(self.manager, '_list', - mock.Mock(return_value=None)): + with mock.patch.object( + self.manager, '_list', mock.Mock(return_value=None) + ): self.manager.list(detailed=True) self.manager._list.assert_called_once_with( security_services.RESOURCES_PATH + '/detail', - security_services.RESOURCES_NAME) + security_services.RESOURCES_NAME, + ) def test_list_no_filters(self): - with mock.patch.object(self.manager, '_list', - mock.Mock(return_value=None)): + with mock.patch.object( + self.manager, '_list', mock.Mock(return_value=None) + ): self.manager.list() self.manager._list.assert_called_once_with( security_services.RESOURCES_PATH + '/detail', - security_services.RESOURCES_NAME) + security_services.RESOURCES_NAME, + ) def test_list_with_filters(self): filters = {'all_tenants': 1, 'network': 'fake', 'status': 'ERROR'} - expected_postfix = ('/detail?all_tenants=1&network=fake&status=ERROR') - with mock.patch.object(self.manager, '_list', - mock.Mock(return_value=None)): + expected_postfix = '/detail?all_tenants=1&network=fake&status=ERROR' + with mock.patch.object( + self.manager, '_list', mock.Mock(return_value=None) + ): self.manager.list(search_opts=filters) self.manager._list.assert_called_once_with( security_services.RESOURCES_PATH + expected_postfix, - security_services.RESOURCES_NAME) + security_services.RESOURCES_NAME, + ) def test_update(self): security_service = 'fake service' @@ -179,13 +199,14 @@ def test_update(self): result = self.manager.update(security_service, **values) self.assertEqual( result['url'], - security_services.RESOURCE_PATH % security_service) + security_services.RESOURCE_PATH % security_service, + ) self.assertEqual( - result['resp_key'], - security_services.RESOURCE_NAME) + result['resp_key'], security_services.RESOURCE_NAME + ) self.assertEqual( - result['body'][security_services.RESOURCE_NAME], - values) + result['body'][security_services.RESOURCE_NAME], values + ) def test_update_by_object(self): security_service = self._FakeSecurityService() @@ -194,16 +215,17 @@ def test_update_by_object(self): result = self.manager.update(security_service, **values) self.assertEqual( result['url'], - security_services.RESOURCE_PATH % security_service.id) + security_services.RESOURCE_PATH % security_service.id, + ) self.assertEqual( - result['resp_key'], - security_services.RESOURCE_NAME) + result['resp_key'], security_services.RESOURCE_NAME + ) self.assertEqual( - result['body'][security_services.RESOURCE_NAME], - values) + result['body'][security_services.RESOURCE_NAME], values + ) def test_update_no_fields_specified(self): security_service = 'fake service' - self.assertRaises(exceptions.CommandError, - self.manager.update, - security_service) + self.assertRaises( + exceptions.CommandError, self.manager.update, security_service + ) diff --git a/manilaclient/tests/unit/v2/test_services.py b/manilaclient/tests/unit/v2/test_services.py index 93518fb0..e01abf08 100644 --- a/manilaclient/tests/unit/v2/test_services.py +++ b/manilaclient/tests/unit/v2/test_services.py @@ -24,15 +24,15 @@ @ddt.ddt class ServicesTest(utils.TestCase): - def _get_manager(self, microversion): version = api_versions.APIVersion(microversion) mock_microversion = mock.Mock(api_version=version) return services.ServiceManager(api=mock_microversion) def _get_resource_path(self, microversion): - if (api_versions.APIVersion(microversion) > - api_versions.APIVersion("2.6")): + if api_versions.APIVersion(microversion) > api_versions.APIVersion( + "2.6" + ): return services.RESOURCE_PATH return services.RESOURCE_PATH_LEGACY @@ -40,20 +40,21 @@ def _get_resource_path(self, microversion): def test_list(self, microversion): manager = self._get_manager(microversion) resource_path = self._get_resource_path(microversion) - with mock.patch.object(manager, '_list', - mock.Mock(return_value='fake')): + with mock.patch.object( + manager, '_list', mock.Mock(return_value='fake') + ): result = manager.list() manager._list.assert_called_once_with( - resource_path, services.RESOURCE_NAME) + resource_path, services.RESOURCE_NAME + ) self.assertEqual("fake", result) def test_list_services_with_one_search_opt(self): manager = self._get_manager("2.7") host = 'fake_host' - query_string = "?host=%s" % host - with mock.patch.object(manager, '_list', - mock.Mock(return_value=None)): + query_string = f"?host={host}" + with mock.patch.object(manager, '_list', mock.Mock(return_value=None)): manager.list({'host': host}) manager._list.assert_called_once_with( services.RESOURCE_PATH + query_string, @@ -64,9 +65,8 @@ def test_list_services_with_two_search_opts(self): manager = self._get_manager("2.7") host = 'fake_host' binary = 'fake_binary' - query_string = "?binary=%s&host=%s" % (binary, host) - with mock.patch.object(manager, '_list', - mock.Mock(return_value=None)): + query_string = f"?binary={binary}&host={host}" + with mock.patch.object(manager, '_list', mock.Mock(return_value=None)): manager.list({'binary': binary, 'host': host}) manager._list.assert_called_once_with( services.RESOURCE_PATH + query_string, diff --git a/manilaclient/tests/unit/v2/test_share_backups.py b/manilaclient/tests/unit/v2/test_share_backups.py index 954bd98b..b2f6bf4a 100644 --- a/manilaclient/tests/unit/v2/test_share_backups.py +++ b/manilaclient/tests/unit/v2/test_share_backups.py @@ -20,52 +20,67 @@ from manilaclient.v2 import share_backups FAKE_BACKUP = 'fake_backup' +FAKE_TARGET_SHARE_ID = 'fake_target_share_id' @ddt.ddt class ShareBackupsTest(utils.TestCase): - - class _FakeShareBackup(object): + class _FakeShareBackup: id = 'fake_share_backup_id' def setUp(self): - super(ShareBackupsTest, self).setUp() - microversion = api_versions.APIVersion("2.80") + super().setUp() + microversion = api_versions.APIVersion("2.91") self.manager = share_backups.ShareBackupManager( - fakes.FakeClient(api_version=microversion)) + fakes.FakeClient(api_version=microversion) + ) def test_delete_str(self): with mock.patch.object(self.manager, '_delete', mock.Mock()): self.manager.delete(FAKE_BACKUP) self.manager._delete.assert_called_once_with( - share_backups.RESOURCE_PATH % FAKE_BACKUP) + share_backups.RESOURCE_PATH % FAKE_BACKUP + ) def test_delete_obj(self): backup = self._FakeShareBackup with mock.patch.object(self.manager, '_delete', mock.Mock()): self.manager.delete(backup) self.manager._delete.assert_called_once_with( - share_backups.RESOURCE_PATH % backup.id) + share_backups.RESOURCE_PATH % backup.id + ) def test_get(self): with mock.patch.object(self.manager, '_get', mock.Mock()): self.manager.get(FAKE_BACKUP) self.manager._get.assert_called_once_with( share_backups.RESOURCE_PATH % FAKE_BACKUP, - share_backups.RESOURCE_NAME) + share_backups.RESOURCE_NAME, + ) def test_restore(self): with mock.patch.object(self.manager, '_action', mock.Mock()): self.manager.restore(FAKE_BACKUP) self.manager._action.assert_called_once_with( - 'restore', FAKE_BACKUP) + 'restore', FAKE_BACKUP, info=None + ) + + def test_restore_to_target(self): + with mock.patch.object(self.manager, '_action', mock.Mock()): + self.manager.restore( + FAKE_BACKUP, target_share_id=FAKE_TARGET_SHARE_ID + ) + self.manager._action.assert_called_once_with( + 'restore', FAKE_BACKUP, info=FAKE_TARGET_SHARE_ID + ) def test_list(self): with mock.patch.object(self.manager, '_list', mock.Mock()): self.manager.list() self.manager._list.assert_called_once_with( share_backups.RESOURCES_PATH + '/detail', - share_backups.RESOURCES_NAME) + share_backups.RESOURCES_NAME, + ) def test_list_with_share(self): with mock.patch.object(self.manager, '_list', mock.Mock()): @@ -73,13 +88,15 @@ def test_list_with_share(self): share_uri = '?share_id=fake_share_id' self.manager._list.assert_called_once_with( (share_backups.RESOURCES_PATH + '/detail' + share_uri), - share_backups.RESOURCES_NAME) + share_backups.RESOURCES_NAME, + ) def test_reset_state(self): with mock.patch.object(self.manager, '_action', mock.Mock()): self.manager.reset_status(FAKE_BACKUP, 'fake_status') self.manager._action.assert_called_once_with( - 'reset_status', FAKE_BACKUP, {'status': 'fake_status'}) + 'reset_status', FAKE_BACKUP, {'status': 'fake_status'} + ) def test_update(self): backup = self._FakeShareBackup @@ -87,5 +104,5 @@ def test_update(self): data = dict(name='backup1') self.manager.update(backup, **data) self.manager._update.assert_called_once_with( - share_backups.RESOURCE_PATH % backup.id, - {'share_backup': data}) + share_backups.RESOURCE_PATH % backup.id, {'share_backup': data} + ) diff --git a/manilaclient/tests/unit/v2/test_share_export_locations.py b/manilaclient/tests/unit/v2/test_share_export_locations.py index aaf8f66b..7ca9a3fd 100644 --- a/manilaclient/tests/unit/v2/test_share_export_locations.py +++ b/manilaclient/tests/unit/v2/test_share_export_locations.py @@ -32,27 +32,22 @@ @ddt.ddt class ShareExportLocationsTest(utils.TestCase): - def _get_manager(self, microversion): version = api_versions.APIVersion(microversion) mock_microversion = mock.Mock(api_version=version) - return ( - share_export_locations.ShareExportLocationManager( - api=mock_microversion) + return share_export_locations.ShareExportLocationManager( + api=mock_microversion ) def test_list_of_export_locations(self): share_id = '1234' cs.share_export_locations.list(share_id, search_opts=None) - cs.assert_called( - 'GET', '/shares/%s/export_locations' % share_id) + cs.assert_called('GET', f'/shares/{share_id}/export_locations') def test_get_single_export_location(self): share_id = '1234' el_uuid = 'fake_el_uuid' cs.share_export_locations.get(share_id, el_uuid) cs.assert_called( - 'GET', - ('/shares/%(share_id)s/export_locations/' - '%(el_uuid)s') % { - 'share_id': share_id, 'el_uuid': el_uuid}) + 'GET', (f'/shares/{share_id}/export_locations/{el_uuid}') + ) diff --git a/manilaclient/tests/unit/v2/test_share_group_snapshots.py b/manilaclient/tests/unit/v2/test_share_group_snapshots.py index d7c6269d..4629bc46 100644 --- a/manilaclient/tests/unit/v2/test_share_group_snapshots.py +++ b/manilaclient/tests/unit/v2/test_share_group_snapshots.py @@ -25,12 +25,12 @@ class ShareGroupSnapshotTest(utils.TestCase): - def setUp(self): - super(ShareGroupSnapshotTest, self).setUp() + super().setUp() self.manager = snapshots.ShareGroupSnapshotManager(fake.FakeClient()) self.share_group_snapshot = snapshots.ShareGroupSnapshot( - self.manager, {'id': 'fake_id'}) + self.manager, {'id': 'fake_id'} + ) self.fake_kwargs = {'key': 'value'} def test_repr(self): @@ -44,7 +44,8 @@ def test_update(self): self.share_group_snapshot.update(**self.fake_kwargs) mock_manager_update.assert_called_once_with( - self.share_group_snapshot, **self.fake_kwargs) + self.share_group_snapshot, **self.fake_kwargs + ) def test_delete(self): mock_manager_delete = self.mock_object(self.manager, 'delete') @@ -55,26 +56,29 @@ def test_delete(self): def test_reset_state(self): mock_manager_reset_state = self.mock_object( - self.manager, 'reset_state') + self.manager, 'reset_state' + ) self.share_group_snapshot.reset_state('fake_state') mock_manager_reset_state.assert_called_once_with( - self.share_group_snapshot, 'fake_state') + self.share_group_snapshot, 'fake_state' + ) @ddt.ddt class ShareGroupSnapshotManagerTest(utils.TestCase): - def setUp(self): - super(ShareGroupSnapshotManagerTest, self).setUp() + super().setUp() self.manager = snapshots.ShareGroupSnapshotManager(fake.FakeClient()) def test_create(self): fake_share_group_snapshot = fake.ShareGroupSnapshot() mock_create = self.mock_object( - self.manager, '_create', - mock.Mock(return_value=fake_share_group_snapshot)) + self.manager, + '_create', + mock.Mock(return_value=fake_share_group_snapshot), + ) create_args = { 'name': fake.ShareGroupSnapshot.name, 'description': fake.ShareGroupSnapshot.description, @@ -91,13 +95,16 @@ def test_create(self): }, } mock_create.assert_called_once_with( - snapshots.RESOURCES_PATH, expected_body, snapshots.RESOURCE_NAME) + snapshots.RESOURCES_PATH, expected_body, snapshots.RESOURCE_NAME + ) def test_create_minimal_args(self): fake_share_group_snapshot = fake.ShareGroupSnapshot() mock_create = self.mock_object( - self.manager, '_create', - mock.Mock(return_value=fake_share_group_snapshot)) + self.manager, + '_create', + mock.Mock(return_value=fake_share_group_snapshot), + ) result = self.manager.create(fake.ShareGroupSnapshot) @@ -108,99 +115,125 @@ def test_create_minimal_args(self): }, } mock_create.assert_called_once_with( - snapshots.RESOURCES_PATH, expected_body, snapshots.RESOURCE_NAME) + snapshots.RESOURCES_PATH, expected_body, snapshots.RESOURCE_NAME + ) def test_create_using_unsupported_microversion(self): self.manager.api.api_version = manilaclient.API_MIN_VERSION self.assertRaises( exceptions.UnsupportedVersion, - self.manager.create, fake.ShareGroupSnapshot) + self.manager.create, + fake.ShareGroupSnapshot, + ) def test_get(self): fake_share_group_snapshot = fake.ShareGroupSnapshot() mock_get = self.mock_object( - self.manager, '_get', - mock.Mock(return_value=fake_share_group_snapshot)) + self.manager, + '_get', + mock.Mock(return_value=fake_share_group_snapshot), + ) result = self.manager.get(fake.ShareGroupSnapshot.id) self.assertIs(fake_share_group_snapshot, result) mock_get.assert_called_once_with( snapshots.RESOURCE_PATH % fake.ShareGroupSnapshot.id, - snapshots.RESOURCE_NAME) + snapshots.RESOURCE_NAME, + ) def test_list(self): fake_share_group_snapshot = fake.ShareGroupSnapshot() mock_list = self.mock_object( - self.manager, '_list', - mock.Mock(return_value=[fake_share_group_snapshot])) + self.manager, + '_list', + mock.Mock(return_value=[fake_share_group_snapshot]), + ) result = self.manager.list() self.assertEqual([fake_share_group_snapshot], result) mock_list.assert_called_once_with( - snapshots.RESOURCES_PATH + '/detail', - snapshots.RESOURCES_NAME) + snapshots.RESOURCES_PATH + '/detail', snapshots.RESOURCES_NAME + ) def test_list_no_detail(self): fake_share_group_snapshot = fake.ShareGroupSnapshot() mock_list = self.mock_object( - self.manager, '_list', - mock.Mock(return_value=[fake_share_group_snapshot])) + self.manager, + '_list', + mock.Mock(return_value=[fake_share_group_snapshot]), + ) result = self.manager.list(detailed=False) self.assertEqual([fake_share_group_snapshot], result) mock_list.assert_called_once_with( - snapshots.RESOURCES_PATH, snapshots.RESOURCES_NAME) + snapshots.RESOURCES_PATH, snapshots.RESOURCES_NAME + ) def test_list_with_filters(self): fake_share_group_snapshot = fake.ShareGroupSnapshot() mock_list = self.mock_object( - self.manager, '_list', - mock.Mock(return_value=[fake_share_group_snapshot])) + self.manager, + '_list', + mock.Mock(return_value=[fake_share_group_snapshot]), + ) filters = {'all_tenants': 1, 'status': 'ERROR'} result = self.manager.list(detailed=False, search_opts=filters) self.assertEqual([fake_share_group_snapshot], result) - expected_path = (snapshots.RESOURCES_PATH + - '?all_tenants=1&status=ERROR') + expected_path = ( + snapshots.RESOURCES_PATH + '?all_tenants=1&status=ERROR' + ) mock_list.assert_called_once_with( - expected_path, snapshots.RESOURCES_NAME) + expected_path, snapshots.RESOURCES_NAME + ) def test_list_with_sorting(self): fake_share_group_snapshot = fake.ShareGroupSnapshot() mock_list = self.mock_object( - self.manager, '_list', - mock.Mock(return_value=[fake_share_group_snapshot])) + self.manager, + '_list', + mock.Mock(return_value=[fake_share_group_snapshot]), + ) result = self.manager.list( - detailed=False, sort_dir='asc', sort_key='name') + detailed=False, sort_dir='asc', sort_key='name' + ) self.assertEqual([fake_share_group_snapshot], result) expected_path = ( - snapshots.RESOURCES_PATH + '?sort_dir=asc&sort_key=name') + snapshots.RESOURCES_PATH + '?sort_dir=asc&sort_key=name' + ) mock_list.assert_called_once_with( - expected_path, snapshots.RESOURCES_NAME) + expected_path, snapshots.RESOURCES_NAME + ) - @ddt.data({'sort_key': 'name', 'sort_dir': 'invalid'}, - {'sort_key': 'invalid', 'sort_dir': 'asc'}) + @ddt.data( + {'sort_key': 'name', 'sort_dir': 'invalid'}, + {'sort_key': 'invalid', 'sort_dir': 'asc'}, + ) @ddt.unpack def test_list_with_invalid_sorting(self, sort_key, sort_dir): self.assertRaises( - ValueError, - self.manager.list, sort_dir=sort_dir, sort_key=sort_key) + ValueError, self.manager.list, sort_dir=sort_dir, sort_key=sort_key + ) def test_update(self): fake_share_group_snapshot = fake.ShareGroupSnapshot() mock_get = self.mock_object( - self.manager, '_get', - mock.Mock(return_value=fake_share_group_snapshot)) + self.manager, + '_get', + mock.Mock(return_value=fake_share_group_snapshot), + ) mock_update = self.mock_object( - self.manager, '_update', - mock.Mock(return_value=fake_share_group_snapshot)) + self.manager, + '_update', + mock.Mock(return_value=fake_share_group_snapshot), + ) update_args = { 'name': fake.ShareGroupSnapshot.name, 'description': fake.ShareGroupSnapshot.description, @@ -213,16 +246,21 @@ def test_update(self): mock_update.assert_called_once_with( snapshots.RESOURCE_PATH % fake.ShareGroupSnapshot.id, {snapshots.RESOURCE_NAME: update_args}, - snapshots.RESOURCE_NAME) + snapshots.RESOURCE_NAME, + ) def test_update_no_data(self): fake_share_group_snapshot = fake.ShareGroupSnapshot() mock_get = self.mock_object( - self.manager, '_get', - mock.Mock(return_value=fake_share_group_snapshot)) + self.manager, + '_get', + mock.Mock(return_value=fake_share_group_snapshot), + ) mock_update = self.mock_object( - self.manager, '_update', - mock.Mock(return_value=fake_share_group_snapshot)) + self.manager, + '_update', + mock.Mock(return_value=fake_share_group_snapshot), + ) update_args = {} result = self.manager.update(fake.ShareGroupSnapshot(), **update_args) @@ -230,7 +268,8 @@ def test_update_no_data(self): self.assertIs(fake_share_group_snapshot, result) mock_get.assert_called_once_with( snapshots.RESOURCE_PATH % fake.ShareGroupSnapshot.id, - snapshots.RESOURCE_NAME) + snapshots.RESOURCE_NAME, + ) self.assertFalse(mock_update.called) def test_delete(self): @@ -240,7 +279,8 @@ def test_delete(self): self.manager.delete(fake.ShareGroupSnapshot()) mock_delete.assert_called_once_with( - snapshots.RESOURCE_PATH % fake.ShareGroupSnapshot.id) + snapshots.RESOURCE_PATH % fake.ShareGroupSnapshot.id + ) self.assertFalse(mock_post.called) def test_delete_force(self): @@ -252,7 +292,8 @@ def test_delete_force(self): self.assertFalse(mock_delete.called) mock_post.assert_called_once_with( snapshots.RESOURCE_PATH_ACTION % fake.ShareGroupSnapshot.id, - body={'force_delete': None}) + body={'force_delete': None}, + ) def test_reset_state(self): mock_post = self.mock_object(self.manager.api.client, 'post') @@ -261,4 +302,5 @@ def test_reset_state(self): mock_post.assert_called_once_with( snapshots.RESOURCE_PATH_ACTION % fake.ShareGroupSnapshot.id, - body={'reset_status': {'status': 'fake_state'}}) + body={'reset_status': {'status': 'fake_state'}}, + ) diff --git a/manilaclient/tests/unit/v2/test_share_group_type_access.py b/manilaclient/tests/unit/v2/test_share_group_type_access.py index def93a10..64b4faa2 100644 --- a/manilaclient/tests/unit/v2/test_share_group_type_access.py +++ b/manilaclient/tests/unit/v2/test_share_group_type_access.py @@ -26,50 +26,58 @@ @ddt.ddt class ShareGroupTypeAccessTest(utils.TestCase): - def setUp(self): - super(ShareGroupTypeAccessTest, self).setUp() + super().setUp() self.manager = type_access.ShareGroupTypeAccessManager( - fake.FakeClient()) + fake.FakeClient() + ) fake_group_type_access_info = { - 'share_group_type_id': fake.ShareGroupTypeAccess.id} + 'share_group_type_id': fake.ShareGroupTypeAccess.id + } self.share_group_type_access = type_access.ShareGroupTypeAccess( - self.manager, fake_group_type_access_info, loaded=True) + self.manager, fake_group_type_access_info, loaded=True + ) def test_repr(self): result = str(self.share_group_type_access) self.assertEqual( - '' % fake.ShareGroupTypeAccess.id, - result) + f'', + result, + ) @ddt.ddt class ShareGroupTypeAccessManagerTest(utils.TestCase): - def setUp(self): - super(ShareGroupTypeAccessManagerTest, self).setUp() + super().setUp() self.manager = type_access.ShareGroupTypeAccessManager( - fake.FakeClient()) + fake.FakeClient() + ) def test_list(self): fake_share_group_type_access = fake.ShareGroupTypeAccess() mock_list = self.mock_object( - self.manager, '_list', - mock.Mock(return_value=[fake_share_group_type_access])) + self.manager, + '_list', + mock.Mock(return_value=[fake_share_group_type_access]), + ) result = self.manager.list(fake.ShareGroupType(), search_opts=None) self.assertEqual([fake_share_group_type_access], result) mock_list.assert_called_once_with( type_access.RESOURCE_PATH % fake.ShareGroupType.id, - type_access.RESOURCE_NAME) + type_access.RESOURCE_NAME, + ) def test_list_public(self): fake_share_group_type_access = fake.ShareGroupTypeAccess() mock_list = self.mock_object( - self.manager, '_list', - mock.Mock(return_value=[fake_share_group_type_access])) + self.manager, + '_list', + mock.Mock(return_value=[fake_share_group_type_access]), + ) fake_share_group_type = fake.ShareGroupType() fake_share_group_type.is_public = True @@ -84,7 +92,9 @@ def test_list_using_unsupported_microversion(self): self.assertRaises( exceptions.UnsupportedVersion, - self.manager.list, fake_share_group_type_access) + self.manager.list, + fake_share_group_type_access, + ) def test_add_project_access(self): mock_post = self.mock_object(self.manager.api.client, 'post') @@ -98,13 +108,15 @@ def test_add_project_access(self): } mock_post.assert_called_once_with( type_access.RESOURCE_PATH_ACTION % fake.ShareGroupType.id, - body=expected_body) + body=expected_body, + ) def test_remove_project_access(self): mock_post = self.mock_object(self.manager.api.client, 'post') self.manager.remove_project_access( - fake.ShareGroupType(), 'fake_project') + fake.ShareGroupType(), 'fake_project' + ) expected_body = { 'removeProjectAccess': { @@ -113,4 +125,5 @@ def test_remove_project_access(self): } mock_post.assert_called_once_with( type_access.RESOURCE_PATH_ACTION % fake.ShareGroupType.id, - body=expected_body) + body=expected_body, + ) diff --git a/manilaclient/tests/unit/v2/test_share_group_types.py b/manilaclient/tests/unit/v2/test_share_group_types.py index 53b86999..8a3390c2 100644 --- a/manilaclient/tests/unit/v2/test_share_group_types.py +++ b/manilaclient/tests/unit/v2/test_share_group_types.py @@ -26,9 +26,8 @@ @ddt.ddt class ShareGroupTypeTest(utils.TestCase): - def setUp(self): - super(ShareGroupTypeTest, self).setUp() + super().setUp() self.manager = types.ShareGroupTypeManager(fake.FakeClient()) self.fake_group_specs = {'key1': 'value1', 'key2': 'value2'} self.fake_share_group_type_info = { @@ -39,13 +38,15 @@ def setUp(self): 'group_specs': self.fake_group_specs, } self.share_group_type = types.ShareGroupType( - self.manager, self.fake_share_group_type_info, loaded=True) + self.manager, self.fake_share_group_type_info, loaded=True + ) def test_repr(self): result = str(self.share_group_type) self.assertEqual( - '' % fake.ShareGroupType.name, result) + f'', result + ) @ddt.data((True, True), (False, False), (None, 'N/A')) @ddt.unpack @@ -54,7 +55,8 @@ def test_is_public(self, is_public, expected): if is_public is not None: fake_share_group_type_info['is_public'] = is_public share_group_type = types.ShareGroupType( - self.manager, fake_share_group_type_info, loaded=True) + self.manager, fake_share_group_type_info, loaded=True + ) result = share_group_type.is_public @@ -70,21 +72,26 @@ def test_get_keys(self): def test_get_keys_force_api_call(self): share_group_type = types.ShareGroupType( - self.manager, self.fake_share_group_type_info, loaded=True) + self.manager, self.fake_share_group_type_info, loaded=True + ) share_group_type._group_specs = {} - self.manager.api.client.get = mock.Mock(return_value=( - None, self.fake_share_group_type_info)) + self.manager.api.client.get = mock.Mock( + return_value=(None, self.fake_share_group_type_info) + ) result = share_group_type.get_keys(prefer_resource_data=False) self.assertEqual(self.fake_group_specs, result) self.manager.api.client.get.assert_called_once_with( - types.GROUP_SPECS_RESOURCES_PATH % fake.ShareGroupType.id) + types.GROUP_SPECS_RESOURCES_PATH % fake.ShareGroupType.id + ) def test_set_keys(self): mock_manager_create = self.mock_object( - self.manager, '_create', - mock.Mock(return_value=self.fake_group_specs)) + self.manager, + '_create', + mock.Mock(return_value=self.fake_group_specs), + ) result = self.share_group_type.set_keys(self.fake_group_specs) @@ -92,47 +99,62 @@ def test_set_keys(self): expected_body = {'group_specs': self.fake_group_specs} mock_manager_create.assert_called_once_with( types.GROUP_SPECS_RESOURCES_PATH % fake.ShareGroupType.id, - expected_body, types.GROUP_SPECS_RESOURCES_NAME, return_raw=True) + expected_body, + types.GROUP_SPECS_RESOURCES_NAME, + return_raw=True, + ) def test_unset_keys(self): mock_manager_delete = self.mock_object( - self.manager, '_delete', mock.Mock(return_value=None)) + self.manager, '_delete', mock.Mock(return_value=None) + ) result = self.share_group_type.unset_keys(self.fake_group_specs.keys()) self.assertIsNone(result) - mock_manager_delete.assert_has_calls([ - mock.call(types.GROUP_SPECS_RESOURCE_PATH % - (fake.ShareGroupType.id, 'key1')), - mock.call(types.GROUP_SPECS_RESOURCE_PATH % - (fake.ShareGroupType.id, 'key2')), - ], any_order=True) + mock_manager_delete.assert_has_calls( + [ + mock.call( + types.GROUP_SPECS_RESOURCE_PATH + % (fake.ShareGroupType.id, 'key1') + ), + mock.call( + types.GROUP_SPECS_RESOURCE_PATH + % (fake.ShareGroupType.id, 'key2') + ), + ], + any_order=True, + ) def test_unset_keys_error(self): mock_manager_delete = self.mock_object( - self.manager, '_delete', mock.Mock(return_value='error')) + self.manager, '_delete', mock.Mock(return_value='error') + ) result = self.share_group_type.unset_keys( - sorted(self.fake_group_specs.keys())) + sorted(self.fake_group_specs.keys()) + ) self.assertEqual('error', result) mock_manager_delete.assert_called_once_with( - types.GROUP_SPECS_RESOURCE_PATH % (fake.ShareGroupType.id, 'key1')) + types.GROUP_SPECS_RESOURCE_PATH % (fake.ShareGroupType.id, 'key1') + ) @ddt.ddt class ShareGroupTypeManagerTest(utils.TestCase): - def setUp(self): - super(ShareGroupTypeManagerTest, self).setUp() + super().setUp() self.manager = types.ShareGroupTypeManager(fake.FakeClient()) self.fake_group_specs = {'key1': 'value1', 'key2': 'value2'} def test_create(self): fake_share_group_type = fake.ShareGroupType() mock_create = self.mock_object( - self.manager, '_create', - mock.Mock(return_value=fake_share_group_type)) + self.manager, + '_create', + mock.Mock(return_value=fake_share_group_type), + ) create_args = { 'name': fake.ShareGroupType.name, 'share_types': [fake.ShareType()], @@ -152,7 +174,8 @@ def test_create(self): }, } mock_create.assert_called_once_with( - types.RESOURCES_PATH, expected_body, types.RESOURCE_NAME) + types.RESOURCES_PATH, expected_body, types.RESOURCE_NAME + ) def test_create_no_share_type(self): create_args = { @@ -172,38 +195,45 @@ def test_create_using_unsupported_microversion(self): def test_get(self): fake_share_group_type = fake.ShareGroupType() mock_get = self.mock_object( - self.manager, '_get', - mock.Mock(return_value=fake_share_group_type)) + self.manager, '_get', mock.Mock(return_value=fake_share_group_type) + ) result = self.manager.get(fake.ShareGroupType.id) self.assertIs(fake_share_group_type, result) mock_get.assert_called_once_with( - types.RESOURCE_PATH % fake.ShareGroupType.id, types.RESOURCE_NAME) + types.RESOURCE_PATH % fake.ShareGroupType.id, types.RESOURCE_NAME + ) def test_list(self): fake_share_group_type = fake.ShareGroupType() mock_list = self.mock_object( - self.manager, '_list', - mock.Mock(return_value=[fake_share_group_type])) + self.manager, + '_list', + mock.Mock(return_value=[fake_share_group_type]), + ) result = self.manager.list(search_opts=None) self.assertEqual([fake_share_group_type], result) mock_list.assert_called_once_with( - types.RESOURCES_PATH + '?is_public=all', types.RESOURCES_NAME) + types.RESOURCES_PATH + '?is_public=all', types.RESOURCES_NAME + ) def test_list_no_public(self): fake_share_group_type = fake.ShareGroupType() mock_list = self.mock_object( - self.manager, '_list', - mock.Mock(return_value=[fake_share_group_type])) + self.manager, + '_list', + mock.Mock(return_value=[fake_share_group_type]), + ) result = self.manager.list(show_all=False) self.assertEqual([fake_share_group_type], result) mock_list.assert_called_once_with( - types.RESOURCES_PATH, types.RESOURCES_NAME) + types.RESOURCES_PATH, types.RESOURCES_NAME + ) def test_delete(self): mock_delete = self.mock_object(self.manager, '_delete') @@ -211,4 +241,5 @@ def test_delete(self): self.manager.delete(fake.ShareGroupType()) mock_delete.assert_called_once_with( - types.RESOURCE_PATH % fake.ShareGroupType.id) + types.RESOURCE_PATH % fake.ShareGroupType.id + ) diff --git a/manilaclient/tests/unit/v2/test_share_groups.py b/manilaclient/tests/unit/v2/test_share_groups.py index 9601d966..adefad2f 100644 --- a/manilaclient/tests/unit/v2/test_share_groups.py +++ b/manilaclient/tests/unit/v2/test_share_groups.py @@ -26,12 +26,12 @@ @ddt.ddt class ShareGroupTest(utils.TestCase): - def setUp(self): - super(ShareGroupTest, self).setUp() + super().setUp() self.manager = share_groups.ShareGroupManager(fake.FakeClient()) self.share_group = share_groups.ShareGroup( - self.manager, {'id': 'fake_id'}) + self.manager, {'id': 'fake_id'} + ) self.fake_kwargs = {'key': 'value'} def test_repr(self): @@ -45,7 +45,8 @@ def test_update(self): self.share_group.update(**self.fake_kwargs) mock_manager_update.assert_called_once_with( - self.share_group, **self.fake_kwargs) + self.share_group, **self.fake_kwargs + ) def test_delete(self): mock_manager_delete = self.mock_object(self.manager, 'delete') @@ -53,7 +54,8 @@ def test_delete(self): self.share_group.delete() mock_manager_delete.assert_called_once_with( - self.share_group, force=False) + self.share_group, force=False + ) @ddt.data(True, False) def test_delete_force(self, force): @@ -62,29 +64,32 @@ def test_delete_force(self, force): self.share_group.delete(force=force) mock_manager_delete.assert_called_once_with( - self.share_group, force=force) + self.share_group, force=force + ) def test_reset_state(self): mock_manager_reset_state = self.mock_object( - self.manager, 'reset_state') + self.manager, 'reset_state' + ) self.share_group.reset_state('fake_state') mock_manager_reset_state.assert_called_once_with( - self.share_group, 'fake_state') + self.share_group, 'fake_state' + ) @ddt.ddt class ShareGroupManagerTest(utils.TestCase): - def setUp(self): - super(ShareGroupManagerTest, self).setUp() + super().setUp() self.manager = share_groups.ShareGroupManager(fake.FakeClient()) def test_create(self): fake_share_group = fake.ShareGroup() mock_create = self.mock_object( - self.manager, '_create', mock.Mock(return_value=fake_share_group)) + self.manager, '_create', mock.Mock(return_value=fake_share_group) + ) create_args = { 'name': fake.ShareGroup.name, 'description': fake.ShareGroup.description, @@ -110,12 +115,14 @@ def test_create(self): mock_create.assert_called_once_with( share_groups.RESOURCES_PATH, expected_body, - share_groups.RESOURCE_NAME) + share_groups.RESOURCE_NAME, + ) def test_create_default_type(self): fake_share_group = fake.ShareGroup() mock_create = self.mock_object( - self.manager, '_create', mock.Mock(return_value=fake_share_group)) + self.manager, '_create', mock.Mock(return_value=fake_share_group) + ) create_args = { 'name': fake.ShareGroup.name, 'description': fake.ShareGroup.description, @@ -129,12 +136,14 @@ def test_create_default_type(self): mock_create.assert_called_once_with( share_groups.RESOURCES_PATH, expected_body, - share_groups.RESOURCE_NAME) + share_groups.RESOURCE_NAME, + ) def test_create_from_snapshot(self): fake_share_group = fake.ShareGroup() mock_create = self.mock_object( - self.manager, '_create', mock.Mock(return_value=fake_share_group)) + self.manager, '_create', mock.Mock(return_value=fake_share_group) + ) create_args = { 'name': fake.ShareGroup.name, 'description': fake.ShareGroup.description, @@ -156,7 +165,8 @@ def test_create_from_snapshot(self): mock_create.assert_called_once_with( share_groups.RESOURCES_PATH, expected_body, - share_groups.RESOURCE_NAME) + share_groups.RESOURCE_NAME, + ) def test_create_using_unsupported_microversion(self): self.manager.api.api_version = manilaclient.API_MIN_VERSION @@ -176,50 +186,58 @@ def test_create_invalid_arguments(self): def test_get(self): fake_share_group = fake.ShareGroup() mock_get = self.mock_object( - self.manager, '_get', mock.Mock(return_value=fake_share_group)) + self.manager, '_get', mock.Mock(return_value=fake_share_group) + ) result = self.manager.get(fake.ShareGroup.id) self.assertIs(fake_share_group, result) mock_get.assert_called_once_with( share_groups.RESOURCE_PATH % fake.ShareGroup.id, - share_groups.RESOURCE_NAME) + share_groups.RESOURCE_NAME, + ) def test_list(self): fake_share_group = fake.ShareGroup() mock_list = self.mock_object( - self.manager, '_list', mock.Mock(return_value=[fake_share_group])) + self.manager, '_list', mock.Mock(return_value=[fake_share_group]) + ) result = self.manager.list() self.assertEqual([fake_share_group], result) mock_list.assert_called_once_with( share_groups.RESOURCES_PATH + '/detail', - share_groups.RESOURCES_NAME) + share_groups.RESOURCES_NAME, + ) def test_list_no_detail(self): fake_share_group = fake.ShareGroup() mock_list = self.mock_object( - self.manager, '_list', mock.Mock(return_value=[fake_share_group])) + self.manager, '_list', mock.Mock(return_value=[fake_share_group]) + ) result = self.manager.list(detailed=False) self.assertEqual([fake_share_group], result) mock_list.assert_called_once_with( - share_groups.RESOURCES_PATH, share_groups.RESOURCES_NAME) + share_groups.RESOURCES_PATH, share_groups.RESOURCES_NAME + ) def test_list_with_filters(self): fake_share_group = fake.ShareGroup() mock_list = self.mock_object( - self.manager, '_list', mock.Mock(return_value=[fake_share_group])) + self.manager, '_list', mock.Mock(return_value=[fake_share_group]) + ) filters = {'all_tenants': 1} result = self.manager.list(detailed=False, search_opts=filters) self.assertEqual([fake_share_group], result) - expected_path = (share_groups.RESOURCES_PATH + '?all_tenants=1') + expected_path = share_groups.RESOURCES_PATH + '?all_tenants=1' mock_list.assert_called_once_with( - expected_path, share_groups.RESOURCES_NAME) + expected_path, share_groups.RESOURCES_NAME + ) @ddt.data( ('name', 'name'), @@ -230,17 +248,22 @@ def test_list_with_filters(self): def test_list_with_sorting(self, key, expected_key): fake_share_group = fake.ShareGroup() mock_list = self.mock_object( - self.manager, '_list', mock.Mock(return_value=[fake_share_group])) + self.manager, '_list', mock.Mock(return_value=[fake_share_group]) + ) result = self.manager.list( - detailed=False, sort_dir='asc', sort_key=key) + detailed=False, sort_dir='asc', sort_key=key + ) self.assertEqual([fake_share_group], result) expected_path = ( - share_groups.RESOURCES_PATH + '?sort_dir=asc&sort_key=' + - expected_key) + share_groups.RESOURCES_PATH + + '?sort_dir=asc&sort_key=' + + expected_key + ) mock_list.assert_called_once_with( - expected_path, share_groups.RESOURCES_NAME) + expected_path, share_groups.RESOURCES_NAME + ) @ddt.data( ('name', 'invalid'), @@ -249,15 +272,17 @@ def test_list_with_sorting(self, key, expected_key): @ddt.unpack def test_list_with_invalid_sorting(self, sort_key, sort_dir): self.assertRaises( - ValueError, - self.manager.list, sort_dir=sort_dir, sort_key=sort_key) + ValueError, self.manager.list, sort_dir=sort_dir, sort_key=sort_key + ) def test_update(self): fake_share_group = fake.ShareGroup() mock_get = self.mock_object( - self.manager, '_get', mock.Mock(return_value=fake_share_group)) + self.manager, '_get', mock.Mock(return_value=fake_share_group) + ) mock_update = self.mock_object( - self.manager, '_update', mock.Mock(return_value=fake_share_group)) + self.manager, '_update', mock.Mock(return_value=fake_share_group) + ) update_args = { 'name': fake.ShareGroup.name, 'description': fake.ShareGroup.description, @@ -270,14 +295,17 @@ def test_update(self): mock_update.assert_called_once_with( share_groups.RESOURCE_PATH % fake.ShareGroup.id, {share_groups.RESOURCE_NAME: update_args}, - share_groups.RESOURCE_NAME) + share_groups.RESOURCE_NAME, + ) def test_update_no_data(self): fake_share_group = fake.ShareGroup() mock_get = self.mock_object( - self.manager, '_get', mock.Mock(return_value=fake_share_group)) + self.manager, '_get', mock.Mock(return_value=fake_share_group) + ) mock_update = self.mock_object( - self.manager, '_update', mock.Mock(return_value=fake_share_group)) + self.manager, '_update', mock.Mock(return_value=fake_share_group) + ) update_args = {} result = self.manager.update(fake.ShareGroup(), **update_args) @@ -285,7 +313,8 @@ def test_update_no_data(self): self.assertIs(fake_share_group, result) mock_get.assert_called_once_with( share_groups.RESOURCE_PATH % fake.ShareGroup.id, - share_groups.RESOURCE_NAME) + share_groups.RESOURCE_NAME, + ) self.assertFalse(mock_update.called) def test_delete(self): @@ -295,7 +324,8 @@ def test_delete(self): self.manager.delete(fake.ShareGroup()) mock_delete.assert_called_once_with( - share_groups.RESOURCE_PATH % fake.ShareGroup.id) + share_groups.RESOURCE_PATH % fake.ShareGroup.id + ) self.assertFalse(mock_post.called) def test_delete_force(self): @@ -307,7 +337,8 @@ def test_delete_force(self): self.assertFalse(mock_delete.called) mock_post.assert_called_once_with( share_groups.RESOURCE_PATH_ACTION % fake.ShareGroup.id, - body={'force_delete': None}) + body={'force_delete': None}, + ) def test_reset_state(self): mock_post = self.mock_object(self.manager.api.client, 'post') @@ -316,4 +347,5 @@ def test_reset_state(self): mock_post.assert_called_once_with( share_groups.RESOURCE_PATH_ACTION % fake.ShareGroup.id, - body={'reset_status': {'status': 'fake_state'}}) + body={'reset_status': {'status': 'fake_state'}}, + ) diff --git a/manilaclient/tests/unit/v2/test_share_instance_export_locations.py b/manilaclient/tests/unit/v2/test_share_instance_export_locations.py index 4fa95565..0adb8aad 100644 --- a/manilaclient/tests/unit/v2/test_share_instance_export_locations.py +++ b/manilaclient/tests/unit/v2/test_share_instance_export_locations.py @@ -25,29 +25,32 @@ extensions = [ - extension.Extension('share_instance_export_locations', - share_instance_export_locations), + extension.Extension( + 'share_instance_export_locations', share_instance_export_locations + ), ] cs = fakes.FakeClient(extensions=extensions) @ddt.ddt class ShareInstanceExportLocationsTest(utils.TestCase): - def _get_manager(self, microversion): version = api_versions.APIVersion(microversion) mock_microversion = mock.Mock(api_version=version) return ( share_instance_export_locations.ShareInstanceExportLocationManager( - api=mock_microversion) + api=mock_microversion + ) ) def test_list_of_export_locations(self): share_instance_id = '1234' cs.share_instance_export_locations.list( - share_instance_id, search_opts=None) + share_instance_id, search_opts=None + ) cs.assert_called( - 'GET', '/share_instances/%s/export_locations' % share_instance_id) + 'GET', f'/share_instances/{share_instance_id}/export_locations' + ) def test_get_single_export_location(self): share_instance_id = '1234' @@ -55,6 +58,8 @@ def test_get_single_export_location(self): cs.share_instance_export_locations.get(share_instance_id, el_uuid) cs.assert_called( 'GET', - ('/share_instances/%(share_instance_id)s/export_locations/' - '%(el_uuid)s') % { - 'share_instance_id': share_instance_id, 'el_uuid': el_uuid}) + ( + f'/share_instances/{share_instance_id}/export_locations/' + f'{el_uuid}' + ), + ) diff --git a/manilaclient/tests/unit/v2/test_share_instances.py b/manilaclient/tests/unit/v2/test_share_instances.py index a59f19d2..2d6f44d1 100644 --- a/manilaclient/tests/unit/v2/test_share_instances.py +++ b/manilaclient/tests/unit/v2/test_share_instances.py @@ -32,7 +32,6 @@ @ddt.ddt class ShareInstancesTest(utils.TestCase): - def _get_manager(self, microversion): version = api_versions.APIVersion(microversion) mock_microversion = mock.Mock(api_version=version) @@ -42,25 +41,28 @@ def test_list(self): cs.share_instances.list(search_opts=None) cs.assert_called('GET', '/share_instances') - @ddt.data(('id', 'b4991315-eb7d-43ec-979e-5715d4399827'), - ('path', '//0.0.0.0/fake_path')) + @ddt.data( + ('id', 'b4991315-eb7d-43ec-979e-5715d4399827'), + ('path', '//0.0.0.0/fake_path'), + ) @ddt.unpack def test_list_by_export_location(self, filter_type, value): cs.share_instances.list(export_location=value) cs.assert_called( - 'GET', '/share_instances?export_location_' + - filter_type + '=' + value) + 'GET', + '/share_instances?export_location_' + filter_type + '=' + value, + ) def test_get(self): - instance = type('None', (object, ), {'id': '1234'}) + instance = type('None', (object,), {'id': '1234'}) cs.share_instances.get(instance) cs.assert_called('GET', '/share_instances/1234') @ddt.data( - ("2.6", type("InstanceUUID", (object, ), {"uuid": "1234"})), - ("2.7", type("InstanceUUID", (object, ), {"uuid": "1234"})), - ("2.6", type("InstanceID", (object, ), {"id": "1234"})), - ("2.7", type("InstanceID", (object, ), {"id": "1234"})), + ("2.6", type("InstanceUUID", (object,), {"uuid": "1234"})), + ("2.7", type("InstanceUUID", (object,), {"uuid": "1234"})), + ("2.6", type("InstanceID", (object,), {"id": "1234"})), + ("2.7", type("InstanceID", (object,), {"id": "1234"})), ("2.6", "1234"), ("2.7", "1234"), ) @@ -68,8 +70,9 @@ def test_get(self): def test_reset_instance_state(self, microversion, instance): manager = self._get_manager(microversion) state = 'available' - if (api_versions.APIVersion(microversion) > - api_versions.APIVersion("2.6")): + if api_versions.APIVersion(microversion) > api_versions.APIVersion( + "2.6" + ): action_name = "reset_status" else: action_name = "os-reset_status" @@ -78,19 +81,21 @@ def test_reset_instance_state(self, microversion, instance): manager.reset_state(instance, state) manager._action.assert_called_once_with( - action_name, instance, {"status": state}) + action_name, instance, {"status": state} + ) @ddt.data( - ("2.6", type('InstanceUUID', (object, ), {"uuid": "1234"})), + ("2.6", type('InstanceUUID', (object,), {"uuid": "1234"})), ("2.6", "1234"), - ("2.7", type('InstanceUUID', (object, ), {"uuid": "1234"})), + ("2.7", type('InstanceUUID', (object,), {"uuid": "1234"})), ("2.7", "1234"), ) @ddt.unpack def test_force_delete_share_snapshot(self, microversion, instance): manager = self._get_manager(microversion) - if (api_versions.APIVersion(microversion) > - api_versions.APIVersion("2.6")): + if api_versions.APIVersion(microversion) > api_versions.APIVersion( + "2.6" + ): action_name = "force_delete" else: action_name = "os-force_delete" @@ -111,8 +116,9 @@ def test_force_delete_share_snapshot(self, microversion, instance): @ddt.unpack def test_valid_instance_state(self, microversion, instance, state): manager = self._get_manager(microversion) - if (api_versions.APIVersion(microversion) > - api_versions.APIVersion("2.6")): + if api_versions.APIVersion(microversion) > api_versions.APIVersion( + "2.6" + ): action_name = "reset_status" else: action_name = "os-reset_status" @@ -121,4 +127,5 @@ def test_valid_instance_state(self, microversion, instance, state): manager.reset_state(instance, state) manager._action.assert_called_once_with( - action_name, instance, {"status": state}) + action_name, instance, {"status": state} + ) diff --git a/manilaclient/tests/unit/v2/test_share_network_subnets.py b/manilaclient/tests/unit/v2/test_share_network_subnets.py index 0dae0d5e..9a89d32d 100644 --- a/manilaclient/tests/unit/v2/test_share_network_subnets.py +++ b/manilaclient/tests/unit/v2/test_share_network_subnets.py @@ -24,11 +24,11 @@ @ddt.ddt class ShareNetworkSubnetTest(utils.TestCase): - def setUp(self): - super(ShareNetworkSubnetTest, self).setUp() + super().setUp() self.manager = share_network_subnets.ShareNetworkSubnetManager( - fakes.FakeClient()) + fakes.FakeClient() + ) def test_create(self): share_network_id = 'fake_share_net_id' @@ -39,7 +39,7 @@ def test_create(self): 'neutron_net_id': 'fake_net_id', 'neutron_subnet_id': 'fake_subnet_id', 'availability_zone': 'fake_availability_zone', - 'metadata': 'fake_metadata' + 'metadata': 'fake_metadata', } expected_body = {'share-network-subnet': expected_values} payload = expected_values.copy() @@ -50,11 +50,9 @@ def test_create(self): self.assertEqual(expected_url, result['url']) self.assertEqual( - share_network_subnets.RESOURCE_NAME, - result['resp_key']) - self.assertEqual( - expected_body, - result['body']) + share_network_subnets.RESOURCE_NAME, result['resp_key'] + ) + self.assertEqual(expected_body, result['body']) def test_get(self): share_network = 'fake_share_network' @@ -64,11 +62,13 @@ def test_get(self): self.manager.get(share_network, share_subnet) self.manager._get.assert_called_once_with( - share_network_subnets.RESOURCE_PATH % { + share_network_subnets.RESOURCE_PATH + % { 'share_network_id': share_network, - 'share_network_subnet_id': share_subnet + 'share_network_subnet_id': share_subnet, }, - share_network_subnets.RESOURCE_NAME) + share_network_subnets.RESOURCE_NAME, + ) def test_delete(self): share_network = 'fake_share_network' @@ -78,7 +78,9 @@ def test_delete(self): self.manager.delete(share_network, share_subnet) self.manager._delete.assert_called_once_with( - share_network_subnets.RESOURCE_PATH % { + share_network_subnets.RESOURCE_PATH + % { 'share_network_id': share_network, - 'share_network_subnet_id': share_subnet - }) + 'share_network_subnet_id': share_subnet, + } + ) diff --git a/manilaclient/tests/unit/v2/test_share_networks.py b/manilaclient/tests/unit/v2/test_share_networks.py index 3380c3dc..9a2f83b9 100644 --- a/manilaclient/tests/unit/v2/test_share_networks.py +++ b/manilaclient/tests/unit/v2/test_share_networks.py @@ -27,15 +27,14 @@ @ddt.ddt class ShareNetworkTest(utils.TestCase): - - class _FakeShareNetwork(object): + class _FakeShareNetwork: id = 'fake_share_network_id' - class _FakeSecurityService(object): + class _FakeSecurityService: id = 'fake_security_service_id' def setUp(self): - super(ShareNetworkTest, self).setUp() + super().setUp() self.manager = share_networks.ShareNetworkManager(fakes.FakeClient()) self.values = { 'nova_net_id': 'fake_nova_net_id', @@ -49,34 +48,35 @@ def setUp(self): def test_create(self, microversion): api_version = api_versions.APIVersion(microversion) values = self.values.copy() - if (api_version >= api_versions.APIVersion("2.26")): + if api_version >= api_versions.APIVersion("2.26"): del values['nova_net_id'] body_expected = {share_networks.RESOURCE_NAME: values} manager = share_networks.ShareNetworkManager( - fakes.FakeClient(api_version=api_version)) + fakes.FakeClient(api_version=api_version) + ) with mock.patch.object(manager, '_create', fakes.fake_create): result = manager.create(**values) self.assertEqual(result['url'], share_networks.RESOURCES_PATH) self.assertEqual(result['resp_key'], share_networks.RESOURCE_NAME) - self.assertEqual( - body_expected, - result['body']) + self.assertEqual(body_expected, result['body']) def test_delete_str(self): share_nw = 'fake share nw' with mock.patch.object(self.manager, '_delete', mock.Mock()): self.manager.delete(share_nw) self.manager._delete.assert_called_once_with( - share_networks.RESOURCE_PATH % share_nw) + share_networks.RESOURCE_PATH % share_nw + ) def test_delete_obj(self): share_nw = self._FakeShareNetwork() with mock.patch.object(self.manager, '_delete', mock.Mock()): self.manager.delete(share_nw) self.manager._delete.assert_called_once_with( - share_networks.RESOURCE_PATH % share_nw.id) + share_networks.RESOURCE_PATH % share_nw.id + ) def test_get(self): share_nw = 'fake share nw' @@ -84,63 +84,71 @@ def test_get(self): self.manager.get(share_nw) self.manager._get.assert_called_once_with( share_networks.RESOURCE_PATH % share_nw, - share_networks.RESOURCE_NAME) + share_networks.RESOURCE_NAME, + ) def test_list_not_detailed(self): - with mock.patch.object(self.manager, '_list', - mock.Mock(return_value=None)): + with mock.patch.object( + self.manager, '_list', mock.Mock(return_value=None) + ): self.manager.list(detailed=False) self.manager._list.assert_called_once_with( - share_networks.RESOURCES_PATH, - share_networks.RESOURCES_NAME) + share_networks.RESOURCES_PATH, share_networks.RESOURCES_NAME + ) def test_list(self): - with mock.patch.object(self.manager, '_list', - mock.Mock(return_value=None)): + with mock.patch.object( + self.manager, '_list', mock.Mock(return_value=None) + ): self.manager.list() self.manager._list.assert_called_once_with( share_networks.RESOURCES_PATH + '/detail', - share_networks.RESOURCES_NAME) + share_networks.RESOURCES_NAME, + ) def test_list_with_filters(self): filters = {'all_tenants': 1, 'status': 'ERROR'} - expected_path = ("%s/detail?all_tenants=1&status=" - "ERROR" % share_networks.RESOURCES_PATH) - - with mock.patch.object(self.manager, '_list', - mock.Mock(return_value=None)): + expected_path = ( + f"{share_networks.RESOURCES_PATH}/detail?all_tenants=1&status=" + "ERROR" + ) + + with mock.patch.object( + self.manager, '_list', mock.Mock(return_value=None) + ): self.manager.list(search_opts=filters) self.manager._list.assert_called_once_with( - expected_path, - share_networks.RESOURCES_NAME) - - @ddt.data(*itertools.product( - ["2.25", "2.26"], - ['fake share nw', _FakeShareNetwork()] - )) + expected_path, share_networks.RESOURCES_NAME + ) + + @ddt.data( + *itertools.product( + ["2.25", "2.26"], ['fake share nw', _FakeShareNetwork()] + ) + ) @ddt.unpack def test_update_share_network(self, microversion, share_nw): api_version = api_versions.APIVersion(microversion) values = self.values.copy() - if (api_version >= api_versions.APIVersion("2.26")): + if api_version >= api_versions.APIVersion("2.26"): del values['nova_net_id'] body_expected = {share_networks.RESOURCE_NAME: values} manager = share_networks.ShareNetworkManager( - fakes.FakeClient(api_version=api_version)) + fakes.FakeClient(api_version=api_version) + ) with mock.patch.object(manager, '_update', fakes.fake_update): result = manager.update(share_nw, **values) id = share_nw.id if hasattr(share_nw, 'id') else share_nw - self.assertEqual(result['url'], - share_networks.RESOURCE_PATH % id) + self.assertEqual(result['url'], share_networks.RESOURCE_PATH % id) self.assertEqual(result['resp_key'], share_networks.RESOURCE_NAME) self.assertEqual(result['body'], body_expected) def test_update_with_exception(self): share_nw = 'fake share nw' - self.assertRaises(exceptions.CommandError, - self.manager.update, - share_nw) + self.assertRaises( + exceptions.CommandError, self.manager.update, share_nw + ) def test_add_security_service(self): security_service = 'fake security service' @@ -152,9 +160,8 @@ def test_add_security_service(self): with mock.patch.object(self.manager, '_action', mock.Mock()): self.manager.add_security_service(share_nw, security_service) self.manager._action.assert_called_once_with( - expected_path, - share_nw, - expected_body) + expected_path, share_nw, expected_body + ) def test_add_security_service_to_share_nw_object(self): security_service = self._FakeSecurityService() @@ -166,9 +173,8 @@ def test_add_security_service_to_share_nw_object(self): with mock.patch.object(self.manager, '_action', mock.Mock()): self.manager.add_security_service(share_nw, security_service) self.manager._action.assert_called_once_with( - expected_path, - share_nw, - expected_body) + expected_path, share_nw, expected_body + ) def test_remove_security_service(self): security_service = 'fake security service' @@ -182,15 +188,15 @@ def test_remove_security_service(self): with mock.patch.object(self.manager, '_create', mock.Mock()): self.manager.remove_security_service(share_nw, security_service) self.manager._create.assert_called_once_with( - expected_path, - expected_body, - share_networks.RESOURCE_NAME) + expected_path, expected_body, share_networks.RESOURCE_NAME + ) def test_remove_security_service_from_share_nw_object(self): security_service = self._FakeSecurityService() share_nw = self._FakeShareNetwork() - expected_path = ((share_networks.RESOURCE_PATH + - '/action') % share_nw.id) + expected_path = ( + share_networks.RESOURCE_PATH + '/action' + ) % share_nw.id expected_body = { 'remove_security_service': { 'security_service_id': security_service.id, @@ -199,9 +205,8 @@ def test_remove_security_service_from_share_nw_object(self): with mock.patch.object(self.manager, '_create', mock.Mock()): self.manager.remove_security_service(share_nw, security_service) self.manager._create.assert_called_once_with( - expected_path, - expected_body, - share_networks.RESOURCE_NAME) + expected_path, expected_body, share_networks.RESOURCE_NAME + ) def test_update_share_network_security_service(self): current_security_service = self._FakeSecurityService() @@ -212,16 +217,16 @@ def test_update_share_network_security_service(self): expected_body = { 'current_service_id': current_security_service.id, - 'new_service_id': new_security_service.id + 'new_service_id': new_security_service.id, } with mock.patch.object(self.manager, '_action', mock.Mock()): self.manager.update_share_network_security_service( - share_nw, current_security_service, new_security_service) + share_nw, current_security_service, new_security_service + ) self.manager._action.assert_called_once_with( - expected_path, - share_nw, - expected_body) + expected_path, share_nw, expected_body + ) def test_share_network_reset_state(self): share_nw = self._FakeShareNetwork() @@ -233,12 +238,10 @@ def test_share_network_reset_state(self): } with mock.patch.object(self.manager, '_action', mock.Mock()): - self.manager.reset_state( - share_nw, state) + self.manager.reset_state(share_nw, state) self.manager._action.assert_called_once_with( - expected_path, - share_nw, - expected_body) + expected_path, share_nw, expected_body + ) def test_share_network_security_service_update_check(self): current_security_service = self._FakeSecurityService() @@ -250,16 +253,16 @@ def test_share_network_security_service_update_check(self): expected_body = { 'current_service_id': current_security_service.id, 'new_service_id': new_security_service.id, - 'reset_operation': False + 'reset_operation': False, } with mock.patch.object(self.manager, '_action', mock.Mock()): self.manager.update_share_network_security_service_check( - share_nw, current_security_service, new_security_service) + share_nw, current_security_service, new_security_service + ) self.manager._action.assert_called_once_with( - expected_path, - share_nw, - expected_body) + expected_path, share_nw, expected_body + ) def test_add_security_service_check(self): current_security_service = self._FakeSecurityService() @@ -269,16 +272,16 @@ def test_add_security_service_check(self): expected_body = { 'security_service_id': current_security_service.id, - 'reset_operation': False + 'reset_operation': False, } with mock.patch.object(self.manager, '_action', mock.Mock()): self.manager.add_security_service_check( - share_nw, current_security_service, False) + share_nw, current_security_service, False + ) self.manager._action.assert_called_once_with( - expected_path, - share_nw, - expected_body) + expected_path, share_nw, expected_body + ) def test_share_network_subnet_create_check(self): share_nw = self._FakeShareNetwork() @@ -288,14 +291,15 @@ def test_share_network_subnet_create_check(self): expected_body = { 'neutron_net_id': self.values['neutron_net_id'], 'neutron_subnet_id': self.values['neutron_subnet_id'], - 'reset_operation': False + 'reset_operation': False, } with mock.patch.object(self.manager, '_action', mock.Mock()): self.manager.share_network_subnet_create_check( - share_nw, self.values['neutron_net_id'], - self.values['neutron_subnet_id']) - self.manager._action.assert_called_once_with( - expected_path, share_nw, - expected_body) + self.values['neutron_net_id'], + self.values['neutron_subnet_id'], + ) + self.manager._action.assert_called_once_with( + expected_path, share_nw, expected_body + ) diff --git a/manilaclient/tests/unit/v2/test_share_replica_export_locations.py b/manilaclient/tests/unit/v2/test_share_replica_export_locations.py index ff21dd70..c42617c3 100644 --- a/manilaclient/tests/unit/v2/test_share_replica_export_locations.py +++ b/manilaclient/tests/unit/v2/test_share_replica_export_locations.py @@ -26,26 +26,28 @@ @ddt.ddt class ShareReplicaExportLocationsTest(utils.TestCase): - def _get_manager(self, microversion): version = api_versions.APIVersion(microversion) mock_microversion = mock.Mock(api_version=version) return ( share_replica_export_locations.ShareReplicaExportLocationManager( - api=mock_microversion) + api=mock_microversion + ) ) def test_list_share_replica_export_locations(self): share_replica_id = '1234' cs.share_replica_export_locations.list(share_replica_id) cs.assert_called( - 'GET', '/share-replicas/%s/export-locations' % share_replica_id) + 'GET', f'/share-replicas/{share_replica_id}/export-locations' + ) def test_get_share_replica_export_location(self): share_replica_id = '1234' el_uuid = 'fake_el_uuid' cs.share_replica_export_locations.get(share_replica_id, el_uuid) - url = ('/share-replicas/%(share_replica_id)s/export-locations/' - '%(el_uuid)s') + url = ( + '/share-replicas/%(share_replica_id)s/export-locations/%(el_uuid)s' + ) payload = {'share_replica_id': share_replica_id, 'el_uuid': el_uuid} cs.assert_called('GET', url % payload) diff --git a/manilaclient/tests/unit/v2/test_share_replicas.py b/manilaclient/tests/unit/v2/test_share_replicas.py index 7cbc0b73..f7174f36 100644 --- a/manilaclient/tests/unit/v2/test_share_replicas.py +++ b/manilaclient/tests/unit/v2/test_share_replicas.py @@ -28,19 +28,21 @@ @ddt.ddt class ShareReplicasTest(utils.TestCase): - - class _FakeShareReplica(object): + class _FakeShareReplica: id = 'fake_share_replica_id' def setUp(self): - super(ShareReplicasTest, self).setUp() + super().setUp() microversion = api_versions.APIVersion("2.67") self.manager = share_replicas.ShareReplicaManager( - fakes.FakeClient(api_version=microversion)) - - @ddt.data("2.11", - constants.REPLICA_PRE_GRADUATION_VERSION, - constants.REPLICA_GRADUATION_VERSION) + fakes.FakeClient(api_version=microversion) + ) + + @ddt.data( + "2.11", + constants.REPLICA_PRE_GRADUATION_VERSION, + constants.REPLICA_GRADUATION_VERSION, + ) def test_create(self, microversion): api_version = api_versions.APIVersion(microversion) values = { @@ -49,7 +51,8 @@ def test_create(self, microversion): } manager = share_replicas.ShareReplicaManager( - fakes.FakeClient(api_version=api_version)) + fakes.FakeClient(api_version=api_version) + ) with mock.patch.object(manager, '_create', fakes.fake_create): result = manager.create(**values) @@ -69,7 +72,31 @@ def test_create_with_share_network(self, microversion): } manager = share_replicas.ShareReplicaManager( - fakes.FakeClient(api_version=api_version)) + fakes.FakeClient(api_version=api_version) + ) + with mock.patch.object(manager, '_create', fakes.fake_create): + result = manager.create(**values) + + values['share_id'] = values.pop('share') + values['share_network_id'] = values.pop('share_network') + body_expected = {share_replicas.RESOURCE_NAME: values} + self.assertEqual(share_replicas.RESOURCES_PATH, result['url']) + self.assertEqual(share_replicas.RESOURCE_NAME, result['resp_key']) + self.assertEqual(body_expected, result['body']) + + @ddt.data("2.95") + def test_create_with_metadata(self, microversion): + api_version = api_versions.APIVersion(microversion) + values = { + 'availability_zone': 'az1', + 'share': 's1', + 'share_network': 'sn1', + 'metadata': {"fake_key": "fake_value"}, + } + + manager = share_replicas.ShareReplicaManager( + fakes.FakeClient(api_version=api_version) + ) with mock.patch.object(manager, '_create', fakes.fake_create): result = manager.create(**values) @@ -84,40 +111,46 @@ def test_delete_str(self): with mock.patch.object(self.manager, '_delete', mock.Mock()): self.manager.delete(FAKE_REPLICA) self.manager._delete.assert_called_once_with( - share_replicas.RESOURCE_PATH % FAKE_REPLICA) + share_replicas.RESOURCE_PATH % FAKE_REPLICA + ) def test_delete_obj(self): replica = self._FakeShareReplica with mock.patch.object(self.manager, '_delete', mock.Mock()): self.manager.delete(replica) self.manager._delete.assert_called_once_with( - share_replicas.RESOURCE_PATH % replica.id) + share_replicas.RESOURCE_PATH % replica.id + ) def test_delete_with_force(self): with mock.patch.object(self.manager, '_action', mock.Mock()): self.manager.delete(FAKE_REPLICA, force=True) self.manager._action.assert_called_once_with( - 'force_delete', FAKE_REPLICA) + 'force_delete', FAKE_REPLICA + ) def test_get(self): with mock.patch.object(self.manager, '_get', mock.Mock()): self.manager.get(FAKE_REPLICA) self.manager._get.assert_called_once_with( share_replicas.RESOURCE_PATH % FAKE_REPLICA, - share_replicas.RESOURCE_NAME) + share_replicas.RESOURCE_NAME, + ) def test_promote(self): with mock.patch.object(self.manager, '_action', mock.Mock()): self.manager.promote(FAKE_REPLICA) self.manager._action.assert_called_once_with( - 'promote', FAKE_REPLICA) + 'promote', FAKE_REPLICA + ) def test_list(self): with mock.patch.object(self.manager, '_list', mock.Mock()): self.manager.list(search_opts=None) self.manager._list.assert_called_once_with( share_replicas.RESOURCES_PATH + '/detail', - share_replicas.RESOURCES_NAME) + share_replicas.RESOURCES_NAME, + ) def test_list_with_share(self): with mock.patch.object(self.manager, '_list', mock.Mock()): @@ -125,13 +158,15 @@ def test_list_with_share(self): share_uri = '?share_id=share_id' self.manager._list.assert_called_once_with( (share_replicas.RESOURCES_PATH + '/detail' + share_uri), - share_replicas.RESOURCES_NAME) + share_replicas.RESOURCES_NAME, + ) def test_resync(self): with mock.patch.object(self.manager, '_action', mock.Mock()): self.manager.resync(FAKE_REPLICA) self.manager._action.assert_called_once_with( - 'resync', FAKE_REPLICA) + 'resync', FAKE_REPLICA + ) @ddt.data('reset_status', 'reset_replica_state') def test_reset_state_actions(self, action): @@ -140,4 +175,5 @@ def test_reset_state_actions(self, action): with mock.patch.object(self.manager, '_action', mock.Mock()): method(FAKE_REPLICA, 'some_status') self.manager._action.assert_called_once_with( - action, FAKE_REPLICA, {attr: 'some_status'}) + action, FAKE_REPLICA, {attr: 'some_status'} + ) diff --git a/manilaclient/tests/unit/v2/test_share_servers.py b/manilaclient/tests/unit/v2/test_share_servers.py index 3850424d..09f645ab 100644 --- a/manilaclient/tests/unit/v2/test_share_servers.py +++ b/manilaclient/tests/unit/v2/test_share_servers.py @@ -24,7 +24,7 @@ from manilaclient.v2 import share_servers -class FakeShareServer(object): +class FakeShareServer: _info = { "backend_details": { "fake_key1": "fake_value1", @@ -34,9 +34,8 @@ class FakeShareServer(object): class ShareServerTest(utils.TestCase): - def setUp(self): - super(ShareServerTest, self).setUp() + super().setUp() self.share_server_id = 'foo' self.share_network = 'bar' info = { @@ -44,11 +43,12 @@ def setUp(self): 'share_network_name': self.share_network, } self.resource_class = share_servers.ShareServer( - manager=self, info=info) + manager=self, info=info + ) def test_get_repr_of_share_server(self): self.assertIn( - 'ShareServer: %s' % self.share_server_id, + f'ShareServer: {self.share_server_id}', repr(self.resource_class), ) @@ -65,24 +65,25 @@ def test_get_nonexistent_share_network_name(self): except AttributeError: pass else: - raise Exception("Expected exception 'AttributeError' " - "has not been raised.") + raise Exception( + "Expected exception 'AttributeError' has not been raised." + ) @ddt.ddt class ShareServerManagerTest(utils.TestCase): - def setUp(self): - super(ShareServerManagerTest, self).setUp() + super().setUp() self.manager = share_servers.ShareServerManager(api=fakes.FakeClient()) def test_list(self): - with mock.patch.object(self.manager, '_list', - mock.Mock(return_value=None)): + with mock.patch.object( + self.manager, '_list', mock.Mock(return_value=None) + ): self.manager.list() self.manager._list.assert_called_once_with( - share_servers.RESOURCES_PATH, - share_servers.RESOURCES_NAME) + share_servers.RESOURCES_PATH, share_servers.RESOURCES_NAME + ) @ddt.data(None, {}, {'opt1': 'fake_opt1', 'opt12': 'fake_opt2'}) def test_manage(self, driver_options): @@ -99,52 +100,65 @@ def test_manage(self, driver_options): 'driver_options': driver_options, 'share_network_subnet_id': share_network_subnet_id, } - with mock.patch.object(self.manager, '_create', - mock.Mock(return_value='fake')): + with mock.patch.object( + self.manager, '_create', mock.Mock(return_value='fake') + ): result = self.manager.manage( - host, share_network_id, identifier, + host, + share_network_id, + identifier, driver_options=driver_options, - share_network_subnet_id=share_network_subnet_id) + share_network_subnet_id=share_network_subnet_id, + ) self.manager._create.assert_called_once_with( share_servers.RESOURCES_PATH + '/manage', - {'share_server': expected_body}, 'share_server' + {'share_server': expected_body}, + 'share_server', ) self.assertEqual('fake', result) @ddt.data(True, False) def test_unmanage(self, force): share_server = {'id': 'fake'} - with mock.patch.object(self.manager, '_action', - mock.Mock(return_value='fake')): + with mock.patch.object( + self.manager, '_action', mock.Mock(return_value='fake') + ): result = self.manager.unmanage(share_server, force) self.manager._action.assert_called_once_with( - "unmanage", share_server, {'force': force}) + "unmanage", share_server, {'force': force} + ) self.assertEqual('fake', result) def test_reset_state(self): share_server = {'id': 'fake'} state = constants.STATUS_AVAILABLE - with mock.patch.object(self.manager, '_action', - mock.Mock(return_value='fake')): + with mock.patch.object( + self.manager, '_action', mock.Mock(return_value='fake') + ): result = self.manager.reset_state(share_server, state) self.manager._action.assert_called_once_with( - "reset_status", share_server, {"status": state}) + "reset_status", share_server, {"status": state} + ) self.assertEqual('fake', result) - @ddt.data(("reset_status", {"status": constants.STATUS_AVAILABLE}), - ("unmanage", {"id": "fake_id"})) + @ddt.data( + ("reset_status", {"status": constants.STATUS_AVAILABLE}), + ("unmanage", {"id": "fake_id"}), + ) @ddt.unpack def test__action(self, action, info): action = "" share_server = {"id": 'fake_id'} - expected_url = '/share-servers/%s/action' % share_server['id'] + expected_url = '/share-servers/{}/action'.format(share_server['id']) expected_body = {action: info} - with mock.patch.object(self.manager.api.client, 'post', - mock.Mock(return_value='fake')): - self.mock_object(base, 'getid', - mock.Mock(return_value=share_server['id'])) + with mock.patch.object( + self.manager.api.client, 'post', mock.Mock(return_value='fake') + ): + self.mock_object( + base, 'getid', mock.Mock(return_value=share_server['id']) + ) result = self.manager._action(action, share_server, info) self.manager.api.client.post.assert_called_once_with( expected_url, body=expected_body @@ -153,9 +167,10 @@ def test__action(self, action, info): def test_list_with_one_search_opt(self): host = 'fake_host' - query_string = "?host=%s" % host - with mock.patch.object(self.manager, '_list', - mock.Mock(return_value=None)): + query_string = f"?host={host}" + with mock.patch.object( + self.manager, '_list', mock.Mock(return_value=None) + ): self.manager.list({'host': host}) self.manager._list.assert_called_once_with( share_servers.RESOURCES_PATH + query_string, @@ -165,9 +180,10 @@ def test_list_with_one_search_opt(self): def test_list_with_two_search_opts(self): host = 'fake_host' status = 'fake_status' - query_string = "?host=%s&status=%s" % (host, status) - with mock.patch.object(self.manager, '_list', - mock.Mock(return_value=None)): + query_string = f"?host={host}&status={status}" + with mock.patch.object( + self.manager, '_list', mock.Mock(return_value=None) + ): self.manager.list({'host': host, 'status': status}) self.manager._list.assert_called_once_with( share_servers.RESOURCES_PATH + query_string, @@ -179,28 +195,33 @@ def test_delete(self): with mock.patch.object(self.manager, '_delete', mock.Mock()): self.manager.delete(share_server_id) self.manager._delete.assert_called_once_with( - share_servers.RESOURCE_PATH % share_server_id) + share_servers.RESOURCE_PATH % share_server_id + ) def test_get(self): server = FakeShareServer() - with mock.patch.object(self.manager, '_get', - mock.Mock(return_value=server)): + with mock.patch.object( + self.manager, '_get', mock.Mock(return_value=server) + ): share_server_id = 'fake_share_server_id' self.manager.get(share_server_id) self.manager._get.assert_called_once_with( - "%s/%s" % (share_servers.RESOURCES_PATH, share_server_id), - share_servers.RESOURCE_NAME) + f"{share_servers.RESOURCES_PATH}/{share_server_id}", + share_servers.RESOURCE_NAME, + ) for key in ["details:fake_key1", "details:fake_key2"]: self.assertIn(key, list(server._info)) def test_details(self): - with mock.patch.object(self.manager, '_get', - mock.Mock(return_value=None)): + with mock.patch.object( + self.manager, '_get', mock.Mock(return_value=None) + ): share_server_id = 'fake_share_server_id' self.manager.details(share_server_id) self.manager._get.assert_called_once_with( - "%s/%s/details" % (share_servers.RESOURCES_PATH, - share_server_id), 'details') + f"{share_servers.RESOURCES_PATH}/{share_server_id}/details", + 'details', + ) def test_migration_check(self): share_server = "fake_share_server" @@ -214,19 +235,27 @@ def test_migration_check(self): 'preserve_snapshots': True, } - with mock.patch.object(self.manager, "_action", - mock.Mock(return_value=['200', returned])): + with mock.patch.object( + self.manager, "_action", mock.Mock(return_value=['200', returned]) + ): result = self.manager.migration_check( - share_server, host, writable=True, nondisruptive=True, - preserve_snapshots=True) + share_server, + host, + writable=True, + nondisruptive=True, + preserve_snapshots=True, + ) self.manager._action.assert_called_once_with( - 'migration_check', share_server, { + 'migration_check', + share_server, + { "host": host, "writable": True, "nondisruptive": True, "preserve_snapshots": True, "new_share_network_id": None, - }) + }, + ) self.assertEqual(returned, result) @@ -235,19 +264,27 @@ def test_migration_start(self): host = "fake_host" returned = "fake" - with mock.patch.object(self.manager, "_action", - mock.Mock(return_value=returned)): + with mock.patch.object( + self.manager, "_action", mock.Mock(return_value=returned) + ): result = self.manager.migration_start( - share_server, host, writable=True, nondisruptive=True, - preserve_snapshots=True) + share_server, + host, + writable=True, + nondisruptive=True, + preserve_snapshots=True, + ) self.manager._action.assert_called_once_with( - 'migration_start', share_server, { + 'migration_start', + share_server, + { "host": host, "writable": True, "nondisruptive": True, "preserve_snapshots": True, "new_share_network_id": None, - }) + }, + ) self.assertEqual(returned, result) @@ -255,24 +292,28 @@ def test_migration_complete(self): share_server = "fake_share_server" returned = "fake" - with mock.patch.object(self.manager, "_action", - mock.Mock(return_value=['200', returned])): + with mock.patch.object( + self.manager, "_action", mock.Mock(return_value=['200', returned]) + ): result = self.manager.migration_complete(share_server) self.manager._action.assert_called_once_with( - "migration_complete", share_server) + "migration_complete", share_server + ) self.assertEqual(returned, result) def test_migration_get_progress(self): share_server = "fake_share_server" returned = "fake" - with mock.patch.object(self.manager, "_action", - mock.Mock(return_value=['200', returned])): + with mock.patch.object( + self.manager, "_action", mock.Mock(return_value=['200', returned]) + ): result = self.manager.migration_get_progress(share_server) self.manager._action.assert_called_once_with( - "migration_get_progress", share_server) + "migration_get_progress", share_server + ) self.assertEqual(returned, result) def test_reset_task_state(self): @@ -280,22 +321,26 @@ def test_reset_task_state(self): state = "fake_state" returned = "fake" - with mock.patch.object(self.manager, "_action", - mock.Mock(return_value=returned)): + with mock.patch.object( + self.manager, "_action", mock.Mock(return_value=returned) + ): result = self.manager.reset_task_state(share_server, state) self.manager._action.assert_called_once_with( - "reset_task_state", share_server, {'task_state': state}) + "reset_task_state", share_server, {'task_state': state} + ) self.assertEqual(returned, result) def test_migration_cancel(self): share_server = "fake_share_server" returned = "fake" - with mock.patch.object(self.manager, "_action", - mock.Mock(return_value=returned)): + with mock.patch.object( + self.manager, "_action", mock.Mock(return_value=returned) + ): result = self.manager.migration_cancel(share_server) self.manager._action.assert_called_once_with( - "migration_cancel", share_server) + "migration_cancel", share_server + ) self.assertEqual(returned, result) diff --git a/manilaclient/tests/unit/v2/test_share_snapshot_export_locations.py b/manilaclient/tests/unit/v2/test_share_snapshot_export_locations.py index 4c248177..fc02d75c 100644 --- a/manilaclient/tests/unit/v2/test_share_snapshot_export_locations.py +++ b/manilaclient/tests/unit/v2/test_share_snapshot_export_locations.py @@ -21,8 +21,9 @@ extensions = [ - extension.Extension('share_snapshot_export_locations', - share_snapshot_export_locations), + extension.Extension( + 'share_snapshot_export_locations', share_snapshot_export_locations + ), ] cs = fakes.FakeClient(extensions=extensions) @@ -31,15 +32,12 @@ class ShareSnapshotExportLocationsTest(utils.TestCase): def test_list_snapshot(self): snapshot_id = '1234' cs.share_snapshot_export_locations.list(snapshot_id, search_opts=None) - cs.assert_called( - 'GET', '/snapshots/%s/export-locations' % snapshot_id) + cs.assert_called('GET', f'/snapshots/{snapshot_id}/export-locations') def test_get_snapshot(self): snapshot_id = '1234' el_id = 'fake_el_id' cs.share_snapshot_export_locations.get(el_id, snapshot_id) cs.assert_called( - 'GET', - ('/snapshots/%(snapshot_id)s/export-locations/' - '%(el_id)s') % { - 'snapshot_id': snapshot_id, 'el_id': el_id}) + 'GET', (f'/snapshots/{snapshot_id}/export-locations/{el_id}') + ) diff --git a/manilaclient/tests/unit/v2/test_share_snapshot_instance_export_locations.py b/manilaclient/tests/unit/v2/test_share_snapshot_instance_export_locations.py index 686093c2..fa829640 100644 --- a/manilaclient/tests/unit/v2/test_share_snapshot_instance_export_locations.py +++ b/manilaclient/tests/unit/v2/test_share_snapshot_instance_export_locations.py @@ -21,8 +21,10 @@ extensions = [ - extension.Extension('share_snapshot_export_locations', - share_snapshot_instance_export_locations), + extension.Extension( + 'share_snapshot_export_locations', + share_snapshot_instance_export_locations, + ), ] cs = fakes.FakeClient(extensions=extensions) @@ -31,18 +33,23 @@ class ShareSnapshotInstanceExportLocationsTest(utils.TestCase): def test_list_snapshot_instance(self): snapshot_instance_id = '1234' cs.share_snapshot_instance_export_locations.list( - snapshot_instance_id, search_opts=None) + snapshot_instance_id, search_opts=None + ) cs.assert_called( - 'GET', '/snapshot-instances/%s/export-locations' - % snapshot_instance_id) + 'GET', + f'/snapshot-instances/{snapshot_instance_id}/export-locations', + ) def test_get_snapshot_instance(self): snapshot_instance_id = '1234' el_id = 'fake_el_id' cs.share_snapshot_instance_export_locations.get( - el_id, snapshot_instance_id) + el_id, snapshot_instance_id + ) cs.assert_called( 'GET', - ('/snapshot-instances/%(snapshot_id)s/export-locations/' - '%(el_id)s') % { - 'snapshot_id': snapshot_instance_id, 'el_id': el_id}) + ( + f'/snapshot-instances/{snapshot_instance_id}/export-locations/' + f'{el_id}' + ), + ) diff --git a/manilaclient/tests/unit/v2/test_share_snapshot_instances.py b/manilaclient/tests/unit/v2/test_share_snapshot_instances.py index 1738c2e4..33e5be9e 100644 --- a/manilaclient/tests/unit/v2/test_share_snapshot_instances.py +++ b/manilaclient/tests/unit/v2/test_share_snapshot_instances.py @@ -33,13 +33,13 @@ @ddt.ddt class SnapshotInstancesTest(utils.TestCase): - def setUp(self): - super(SnapshotInstancesTest, self).setUp() + super().setUp() microversion = api_versions.APIVersion("2.19") mock_microversion = mock.Mock(api_version=microversion) self.manager = share_snapshot_instances.ShareSnapshotInstanceManager( - api=mock_microversion) + api=mock_microversion + ) @ddt.data(True, False) def test_list(self, detailed): @@ -60,14 +60,17 @@ def test_list_with_snapshot(self, detailed): self.mock_object(self.manager, '_list', mock.Mock()) self.manager.list(detailed=detailed, snapshot='snapshot_id') self.manager._list.assert_called_once_with( - (url + '?snapshot_id=snapshot_id'), 'snapshot_instances',) + (url + '?snapshot_id=snapshot_id'), + 'snapshot_instances', + ) def test_get(self): self.mock_object(self.manager, '_get', mock.Mock()) self.manager.get('fake_snapshot_instance') self.manager._get.assert_called_once_with( '/snapshot-instances/' + 'fake_snapshot_instance', - 'snapshot_instance') + 'snapshot_instance', + ) def test_reset_instance_state(self): state = 'available' @@ -75,7 +78,8 @@ def test_reset_instance_state(self): self.mock_object(self.manager, '_action', mock.Mock()) self.manager.reset_state('fake_instance', state) self.manager._action.assert_called_once_with( - "reset_status", 'fake_instance', {"status": state}) + "reset_status", 'fake_instance', {"status": state} + ) @ddt.data('get', 'list', 'reset_state') def test_upsupported_microversion(self, method_name): @@ -90,7 +94,9 @@ def test_upsupported_microversion(self, method_name): microversion = api_versions.APIVersion(microversion) mock_microversion = mock.Mock(api_version=microversion) manager = share_snapshot_instances.ShareSnapshotInstanceManager( - api=mock_microversion) + api=mock_microversion + ) method = getattr(manager, method_name) - self.assertRaises(exceptions.UnsupportedVersion, - method, **arguments) + self.assertRaises( + exceptions.UnsupportedVersion, method, **arguments + ) diff --git a/manilaclient/tests/unit/v2/test_share_snapshots.py b/manilaclient/tests/unit/v2/test_share_snapshots.py index bd8a525c..9fe29cab 100644 --- a/manilaclient/tests/unit/v2/test_share_snapshots.py +++ b/manilaclient/tests/unit/v2/test_share_snapshots.py @@ -34,7 +34,6 @@ @ddt.ddt class ShareSnapshotsTest(utils.TestCase): - def _get_manager(self, microversion): version = api_versions.APIVersion(microversion) mock_microversion = mock.Mock(api_version=version) @@ -45,27 +44,29 @@ def test_create_share_snapshot(self): cs.assert_called('POST', '/snapshots') @ddt.data( - type('SnapshotUUID', (object, ), {'uuid': '1234'}), - type('SnapshotID', (object, ), {'id': '1234'}), - '1234') + type('SnapshotUUID', (object,), {'uuid': '1234'}), + type('SnapshotID', (object,), {'id': '1234'}), + '1234', + ) def test_get_share_snapshot(self, snapshot): snapshot = cs.share_snapshots.get(snapshot) cs.assert_called('GET', '/snapshots/1234') @ddt.data( - type('SnapshotUUID', (object, ), {'uuid': '1234'}), - type('SnapshotID', (object, ), {'id': '1234'}), - '1234') + type('SnapshotUUID', (object,), {'uuid': '1234'}), + type('SnapshotID', (object,), {'id': '1234'}), + '1234', + ) def test_update_share_snapshot(self, snapshot): data = dict(foo='bar', quuz='foobar') snapshot = cs.share_snapshots.update(snapshot, **data) cs.assert_called('PUT', '/snapshots/1234', {'snapshot': data}) @ddt.data( - ("2.6", type('SnapshotUUID', (object, ), {'uuid': '1234'})), - ("2.7", type('SnapshotUUID', (object, ), {'uuid': '1234'})), - ("2.6", type('SnapshotID', (object, ), {'id': '1234'})), - ("2.7", type('SnapshotID', (object, ), {'id': '1234'})), + ("2.6", type('SnapshotUUID', (object,), {'uuid': '1234'})), + ("2.7", type('SnapshotUUID', (object,), {'uuid': '1234'})), + ("2.6", type('SnapshotID', (object,), {'id': '1234'})), + ("2.7", type('SnapshotID', (object,), {'id': '1234'})), ("2.6", "1234"), ("2.7", "1234"), ) @@ -73,8 +74,9 @@ def test_update_share_snapshot(self, snapshot): def test_reset_snapshot_state(self, microversion, snapshot): manager = self._get_manager(microversion) state = 'available' - if (api_versions.APIVersion(microversion) > - api_versions.APIVersion("2.6")): + if api_versions.APIVersion(microversion) > api_versions.APIVersion( + "2.6" + ): action_name = "reset_status" else: action_name = "os-reset_status" @@ -83,7 +85,8 @@ def test_reset_snapshot_state(self, microversion, snapshot): manager.reset_state(snapshot, state) manager._action.assert_called_once_with( - action_name, snapshot, {"status": state}) + action_name, snapshot, {"status": state} + ) def test_delete_share_snapshot(self): snapshot = cs.share_snapshots.get(1234) @@ -91,16 +94,17 @@ def test_delete_share_snapshot(self): cs.assert_called('DELETE', '/snapshots/1234') @ddt.data( - ("2.6", type('SnapshotUUID', (object, ), {"uuid": "1234"})), + ("2.6", type('SnapshotUUID', (object,), {"uuid": "1234"})), ("2.6", "1234"), - ("2.7", type('SnapshotUUID', (object, ), {"uuid": "1234"})), + ("2.7", type('SnapshotUUID', (object,), {"uuid": "1234"})), ("2.7", "1234"), ) @ddt.unpack def test_force_delete_share_snapshot(self, microversion, snapshot): manager = self._get_manager(microversion) - if (api_versions.APIVersion(microversion) > - api_versions.APIVersion("2.6")): + if api_versions.APIVersion(microversion) > api_versions.APIVersion( + "2.6" + ): action_name = "force_delete" else: action_name = "os-force_delete" @@ -118,16 +122,19 @@ def test_list_share_snapshots_index_with_search_opts(self): search_opts = {'fake_str': 'fake_str_value', 'fake_int': 1} cs.share_snapshots.list(detailed=False, search_opts=search_opts) cs.assert_called( - 'GET', '/snapshots?fake_int=1&fake_str=fake_str_value') + 'GET', '/snapshots?fake_int=1&fake_str=fake_str_value' + ) def test_list_share_snapshots_sort_by_asc_and_share_id(self): cs.share_snapshots.list( - detailed=False, sort_key='share_id', sort_dir='asc') + detailed=False, sort_key='share_id', sort_dir='asc' + ) cs.assert_called('GET', '/snapshots?sort_dir=asc&sort_key=share_id') def test_list_share_snapshots_sort_by_desc_and_status(self): cs.share_snapshots.list( - detailed=False, sort_key='status', sort_dir='desc') + detailed=False, sort_key='status', sort_dir='desc' + ) cs.assert_called('GET', '/snapshots?sort_dir=desc&sort_key=status') def test_list_share_snapshots_by_improper_direction(self): @@ -144,10 +151,10 @@ def test_list_share_snapshots_detail_with_count(self): search_opts = { 'with_count': 'True', } - snapshots, count = cs.share_snapshots.list(detailed=True, - search_opts=search_opts) - cs.assert_called( - 'GET', '/snapshots/detail?with_count=True') + snapshots, count = cs.share_snapshots.list( + detailed=True, search_opts=search_opts + ) + cs.assert_called('GET', '/snapshots/detail?with_count=True') self.assertEqual(2, count) self.assertEqual(1, len(snapshots)) @@ -168,16 +175,21 @@ def test_manage_snapshot(self): mock_microversion = mock.Mock(api_version=version) manager = share_snapshots.ShareSnapshotManager(api=mock_microversion) - with mock.patch.object(manager, "_create", - mock.Mock(return_value="fake")): - - result = manager.manage(share_id, provider_location, - driver_options=driver_options, - name=name, description=description) + with mock.patch.object( + manager, "_create", mock.Mock(return_value="fake") + ): + result = manager.manage( + share_id, + provider_location, + driver_options=driver_options, + name=name, + description=description, + ) self.assertEqual(manager._create.return_value, result) manager._create.assert_called_once_with( - "/snapshots/manage", {"snapshot": expected_body}, "snapshot") + "/snapshots/manage", {"snapshot": expected_body}, "snapshot" + ) def test_unmanage_snapshot(self): snapshot = "fake_snapshot" @@ -185,8 +197,9 @@ def test_unmanage_snapshot(self): mock_microversion = mock.Mock(api_version=version) manager = share_snapshots.ShareSnapshotManager(api=mock_microversion) - with mock.patch.object(manager, "_action", - mock.Mock(return_value="fake")): + with mock.patch.object( + manager, "_action", mock.Mock(return_value="fake") + ): result = manager.unmanage(snapshot) manager._action.assert_called_once_with("unmanage", snapshot) @@ -202,13 +215,16 @@ def test_allow_access(self): mock_microversion = mock.Mock(api_version=version) manager = share_snapshots.ShareSnapshotManager(api=mock_microversion) - with mock.patch.object(manager, "_action", - mock.Mock(return_value=access)): + with mock.patch.object( + manager, "_action", mock.Mock(return_value=access) + ): result = manager.allow(snapshot, access_type, access_to) self.assertEqual("fake", result) manager._action.assert_called_once_with( - "allow_access", snapshot, - {'access_type': access_type, 'access_to': access_to}) + "allow_access", + snapshot, + {'access_type': access_type, 'access_to': access_to}, + ) def test_deny_access(self): snapshot = "fake_snapshot" @@ -221,7 +237,8 @@ def test_deny_access(self): with mock.patch.object(manager, "_action"): manager.deny(snapshot, access_id) manager._action.assert_called_once_with( - "deny_access", snapshot, {'access_id': access_id}) + "deny_access", snapshot, {'access_id': access_id} + ) def test_access_list(self): cs.share_snapshots.access_list(1234) @@ -233,23 +250,27 @@ def test_get_metadata(self): def test_set_metadata(self): cs.share_snapshots.set_metadata(1234, {'k1': 'v2'}) - cs.assert_called('POST', '/snapshots/1234/metadata', - {'metadata': {'k1': 'v2'}}) + cs.assert_called( + 'POST', '/snapshots/1234/metadata', {'metadata': {'k1': 'v2'}} + ) @ddt.data( - type('SnapshotUUID', (object, ), {'uuid': '1234'}), - type('SnapshotID', (object, ), {'id': '1234'}), - '1234') + type('SnapshotUUID', (object,), {'uuid': '1234'}), + type('SnapshotID', (object,), {'id': '1234'}), + '1234', + ) def test_delete_metadata(self, snapshot): keys = ['key1'] cs.share_snapshots.delete_metadata(snapshot, keys) cs.assert_called('DELETE', '/snapshots/1234/metadata/key1') @ddt.data( - type('SnapshotUUID', (object, ), {'uuid': '1234'}), - type('SnapshotID', (object, ), {'id': '1234'}), - '1234') + type('SnapshotUUID', (object,), {'uuid': '1234'}), + type('SnapshotID', (object,), {'id': '1234'}), + '1234', + ) def test_metadata_update_all(self, snapshot): cs.share_snapshots.update_all_metadata(snapshot, {'k1': 'v1'}) - cs.assert_called('PUT', '/snapshots/1234/metadata', - {'metadata': {'k1': 'v1'}}) + cs.assert_called( + 'PUT', '/snapshots/1234/metadata', {'metadata': {'k1': 'v1'}} + ) diff --git a/manilaclient/tests/unit/v2/test_share_transfers.py b/manilaclient/tests/unit/v2/test_share_transfers.py index 6cec52b5..54a6a640 100644 --- a/manilaclient/tests/unit/v2/test_share_transfers.py +++ b/manilaclient/tests/unit/v2/test_share_transfers.py @@ -22,29 +22,29 @@ class ShareTransfersTest(utils.TestCase): - def test_create(self): cs.transfers.create('1234') - cs.assert_called('POST', '/%s' % TRANSFER_URL, - body={'transfer': {'share_id': '1234', - 'name': None}}) + cs.assert_called( + 'POST', + f'/{TRANSFER_URL}', + body={'transfer': {'share_id': '1234', 'name': None}}, + ) def test_get(self): transfer_id = '5678' cs.transfers.get(transfer_id) - cs.assert_called('GET', '/%s/%s' % (TRANSFER_URL, transfer_id)) + cs.assert_called('GET', f'/{TRANSFER_URL}/{transfer_id}') def test_list(self): cs.transfers.list() - cs.assert_called('GET', '/%s/detail' % TRANSFER_URL) + cs.assert_called('GET', f'/{TRANSFER_URL}/detail') def test_delete(self): cs.transfers.delete('5678') - cs.assert_called('DELETE', '/%s/5678' % TRANSFER_URL) + cs.assert_called('DELETE', f'/{TRANSFER_URL}/5678') def test_accept(self): transfer_id = '5678' auth_key = '12345' cs.transfers.accept(transfer_id, auth_key) - cs.assert_called('POST', - '/%s/%s/accept' % (TRANSFER_URL, transfer_id)) + cs.assert_called('POST', f'/{TRANSFER_URL}/{transfer_id}/accept') diff --git a/manilaclient/tests/unit/v2/test_shares.py b/manilaclient/tests/unit/v2/test_shares.py index e5ce890c..038e202a 100644 --- a/manilaclient/tests/unit/v2/test_shares.py +++ b/manilaclient/tests/unit/v2/test_shares.py @@ -35,10 +35,9 @@ @ddt.ddt class SharesTest(utils.TestCase): - # Testcases for class Share def setUp(self): - super(SharesTest, self).setUp() + super().setUp() self.share = shares.Share(None, {'id': 1}) self.share.manager = mock.Mock() @@ -50,7 +49,8 @@ def test_share_allow_access(self): self.share.allow(access_type, access_to, access_level) self.share.manager.allow.assert_called_once_with( - self.share, access_type, access_to, access_level) + self.share, access_type, access_to, access_level + ) # Testcases for class ShareManager @@ -73,9 +73,10 @@ def test_create_share_with_protocol(self, protocol): cs.assert_called('POST', '/shares', {'share': expected}) @ddt.data( - type('ShareNetworkUUID', (object, ), {'uuid': 'fake_nw'}), - type('ShareNetworkID', (object, ), {'id': 'fake_nw'}), - 'fake_nw') + type('ShareNetworkUUID', (object,), {'uuid': 'fake_nw'}), + type('ShareNetworkID', (object,), {'id': 'fake_nw'}), + 'fake_nw', + ) def test_create_share_with_share_network(self, share_network): expected = { 'size': 1, @@ -94,9 +95,10 @@ def test_create_share_with_share_network(self, share_network): cs.assert_called('POST', '/shares', {'share': expected}) @ddt.data( - type('ShareTypeUUID', (object, ), {'uuid': 'fake_st'}), - type('ShareTypeID', (object, ), {'id': 'fake_st'}), - 'fake_st') + type('ShareTypeUUID', (object,), {'uuid': 'fake_st'}), + type('ShareTypeID', (object,), {'id': 'fake_st'}), + 'fake_st', + ) def test_create_share_with_share_type(self, share_type): expected = { 'size': 1, @@ -114,13 +116,14 @@ def test_create_share_with_share_type(self, share_type): cs.shares.create('nfs', 1, share_type=share_type) cs.assert_called('POST', '/shares', {'share': expected}) - @ddt.data({'is_public': True, - 'availability_zone': 'nova'}, - {'is_public': False, - 'availability_zone': 'fake_azzzzz'}) + @ddt.data( + {'is_public': True, 'availability_zone': 'nova'}, + {'is_public': False, 'availability_zone': 'fake_azzzzz'}, + ) @ddt.unpack - def test_create_share_with_all_params_defined(self, is_public, - availability_zone): + def test_create_share_with_all_params_defined( + self, is_public, availability_zone + ): body = { 'share': { 'is_public': is_public, @@ -136,12 +139,15 @@ def test_create_share_with_all_params_defined(self, is_public, 'scheduler_hints': {}, } } - cs.shares.create('nfs', 1, is_public=is_public, - availability_zone=availability_zone) + cs.shares.create( + 'nfs', 1, is_public=is_public, availability_zone=availability_zone + ) cs.assert_called('POST', '/shares', body) - @ddt.data({'mount_point_name': 'fake_mount_pt1'}, - {'mount_point_name': 'fake_mount_pt2'}) + @ddt.data( + {'mount_point_name': 'fake_mount_pt1'}, + {'mount_point_name': 'fake_mount_pt2'}, + ) @ddt.unpack def test_create_share_with_mount_point_name(self, mount_point_name): body = { @@ -164,17 +170,44 @@ def test_create_share_with_mount_point_name(self, mount_point_name): cs.assert_called('POST', '/shares', body) @ddt.data( - type('ShareUUID', (object, ), {'uuid': '1234'}), - type('ShareID', (object, ), {'id': '1234'}), - '1234') + {'encryption_key_ref': 'fake_key1'}, + {'encryption_key_ref': 'fake_key2'}, + ) + @ddt.unpack + def test_create_share_with_encryption_key_ref(self, encryption_key_ref): + body = { + 'share': { + 'is_public': False, + 'share_type': None, + 'name': None, + 'snapshot_id': None, + 'description': None, + 'metadata': {}, + 'share_proto': 'nfs', + 'share_network_id': None, + 'size': 1, + 'availability_zone': None, + 'scheduler_hints': {}, + 'encryption_key_ref': encryption_key_ref, + } + } + cs.shares.create('nfs', 1, encryption_key_ref=encryption_key_ref) + cs.assert_called('POST', '/shares', body) + + @ddt.data( + type('ShareUUID', (object,), {'uuid': '1234'}), + type('ShareID', (object,), {'id': '1234'}), + '1234', + ) def test_get_share(self, share): share = cs.shares.get(share) cs.assert_called('GET', '/shares/1234') @ddt.data( - type('ShareUUID', (object, ), {'uuid': '1234'}), - type('ShareID', (object, ), {'id': '1234'}), - '1234') + type('ShareUUID', (object,), {'uuid': '1234'}), + type('ShareID', (object,), {'id': '1234'}), + '1234', + ) def test_get_update(self, share): data = dict(foo='bar', quuz='foobar') share = cs.shares.update(share, **data) @@ -203,10 +236,17 @@ def test_restore_share(self): ("2.8", "/shares/manage", True), ("2.8", "/shares/manage", False), ("2.49", "/shares/manage", False, '1234'), + ("2.92", "/shares/manage", False, None, 'fake_mount_pt1'), ) @ddt.unpack - def test_manage_share(self, microversion, resource_path, is_public=False, - share_server_id=None): + def test_manage_share( + self, + microversion, + resource_path, + is_public=False, + share_server_id=None, + mount_point_name=None, + ): service_host = "fake_service_host" protocol = "fake_protocol" export_path = "fake_export_path" @@ -228,47 +268,96 @@ def test_manage_share(self, microversion, resource_path, is_public=False, if version >= api_versions.APIVersion('2.8'): expected_body["is_public"] = is_public + if version >= api_versions.APIVersion('2.92'): + expected_body["mount_point_name"] = mount_point_name + mock_microversion = mock.Mock(api_version=version) manager = shares.ShareManager(api=mock_microversion) - with mock.patch.object(manager, "_create", - mock.Mock(return_value="fake")): + with mock.patch.object( + manager, "_create", mock.Mock(return_value="fake") + ): if version < api_versions.APIVersion('2.8'): result = manager.manage( - service_host, protocol, export_path, driver_options, - share_type, name, description) - elif (api_versions.APIVersion('2.8') <= version - < api_versions.APIVersion('2.49')): + service_host, + protocol, + export_path, + driver_options, + share_type, + name, + description, + ) + elif ( + api_versions.APIVersion('2.8') + <= version + < api_versions.APIVersion('2.49') + ): + result = manager.manage( + service_host, + protocol, + export_path, + driver_options, + share_type, + name, + description, + is_public, + ) + elif ( + api_versions.APIVersion('2.49') + <= version + < api_versions.APIVersion('2.92') + ): result = manager.manage( - service_host, protocol, export_path, driver_options, - share_type, name, description, is_public) + service_host, + protocol, + export_path, + driver_options, + share_type, + name, + description, + is_public, + share_server_id, + ) else: result = manager.manage( - service_host, protocol, export_path, driver_options, - share_type, name, description, is_public, share_server_id) + service_host, + protocol, + export_path, + driver_options, + share_type, + name, + description, + is_public, + share_server_id, + mount_point_name, + ) self.assertEqual(manager._create.return_value, result) manager._create.assert_called_once_with( - resource_path, {"share": expected_body}, "share") + resource_path, {"share": expected_body}, "share" + ) @ddt.data( - type("ShareUUID", (object, ), {"uuid": "1234"}), - type("ShareID", (object, ), {"id": "1234"}), - "1234") + type("ShareUUID", (object,), {"uuid": "1234"}), + type("ShareID", (object,), {"id": "1234"}), + "1234", + ) def test_unmanage_share_v2_6(self, share): version = api_versions.APIVersion("2.6") mock_microversion = mock.Mock(api_version=version) manager = shares.ShareManager(api=mock_microversion) - with mock.patch.object(manager, "_action", - mock.Mock(return_value="fake")): + with mock.patch.object( + manager, "_action", mock.Mock(return_value="fake") + ): result = manager.unmanage(share) self.assertFalse(manager._action.called) self.assertNotEqual("fake", result) self.assertEqual(manager.api.client.post.return_value, result) manager.api.client.post.assert_called_once_with( - "/os-share-unmanage/1234/unmanage") + "/os-share-unmanage/1234/unmanage" + ) def test_unmanage_share_v2_7(self): share = "fake_share" @@ -276,41 +365,44 @@ def test_unmanage_share_v2_7(self): mock_microversion = mock.Mock(api_version=version) manager = shares.ShareManager(api=mock_microversion) - with mock.patch.object(manager, "_action", - mock.Mock(return_value="fake")): + with mock.patch.object( + manager, "_action", mock.Mock(return_value="fake") + ): result = manager.unmanage(share) manager._action.assert_called_once_with("unmanage", share) self.assertEqual("fake", result) def test_revert_to_snapshot(self): - share = 'fake_share' snapshot = 'fake_snapshot' version = api_versions.APIVersion("2.27") mock_microversion = mock.Mock(api_version=version) manager = shares.ShareManager(api=mock_microversion) mock_action = self.mock_object( - manager, '_action', mock.Mock(return_value='fake')) + manager, '_action', mock.Mock(return_value='fake') + ) result = manager.revert_to_snapshot(share, snapshot) self.assertEqual('fake', result) mock_action.assert_called_once_with( - 'revert', 'fake_share', info={'snapshot_id': 'fake_snapshot'}) + 'revert', 'fake_share', info={'snapshot_id': 'fake_snapshot'} + ) def test_revert_to_snapshot_not_supported(self): - share = 'fake_share' snapshot = 'fake_snapshot' version = api_versions.APIVersion("2.26") mock_microversion = mock.Mock(api_version=version) manager = shares.ShareManager(api=mock_microversion) - self.assertRaises(client_exceptions.UnsupportedVersion, - manager.revert_to_snapshot, - share, - snapshot) + self.assertRaises( + client_exceptions.UnsupportedVersion, + manager.revert_to_snapshot, + share, + snapshot, + ) @ddt.data( ("2.6", "os-force_delete"), @@ -323,8 +415,9 @@ def test_force_delete_share(self, microversion, action_name): mock_microversion = mock.Mock(api_version=version) manager = shares.ShareManager(api=mock_microversion) - with mock.patch.object(manager, "_action", - mock.Mock(return_value="fake")): + with mock.patch.object( + manager, "_action", mock.Mock(return_value="fake") + ): result = manager.force_delete(share) manager._action.assert_called_once_with(action_name, share) @@ -348,22 +441,35 @@ def test_list_shares_index_diff_api_version(self, microversion): 'is_soft_deleted': 'True', } - with mock.patch.object(manager, "do_list", - mock.Mock(return_value="fake")): + with mock.patch.object( + manager, "do_list", mock.Mock(return_value="fake") + ): manager.list(detailed=False, search_opts=search_opts3) if version >= api_versions.APIVersion('2.69'): manager.do_list.assert_called_once_with( - detailed=False, search_opts=search_opts3, - sort_key=None, sort_dir=None, return_raw=False) + detailed=False, + search_opts=search_opts3, + sort_key=None, + sort_dir=None, + return_raw=False, + ) elif version >= api_versions.APIVersion('2.35'): manager.do_list.assert_called_once_with( - detailed=False, search_opts=search_opts2, - sort_key=None, sort_dir=None, return_raw=False) + detailed=False, + search_opts=search_opts2, + sort_key=None, + sort_dir=None, + return_raw=False, + ) else: manager.do_list.assert_called_once_with( - detailed=False, search_opts=search_opts1, - sort_key=None, sort_dir=None, return_raw=False) + detailed=False, + search_opts=search_opts1, + sort_key=None, + sort_dir=None, + return_raw=False, + ) def test_list_shares_index_with_search_opts(self): search_opts = { @@ -376,27 +482,45 @@ def test_list_shares_index_with_search_opts(self): cs.assert_called( 'GET', '/shares?description~=fake_description&fake_int=1&' - 'fake_str=fake_str_value&is_public=True&name~=fake_name') + 'fake_str=fake_str_value&is_public=True&name~=fake_name', + ) - @ddt.data(('id', 'b4991315-eb7d-43ec-979e-5715d4399827', True), - ('id', 'b4991315-eb7d-43ec-979e-5715d4399827', False), - ('path', 'fake_path', False), - ('path', 'fake_path', True)) + @ddt.data( + ('id', 'b4991315-eb7d-43ec-979e-5715d4399827', True), + ('id', 'b4991315-eb7d-43ec-979e-5715d4399827', False), + ('path', 'fake_path', False), + ('path', 'fake_path', True), + ) @ddt.unpack - def test_list_shares_index_with_export_location(self, filter_type, - value, detailed): + def test_list_shares_index_with_export_location( + self, filter_type, value, detailed + ): search_opts = { 'export_location': value, } cs.shares.list(detailed=detailed, search_opts=search_opts) if detailed: cs.assert_called( - 'GET', ('/shares/detail?export_location_' + filter_type + - '=' + value + '&is_public=True')) + 'GET', + ( + '/shares/detail?export_location_' + + filter_type + + '=' + + value + + '&is_public=True' + ), + ) else: cs.assert_called( - 'GET', ('/shares?export_location_' + filter_type + '=' - + value + '&is_public=True')) + 'GET', + ( + '/shares?export_location_' + + filter_type + + '=' + + value + + '&is_public=True' + ), + ) @ddt.data(True, False) def test_list_shares_index_with_is_soft_deleted(self, detailed): @@ -406,12 +530,13 @@ def test_list_shares_index_with_is_soft_deleted(self, detailed): cs.shares.list(detailed=detailed, search_opts=search_opts) if detailed: cs.assert_called( - 'GET', ('/shares/detail?is_public=True' - + '&is_soft_deleted=True')) + 'GET', + ('/shares/detail?is_public=True' + '&is_soft_deleted=True'), + ) else: cs.assert_called( - 'GET', ('/shares?is_public=True' - + '&is_soft_deleted=True')) + 'GET', ('/shares?is_public=True' + '&is_soft_deleted=True') + ) def test_list_shares_detailed(self): search_opts = { @@ -419,7 +544,8 @@ def test_list_shares_detailed(self): } shares, count = cs.shares.list(detailed=True, search_opts=search_opts) cs.assert_called( - 'GET', '/shares/detail?is_public=True&with_count=True') + 'GET', '/shares/detail?is_public=True&with_count=True' + ) self.assertEqual(2, count) self.assertEqual(4, len(shares)) @@ -435,22 +561,26 @@ def test_list_shares_detailed_with_search_opts(self): cs.shares.list(detailed=True, search_opts=search_opts) cs.assert_called( 'GET', - '/shares/detail?fake_int=1&fake_str=fake_str_value&is_public=True') + '/shares/detail?fake_int=1&fake_str=fake_str_value&is_public=True', + ) def test_list_shares_sort_by_asc_and_host_key(self): cs.shares.list(detailed=False, sort_key='host', sort_dir='asc') - cs.assert_called('GET', - '/shares?is_public=True&sort_dir=asc&sort_key=host') + cs.assert_called( + 'GET', '/shares?is_public=True&sort_dir=asc&sort_key=host' + ) def test_list_shares_sort_by_desc_and_size_key(self): cs.shares.list(detailed=False, sort_key='size', sort_dir='desc') - cs.assert_called('GET', - '/shares?is_public=True&sort_dir=desc&sort_key=size') + cs.assert_called( + 'GET', '/shares?is_public=True&sort_dir=desc&sort_key=size' + ) def test_list_shares_filter_by_share_network_alias(self): cs.shares.list(detailed=False, sort_key='share_network') - cs.assert_called('GET', - '/shares?is_public=True&sort_key=share_network_id') + cs.assert_called( + 'GET', '/shares?is_public=True&sort_key=share_network_id' + ) def test_list_shares_filter_by_snapshot_alias(self): cs.shares.list(detailed=False, sort_key='snapshot') @@ -458,8 +588,9 @@ def test_list_shares_filter_by_snapshot_alias(self): def test_list_shares_filter_by_share_type_alias(self): cs.shares.list(detailed=False, sort_key='share_type') - cs.assert_called('GET', - '/shares?is_public=True&sort_key=share_type_id') + cs.assert_called( + 'GET', '/shares?is_public=True&sort_key=share_type_id' + ) def test_list_shares_by_improper_direction(self): self.assertRaises(ValueError, cs.shares.list, sort_dir='fake') @@ -468,54 +599,131 @@ def test_list_shares_by_improper_key(self): self.assertRaises(ValueError, cs.shares.list, sort_key='fake') @ddt.data( - {'access_to': '127.0.0.1', 'access_type': 'ip', - 'action_name': 'os-allow_access', 'microversion': '2.0'}, - {'access_to': '1' * 4, 'access_type': 'user', - 'action_name': 'os-allow_access', 'microversion': '2.0'}, - {'access_to': '1' * 255, 'access_type': 'user', - 'action_name': 'os-allow_access', 'microversion': '2.0'}, - {'access_to': 'fake${.-_\'`}', 'access_type': 'user', - 'action_name': 'os-allow_access', 'microversion': '2.0'}, - {'access_to': 'MYDOMAIN-Administrator', 'access_type': 'user', - 'action_name': 'os-allow_access', 'microversion': '2.0'}, - {'access_to': 'test group name', 'access_type': 'user', - 'action_name': 'os-allow_access', 'microversion': '2.0'}, - {'access_to': 'x', 'access_type': 'cert', - 'action_name': 'os-allow_access', 'microversion': '2.0'}, - {'access_to': 'x' * 64, 'access_type': 'cert', - 'action_name': 'os-allow_access', 'microversion': '2.0'}, - {'access_to': 'tenant.example.com', 'access_type': 'cert', - 'action_name': 'os-allow_access', 'microversion': '2.0'}, - {'access_to': '127.0.0.1', 'access_type': 'ip', - 'action_name': 'allow_access', 'microversion': '2.7'}, - {'access_to': 'test group name', 'access_type': 'user', - 'action_name': 'allow_access', 'microversion': '2.7'}, - {'access_to': 'alice', 'access_type': 'cephx', - 'action_name': 'allow_access', 'microversion': '2.13'}, - {'access_to': 'alice_bob', 'access_type': 'cephx', - 'action_name': 'allow_access', 'microversion': '2.13'}, - {'access_to': 'alice bob', 'access_type': 'cephx', - 'action_name': 'allow_access', 'microversion': '2.13'}, - {'access_to': 'test group name', 'access_type': 'user', - 'action_name': 'allow_access', 'microversion': '2.13'}, - {'access_to': 'AD80:0000:0000:0000:ABAA:0000:00C2:0002', - 'access_type': 'ip', 'action_name': 'allow_access', - 'microversion': '2.38'}, - {'access_to': 'AD80::/36', - 'access_type': 'ip', 'action_name': 'allow_access', - 'microversion': '2.38'}, - {'access_to': 'AD80:ABAA::/128', - 'access_type': 'ip', 'action_name': 'allow_access', - 'microversion': '2.38'}, - {'access_to': 'ad80::abaa:0:c2:2', - 'access_type': 'ip', 'action_name': 'allow_access', - 'microversion': '2.38'}, - {'access_to': 'test group name', 'access_type': 'user', - 'action_name': 'allow_access', 'microversion': '2.38'}, + { + 'access_to': '127.0.0.1', + 'access_type': 'ip', + 'action_name': 'os-allow_access', + 'microversion': '2.0', + }, + { + 'access_to': '1' * 4, + 'access_type': 'user', + 'action_name': 'os-allow_access', + 'microversion': '2.0', + }, + { + 'access_to': '1' * 255, + 'access_type': 'user', + 'action_name': 'os-allow_access', + 'microversion': '2.0', + }, + { + 'access_to': 'fake${.-_\'`}', + 'access_type': 'user', + 'action_name': 'os-allow_access', + 'microversion': '2.0', + }, + { + 'access_to': 'MYDOMAIN-Administrator', + 'access_type': 'user', + 'action_name': 'os-allow_access', + 'microversion': '2.0', + }, + { + 'access_to': 'test group name', + 'access_type': 'user', + 'action_name': 'os-allow_access', + 'microversion': '2.0', + }, + { + 'access_to': 'x', + 'access_type': 'cert', + 'action_name': 'os-allow_access', + 'microversion': '2.0', + }, + { + 'access_to': 'x' * 64, + 'access_type': 'cert', + 'action_name': 'os-allow_access', + 'microversion': '2.0', + }, + { + 'access_to': 'tenant.example.com', + 'access_type': 'cert', + 'action_name': 'os-allow_access', + 'microversion': '2.0', + }, + { + 'access_to': '127.0.0.1', + 'access_type': 'ip', + 'action_name': 'allow_access', + 'microversion': '2.7', + }, + { + 'access_to': 'test group name', + 'access_type': 'user', + 'action_name': 'allow_access', + 'microversion': '2.7', + }, + { + 'access_to': 'alice', + 'access_type': 'cephx', + 'action_name': 'allow_access', + 'microversion': '2.13', + }, + { + 'access_to': 'alice_bob', + 'access_type': 'cephx', + 'action_name': 'allow_access', + 'microversion': '2.13', + }, + { + 'access_to': 'alice bob', + 'access_type': 'cephx', + 'action_name': 'allow_access', + 'microversion': '2.13', + }, + { + 'access_to': 'test group name', + 'access_type': 'user', + 'action_name': 'allow_access', + 'microversion': '2.13', + }, + { + 'access_to': 'AD80:0000:0000:0000:ABAA:0000:00C2:0002', + 'access_type': 'ip', + 'action_name': 'allow_access', + 'microversion': '2.38', + }, + { + 'access_to': 'AD80::/36', + 'access_type': 'ip', + 'action_name': 'allow_access', + 'microversion': '2.38', + }, + { + 'access_to': 'AD80:ABAA::/128', + 'access_type': 'ip', + 'action_name': 'allow_access', + 'microversion': '2.38', + }, + { + 'access_to': 'ad80::abaa:0:c2:2', + 'access_type': 'ip', + 'action_name': 'allow_access', + 'microversion': '2.38', + }, + { + 'access_to': 'test group name', + 'access_type': 'user', + 'action_name': 'allow_access', + 'microversion': '2.38', + }, ) @ddt.unpack - def test_allow_access_to_share(self, access_to, access_type, - action_name, microversion): + def test_allow_access_to_share( + self, access_to, access_type, action_name, microversion + ): access = ('foo', {'access': 'bar'}) access_level = 'fake_access_level' share = 'fake_share' @@ -523,56 +731,69 @@ def test_allow_access_to_share(self, access_to, access_type, mock_microversion = mock.Mock(api_version=version) manager = shares.ShareManager(api=mock_microversion) - with mock.patch.object(manager, '_action', - mock.Mock(return_value=access)): + with mock.patch.object( + manager, '_action', mock.Mock(return_value=access) + ): result = manager.allow(share, access_type, access_to, access_level) manager._action.assert_called_once_with( - action_name, share, {'access_level': access_level, - 'access_type': access_type, - 'access_to': access_to}) + action_name, + share, + { + 'access_level': access_level, + 'access_type': access_type, + 'access_to': access_to, + }, + ) self.assertEqual('bar', result) @ddt.data( - {'access_to': 'localhost', 'access_type': 'ip', - 'microversion': '2.0'}, - {'access_to': '127.0.0.*', 'access_type': 'ip', - 'microversion': '2.0'}, - {'access_to': '127.0.0.0/33', 'access_type': 'ip', - 'microversion': '2.0'}, - {'access_to': '127.0.0.256', 'access_type': 'ip', - 'microversion': '2.0'}, - {'access_to': '1', 'access_type': 'user', - 'microversion': '2.0'}, - {'access_to': '1' * 3, 'access_type': 'user', - 'microversion': '2.0'}, - {'access_to': '1' * 256, 'access_type': 'user', - 'microversion': '2.0'}, - {'access_to': 'root+=', 'access_type': 'user', - 'microversion': '2.0'}, - {'access_to': '', 'access_type': 'cert', - 'microversion': '2.0'}, - {'access_to': ' ', 'access_type': 'cert', - 'microversion': '2.0'}, - {'access_to': 'x' * 65, 'access_type': 'cert', - 'microversion': '2.0'}, - {'access_to': 'alice', 'access_type': 'cephx', - 'microversion': '2.0'}, - {'access_to': '', 'access_type': 'cephx', - 'microversion': '2.13'}, - {'access_to': u"bj\u00F6rn", 'access_type': 'cephx', - 'microversion': '2.13'}, - {'access_to': "AD80:0000:0000:0000:ABAA:0000:00C2:0002/65", - 'access_type': 'ip', 'microversion': '2.38'}, - {'access_to': "AD80:0000:0000:0000:ABAA:0000:00C2:0002*32", - 'access_type': 'ip', 'microversion': '2.38'}, - {'access_to': "AD80:0000:0000:0000:ABAA:0000:00C2:0002", - 'access_type': 'ip', 'microversion': '2.37'}, + {'access_to': 'localhost', 'access_type': 'ip', 'microversion': '2.0'}, + {'access_to': '127.0.0.*', 'access_type': 'ip', 'microversion': '2.0'}, + { + 'access_to': '127.0.0.0/33', + 'access_type': 'ip', + 'microversion': '2.0', + }, + { + 'access_to': '127.0.0.256', + 'access_type': 'ip', + 'microversion': '2.0', + }, + {'access_to': '1', 'access_type': 'user', 'microversion': '2.0'}, + {'access_to': '1' * 3, 'access_type': 'user', 'microversion': '2.0'}, + {'access_to': '1' * 256, 'access_type': 'user', 'microversion': '2.0'}, + {'access_to': 'root+=', 'access_type': 'user', 'microversion': '2.0'}, + {'access_to': '', 'access_type': 'cert', 'microversion': '2.0'}, + {'access_to': ' ', 'access_type': 'cert', 'microversion': '2.0'}, + {'access_to': 'x' * 65, 'access_type': 'cert', 'microversion': '2.0'}, + {'access_to': 'alice', 'access_type': 'cephx', 'microversion': '2.0'}, + {'access_to': '', 'access_type': 'cephx', 'microversion': '2.13'}, + { + 'access_to': "bj\u00f6rn", + 'access_type': 'cephx', + 'microversion': '2.13', + }, + { + 'access_to': "AD80:0000:0000:0000:ABAA:0000:00C2:0002/65", + 'access_type': 'ip', + 'microversion': '2.38', + }, + { + 'access_to': "AD80:0000:0000:0000:ABAA:0000:00C2:0002*32", + 'access_type': 'ip', + 'microversion': '2.38', + }, + { + 'access_to': "AD80:0000:0000:0000:ABAA:0000:00C2:0002", + 'access_type': 'ip', + 'microversion': '2.37', + }, ) @ddt.unpack - def test_allow_access_to_share_error_invalid_access(self, access_to, - access_type, - microversion): + def test_allow_access_to_share_error_invalid_access( + self, access_to, access_type, microversion + ): access = ('foo', {'access': 'bar'}) access_level = 'fake_access_level' share = 'fake_share' @@ -580,10 +801,17 @@ def test_allow_access_to_share_error_invalid_access(self, access_to, mock_microversion = mock.Mock(api_version=version) manager = shares.ShareManager(api=mock_microversion) - with mock.patch.object(manager, '_action', - mock.Mock(return_value=access)): - self.assertRaises(exceptions.CommandError, manager.allow, - share, access_type, access_to, access_level) + with mock.patch.object( + manager, '_action', mock.Mock(return_value=access) + ): + self.assertRaises( + exceptions.CommandError, + manager.allow, + share, + access_type, + access_to, + access_level, + ) manager._action.assert_not_called() @@ -599,12 +827,14 @@ def test_deny_access_to_share(self, microversion, action_name): mock_microversion = mock.Mock(api_version=version) manager = shares.ShareManager(api=mock_microversion) - with mock.patch.object(manager, "_action", - mock.Mock(return_value="fake")): + with mock.patch.object( + manager, "_action", mock.Mock(return_value="fake") + ): result = manager.deny(share, access_id) manager._action.assert_called_once_with( - action_name, share, {"access_id": access_id}) + action_name, share, {"access_id": access_id} + ) self.assertEqual("fake", result) def test_get_metadata(self): @@ -613,26 +843,30 @@ def test_get_metadata(self): def test_set_metadata(self): cs.shares.set_metadata(1234, {'k1': 'v2'}) - cs.assert_called('POST', '/shares/1234/metadata', - {'metadata': {'k1': 'v2'}}) + cs.assert_called( + 'POST', '/shares/1234/metadata', {'metadata': {'k1': 'v2'}} + ) @ddt.data( - type('ShareUUID', (object, ), {'uuid': '1234'}), - type('ShareID', (object, ), {'id': '1234'}), - '1234') + type('ShareUUID', (object,), {'uuid': '1234'}), + type('ShareID', (object,), {'id': '1234'}), + '1234', + ) def test_delete_metadata(self, share): keys = ['key1'] cs.shares.delete_metadata(share, keys) cs.assert_called('DELETE', '/shares/1234/metadata/key1') @ddt.data( - type('ShareUUID', (object, ), {'uuid': '1234'}), - type('ShareID', (object, ), {'id': '1234'}), - '1234') + type('ShareUUID', (object,), {'uuid': '1234'}), + type('ShareID', (object,), {'id': '1234'}), + '1234', + ) def test_metadata_update_all(self, share): cs.shares.update_all_metadata(share, {'k1': 'v1'}) - cs.assert_called('PUT', '/shares/1234/metadata', - {'metadata': {'k1': 'v1'}}) + cs.assert_called( + 'PUT', '/shares/1234/metadata', {'metadata': {'k1': 'v1'}} + ) @ddt.data( ("2.6", "os-reset_status"), @@ -646,12 +880,14 @@ def test_reset_share_state(self, microversion, action_name): mock_microversion = mock.Mock(api_version=version) manager = shares.ShareManager(api=mock_microversion) - with mock.patch.object(manager, "_action", - mock.Mock(return_value="fake")): + with mock.patch.object( + manager, "_action", mock.Mock(return_value="fake") + ): result = manager.reset_state(share, state) manager._action.assert_called_once_with( - action_name, share, {"status": state}) + action_name, share, {"status": state} + ) self.assertEqual("fake", result) @ddt.data( @@ -667,17 +903,19 @@ def test_extend_share(self, microversion, action_name, force): mock_microversion = mock.Mock(api_version=version) manager = shares.ShareManager(api=mock_microversion) - with mock.patch.object(manager, "_action", - mock.Mock(return_value="fake")): + with mock.patch.object( + manager, "_action", mock.Mock(return_value="fake") + ): if not force: result = manager.extend(share, size) manager._action.assert_called_once_with( - action_name, share, {"new_size": size}) + action_name, share, {"new_size": size} + ) else: result = manager.extend(share, size, force=force) manager._action.assert_called_once_with( - action_name, share, {"new_size": size, - "force": "true"}) + action_name, share, {"new_size": size, "force": "true"} + ) self.assertEqual("fake", result) @ddt.data( @@ -692,16 +930,18 @@ def test_shrink_share(self, microversion, action_name): mock_microversion = mock.Mock(api_version=version) manager = shares.ShareManager(api=mock_microversion) - with mock.patch.object(manager, "_action", - mock.Mock(return_value="fake")): + with mock.patch.object( + manager, "_action", mock.Mock(return_value="fake") + ): result = manager.shrink(share, size) manager._action.assert_called_once_with( - action_name, share, {"new_size": size}) + action_name, share, {"new_size": size} + ) self.assertEqual("fake", result) def test_list_share_instances(self): - share = type('ShareID', (object, ), {'id': '1234'}) + share = type('ShareID', (object,), {'id': '1234'}) cs.shares.list_instances(share) cs.assert_called('GET', '/shares/1234/instances') @@ -710,16 +950,25 @@ def test_migration_start(self): host = "fake_host" version = api_versions.APIVersion('2.29') manager = shares.ShareManager( - api=fakes.FakeClient(api_version=version)) + api=fakes.FakeClient(api_version=version) + ) - with mock.patch.object(manager, "_action", - mock.Mock(return_value="fake")): + with mock.patch.object( + manager, "_action", mock.Mock(return_value="fake") + ): result = manager.migration_start( - share, host, force_host_assisted_migration=True, - preserve_metadata=True, writable=True, nondisruptive=True, - preserve_snapshots=True) + share, + host, + force_host_assisted_migration=True, + preserve_metadata=True, + writable=True, + nondisruptive=True, + preserve_snapshots=True, + ) manager._action.assert_called_once_with( - 'migration_start', share, { + 'migration_start', + share, + { "host": host, "force_host_assisted_migration": True, "preserve_metadata": True, @@ -728,7 +977,8 @@ def test_migration_start(self): "preserve_snapshots": True, "new_share_network_id": None, "new_share_type_id": None, - }) + }, + ) self.assertEqual("fake", result) @@ -736,24 +986,28 @@ def test_migration_complete(self): share = "fake_share" manager = shares.ShareManager(api=fakes.FakeClient()) - with mock.patch.object(manager, "_action", - mock.Mock(return_value="fake")): + with mock.patch.object( + manager, "_action", mock.Mock(return_value="fake") + ): result = manager.migration_complete(share) manager._action.assert_called_once_with( - "migration_complete", share) + "migration_complete", share + ) self.assertEqual("fake", result) def test_migration_get_progress(self): share = "fake_share" manager = shares.ShareManager(api=fakes.FakeClient()) - with mock.patch.object(manager, "_action", - mock.Mock(return_value="fake")): + with mock.patch.object( + manager, "_action", mock.Mock(return_value="fake") + ): result = manager.migration_get_progress(share) manager._action.assert_called_once_with( - "migration_get_progress", share) + "migration_get_progress", share + ) self.assertEqual("fake", result) def test_reset_task_state(self): @@ -761,22 +1015,24 @@ def test_reset_task_state(self): state = "fake_state" manager = shares.ShareManager(api=fakes.FakeClient()) - with mock.patch.object(manager, "_action", - mock.Mock(return_value="fake")): + with mock.patch.object( + manager, "_action", mock.Mock(return_value="fake") + ): result = manager.reset_task_state(share, state) manager._action.assert_called_once_with( - "reset_task_state", share, {'task_state': state}) + "reset_task_state", share, {'task_state': state} + ) self.assertEqual("fake", result) def test_migration_cancel(self): share = "fake_share" manager = shares.ShareManager(api=fakes.FakeClient()) - with mock.patch.object(manager, "_action", - mock.Mock(return_value="fake")): + with mock.patch.object( + manager, "_action", mock.Mock(return_value="fake") + ): result = manager.migration_cancel(share) - manager._action.assert_called_once_with( - "migration_cancel", share) + manager._action.assert_called_once_with("migration_cancel", share) self.assertEqual("fake", result) diff --git a/manilaclient/tests/unit/v2/test_shell.py b/manilaclient/tests/unit/v2/test_shell.py deleted file mode 100644 index 58e1dc65..00000000 --- a/manilaclient/tests/unit/v2/test_shell.py +++ /dev/null @@ -1,4175 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2013 OpenStack Foundation -# Copyright 2014 Mirantis, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import itertools -from unittest import mock - -import ddt -import fixtures -from oslo_utils import strutils - -from manilaclient import api_versions -from manilaclient import client -from manilaclient.common.apiclient import utils as apiclient_utils -from manilaclient.common import cliutils -from manilaclient.common import constants -from manilaclient import exceptions -from manilaclient import shell -from manilaclient.tests.unit import utils as test_utils -from manilaclient.tests.unit.v2 import fakes -from manilaclient import utils -from manilaclient.v2 import messages -from manilaclient.v2 import security_services -from manilaclient.v2 import share_access_rules -from manilaclient.v2 import share_group_types -from manilaclient.v2 import share_groups -from manilaclient.v2 import share_instances -from manilaclient.v2 import share_network_subnets -from manilaclient.v2 import share_networks -from manilaclient.v2 import share_servers -from manilaclient.v2 import share_snapshots -from manilaclient.v2 import share_types -from manilaclient.v2 import shares -from manilaclient.v2 import shell as shell_v2 - - -@ddt.ddt -class ShellTest(test_utils.TestCase): - - FAKE_ENV = { - 'MANILA_USERNAME': 'username', - 'MANILA_PASSWORD': 'password', - 'MANILA_PROJECT_ID': 'project_id', - 'MANILA_URL': 'http://no.where', - } - - # Patch os.environ to avoid required auth info. - def setUp(self): - """Run before each test.""" - super(ShellTest, self).setUp() - for var in self.FAKE_ENV: - self.useFixture(fixtures.EnvironmentVariable(var, - self.FAKE_ENV[var])) - self.mock_completion() - - self.shell = shell.OpenStackManilaShell() - - # HACK(bcwaldon): replace this when we start using stubs - self.old_get_client_class = client.get_client_class - client.get_client_class = lambda *_: fakes.FakeClient - - # Following shows available separators for optional params - # and its values - self.separators = [' ', '='] - self.create_share_body = { - "share": { - "share_type": None, - "name": None, - "snapshot_id": None, - "description": None, - "metadata": {}, - "share_proto": "nfs", - "share_network_id": None, - "size": 1, - "is_public": False, - "availability_zone": None, - "scheduler_hints": {}, - } - } - - def tearDown(self): - # For some method like test_image_meta_bad_action we are - # testing a SystemExit to be thrown and object self.shell has - # no time to get instantatiated which is OK in this case, so - # we make sure the method is there before launching it. - if hasattr(self.shell, 'cs') and hasattr(self.shell.cs, - 'clear_callstack'): - self.shell.cs.clear_callstack() - - # HACK(bcwaldon): replace this when we start using stubs - client.get_client_class = self.old_get_client_class - super(ShellTest, self).tearDown() - - def run_command(self, cmd, version=None): - if version: - args = ['--os-share-api-version', version] + cmd.split() - else: - args = cmd.split() - self.shell.main(args) - - def assert_called(self, method, url, body=None, **kwargs): - return self.shell.cs.assert_called(method, url, body, **kwargs) - - def assert_called_anytime(self, method, url, body=None, - clear_callstack=True): - return self.shell.cs.assert_called_anytime( - method, url, body, clear_callstack=clear_callstack) - - def test_availability_zone_list(self): - self.run_command('availability-zone-list') - self.assert_called('GET', '/availability-zones') - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_availability_zone_list_select_column(self): - self.run_command('availability-zone-list --columns id,name') - self.assert_called('GET', '/availability-zones') - cliutils.print_list.assert_called_once_with( - mock.ANY, fields=['Id', 'Name']) - - def test_service_list(self): - self.run_command('service-list') - self.assert_called('GET', '/services') - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_service_list_select_column(self): - self.run_command('service-list --columns id,host') - self.assert_called('GET', '/services') - cliutils.print_list.assert_called_once_with( - mock.ANY, fields=['Id', 'Host']) - - def test_service_enable(self): - self.run_command('service-enable foo_host@bar_backend manila-share') - self.assert_called( - 'PUT', - '/services/enable', - {'host': 'foo_host@bar_backend', 'binary': 'manila-share'}) - - def test_service_disable(self): - self.run_command('service-disable foo_host@bar_backend manila-share') - self.assert_called( - 'PUT', - '/services/disable', - {'host': 'foo_host@bar_backend', 'binary': 'manila-share'}) - - def test_list(self): - self.run_command('list') - # NOTE(jdg): we default to detail currently - self.assert_called('GET', '/shares/detail') - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_list_select_column(self): - self.run_command('list --column id,name') - self.assert_called('GET', '/shares/detail') - cliutils.print_list.assert_called_once_with( - mock.ANY, - ['Id', 'Name'], sortby_index=None) - - def test_list_sort_by_name(self): - self.run_command('list --sort_key name') - self.assert_called('GET', '/shares/detail?sort_key=name') - - def test_list_filter_status(self): - for separator in self.separators: - self.run_command('list --status' + separator + 'available') - self.assert_called('GET', '/shares/detail?status=available') - - def test_list_filter_name(self): - for separator in self.separators: - self.run_command('list --name' + separator + '1234') - self.assert_called('GET', '/shares/detail?name=1234') - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_list_all_tenants_only_key(self): - self.run_command('list --all-tenants') - self.assert_called('GET', '/shares/detail?all_tenants=1') - cliutils.print_list.assert_called_once_with( - mock.ANY, - ['ID', 'Name', 'Size', 'Share Proto', 'Status', 'Is Public', - 'Share Type Name', 'Host', 'Availability Zone', 'Project ID'], - sortby_index=None) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_list_select_column_and_all_tenants(self): - self.run_command('list --columns ID,Name --all-tenants') - self.assert_called('GET', '/shares/detail?all_tenants=1') - cliutils.print_list.assert_called_once_with( - mock.ANY, - ['Id', 'Name'], sortby_index=None) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_list_select_column_and_public(self): - self.run_command('list --columns ID,Name --public') - self.assert_called('GET', '/shares/detail?is_public=True') - cliutils.print_list.assert_called_once_with( - mock.ANY, - ['Id', 'Name'], sortby_index=None) - - def test_list_all_tenants_key_and_value_1(self): - for separator in self.separators: - self.run_command('list --all-tenants' + separator + '1') - self.assert_called('GET', '/shares/detail?all_tenants=1') - - def test_list_all_tenants_key_and_value_0(self): - for separator in self.separators: - self.run_command('list --all-tenants' + separator + '0') - self.assert_called('GET', '/shares/detail') - - def test_list_filter_by_share_server_and_its_aliases(self): - aliases = [ - '--share-server-id', '--share-server_id', - '--share_server-id', '--share_server_id', - ] - for alias in aliases: - for separator in self.separators: - self.run_command('list ' + alias + separator + '1234') - self.assert_called( - 'GET', '/shares/detail?share_server_id=1234') - - def test_list_filter_by_metadata(self): - self.run_command('list --metadata key=value') - # /shares/detail?metadata={'key': 'value'} - self.assert_called( - 'GET', '/shares/detail?metadata=' - '%7B%27key%27%3A+%27value%27%7D') - - def test_list_filter_by_metadata_with_multiple_key_values(self): - self.run_command('list --metadata key1=value1 ' - 'key2=value2 key3=value3') - # /shares/detail?metadata={'key1': 'value1', - # 'key2': 'value2', 'key3': 'value3'} - self.assert_called( - 'GET', '/shares/detail?metadata=' - '%7B%27key1%27%3A+%27value1%27%2C+%27key2%27%3A+' - '%27value2%27%2C+%27key3%27%3A+%27value3%27%7D') - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_list_filter_by_metadata_with_empty_metadata(self): - self.run_command('list --metadata \'\'') - - self.assert_called( - 'GET', '/shares/detail') - cliutils.print_list.assert_called() - args, _ = cliutils.print_list.call_args - shares = args[0] - # All 4 shares irrespective of metadata values printed - self.assertEqual(len(shares), 4) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_list_filter_by_metadata_set_to_None(self): - self.run_command('list --metadata None') - - self.assert_called( - 'GET', '/shares/detail') - cliutils.print_list.assert_called() - args, _ = cliutils.print_list.call_args - shares = args[0] - # Check that the size of shares is 2(shares with metadata={}) - self.assertEqual(len(shares), 2) - for share in shares: - self.assertEqual(share.metadata, {}) - - def test_list_filter_by_metadata_with_one_empty_of_many_metadata(self): - self.run_command('list --metadata key=value \'\'') - # /shares/detail?metadata={'key': 'value'} - self.assert_called( - 'GET', '/shares/detail?metadata=' - '%7B%27key%27%3A+%27value%27%7D') - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_list_filter_by_metadata_with_no_metadata(self): - self.run_command('list --metadata') - # /shares/detail - self.assert_called( - 'GET', '/shares/detail') - cliutils.print_list.assert_called() - args, _ = cliutils.print_list.call_args - shares = args[0] - # All 4 shares printed - self.assertEqual(len(shares), 4) - - def test_list_filter_by_extra_specs_and_its_aliases(self): - aliases = ['--extra-specs', '--extra_specs', ] - for alias in aliases: - self.run_command('list ' + alias + ' key=value') - self.assert_called( - 'GET', - '/shares/detail?extra_specs=%7B%27key%27%3A+%27value%27%7D', - ) - - def test_list_filter_by_share_type_and_its_aliases(self): - fake_st = type('Empty', (object,), {'id': 'fake_st'}) - aliases = [ - '--share-type', '--share_type', '--share-type-id', - '--share-type_id', '--share_type-id', '--share_type_id', - ] - for alias in aliases: - for separator in self.separators: - with mock.patch.object( - apiclient_utils, - 'find_resource', - mock.Mock(return_value=fake_st)): - self.run_command('list ' + alias + separator + fake_st.id) - self.assert_called( - 'GET', '/shares/detail?share_type_id=' + fake_st.id) - - def test_list_filter_by_inexact_name(self): - for separator in self.separators: - self.run_command('list --name~' + separator + - 'fake_name') - self.assert_called( - 'GET', - '/shares/detail?name~=fake_name') - - def test_list_filter_by_inexact_description(self): - for separator in self.separators: - self.run_command('list --description~' + separator + - 'fake_description') - self.assert_called( - 'GET', - '/shares/detail?description~=fake_description') - - def test_list_filter_by_inexact_unicode_name(self): - for separator in self.separators: - self.run_command('list --name~' + separator + - u'ффф') - self.assert_called( - 'GET', - '/shares/detail?name~=%D1%84%D1%84%D1%84') - - def test_list_filter_by_inexact_unicode_description(self): - for separator in self.separators: - self.run_command('list --description~' + separator + - u'ффф') - self.assert_called( - 'GET', - '/shares/detail?description~=%D1%84%D1%84%D1%84') - - def test_list_filter_by_share_type_not_found(self): - for separator in self.separators: - self.assertRaises( - exceptions.CommandError, - self.run_command, - 'list --share-type' + separator + 'not_found_expected', - ) - self.assert_called('GET', '/types?all_tenants=1&is_public=all') - - def test_list_with_limit(self): - for separator in self.separators: - self.run_command('list --limit' + separator + '50') - self.assert_called('GET', '/shares/detail?limit=50') - - def test_list_with_offset(self): - for separator in self.separators: - self.run_command('list --offset' + separator + '50') - self.assert_called('GET', '/shares/detail?offset=50') - - def test_list_with_sort_dir_verify_keys(self): - # Verify allowed aliases and keys - aliases = ['--sort_dir', '--sort-dir'] - for alias in aliases: - for key in constants.SORT_DIR_VALUES: - for separator in self.separators: - self.run_command('list ' + alias + separator + key) - self.assert_called('GET', '/shares/detail?sort_dir=' + key) - - def test_list_with_fake_sort_dir(self): - self.assertRaises( - ValueError, - self.run_command, - 'list --sort-dir fake_sort_dir', - ) - - def test_list_with_sort_key_verify_keys(self): - # Verify allowed aliases and keys - aliases = ['--sort_key', '--sort-key'] - for alias in aliases: - for key in constants.SHARE_SORT_KEY_VALUES: - for separator in self.separators: - self.run_command('list ' + alias + separator + key) - key = 'share_network_id' if key == 'share_network' else key - key = 'snapshot_id' if key == 'snapshot' else key - key = 'share_type_id' if key == 'share_type' else key - key = ('availability_zone_id' if key == 'availability_zone' - else key) - self.assert_called('GET', '/shares/detail?sort_key=' + key) - - def test_list_with_fake_sort_key(self): - self.assertRaises( - ValueError, - self.run_command, - 'list --sort-key fake_sort_key', - ) - - def test_list_filter_by_snapshot(self): - fake_s = type('Empty', (object,), {'id': 'fake_snapshot_id'}) - for separator in self.separators: - with mock.patch.object( - apiclient_utils, - 'find_resource', - mock.Mock(return_value=fake_s)): - self.run_command('list --snapshot' + separator + fake_s.id) - self.assert_called( - 'GET', '/shares/detail?snapshot_id=' + fake_s.id) - - def test_list_filter_by_snapshot_not_found(self): - self.assertRaises( - exceptions.CommandError, - self.run_command, - 'list --snapshot not_found_expected', - ) - self.assert_called('GET', '/snapshots/detail?all_tenants=1') - - def test_list_filter_by_host(self): - for separator in self.separators: - self.run_command('list --host' + separator + 'fake_host') - self.assert_called('GET', '/shares/detail?host=fake_host') - - @ddt.data(('id', 'b4991315-eb7d-43ec-979e-5715d4399827'), - ('path', 'fake_path')) - @ddt.unpack - def test_share_list_filter_by_export_location(self, filter_type, value): - for separator in self.separators: - self.run_command('list --export_location' + separator + value) - self.assert_called( - 'GET', - '/shares/detail?export_location_' + filter_type + '=' + value) - - @ddt.data('list', 'share-instance-list') - def test_share_or_instance_list_filter_by_export_location_version_invalid( - self, cmd): - self.assertRaises( - exceptions.CommandError, - self.run_command, - cmd + ' --export_location=fake', - '2.34' - ) - - def test_list_filter_by_share_network(self): - aliases = ['--share-network', '--share_network', ] - fake_sn = type('Empty', (object,), {'id': 'fake_share_network_id'}) - for alias in aliases: - for separator in self.separators: - with mock.patch.object( - apiclient_utils, - 'find_resource', - mock.Mock(return_value=fake_sn)): - self.run_command('list ' + alias + separator + fake_sn.id) - self.assert_called( - 'GET', '/shares/detail?share_network_id=' + fake_sn.id) - - def test_list_filter_by_share_network_not_found(self): - self.assertRaises( - exceptions.CommandError, - self.run_command, - 'list --share-network not_found_expected', - ) - self.assert_called('GET', '/share-networks/detail?all_tenants=1') - - @ddt.data('True', 'False') - def test_list_filter_with_count(self, value): - except_url = '/shares/detail?with_count=' + value - if value == 'False': - except_url = '/shares/detail' - - for separator in self.separators: - self.run_command('list --count' + separator + value) - self.assert_called('GET', except_url) - - @ddt.data('True', 'False') - def test_list_filter_with_count_invalid_version(self, value): - self.assertRaises( - exceptions.CommandError, - self.run_command, - 'list --count ' + value, - version='2.41' - ) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_share_instance_list(self): - self.run_command('share-instance-list') - - self.assert_called('GET', '/share_instances') - cliutils.print_list.assert_called_once_with( - mock.ANY, - ['ID', 'Share ID', 'Host', 'Status', 'Availability Zone', - 'Share Network ID', 'Share Server ID', 'Share Type ID']) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_share_instance_list_select_column(self): - self.run_command('share-instance-list --column id,host,status') - - self.assert_called('GET', '/share_instances') - cliutils.print_list.assert_called_once_with( - mock.ANY, - ['Id', 'Host', 'Status']) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - @ddt.data(('id', 'b4991315-eb7d-43ec-979e-5715d4399827'), - ('path', 'fake_path')) - @ddt.unpack - def test_share_instance_list_filter_by_export_location(self, filter_type, - value): - for separator in self.separators: - self.run_command('share-instance-list --export_location' + - separator + value) - self.assert_called( - 'GET', - ('/share_instances?export_location_' + - filter_type + '=' + value)) - - @mock.patch.object(apiclient_utils, 'find_resource', - mock.Mock(return_value='fake')) - def test_share_instance_list_with_share(self): - self.run_command('share-instance-list --share-id=fake') - self.assert_called('GET', '/shares/fake/instances') - - def test_share_instance_list_invalid_share(self): - self.assertRaises( - exceptions.CommandError, - self.run_command, - 'share-instance-list --share-id=not-found-id', - ) - - def test_share_instance_show(self): - self.run_command('share-instance-show 1234') - self.assert_called_anytime('GET', '/share_instances/1234') - - def test_share_instance_export_location_list(self): - self.run_command('share-instance-export-location-list 1234') - - self.assert_called_anytime( - 'GET', '/share_instances/1234/export_locations') - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_share_instance_export_location_list_with_columns(self): - self.run_command( - 'share-instance-export-location-list 1234 --columns uuid,path') - - self.assert_called_anytime( - 'GET', '/share_instances/1234/export_locations') - cliutils.print_list.assert_called_once_with(mock.ANY, ['Uuid', 'Path']) - - def test_share_instance_export_location_show(self): - self.run_command( - 'share-instance-export-location-show 1234 fake_el_uuid') - self.assert_called_anytime( - 'GET', '/share_instances/1234/export_locations/fake_el_uuid') - - def test_share_instance_reset_state(self): - self.run_command('share-instance-reset-state 1234') - expected = {'reset_status': {'status': 'available'}} - self.assert_called('POST', '/share_instances/1234/action', - body=expected) - - def test_share_instance_force_delete(self): - manager_mock = mock.Mock() - share_instance = share_instances.ShareInstance( - manager_mock, {'id': 'fake'}, True) - - with mock.patch.object(shell_v2, '_find_share_instance', - mock.Mock(return_value=share_instance)): - self.run_command('share-instance-force-delete 1234') - manager_mock.force_delete.assert_called_once_with(share_instance) - - @ddt.data(('share_instance_xyz', ), ('share_instance_abc', - 'share_instance_xyz')) - def test_share_instance_force_delete_wait(self, instances_to_delete): - fake_manager = mock.Mock() - fake_instances = [ - share_instances.ShareInstance(fake_manager, {'id': '1234'}) - for instance in instances_to_delete - ] - instance_not_found_error = ("Delete for instance %s failed: No " - "instance with a name or " - "ID of '%s' exists.") - instances_are_not_found_errors = [ - exceptions.CommandError( - instance_not_found_error % (instance, instance)) - for instance in instances_to_delete - ] - self.mock_object( - shell_v2, '_find_share_instance', - mock.Mock(side_effect=( - fake_instances + instances_are_not_found_errors))) - self.run_command( - 'share-instance-force-delete %s --wait' % ' '.join( - instances_to_delete)) - shell_v2._find_share_instance.assert_has_calls([ - mock.call(self.shell.cs, instance) for instance in - instances_to_delete - ]) - fake_manager.force_delete.assert_has_calls([ - mock.call(instance) for instance in fake_instances]) - self.assertEqual(len(instances_to_delete), - fake_manager.force_delete.call_count) - - def test_type_show_details(self): - self.run_command('type-show 1234') - self.assert_called_anytime('GET', '/types/1234') - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - @ddt.data(*itertools.product( - ('type-list --columns id,is_default', 'type-list --columns id,name', - 'type-list --columns is_default', 'type-list'), - {'2.45', '2.46', api_versions.MAX_VERSION})) - @ddt.unpack - def test_type_list(self, command, version): - self.run_command(command, version=version) - - columns_requested = ['ID', 'Name', 'visibility', - 'is_default', 'required_extra_specs', - 'optional_extra_specs', 'Description'] - if 'columns' in command: - columns_requested = command.split('--columns ')[1].split(',') - - is_default_in_api = (api_versions.APIVersion(version) >= - api_versions.APIVersion('2.46')) - - if not is_default_in_api and 'is_default' in columns_requested: - self.assert_called('GET', '/types/default') - self.assert_called_anytime('GET', '/types') - else: - self.assert_called('GET', '/types') - - cliutils.print_list.assert_called_with( - mock.ANY, columns_requested, mock.ANY) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_type_list_select_column(self): - self.run_command('type-list --columns id,name') - - self.assert_called('GET', '/types') - cliutils.print_list.assert_called_once_with( - mock.ANY, - ['id', 'name'], - mock.ANY) - - def test_type_list_all(self): - self.run_command('type-list --all') - self.assert_called_anytime('GET', '/types?is_public=all') - - @ddt.data(True, False) - def test_type_create_with_access(self, public): - expected = { - 'share_type': { - 'name': 'test-type-3', - 'extra_specs': { - 'driver_handles_share_servers': False, - }, - 'share_type_access:is_public': public - } - } - self.run_command( - 'type-create test-type-3 false --is-public %s' % - str(public)) - self.assert_called('POST', '/types', body=expected) - - def test_type_access_list(self): - self.run_command('type-access-list 3') - self.assert_called('GET', '/types/3/share_type_access') - - def test_type_access_add_project(self): - expected = {'addProjectAccess': {'project': '101'}} - self.run_command('type-access-add 3 101') - self.assert_called('POST', '/types/3/action', body=expected) - - def test_type_access_remove_project(self): - expected = {'removeProjectAccess': {'project': '101'}} - self.run_command('type-access-remove 3 101') - self.assert_called('POST', '/types/3/action', body=expected) - - def test_list_filter_by_project_id(self): - aliases = ['--project-id', '--project_id'] - for alias in aliases: - for separator in self.separators: - self.run_command('list ' + alias + separator + 'fake_id') - self.assert_called('GET', '/shares/detail?project_id=fake_id') - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_list_with_public_shares(self): - listed_fields = [ - 'ID', - 'Name', - 'Size', - 'Share Proto', - 'Status', - 'Is Public', - 'Share Type Name', - 'Host', - 'Availability Zone', - 'Project ID' - ] - self.run_command('list --public') - self.assert_called('GET', '/shares/detail?is_public=True') - cliutils.print_list.assert_called_with(mock.ANY, listed_fields, - sortby_index=None) - - def test_show(self): - self.run_command('show 1234') - self.assert_called_anytime('GET', '/shares/1234') - - def test_share_export_location_list(self): - self.run_command('share-export-location-list 1234') - self.assert_called_anytime( - 'GET', '/shares/1234/export_locations') - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_share_export_location_list_with_columns(self): - self.run_command('share-export-location-list 1234 --columns uuid,path') - - self.assert_called_anytime( - 'GET', '/shares/1234/export_locations') - cliutils.print_list.assert_called_once_with(mock.ANY, ['Uuid', 'Path']) - - def test_share_export_location_show(self): - self.run_command('share-export-location-show 1234 fake_el_uuid') - self.assert_called_anytime( - 'GET', '/shares/1234/export_locations/fake_el_uuid') - - @ddt.data({'cmd_args': '--driver_options opt1=opt1 opt2=opt2' - ' --share_type fake_share_type', - 'valid_params': { - 'driver_options': {'opt1': 'opt1', 'opt2': 'opt2'}, - 'share_type': 'fake_share_type', - 'share_server_id': None, - }}, - {'cmd_args': '--share_type fake_share_type', - 'valid_params': { - 'driver_options': {}, - 'share_type': 'fake_share_type', - 'share_server_id': None, - }}, - {'cmd_args': '', - 'valid_params': { - 'driver_options': {}, - 'share_type': None, - 'share_server_id': None, - }}, - {'cmd_args': '--public' - ' --wait', - 'valid_params': { - 'driver_options': {}, - 'share_type': None, - 'share_server_id': None, - }, - 'is_public': True, - 'version': '--os-share-api-version 2.8', - }, - {'cmd_args': '', - 'valid_params': { - 'driver_options': {}, - 'share_type': None, - 'share_server_id': None, - }, - 'is_public': False, - 'version': '--os-share-api-version 2.8', - }, - {'cmd_args': '--driver_options opt1=opt1 opt2=opt2' - ' --share_type fake_share_type' - ' --wait', - 'valid_params': { - 'driver_options': {'opt1': 'opt1', 'opt2': 'opt2'}, - 'share_type': 'fake_share_type', - 'share_server_id': None, - }, - 'version': '--os-share-api-version 2.49', - }, - {'cmd_args': '--driver_options opt1=opt1 opt2=opt2' - ' --share_type fake_share_type' - ' --share_server_id fake_server', - 'valid_params': { - 'driver_options': {'opt1': 'opt1', 'opt2': 'opt2'}, - 'share_type': 'fake_share_type', - 'share_server_id': 'fake_server', - }, - 'version': '--os-share-api-version 2.49', - }, - {'cmd_args': '--driver_options opt1=opt1 opt2=opt2' - ' --share_type fake_share_type' - ' --share_server_id fake_server' - ' --wait', - 'valid_params': { - 'driver_options': {'opt1': 'opt1', 'opt2': 'opt2'}, - 'share_type': 'fake_share_type', - 'share_server_id': 'fake_server', - }}, - ) - @ddt.unpack - def test_manage(self, cmd_args, valid_params, is_public=False, - version=None): - share_to_be_managed = shares.Share( - 'fake_share', { - 'id': 'fake' - } - ) - self.mock_object( - shell_v2, '_wait_for_resource_status', - mock.Mock(return_value=share_to_be_managed) - ) - - if version is not None: - self.run_command(version - + ' manage fake_service fake_protocol ' - + ' fake_export_path ' - + cmd_args) - else: - self.run_command(' manage fake_service fake_protocol ' - + ' fake_export_path ' - + cmd_args) - expected = { - 'share': { - 'service_host': 'fake_service', - 'protocol': 'fake_protocol', - 'export_path': 'fake_export_path', - 'name': None, - 'description': None, - 'is_public': is_public, - 'share_server_id': valid_params['share_server_id'], - } - } - expected['share'].update(valid_params) - - self.assert_called('POST', '/shares/manage', body=expected) - - if '--wait' in cmd_args: - shell_v2._wait_for_resource_status.assert_called_once_with( - self.shell.cs, share_to_be_managed, resource_type='share', - expected_status='available') - else: - shell_v2._wait_for_resource_status.assert_not_called() - - def test_manage_invalid_param_share_server_id(self): - self.assertRaises( - exceptions.CommandError, - self.run_command, - '--os-share-api-version 2.48' - + ' manage fake_service fake_protocol ' - + ' fake_export_path ' - + ' --driver_options opt1=opt1 opt2=opt2' - + ' --share_type fake_share_type' - + ' --share_server_id fake_server') - - def test_share_server_manage_unsupported_version(self): - self.assertRaises( - exceptions.UnsupportedVersion, - self.run_command, - '--os-share-api-version 2.48 ' + - 'share-server-manage fake_host fake_share_net_id fake_id') - - def test_share_server_manage_invalid_param_subnet_id(self): - self.assertRaises( - exceptions.CommandError, - self.run_command, - '--os-share-api-version 2.49 ' + - 'share-server-manage fake_host fake_share_net_id fake_id ' + - '--share-network-subnet fake_subnet_id') - - @ddt.data({'driver_args': '--driver_options opt1=opt1 opt2=opt2', - 'valid_params': { - 'driver_options': {'opt1': 'opt1', 'opt2': 'opt2'}, - }}, - {'driver_args': '--driver_options opt1=opt1 opt2=opt2', - 'subnet_id': 'fake_subnet_1', - 'valid_params': { - 'driver_options': {'opt1': 'opt1', 'opt2': 'opt2'}, - }}, - {'driver_args': '--driver_options opt1=opt1 opt2=opt2', - 'valid_params': { - 'driver_options': {'opt1': 'opt1', 'opt2': 'opt2'}, - }, - 'version': '2.51', - }, - {'driver_args': '--driver_options opt1=opt1 opt2=opt2', - 'subnet_id': 'fake_subnet_1', - 'valid_params': { - 'driver_options': {'opt1': 'opt1', 'opt2': 'opt2'}, - }, - 'version': '2.51', - }, - {'driver_args': "", - 'valid_params': { - 'driver_options': {} - }, - 'version': '2.51', - }, - {'driver_args': '--driver_options opt1=opt1 opt2=opt2', - 'valid_params': { - 'driver_options': {'opt1': 'opt1', 'opt2': 'opt2'}, - }, - 'version': '2.49', - }, - {'driver_args': '', - 'valid_params': { - 'driver_options': {}, - }, - 'network_id': 'fake_network_id', - 'version': '2.49', - }, - {'driver_args': "", - 'valid_params': { - 'driver_options': {} - }, - 'version': '2.49', - }, - ) - @ddt.unpack - def test_share_server_manage_wait(self, driver_args, valid_params, - version=None, network_id=None, - subnet_id=None): - fake_manager = mock.Mock() - subnet_support = (version is None or - api_versions.APIVersion(version) >= - api_versions.APIVersion('2.51')) - - network_id = '3456' if network_id is None else network_id - fake_share_network = share_networks.ShareNetwork( - fake_manager, {'id': network_id, 'uuid': network_id}) - self.mock_object( - shell_v2, '_find_share_network', - mock.Mock(return_value=fake_share_network)) - fake_share_server = share_servers.ShareServer( - fake_manager, {'id': 'fake'}) - self.mock_object( - shell_v2, '_find_share_server', - mock.Mock(return_value=fake_share_server)) - - self.mock_object( - shell_v2, '_wait_for_resource_status', - mock.Mock() - ) - command = ('share-server-manage ' - '%(host)s ' - '%(share_network_id)s ' - '%(identifier)s ' - '%(driver_args)s ' % { - 'host': 'fake_host', - 'share_network_id': fake_share_network.id, - 'identifier': '88-as-23-f3-45', - 'driver_args': driver_args, - }) - command += '--share-network-subnet %s' % subnet_id if subnet_id else '' - - self.run_command(command, version=version) - - expected = { - 'share_server': { - 'host': 'fake_host', - 'share_network_id': fake_share_network.id, - 'identifier': '88-as-23-f3-45', - 'driver_options': driver_args - } - } - if subnet_support: - expected['share_server']['share_network_subnet_id'] = subnet_id - expected['share_server'].update(valid_params) - - self.assert_called('POST', '/share-servers/manage', body=expected) - - shell_v2._wait_for_resource_status.assert_has_calls([ - mock.call(self.shell.cs, fake_share_server, - resource_type='share_server', expected_status='active') - ]) - - @ddt.data(constants.STATUS_ERROR, constants.STATUS_ACTIVE, - constants.STATUS_MANAGE_ERROR, constants.STATUS_UNMANAGE_ERROR, - constants.STATUS_DELETING, constants.STATUS_CREATING) - def test_share_server_reset_state(self, status): - self.run_command('share-server-reset-state 1234 --state %s ' % status) - expected = {'reset_status': {'status': status}} - self.assert_called('POST', '/share-servers/1234/action', body=expected) - - @ddt.data('--wait', '') - def test_unmanage(self, wait_option): - version = api_versions.APIVersion('2.46') - api = mock.Mock(api_version=version) - manager = shares.ShareManager(api=api) - fake_share = shares.Share( - manager, { - 'id': 'xyzzyspoon', - 'api_version': version, - 'status': 'available', - } - ) - share_not_found_error = ("ERROR: No share with " - "a name or ID of '%s' exists.") - share_not_found_error = exceptions.CommandError( - share_not_found_error % (fake_share.id) - ) - self.mock_object( - shell_v2, '_find_share', - mock.Mock(side_effect=([fake_share, fake_share, fake_share, - share_not_found_error]))) - self.mock_object( - shares.ShareManager, 'get', - mock.Mock(return_value=fake_share)) - - self.run_command('unmanage %s xyzzyspoon' % wait_option) - - expected_get_share_calls = 4 if wait_option else 1 - shell_v2._find_share.assert_has_calls( - [mock.call(self.shell.cs, fake_share.id)] * - expected_get_share_calls - ) - uri = '/shares/%s/action' % fake_share.id - api.client.post.assert_called_once_with(uri, body={'unmanage': None}) - - def test_share_server_unmanage(self): - self.run_command('share-server-unmanage 1234') - self.assert_called('POST', '/share-servers/1234/action', - body={'unmanage': {'force': False}}) - - def test_share_server_unmanage_force(self): - self.run_command('share-server-unmanage 1234 --force') - self.assert_called('POST', '/share-servers/1234/action', - body={'unmanage': {'force': True}}) - - @ddt.data({'cmd_args': '--driver_options opt1=opt1 opt2=opt2', - 'valid_params': { - 'driver_options': {'opt1': 'opt1', 'opt2': 'opt2'}, - }}, - {'cmd_args': '', - 'valid_params': { - 'driver_options': {}, - }}, - ) - @ddt.unpack - @mock.patch.object(shell_v2, '_find_share', mock.Mock()) - @mock.patch.object(shell_v2, '_wait_for_resource_status', mock.Mock()) - def test_snapshot_manage(self, cmd_args, valid_params): - share_containing_snapshot = shares.Share('fake_share', {'id': '1234'}) - shell_v2._find_share.return_value = share_containing_snapshot - self.run_command('snapshot-manage fake_share fake_provider_location ' - + cmd_args) - expected = { - 'snapshot': { - 'share_id': '1234', - 'provider_location': 'fake_provider_location', - 'name': None, - 'description': None, - } - } - expected['snapshot'].update(valid_params) - self.assert_called('POST', '/snapshots/manage', body=expected) - # _wait_for_resource_status should not be triggered - self.assertEqual(0, shell_v2._wait_for_resource_status.call_count) - - @mock.patch.object(shell_v2, '_find_share', mock.Mock()) - @mock.patch.object(shell_v2, '_wait_for_resource_status', mock.Mock()) - def test_snapshot_manage_with_wait(self): - share_containing_snapshot = shares.Share('fake_share', {'id': '1234'}) - shell_v2._find_share.return_value = share_containing_snapshot - cmd_args = '--wait --driver_options opt1=opt1 opt2=opt2' - self.run_command('snapshot-manage fake_share fake_provider_location ' - + cmd_args) - expected = { - 'snapshot': { - 'share_id': '1234', - 'provider_location': 'fake_provider_location', - 'name': None, - 'description': None, - } - } - valid_params = {'driver_options': {'opt1': 'opt1', 'opt2': 'opt2'}} - expected['snapshot'].update(valid_params) - self.assert_called('POST', '/snapshots/manage', body=expected) - - shell_v2._find_share.assert_has_calls( - [mock.call(self.shell.cs, 'fake_share')]) - self.assertEqual(1, shell_v2._find_share.call_count) - # _wait_for_resource_status should be triggered once - shell_v2._wait_for_resource_status.assert_called_once_with( - self.shell.cs, mock.ANY, 'available', resource_type='snapshot') - - @mock.patch.object(shell_v2, '_find_share', mock.Mock()) - @mock.patch.object(shell_v2, '_wait_for_resource_status', mock.Mock()) - def test_snapshot_unmanage(self): - share_containing_snapshot = shares.Share('fake_share', {'id': '1234'}) - shell_v2._find_share.return_value = share_containing_snapshot - self.run_command('snapshot-unmanage 1234') - - self.assert_called('POST', '/snapshots/1234/action', - body={'unmanage': None}) - self.assertEqual(0, shell_v2._wait_for_resource_status.call_count) - - @mock.patch.object(shell_v2, '_find_share', mock.Mock()) - @mock.patch.object(shell_v2, '_wait_for_resource_status', mock.Mock()) - def test_snapshot_unmanage_with_wait(self): - share_containing_snapshot = shares.Share('fake_share', {'id': '1234'}) - shell_v2._find_share.return_value = share_containing_snapshot - self.run_command('snapshot-unmanage 1234 --wait') - - self.assert_called('POST', '/snapshots/1234/action', - body={'unmanage': None}) - expected_snapshot = shell_v2._find_share_snapshot( - self.shell.cs, '1234') - # _wait_for_resource_status should be trigerred once - shell_v2._wait_for_resource_status.assert_called_once_with( - self.shell.cs, expected_snapshot, 'deleted', - resource_type='snapshot') - - @mock.patch.object(shell_v2, '_wait_for_share_status', mock.Mock()) - def test_revert_to_snapshot(self): - - fake_share_snapshot = type( - 'FakeShareSnapshot', (object,), {'id': '5678', 'share_id': '1234'}) - self.mock_object( - shell_v2, '_find_share_snapshot', - mock.Mock(return_value=fake_share_snapshot)) - - self.run_command('revert-to-snapshot 5678') - - self.assert_called('POST', '/shares/1234/action', - body={'revert': {'snapshot_id': '5678'}}) - # _wait_for_share_status should not be trigerred - self.assertEqual(0, shell_v2._wait_for_share_status.call_count) - - @mock.patch.object(shell_v2, '_wait_for_share_status', mock.Mock()) - def test_revert_to_snapshot_with_wait(self): - - fake_share_snapshot = type( - 'FakeShareSnapshot', (object,), {'id': '5678', 'share_id': '1234'}) - self.mock_object( - shell_v2, '_find_share_snapshot', - mock.Mock(return_value=fake_share_snapshot)) - - self.run_command('revert-to-snapshot 5678 --wait') - - self.assert_called('POST', '/shares/1234/action', - body={'revert': {'snapshot_id': '5678'}}) - # _wait_for_share_status should be trigerred once - shell_v2._wait_for_share_status.assert_called_once_with( - self.shell.cs, mock.ANY) - - def test_delete(self): - self.run_command('delete 1234') - self.assert_called('DELETE', '/shares/1234') - - @ddt.data( - '--group sg1313', '--share-group sg1313', '--share_group sg1313') - @mock.patch.object(shell_v2, '_find_share_group', mock.Mock()) - def test_delete_with_share_group(self, sg_cmd): - fake_sg = type('FakeShareGroup', (object,), {'id': sg_cmd.split()[-1]}) - shell_v2._find_share_group.return_value = fake_sg - - self.run_command('delete 1234 %s' % sg_cmd) - - self.assert_called('DELETE', '/shares/1234?share_group_id=sg1313') - self.assertTrue(shell_v2._find_share_group.called) - - def test_delete_not_found(self): - self.assertRaises( - exceptions.CommandError, - self.run_command, - 'delete fake-not-found' - ) - - @ddt.data(('share_xyz', ), ('share_abc', 'share_xyz')) - def test_delete_wait(self, shares_to_delete): - fake_shares = [ - shares.Share('fake', {'id': share}) - for share in shares_to_delete - ] - share_not_found_error = ("Delete for share %s failed: No share with " - "a name or ID of '%s' exists.") - shares_are_not_found_errors = [ - exceptions.CommandError(share_not_found_error % (share, share)) - for share in shares_to_delete - ] - self.mock_object( - shell_v2, '_find_share', - mock.Mock(side_effect=(fake_shares + shares_are_not_found_errors))) - - self.run_command('delete %s --wait' % ' '.join(shares_to_delete)) - - shell_v2._find_share.assert_has_calls([ - mock.call(self.shell.cs, share) for share in shares_to_delete - ]) - for share in fake_shares: - uri = '/shares/%s' % share.id - self.assert_called_anytime('DELETE', uri, clear_callstack=False) - - @ddt.data(('share_xyz', ), ('share_abc', 'share_xyz')) - def test_force_delete_wait(self, shares_to_delete): - fake_manager = mock.Mock() - fake_shares = [ - shares.Share(fake_manager, {'id': '1234'}) - for share in shares_to_delete - ] - share_not_found_error = ("Delete for share %s failed: No share with " - "a name or ID of '%s' exists.") - shares_are_not_found_errors = [ - exceptions.CommandError(share_not_found_error % (share, share)) - for share in shares_to_delete - ] - self.mock_object( - shell_v2, '_find_share', - mock.Mock(side_effect=(fake_shares + shares_are_not_found_errors))) - self.run_command('force-delete %s --wait' % ' '.join(shares_to_delete)) - shell_v2._find_share.assert_has_calls([ - mock.call(self.shell.cs, share) for share in shares_to_delete - ]) - fake_manager.force_delete.assert_has_calls([ - mock.call(share) for share in fake_shares]) - self.assertEqual(len(shares_to_delete), - fake_manager.force_delete.call_count) - - def test_soft_delete(self): - self.run_command('soft-delete 1234') - expected = {'soft_delete': None} - self.assert_called('POST', '/shares/1234/action', body=expected) - - def test_restore(self): - self.run_command('restore 1234') - expected = {'restore': None} - self.assert_called('POST', '/shares/1234/action', body=expected) - - def test_list_snapshots(self): - self.run_command('snapshot-list') - self.assert_called('GET', '/snapshots/detail') - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_snapshot_list_select_column(self): - self.run_command('snapshot-list --columns id,name') - self.assert_called('GET', '/snapshots/detail') - cliutils.print_list.assert_called_once_with( - mock.ANY, - ['Id', 'Name'], sortby_index=None) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_list_snapshots_all_tenants_only_key(self): - self.run_command('snapshot-list --all-tenants') - self.assert_called('GET', '/snapshots/detail?all_tenants=1') - cliutils.print_list.assert_called_once_with( - mock.ANY, - ['ID', 'Share ID', 'Status', 'Name', 'Share Size', 'Project ID'], - sortby_index=None) - - def test_list_snapshots_all_tenants_key_and_value_1(self): - for separator in self.separators: - self.run_command('snapshot-list --all-tenants' + separator + '1') - self.assert_called( - 'GET', '/snapshots/detail?all_tenants=1') - - def test_list_snapshots_all_tenants_key_and_value_0(self): - for separator in self.separators: - self.run_command('snapshot-list --all-tenants' + separator + '0') - self.assert_called('GET', '/snapshots/detail') - - def test_list_snapshots_filter_by_name(self): - for separator in self.separators: - self.run_command('snapshot-list --name' + separator + '1234') - self.assert_called( - 'GET', '/snapshots/detail?name=1234') - - def test_list_snapshots_filter_by_status(self): - for separator in self.separators: - self.run_command('snapshot-list --status' + separator + '1234') - self.assert_called( - 'GET', '/snapshots/detail?status=1234') - - def test_list_snapshots_filter_by_share_id(self): - aliases = ['--share_id', '--share-id'] - for alias in aliases: - for separator in self.separators: - self.run_command('snapshot-list ' + alias + separator + '1234') - self.assert_called( - 'GET', '/snapshots/detail?share_id=1234') - - def test_list_snapshots_only_used(self): - for separator in self.separators: - self.run_command('snapshot-list --usage' + separator + 'used') - self.assert_called('GET', '/snapshots/detail?usage=used') - - def test_list_snapshots_only_unused(self): - for separator in self.separators: - self.run_command('snapshot-list --usage' + separator + 'unused') - self.assert_called('GET', '/snapshots/detail?usage=unused') - - def test_list_snapshots_any(self): - for separator in self.separators: - self.run_command('snapshot-list --usage' + separator + 'any') - self.assert_called('GET', '/snapshots/detail?usage=any') - - def test_list_snapshots_with_limit(self): - for separator in self.separators: - self.run_command('snapshot-list --limit' + separator + '50') - self.assert_called( - 'GET', '/snapshots/detail?limit=50') - - def test_list_snapshots_with_offset(self): - for separator in self.separators: - self.run_command('snapshot-list --offset' + separator + '50') - self.assert_called( - 'GET', '/snapshots/detail?offset=50') - - def test_list_snapshots_filter_by_inexact_name(self): - for separator in self.separators: - self.run_command('snapshot-list --name~' + separator + - 'fake_name') - self.assert_called( - 'GET', - '/snapshots/detail?name~=fake_name') - - def test_list_snapshots_filter_by_inexact_description(self): - for separator in self.separators: - self.run_command('snapshot-list --description~' + separator + - 'fake_description') - self.assert_called( - 'GET', - '/snapshots/detail?description~=fake_description') - - def test_list_snapshots_filter_by_inexact_unicode_name(self): - for separator in self.separators: - self.run_command('snapshot-list --name~' + separator + - u'ффф') - self.assert_called( - 'GET', - '/snapshots/detail?name~=%D1%84%D1%84%D1%84') - - def test_list_snapshots_filter_by_inexact_unicode_description(self): - for separator in self.separators: - self.run_command('snapshot-list --description~' + separator + - u'ффф') - self.assert_called( - 'GET', - '/snapshots/detail?description~=%D1%84%D1%84%D1%84') - - def test_list_snapshots_with_sort_dir_verify_keys(self): - aliases = ['--sort_dir', '--sort-dir'] - for alias in aliases: - for key in constants.SORT_DIR_VALUES: - for separator in self.separators: - self.run_command( - 'snapshot-list ' + alias + separator + key) - self.assert_called( - 'GET', - '/snapshots/detail?sort_dir=' + key) - - def test_list_snapshots_with_fake_sort_dir(self): - self.assertRaises( - ValueError, - self.run_command, - 'snapshot-list --sort-dir fake_sort_dir', - ) - - def test_list_snapshots_with_sort_key_verify_keys(self): - aliases = ['--sort_key', '--sort-key'] - for alias in aliases: - for key in constants.SNAPSHOT_SORT_KEY_VALUES: - for separator in self.separators: - self.run_command( - 'snapshot-list ' + alias + separator + key) - self.assert_called( - 'GET', - '/snapshots/detail?sort_key=' + key) - - def test_list_snapshots_with_fake_sort_key(self): - self.assertRaises( - ValueError, - self.run_command, - 'snapshot-list --sort-key fake_sort_key', - ) - - @ddt.data('True', 'False') - def test_list_snapshots_filter_with_count(self, value): - except_url = '/snapshots/detail?with_count=' + value - if value == 'False': - except_url = '/snapshots/detail' - - for separator in self.separators: - self.run_command('snapshot-list --count' + separator + value) - self.assert_called('GET', except_url) - - @ddt.data('True', 'False') - def test_list_snapshots_filter_with_count_invalid_version(self, value): - self.assertRaises( - exceptions.CommandError, - self.run_command, - 'snapshot-list --count ' + value, - version='2.78' - ) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_extra_specs_list(self): - self.run_command('extra-specs-list') - - self.assert_called('GET', '/types?is_public=all') - cliutils.print_list.assert_called_once_with( - mock.ANY, ['ID', 'Name', 'all_extra_specs'], mock.ANY) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_extra_specs_list_select_column(self): - self.run_command('extra-specs-list --columns id,name') - - self.assert_called('GET', '/types?is_public=all') - cliutils.print_list.assert_called_once_with( - mock.ANY, ['id', 'name'], mock.ANY) - - @ddt.data('fake', 'FFFalse', 'trueee') - def test_type_create_invalid_dhss_value(self, value): - self.assertRaises( - exceptions.CommandError, - self.run_command, - 'type-create test ' + value, - ) - - @ddt.data('True', 'False') - def test_type_create_duplicate_dhss(self, value): - self.assertRaises( - exceptions.CommandError, - self.run_command, - 'type-create test ' + value + - ' --extra-specs driver_handles_share_servers=' + value, - ) - - @ddt.data(*itertools.product( - ['snapshot_support', 'create_share_from_snapshot_support'], - ['True', 'False']) - ) - @ddt.unpack - def test_type_create_duplicate_switch_and_extra_spec(self, key, value): - - cmd = ('type-create test True --%(key)s %(value)s --extra-specs ' - '%(key)s=%(value)s' % {'key': key, 'value': value}) - - self.assertRaises(exceptions.CommandError, self.run_command, cmd) - - def test_type_create_duplicate_extra_spec_key(self): - self.assertRaises( - exceptions.CommandError, - self.run_command, - 'type-create test True --extra-specs' - ' a=foo1 a=foo2', - ) - - @ddt.unpack - @ddt.data({'expected_bool': True, 'text': 'true'}, - {'expected_bool': True, 'text': '1'}, - {'expected_bool': False, 'text': 'false'}, - {'expected_bool': False, 'text': '0'}) - def test_type_create(self, expected_bool, text): - expected = { - "share_type": { - "name": "test", - "share_type_access:is_public": True, - "extra_specs": { - "driver_handles_share_servers": expected_bool, - } - } - } - - self.run_command('type-create test ' + text) - - self.assert_called('POST', '/types', body=expected) - - def test_type_create_with_description(self): - expected = { - "share_type": { - "name": "test", - "description": "test_description", - "share_type_access:is_public": True, - "extra_specs": { - "driver_handles_share_servers": False, - } - } - } - self.run_command('type-create test false ' - '--description test_description', version='2.41') - - self.assert_called('POST', '/types', body=expected) - - @ddt.data('2.26', '2.40') - def test_type_create_invalid_description_version(self, version): - self.assertRaises( - exceptions.CommandError, - self.run_command, - 'type-create test false --description test_description', - version=version - ) - - @ddt.unpack - @ddt.data( - *([{'expected_bool': True, 'text': v} - for v in ('true', 'True', '1', 'TRUE', 'tRuE')] + - [{'expected_bool': False, 'text': v} - for v in ('false', 'False', '0', 'FALSE', 'fAlSe')]) - ) - def test_type_create_with_snapshot_support(self, expected_bool, text): - expected = { - "share_type": { - "name": "test", - "share_type_access:is_public": True, - "extra_specs": { - "snapshot_support": expected_bool, - "driver_handles_share_servers": False, - } - } - } - self.run_command('type-create test false --snapshot-support ' + text) - - self.assert_called('POST', '/types', body=expected) - - @ddt.unpack - @ddt.data({'expected_bool': True, - 'snapshot_text': 'true', - 'replication_type': 'readable'}, - {'expected_bool': False, - 'snapshot_text': 'false', - 'replication_type': 'writable'}) - def test_create_with_extra_specs(self, expected_bool, snapshot_text, - replication_type): - expected = { - "share_type": { - "name": "test", - "share_type_access:is_public": True, - "extra_specs": { - "driver_handles_share_servers": False, - "snapshot_support": expected_bool, - "replication_type": replication_type, - } - } - } - - self.run_command('type-create test false --extra-specs' - ' snapshot_support=' + snapshot_text + - ' replication_type=' + replication_type) - - self.assert_called('POST', '/types', body=expected) - - @ddt.unpack - @ddt.data( - *([{'expected_bool': True, 'text': v} - for v in ('true', 'True', '1', 'TRUE', 'tRuE')] + - [{'expected_bool': False, 'text': v} - for v in ('false', 'False', '0', 'FALSE', 'fAlSe')]) - ) - def test_type_create_with_create_share_from_snapshot_support( - self, expected_bool, text): - expected = { - "share_type": { - "name": "test", - "share_type_access:is_public": True, - "extra_specs": { - "driver_handles_share_servers": False, - "snapshot_support": True, - "create_share_from_snapshot_support": expected_bool, - } - } - } - - self.run_command('type-create test false --snapshot-support true ' - '--create-share-from-snapshot-support ' + text) - - self.assert_called('POST', '/types', body=expected) - - @ddt.data('snapshot_support', 'create_share_from_snapshot_support') - def test_type_create_invalid_switch_value(self, value): - self.assertRaises( - exceptions.CommandError, - self.run_command, - 'type-create test false --%s fake' % value, - ) - - @ddt.data('snapshot_support', 'create_share_from_snapshot_support') - def test_type_create_invalid_extra_spec_value(self, value): - self.assertRaises( - exceptions.CommandError, - self.run_command, - 'type-create test false --extra-specs %s=fake' % value, - ) - - @ddt.unpack - @ddt.data( - *([{'expected_bool': True, 'text': v} - for v in ('true', 'True', '1', 'TRUE', 'tRuE')] + - [{'expected_bool': False, 'text': v} - for v in ('false', 'False', '0', 'FALSE', 'fAlSe')]) - ) - def test_type_create_with_revert_to_snapshot_support( - self, expected_bool, text): - expected = { - "share_type": { - "name": "test", - "share_type_access:is_public": True, - "extra_specs": { - "driver_handles_share_servers": False, - "snapshot_support": True, - "revert_to_snapshot_support": expected_bool, - } - } - } - - self.run_command('type-create test false --snapshot-support true ' - '--revert-to-snapshot-support ' + text) - - self.assert_called('POST', '/types', body=expected) - - @ddt.data('fake', 'FFFalse', 'trueee') - def test_type_create_invalid_revert_to_snapshot_support_value(self, value): - self.assertRaises( - exceptions.CommandError, - self.run_command, - 'type-create test false --revert-to-snapshot-support ' + value, - ) - - @ddt.unpack - @ddt.data( - *([{'expected_bool': True, 'text': v} - for v in ('true', 'True', '1', 'TRUE', 'tRuE')] + - [{'expected_bool': False, 'text': v} - for v in ('false', 'False', '0', 'FALSE', 'fAlSe')]) - ) - def test_type_create_with_mount_snapshot_support( - self, expected_bool, text): - expected = { - "share_type": { - "name": "test", - "share_type_access:is_public": True, - "extra_specs": { - "driver_handles_share_servers": False, - "snapshot_support": True, - "revert_to_snapshot_support": False, - "mount_snapshot_support": expected_bool, - } - } - } - - self.run_command('type-create test false --snapshot-support true ' - '--revert-to-snapshot-support false ' - '--mount-snapshot-support ' + text) - - self.assert_called('POST', '/types', body=expected) - - @ddt.data('fake', 'FFFalse', 'trueee') - def test_type_create_invalid_mount_snapshot_support_value(self, value): - self.assertRaises( - exceptions.CommandError, - self.run_command, - 'type-create test false --mount-snapshot-support ' + value, - ) - - @ddt.data('--is-public', '--is_public') - def test_update(self, alias): - # basic rename with positional arguments - self.run_command('update 1234 --name new-name') - expected = {'share': {'display_name': 'new-name'}} - self.assert_called('PUT', '/shares/1234', body=expected) - # change description only - self.run_command('update 1234 --description=new-description') - expected = {'share': {'display_description': 'new-description'}} - self.assert_called('PUT', '/shares/1234', body=expected) - # update is_public attr - valid_is_public_values = strutils.TRUE_STRINGS + strutils.FALSE_STRINGS - for is_public in valid_is_public_values: - self.run_command('update 1234 %(alias)s %(value)s' % { - 'alias': alias, - 'value': is_public}) - expected = { - 'share': { - 'is_public': strutils.bool_from_string(is_public, - strict=True), - }, - } - self.assert_called('PUT', '/shares/1234', body=expected) - for invalid_val in ['truebar', 'bartrue']: - self.assertRaises(ValueError, self.run_command, - 'update 1234 %(alias)s %(value)s' % { - 'alias': alias, - 'value': invalid_val}) - # update all attributes - self.run_command('update 1234 --name new-name ' - '--description=new-description ' - '%s True' % alias) - expected = {'share': { - 'display_name': 'new-name', - 'display_description': 'new-description', - 'is_public': True, - }} - self.assert_called('PUT', '/shares/1234', body=expected) - self.assertRaises(exceptions.CommandError, - self.run_command, 'update 1234') - - def test_rename_snapshot(self): - # basic rename with positional arguments - self.run_command('snapshot-rename 1234 new-name') - expected = {'snapshot': {'display_name': 'new-name'}} - self.assert_called('PUT', '/snapshots/1234', body=expected) - # change description only - self.run_command('snapshot-rename 1234 ' - '--description=new-description') - expected = {'snapshot': {'display_description': 'new-description'}} - - self.assert_called('PUT', '/snapshots/1234', body=expected) - # snapshot-rename and change description - self.run_command('snapshot-rename 1234 new-name ' - '--description=new-description') - expected = {'snapshot': { - 'display_name': 'new-name', - 'display_description': 'new-description', - }} - self.assert_called('PUT', '/snapshots/1234', body=expected) - # noop, the only all will be the lookup - self.assertRaises(exceptions.CommandError, - self.run_command, 'snapshot-rename 1234') - - def test_set_metadata_set(self): - self.run_command('metadata 1234 set key1=val1 key2=val2') - self.assert_called('POST', '/shares/1234/metadata', - {'metadata': {'key1': 'val1', 'key2': 'val2'}}) - - def test_set_metadata_delete_dict(self): - self.run_command('metadata 1234 unset key1=val1 key2=val2') - self.assert_called('DELETE', '/shares/1234/metadata/key1') - self.assert_called('DELETE', '/shares/1234/metadata/key2', pos=-2) - - def test_set_metadata_delete_keys(self): - self.run_command('metadata 1234 unset key1 key2') - self.assert_called('DELETE', '/shares/1234/metadata/key1') - self.assert_called('DELETE', '/shares/1234/metadata/key2', pos=-2) - - def test_share_metadata_update_all(self): - self.run_command('metadata-update-all 1234 key1=val1 key2=val2') - self.assert_called('PUT', '/shares/1234/metadata', - {'metadata': {'key1': 'val1', 'key2': 'val2'}}) - - def test_extract_metadata(self): - # mimic the result of argparse's parse_args() method - class Arguments(object): - def __init__(self, metadata=None): - if metadata is None: - metadata = [] - self.metadata = metadata - - inputs = [ - ([], {}), - (["key=value"], {"key": "value"}), - (["key"], {"key": None}), - (["k1=v1", "k2=v2"], {"k1": "v1", "k2": "v2"}), - (["k1=v1", "k2"], {"k1": "v1", "k2": None}), - (["k1", "k2=v2"], {"k1": None, "k2": "v2"}) - ] - - for input in inputs: - args = Arguments(metadata=input[0]) - self.assertEqual(shell_v2._extract_metadata(args), input[1]) - - @ddt.data('--wait', '') - def test_extend_with_wait_option(self, wait_option): - available_share = shares.Share( - 'fake', {'id': '1234', 'status': 'available'}) - share_to_extend = shares.Share('fake', {'id': '1234', - 'status': 'extending'}) - fake_shares = [ - available_share, share_to_extend, share_to_extend, available_share - ] - self.mock_object(shell_v2, '_find_share', - mock.Mock(side_effect=fake_shares)) - expected_extend_body = {'extend': {'new_size': 77}} - self.run_command('extend 1234 77 %s' % wait_option) - self.assert_called_anytime('POST', '/shares/1234/action', - body=expected_extend_body, - clear_callstack=False) - if wait_option: - shell_v2._find_share.assert_has_calls( - [mock.call(self.shell.cs, '1234')] * 4) - self.assertEqual(4, shell_v2._find_share.call_count) - else: - shell_v2._find_share.assert_called_with( - self.shell.cs, '1234') - self.assertEqual(2, shell_v2._find_share.call_count) - - def test_reset_state(self): - self.run_command('reset-state 1234') - expected = {'reset_status': {'status': 'available'}} - self.assert_called('POST', '/shares/1234/action', body=expected) - - @ddt.data('--wait', '') - def test_shrink_with_wait_option(self, wait_option): - available_share = shares.Share( - 'fake', {'id': '1234', 'status': 'available'}) - share_to_shrink = shares.Share('fake', {'id': '1234', - 'status': 'shrinking'}) - fake_shares = [ - available_share, share_to_shrink, share_to_shrink, available_share - ] - self.mock_object(shell_v2, '_find_share', - mock.Mock(side_effect=fake_shares)) - expected_shrink_body = {'shrink': {'new_size': 77}} - self.run_command('shrink 1234 77 %s' % wait_option) - self.assert_called_anytime('POST', '/shares/1234/action', - body=expected_shrink_body, - clear_callstack=False) - if wait_option: - shell_v2._find_share.assert_has_calls( - [mock.call(self.shell.cs, '1234')] * 4) - self.assertEqual(4, shell_v2._find_share.call_count) - else: - shell_v2._find_share.assert_called_with( - self.shell.cs, '1234') - self.assertEqual(2, shell_v2._find_share.call_count) - - def test_reset_state_with_flag(self): - self.run_command('reset-state --state error 1234') - expected = {'reset_status': {'status': 'error'}} - self.assert_called('POST', '/shares/1234/action', body=expected) - - def test_snapshot_reset_state(self): - self.run_command('snapshot-reset-state 1234') - expected = {'reset_status': {'status': 'available'}} - self.assert_called('POST', '/snapshots/1234/action', body=expected) - - def test_snapshot_reset_state_with_flag(self): - self.run_command('snapshot-reset-state --state error 1234') - expected = {'reset_status': {'status': 'error'}} - self.assert_called('POST', '/snapshots/1234/action', body=expected) - - @ddt.data( - {}, - {'--name': 'fake_name'}, - {'--description': 'fake_description'}, - {'--neutron_net_id': 'fake_neutron_net_id'}, - {'--neutron_subnet_id': 'fake_neutron_subnet_id'}, - {'--description': 'fake_description', - '--name': 'fake_name', - '--neutron_net_id': 'fake_neutron_net_id', - '--neutron_subnet_id': 'fake_neutron_subnet_id'}) - def test_share_network_create(self, data): - cmd = 'share-network-create' - for k, v in data.items(): - cmd += ' ' + k + ' ' + v - self.run_command(cmd) - - self.assert_called('POST', '/share-networks') - - @ddt.unpack - @ddt.data( - {'data': {'--name': 'fake_name'}}, - {'data': {'--description': 'fake_description'}}, - {'data': {'--neutron_net_id': 'fake_neutron_net_id'}, - 'version': '2.49', - }, - {'data': {'--neutron_subnet_id': 'fake_neutron_subnet_id'}, - 'version': '2.49', - }, - {'data': { - '--description': 'fake_description', - '--name': 'fake_name', - '--neutron_net_id': 'fake_neutron_net_id', - '--neutron_subnet_id': 'fake_neutron_subnet_id'}, - 'version': '2.49', - }, - {'data': {'--name': '""'}}, - {'data': {'--description': '""'}}, - {'data': {'--neutron_net_id': '""'}, - 'version': '2.49', - }, - {'data': {'--neutron_subnet_id': '""'}, - 'version': '2.49', - }, - {'data': { - '--description': '""', - '--name': '""', - '--neutron_net_id': '""', - '--neutron_subnet_id': '""'}, - 'version': '2.49', - }) - def test_share_network_update(self, data, version=None): - cmd = 'share-network-update 1111' - expected = dict() - for k, v in data.items(): - cmd += ' ' + k + ' ' + v - expected[k[2:]] = v - expected = dict(share_network=expected) - - self.run_command(cmd, version=version) - - self.assert_called('PUT', '/share-networks/1111', body=expected) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_share_network_list(self): - self.run_command('share-network-list') - self.assert_called( - 'GET', - '/share-networks/detail', - ) - cliutils.print_list.assert_called_once_with( - mock.ANY, - fields=['id', 'name']) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_share_network_list_select_column(self): - self.run_command('share-network-list --columns id') - self.assert_called( - 'GET', - '/share-networks/detail', - ) - cliutils.print_list.assert_called_once_with( - mock.ANY, - fields=['Id']) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_share_network_list_all_tenants(self): - self.run_command('share-network-list --all-tenants') - self.assert_called( - 'GET', - '/share-networks/detail?all_tenants=1', - ) - cliutils.print_list.assert_called_once_with( - mock.ANY, - fields=['id', 'name']) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - @mock.patch.object(shell_v2, '_find_security_service', mock.Mock()) - def test_share_network_list_filter_by_security_service(self): - ss = type('FakeSecurityService', (object,), {'id': 'fake-ss-id'}) - shell_v2._find_security_service.return_value = ss - for command in ['--security_service', '--security-service']: - self.run_command('share-network-list %(command)s %(ss_id)s' % - {'command': command, - 'ss_id': ss.id}) - self.assert_called( - 'GET', - '/share-networks/detail?security_service_id=%s' % ss.id, - ) - shell_v2._find_security_service.assert_called_with(mock.ANY, ss.id) - cliutils.print_list.assert_called_with( - mock.ANY, - fields=['id', 'name']) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_share_network_list_project_id_aliases(self): - for command in ['--project-id', '--project_id']: - self.run_command('share-network-list %s 1234' % command) - self.assert_called( - 'GET', - '/share-networks/detail?project_id=1234', - ) - cliutils.print_list.assert_called_with( - mock.ANY, - fields=['id', 'name']) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_share_network_list_created_before_aliases(self): - for command in ['--created-before', '--created_before']: - self.run_command('share-network-list %s 2001-01-01' % command) - self.assert_called( - 'GET', - '/share-networks/detail?created_before=2001-01-01', - ) - cliutils.print_list.assert_called_with( - mock.ANY, - fields=['id', 'name']) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_share_network_list_created_since_aliases(self): - for command in ['--created-since', '--created_since']: - self.run_command('share-network-list %s 2001-01-01' % command) - self.assert_called( - 'GET', - '/share-networks/detail?created_since=2001-01-01', - ) - cliutils.print_list.assert_called_with( - mock.ANY, - fields=['id', 'name']) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_share_network_list_neutron_net_id_aliases(self): - for command in ['--neutron-net-id', '--neutron-net_id', - '--neutron_net-id', '--neutron_net_id']: - self.run_command('share-network-list %s fake-id' % command) - self.assert_called( - 'GET', - '/share-networks/detail?neutron_net_id=fake-id', - ) - cliutils.print_list.assert_called_with( - mock.ANY, - fields=['id', 'name']) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_share_network_list_neutron_subnet_id_aliases(self): - for command in ['--neutron-subnet-id', '--neutron-subnet_id', - '--neutron_subnet-id', '--neutron_subnet_id']: - self.run_command('share-network-list %s fake-id' % command) - self.assert_called( - 'GET', - '/share-networks/detail?neutron_subnet_id=fake-id', - ) - cliutils.print_list.assert_called_with( - mock.ANY, - fields=['id', 'name']) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_share_network_list_network_type_aliases(self): - for command in ['--network_type', '--network-type']: - self.run_command('share-network-list %s local' % command) - self.assert_called( - 'GET', - '/share-networks/detail?network_type=local', - ) - cliutils.print_list.assert_called_with( - mock.ANY, - fields=['id', 'name']) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_share_network_list_segmentation_id_aliases(self): - for command in ['--segmentation-id', '--segmentation_id']: - self.run_command('share-network-list %s 1234' % command) - self.assert_called( - 'GET', - '/share-networks/detail?segmentation_id=1234', - ) - cliutils.print_list.assert_called_with( - mock.ANY, - fields=['id', 'name']) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_share_network_list_ip_version_aliases(self): - for command in ['--ip-version', '--ip_version']: - self.run_command('share-network-list %s 4' % command) - self.assert_called( - 'GET', - '/share-networks/detail?ip_version=4', - ) - cliutils.print_list.assert_called_with( - mock.ANY, - fields=['id', 'name']) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_share_network_list_all_filters(self): - filters = { - 'name': 'fake-name', - 'project-id': '1234', - 'created-since': '2001-01-01', - 'created-before': '2002-02-02', - 'neutron-net-id': 'fake-net', - 'neutron-subnet-id': 'fake-subnet', - 'network-type': 'local', - 'segmentation-id': '5678', - 'cidr': 'fake-cidr', - 'ip-version': '4', - 'offset': 10, - 'limit': 20, - } - command_str = 'share-network-list' - for key, value in filters.items(): - command_str += ' --%(key)s=%(value)s' % {'key': key, - 'value': value} - self.run_command(command_str) - query = utils.safe_urlencode(sorted([(k.replace('-', '_'), v) for - (k, v) in filters.items()])) - self.assert_called( - 'GET', - '/share-networks/detail?%s' % query, - ) - cliutils.print_list.assert_called_once_with( - mock.ANY, - fields=['id', 'name']) - - def test_share_network_list_filter_by_inexact_name(self): - for separator in self.separators: - self.run_command('share-network-list --name~' + separator + - 'fake_name') - self.assert_called( - 'GET', - '/share-networks/detail?name~=fake_name') - - def test_share_network_list_filter_by_inexact_description(self): - for separator in self.separators: - self.run_command('share-network-list --description~' + separator + - 'fake_description') - self.assert_called( - 'GET', - '/share-networks/detail?description~=fake_description') - - def test_share_network_list_filter_by_inexact_unicode_name(self): - for separator in self.separators: - self.run_command('share-network-list --name~' + separator + - u'ффф') - self.assert_called( - 'GET', - '/share-networks/detail?name~=%D1%84%D1%84%D1%84') - - def test_share_network_list_filter_by_inexact_unicode_description(self): - for separator in self.separators: - self.run_command('share-network-list --description~' + separator + - u'ффф') - self.assert_called( - 'GET', - '/share-networks/detail?description~=%D1%84%D1%84%D1%84') - - def test_share_network_security_service_add(self): - self.run_command('share-network-security-service-add fake_share_nw ' - 'fake_security_service') - self.assert_called( - 'POST', - '/share-networks/1234/action', - ) - - def test_share_network_security_service_remove(self): - self.run_command('share-network-security-service-remove fake_share_nw ' - 'fake_security_service') - self.assert_called( - 'POST', - '/share-networks/1234/action', - ) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_share_network_security_service_list_select_column(self): - self.run_command('share-network-security-service-list ' - 'fake_share_nw --column id,name') - self.assert_called( - 'GET', - '/security-services/detail?share_network_id=1234', - ) - cliutils.print_list.assert_called_once_with( - mock.ANY, - fields=['Id', 'Name']) - - def test_share_network_security_service_list_by_name(self): - self.run_command('share-network-security-service-list fake_share_nw') - self.assert_called( - 'GET', - '/security-services/detail?share_network_id=1234', - ) - - def test_share_network_security_service_list_by_name_not_found(self): - self.assertRaises( - exceptions.CommandError, - self.run_command, - 'share-network-security-service-list inexistent_share_nw', - ) - - def test_share_network_security_service_list_by_name_multiple(self): - self.assertRaises( - exceptions.CommandError, - self.run_command, - 'share-network-security-service-list duplicated_name', - ) - - def test_share_network_security_service_list_by_id(self): - self.run_command('share-network-security-service-list 1111') - self.assert_called( - 'GET', - '/security-services/detail?share_network_id=1111', - ) - - @ddt.data( - {}, - {'--neutron_net_id': 'fake_neutron_net_id', - '--neutron_subnet_id': 'fake_neutron_subnet_id'}, - {'--availability-zone': 'fake_availability_zone_id'}, - {'--neutron_net_id': 'fake_neutron_net_id', - '--neutron_subnet_id': 'fake_neutron_subnet_id', - '--availability-zone': 'fake_availability_zone_id'}) - def test_share_network_subnet_add(self, data): - fake_share_network = type( - 'FakeShareNetwork', (object,), {'id': '1234'}) - self.mock_object( - shell_v2, '_find_share_network', - mock.Mock(return_value=fake_share_network)) - - cmd = 'share-network-subnet-create' - for k, v in data.items(): - cmd += ' ' + k + ' ' + v - cmd += ' ' + fake_share_network.id - self.run_command(cmd) - - shell_v2._find_share_network.assert_called_once_with( - mock.ANY, fake_share_network.id) - self.assert_called('POST', '/share-networks/1234/subnets') - - @ddt.data( - {'--neutron_net_id': 'fake_neutron_net_id'}, - {'--neutron_subnet_id': 'fake_neutron_subnet_id'}, - {'--neutron_net_id': 'fake_neutron_net_id', - '--availability-zone': 'fake_availability_zone_id'}, - {'--neutron_subnet_id': 'fake_neutron_subnet_id', - '--availability-zone': 'fake_availability_zone_id'}) - def test_share_network_subnet_add_invalid_param(self, data): - cmd = 'share-network-subnet-create' - for k, v in data.items(): - cmd += ' ' + k + ' ' + v - cmd += ' fake_network_id' - - self.assertRaises( - exceptions.CommandError, - self.run_command, - cmd) - - def test_share_network_subnet_add_invalid_share_network(self): - cmd = 'share-network-subnet-create not-found-id' - - self.assertRaises( - exceptions.CommandError, - self.run_command, - cmd) - - @ddt.data(('fake_subnet1', ), - ('fake_subnet1', 'fake_subnet2')) - def test_share_network_subnet_delete(self, subnet_ids): - fake_share_network = type( - 'FakeShareNetwork', (object,), {'id': '1234'}) - self.mock_object( - shell_v2, '_find_share_network', - mock.Mock(return_value=fake_share_network)) - fake_share_network_subnets = [ - share_network_subnets.ShareNetworkSubnet( - 'fake', {'id': subnet_id}, True) - for subnet_id in subnet_ids - ] - - self.run_command( - 'share-network-subnet-delete %(network_id)s %(subnet_ids)s' % { - 'network_id': fake_share_network.id, - 'subnet_ids': ' '.join(subnet_ids) - }) - - shell_v2._find_share_network.assert_called_once_with( - mock.ANY, fake_share_network.id) - for subnet in fake_share_network_subnets: - self.assert_called_anytime( - 'DELETE', '/share-networks/1234/subnets/%s' % subnet.id, - clear_callstack=False) - - def test_share_network_subnet_delete_invalid_share_network(self): - command = 'share-network-subnet-delete %(net_id)s %(subnet_id)s' % { - 'net_id': 'not-found-id', - 'subnet_id': '1234', - } - - self.assertRaises( - exceptions.CommandError, - self.run_command, - command) - - def test_share_network_subnet_delete_invalid_share_network_subnet(self): - fake_share_network = type( - 'FakeShareNetwork', (object,), {'id': '1234'}) - self.mock_object( - shell_v2, '_find_share_network', - mock.Mock(return_value=fake_share_network)) - command = 'share-network-subnet-delete %(net_id)s %(subnet_id)s' % { - 'net_id': fake_share_network.id, - 'subnet_id': 'not-found-id', - } - - self.assertRaises( - exceptions.CommandError, - self.run_command, - command) - - @mock.patch.object(cliutils, 'print_dict', mock.Mock()) - def test_share_network_subnet_show(self): - fake_share_network = type( - 'FakeShareNetwork', (object,), {'id': '1234'}) - self.mock_object( - shell_v2, '_find_share_network', - mock.Mock(return_value=fake_share_network)) - args = { - 'share_net_id': fake_share_network.id, - 'subnet_id': 'fake_subnet_id', - } - - self.run_command( - 'share-network-subnet-show %(share_net_id)s %(subnet_id)s' % args) - - self.assert_called( - 'GET', - '/share-networks/%(share_net_id)s/subnets/%(subnet_id)s' % args, - ) - cliutils.print_dict.assert_called_once_with(mock.ANY) - - def test_share_network_subnet_show_invalid_share_network(self): - command = 'share-network-subnet-show %(net_id)s %(subnet_id)s' % { - 'net_id': 'not-found-id', - 'subnet_id': 1234, - } - - self.assertRaises( - exceptions.CommandError, - self.run_command, - command) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_share_server_list_select_column(self): - self.run_command('share-server-list --columns id,host,status') - self.assert_called('GET', '/share-servers') - cliutils.print_list.assert_called_once_with( - mock.ANY, - fields=['Id', 'Host', 'Status']) - - def test_create_share(self): - # Use only required fields - expected = self.create_share_body.copy() - expected['share']['share_type'] = 'test_type' - self.run_command("create nfs 1 --share-type test_type") - self.assert_called("POST", "/shares", body=expected) - - def test_create_public_share(self): - expected = self.create_share_body.copy() - expected['share']['is_public'] = True - expected['share']['share_type'] = 'test_type' - self.run_command("create --public nfs 1 --share-type test_type") - self.assert_called("POST", "/shares", body=expected) - - def test_create_with_share_network(self): - # Except required fields added share network - sn = "fake-share-network" - with mock.patch.object(shell_v2, "_find_share_network", - mock.Mock(return_value=sn)): - self.run_command("create nfs 1 --share-type test_type " - "--share-network %s" % sn) - expected = self.create_share_body.copy() - expected['share']['share_network_id'] = sn - expected['share']['share_type'] = 'test_type' - self.assert_called("POST", "/shares", body=expected) - shell_v2._find_share_network.assert_called_once_with(mock.ANY, sn) - - def test_create_with_metadata(self): - # Except required fields added metadata - self.run_command("create nfs 1 --metadata key1=value1 key2=value2 " - "--share-type test_type") - expected = self.create_share_body.copy() - expected['share']['metadata'] = {"key1": "value1", "key2": "value2"} - expected['share']['share_type'] = 'test_type' - self.assert_called("POST", "/shares", body=expected) - - def test_create_with_wait(self): - self.run_command("create nfs 1 --wait --share-type test_type") - expected = self.create_share_body.copy() - expected['share']['share_type'] = 'test_type' - self.assert_called_anytime( - "POST", "/shares", body=expected, clear_callstack=False) - self.assert_called("GET", "/shares/1234") - - def test_create_share_with_no_existing_share_type(self): - self.assertRaises( - exceptions.CommandError, self.run_command, "create nfs 1") - - @ddt.data('None', 'NONE', 'none') - def test_create_share_with_the_name_none(self, name): - self.assertRaises( - exceptions.CommandError, self.run_command, - "create nfs 1 --name %s --share-type test_type" % name) - - def test_allow_access_cert(self): - self.run_command("access-allow 1234 cert client.example.com") - - expected = { - "allow_access": { - "access_type": "cert", - "access_to": "client.example.com", - } - } - self.assert_called("POST", "/shares/1234/action", body=expected) - - def test_allow_access_cert_error_gt64(self): - common_name = 'x' * 65 - self.assertRaises(exceptions.CommandError, self.run_command, - ("access-allow 1234 cert %s" % common_name)) - - def test_allow_access_cert_error_zero(self): - cmd = mock.Mock() - cmd.split = mock.Mock(side_effect=lambda: ['access-allow', '1234', - 'cert', '']) - - self.assertRaises(exceptions.CommandError, self.run_command, cmd) - - cmd.split.assert_called_once_with() - - def test_allow_access_cert_error_whitespace(self): - cmd = mock.Mock() - cmd.split = mock.Mock(side_effect=lambda: ['access-allow', '1234', - 'cert', ' ']) - - self.assertRaises(exceptions.CommandError, self.run_command, cmd) - - cmd.split.assert_called_once_with() - - def test_allow_access_with_access_level(self): - aliases = ['--access_level', '--access-level'] - expected = { - "allow_access": { - "access_type": "ip", - "access_to": "10.0.0.6", - "access_level": "ro", - } - } - - for alias in aliases: - for s in self.separators: - self.run_command( - "access-allow " + alias + s + "ro 1111 ip 10.0.0.6") - self.assert_called("POST", "/shares/1111/action", - body=expected) - - def test_allow_access_with_valid_access_levels(self): - expected = { - "allow_access": { - "access_type": "ip", - "access_to": "10.0.0.6", - } - } - - for level in ['rw', 'ro']: - expected["allow_access"]['access_level'] = level - self.run_command( - "access-allow --access-level " + level + " 1111 ip 10.0.0.6") - self.assert_called("POST", "/shares/1111/action", - body=expected) - - def test_allow_access_with_invalid_access_level(self): - self.assertRaises(SystemExit, self.run_command, - "access-allow --access-level fake 1111 ip 10.0.0.6") - - def test_allow_access_with_metadata(self): - expected = { - "allow_access": { - "access_type": "ip", - "access_to": "10.0.0.6", - "metadata": {"key1": "v1", "key2": "v2"}, - } - } - - self.run_command( - "access-allow 2222 ip 10.0.0.6 --metadata key1=v1 key2=v2", - version="2.45") - self.assert_called("POST", "/shares/2222/action", body=expected) - - def test_set_access_metadata(self): - expected = { - "metadata": { - "key1": "v1", - "key2": "v2", - } - } - self.run_command( - "access-metadata 9999 set key1=v1 key2=v2", - version="2.45") - self.assert_called("PUT", "/share-access-rules/9999/metadata", - body=expected) - - def test_unset_access_metadata(self): - self.run_command( - "access-metadata 9999 unset key1", - version="2.45") - self.assert_called("DELETE", "/share-access-rules/9999/metadata/key1") - - @ddt.data("1.0", "2.0", "2.44") - def test_allow_access_with_metadata_not_support_version(self, version): - self.assertRaises( - exceptions.CommandError, - self.run_command, - "access-allow 2222 ip 10.0.0.6 --metadata key1=v1", - version=version, - ) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - @ddt.data(*set(["2.44", "2.45", api_versions.MAX_VERSION])) - def test_access_list(self, version): - self.run_command("access-list 1111", version=version) - version = api_versions.APIVersion(version) - cliutils.print_list.assert_called_with( - mock.ANY, - ['id', 'access_type', 'access_to', 'access_level', 'state', - 'access_key', 'created_at', 'updated_at']) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - @ddt.data(*set(["2.44", "2.45", api_versions.MAX_VERSION])) - def test_access_list_select_column(self, version): - self.run_command("access-list 1111 --columns id,access_type", - version=version) - cliutils.print_list.assert_called_with( - mock.ANY, - ['Id', 'Access_Type']) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_snapshot_access_list(self): - self.run_command("snapshot-access-list 1234") - - self.assert_called('GET', '/snapshots/1234/access-list') - cliutils.print_list.assert_called_with( - mock.ANY, ['id', 'access_type', 'access_to', 'state']) - - @mock.patch.object(cliutils, 'print_dict', mock.Mock()) - def test_snapshot_access_allow(self): - self.run_command("snapshot-access-allow 1234 ip 1.1.1.1") - - self.assert_called('POST', '/snapshots/1234/action') - cliutils.print_dict.assert_called_with( - {'access_type': 'ip', 'access_to': '1.1.1.1'}) - - @ddt.data(*set(["2.45", api_versions.MAX_VERSION])) - def test_allow_access_wait(self, version): - fake_access_rule = {'id': 'fake_id'} - fake_access = mock.Mock() - fake_access._info = fake_access_rule - fake_share = mock.Mock() - fake_share.name = 'fake_share' - fake_share.allow = mock.Mock(return_value=fake_access_rule) - self.mock_object(shell_v2, '_wait_for_resource_status', - mock.Mock(return_value=fake_access)) - self.mock_object(share_access_rules.ShareAccessRuleManager, 'get', - mock.Mock(return_value=fake_access_rule)) - with mock.patch.object(apiclient_utils, 'find_resource', - mock.Mock(return_value=fake_share)): - is_default_in_api = (api_versions.APIVersion(version) >= - api_versions.APIVersion('2.45')) - if is_default_in_api: - self.run_command("access-allow fake_share ip 10.0.0.1 --wait", - version=version) - shell_v2._wait_for_resource_status.assert_has_calls([ - mock.call(self.shell.cs, fake_access_rule, - resource_type='share_access_rule', - expected_status='active', status_attr='state')]) - - def test_snapshot_access_deny(self): - self.run_command("snapshot-access-deny 1234 fake_id") - - self.assert_called('POST', '/snapshots/1234/action') - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_snapshot_export_location_list(self): - self.run_command('snapshot-export-location-list 1234') - - self.assert_called( - 'GET', '/snapshots/1234/export-locations') - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_snapshot_instance_export_location_list(self): - self.run_command('snapshot-instance-export-location-list 1234') - - self.assert_called( - 'GET', '/snapshot-instances/1234/export-locations') - - @mock.patch.object(cliutils, 'print_dict', mock.Mock()) - def test_snapshot_instance_export_location_show(self): - self.run_command('snapshot-instance-export-location-show 1234 ' - 'fake_el_id') - - self.assert_called( - 'GET', '/snapshot-instances/1234/export-locations/fake_el_id') - cliutils.print_dict.assert_called_once_with( - {'path': '/fake_path', 'id': 'fake_id'}) - - @mock.patch.object(cliutils, 'print_dict', mock.Mock()) - def test_snapshot_export_location_show(self): - self.run_command('snapshot-export-location-show 1234 fake_el_id') - - self.assert_called('GET', - '/snapshots/1234/export-locations/fake_el_id') - cliutils.print_dict.assert_called_once_with( - {'path': '/fake_path', 'id': 'fake_id'}) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_security_service_list(self): - self.run_command('security-service-list') - self.assert_called( - 'GET', - '/security-services', - ) - cliutils.print_list.assert_called_once_with( - mock.ANY, - fields=['id', 'name', 'status', 'type']) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_security_service_list_select_column(self): - self.run_command('security-service-list --columns name,type') - self.assert_called( - 'GET', - '/security-services', - ) - cliutils.print_list.assert_called_once_with( - mock.ANY, - fields=['Name', 'Type']) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - @mock.patch.object(shell_v2, '_find_share_network', mock.Mock()) - def test_security_service_list_filter_share_network(self): - class FakeShareNetwork(object): - id = 'fake-sn-id' - sn = FakeShareNetwork() - shell_v2._find_share_network.return_value = sn - for command in ['--share-network', '--share_network']: - self.run_command('security-service-list %(command)s %(sn_id)s' % - {'command': command, - 'sn_id': sn.id}) - self.assert_called( - 'GET', - '/security-services?share_network_id=%s' % sn.id, - ) - shell_v2._find_share_network.assert_called_with(mock.ANY, sn.id) - cliutils.print_list.assert_called_with( - mock.ANY, - fields=['id', 'name', 'status', 'type']) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_security_service_list_detailed(self): - self.run_command('security-service-list --detailed') - self.assert_called( - 'GET', - '/security-services/detail', - ) - cliutils.print_list.assert_called_once_with( - mock.ANY, - fields=['id', 'name', 'status', 'type', 'share_networks']) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_security_service_list_all_tenants(self): - self.run_command('security-service-list --all-tenants') - self.assert_called( - 'GET', - '/security-services?all_tenants=1', - ) - cliutils.print_list.assert_called_once_with( - mock.ANY, - fields=['id', 'name', 'status', 'type']) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_security_service_list_all_filters(self): - filters = { - 'status': 'new', - 'name': 'fake-name', - 'type': 'ldap', - 'user': 'fake-user', - 'dns-ip': '1.1.1.1', - 'ou': 'fake-ou', - 'server': 'fake-server', - 'domain': 'fake-domain', - 'offset': 10, - 'limit': 20, - } - command_str = 'security-service-list' - for key, value in filters.items(): - command_str += ' --%(key)s=%(value)s' % {'key': key, - 'value': value} - self.run_command(command_str) - self.assert_called( - 'GET', - '/security-services?dns_ip=1.1.1.1&domain=fake-domain&limit=20' - '&name=fake-name&offset=10&ou=fake-ou&server=fake-server' - '&status=new&type=ldap&user=fake-user', - ) - cliutils.print_list.assert_called_once_with( - mock.ANY, - fields=['id', 'name', 'status', 'type']) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_security_service_list_filter_by_dns_ip_alias(self): - self.run_command('security-service-list --dns_ip 1.1.1.1') - self.assert_called( - 'GET', - '/security-services?dns_ip=1.1.1.1', - ) - cliutils.print_list.assert_called_once_with( - mock.ANY, - fields=['id', 'name', 'status', 'type']) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_security_service_list_filter_by_ou_alias(self): - self.run_command('security-service-list --ou fake-ou') - self.assert_called( - 'GET', - '/security-services?ou=fake-ou', - ) - cliutils.print_list.assert_called_once_with( - mock.ANY, - fields=['id', 'name', 'status', 'type']) - - @ddt.data( - {'--name': 'fake_name'}, - {'--description': 'fake_description'}, - {'--dns-ip': 'fake_dns_ip'}, - {'--ou': 'fake_ou'}, - {'--domain': 'fake_domain'}, - {'--server': 'fake_server'}, - {'--user': 'fake_user'}, - {'--password': 'fake_password'}, - {'--name': 'fake_name', - '--description': 'fake_description', - '--dns-ip': 'fake_dns_ip', - '--ou': 'fake_ou', - '--domain': 'fake_domain', - '--server': 'fake_server', - '--user': 'fake_user', - '--password': 'fake_password'}, - {'--name': '""'}, - {'--description': '""'}, - {'--dns-ip': '""'}, - {'--ou': '""'}, - {'--domain': '""'}, - {'--server': '""'}, - {'--user': '""'}, - {'--password': '""'}, - {'--name': '""', - '--description': '""', - '--dns-ip': '""', - '--ou': '""', - '--domain': '""', - '--server': '""', - '--user': '""', - '--password': '""'},) - def test_security_service_update(self, data): - cmd = 'security-service-update 1111' - expected = dict() - for k, v in data.items(): - cmd += ' ' + k + ' ' + v - expected[k[2:].replace('-', '_')] = v - expected = dict(security_service=expected) - - self.run_command(cmd) - - self.assert_called('PUT', '/security-services/1111', body=expected) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_pool_list(self): - self.run_command('pool-list') - self.assert_called( - 'GET', - '/scheduler-stats/pools?backend=.%2A&host=.%2A&pool=.%2A', - ) - cliutils.print_list.assert_called_with( - mock.ANY, - fields=["Name", "Host", "Backend", "Pool"]) - - @mock.patch.object(cliutils, 'print_dict', mock.Mock()) - def test_quota_show(self): - self.run_command('quota-show --tenant 1234') - self.assert_called( - 'GET', - '/quota-sets/1234', - ) - cliutils.print_dict.assert_called_once_with(mock.ANY) - - @mock.patch.object(cliutils, 'print_dict', mock.Mock()) - def test_quota_show_with_detail(self): - self.run_command('quota-show --tenant 1234 --detail') - self.assert_called( - 'GET', - '/quota-sets/1234/detail', - ) - cliutils.print_dict.assert_called_once_with(mock.ANY) - - @mock.patch.object(cliutils, 'print_dict', mock.Mock()) - def test_quota_show_with_user_id(self): - self.run_command('quota-show --tenant 1234 --user 1111') - self.assert_called( - 'GET', - '/quota-sets/1234?user_id=1111', - ) - cliutils.print_dict.assert_called_once_with(mock.ANY) - - @ddt.data('1111', '0') - @mock.patch('manilaclient.common.cliutils.print_dict') - def test_quota_show_with_share_type(self, share_type_id, mock_print_dict): - self.run_command( - 'quota-show --tenant 1234 --share_type %s' % share_type_id) - - self.assert_called( - 'GET', - '/quota-sets/1234?share_type=%s' % share_type_id, - ) - mock_print_dict.assert_called_once_with(mock.ANY) - - @ddt.data( - ('--shares 13', {'shares': 13}), - ('--gigabytes 14', {'gigabytes': 14}), - ('--snapshots 15', {'snapshots': 15}), - ('--snapshot-gigabytes 13', {'snapshot_gigabytes': 13}), - ('--share-networks 13', {'share_networks': 13}), - ('--share-groups 13', {'share_groups': 13}), - ('--share-groups 0', {'share_groups': 0}), - ('--share-group-snapshots 13', {'share_group_snapshots': 13}), - ('--share-group-snapshots 0', {'share_group_snapshots': 0}), - ('--share-replicas 15', {'share_replicas': 15}), - ('--replica_gigabytes 100', {'replica_gigabytes': 100}), - ('--per_share_gigabytes 101', {'per_share_gigabytes': 101}), - ) - @ddt.unpack - def test_quota_update(self, cmd, expected_body): - self.run_command('quota-update 1234 %s' % cmd) - - expected = {'quota_set': dict(expected_body, tenant_id='1234')} - self.assert_called('PUT', '/quota-sets/1234', body=expected) - - @ddt.data( - "quota-update 1234 --share-groups 13 --share-type foo", - "quota-update 1234 --share-group-snapshots 14 --share-type bar", - ("quota-update 1234 --share-groups 13 --share-type foo " - "--share-group-snapshots 14"), - "--os-share-api-version 2.39 quota-update 1234 --share-groups 13", - ("--os-share-api-version 2.39 quota-update 1234 " - "--share-group-snapshots 13"), - ("--os-share-api-version 2.38 quota-update 1234 --shares 5 " - "--share-type foo"), - ) - def test_quota_update_with_wrong_combinations(self, cmd): - self.assertRaises(exceptions.CommandError, self.run_command, cmd) - - @mock.patch.object(cliutils, 'print_dict', mock.Mock()) - def test_pool_list_with_detail(self): - self.run_command('pool-list --detail') - self.assert_called( - 'GET', - '/scheduler-stats/pools/detail?backend=.%2A&host=.%2A&pool=.%2A', - ) - cliutils.print_dict.assert_called_with( - {'name': 'host1@backend1#pool2', 'qos': False}) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_pool_list_select_column(self): - self.run_command('pool-list --columns name,host') - self.assert_called( - 'GET', - '/scheduler-stats/pools/detail?backend=.%2A&host=.%2A&pool=.%2A', - ) - cliutils.print_list.assert_called_with( - mock.ANY, - fields=["Name", "Host"]) - - @ddt.data(({"key1": "value1", - "key2": "value2"}, - {"key1": "value1", - "key2": "value2"}), - ({"key1": {"key11": "value11", "key12": "value12"}, - "key2": {"key21": "value21"}}, - {"key1": "key11 = value11\nkey12 = value12", - "key2": "key21 = value21"}), - ({}, {})) - @ddt.unpack - @mock.patch.object(cliutils, 'print_dict', mock.Mock()) - def test_quota_set_pretty_show(self, value, expected): - fake_quota_set = fakes.FakeQuotaSet(value) - - shell_v2._quota_set_pretty_show(fake_quota_set) - cliutils.print_dict.assert_called_with(expected) - - @ddt.data('--share-type test_type', '--share_type test_type', - '--share-type-id 0123456789', '--share_type_id 0123456789') - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_pool_list_with_filters(self, param): - cmd = ('pool-list --host host1 --backend backend1 --pool pool1' + ' ' + - param) - self.run_command(cmd) - self.assert_called( - 'GET', - '/scheduler-stats/pools?backend=backend1&host=host1&' - 'pool=pool1&share_type=%s' % param.split()[-1], - ) - cliutils.print_list.assert_called_with( - mock.ANY, - fields=["Name", "Host", "Backend", "Pool"]) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_api_version(self): - self.run_command('api-version') - self.assert_called('GET', '') - cliutils.print_list.assert_called_with( - mock.ANY, - ['ID', 'Status', 'Version', 'Min_version'], - field_labels=['ID', 'Status', 'Version', 'Minimum Version']) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_share_group_list(self): - self.run_command('share-group-list') - - self.assert_called('GET', '/share-groups/detail') - cliutils.print_list.assert_called_once_with( - mock.ANY, fields=('ID', 'Name', 'Status', 'Description'), - sortby_index=None) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_share_group_list_select_column(self): - self.run_command('share-group-list --columns id,name,description') - - self.assert_called('GET', '/share-groups/detail') - cliutils.print_list.assert_called_once_with( - mock.ANY, fields=['Id', 'Name', 'Description'], sortby_index=None) - - def test_share_group_list_filter_by_inexact_name(self): - for separator in self.separators: - self.run_command('share-group-list --name~' + separator + - 'fake_name') - self.assert_called( - 'GET', - '/share-groups/detail?name~=fake_name') - - def test_share_group_list_filter_by_inexact_description(self): - for separator in self.separators: - self.run_command('share-group-list --description~' + separator + - 'fake_description') - self.assert_called( - 'GET', - '/share-groups/detail?description~=fake_description') - - def test_share_group_list_filter_by_inexact_unicode_name(self): - for separator in self.separators: - self.run_command('share-group-list --name~' + separator + - u'ффф') - self.assert_called( - 'GET', - '/share-groups/detail?name~=%D1%84%D1%84%D1%84') - - def test_share_group_list_filter_by_inexact_unicode_description(self): - for separator in self.separators: - self.run_command('share-group-list --description~' + separator + - u'ффф') - self.assert_called( - 'GET', - '/share-groups/detail?description~=%D1%84%D1%84%D1%84') - - def test_share_group_show(self): - fake_manager = mock.Mock() - fake_share_group = share_groups.ShareGroup( - fake_manager, {'id': '1234'}) - self.mock_object( - shell_v2, '_find_share_group', - mock.Mock(side_effect=[fake_share_group])) - - self.run_command('share-group-show 1234') - - shell_v2._find_share_group.assert_has_calls( - [mock.call(self.shell.cs, "1234")]) - - def test_share_group_create_wait(self): - fake_manager = mock.Mock() - fake_share_type1 = share_types.ShareType( - fake_manager, {'name': '1234', 'uuid': '1234'}) - fake_share_type2 = share_types.ShareType( - fake_manager, {'name': '5678', 'uuid': '5678'}) - fake_share_group_type = share_group_types.ShareGroupType( - fake_manager, {'name': 'fake_sg', 'uuid': '2345'}) - fake_share_network = share_networks.ShareNetwork( - fake_manager, {'id': '3456', 'uuid': '3456'}) - fake_share_group = share_groups.ShareGroup( - fake_manager, {'id': 'fake-sg-id', 'name': 'fake_sg'}) - - self.mock_object( - shell_v2, '_find_share_type', - mock.Mock(side_effect=[fake_share_type1, fake_share_type2])) - self.mock_object( - shell_v2, '_find_share_group_type', - mock.Mock(side_effect=[fake_share_group_type])) - self.mock_object( - shell_v2, '_find_share_network', - mock.Mock(side_effect=[fake_share_network])) - self.mock_object( - shell_v2, '_wait_for_resource_status', - mock.Mock(side_effect=[fake_share_group]) - ) - - self.run_command( - 'share-group-create --name fake_sg --description my_group ' - '--share-types 1234,5678 ' - '--share-group-type fake_sg ' - '--share-network 3456 ' - '--availability-zone fake_az --wait') - - shell_v2._find_share_type.assert_has_calls([ - mock.call(self.shell.cs, '1234'), - mock.call(self.shell.cs, '5678') - ]) - - shell_v2._find_share_group_type.assert_has_calls([ - mock.call(self.shell.cs, 'fake_sg') - ]) - - shell_v2._find_share_network.assert_has_calls([ - mock.call(self.shell.cs, '3456') - ]) - - expected = { - 'share_group': { - 'name': 'fake_sg', - 'description': 'my_group', - 'availability_zone': 'fake_az', - 'share_group_type_id': '2345', - 'share_network_id': '3456', - 'share_types': ['1234', '5678'], - }, - } - self.assert_called('POST', '/share-groups', body=expected) - - shell_v2._wait_for_resource_status.assert_has_calls([ - mock.call(self.shell.cs, fake_share_group, - resource_type='share_group', - expected_status='available') - ]) - - @ddt.data( - '--name fake_name --availability-zone fake_az', - '--description my_fake_description --name fake_name', - '--availability-zone fake_az', - ) - def test_share_group_create_no_share_types(self, data): - cmd = 'share-group-create' + ' ' + data - - self.run_command(cmd) - - self.assert_called('POST', '/share-groups') - - def test_share_group_create_invalid_args(self): - fake_share_type_1 = type('FakeShareType1', (object,), {'id': '1234'}) - fake_share_type_2 = type('FakeShareType2', (object,), {'id': '5678'}) - self.mock_object( - shell_v2, '_find_share_type', - mock.Mock(side_effect=[fake_share_type_1, fake_share_type_2])) - fake_share_group_type = type( - 'FakeShareGroupType', (object,), {'id': '2345'}) - self.mock_object( - shell_v2, '_find_share_group_type', - mock.Mock(return_value=fake_share_group_type)) - fake_share_group_snapshot = type( - 'FakeShareGroupSnapshot', (object,), {'id': '3456'}) - self.mock_object( - shell_v2, '_find_share_group_snapshot', - mock.Mock(return_value=fake_share_group_snapshot)) - - self.assertRaises( - ValueError, - self.run_command, - 'share-group-create --name fake_sg ' - '--description my_group --share-types 1234,5678 ' - '--share-group-type fake_sg_type ' - '--source-share-group-snapshot fake_share_group_snapshot ' - '--availability-zone fake_az') - - @ddt.data( - ('--name new-name', {'name': 'new-name'}), - ('--description new-description', {'description': 'new-description'}), - ('--name new-name --description new-description', - {'name': 'new-name', 'description': 'new-description'}), - ) - @ddt.unpack - def test_share_group_update(self, cmd, expected_body): - fake_manager = mock.Mock() - fake_share_group = share_groups.ShareGroup( - fake_manager, {'uuid': '1234', 'id': '1234'}) - self.mock_object( - shell_v2, '_find_share_group', - mock.Mock(side_effect=[fake_share_group])) - - self.run_command('share-group-update 1234 %s' % cmd) - - shell_v2._find_share_group.assert_has_calls( - [mock.call(self.shell.cs, '1234')]) - expected = {'share_group': expected_body} - self.assert_called('PUT', '/share-groups/1234', body=expected) - - def test_try_update_share_group_without_data(self): - self.assertRaises( - exceptions.CommandError, - self.run_command, 'share-group-update 1234') - - @ddt.data(('share_group_xyz', ), ('share_group_abc', 'share_group_xyz')) - def test_share_group_delete_wait(self, share_group_to_delete): - fake_manager = mock.Mock() - fake_share_group = [ - share_groups.ShareGroup(fake_manager, {'id': share_group}) - for share_group in share_group_to_delete - ] - share_group_not_found_error = ("Delete for share group %s " - "failed: No group with a " - "name or ID of '%s' exists.") - share_group_are_not_found_errors = [ - exceptions.CommandError( - share_group_not_found_error % (share_group, share_group)) - for share_group in share_group_to_delete - ] - self.mock_object( - shell_v2, '_find_share_group', - mock.Mock(side_effect=( - fake_share_group + share_group_are_not_found_errors))) - self.mock_object( - shell_v2, '_wait_for_resource_status', - mock.Mock() - ) - self.run_command( - 'share-group-delete %s --wait' % ' '.join( - share_group_to_delete)) - shell_v2._find_share_group.assert_has_calls([ - mock.call(self.shell.cs, share_group) for share_group in - share_group_to_delete - ]) - fake_manager.delete.assert_has_calls([ - mock.call(share_group, - force=False) for share_group in fake_share_group]) - shell_v2._wait_for_resource_status.assert_has_calls([ - mock.call(self.shell.cs, share_group, - resource_type='share_group', expected_status='deleted') - for share_group in fake_share_group - ]) - - def test_share_group_delete_force(self): - fake_manager = mock.Mock() - fake_share_group = share_groups.ShareGroup( - fake_manager, {'id': 'fake-group'}) - self.mock_object( - shell_v2, '_find_share_group', - mock.Mock(side_effect=[fake_share_group])) - self.run_command('share-group-delete --force fake-group') - shell_v2._find_share_group.assert_has_calls( - [mock.call(self.shell.cs, "fake-group")]) - fake_manager.delete.assert_has_calls( - [mock.call(fake_share_group, force=True)]) - self.assertEqual(1, fake_manager.delete.call_count) - - @mock.patch.object(shell_v2, '_find_share_group', mock.Mock()) - def test_share_group_delete_all_fail(self): - shell_v2._find_share_group.side_effect = Exception - - self.assertRaises( - exceptions.CommandError, - self.run_command, 'share-group-delete fake-group') - - @mock.patch.object(shell_v2, '_find_share_group', mock.Mock()) - def test_share_group_reset_state_with_flag(self): - fake_group = type('FakeShareGroup', (object,), {'id': '1234'}) - shell_v2._find_share_group.return_value = fake_group - - self.run_command('share-group-reset-state --state error 1234') - - self.assert_called( - 'POST', '/share-groups/1234/action', - {'reset_status': {'status': 'error'}}) - - @ddt.data( - 'fake-sg-id', - '--name fake_name fake-sg-id', - '--description my_fake_description --name fake_name fake-sg-id', - ) - @mock.patch.object(shell_v2, '_find_share_group', mock.Mock()) - @mock.patch.object(shell_v2, '_wait_for_resource_status', mock.Mock()) - def test_share_group_snapshot_create(self, data): - fake_sg = type('FakeShareGroup', (object,), {'id': '1234'}) - shell_v2._find_share_group.return_value = fake_sg - - self.run_command('share-group-snapshot-create ' + data) - - shell_v2._find_share_group.assert_called_with(mock.ANY, 'fake-sg-id') - self.assert_called('POST', '/share-group-snapshots') - self.assertEqual(0, shell_v2._wait_for_resource_status.call_count) - - @mock.patch.object(shell_v2, '_find_share_group', mock.Mock()) - @mock.patch.object(shell_v2, '_wait_for_resource_status', mock.Mock()) - def test_share_group_snapshot_create_with_wait(self): - fake_sg = type('FakeShareGroup', (object,), {'id': '1234'}) - shell_v2._find_share_group.return_value = fake_sg - self.run_command('share-group-snapshot-create fake-sg-id --wait') - - shell_v2._find_share_group.assert_called_with(mock.ANY, 'fake-sg-id') - self.assert_called('POST', '/share-group-snapshots') - # _wait_for_resource_status should be triggered once - shell_v2._wait_for_resource_status.assert_called_once_with( - self.shell.cs, mock.ANY, resource_type='share_group_snapshot', - expected_status='available') - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_share_group_snapshot_list(self): - self.run_command('share-group-snapshot-list') - - self.assert_called('GET', '/share-group-snapshots/detail') - cliutils.print_list.assert_called_once_with( - mock.ANY, fields=('id', 'name', 'status', 'description'), - sortby_index=None) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_share_group_snapshot_list_select_column(self): - self.run_command('share-group-snapshot-list --columns id,name') - - self.assert_called('GET', '/share-group-snapshots/detail') - cliutils.print_list.assert_called_once_with( - mock.ANY, fields=['Id', 'Name'], sortby_index=None) - - def test_share_group_snapshot_list_all_tenants_only_key(self): - self.run_command('share-group-snapshot-list --all-tenants') - - self.assert_called( - 'GET', '/share-group-snapshots/detail?all_tenants=1') - - def test_share_group_snapshot_list_all_tenants_key_and_value_1(self): - for separator in self.separators: - self.run_command( - 'share-group-snapshot-list --all-tenants' + separator + '1') - - self.assert_called( - 'GET', '/share-group-snapshots/detail?all_tenants=1') - - def test_share_group_snapshot_list_with_filters(self): - self.run_command('share-group-snapshot-list --limit 10 --offset 0') - - self.assert_called( - 'GET', '/share-group-snapshots/detail?limit=10&offset=0') - - def test_share_group_snapshot_show(self): - self.run_command('share-group-snapshot-show 1234') - - self.assert_called('GET', '/share-group-snapshots/1234') - - def test_share_group_snapshot_list_members(self): - self.run_command('share-group-snapshot-list-members 1234') - - self.assert_called('GET', '/share-group-snapshots/1234') - - def test_share_group_snapshot_list_members_select_column(self): - self.mock_object(cliutils, 'print_list') - - self.run_command( - 'share-group-snapshot-list-members 1234 --columns id,size') - - self.assert_called('GET', '/share-group-snapshots/1234') - cliutils.print_list.assert_called_once_with( - mock.ANY, fields=['Id', 'Size']) - - @mock.patch.object(shell_v2, '_find_share_group_snapshot', mock.Mock()) - def test_share_group_snapshot_reset_state(self): - fake_sg_snapshot = type( - 'FakeShareGroupSnapshot', (object,), {'id': '1234'}) - shell_v2._find_share_group_snapshot.return_value = fake_sg_snapshot - - self.run_command('share-group-snapshot-reset-state 1234') - - self.assert_called( - 'POST', '/share-group-snapshots/1234/action', - {'reset_status': {'status': 'available'}}) - - @mock.patch.object(shell_v2, '_find_share_group_snapshot', mock.Mock()) - def test_share_group_snapshot_reset_state_with_flag(self): - fake_sg_snapshot = type('FakeSGSnapshot', (object,), {'id': '1234'}) - shell_v2._find_share_group_snapshot.return_value = fake_sg_snapshot - - self.run_command( - 'share-group-snapshot-reset-state --state creating 1234') - - self.assert_called( - 'POST', '/share-group-snapshots/1234/action', - {'reset_status': {'status': 'creating'}}) - - @ddt.data( - ('--name new-name', {'name': 'new-name'}), - ('--description new-description', {'description': 'new-description'}), - ('--name new-name --description new-description', - {'name': 'new-name', 'description': 'new-description'}), - ) - @ddt.unpack - def test_share_group_snapshot_update(self, cmd, expected_body): - self.run_command('share-group-snapshot-update 1234 %s' % cmd) - - expected = {'share_group_snapshot': expected_body} - self.assert_called('PUT', '/share-group-snapshots/1234', body=expected) - - def test_try_update_share_group_snapshot_without_data(self): - self.assertRaises( - exceptions.CommandError, - self.run_command, 'share-group-snapshot-update 1234') - - @mock.patch.object(shell_v2, '_find_share_group_snapshot', mock.Mock()) - @mock.patch.object(shell_v2, '_wait_for_resource_status', mock.Mock()) - def test_share_group_snapshot_delete(self): - fake_sg_snapshot = type('FakeSGSnapshot', (object,), {'id': '1234'}) - shell_v2._find_share_group_snapshot.return_value = fake_sg_snapshot - - self.run_command('share-group-snapshot-delete fake-group-snapshot') - - self.assert_called('DELETE', '/share-group-snapshots/1234') - self.assertEqual(0, shell_v2._wait_for_resource_status.call_count) - - @mock.patch.object(shell_v2, '_find_share_group_snapshot', mock.Mock()) - @mock.patch.object(shell_v2, '_wait_for_resource_status', mock.Mock()) - def test_share_group_snapshot_delete_with_wait(self): - fake_sg_snapshot = type('FakeSGSnapshot', (object,), {'id': '1234'}) - shell_v2._find_share_group_snapshot.return_value = fake_sg_snapshot - - self.run_command('share-group-snapshot-delete fake-group-snapshot' - ' --wait') - - self.assert_called('DELETE', '/share-group-snapshots/1234') - # _wait_for_resource_status should be triggered once - shell_v2._wait_for_resource_status.assert_called_once_with( - self.shell.cs, mock.ANY, resource_type='share_group_snapshot', - expected_status='deleted') - - @mock.patch.object(shell_v2, '_find_share_group_snapshot', mock.Mock()) - def test_share_group_snapshot_delete_force(self): - fake_sg_snapshot = type('FakeSGSnapshot', (object,), {'id': '1234'}) - shell_v2._find_share_group_snapshot.return_value = fake_sg_snapshot - - self.run_command( - 'share-group-snapshot-delete --force fake-sg-snapshot') - - self.assert_called( - 'POST', '/share-group-snapshots/1234/action', - {'force_delete': None}) - - def test_share_group_snapshot_delete_all_fail(self): - self.mock_object( - shell_v2, '_find_share_group_snapshot', - mock.Mock(side_effect=Exception)) - - self.assertRaises( - exceptions.CommandError, - self.run_command, 'share-group-snapshot-delete fake-sg-snapshot') - - @ddt.data(*itertools.product( - ('--columns id,is_default', '--columns id,name', - '--columns is_default', ''), - {'2.45', '2.46', api_versions.MAX_VERSION})) - @ddt.unpack - def test_share_group_type_list(self, command_args, version): - self.mock_object(shell_v2, '_print_share_group_type_list') - command = 'share-group-type-list ' + command_args - columns_requested = command_args.split('--columns ')[-1] or None - is_default_in_api = (api_versions.APIVersion(version) >= - api_versions.APIVersion('2.46')) - - self.run_command(command, version=version) - - if (not is_default_in_api and - (not columns_requested or 'is_default' in columns_requested)): - self.assert_called('GET', '/share-group-types/default') - self.assert_called_anytime('GET', '/share-group-types') - else: - self.assert_called('GET', '/share-group-types') - - shell_v2._print_share_group_type_list.assert_called_once_with( - mock.ANY, default_share_group_type=mock.ANY, - columns=columns_requested) - - def test_share_group_type_list_select_column(self): - self.mock_object(shell_v2, '_print_share_group_type_list') - - self.run_command('share-group-type-list --columns id,name') - - self.assert_called('GET', '/share-group-types') - shell_v2._print_share_group_type_list.assert_called_once_with( - mock.ANY, default_share_group_type=mock.ANY, columns='id,name') - - def test_share_group_type_list_all(self): - self.run_command('share-group-type-list --all') - - self.assert_called_anytime('GET', '/share-group-types?is_public=all') - - @ddt.data(('', mock.ANY), (' --columns id,name', 'id,name')) - @ddt.unpack - def test_share_group_specs_list(self, args_cmd, expected_columns): - self.mock_object(shell_v2, '_print_type_and_extra_specs_list') - - self.run_command('share-group-type-specs-list') - - self.assert_called('GET', '/share-group-types?is_public=all') - shell_v2._print_type_and_extra_specs_list.assert_called_once_with( - mock.ANY, columns=mock.ANY) - - @ddt.data(True, False) - def test_share_group_type_create_with_access_and_group_specs(self, public): - fake_share_type_1 = type('FakeShareType', (object,), {'id': '1234'}) - fake_share_type_2 = type('FakeShareType', (object,), {'id': '5678'}) - self.mock_object( - shell_v2, '_find_share_type', - mock.Mock(side_effect=[fake_share_type_1, fake_share_type_2])) - expected = { - 'share_group_type': { - 'name': 'test-group-type-1', - 'share_types': ['1234', '5678'], - 'group_specs': {'spec1': 'value1'}, - 'is_public': public, - } - } - - self.run_command( - 'share-group-type-create test-group-type-1 ' - 'type1,type2 --is-public %s --group-specs ' - 'spec1=value1' % str(public)) - - self.assert_called_anytime('POST', '/share-group-types', body=expected) - - def test_share_group_type_delete(self): - fake_share_group_type = type( - 'FakeShareGroupType', (object,), {'id': '1234'}) - self.mock_object( - shell_v2, '_find_share_group_type', - mock.Mock(return_value=fake_share_group_type)) - - self.run_command('share-group-type-delete test-group-type-1') - - self.assert_called('DELETE', '/share-group-types/1234') - - def test_share_group_type_key_set(self): - fake_share_group_type = type( - 'FakeShareGroupType', (object,), - {'id': '1234', 'is_public': False, 'set_keys': mock.Mock(), - 'unset_keys': mock.Mock()}) - self.mock_object( - shell_v2, '_find_share_group_type', - mock.Mock(return_value=fake_share_group_type)) - - self.run_command('share-group-type-key fake_sg_type set key1=value1') - - fake_share_group_type.set_keys.assert_called_with({'key1': 'value1'}) - - def test_share_group_type_key_unset(self): - fake_share_group_type = type( - 'FakeShareGroupType', (object,), - {'id': '1234', 'is_public': False, 'set_keys': mock.Mock(), - 'unset_keys': mock.Mock()}) - self.mock_object( - shell_v2, '_find_share_group_type', - mock.Mock(return_value=fake_share_group_type)) - - self.run_command('share-group-type-key fake_group_type unset key1') - - fake_share_group_type.unset_keys.assert_called_with(['key1']) - - def test_share_group_type_access_list(self): - fake_share_group_type = type( - 'FakeShareGroupType', (object,), - {'id': '1234', 'is_public': False}) - self.mock_object( - shell_v2, '_find_share_group_type', - mock.Mock(return_value=fake_share_group_type)) - - self.run_command('share-group-type-access-list 1234') - - self.assert_called('GET', '/share-group-types/1234/access') - - def test_share_group_type_access_list_public(self): - fake_share_group_type = type( - 'FakeShareGroupType', (object,), - {'id': '1234', 'is_public': True}) - self.mock_object( - shell_v2, '_find_share_group_type', - mock.Mock(return_value=fake_share_group_type)) - - self.assertRaises( - exceptions.CommandError, - self.run_command, 'share-group-type-access-list 1234') - - def test_share_group_type_access_add_project(self): - fake_share_group_type = type( - 'FakeShareGroupType', (object,), - {'id': '1234', 'is_public': False}) - self.mock_object( - shell_v2, '_find_share_group_type', - mock.Mock(return_value=fake_share_group_type)) - expected = {'addProjectAccess': {'project': '101'}} - - self.run_command('share-group-type-access-add 1234 101') - - self.assert_called( - 'POST', '/share-group-types/1234/action', body=expected) - - def test_share_group_type_access_remove_project(self): - fake_share_group_type = type( - 'FakeShareGroupType', (object,), - {'id': '1234', 'is_public': False}) - self.mock_object( - shell_v2, '_find_share_group_type', - mock.Mock(return_value=fake_share_group_type)) - expected = {'removeProjectAccess': {'project': '101'}} - - self.run_command('share-group-type-access-remove 1234 101') - - self.assert_called( - 'POST', '/share-group-types/1234/action', body=expected) - - @ddt.data( - {'--shares': 5}, - {'--snapshots': 5}, - {'--gigabytes': 5}, - {'--snapshot-gigabytes': 5}, - {'--snapshot_gigabytes': 5}, - {'--share-networks': 5}, - {'--share_networks': 5}, - {'--shares': 5, - '--snapshots': 5, - '--gigabytes': 5, - '--snapshot-gigabytes': 5, - '--share-networks': 5}, - {'--shares': 5, - '--snapshots': 5, - '--gigabytes': 5, - '--snapshot-gigabytes': 5, - '--share-networks': 5, - '--share-groups': 5, - '--share-group-snapshots': 5}) - def test_quota_class_update(self, data): - cmd = 'quota-class-update test' - expected = dict() - for k, v in data.items(): - cmd += ' %(arg)s %(val)s' % {'arg': k, 'val': v} - expected[k[2:].replace('-', '_')] = v - expected['class_name'] = 'test' - expected = dict(quota_class_set=expected) - - self.run_command(cmd) - self.assert_called('PUT', '/quota-class-sets/test', body=expected) - - @ddt.data(True, False) - @mock.patch.object(shell_v2, '_find_share_replica', mock.Mock()) - @mock.patch.object(shell_v2, '_wait_for_resource_status', mock.Mock()) - def test_share_replica_delete_force(self, force): - - fake_replica = type('FakeShareReplica', (object,), {'id': '1234'}) - shell_v2._find_share_replica.return_value = fake_replica - - force = '--force' if force else '' - self.run_command('share-replica-delete fake-replica ' + force) - - if force: - self.assert_called('POST', '/share-replicas/1234/action', - body={'force_delete': None}) - else: - self.assert_called('DELETE', '/share-replicas/1234') - self.assertEqual(0, shell_v2._wait_for_resource_status.call_count) - - @mock.patch.object(shell_v2, '_find_share_replica', mock.Mock()) - @mock.patch.object(shell_v2, '_wait_for_resource_status', mock.Mock()) - def test_share_replica_delete_with_wait(self): - - fake_replica = type('FakeShareReplica', (object,), {'id': '1234'}) - shell_v2._find_share_replica.return_value = fake_replica - - self.run_command('share-replica-delete fake-replica --wait') - - self.assert_called('DELETE', '/share-replicas/1234') - - # _wait_for_resource_status should be triggered once - shell_v2._wait_for_resource_status.assert_called_once_with( - self.shell.cs, mock.ANY, resource_type='share_replica', - expected_status='deleted') - - @ddt.data([1, 0], [1, 1], [2, 0], [2, 1], [2, 2]) - @ddt.unpack - @mock.patch.object(shell_v2, '_find_share_replica', mock.Mock()) - def test_share_replica_delete_errors(self, replica_count, replica_errors): - - class StubbedReplicaFindError(Exception): - """Error in find share replica stub""" - pass - - class StubbedFindWithErrors(object): - def __init__(self, existing_replicas): - self.existing_replicas = existing_replicas - - def __call__(self, cs, replica): - if replica not in self.existing_replicas: - raise StubbedReplicaFindError - return type('FakeShareReplica', (object,), {'id': replica}) - - all_replicas = [] - existing_replicas = [] - for counter in range(replica_count): - replica = 'fake-replica-%d' % counter - if counter >= replica_errors: - existing_replicas.append(replica) - all_replicas.append(replica) - - shell_v2._find_share_replica.side_effect = StubbedFindWithErrors( - existing_replicas) - cmd = 'share-replica-delete %s' % ' '.join(all_replicas) - - if replica_count == replica_errors: - self.assertRaises(exceptions.CommandError, self.run_command, cmd) - else: - self.run_command(cmd) - for replica in existing_replicas: - self.assert_called_anytime('DELETE', - '/share-replicas/' + replica, - clear_callstack=False) - - def test_share_replica_list_all(self): - - self.run_command('share-replica-list') - - self.assert_called('GET', '/share-replicas/detail') - - @mock.patch.object(shell_v2, '_find_share', mock.Mock()) - def test_share_replica_list_for_share(self): - - fshare = type('FakeShare', (object,), {'id': 'fake-share-id'}) - shell_v2._find_share.return_value = fshare - cmd = 'share-replica-list --share-id %s' - self.run_command(cmd % fshare.id) - - self.assert_called( - 'GET', '/share-replicas/detail?share_id=fake-share-id') - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_share_replica_list_select_column(self): - self.run_command('share-replica-list --columns id,status') - - self.assert_called('GET', '/share-replicas/detail') - - cliutils.print_list.assert_called_once_with( - mock.ANY, ['Id', 'Status']) - - @ddt.data( - 'fake-share-id --az fake-az', - 'fake-share-id --availability-zone fake-az', - ) - @mock.patch.object(shell_v2, '_find_share', mock.Mock()) - @mock.patch.object(shell_v2, '_wait_for_resource_status', mock.Mock()) - def test_share_replica_create(self, data): - - fshare = type('FakeShare', (object,), {'id': 'fake-share-id'}) - shell_v2._find_share.return_value = fshare - - cmd = 'share-replica-create' + ' ' + data - - self.run_command(cmd) - - shell_v2._find_share.assert_called_with(mock.ANY, fshare.id) - self.assert_called('POST', '/share-replicas') - self.assertEqual(0, shell_v2._wait_for_resource_status.call_count) - - @mock.patch.object(shell_v2, '_find_share', mock.Mock()) - @mock.patch.object(shell_v2, '_wait_for_resource_status', mock.Mock()) - def test_share_replica_create_with_wait(self): - - fshare = type('FakeShare', (object,), {'id': 'fake-share-id'}) - shell_v2._find_share.return_value = fshare - - cmd = ('share-replica-create fake-share-id ' - '--availability-zone fake-az --wait') - - self.run_command(cmd) - - shell_v2._find_share.assert_called_with(mock.ANY, fshare.id) - self.assert_called('POST', '/share-replicas') - # _wait_for_resource_status should be triggered once - shell_v2._wait_for_resource_status.assert_called_once_with( - self.shell.cs, mock.ANY, resource_type='share_replica', - expected_status='available') - - def test_share_replica_show(self): - - self.run_command('share-replica-show 5678') - - self.assert_called_anytime('GET', '/share-replicas/5678') - - @mock.patch.object(shell_v2, '_find_share_replica', mock.Mock()) - @mock.patch.object(shell_v2, '_wait_for_resource_status', mock.Mock()) - def test_share_replica_promote_quiesce_wait_time(self): - fake_replica = type('FakeShareReplica', (object,), {'id': '1234'}) - shell_v2._find_share_replica.return_value = fake_replica - cmd = ('share-replica-promote ' + fake_replica.id + - ' --quiesce-wait-time 5') - self.run_command(cmd) - self.assert_called( - 'POST', '/share-replicas/1234/action', - body={'promote': {'quiesce_wait_time': '5'}}) - self.assertEqual(0, shell_v2._wait_for_resource_status.call_count) - - @mock.patch.object(shell_v2, '_find_share_replica', mock.Mock()) - @mock.patch.object(shell_v2, '_wait_for_resource_status', mock.Mock()) - def test_share_replica_promote_with_wait_(self): - fake_replica = type('FakeShareReplica', (object,), {'id': '1234'}) - shell_v2._find_share_replica.return_value = fake_replica - cmd = ('share-replica-promote ' + fake_replica.id + ' --wait') - self.run_command(cmd) - self.assert_called( - 'POST', '/share-replicas/1234/action') - # _wait_for_resource_status should be triggered once - shell_v2._wait_for_resource_status.assert_called_once_with( - self.shell.cs, mock.ANY, resource_type='share_replica', - expected_status='active', status_attr='replica_state') - - @ddt.data('promote', 'resync') - @mock.patch.object(shell_v2, '_find_share_replica', mock.Mock()) - def test_share_replica_actions(self, action): - fake_replica = type('FakeShareReplica', (object,), {'id': '1234'}) - shell_v2._find_share_replica.return_value = fake_replica - cmd = 'share-replica-' + action + ' ' + fake_replica.id - - self.run_command(cmd) - - self.assert_called( - 'POST', '/share-replicas/1234/action', - body={action.replace('-', '_'): None}) - - @mock.patch.object(shell_v2, '_find_share_replica', mock.Mock()) - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - @ddt.data(None, "replica_state,path") - def test_share_replica_export_location_list(self, columns): - fake_replica = type('FakeShareReplica', (object,), {'id': '1234'}) - shell_v2._find_share_replica.return_value = fake_replica - cmd = 'share-replica-export-location-list ' + fake_replica.id - if columns is not None: - cmd = cmd + ' --columns=%s' % columns - expected_columns = list(map(lambda x: x.strip().title(), - columns.split(","))) - else: - expected_columns = [ - 'ID', 'Availability Zone', 'Replica State', - 'Preferred', 'Path' - ] - - self.run_command(cmd) - - self.assert_called( - 'GET', '/share-replicas/1234/export-locations') - cliutils.print_list.assert_called_with(mock.ANY, expected_columns) - - @mock.patch.object(shell_v2, '_find_share_replica', mock.Mock()) - def test_share_replica_export_location_show(self): - fake_replica = type('FakeShareReplica', (object,), {'id': '1234'}) - shell_v2._find_share_replica.return_value = fake_replica - self.run_command( - 'share-replica-export-location-show 1234 fake-el-uuid') - self.assert_called( - 'GET', '/share-replicas/1234/export-locations/fake-el-uuid') - - @ddt.data('reset-state', 'reset-replica-state') - @mock.patch.object(shell_v2, '_find_share_replica', mock.Mock()) - def test_share_replica_reset_state_cmds(self, action): - if action == 'reset-state': - attr = 'status' - action_name = 'reset_status' - else: - attr = 'replica_state' - action_name = action.replace('-', '_') - fake_replica = type('FakeShareReplica', (object,), {'id': '1234'}) - shell_v2._find_share_replica.return_value = fake_replica - cmd = 'share-replica-%(action)s %(resource)s --state %(state)s' - - self.run_command(cmd % { - 'action': action, 'resource': 1234, 'state': 'xyzzyspoon!'}) - - self.assert_called( - 'POST', '/share-replicas/1234/action', - body={action_name: {attr: 'xyzzyspoon!'}}) - - def test_snapshot_instance_list_all(self): - self.run_command('snapshot-instance-list') - self.assert_called('GET', '/snapshot-instances') - - def test_snapshot_instance_list_all_detail(self): - self.run_command('snapshot-instance-list --detail True') - self.assert_called('GET', '/snapshot-instances/detail') - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_snapshot_instance_list_select_column(self): - self.run_command('snapshot-instance-list --columns id,status') - self.assert_called('GET', '/snapshot-instances') - cliutils.print_list.assert_called_once_with( - mock.ANY, ['Id', 'Status']) - - @mock.patch.object(shell_v2, '_find_share_snapshot', mock.Mock()) - def test_snapshot_instance_list_for_snapshot(self): - fsnapshot = type('FakeSnapshot', (object,), - {'id': 'fake-snapshot-id'}) - shell_v2._find_share_snapshot.return_value = fsnapshot - cmd = 'snapshot-instance-list --snapshot %s' - self.run_command(cmd % fsnapshot.id) - - self.assert_called( - 'GET', '/snapshot-instances?snapshot_id=fake-snapshot-id') - - def test_snapshot_instance_show(self): - self.run_command('snapshot-instance-show 1234') - self.assert_called_anytime('GET', '/snapshot-instances/1234', - clear_callstack=False) - self.assert_called_anytime('GET', - '/snapshot-instances/1234/export-locations') - - def test_snapshot_instance_reset_state(self): - self.run_command('snapshot-instance-reset-state 1234') - expected = {'reset_status': {'status': 'available'}} - self.assert_called('POST', '/snapshot-instances/1234/action', - body=expected) - - def test_migration_start(self): - command = ("migration-start --force-host-assisted-migration True " - "--new-share-network 1111 --new-share-type 1 1234 " - "host@backend#pool --writable False --nondisruptive True " - "--preserve-metadata False --preserve-snapshots True") - self.run_command(command) - expected = {'migration_start': { - 'host': 'host@backend#pool', - 'force_host_assisted_migration': 'True', - 'preserve_metadata': 'False', - 'writable': 'False', - 'nondisruptive': 'True', - 'preserve_snapshots': 'True', - 'new_share_network_id': 1111, - 'new_share_type_id': 1, - }} - self.assert_called('POST', '/shares/1234/action', body=expected) - - @ddt.data('migration-complete', 'migration-get-progress', - 'migration-cancel') - def test_migration_others(self, method): - command = ' '.join((method, '1234')) - self.run_command(command) - expected = {method.replace('-', '_'): None} - self.assert_called('POST', '/shares/1234/action', body=expected) - - @ddt.data('migration_error', 'migration_success', None) - def test_reset_task_state(self, param): - command = ' '.join(('reset-task-state --state', str(param), - '1234')) - self.run_command(command) - expected = {'reset_task_state': {'task_state': param}} - self.assert_called('POST', '/shares/1234/action', body=expected) - - @ddt.data(('fake_security_service1', ), - ('fake_security_service1', 'fake_security_service2')) - def test_security_service_delete(self, ss_ids): - fake_security_services = [ - security_services.SecurityService('fake', {'id': ss_id}, True) - for ss_id in ss_ids - ] - self.mock_object( - shell_v2, '_find_security_service', - mock.Mock(side_effect=fake_security_services)) - - self.run_command('security-service-delete %s' % ' '.join(ss_ids)) - - shell_v2._find_security_service.assert_has_calls([ - mock.call(self.shell.cs, ss_id) for ss_id in ss_ids - ]) - for ss in fake_security_services: - self.assert_called_anytime( - 'DELETE', '/security-services/%s' % ss.id, - clear_callstack=False) - - @ddt.data(('fake_share_network1', ), - ('fake_share_network1', 'fake_share_network1')) - def test_share_network_delete(self, sn_ids): - fake_share_networks = [ - share_networks.ShareNetwork('fake', {'id': sn_id}, True) - for sn_id in sn_ids - ] - self.mock_object( - shell_v2, '_find_share_network', - mock.Mock(side_effect=fake_share_networks)) - - self.run_command('share-network-delete %s' % ' '.join(sn_ids)) - - shell_v2._find_share_network.assert_has_calls([ - mock.call(self.shell.cs, sn_id) for sn_id in sn_ids - ]) - for sn in fake_share_networks: - self.assert_called_anytime( - 'DELETE', '/share-networks/%s' % sn.id, - clear_callstack=False) - - @mock.patch.object(shell_v2, '_find_share', mock.Mock()) - @mock.patch.object(shell_v2, '_wait_for_snapshot_status', mock.Mock()) - def test_snapshot_create(self): - share_to_create_snapshot = shares.Share('fake_share', {'id': '1234'}) - shell_v2._find_share.return_value = share_to_create_snapshot - - self.run_command( - 'snapshot-create fake_share --name testshare1snapshot') - - shell_v2._find_share.assert_has_calls([ - mock.call(self.shell.cs, 'fake_share')]) - self.assert_called_anytime( - 'POST', '/snapshots', clear_callstack=False) - # _wait_for_snapshot_status should not be trigerred - self.assertEqual(0, shell_v2._wait_for_snapshot_status.call_count) - - @mock.patch.object(shell_v2, '_find_share', mock.Mock()) - @mock.patch.object(shell_v2, '_wait_for_snapshot_status', mock.Mock()) - def test_snapshot_create_with_wait(self): - share_to_create_snapshot = shares.Share('fake_share', {'id': '1234'}) - shell_v2._find_share.return_value = share_to_create_snapshot - - self.run_command( - 'snapshot-create fake_share --name testshare1snapshot --wait') - - shell_v2._find_share.assert_has_calls([ - mock.call(self.shell.cs, 'fake_share')]) - self.assert_called_anytime( - 'POST', '/snapshots', clear_callstack=False) - # _wait_for_snapshot_status should be trigerred once - shell_v2._wait_for_snapshot_status.assert_called_once_with( - self.shell.cs, mock.ANY, expected_status='available') - - @ddt.data(('fake_snapshot1', ), ('fake_snapshot1', 'fake_snapshot2')) - def test_snapshot_delete(self, snapshot_ids): - fake_snapshots = [ - share_snapshots.ShareSnapshot('fake', {'id': snapshot_id}, True) - for snapshot_id in snapshot_ids - ] - self.mock_object( - shell_v2, '_find_share_snapshot', - mock.Mock(side_effect=fake_snapshots)) - - self.run_command('snapshot-delete %s' % ' '.join(snapshot_ids)) - - shell_v2._find_share_snapshot.assert_has_calls([ - mock.call(self.shell.cs, s_id) for s_id in snapshot_ids - ]) - for snapshot in fake_snapshots: - self.assert_called_anytime( - 'DELETE', '/snapshots/%s' % snapshot.id, - clear_callstack=False) - - @mock.patch.object(shell_v2, '_find_share_snapshot', mock.Mock()) - @mock.patch.object(shell_v2, '_wait_for_snapshot_status', mock.Mock()) - def test_snapshot_delete_with_wait(self): - fake_snapshot = share_snapshots.ShareSnapshot( - 'fake', {'id': 'fake_snapshot1'}, True) - shell_v2._find_share_snapshot.return_value = fake_snapshot - - self.run_command('snapshot-delete fake_snapshot1 --wait') - - shell_v2._find_share_snapshot.assert_has_calls([ - mock.call(self.shell.cs, 'fake_snapshot1')]) - self.assert_called_anytime( - 'DELETE', '/snapshots/fake_snapshot1', clear_callstack=False) - # _wait_for_resource_status should be trigerred once - shell_v2._wait_for_snapshot_status.assert_called_once_with( - self.shell.cs, 'fake_snapshot1', expected_status='deleted') - - @ddt.data(('snapshot_xyz', ), ('snapshot_abc', 'snapshot_xyz')) - def test_snapshot_force_delete_wait(self, snapshots_to_delete): - fake_manager = mock.Mock() - fake_snapshots = [ - share_snapshots.ShareSnapshot(fake_manager, {'id': '1234'}) - for snapshot in snapshots_to_delete - ] - snapshot_not_found_error = ("Delete for snapshot %s failed: No " - "snapshot with a name or " - "ID of '%s' exists.") - snapshots_are_not_found_errors = [ - exceptions.CommandError( - snapshot_not_found_error % (snapshot, snapshot)) - for snapshot in snapshots_to_delete - ] - self.mock_object( - shell_v2, '_find_share_snapshot', - mock.Mock(side_effect=( - fake_snapshots + snapshots_are_not_found_errors))) - self.run_command( - 'snapshot-force-delete %s --wait' % ' '.join( - snapshots_to_delete)) - shell_v2._find_share_snapshot.assert_has_calls([ - mock.call(self.shell.cs, snapshot) for snapshot in - snapshots_to_delete - ]) - fake_manager.force_delete.assert_has_calls([ - mock.call(snapshot) for snapshot in fake_snapshots]) - self.assertEqual(len(snapshots_to_delete), - fake_manager.force_delete.call_count) - - @ddt.data(('fake_type1', ), ('fake_type1', 'fake_type2')) - def test_share_type_delete(self, type_ids): - fake_share_types = [ - share_types.ShareType('fake', {'id': type_id}, True) - for type_id in type_ids - ] - self.mock_object( - shell_v2, '_find_share_type', - mock.Mock(side_effect=fake_share_types)) - - self.run_command('type-delete %s' % ' '.join(type_ids)) - - shell_v2._find_share_type.assert_has_calls([ - mock.call(self.shell.cs, t_id) for t_id in type_ids - ]) - for fake_share_type in fake_share_types: - self.assert_called_anytime( - 'DELETE', '/types/%s' % fake_share_type.id, - clear_callstack=False) - - @ddt.data(('share_server_xyz', ), ('share_server_abc', 'share_server_xyz')) - def test_share_server_delete_wait(self, share_servers_to_delete): - fake_manager = mock.Mock() - fake_share_servers = [ - share_servers.ShareServer(fake_manager, {'id': '1234'}) - for share_server in share_servers_to_delete - ] - share_server_not_found_error = ("Delete for share server %s " - "failed: No server with a " - "name or ID of '%s' exists.") - share_servers_are_not_found_errors = [ - exceptions.CommandError(share_server_not_found_error - % (share_server, share_server)) - for share_server in share_servers_to_delete - ] - self.mock_object( - shell_v2, '_find_share_server', mock.Mock( - side_effect=(fake_share_servers + - share_servers_are_not_found_errors))) - - self.mock_object( - shell_v2, '_wait_for_resource_status', - mock.Mock() - ) - - self.run_command('share-server-delete %s --wait' % ' ' - .join(share_servers_to_delete)) - - shell_v2._find_share_server.assert_has_calls([ - mock.call(self.shell.cs, share_server) - for share_server in share_servers_to_delete - ]) - fake_manager.delete.assert_has_calls([ - mock.call(share_server) for share_server in fake_share_servers]) - shell_v2._wait_for_resource_status.assert_has_calls([ - mock.call(self.shell.cs, share_server, - resource_type='share_server', expected_status='deleted') - for share_server in fake_share_servers - ]) - self.assertEqual(len(share_servers_to_delete), - fake_manager.delete.call_count) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_message_list(self): - self.run_command('message-list') - - self.assert_called('GET', '/messages') - cliutils.print_list.assert_called_once_with( - mock.ANY, fields=['ID', 'Resource Type', 'Resource ID', - 'Action ID', 'User Message', 'Detail ID', - 'Created At'], sortby_index=None) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_share_message_list_created_before_aliases(self): - self.run_command('message-list --before 2001-01-01') - self.assert_called( - 'GET', - '/messages?created_before=2001-01-01', - ) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_share_message_list_created_since_aliases(self): - self.run_command('message-list --since 2001-01-01') - self.assert_called( - 'GET', - '/messages?created_since=2001-01-01', - ) - - @mock.patch.object(cliutils, 'print_list', mock.Mock()) - def test_message_list_select_column(self): - self.run_command('message-list --columns id,resource_type') - - self.assert_called('GET', '/messages') - cliutils.print_list.assert_called_once_with( - mock.ANY, fields=['Id', 'Resource_Type'], sortby_index=None) - - def test_message_list_with_filters(self): - self.run_command('message-list --limit 10 --offset 0') - - self.assert_called( - 'GET', '/messages?limit=10&offset=0') - - def test_message_show(self): - self.run_command('message-show 1234') - - self.assert_called('GET', '/messages/1234') - - @ddt.data(('1234', ), - ('1234_error', ), - ('1234_error', '5678'), - ('1234', '5678_error'), - ('1234', '5678')) - def test_message_delete(self, ids): - fake_messages = dict() - for mid in ids: - if mid.endswith('_error'): - continue - fake_messages[mid] = messages.Message('fake', {'id': mid}, True) - - def _find_message_with_errors(cs, mid): - if mid.endswith('_error'): - raise Exception - return fake_messages[mid] - - self.mock_object( - shell_v2, '_find_message', - mock.Mock(side_effect=_find_message_with_errors)) - - cmd = 'message-delete %s' % ' '.join(ids) - - if len(fake_messages) == 0: - self.assertRaises(exceptions.CommandError, self.run_command, cmd) - else: - self.run_command(cmd) - - shell_v2._find_message.assert_has_calls([ - mock.call(self.shell.cs, mid) for mid in ids - ]) - for fake_message in fake_messages.values(): - self.assert_called_anytime( - 'DELETE', '/messages/%s' % fake_message.id, - clear_callstack=False) - - @ddt.data(('share-network-list', ' --description~', - '/share-networks/', '2.35'), - ('share-network-list', ' --name~', - '/share-networks/', '2.35'), - ('share-group-list', ' --description~', - '/share-groups/', '2.35'), - ('share-group-list', ' --name~', '/share-groups/', '2.35'), - ('list', ' --description~', '/shares/', '2.35'), - ('list', ' --name~', '/shares/', '2.35'), - ('snapshot-list', ' --description~', '/snapshots/', '2.35'), - ('snapshot-list', ' --name~', '/snapshots/', '2.35')) - @ddt.unpack - def test_list_filter_by_inexact_version_not_support( - self, cmd, option, url, version): - for separator in self.separators: - self.assertRaises( - exceptions.CommandError, - self.run_command, - cmd + option + separator + 'fake', - version=version - ) - - def test_share_server_unmanage_all_fail(self): - # All of 2345, 5678, 9999 throw exception - cmd = '--os-share-api-version 2.49' - cmd += ' share-server-unmanage' - cmd += ' 2345 5678 9999' - self.assertRaises(exceptions.CommandError, - self.run_command, cmd) - - def test_share_server_unmanage_some_fail(self): - # 5678 and 9999 throw exception - self.run_command('share-server-unmanage 1234 5678 9999') - expected = {'unmanage': {'force': False}} - self.assert_called('POST', '/share-servers/1234/action', - body=expected) - - @ddt.data('migration-start', 'migration-check') - def test_share_server_migration_start_and_check(self, method): - command = ("share-server-%s " - "1234 host@backend --new-share-network 1111 " - "--writable False --nondisruptive True " - "--preserve-snapshots True" % - method) - self.run_command(command) - method = method.replace('-', '_') - expected = {method: { - 'host': 'host@backend', - 'writable': 'False', - 'nondisruptive': 'True', - 'preserve_snapshots': 'True', - 'new_share_network_id': 1111 - }} - self.assert_called('POST', '/share-servers/1234/action', body=expected) - - @ddt.data('migration-complete', 'migration-get-progress', - 'migration-cancel') - def test_share_server_migration_others(self, method): - command = 'share-server-' + ' '.join((method, '1234')) - self.run_command(command) - expected = {method.replace('-', '_'): None} - self.assert_called('POST', '/share-servers/1234/action', body=expected) - - @ddt.data('migration_error', 'migration_success', None) - def test_share_server_reset_task_state(self, param): - command = ' '.join(('share-server-reset-task-state --state', - str(param), - '1234')) - self.run_command(command) - expected = {'reset_task_state': {'task_state': param}} - self.assert_called('POST', '/share-servers/1234/action', body=expected) diff --git a/manilaclient/tests/unit/v2/test_type_access.py b/manilaclient/tests/unit/v2/test_type_access.py index 50f0e8ce..0b727aa0 100644 --- a/manilaclient/tests/unit/v2/test_type_access.py +++ b/manilaclient/tests/unit/v2/test_type_access.py @@ -27,12 +27,10 @@ @ddt.ddt class TypeAccessTest(utils.TestCase): - def _get_share_type_access_manager(self, microversion): version = api_versions.APIVersion(microversion) mock_microversion = mock.Mock(api_version=version) - return share_type_access.ShareTypeAccessManager( - api=mock_microversion) + return share_type_access.ShareTypeAccessManager(api=mock_microversion) @ddt.data( ("1.0", "os-share-type-access"), @@ -48,12 +46,14 @@ def test_list(self, microversion, action_name): share_type.is_public = False manager = self._get_share_type_access_manager(microversion) - with mock.patch.object(manager, '_list', - mock.Mock(return_value=fake_access_list)): + with mock.patch.object( + manager, '_list', mock.Mock(return_value=fake_access_list) + ): access = manager.list(share_type=share_type, search_opts=None) manager._list.assert_called_once_with( - "/types/3/%s" % action_name, "share_type_access") + f"/types/3/{action_name}", "share_type_access" + ) self.assertEqual(fake_access_list, access) @ddt.data("1.0", "2.0", "2.6", "2.7") @@ -63,8 +63,9 @@ def test_list_public(self, microversion): share_type.is_public = True manager = self._get_share_type_access_manager(microversion) - with mock.patch.object(manager, '_list', - mock.Mock(return_value='fake')): + with mock.patch.object( + manager, '_list', mock.Mock(return_value='fake') + ): access = manager.list(share_type=share_type) self.assertFalse(manager._list.called) @@ -75,21 +76,25 @@ def test_add_project_access(self, microversion): share_type = mock.Mock() manager = self._get_share_type_access_manager(microversion) - with mock.patch.object(manager, '_action', - mock.Mock(return_value='fake_action')): + with mock.patch.object( + manager, '_action', mock.Mock(return_value='fake_action') + ): manager.add_project_access(share_type, PROJECT_UUID) manager._action.assert_called_once_with( - 'addProjectAccess', share_type, {'project': PROJECT_UUID}) + 'addProjectAccess', share_type, {'project': PROJECT_UUID} + ) @ddt.data("1.0", "2.0", "2.6", "2.7") def test_remove_project_access(self, microversion): share_type = mock.Mock() manager = self._get_share_type_access_manager(microversion) - with mock.patch.object(manager, '_action', - mock.Mock(return_value='fake_action')): + with mock.patch.object( + manager, '_action', mock.Mock(return_value='fake_action') + ): manager.remove_project_access(share_type, PROJECT_UUID) manager._action.assert_called_once_with( - 'removeProjectAccess', share_type, {'project': PROJECT_UUID}) + 'removeProjectAccess', share_type, {'project': PROJECT_UUID} + ) diff --git a/manilaclient/tests/unit/v2/test_types.py b/manilaclient/tests/unit/v2/test_types.py index dfcd4018..369adb8f 100644 --- a/manilaclient/tests/unit/v2/test_types.py +++ b/manilaclient/tests/unit/v2/test_types.py @@ -32,7 +32,6 @@ def get_valid_type_create_data_2_0(): - public = [True, False] dhss = [True, False] snapshot = [None, True, False] @@ -44,16 +43,17 @@ def get_valid_type_create_data_2_0(): def get_valid_type_create_data_2_24(): - public = [True, False] dhss = [True, False] snapshot = [None] create_from_snapshot = [None] extra_specs = [None, {'replication_type': 'writable', 'foo': 'bar'}] - snapshot_none_combos = list(itertools.product(public, dhss, snapshot, - create_from_snapshot, - extra_specs)) + snapshot_none_combos = list( + itertools.product( + public, dhss, snapshot, create_from_snapshot, extra_specs + ) + ) public = [True, False] dhss = [True, False] @@ -61,9 +61,11 @@ def get_valid_type_create_data_2_24(): create_from_snapshot = [True, False, None] extra_specs = [None, {'replication_type': 'readable', 'foo': 'bar'}] - snapshot_true_combos = list(itertools.product(public, dhss, snapshot, - create_from_snapshot, - extra_specs)) + snapshot_true_combos = list( + itertools.product( + public, dhss, snapshot, create_from_snapshot, extra_specs + ) + ) public = [True, False] dhss = [True, False] @@ -71,15 +73,16 @@ def get_valid_type_create_data_2_24(): create_from_snapshot = [False, None] extra_specs = [None, {'replication_type': 'dr', 'foo': 'bar'}] - snapshot_false_combos = list(itertools.product(public, dhss, snapshot, - create_from_snapshot, - extra_specs)) + snapshot_false_combos = list( + itertools.product( + public, dhss, snapshot, create_from_snapshot, extra_specs + ) + ) return snapshot_none_combos + snapshot_true_combos + snapshot_false_combos def get_valid_type_create_data_2_27(): - public = [True, False] dhss = [True, False] snapshot = [None] @@ -87,10 +90,16 @@ def get_valid_type_create_data_2_27(): revert_to_snapshot = [None] extra_specs = [None, {'replication_type': 'writable', 'foo': 'bar'}] - snapshot_none_combos = list(itertools.product(public, dhss, snapshot, - create_from_snapshot, - revert_to_snapshot, - extra_specs)) + snapshot_none_combos = list( + itertools.product( + public, + dhss, + snapshot, + create_from_snapshot, + revert_to_snapshot, + extra_specs, + ) + ) public = [True, False] dhss = [True, False] @@ -99,10 +108,16 @@ def get_valid_type_create_data_2_27(): revert_to_snapshot = [True, False, None] extra_specs = [None, {'replication_type': 'readable', 'foo': 'bar'}] - snapshot_true_combos = list(itertools.product(public, dhss, snapshot, - create_from_snapshot, - revert_to_snapshot, - extra_specs)) + snapshot_true_combos = list( + itertools.product( + public, + dhss, + snapshot, + create_from_snapshot, + revert_to_snapshot, + extra_specs, + ) + ) public = [True, False] dhss = [True, False] @@ -111,17 +126,22 @@ def get_valid_type_create_data_2_27(): revert_to_snapshot = [False, None] extra_specs = [None, {'replication_type': 'dr', 'foo': 'bar'}] - snapshot_false_combos = list(itertools.product(public, dhss, snapshot, - create_from_snapshot, - revert_to_snapshot, - extra_specs)) + snapshot_false_combos = list( + itertools.product( + public, + dhss, + snapshot, + create_from_snapshot, + revert_to_snapshot, + extra_specs, + ) + ) return snapshot_none_combos + snapshot_true_combos + snapshot_false_combos @ddt.ddt class TypesTest(utils.TestCase): - def _get_share_types_manager(self, microversion): version = api_versions.APIVersion(microversion) mock_microversion = mock.Mock(api_version=version) @@ -165,16 +185,18 @@ def test_list_types_search_by_extra_specs(self): @ddt.data(*get_valid_type_create_data_2_0()) @ddt.unpack def test_create_2_7(self, is_public, dhss, snapshot, extra_specs): - extra_specs = copy.copy(extra_specs) manager = self._get_share_types_manager("2.7") self.mock_object(manager, '_create', mock.Mock(return_value="fake")) result = manager.create( - 'test-type-3', spec_driver_handles_share_servers=dhss, - spec_snapshot_support=snapshot, extra_specs=extra_specs, - is_public=is_public) + 'test-type-3', + spec_driver_handles_share_servers=dhss, + spec_snapshot_support=snapshot, + extra_specs=extra_specs, + is_public=is_public, + ) if extra_specs is None: extra_specs = {} @@ -190,54 +212,68 @@ def test_create_2_7(self, is_public, dhss, snapshot, extra_specs): } expected_body["share_type"]["extra_specs"][ - "driver_handles_share_servers"] = dhss + "driver_handles_share_servers" + ] = dhss expected_body["share_type"]["extra_specs"]['snapshot_support'] = ( - True if snapshot is None else snapshot) + True if snapshot is None else snapshot + ) manager._create.assert_called_once_with( - "/types", expected_body, "share_type") + "/types", expected_body, "share_type" + ) self.assertEqual("fake", result) - def _add_standard_extra_specs_to_dict(self, extra_specs, - create_from_snapshot=None, - revert_to_snapshot=None, - mount_snapshot=None): - + def _add_standard_extra_specs_to_dict( + self, + extra_specs, + create_from_snapshot=None, + revert_to_snapshot=None, + mount_snapshot=None, + ): # Short-circuit checks to allow for extra specs to be (and remain) None - if all(spec is None for spec in [ - create_from_snapshot, revert_to_snapshot, mount_snapshot]): + if all( + spec is None + for spec in [ + create_from_snapshot, + revert_to_snapshot, + mount_snapshot, + ] + ): return extra_specs extra_specs = extra_specs or {} if create_from_snapshot is not None: extra_specs['create_share_from_snapshot_support'] = ( - create_from_snapshot) + create_from_snapshot + ) if revert_to_snapshot is not None: - extra_specs['revert_to_snapshot_support'] = ( - revert_to_snapshot) + extra_specs['revert_to_snapshot_support'] = revert_to_snapshot if mount_snapshot is not None: - extra_specs['mount_snapshot_support'] = ( - mount_snapshot) + extra_specs['mount_snapshot_support'] = mount_snapshot return extra_specs @ddt.data(*get_valid_type_create_data_2_24()) @ddt.unpack - def test_create_2_24(self, is_public, dhss, snapshot, create_from_snapshot, - extra_specs): - + def test_create_2_24( + self, is_public, dhss, snapshot, create_from_snapshot, extra_specs + ): extra_specs = copy.copy(extra_specs) extra_specs = self._add_standard_extra_specs_to_dict( - extra_specs, create_from_snapshot=create_from_snapshot) + extra_specs, create_from_snapshot=create_from_snapshot + ) manager = self._get_share_types_manager("2.24") self.mock_object(manager, '_create', mock.Mock(return_value="fake")) result = manager.create( - 'test-type-3', spec_driver_handles_share_servers=dhss, + 'test-type-3', + spec_driver_handles_share_servers=dhss, spec_snapshot_support=snapshot, - extra_specs=extra_specs, is_public=is_public) + extra_specs=extra_specs, + is_public=is_public, + ) expected_extra_specs = dict(extra_specs or {}) expected_extra_specs["driver_handles_share_servers"] = dhss @@ -248,11 +284,13 @@ def test_create_2_24(self, is_public, dhss, snapshot, create_from_snapshot, expected_extra_specs["snapshot_support"] = snapshot if create_from_snapshot is None: - expected_extra_specs.pop("create_share_from_snapshot_support", - None) + expected_extra_specs.pop( + "create_share_from_snapshot_support", None + ) else: expected_extra_specs["create_share_from_snapshot_support"] = ( - create_from_snapshot) + create_from_snapshot + ) expected_body = { "share_type": { @@ -263,26 +301,38 @@ def test_create_2_24(self, is_public, dhss, snapshot, create_from_snapshot, } manager._create.assert_called_once_with( - "/types", expected_body, "share_type") + "/types", expected_body, "share_type" + ) self.assertEqual("fake", result) @ddt.data(*get_valid_type_create_data_2_27()) @ddt.unpack - def test_create_2_27(self, is_public, dhss, snapshot, create_from_snapshot, - revert_to_snapshot, extra_specs): - + def test_create_2_27( + self, + is_public, + dhss, + snapshot, + create_from_snapshot, + revert_to_snapshot, + extra_specs, + ): extra_specs = copy.copy(extra_specs) extra_specs = self._add_standard_extra_specs_to_dict( - extra_specs, create_from_snapshot=create_from_snapshot, - revert_to_snapshot=revert_to_snapshot) + extra_specs, + create_from_snapshot=create_from_snapshot, + revert_to_snapshot=revert_to_snapshot, + ) manager = self._get_share_types_manager("2.27") self.mock_object(manager, '_create', mock.Mock(return_value="fake")) result = manager.create( - 'test-type-3', spec_driver_handles_share_servers=dhss, + 'test-type-3', + spec_driver_handles_share_servers=dhss, spec_snapshot_support=snapshot, - extra_specs=extra_specs, is_public=is_public) + extra_specs=extra_specs, + is_public=is_public, + ) expected_extra_specs = dict(extra_specs or {}) expected_extra_specs["driver_handles_share_servers"] = dhss @@ -293,17 +343,20 @@ def test_create_2_27(self, is_public, dhss, snapshot, create_from_snapshot, expected_extra_specs["snapshot_support"] = snapshot if create_from_snapshot is None: - expected_extra_specs.pop("create_share_from_snapshot_support", - None) + expected_extra_specs.pop( + "create_share_from_snapshot_support", None + ) else: expected_extra_specs["create_share_from_snapshot_support"] = ( - create_from_snapshot) + create_from_snapshot + ) if revert_to_snapshot is None: expected_extra_specs.pop("revert_to_snapshot_support", None) else: expected_extra_specs["revert_to_snapshot_support"] = ( - revert_to_snapshot) + revert_to_snapshot + ) expected_body = { "share_type": { @@ -314,27 +367,42 @@ def test_create_2_27(self, is_public, dhss, snapshot, create_from_snapshot, } manager._create.assert_called_once_with( - "/types", expected_body, "share_type") + "/types", expected_body, "share_type" + ) self.assertEqual("fake", result) @ddt.data( - (False, False, True, {'snapshot_support': True, - 'replication_type': 'fake_repl_type'}), - (False, False, False, {'snapshot_support': False, - 'replication_type': 'fake_repl_type'}), - (False, False, True, {'snapshot_support': False, - 'replication_type': 'fake_repl_type'}), - (False, False, False, {'snapshot_support': True, - 'replication_type': 'fake_repl_type'}), - + ( + False, + False, + True, + {'snapshot_support': True, 'replication_type': 'fake_repl_type'}, + ), + ( + False, + False, + False, + {'snapshot_support': False, 'replication_type': 'fake_repl_type'}, + ), + ( + False, + False, + True, + {'snapshot_support': False, 'replication_type': 'fake_repl_type'}, + ), + ( + False, + False, + False, + {'snapshot_support': True, 'replication_type': 'fake_repl_type'}, + ), (False, True, None, {'driver_handles_share_servers': True}), (False, False, None, {'driver_handles_share_servers': True}), (False, None, None, {'driver_handles_share_servers': True}), (False, None, None, {'driver_handles_share_servers': None}), ) @ddt.unpack - def test_create_error_2_7(self, is_public, dhss, snapshot, - extra_specs): + def test_create_error_2_7(self, is_public, dhss, snapshot, extra_specs): manager = self._get_share_types_manager("2.7") self.mock_object(manager, '_create', mock.Mock(return_value="fake")) @@ -345,20 +413,27 @@ def test_create_error_2_7(self, is_public, dhss, snapshot, spec_driver_handles_share_servers=dhss, spec_snapshot_support=snapshot, extra_specs=extra_specs, - is_public=is_public) + is_public=is_public, + ) @ddt.data( (False, True, None, None, {'driver_handles_share_servers': True}), - (False, False, False, False, {'snapshot_support': True, - 'replication_type': 'fake_repl_type'}), + ( + False, + False, + False, + False, + {'snapshot_support': True, 'replication_type': 'fake_repl_type'}, + ), ) @ddt.unpack - def test_create_error_2_24(self, is_public, dhss, snapshot, - create_from_snapshot, extra_specs): - + def test_create_error_2_24( + self, is_public, dhss, snapshot, create_from_snapshot, extra_specs + ): extra_specs = copy.copy(extra_specs) extra_specs = self._add_standard_extra_specs_to_dict( - extra_specs, create_from_snapshot=create_from_snapshot) + extra_specs, create_from_snapshot=create_from_snapshot + ) manager = self._get_share_types_manager("2.24") self.mock_object(manager, '_create', mock.Mock(return_value="fake")) @@ -370,7 +445,8 @@ def test_create_error_2_24(self, is_public, dhss, snapshot, spec_driver_handles_share_servers=dhss, spec_snapshot_support=snapshot, extra_specs=extra_specs, - is_public=is_public) + is_public=is_public, + ) @ddt.data( ("2.6", True), @@ -384,20 +460,22 @@ def test_create_error_2_24(self, is_public, dhss, snapshot, ) @ddt.unpack def test_create_with_default_values(self, microversion, dhss): - manager = self._get_share_types_manager(microversion) self.mock_object(manager, '_create', mock.Mock(return_value="fake")) description = 'test description' - if (api_versions.APIVersion(microversion) >= - api_versions.APIVersion("2.41")): + if api_versions.APIVersion(microversion) >= api_versions.APIVersion( + "2.41" + ): result = manager.create( - 'test-type-3', dhss, description=description) + 'test-type-3', dhss, description=description + ) else: result = manager.create('test-type-3', dhss) - if (api_versions.APIVersion(microversion) > - api_versions.APIVersion("2.6")): + if api_versions.APIVersion(microversion) > api_versions.APIVersion( + "2.6" + ): is_public_keyname = "share_type_access:is_public" else: is_public_keyname = "os-share-type-access:is_public" @@ -409,27 +487,30 @@ def test_create_with_default_values(self, microversion, dhss): "extra_specs": { "driver_handles_share_servers": dhss, "snapshot_support": True, - } + }, } } - if (api_versions.APIVersion(microversion) >= - api_versions.APIVersion("2.24")): + if api_versions.APIVersion(microversion) >= api_versions.APIVersion( + "2.24" + ): del expected_body['share_type']['extra_specs']['snapshot_support'] - if (api_versions.APIVersion(microversion) >= - api_versions.APIVersion("2.41")): + if api_versions.APIVersion(microversion) >= api_versions.APIVersion( + "2.41" + ): expected_body['share_type']['description'] = description manager._create.assert_called_once_with( - "/types", expected_body, "share_type") + "/types", expected_body, "share_type" + ) self.assertEqual("fake", result) def test_set_key(self): t = cs.share_types.get(1) t.set_keys({'k': 'v'}) - cs.assert_called('POST', - '/types/1/extra_specs', - {'extra_specs': {'k': 'v'}}) + cs.assert_called( + 'POST', '/types/1/extra_specs', {'extra_specs': {'k': 'v'}} + ) def test_unset_keys(self): t = cs.share_types.get(1) @@ -451,11 +532,11 @@ def test_update(self, microversion): is_public_key_name: is_public, } } - result = manager.update( - share_type, name, is_public, description) + result = manager.update(share_type, name, is_public, description) expected_body['share_type']['description'] = description manager._update.assert_called_once_with( - "/types/%s" % share_type, expected_body, "share_type") + f"/types/{share_type}", expected_body, "share_type" + ) self.assertEqual("fake", result) def test_delete(self): @@ -466,33 +547,38 @@ def test_get_keys_from_resource_data(self): manager = mock.Mock() manager.api.client.get = mock.Mock(return_value=(200, {})) valid_extra_specs = {'test': 'test'} - share_type = share_types.ShareType(mock.Mock(), - {'extra_specs': valid_extra_specs, - 'name': 'test'}, - loaded=True) + share_type = share_types.ShareType( + mock.Mock(), + {'extra_specs': valid_extra_specs, 'name': 'test'}, + loaded=True, + ) actual_result = share_type.get_keys() self.assertEqual(actual_result, valid_extra_specs) self.assertEqual(manager.api.client.get.call_count, 0) - @ddt.data({'prefer_resource_data': True, - 'resource_extra_specs': {}}, - {'prefer_resource_data': False, - 'resource_extra_specs': {'fake': 'fake'}}, - {'prefer_resource_data': False, - 'resource_extra_specs': {}}) + @ddt.data( + {'prefer_resource_data': True, 'resource_extra_specs': {}}, + { + 'prefer_resource_data': False, + 'resource_extra_specs': {'fake': 'fake'}, + }, + {'prefer_resource_data': False, 'resource_extra_specs': {}}, + ) @ddt.unpack - def test_get_keys_from_api(self, prefer_resource_data, - resource_extra_specs): + def test_get_keys_from_api( + self, prefer_resource_data, resource_extra_specs + ): manager = mock.Mock() valid_extra_specs = {'test': 'test'} manager.api.client.get = mock.Mock( - return_value=(200, {'extra_specs': valid_extra_specs})) + return_value=(200, {'extra_specs': valid_extra_specs}) + ) info = { 'name': 'test', 'uuid': 'fake', - 'extra_specs': resource_extra_specs + 'extra_specs': resource_extra_specs, } share_type = share_types.ShareType(manager, info, loaded=True) diff --git a/manilaclient/utils.py b/manilaclient/utils.py index 8dcc477b..fae3bb99 100644 --- a/manilaclient/utils.py +++ b/manilaclient/utils.py @@ -13,8 +13,9 @@ from urllib import parse -class HookableMixin(object): +class HookableMixin: """Mixin so classes can register and run hooks.""" + _hooks_map = {} @classmethod @@ -44,7 +45,7 @@ def safe_issubclass(*args): def get_function_name(func): - return "%s.%s" % (func.__module__, func.__qualname__) + return f"{func.__module__}.{func.__qualname__}" def safe_urlencode(params_dict): diff --git a/manilaclient/v1/__init__.py b/manilaclient/v1/__init__.py index 56c143be..44787d62 100644 --- a/manilaclient/v1/__init__.py +++ b/manilaclient/v1/__init__.py @@ -20,7 +20,7 @@ from manilaclient import v2 -class MovedModule(object): +class MovedModule: def __init__(self, new_module): self.new_module = new_module diff --git a/manilaclient/v1/client.py b/manilaclient/v1/client.py index 67acc3b5..3a8d6a41 100644 --- a/manilaclient/v1/client.py +++ b/manilaclient/v1/client.py @@ -13,8 +13,8 @@ from debtcollector import removals from keystoneauth1 import adapter +from keystoneauth1 import identity from keystoneauth1 import session -from keystoneclient import client as ks_client import manilaclient from manilaclient.common import constants @@ -34,9 +34,10 @@ from manilaclient.v2 import shares -@removals.removed_class("Client", message="Please use 'v2.Client' instead", - removal_version='2.0.0') -class Client(object): +@removals.removed_class( + "Client", message="Please use 'v2.Client' instead", removal_version='2.0.0' +) +class Client: """Top-level object to access the OpenStack Manila API. Create an instance with your creds:: @@ -49,7 +50,7 @@ class Client(object): Or, alternatively, you can create a client instance using the keystoneauth1.session API:: - >>> from keystoneclient.auth.identity import v3 + >>> from keystoneauth1.identity import v3 >>> from keystoneauth1 import session >>> from manilaclient import client >>> auth = v3.Password(auth_url=AUTH_URL, @@ -66,26 +67,60 @@ class Client(object): >>> client.shares.list() ... """ - def __init__(self, username=None, project_id=None, auth_url=None, - insecure=False, timeout=None, tenant_id=None, - project_name=None, region_name=None, - endpoint_type='publicURL', extensions=None, - service_type=constants.V1_SERVICE_TYPE, service_name=None, - retries=None, http_log_debug=False, input_auth_token=None, - session=None, auth=None, cacert=None, - service_catalog_url=None, user_agent='python-manilaclient', - use_keyring=False, force_new_token=False, - cached_token_lifetime=300, - api_version=manilaclient.API_DEPRECATED_VERSION, - user_id=None, - user_domain_id=None, - user_domain_name=None, - project_domain_id=None, - project_domain_name=None, - cert=None, - password=None, - **kwargs): + @removals.removed_kwarg( + 'use_keyring', + message='This parameter is no longer supported and has no effect.', + version='5.8.0', + removal_version='6.0.0', + ) + @removals.removed_kwarg( + 'force_new_token', + message='This parameter is no longer supported and has no effect.', + version='5.8.0', + removal_version='6.0.0', + ) + @removals.removed_kwarg( + 'cached_token_lifetime', + message='This parameter is no longer supported and has no effect.', + version='5.8.0', + removal_version='6.0.0', + ) + def __init__( + self, + username=None, + project_id=None, + auth_url=None, + insecure=False, + timeout=None, + tenant_id=None, + project_name=None, + region_name=None, + endpoint_type='publicURL', + extensions=None, + service_type=constants.V1_SERVICE_TYPE, + service_name=None, + retries=None, + http_log_debug=False, + input_auth_token=None, + session=None, + auth=None, + cacert=None, + service_catalog_url=None, + user_agent='python-manilaclient', + use_keyring=False, + force_new_token=False, + cached_token_lifetime=300, + api_version=manilaclient.API_DEPRECATED_VERSION, + user_id=None, + user_domain_id=None, + user_domain_name=None, + project_domain_id=None, + project_domain_name=None, + cert=None, + password=None, + **kwargs, + ): self.username = username self.password = password self.tenant_id = tenant_id or project_id @@ -107,13 +142,11 @@ def __init__(self, username=None, project_id=None, auth_url=None, self.cert = cert self.insecure = insecure - self.use_keyring = use_keyring - self.force_new_token = force_new_token - self.cached_token_lifetime = cached_token_lifetime - if input_auth_token and not service_catalog_url: - msg = ("For token-based authentication you should " - "provide 'input_auth_token' and 'service_catalog_url'.") + msg = ( + "For token-based authentication you should " + "provide 'input_auth_token' and 'service_catalog_url'." + ) raise exceptions.ClientException(msg) self.project_id = tenant_id if tenant_id is not None else project_id @@ -125,56 +158,57 @@ def __init__(self, username=None, project_id=None, auth_url=None, # if token is provided. if not input_auth_token: if session: + # Modern path - session provided by caller (e.g., OSC plugin) self.keystone_client = adapter.LegacyJsonAdapter( session=session, auth=auth, interface=endpoint_type, service_type=service_type, service_name=service_name, - region_name=region_name) + region_name=region_name, + ) input_auth_token = self.keystone_client.session.get_token(auth) - else: - self.keystone_client = self._get_keystone_client() - input_auth_token = self.keystone_client.auth_token + # Legacy path - create auth plugin and session ourselves + auth, ks_session = self._get_keystone_auth_and_session() + self.keystone_client = adapter.LegacyJsonAdapter( + session=ks_session, + auth=auth, + interface=endpoint_type, + service_type=service_type, + service_name=service_name, + region_name=region_name, + ) + input_auth_token = self.keystone_client.session.get_token(auth) if not input_auth_token: raise RuntimeError("Not Authorized") - if session and not service_catalog_url: + if not service_catalog_url: + # Use keystoneauth1 session endpoint discovery service_catalog_url = self.keystone_client.session.get_endpoint( - auth, interface=endpoint_type, - service_type=service_type) - elif not service_catalog_url: - catalog = self.keystone_client.service_catalog.get_endpoints( - service_type) - for catalog_entry in catalog.get(service_type, []): - if (catalog_entry.get("interface") == ( - endpoint_type.lower().split("url")[0]) or - catalog_entry.get(endpoint_type)): - if (region_name and not region_name == ( - catalog_entry.get( - "region", - catalog_entry.get("region_id")))): - continue - service_catalog_url = catalog_entry.get( - "url", catalog_entry.get(endpoint_type)) - break + self.keystone_client.auth, + interface=endpoint_type, + service_type=service_type, + region_name=region_name, + ) if not service_catalog_url: raise RuntimeError("Could not find Manila endpoint in catalog") self.api_version = api_version - self.client = httpclient.HTTPClient(service_catalog_url, - input_auth_token, - user_agent, - insecure=insecure, - cacert=cacert, - cert=cert, - timeout=timeout, - retries=retries, - http_log_debug=http_log_debug, - api_version=self.api_version) + self.client = httpclient.HTTPClient( + service_catalog_url, + input_auth_token, + user_agent, + insecure=insecure, + cacert=cacert, + cert=cert, + timeout=timeout, + retries=retries, + http_log_debug=http_log_debug, + api_version=self.api_version, + ) self.limits = limits.LimitsManager(self) self.services = services.ServiceManager(self) @@ -202,26 +236,30 @@ def _load_extensions(self, extensions): if extension.manager_class: setattr(self, extension.name, extension.manager_class(self)) - def _get_keystone_client(self): - # First create a Keystone session + def _get_keystone_auth_and_session(self): + """Create keystoneauth1 auth plugin and session for authentication. + + Returns: + tuple: (auth_plugin, session) for use with keystoneauth1 + """ + # Create session with SSL settings if self.insecure: verify = False else: verify = self.cacert or True ks_session = session.Session(verify=verify, cert=self.cert) - # Discover the supported keystone versions using the given url + # Discover Keystone v3 endpoint ks_discover = session.discover.Discover(ks_session, self.auth_url) - auth_url = ks_discover.url_for('v3.0') if not auth_url: raise exceptions.CommandError( 'Unable to determine the Keystone version to authenticate ' - 'with using the given auth_url.') + 'with using the given auth_url.' + ) - keystone_client = ks_client.Client( - session=ks_session, - version=(3, 0), + # Create v3 Password auth plugin + auth = identity.v3.Password( auth_url=auth_url, username=self.username, password=self.password, @@ -232,7 +270,6 @@ def _get_keystone_client(self): project_name=self.project_name, project_domain_name=self.project_domain_name, project_domain_id=self.project_domain_id, - region_name=self.region_name) + ) - keystone_client.authenticate() - return keystone_client + return auth, ks_session diff --git a/manilaclient/v1/contrib/list_extensions.py b/manilaclient/v1/contrib/list_extensions.py index 7c9508cd..d6fc3156 100644 --- a/manilaclient/v1/contrib/list_extensions.py +++ b/manilaclient/v1/contrib/list_extensions.py @@ -22,10 +22,11 @@ "Module manilaclient.v1.contrib.list_extensions is deprecated " "(taken as a basis for manilaclient.v2.contrib.list_extensions). " "The preferable way to get a client class or object is to use " - "the manilaclient.client module.") + "the manilaclient.client module." +) -class MovedModule(object): +class MovedModule: def __init__(self, new_module): self.new_module = new_module @@ -34,4 +35,5 @@ def __getattr__(self, attr): sys.modules["manilaclient.v1.contrib.list_extensions"] = MovedModule( - list_extensions) + list_extensions +) diff --git a/manilaclient/v1/limits.py b/manilaclient/v1/limits.py index 06c55766..6632a065 100644 --- a/manilaclient/v1/limits.py +++ b/manilaclient/v1/limits.py @@ -19,13 +19,15 @@ from manilaclient.v2 import limits -warnings.warn("Module manilaclient.v1.limits is deprecated (taken as a basis " - "for manilaclient.v2.limits). " - "The preferable way to get a client class or object is to use " - "the manilaclient.client module.") +warnings.warn( + "Module manilaclient.v1.limits is deprecated (taken as a basis " + "for manilaclient.v2.limits). " + "The preferable way to get a client class or object is to use " + "the manilaclient.client module." +) -class MovedModule(object): +class MovedModule: def __init__(self, new_module): self.new_module = new_module diff --git a/manilaclient/v1/quota_classes.py b/manilaclient/v1/quota_classes.py index 32e22a00..a404a8da 100644 --- a/manilaclient/v1/quota_classes.py +++ b/manilaclient/v1/quota_classes.py @@ -19,13 +19,15 @@ from manilaclient.v2 import quota_classes -warnings.warn("Module manilaclient.v1.quota_classes is deprecated (taken as " - "a basis for manilaclient.v2.quota_classes). " - "The preferable way to get a client class or object is to use " - "the manilaclient.client module.") +warnings.warn( + "Module manilaclient.v1.quota_classes is deprecated (taken as " + "a basis for manilaclient.v2.quota_classes). " + "The preferable way to get a client class or object is to use " + "the manilaclient.client module." +) -class MovedModule(object): +class MovedModule: def __init__(self, new_module): self.new_module = new_module diff --git a/manilaclient/v1/quotas.py b/manilaclient/v1/quotas.py index d0b79b6a..a7961521 100644 --- a/manilaclient/v1/quotas.py +++ b/manilaclient/v1/quotas.py @@ -19,13 +19,15 @@ from manilaclient.v2 import quotas -warnings.warn("Module manilaclient.v1.quotas is deprecated (taken as " - "a basis for manilaclient.v2.quotas). " - "The preferable way to get a client class or object is to use " - "the manilaclient.client module.") +warnings.warn( + "Module manilaclient.v1.quotas is deprecated (taken as " + "a basis for manilaclient.v2.quotas). " + "The preferable way to get a client class or object is to use " + "the manilaclient.client module." +) -class MovedModule(object): +class MovedModule: def __init__(self, new_module): self.new_module = new_module diff --git a/manilaclient/v1/scheduler_stats.py b/manilaclient/v1/scheduler_stats.py index d30a96d4..3c9fae89 100644 --- a/manilaclient/v1/scheduler_stats.py +++ b/manilaclient/v1/scheduler_stats.py @@ -19,13 +19,15 @@ from manilaclient.v2 import scheduler_stats -warnings.warn("Module manilaclient.v1.scheduler_stats is deprecated (taken as " - "a basis for manilaclient.v2.scheduler_stats). " - "The preferable way to get a client class or object is to use " - "the manilaclient.client module.") +warnings.warn( + "Module manilaclient.v1.scheduler_stats is deprecated (taken as " + "a basis for manilaclient.v2.scheduler_stats). " + "The preferable way to get a client class or object is to use " + "the manilaclient.client module." +) -class MovedModule(object): +class MovedModule: def __init__(self, new_module): self.new_module = new_module diff --git a/manilaclient/v1/security_services.py b/manilaclient/v1/security_services.py index 1819b055..a456ed1f 100644 --- a/manilaclient/v1/security_services.py +++ b/manilaclient/v1/security_services.py @@ -19,13 +19,15 @@ from manilaclient.v2 import security_services -warnings.warn("Module manilaclient.v1.security_services is deprecated (taken " - "as a basis for manilaclient.v2.security_services). " - "The preferable way to get a client class or object is to use " - "the manilaclient.client module.") +warnings.warn( + "Module manilaclient.v1.security_services is deprecated (taken " + "as a basis for manilaclient.v2.security_services). " + "The preferable way to get a client class or object is to use " + "the manilaclient.client module." +) -class MovedModule(object): +class MovedModule: def __init__(self, new_module): self.new_module = new_module @@ -33,5 +35,6 @@ def __getattr__(self, attr): return getattr(self.new_module, attr) -sys.modules[ - "manilaclient.v1.security_services"] = MovedModule(security_services) +sys.modules["manilaclient.v1.security_services"] = MovedModule( + security_services +) diff --git a/manilaclient/v1/services.py b/manilaclient/v1/services.py index 7dfbc10c..e6f16937 100644 --- a/manilaclient/v1/services.py +++ b/manilaclient/v1/services.py @@ -19,13 +19,15 @@ from manilaclient.v2 import services -warnings.warn("Module manilaclient.v1.services is deprecated (taken as " - "a basis for manilaclient.v2.services). " - "The preferable way to get a client class or object is to use " - "the manilaclient.client module.") +warnings.warn( + "Module manilaclient.v1.services is deprecated (taken as " + "a basis for manilaclient.v2.services). " + "The preferable way to get a client class or object is to use " + "the manilaclient.client module." +) -class MovedModule(object): +class MovedModule: def __init__(self, new_module): self.new_module = new_module diff --git a/manilaclient/v1/share_networks.py b/manilaclient/v1/share_networks.py index 076fbd30..4c5a346e 100644 --- a/manilaclient/v1/share_networks.py +++ b/manilaclient/v1/share_networks.py @@ -19,13 +19,15 @@ from manilaclient.v2 import share_networks -warnings.warn("Module manilaclient.v1.share_networks is deprecated (taken as " - "a basis for manilaclient.v2.share_networks). " - "The preferable way to get a client class or object is to use " - "the manilaclient.client module.") +warnings.warn( + "Module manilaclient.v1.share_networks is deprecated (taken as " + "a basis for manilaclient.v2.share_networks). " + "The preferable way to get a client class or object is to use " + "the manilaclient.client module." +) -class MovedModule(object): +class MovedModule: def __init__(self, new_module): self.new_module = new_module diff --git a/manilaclient/v1/share_servers.py b/manilaclient/v1/share_servers.py index 7440b915..d136a33f 100644 --- a/manilaclient/v1/share_servers.py +++ b/manilaclient/v1/share_servers.py @@ -19,13 +19,15 @@ from manilaclient.v2 import share_servers -warnings.warn("Module manilaclient.v1.share_servers is deprecated (taken as " - "a basis for manilaclient.v2.share_servers). " - "The preferable way to get a client class or object is to use " - "the manilaclient.client module.") +warnings.warn( + "Module manilaclient.v1.share_servers is deprecated (taken as " + "a basis for manilaclient.v2.share_servers). " + "The preferable way to get a client class or object is to use " + "the manilaclient.client module." +) -class MovedModule(object): +class MovedModule: def __init__(self, new_module): self.new_module = new_module diff --git a/manilaclient/v1/share_snapshots.py b/manilaclient/v1/share_snapshots.py index 96070a40..71192371 100644 --- a/manilaclient/v1/share_snapshots.py +++ b/manilaclient/v1/share_snapshots.py @@ -19,13 +19,15 @@ from manilaclient.v2 import share_snapshots -warnings.warn("Module manilaclient.v1.share_snapshots is deprecated (taken as " - "a basis for manilaclient.v2.share_snapshots). " - "The preferable way to get a client class or object is to use " - "the manilaclient.client module.") +warnings.warn( + "Module manilaclient.v1.share_snapshots is deprecated (taken as " + "a basis for manilaclient.v2.share_snapshots). " + "The preferable way to get a client class or object is to use " + "the manilaclient.client module." +) -class MovedModule(object): +class MovedModule: def __init__(self, new_module): self.new_module = new_module diff --git a/manilaclient/v1/share_type_access.py b/manilaclient/v1/share_type_access.py index 2da0873f..e4614a7e 100644 --- a/manilaclient/v1/share_type_access.py +++ b/manilaclient/v1/share_type_access.py @@ -19,13 +19,15 @@ from manilaclient.v2 import share_type_access -warnings.warn("Module manilaclient.v1.share_type_access is deprecated (taken " - "as a basis for manilaclient.v2.share_type_access). " - "The preferable way to get a client class or object is to use " - "the manilaclient.client module.") +warnings.warn( + "Module manilaclient.v1.share_type_access is deprecated (taken " + "as a basis for manilaclient.v2.share_type_access). " + "The preferable way to get a client class or object is to use " + "the manilaclient.client module." +) -class MovedModule(object): +class MovedModule: def __init__(self, new_module): self.new_module = new_module @@ -33,5 +35,6 @@ def __getattr__(self, attr): return getattr(self.new_module, attr) -sys.modules[ - "manilaclient.v1.share_type_access"] = MovedModule(share_type_access) +sys.modules["manilaclient.v1.share_type_access"] = MovedModule( + share_type_access +) diff --git a/manilaclient/v1/share_types.py b/manilaclient/v1/share_types.py index 793766f7..b3f64220 100644 --- a/manilaclient/v1/share_types.py +++ b/manilaclient/v1/share_types.py @@ -19,13 +19,15 @@ from manilaclient.v2 import share_types -warnings.warn("Module manilaclient.v1.share_types is deprecated (taken as " - "a basis for manilaclient.v2.share_types). " - "The preferable way to get a client class or object is to use " - "the manilaclient.client module.") +warnings.warn( + "Module manilaclient.v1.share_types is deprecated (taken as " + "a basis for manilaclient.v2.share_types). " + "The preferable way to get a client class or object is to use " + "the manilaclient.client module." +) -class MovedModule(object): +class MovedModule: def __init__(self, new_module): self.new_module = new_module diff --git a/manilaclient/v1/shares.py b/manilaclient/v1/shares.py index cc007fb9..79dd5e56 100644 --- a/manilaclient/v1/shares.py +++ b/manilaclient/v1/shares.py @@ -19,13 +19,15 @@ from manilaclient.v2 import shares -warnings.warn("Module manilaclient.v1.shares is deprecated (taken as " - "a basis for manilaclient.v2.shares). " - "The preferable way to get a client class or object is to use " - "the manilaclient.client module.") +warnings.warn( + "Module manilaclient.v1.shares is deprecated (taken as " + "a basis for manilaclient.v2.shares). " + "The preferable way to get a client class or object is to use " + "the manilaclient.client module." +) -class MovedModule(object): +class MovedModule: def __init__(self, new_module): self.new_module = new_module diff --git a/manilaclient/v2/__init__.py b/manilaclient/v2/__init__.py index c5fa79a7..a2e057d9 100644 --- a/manilaclient/v2/__init__.py +++ b/manilaclient/v2/__init__.py @@ -14,4 +14,4 @@ # License for the specific language governing permissions and limitations # under the License. -from manilaclient.v2.client import Client # noqa +from manilaclient.v2.client import Client # noqa diff --git a/manilaclient/v2/availability_zones.py b/manilaclient/v2/availability_zones.py index 52555e0d..e8ee08fe 100644 --- a/manilaclient/v2/availability_zones.py +++ b/manilaclient/v2/availability_zones.py @@ -22,13 +22,13 @@ class AvailabilityZone(base.Resource): - def __repr__(self): - return "" % self.id + return f"" class AvailabilityZoneManager(base.Manager): - """Manage :class:`Service` resources.""" + """Manage :class:`AvailabilityZone` resources.""" + resource_class = AvailabilityZone @api_versions.wraps("1.0", "2.6") diff --git a/manilaclient/v2/client.py b/manilaclient/v2/client.py index c0ff0a97..16434187 100644 --- a/manilaclient/v2/client.py +++ b/manilaclient/v2/client.py @@ -10,9 +10,10 @@ # License for the specific language governing permissions and limitations # under the License. +from debtcollector import removals from keystoneauth1 import adapter +from keystoneauth1 import identity from keystoneauth1 import session -from keystoneclient import client as ks_client import manilaclient from manilaclient.common import constants @@ -21,6 +22,7 @@ from manilaclient.v2 import availability_zones from manilaclient.v2 import limits from manilaclient.v2 import messages +from manilaclient.v2 import qos_types from manilaclient.v2 import quota_classes from manilaclient.v2 import quotas from manilaclient.v2 import resource_locks @@ -51,7 +53,7 @@ from manilaclient.v2 import shares -class Client(object): +class Client: """Top-level object to access the OpenStack Manila API. Create an instance with your creds:: @@ -64,7 +66,7 @@ class Client(object): Or, alternatively, you can create a client instance using the keystoneauth1.session API:: - >>> from keystoneclient.auth.identity import v3 + >>> from keystoneauth1.identity import v3 >>> from keystoneauth1 import session >>> from manilaclient import client >>> auth = v3.Password(auth_url=AUTH_URL, @@ -81,26 +83,60 @@ class Client(object): >>> client.shares.list() ... """ - def __init__(self, username=None, project_id=None, auth_url=None, - insecure=False, timeout=None, tenant_id=None, - project_name=None, region_name=None, - endpoint_type='publicURL', extensions=None, - service_type=constants.V2_SERVICE_TYPE, service_name=None, - retries=None, http_log_debug=False, input_auth_token=None, - session=None, auth=None, cacert=None, - service_catalog_url=None, user_agent='python-manilaclient', - use_keyring=False, force_new_token=False, - cached_token_lifetime=300, - api_version=manilaclient.API_MIN_VERSION, - user_id=None, - user_domain_id=None, - user_domain_name=None, - project_domain_id=None, - project_domain_name=None, - cert=None, - password=None, - **kwargs): + @removals.removed_kwarg( + 'use_keyring', + message='This parameter is no longer supported and has no effect.', + version='5.8.0', + removal_version='6.0.0', + ) + @removals.removed_kwarg( + 'force_new_token', + message='This parameter is no longer supported and has no effect.', + version='5.8.0', + removal_version='6.0.0', + ) + @removals.removed_kwarg( + 'cached_token_lifetime', + message='This parameter is no longer supported and has no effect.', + version='5.8.0', + removal_version='6.0.0', + ) + def __init__( + self, + username=None, + project_id=None, + auth_url=None, + insecure=False, + timeout=None, + tenant_id=None, + project_name=None, + region_name=None, + endpoint_type='publicURL', + extensions=None, + service_type=constants.V2_SERVICE_TYPE, + service_name=None, + retries=None, + http_log_debug=False, + input_auth_token=None, + session=None, + auth=None, + cacert=None, + service_catalog_url=None, + user_agent='python-manilaclient', + use_keyring=False, + force_new_token=False, + cached_token_lifetime=300, + api_version=manilaclient.API_MIN_VERSION, + user_id=None, + user_domain_id=None, + user_domain_name=None, + project_domain_id=None, + project_domain_name=None, + cert=None, + password=None, + **kwargs, + ): self.username = username self.password = password self.tenant_id = tenant_id or project_id @@ -122,13 +158,11 @@ def __init__(self, username=None, project_id=None, auth_url=None, self.cert = cert self.insecure = insecure - self.use_keyring = use_keyring - self.force_new_token = force_new_token - self.cached_token_lifetime = cached_token_lifetime - if input_auth_token and not service_catalog_url: - msg = ("For token-based authentication you should " - "provide 'input_auth_token' and 'service_catalog_url'.") + msg = ( + "For token-based authentication you should " + "provide 'input_auth_token' and 'service_catalog_url'." + ) raise exceptions.ClientException(msg) self.project_id = tenant_id if tenant_id is not None else project_id @@ -140,67 +174,71 @@ def __init__(self, username=None, project_id=None, auth_url=None, # if token is provided. if not input_auth_token: if session: + # Modern path - session provided by caller (e.g., OSC plugin) self.keystone_client = adapter.LegacyJsonAdapter( session=session, auth=auth, interface=endpoint_type, service_type=service_type, service_name=service_name, - region_name=region_name) + region_name=region_name, + ) input_auth_token = self.keystone_client.session.get_token(auth) - else: - self.keystone_client = self._get_keystone_client() - input_auth_token = self.keystone_client.auth_token + # Legacy path - create auth plugin and session ourselves + auth, ks_session = self._get_keystone_auth_and_session() + self.keystone_client = adapter.LegacyJsonAdapter( + session=ks_session, + auth=auth, + interface=endpoint_type, + service_type=service_type, + service_name=service_name, + region_name=region_name, + ) + input_auth_token = self.keystone_client.session.get_token(auth) if not input_auth_token: raise RuntimeError("Not Authorized") - if session and not service_catalog_url: + if not service_catalog_url: + # Use keystoneauth1 session endpoint discovery service_catalog_url = self.keystone_client.session.get_endpoint( - auth, interface=endpoint_type, - service_type=service_type) - elif not service_catalog_url: - catalog = self.keystone_client.service_catalog.get_endpoints( - service_type) - for catalog_entry in catalog.get(service_type, []): - if (catalog_entry.get("interface") == ( - endpoint_type.lower().split("url")[0]) or - catalog_entry.get(endpoint_type)): - if (region_name and not region_name == ( - catalog_entry.get( - "region", - catalog_entry.get("region_id")))): - continue - service_catalog_url = catalog_entry.get( - "url", catalog_entry.get(endpoint_type)) - break + self.keystone_client.auth, + interface=endpoint_type, + service_type=service_type, + region_name=region_name, + ) if not service_catalog_url: raise RuntimeError("Could not find Manila endpoint in catalog") self.api_version = api_version - self.client = httpclient.HTTPClient(service_catalog_url, - input_auth_token, - user_agent, - insecure=insecure, - cacert=cacert, - cert=cert, - timeout=timeout, - retries=retries, - http_log_debug=http_log_debug, - api_version=self.api_version) + self.client = httpclient.HTTPClient( + service_catalog_url, + input_auth_token, + user_agent, + insecure=insecure, + cacert=cacert, + cert=cert, + timeout=timeout, + retries=retries, + http_log_debug=http_log_debug, + api_version=self.api_version, + ) self.availability_zones = availability_zones.AvailabilityZoneManager( - self) + self + ) self.limits = limits.LimitsManager(self) self.transfers = share_transfers.ShareTransferManager(self) self.messages = messages.MessageManager(self) + self.qos_types = qos_types.QosTypeManager(self) self.services = services.ServiceManager(self) self.security_services = security_services.SecurityServiceManager(self) self.share_networks = share_networks.ShareNetworkManager(self) self.share_network_subnets = ( - share_network_subnets.ShareNetworkSubnetManager(self)) + share_network_subnets.ShareNetworkSubnetManager(self) + ) self.quota_classes = quota_classes.QuotaClassSetManager(self) self.quotas = quotas.QuotaSetManager(self) @@ -209,26 +247,34 @@ def __init__(self, username=None, project_id=None, auth_url=None, self.shares = shares.ShareManager(self) self.share_export_locations = ( - share_export_locations.ShareExportLocationManager(self)) + share_export_locations.ShareExportLocationManager(self) + ) self.share_groups = share_groups.ShareGroupManager(self) self.share_group_snapshots = ( - share_group_snapshots.ShareGroupSnapshotManager(self)) + share_group_snapshots.ShareGroupSnapshotManager(self) + ) self.share_group_type_access = ( - share_group_type_access.ShareGroupTypeAccessManager(self)) + share_group_type_access.ShareGroupTypeAccessManager(self) + ) self.share_group_types = share_group_types.ShareGroupTypeManager(self) self.share_instances = share_instances.ShareInstanceManager(self) self.share_instance_export_locations = ( share_instance_export_locations.ShareInstanceExportLocationManager( - self)) + self + ) + ) self.share_snapshots = share_snapshots.ShareSnapshotManager(self) self.share_snapshot_instances = ( - share_snapshot_instances.ShareSnapshotInstanceManager(self)) + share_snapshot_instances.ShareSnapshotInstanceManager(self) + ) self.share_snapshot_export_locations = ( share_snapshot_export_locations.ShareSnapshotExportLocationManager( - self)) - self.share_snapshot_instance_export_locations = ( - share_snapshot_instance_export_locations. - ShareSnapshotInstanceExportLocationManager(self)) + self + ) + ) + self.share_snapshot_instance_export_locations = share_snapshot_instance_export_locations.ShareSnapshotInstanceExportLocationManager( # noqa: E501 + self + ) self.share_types = share_types.ShareTypeManager(self) self.share_type_access = share_type_access.ShareTypeAccessManager(self) @@ -236,10 +282,13 @@ def __init__(self, username=None, project_id=None, auth_url=None, self.share_replicas = share_replicas.ShareReplicaManager(self) self.share_replica_export_locations = ( share_replica_export_locations.ShareReplicaExportLocationManager( - self)) + self + ) + ) self.pools = scheduler_stats.PoolManager(self) - self.share_access_rules = ( - share_access_rules.ShareAccessRuleManager(self)) + self.share_access_rules = share_access_rules.ShareAccessRuleManager( + self + ) self.share_backups = share_backups.ShareBackupManager(self) self._load_extensions(extensions) @@ -252,26 +301,30 @@ def _load_extensions(self, extensions): if extension.manager_class: setattr(self, extension.name, extension.manager_class(self)) - def _get_keystone_client(self): - # First create a Keystone session + def _get_keystone_auth_and_session(self): + """Create keystoneauth1 auth plugin and session for authentication. + + Returns: + tuple: (auth_plugin, session) for use with keystoneauth1 + """ + # Create session with SSL settings if self.insecure: verify = False else: verify = self.cacert or True ks_session = session.Session(verify=verify, cert=self.cert) - # Discover the supported keystone versions using the given url + # Discover Keystone v3 endpoint ks_discover = session.discover.Discover(ks_session, self.auth_url) - auth_url = ks_discover.url_for('v3.0') if not auth_url: raise exceptions.CommandError( 'Unable to determine the Keystone version to authenticate ' - 'with using the given auth_url.') + 'with using the given auth_url.' + ) - keystone_client = ks_client.Client( - session=ks_session, - version=(3, 0), + # Create v3 Password auth plugin + auth = identity.v3.Password( auth_url=auth_url, username=self.username, password=self.password, @@ -282,7 +335,6 @@ def _get_keystone_client(self): project_name=self.project_name, project_domain_name=self.project_domain_name, project_domain_id=self.project_domain_id, - region_name=self.region_name) + ) - keystone_client.authenticate() - return keystone_client + return auth, ks_session diff --git a/manilaclient/v2/limits.py b/manilaclient/v2/limits.py index 1a46cf67..9cfb93a4 100644 --- a/manilaclient/v2/limits.py +++ b/manilaclient/v2/limits.py @@ -25,7 +25,7 @@ def __repr__(self): @property def absolute(self): - for (name, value) in list(self._info['absolute'].items()): + for name, value in list(self._info['absolute'].items()): yield AbsoluteLimit(name, value) @property @@ -34,16 +34,21 @@ def rate(self): uri = group['uri'] regex = group['regex'] for rate in group['limit']: - yield RateLimit(rate['verb'], uri, regex, rate['value'], - rate['remaining'], rate['unit'], - rate['next-available']) - - -class RateLimit(object): + yield RateLimit( + rate['verb'], + uri, + regex, + rate['value'], + rate['remaining'], + rate['unit'], + rate['next-available'], + ) + + +class RateLimit: """Data model that represents a flattened view of a single rate limit.""" - def __init__(self, verb, uri, regex, value, remain, - unit, next_available): + def __init__(self, verb, uri, regex, value, remain, unit, next_available): self.verb = verb self.uri = uri self.regex = regex @@ -54,19 +59,21 @@ def __init__(self, verb, uri, regex, value, remain, self.next_available = next_available def __eq__(self, other): - return (self.uri == other.uri and - self.regex == other.regex and - self.value == other.value and - self.verb == other.verb and - self.remain == other.remain and - self.unit == other.unit and - self.next_available == other.next_available) + return ( + self.uri == other.uri + and self.regex == other.regex + and self.value == other.value + and self.verb == other.verb + and self.remain == other.remain + and self.unit == other.unit + and self.next_available == other.next_available + ) def __repr__(self): - return "" % (self.verb, self.uri) + return f"" -class AbsoluteLimit(object): +class AbsoluteLimit: """Data model that represents a single absolute limit.""" def __init__(self, name, value): @@ -77,7 +84,7 @@ def __eq__(self, other): return self.value == other.value and self.name == other.name def __repr__(self): - return "" % (self.name) + return f"" class LimitsManager(base.Manager): diff --git a/manilaclient/v2/messages.py b/manilaclient/v2/messages.py index ef54250d..7b638d78 100644 --- a/manilaclient/v2/messages.py +++ b/manilaclient/v2/messages.py @@ -11,6 +11,7 @@ # under the License. """Asynchronous User Message interface.""" + from manilaclient import api_versions from manilaclient import base from manilaclient.common import constants @@ -25,7 +26,7 @@ class Message(base.Resource): NAME_ATTR = 'id' def __repr__(self): - return "" % self.id + return f"" def delete(self): """Delete this message.""" @@ -34,6 +35,7 @@ def delete(self): class MessageManager(base.ManagerWithFind): """Manage :class:`Message` resources.""" + resource_class = Message @api_versions.wraps('2.37') @@ -59,15 +61,20 @@ def list(self, search_opts=None, sort_key=None, sort_dir=None): search_opts['sort_key'] = sort_key else: raise ValueError( - 'sort_key must be one of the following: %s.' - % ', '.join(constants.MESSAGE_SORT_KEY_VALUES)) + 'sort_key must be one of the following: {}.'.format( + ', '.join(constants.MESSAGE_SORT_KEY_VALUES) + ) + ) if sort_dir is not None: if sort_dir in constants.SORT_DIR_VALUES: search_opts['sort_dir'] = sort_dir else: - raise ValueError('sort_dir must be one of the following: %s.' - % ', '.join(constants.SORT_DIR_VALUES)) + raise ValueError( + 'sort_dir must be one of the following: {}.'.format( + ', '.join(constants.SORT_DIR_VALUES) + ) + ) query_string = self._build_query_string(search_opts) diff --git a/manilaclient/v2/qos_types.py b/manilaclient/v2/qos_types.py new file mode 100644 index 00000000..d64d2364 --- /dev/null +++ b/manilaclient/v2/qos_types.py @@ -0,0 +1,185 @@ +# Copyright (c) 2025 Cloudification GmbH. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +""" +Qos Type interface. +""" + +from manilaclient import api_versions +from manilaclient import base +from manilaclient.common import constants + + +class QosType(base.Resource): + """A Qos Type represents Quality of service of Manila resource.""" + + def __init__(self, manager, info, loaded=False): + super().__init__(manager, info, loaded) + self._specs = info.get('specs', {}) + + def __repr__(self): + return f"" + + def get_keys(self, prefer_resource_data=True): + """Get specs from a qos type. + + :param prefer_resource_data: By default specs are retrieved from + resource data, but user can force this method to make API call. + :return: dict with specs + """ + specs = getattr(self, 'specs', None) + + if prefer_resource_data and specs: + return specs + + qos_type_id = base.getid(self) + _resp, body = self.manager.api.client.get( + f"/qos-types/{qos_type_id}/specs" + ) + + self.specs = body["specs"] + + return body["specs"] + + def set_keys(self, metadata): + """Set specs on a qos type. + + :param metadata: A dict of key/value pairs to be set + """ + body = {'specs': metadata} + qos_type_id = base.getid(self) + return self.manager._create( + f"/qos-types/{qos_type_id}/specs", + body, + "specs", + return_raw=True, + ) + + def unset_keys(self, keys): + """Unset specs on a qos type. + + :param keys: A list of keys to be unset + """ + qos_type_id = base.getid(self) + for k in keys: + self.manager._delete(f"/qos-types/{qos_type_id}/specs/{k}") + + def update(self, **kwargs): + """Update this qos type.""" + return self.manager.update(self, **kwargs) + + def delete(self): + """Delete this qos type.""" + return self.manager.delete(self) + + +class QosTypeManager(base.ManagerWithFind): + """Manage :class:`QosType` resources.""" + + resource_class = QosType + + @api_versions.wraps(constants.QOS_TYPE_VERSION) + def list(self, search_opts=None, sort_key=None, sort_dir=None): + """Get a list of all qos types. + + :param search_opts: Search options to filter out qos types. + :param sort_key: Key to be sorted. + :param sort_dir: Sort direction, should be 'desc' or 'asc'. + :rtype: list of :class:`QosType`. + """ + search_opts = search_opts or {} + + if sort_key is not None: + if sort_key in constants.QOS_TYPE_SORT_KEY_VALUES: + search_opts['sort_key'] = sort_key + else: + raise ValueError( + 'sort_key must be one of the following: {}.'.format( + ', '.join(constants.QOS_TYPE_SORT_KEY_VALUES) + ) + ) + + if sort_dir is not None: + if sort_dir in constants.SORT_DIR_VALUES: + search_opts['sort_dir'] = sort_dir + else: + raise ValueError( + 'sort_dir must be one of the following: {}.'.format( + ', '.join(constants.SORT_DIR_VALUES) + ) + ) + + query_string = self._build_query_string(search_opts) + return self._list(f"/qos-types{query_string}", "qos_types") + + @api_versions.wraps(constants.QOS_TYPE_VERSION) + def get(self, qos_type): + """Get a specific qos type. + + :param qos_type: The ID of the :class:`QosType` to get. + :rtype: :class:`QosType` + """ + qos_type_id = base.getid(qos_type) + return self._get(f"/qos-types/{qos_type_id}", "qos_type") + + @api_versions.wraps(constants.QOS_TYPE_VERSION) + def delete(self, qos_type): + """Delete a specific qos_type. + + :param qos_type: The name or ID of the :class:`QosType` to get. + """ + qos_type_id = base.getid(qos_type) + self._delete(f"/qos-types/{qos_type_id}") + + @api_versions.wraps(constants.QOS_TYPE_VERSION) + def create(self, name, description=None, specs=None): + """Create a qos type. + + :param name: Descriptive name of the qos type + :param specs: Specs of the qos type + :rtype: :class:`QosType` + """ + if specs is None: + specs = {} + + body = { + "qos_type": { + "name": name, + "specs": specs, + } + } + + if description: + body["qos_type"]["description"] = description + return self._create("/qos-types", body, "qos_type") + + @api_versions.wraps(constants.QOS_TYPE_VERSION) + def update(self, qos_type, **kwargs): + """Update the description for a qos type. + + :param qos_type: the ID of the :class: `QosType` to update. + :param description: Description of the qos type. + :rtype: :class:`QosType` + """ + + if not kwargs: + return + + body = { + 'qos_type': kwargs, + } + qos_type_id = base.getid(qos_type) + return self._update(f"/qos-types/{qos_type_id}", body, "qos_type") diff --git a/manilaclient/v2/quota_classes.py b/manilaclient/v2/quota_classes.py index 4acc972b..338a0579 100644 --- a/manilaclient/v2/quota_classes.py +++ b/manilaclient/v2/quota_classes.py @@ -22,7 +22,6 @@ class QuotaClassSet(base.Resource): - @property def id(self): """Needed by base.Resource to self-refresh and be indexed.""" @@ -38,24 +37,28 @@ class QuotaClassSetManager(base.ManagerWithFind): @api_versions.wraps("1.0", "2.6") def get(self, class_name): return self._get( - "%(resource_path)s/%(class_name)s" % { - "resource_path": RESOURCE_PATH_LEGACY, - "class_name": class_name}, - "quota_class_set") + f"{RESOURCE_PATH_LEGACY}/{class_name}", "quota_class_set" + ) @api_versions.wraps("2.7") # noqa def get(self, class_name): # noqa - return self._get( - "%(resource_path)s/%(class_name)s" % { - "resource_path": RESOURCE_PATH, "class_name": class_name}, - "quota_class_set") - - def _do_update(self, class_name, shares=None, gigabytes=None, - snapshots=None, snapshot_gigabytes=None, - share_networks=None, share_replicas=None, - replica_gigabytes=None, per_share_gigabytes=None, - share_groups=None, share_group_snapshots=None, - resource_path=RESOURCE_PATH): + return self._get(f"{RESOURCE_PATH}/{class_name}", "quota_class_set") + + def _do_update( + self, + class_name, + shares=None, + gigabytes=None, + snapshots=None, + snapshot_gigabytes=None, + share_networks=None, + share_replicas=None, + replica_gigabytes=None, + per_share_gigabytes=None, + share_groups=None, + share_group_snapshots=None, + resource_path=RESOURCE_PATH, + ): body = { 'quota_class_set': { 'class_name': class_name, @@ -76,64 +79,126 @@ def _do_update(self, class_name, shares=None, gigabytes=None, if body['quota_class_set'][key] is None: body['quota_class_set'].pop(key) - self._update( - "%(resource_path)s/%(class_name)s" % { - "resource_path": resource_path, - "class_name": class_name}, - body) + self._update(f"{resource_path}/{class_name}", body) @api_versions.wraps("1.0", "2.6") - def update(self, class_name, shares=None, gigabytes=None, - snapshots=None, snapshot_gigabytes=None, share_networks=None): + def update( + self, + class_name, + shares=None, + gigabytes=None, + snapshots=None, + snapshot_gigabytes=None, + share_networks=None, + ): return self._do_update( - class_name, shares=shares, gigabytes=gigabytes, - snapshots=snapshots, snapshot_gigabytes=snapshot_gigabytes, - share_networks=share_networks, resource_path=RESOURCE_PATH_LEGACY) + class_name, + shares=shares, + gigabytes=gigabytes, + snapshots=snapshots, + snapshot_gigabytes=snapshot_gigabytes, + share_networks=share_networks, + resource_path=RESOURCE_PATH_LEGACY, + ) @api_versions.wraps("2.7", "2.39") # noqa - def update(self, class_name, shares=None, gigabytes=None, # noqa - snapshots=None, snapshot_gigabytes=None, share_networks=None): + def update( # noqa + self, + class_name, + shares=None, + gigabytes=None, + snapshots=None, + snapshot_gigabytes=None, + share_networks=None, + ): return self._do_update( - class_name, shares=shares, gigabytes=gigabytes, - snapshots=snapshots, snapshot_gigabytes=snapshot_gigabytes, - share_networks=share_networks, resource_path=RESOURCE_PATH) + class_name, + shares=shares, + gigabytes=gigabytes, + snapshots=snapshots, + snapshot_gigabytes=snapshot_gigabytes, + share_networks=share_networks, + resource_path=RESOURCE_PATH, + ) @api_versions.wraps("2.40", "2.52") # noqa - def update(self, class_name, shares=None, gigabytes=None, # noqa - snapshots=None, snapshot_gigabytes=None, share_networks=None, - share_groups=None, share_group_snapshots=None): + def update( # noqa + self, + class_name, + shares=None, + gigabytes=None, + snapshots=None, + snapshot_gigabytes=None, + share_networks=None, + share_groups=None, + share_group_snapshots=None, + ): return self._do_update( - class_name, shares=shares, gigabytes=gigabytes, - snapshots=snapshots, snapshot_gigabytes=snapshot_gigabytes, - share_networks=share_networks, share_groups=share_groups, + class_name, + shares=shares, + gigabytes=gigabytes, + snapshots=snapshots, + snapshot_gigabytes=snapshot_gigabytes, + share_networks=share_networks, + share_groups=share_groups, share_group_snapshots=share_group_snapshots, - resource_path=RESOURCE_PATH) + resource_path=RESOURCE_PATH, + ) @api_versions.wraps(REPLICA_QUOTAS_MICROVERSION, "2.61") # noqa - def update(self, class_name, shares=None, gigabytes=None, # noqa - snapshots=None, snapshot_gigabytes=None, share_networks=None, - share_groups=None, share_group_snapshots=None, - share_replicas=None, replica_gigabytes=None): + def update( # noqa + self, + class_name, + shares=None, + gigabytes=None, + snapshots=None, + snapshot_gigabytes=None, + share_networks=None, + share_groups=None, + share_group_snapshots=None, + share_replicas=None, + replica_gigabytes=None, + ): return self._do_update( - class_name, shares=shares, gigabytes=gigabytes, - snapshots=snapshots, snapshot_gigabytes=snapshot_gigabytes, - share_networks=share_networks, share_groups=share_groups, + class_name, + shares=shares, + gigabytes=gigabytes, + snapshots=snapshots, + snapshot_gigabytes=snapshot_gigabytes, + share_networks=share_networks, + share_groups=share_groups, share_group_snapshots=share_group_snapshots, - share_replicas=share_replicas, replica_gigabytes=replica_gigabytes, - resource_path=RESOURCE_PATH) + share_replicas=share_replicas, + replica_gigabytes=replica_gigabytes, + resource_path=RESOURCE_PATH, + ) @api_versions.wraps("2.62") # noqa - def update(self, class_name, shares=None, gigabytes=None, # noqa - snapshots=None, snapshot_gigabytes=None, share_networks=None, - share_groups=None, share_group_snapshots=None, - share_replicas=None, replica_gigabytes=None, - per_share_gigabytes=None): + def update( # noqa + self, + class_name, + shares=None, + gigabytes=None, + snapshots=None, + snapshot_gigabytes=None, + share_networks=None, + share_groups=None, + share_group_snapshots=None, + share_replicas=None, + replica_gigabytes=None, + per_share_gigabytes=None, + ): return self._do_update( - class_name, shares=shares, gigabytes=gigabytes, - snapshots=snapshots, snapshot_gigabytes=snapshot_gigabytes, - share_networks=share_networks, share_groups=share_groups, + class_name, + shares=shares, + gigabytes=gigabytes, + snapshots=snapshots, + snapshot_gigabytes=snapshot_gigabytes, + share_networks=share_networks, + share_groups=share_groups, share_group_snapshots=share_group_snapshots, share_replicas=share_replicas, replica_gigabytes=replica_gigabytes, per_share_gigabytes=per_share_gigabytes, - resource_path=RESOURCE_PATH) + resource_path=RESOURCE_PATH, + ) diff --git a/manilaclient/v2/quotas.py b/manilaclient/v2/quotas.py index a4a68838..46bda801 100644 --- a/manilaclient/v2/quotas.py +++ b/manilaclient/v2/quotas.py @@ -22,7 +22,6 @@ class QuotaSet(base.Resource): - @property def id(self): """Needed by Resource to self-refresh and be indexed.""" @@ -39,10 +38,17 @@ def _check_user_id_and_share_type_args(self, user_id, share_type): if user_id and share_type: raise ValueError( "'user_id' and 'share_type' values are mutually exclusive. " - "one or both should be unset.") - - def _do_get(self, tenant_id, user_id=None, share_type=None, detail=False, - resource_path=RESOURCE_PATH): + "one or both should be unset." + ) + + def _do_get( + self, + tenant_id, + user_id=None, + share_type=None, + detail=False, + resource_path=RESOURCE_PATH, + ): self._check_user_id_and_share_type_args(user_id, share_type) if hasattr(tenant_id, 'tenant_id'): tenant_id = tenant_id.tenant_id @@ -53,12 +59,11 @@ def _do_get(self, tenant_id, user_id=None, share_type=None, detail=False, query = '' if user_id and share_type: - query = '%s?user_id=%s&share_type=%s' % ( - query, user_id, share_type) + query = f'{query}?user_id={user_id}&share_type={share_type}' elif user_id: - query = '%s?user_id=%s' % (query, user_id) + query = f'{query}?user_id={user_id}' elif share_type: - query = '%s?share_type=%s' % (query, share_type) + query = f'{query}?share_type={share_type}' data = { "resource_path": resource_path, "tenant_id": tenant_id, @@ -69,33 +74,49 @@ def _do_get(self, tenant_id, user_id=None, share_type=None, detail=False, @api_versions.wraps("1.0", "2.6") def get(self, tenant_id, user_id=None, detail=False): - return self._do_get(tenant_id, user_id, - resource_path=RESOURCE_PATH_LEGACY) + return self._do_get( + tenant_id, user_id, resource_path=RESOURCE_PATH_LEGACY + ) @api_versions.wraps("2.7", "2.24") # noqa def get(self, tenant_id, user_id=None, detail=False): # noqa - return self._do_get(tenant_id, user_id, - resource_path=RESOURCE_PATH) + return self._do_get(tenant_id, user_id, resource_path=RESOURCE_PATH) @api_versions.wraps("2.25", "2.38") # noqa def get(self, tenant_id, user_id=None, detail=False): # noqa - return self._do_get(tenant_id, user_id, detail=detail, - resource_path=RESOURCE_PATH) + return self._do_get( + tenant_id, user_id, detail=detail, resource_path=RESOURCE_PATH + ) @api_versions.wraps("2.39") # noqa - def get(self, tenant_id, user_id=None, share_type=None, detail=False): # noqa + def get(self, tenant_id, user_id=None, share_type=None, detail=False): # noqa return self._do_get( - tenant_id, user_id, share_type=share_type, detail=detail, - resource_path=RESOURCE_PATH) - - def _do_update(self, tenant_id, shares=None, snapshots=None, - gigabytes=None, snapshot_gigabytes=None, - share_networks=None, - force=None, user_id=None, share_type=None, - share_groups=None, share_group_snapshots=None, - share_replicas=None, replica_gigabytes=None, - per_share_gigabytes=None, - resource_path=RESOURCE_PATH): + tenant_id, + user_id, + share_type=share_type, + detail=detail, + resource_path=RESOURCE_PATH, + ) + + def _do_update( + self, + tenant_id, + shares=None, + snapshots=None, + gigabytes=None, + snapshot_gigabytes=None, + share_networks=None, + force=None, + user_id=None, + share_type=None, + share_groups=None, + share_group_snapshots=None, + share_replicas=None, + replica_gigabytes=None, + per_share_gigabytes=None, + encryption_keys=None, + resource_path=RESOURCE_PATH, + ): self._check_user_id_and_share_type_args(user_id, share_type) body = { 'quota_set': { @@ -111,6 +132,7 @@ def _do_update(self, tenant_id, shares=None, snapshots=None, 'share_replicas': share_replicas, 'replica_gigabytes': replica_gigabytes, 'per_share_gigabytes': per_share_gigabytes, + 'encryption_keys': encryption_keys, }, } @@ -124,60 +146,123 @@ def _do_update(self, tenant_id, shares=None, snapshots=None, "st": share_type, } if user_id: - url = '%(resource_path)s/%(tenant_id)s?user_id=%(user_id)s' % data + url = '{resource_path}/{tenant_id}?user_id={user_id}'.format( + **data + ) elif share_type: - url = '%(resource_path)s/%(tenant_id)s?share_type=%(st)s' % data + url = '{resource_path}/{tenant_id}?share_type={st}'.format(**data) else: - url = "%(resource_path)s/%(tenant_id)s" % data + url = "{resource_path}/{tenant_id}".format(**data) return self._update(url, body, 'quota_set') @api_versions.wraps("1.0", "2.6") - def update(self, tenant_id, shares=None, snapshots=None, gigabytes=None, - snapshot_gigabytes=None, share_networks=None, force=None, - user_id=None): + def update( + self, + tenant_id, + shares=None, + snapshots=None, + gigabytes=None, + snapshot_gigabytes=None, + share_networks=None, + force=None, + user_id=None, + ): return self._do_update( - tenant_id, shares, snapshots, gigabytes, snapshot_gigabytes, - share_networks, force, user_id, resource_path=RESOURCE_PATH_LEGACY, + tenant_id, + shares, + snapshots, + gigabytes, + snapshot_gigabytes, + share_networks, + force, + user_id, + resource_path=RESOURCE_PATH_LEGACY, ) @api_versions.wraps("2.7", "2.38") # noqa - def update(self, tenant_id, shares=None, snapshots=None, gigabytes=None, # noqa - snapshot_gigabytes=None, share_networks=None, force=None, - user_id=None): + def update( # noqa + self, + tenant_id, + shares=None, + snapshots=None, + gigabytes=None, + snapshot_gigabytes=None, + share_networks=None, + force=None, + user_id=None, + ): return self._do_update( - tenant_id, shares, snapshots, gigabytes, snapshot_gigabytes, - share_networks, force, user_id, resource_path=RESOURCE_PATH, + tenant_id, + shares, + snapshots, + gigabytes, + snapshot_gigabytes, + share_networks, + force, + user_id, + resource_path=RESOURCE_PATH, ) def _validate_st_and_sn_in_same_request(self, share_type, share_networks): if share_type and share_networks: raise ValueError( "'share_networks' quota can be set only for project or user, " - "not share type.") + "not share type." + ) @api_versions.wraps("2.39", "2.39") # noqa - def update(self, tenant_id, user_id=None, share_type=None, # noqa - shares=None, snapshots=None, gigabytes=None, - snapshot_gigabytes=None, share_networks=None, force=None): + def update( # noqa + self, + tenant_id, + user_id=None, + share_type=None, + shares=None, + snapshots=None, + gigabytes=None, + snapshot_gigabytes=None, + share_networks=None, + force=None, + ): self._validate_st_and_sn_in_same_request(share_type, share_networks) return self._do_update( - tenant_id, shares, snapshots, gigabytes, snapshot_gigabytes, - share_networks, force, user_id, + tenant_id, + shares, + snapshots, + gigabytes, + snapshot_gigabytes, + share_networks, + force, + user_id, share_type=share_type, resource_path=RESOURCE_PATH, ) @api_versions.wraps("2.40", "2.52") # noqa - def update(self, tenant_id, user_id=None, share_type=None, # noqa - shares=None, snapshots=None, gigabytes=None, - snapshot_gigabytes=None, share_networks=None, - share_groups=None, share_group_snapshots=None, - force=None): + def update( # noqa + self, + tenant_id, + user_id=None, + share_type=None, + shares=None, + snapshots=None, + gigabytes=None, + snapshot_gigabytes=None, + share_networks=None, + share_groups=None, + share_group_snapshots=None, + force=None, + ): self._validate_st_and_sn_in_same_request(share_type, share_networks) return self._do_update( - tenant_id, shares, snapshots, gigabytes, snapshot_gigabytes, - share_networks, force, user_id, + tenant_id, + shares, + snapshots, + gigabytes, + snapshot_gigabytes, + share_networks, + force, + user_id, share_type=share_type, share_groups=share_groups, share_group_snapshots=share_group_snapshots, @@ -185,59 +270,133 @@ def update(self, tenant_id, user_id=None, share_type=None, # noqa ) @api_versions.wraps(REPLICA_QUOTAS_MICROVERSION, "2.61") # noqa - def update(self, tenant_id, user_id=None, share_type=None, # noqa - shares=None, snapshots=None, gigabytes=None, - snapshot_gigabytes=None, share_networks=None, - share_groups=None, share_group_snapshots=None, - share_replicas=None, replica_gigabytes=None, force=None): + def update( # noqa + self, + tenant_id, + user_id=None, + share_type=None, + shares=None, + snapshots=None, + gigabytes=None, + snapshot_gigabytes=None, + share_networks=None, + share_groups=None, + share_group_snapshots=None, + share_replicas=None, + replica_gigabytes=None, + force=None, + ): self._validate_st_and_sn_in_same_request(share_type, share_networks) return self._do_update( - tenant_id, shares, snapshots, gigabytes, snapshot_gigabytes, - share_networks, force, user_id, + tenant_id, + shares, + snapshots, + gigabytes, + snapshot_gigabytes, + share_networks, + force, + user_id, share_type=share_type, share_groups=share_groups, share_group_snapshots=share_group_snapshots, share_replicas=share_replicas, replica_gigabytes=replica_gigabytes, - resource_path=RESOURCE_PATH + resource_path=RESOURCE_PATH, ) - @api_versions.wraps("2.62") # noqa - def update(self, tenant_id, user_id=None, share_type=None, # noqa - shares=None, snapshots=None, gigabytes=None, - snapshot_gigabytes=None, share_networks=None, - share_groups=None, share_group_snapshots=None, - share_replicas=None, replica_gigabytes=None, force=None, - per_share_gigabytes=None): + @api_versions.wraps("2.62", "2.89") # noqa + def update( # noqa + self, + tenant_id, + user_id=None, + share_type=None, + shares=None, + snapshots=None, + gigabytes=None, + snapshot_gigabytes=None, + share_networks=None, + share_groups=None, + share_group_snapshots=None, + share_replicas=None, + replica_gigabytes=None, + force=None, + per_share_gigabytes=None, + ): self._validate_st_and_sn_in_same_request(share_type, share_networks) return self._do_update( - tenant_id, shares, snapshots, gigabytes, snapshot_gigabytes, - share_networks, force, user_id, + tenant_id, + shares, + snapshots, + gigabytes, + snapshot_gigabytes, + share_networks, + force, + user_id, share_type=share_type, share_groups=share_groups, share_group_snapshots=share_group_snapshots, share_replicas=share_replicas, replica_gigabytes=replica_gigabytes, per_share_gigabytes=per_share_gigabytes, - resource_path=RESOURCE_PATH + resource_path=RESOURCE_PATH, + ) + + @api_versions.wraps("2.90") # noqa + def update( # noqa + self, + tenant_id, + user_id=None, + share_type=None, + shares=None, + snapshots=None, + gigabytes=None, + snapshot_gigabytes=None, + share_networks=None, + share_groups=None, + share_group_snapshots=None, + share_replicas=None, + replica_gigabytes=None, + force=None, + per_share_gigabytes=None, + encryption_keys=None, + ): + self._validate_st_and_sn_in_same_request(share_type, share_networks) + return self._do_update( + tenant_id, + shares, + snapshots, + gigabytes, + snapshot_gigabytes, + share_networks, + force, + user_id, + share_type=share_type, + share_groups=share_groups, + share_group_snapshots=share_group_snapshots, + share_replicas=share_replicas, + replica_gigabytes=replica_gigabytes, + per_share_gigabytes=per_share_gigabytes, + encryption_keys=encryption_keys, + resource_path=RESOURCE_PATH, ) @api_versions.wraps("1.0", "2.6") def defaults(self, tenant_id): return self._get( - "%(resource_path)s/%(tenant_id)s/defaults" % { - "resource_path": RESOURCE_PATH_LEGACY, "tenant_id": tenant_id}, - "quota_set") + f"{RESOURCE_PATH_LEGACY}/{tenant_id}/defaults", "quota_set" + ) @api_versions.wraps("2.7") # noqa def defaults(self, tenant_id): # noqa - return self._get( - "%(resource_path)s/%(tenant_id)s/defaults" % { - "resource_path": RESOURCE_PATH, "tenant_id": tenant_id}, - "quota_set") - - def _do_delete(self, tenant_id, user_id=None, share_type=None, - resource_path=RESOURCE_PATH): + return self._get(f"{RESOURCE_PATH}/{tenant_id}/defaults", "quota_set") + + def _do_delete( + self, + tenant_id, + user_id=None, + share_type=None, + resource_path=RESOURCE_PATH, + ): self._check_user_id_and_share_type_args(user_id, share_type) data = { "resource_path": resource_path, @@ -246,23 +405,27 @@ def _do_delete(self, tenant_id, user_id=None, share_type=None, "st": share_type, } if user_id: - url = '%(resource_path)s/%(tenant_id)s?user_id=%(user_id)s' % data + url = '{resource_path}/{tenant_id}?user_id={user_id}'.format( + **data + ) elif share_type: - url = '%(resource_path)s/%(tenant_id)s?share_type=%(st)s' % data + url = '{resource_path}/{tenant_id}?share_type={st}'.format(**data) else: - url = '%(resource_path)s/%(tenant_id)s' % data + url = '{resource_path}/{tenant_id}'.format(**data) self._delete(url) @api_versions.wraps("1.0", "2.6") def delete(self, tenant_id, user_id=None): return self._do_delete( - tenant_id, user_id, resource_path=RESOURCE_PATH_LEGACY) + tenant_id, user_id, resource_path=RESOURCE_PATH_LEGACY + ) @api_versions.wraps("2.7", "2.38") # noqa def delete(self, tenant_id, user_id=None): # noqa return self._do_delete(tenant_id, user_id, resource_path=RESOURCE_PATH) @api_versions.wraps("2.39") # noqa - def delete(self, tenant_id, user_id=None, share_type=None): # noqa + def delete(self, tenant_id, user_id=None, share_type=None): # noqa return self._do_delete( - tenant_id, user_id, share_type, resource_path=RESOURCE_PATH) + tenant_id, user_id, share_type, resource_path=RESOURCE_PATH + ) diff --git a/manilaclient/v2/resource_locks.py b/manilaclient/v2/resource_locks.py index b396420f..80e8ec15 100644 --- a/manilaclient/v2/resource_locks.py +++ b/manilaclient/v2/resource_locks.py @@ -19,7 +19,7 @@ class ResourceLock(base.Resource): """Lock a share resource action from being executed""" def __repr__(self): - return "" % self.id + return f"" def delete(self): """Delete this lock.""" @@ -32,11 +32,17 @@ def update(self, **kwargs): class ResourceLockManager(base.ManagerWithFind): """Manage :class:`ResourceLock` resources.""" + resource_class = ResourceLock @api_versions.wraps(constants.RESOURCE_LOCK_VERSION) - def create(self, resource_id, resource_type, - resource_action='delete', lock_reason=None): + def create( + self, + resource_id, + resource_type, + resource_action='delete', + lock_reason=None, + ): """Creates a resource lock. :param resource_id: The ID of the resource to lock @@ -65,7 +71,7 @@ def get(self, lock_id): :param lock_id: The ID of the resource lock to display. :rtype: :class:`ResourceLock` """ - return self._get("/resource-locks/%s" % lock_id, "resource_lock") + return self._get(f"/resource-locks/{lock_id}", "resource_lock") @api_versions.wraps(constants.RESOURCE_LOCK_VERSION) def list(self, search_opts=None, sort_key=None, sort_dir=None): @@ -83,18 +89,23 @@ def list(self, search_opts=None, sort_key=None, sort_dir=None): search_opts['sort_key'] = sort_key else: raise ValueError( - 'sort_key must be one of the following: %s.' - % ', '.join(constants.RESOURCE_LOCK_SORT_KEY_VALUES)) + 'sort_key must be one of the following: {}.'.format( + ', '.join(constants.RESOURCE_LOCK_SORT_KEY_VALUES) + ) + ) sort_dir = sort_dir or 'desc' if sort_dir in constants.SORT_DIR_VALUES: search_opts['sort_dir'] = sort_dir else: - raise ValueError('sort_dir must be one of the following: %s.' - % ', '.join(constants.SORT_DIR_VALUES)) + raise ValueError( + 'sort_dir must be one of the following: {}.'.format( + ', '.join(constants.SORT_DIR_VALUES) + ) + ) query_string = self._build_query_string(search_opts) - path = "/resource-locks%s" % (query_string,) + path = f"/resource-locks{query_string}" return self._list(path, 'resource_locks') @@ -114,12 +125,12 @@ def update(self, lock, **kwargs): if 'lock_reason' in kwargs: body['resource_lock']['lock_reason'] = kwargs['lock_reason'] if 'resource_action' in kwargs: - body['resource_lock']['resource_action'] = ( - kwargs['resource_action'] - ) + body['resource_lock']['resource_action'] = kwargs[ + 'resource_action' + ] lock_id = base.getid(lock) - return self._update("/resource-locks/%s" % lock_id, body) + return self._update(f"/resource-locks/{lock_id}", body) @api_versions.wraps(constants.RESOURCE_LOCK_VERSION) def delete(self, lock): @@ -127,4 +138,4 @@ def delete(self, lock): :param lock: The :class:`ResourceLock` object, or a lock id to delete. """ - return self._delete("/resource-locks/%s" % base.getid(lock)) + return self._delete(f"/resource-locks/{base.getid(lock)}") diff --git a/manilaclient/v2/scheduler_stats.py b/manilaclient/v2/scheduler_stats.py index a6f6295e..642db840 100644 --- a/manilaclient/v2/scheduler_stats.py +++ b/manilaclient/v2/scheduler_stats.py @@ -19,13 +19,13 @@ class Pool(base.Resource): - def __repr__(self): - return "" % self.name + return f"" class PoolManager(base.Manager): """Manage :class:`Pool` resources.""" + resource_class = Pool def list(self, detailed=True, search_opts=None): @@ -35,14 +35,8 @@ def list(self, detailed=True, search_opts=None): """ query_string = self._build_query_string(search_opts) if detailed: - path = '%(resources_path)s/detail%(query)s' % { - 'resources_path': RESOURCES_PATH, - 'query': query_string - } + path = f'{RESOURCES_PATH}/detail{query_string}' else: - path = '%(resources_path)s%(query)s' % { - 'resources_path': RESOURCES_PATH, - 'query': query_string - } + path = f'{RESOURCES_PATH}{query_string}' return self._list(path, RESOURCES_NAME) diff --git a/manilaclient/v2/security_services.py b/manilaclient/v2/security_services.py index 7732a318..2f40648f 100644 --- a/manilaclient/v2/security_services.py +++ b/manilaclient/v2/security_services.py @@ -25,15 +25,16 @@ class SecurityService(base.Resource): """Security service for Manila shares.""" + def __repr__(self): - return "" % self.id + return f"" def update(self, **kwargs): """Update this security service.""" return self.manager.update(self, **kwargs) def delete(self): - """"Delete this security service.""" + """Delete this security service.""" self.manager.delete(self) @@ -43,9 +44,18 @@ class SecurityServiceManager(base.ManagerWithFind): resource_class = SecurityService @api_versions.wraps("1.0", "2.75") - def create(self, type, dns_ip=None, ou=None, server=None, domain=None, - user=None, password=None, name=None, - description=None): + def create( + self, + type, + dns_ip=None, + ou=None, + server=None, + domain=None, + user=None, + password=None, + name=None, + description=None, + ): """Create security service for NAS. :param type: security service type - 'ldap', 'kerberos' or @@ -60,16 +70,32 @@ def create(self, type, dns_ip=None, ou=None, server=None, domain=None, :param description: security service description :rtype: :class:`SecurityService` """ - return self._create_security_service(type, dns_ip=dns_ip, ou=ou, - server=server, domain=domain, - user=user, password=password, - name=name, - description=description) + return self._create_security_service( + type, + dns_ip=dns_ip, + ou=ou, + server=server, + domain=domain, + user=user, + password=password, + name=name, + description=description, + ) @api_versions.wraps("2.76") # noqa - def create(self, type, dns_ip=None, ou=None, server=None, # noqa - domain=None, user=None, password=None, name=None, - description=None, default_ad_site=None): + def create( # noqa + self, + type, + dns_ip=None, + ou=None, + server=None, + domain=None, + user=None, + password=None, + name=None, + description=None, + default_ad_site=None, + ): """Create security service for NAS. :param type: security service type - 'ldap', 'kerberos' or @@ -85,17 +111,32 @@ def create(self, type, dns_ip=None, ou=None, server=None, # noqa :param default_ad_site: default AD-Site :rtype: :class:`SecurityService` """ - return self._create_security_service(type, dns_ip=dns_ip, ou=ou, - server=server, domain=domain, - user=user, password=password, - name=name, - description=description, - default_ad_site=default_ad_site) - - def _create_security_service(self, type, dns_ip=None, ou=None, - server=None, domain=None, user=None, - password=None, name=None, - description=None, default_ad_site=None): + return self._create_security_service( + type, + dns_ip=dns_ip, + ou=ou, + server=server, + domain=domain, + user=user, + password=password, + name=name, + description=description, + default_ad_site=default_ad_site, + ) + + def _create_security_service( + self, + type, + dns_ip=None, + ou=None, + server=None, + domain=None, + user=None, + password=None, + name=None, + description=None, + default_ad_site=None, + ): values = {'type': type} if dns_ip: values['dns_ip'] = dns_ip @@ -132,9 +173,18 @@ def get(self, security_service): ) @api_versions.wraps("1.0", "2.75") - def update(self, security_service, dns_ip=None, ou=None, server=None, - domain=None, password=None, user=None, name=None, - description=None): + def update( + self, + security_service, + dns_ip=None, + ou=None, + server=None, + domain=None, + password=None, + user=None, + name=None, + description=None, + ): """Updates a security service. :param security_service: security service to update. @@ -148,16 +198,32 @@ def update(self, security_service, dns_ip=None, ou=None, server=None, :param description: security service description :rtype: :class:`SecurityService` """ - return self._update_security_service(security_service, dns_ip=dns_ip, - ou=ou, server=server, - domain=domain, password=password, - user=user, name=name, - description=description) + return self._update_security_service( + security_service, + dns_ip=dns_ip, + ou=ou, + server=server, + domain=domain, + password=password, + user=user, + name=name, + description=description, + ) @api_versions.wraps("2.76") # noqa - def update(self, security_service, dns_ip=None, ou=None, # noqa - server=None, domain=None, password=None, user=None, - name=None, description=None, default_ad_site=None): + def update( # noqa + self, + security_service, + dns_ip=None, + ou=None, + server=None, + domain=None, + password=None, + user=None, + name=None, + description=None, + default_ad_site=None, + ): """Updates a security service. :param security_service: security service to update. @@ -172,17 +238,32 @@ def update(self, security_service, dns_ip=None, ou=None, # noqa :param default_ad_site: default AD-Site :rtype: :class:`SecurityService` """ - return self._update_security_service(security_service, dns_ip=dns_ip, - ou=ou, server=server, - domain=domain, password=password, - user=user, name=name, - description=description, - default_ad_site=default_ad_site) - - def _update_security_service(self, security_service, dns_ip=None, ou=None, - server=None, domain=None, password=None, - user=None, name=None, description=None, - default_ad_site=None): + return self._update_security_service( + security_service, + dns_ip=dns_ip, + ou=ou, + server=server, + domain=domain, + password=password, + user=user, + name=name, + description=description, + default_ad_site=default_ad_site, + ) + + def _update_security_service( + self, + security_service, + dns_ip=None, + ou=None, + server=None, + domain=None, + password=None, + user=None, + name=None, + description=None, + default_ad_site=None, + ): values = {} if dns_ip is not None: values['dns_ip'] = dns_ip diff --git a/manilaclient/v2/services.py b/manilaclient/v2/services.py index f87fff6a..4d7922ba 100644 --- a/manilaclient/v2/services.py +++ b/manilaclient/v2/services.py @@ -22,9 +22,8 @@ class Service(base.Resource): - def __repr__(self): - return "" % self.id + return f"" def server_api_version(self, **kwargs): """Get api version.""" @@ -33,6 +32,7 @@ def server_api_version(self, **kwargs): class ServiceManager(base.Manager): """Manage :class:`Service` resources.""" + resource_class = Service def _do_list(self, search_opts=None, resource_path=RESOURCE_PATH): @@ -46,17 +46,19 @@ def _do_list(self, search_opts=None, resource_path=RESOURCE_PATH): @api_versions.wraps("1.0", "2.6") def list(self, search_opts=None): return self._do_list( - search_opts=search_opts, resource_path=RESOURCE_PATH_LEGACY) + search_opts=search_opts, resource_path=RESOURCE_PATH_LEGACY + ) @api_versions.wraps("2.7") # noqa def list(self, search_opts=None): # noqa return self._do_list( - search_opts=search_opts, resource_path=RESOURCE_PATH) + search_opts=search_opts, resource_path=RESOURCE_PATH + ) def _do_enable(self, host, binary, resource_path=RESOURCE_PATH): """Enable the service specified by hostname and binary.""" body = {"host": host, "binary": binary} - return self._update("%s/enable" % resource_path, body) + return self._update(f"{resource_path}/enable", body) @api_versions.wraps("1.0", "2.6") def enable(self, host, binary): @@ -66,13 +68,14 @@ def enable(self, host, binary): def enable(self, host, binary): # noqa return self._do_enable(host, binary, RESOURCE_PATH) - def _do_disable(self, host, binary, resource_path=RESOURCE_PATH, - disable_reason=None): + def _do_disable( + self, host, binary, resource_path=RESOURCE_PATH, disable_reason=None + ): """Disable the service specified by hostname and binary.""" body = {"host": host, "binary": binary} if disable_reason: body["disabled_reason"] = disable_reason - return self._update("%s/disable" % resource_path, body) + return self._update(f"{resource_path}/disable", body) @api_versions.wraps("1.0", "2.6") def disable(self, host, binary): @@ -84,12 +87,13 @@ def disable(self, host, binary): # noqa @api_versions.wraps("2.83") # noqa def disable(self, host, binary, disable_reason=None): # noqa - return self._do_disable(host, binary, RESOURCE_PATH, - disable_reason=disable_reason) + return self._do_disable( + host, binary, RESOURCE_PATH, disable_reason=disable_reason + ) @api_versions.wraps("2.86") def ensure_shares(self, host): # noqa - resource_path = f'{RESOURCE_PATH}/ensure_shares' + resource_path = f'{RESOURCE_PATH}/ensure-shares' body = {"host": host} return self.api.client.post(resource_path, body=body) diff --git a/manilaclient/v2/share_access_rules.py b/manilaclient/v2/share_access_rules.py index 2f68f5ac..47053084 100644 --- a/manilaclient/v2/share_access_rules.py +++ b/manilaclient/v2/share_access_rules.py @@ -32,10 +32,10 @@ class ShareAccessRule(base.Resource): """A Share Access Rule.""" def __repr__(self): - return "" % self.id + return f"" def delete(self): - """"Delete this share access rule.""" + """Delete this share access rule.""" self.manager.delete(self) @@ -87,11 +87,7 @@ def set_access_level(self, access, access_level): :param access: either share access rule object or text with its ID. :param access_level: value of access_level (e.g. ro/rw) """ - body = { - 'update_access': { - 'access_level': access_level - } - } + body = {'update_access': {'access_level': access_level}} access_id = base.getid(access) url = RESOURCE_PATH % access_id return self._update(url, body) diff --git a/manilaclient/v2/share_backups.py b/manilaclient/v2/share_backups.py index 3f2bccc8..64ff36d4 100644 --- a/manilaclient/v2/share_backups.py +++ b/manilaclient/v2/share_backups.py @@ -23,11 +23,12 @@ class ShareBackup(base.Resource): def __repr__(self): - return "" % self.id + return f"" class ShareBackupManager(base.ManagerWithFind): """Manage :class:`ShareBackup` resources.""" + resource_class = ShareBackup @api_versions.wraps("2.80") @@ -43,8 +44,9 @@ def get(self, backup): @api_versions.wraps("2.80") @api_versions.experimental_api - def list(self, detailed=True, search_opts=None, sort_key=None, - sort_dir=None): + def list( + self, detailed=True, search_opts=None, sort_key=None, sort_dir=None + ): """List all share backups or list backups belonging to a share. :param detailed: list backups with detailed fields. @@ -61,22 +63,26 @@ def list(self, detailed=True, search_opts=None, sort_key=None, search_opts['sort_key'] = sort_key else: raise ValueError( - 'sort_key must be one of the following: %s.' - % ', '.join(constants.BACKUP_SORT_KEY_VALUES)) + 'sort_key must be one of the following: {}.'.format( + ', '.join(constants.BACKUP_SORT_KEY_VALUES) + ) + ) if sort_dir is not None: if sort_dir in constants.SORT_DIR_VALUES: search_opts['sort_dir'] = sort_dir else: raise ValueError( - 'sort_dir must be one of the following: %s.' - % ', '.join(constants.SORT_DIR_VALUES)) + 'sort_dir must be one of the following: {}.'.format( + ', '.join(constants.SORT_DIR_VALUES) + ) + ) query_string = self._build_query_string(search_opts) if detailed: - path = "/share-backups/detail%s" % (query_string,) + path = f"/share-backups/detail{query_string}" else: - path = "/share-backups%s" % (query_string,) + path = f"/share-backups{query_string}" return self._list(path, 'share_backups') @@ -99,9 +105,9 @@ def create(self, share, backup_options=None, description=None, name=None): 'name': name, } - return self._create(RESOURCES_PATH, - {RESOURCE_NAME: body}, - RESOURCE_NAME) + return self._create( + RESOURCES_PATH, {RESOURCE_NAME: body}, RESOURCE_NAME + ) @api_versions.wraps("2.80") @api_versions.experimental_api @@ -110,10 +116,15 @@ def delete(self, backup): url = RESOURCE_PATH % backup_id self._delete(url) - @api_versions.wraps("2.80") + @api_versions.wraps("2.80", "2.90") + @api_versions.experimental_api + def restore(self, backup_id): + return self._action('restore', backup_id) + + @api_versions.wraps("2.91") @api_versions.experimental_api - def restore(self, backup): - return self._action('restore', backup) + def restore(self, backup_id, target_share_id=None): # noqa F811 + return self._action('restore', backup_id, info=target_share_id) @api_versions.wraps("2.80") @api_versions.experimental_api diff --git a/manilaclient/v2/share_export_locations.py b/manilaclient/v2/share_export_locations.py index ed716aa9..fa9b6263 100644 --- a/manilaclient/v2/share_export_locations.py +++ b/manilaclient/v2/share_export_locations.py @@ -21,7 +21,7 @@ class ShareExportLocation(base.Resource): """Resource class for a share export location.""" def __repr__(self): - return "" % self.id + return f"" def __getitem__(self, key): return self._info[key] @@ -29,6 +29,7 @@ def __getitem__(self, key): class ShareExportLocationManager(base.MetadataCapableManager): """Manage :class:`ShareExportLocation` resources.""" + resource_class = ShareExportLocation resource_path = '/shares' subresource_path = '/export_locations' @@ -37,8 +38,9 @@ class ShareExportLocationManager(base.MetadataCapableManager): def list(self, share, search_opts=None): """List all share export locations.""" share_id = base.getid(share) - return self._list("/shares/%s/export_locations" % share_id, - "export_locations") + return self._list( + f"/shares/{share_id}/export_locations", "export_locations" + ) @api_versions.wraps("2.9") def get(self, share, export_location): @@ -46,26 +48,26 @@ def get(self, share, export_location): share_id = base.getid(share) export_location_id = base.getid(export_location) return self._get( - "/shares/%(share_id)s/export_locations/%(export_location_id)s" % { - "share_id": share_id, - "export_location_id": export_location_id}, "export_location") + f"/shares/{share_id}/export_locations/{export_location_id}", + "export_location", + ) @api_versions.wraps('2.87') def get_metadata(self, share, share_export_location): - return super(ShareExportLocationManager, self).get_metadata( - share, subresource=share_export_location) + return super().get_metadata(share, subresource=share_export_location) @api_versions.wraps('2.87') def set_metadata(self, resource, metadata, subresource=None): - return super(ShareExportLocationManager, self).set_metadata( - resource, metadata, subresource=subresource) + return super().set_metadata( + resource, metadata, subresource=subresource + ) @api_versions.wraps('2.87') def delete_metadata(self, resource, keys, subresource=None): - return super(ShareExportLocationManager, self).delete_metadata( - resource, keys, subresource=subresource) + return super().delete_metadata(resource, keys, subresource=subresource) @api_versions.wraps('2.87') def update_all_metadata(self, resource, metadata, subresource=None): - return super(ShareExportLocationManager, self).update_all_metadata( - resource, metadata, subresource=subresource) + return super().update_all_metadata( + resource, metadata, subresource=subresource + ) diff --git a/manilaclient/v2/share_group_snapshots.py b/manilaclient/v2/share_group_snapshots.py index 52c1da97..5daee374 100644 --- a/manilaclient/v2/share_group_snapshots.py +++ b/manilaclient/v2/share_group_snapshots.py @@ -30,7 +30,7 @@ class ShareGroupSnapshot(base.Resource): """A snapshot of a share group.""" def __repr__(self): - return "" % self.id + return f"" def update(self, **kwargs): """Update this share group snapshot.""" @@ -47,10 +47,12 @@ def reset_state(self, state): class ShareGroupSnapshotManager(base.ManagerWithFind): """Manage :class:`ShareGroupSnapshot` resources.""" + resource_class = ShareGroupSnapshot - def _create_share_group_snapshot(self, share_group, name=None, - description=None): + def _create_share_group_snapshot( + self, share_group, name=None, description=None + ): """Create a share group snapshot. :param share_group: either ShareGroup object or text with its UUID @@ -66,18 +68,21 @@ def _create_share_group_snapshot(self, share_group, name=None, body['description'] = description return self._create( - RESOURCES_PATH, {RESOURCE_NAME: body}, RESOURCE_NAME) + RESOURCES_PATH, {RESOURCE_NAME: body}, RESOURCE_NAME + ) @api_versions.wraps("2.31", "2.54") @api_versions.experimental_api def create(self, share_group, name=None, description=None): - return self._create_share_group_snapshot(share_group, name, - description) + return self._create_share_group_snapshot( + share_group, name, description + ) @api_versions.wraps(SG_GRADUATION_VERSION) # noqa def create(self, share_group, name=None, description=None): # noqa - return self._create_share_group_snapshot(share_group, name, - description) + return self._create_share_group_snapshot( + share_group, name, description + ) def _get_share_group_snapshot(self, share_group_snapshot): """Get a share group snapshot. @@ -99,8 +104,9 @@ def get(self, share_group_snapshot): def get(self, share_group_snapshot): # noqa return self._get_share_group_snapshot(share_group_snapshot) - def _list_share_group_snapshots(self, detailed=True, search_opts=None, - sort_key=None, sort_dir=None): + def _list_share_group_snapshots( + self, detailed=True, search_opts=None, sort_key=None, sort_dir=None + ): """Get a list of all share group snapshots. :param detailed: Whether to return detailed snapshot info or not. @@ -125,15 +131,19 @@ def _list_share_group_snapshots(self, detailed=True, search_opts=None, else: msg = 'sort_key must be one of the following: %s.' msg_args = ', '.join( - constants.SHARE_GROUP_SNAPSHOT_SORT_KEY_VALUES) + constants.SHARE_GROUP_SNAPSHOT_SORT_KEY_VALUES + ) raise ValueError(msg % msg_args) if sort_dir is not None: if sort_dir in constants.SORT_DIR_VALUES: search_opts['sort_dir'] = sort_dir else: - raise ValueError('sort_dir must be one of the following: %s.' - % ', '.join(constants.SORT_DIR_VALUES)) + raise ValueError( + 'sort_dir must be one of the following: {}.'.format( + ', '.join(constants.SORT_DIR_VALUES) + ) + ) query_string = self._build_query_string(search_opts) @@ -146,18 +156,30 @@ def _list_share_group_snapshots(self, detailed=True, search_opts=None, @api_versions.wraps("2.31", "2.54") @api_versions.experimental_api - def list(self, detailed=True, search_opts=None, - sort_key=None, sort_dir=None): + def list( + self, detailed=True, search_opts=None, sort_key=None, sort_dir=None + ): return self._list_share_group_snapshots( - detailed=detailed, search_opts=search_opts, - sort_key=sort_key, sort_dir=sort_dir) + detailed=detailed, + search_opts=search_opts, + sort_key=sort_key, + sort_dir=sort_dir, + ) @api_versions.wraps(SG_GRADUATION_VERSION) # noqa - def list(self, detailed=True, search_opts=None, # noqa - sort_key=None, sort_dir=None): + def list( # noqa + self, + detailed=True, + search_opts=None, + sort_key=None, + sort_dir=None, + ): return self._list_share_group_snapshots( - detailed=detailed, search_opts=search_opts, - sort_key=sort_key, sort_dir=sort_dir) + detailed=detailed, + search_opts=search_opts, + sort_key=sort_key, + sort_dir=sort_dir, + ) def _update_share_group_snapshot(self, share_group_snapshot, **kwargs): """Updates a share group snapshot. @@ -177,13 +199,15 @@ def _update_share_group_snapshot(self, share_group_snapshot, **kwargs): @api_versions.wraps("2.31", "2.54") @api_versions.experimental_api def update(self, share_group_snapshot, **kwargs): - return self._update_share_group_snapshot(share_group_snapshot, - **kwargs) + return self._update_share_group_snapshot( + share_group_snapshot, **kwargs + ) @api_versions.wraps(SG_GRADUATION_VERSION) # noqa def update(self, share_group_snapshot, **kwargs): # noqa - return self._update_share_group_snapshot(share_group_snapshot, - **kwargs) + return self._update_share_group_snapshot( + share_group_snapshot, **kwargs + ) def _delete_share_group_snapshot(self, share_group_snapshot, force=False): """Delete a share group snapshot. @@ -228,5 +252,5 @@ def reset_state(self, share_group_snapshot, state): self._share_group_snapshot_reset_state(share_group_snapshot, state) @api_versions.wraps(SG_GRADUATION_VERSION) # noqa - def reset_state(self, share_group_snapshot, state): # noqa + def reset_state(self, share_group_snapshot, state): # noqa self._share_group_snapshot_reset_state(share_group_snapshot, state) diff --git a/manilaclient/v2/share_group_type_access.py b/manilaclient/v2/share_group_type_access.py index de409145..85cce7c0 100644 --- a/manilaclient/v2/share_group_type_access.py +++ b/manilaclient/v2/share_group_type_access.py @@ -25,15 +25,17 @@ class ShareGroupTypeAccess(base.Resource): def __repr__(self): - return "" % self.share_group_type_id + return f"" class ShareGroupTypeAccessManager(base.ManagerWithFind): """Manage :class:`ShareGroupTypeAccess` resources.""" + resource_class = ShareGroupTypeAccess - def _list_share_group_type_access(self, share_group_type, - search_opts=None): + def _list_share_group_type_access( + self, share_group_type, search_opts=None + ): if share_group_type.is_public: return None share_group_type_id = base.getid(share_group_type) @@ -43,13 +45,15 @@ def _list_share_group_type_access(self, share_group_type, @api_versions.wraps("2.31", "2.54") @api_versions.experimental_api def list(self, share_group_type, search_opts=None): - return self._list_share_group_type_access(share_group_type, - search_opts) + return self._list_share_group_type_access( + share_group_type, search_opts + ) @api_versions.wraps(SG_GRADUATION_VERSION) # noqa def list(self, share_group_type, search_opts=None): # noqa - return self._list_share_group_type_access(share_group_type, - search_opts) + return self._list_share_group_type_access( + share_group_type, search_opts + ) @api_versions.wraps("2.31", "2.54") @api_versions.experimental_api diff --git a/manilaclient/v2/share_group_types.py b/manilaclient/v2/share_group_types.py index f1bdd15c..2fe5f24d 100644 --- a/manilaclient/v2/share_group_types.py +++ b/manilaclient/v2/share_group_types.py @@ -33,11 +33,11 @@ class ShareGroupType(base.Resource): """A Share Group Type is the type of share group to be created.""" def __init__(self, manager, info, loaded=False): - super(ShareGroupType, self).__init__(manager, info, loaded) + super().__init__(manager, info, loaded) self._group_specs = info.get(GROUP_SPECS_RESOURCES_NAME, {}) def __repr__(self): - return "" % self.name + return f"" @property def is_public(self): @@ -71,7 +71,8 @@ def set_keys(self, group_specs): url = GROUP_SPECS_RESOURCES_PATH % share_group_type_id body = {GROUP_SPECS_RESOURCES_NAME: group_specs} return self.manager._create( - url, body, GROUP_SPECS_RESOURCES_NAME, return_raw=True) + url, body, GROUP_SPECS_RESOURCES_NAME, return_raw=True + ) def unset_keys(self, keys): """Unset group specs on a share group type. @@ -89,10 +90,12 @@ def unset_keys(self, keys): class ShareGroupTypeManager(base.ManagerWithFind): """Manage :class:`ShareGroupType` resources.""" + resource_class = ShareGroupType - def _create_share_group_type(self, name, share_types, is_public=False, - group_specs=None): + def _create_share_group_type( + self, name, share_types, is_public=False, group_specs=None + ): """Create a share group type. :param name: Descriptive name of the share group type @@ -103,28 +106,34 @@ def _create_share_group_type(self, name, share_types, is_public=False, :rtype: :class:`ShareGroupType` """ if not share_types: - raise ValueError('At least one share type must be specified when ' - 'creating a share group type.') + raise ValueError( + 'At least one share type must be specified when ' + 'creating a share group type.' + ) body = { 'name': name, 'is_public': is_public, 'group_specs': group_specs or {}, - 'share_types': [base.getid(share_type) - for share_type in share_types], + 'share_types': [ + base.getid(share_type) for share_type in share_types + ], } return self._create( - RESOURCES_PATH, {RESOURCE_NAME: body}, RESOURCE_NAME) + RESOURCES_PATH, {RESOURCE_NAME: body}, RESOURCE_NAME + ) @api_versions.wraps("2.31", "2.54") @api_versions.experimental_api def create(self, name, share_types, is_public=False, group_specs=None): - return self._create_share_group_type(name, share_types, is_public, - group_specs) + return self._create_share_group_type( + name, share_types, is_public, group_specs + ) @api_versions.wraps(SG_GRADUATION_VERSION) # noqa def create(self, name, share_types, is_public=False, group_specs=None): # noqa - return self._create_share_group_type(name, share_types, is_public, - group_specs) + return self._create_share_group_type( + name, share_types, is_public, group_specs + ) def _get_share_group_type(self, share_group_type="default"): """Get a specific share group type. diff --git a/manilaclient/v2/share_groups.py b/manilaclient/v2/share_groups.py index 3cb85352..462abc5a 100644 --- a/manilaclient/v2/share_groups.py +++ b/manilaclient/v2/share_groups.py @@ -31,7 +31,7 @@ class ShareGroup(base.Resource): """A share group is a logical grouping of shares on a single backend.""" def __repr__(self): - return "" % self.id + return f"" def update(self, **kwargs): """Update this share group.""" @@ -48,12 +48,19 @@ def reset_state(self, state): class ShareGroupManager(base.ManagerWithFind): """Manage :class:`ShareGroup` resources.""" + resource_class = ShareGroup def _create_share_group( - self, share_group_type=None, share_types=None, share_network=None, - name=None, description=None, source_share_group_snapshot=None, - availability_zone=None): + self, + share_group_type=None, + share_types=None, + share_network=None, + name=None, + description=None, + source_share_group_snapshot=None, + availability_zone=None, + ): """Create a Share Group. :param share_group_type: either instance of ShareGroupType or text @@ -75,8 +82,10 @@ def _create_share_group( """ if share_types and source_share_group_snapshot: - raise ValueError('Cannot specify a share group with both' - 'share_types and source_share_group_snapshot.') + raise ValueError( + 'Cannot specify a share group with both' + 'share_types and source_share_group_snapshot.' + ) body = {} @@ -93,34 +102,59 @@ def _create_share_group( if source_share_group_snapshot: body['source_share_group_snapshot_id'] = base.getid( - source_share_group_snapshot) + source_share_group_snapshot + ) elif share_types: - body['share_types'] = [base.getid(share_type) - for share_type in share_types] + body['share_types'] = [ + base.getid(share_type) for share_type in share_types + ] return self._create( - RESOURCES_PATH, {RESOURCE_NAME: body}, RESOURCE_NAME) + RESOURCES_PATH, {RESOURCE_NAME: body}, RESOURCE_NAME + ) @api_versions.wraps("2.31", "2.54") @api_versions.experimental_api - def create(self, share_group_type=None, share_types=None, - share_network=None, name=None, description=None, - source_share_group_snapshot=None, availability_zone=None): + def create( + self, + share_group_type=None, + share_types=None, + share_network=None, + name=None, + description=None, + source_share_group_snapshot=None, + availability_zone=None, + ): return self._create_share_group( - share_group_type=share_group_type, share_types=share_types, - share_network=share_network, name=name, description=description, + share_group_type=share_group_type, + share_types=share_types, + share_network=share_network, + name=name, + description=description, source_share_group_snapshot=source_share_group_snapshot, - availability_zone=availability_zone) + availability_zone=availability_zone, + ) @api_versions.wraps(SG_GRADUATION_VERSION) # noqa - def create(self, share_group_type=None, share_types=None, # noqa - share_network=None, name=None, description=None, - source_share_group_snapshot=None, availability_zone=None): + def create( # noqa + self, + share_group_type=None, + share_types=None, + share_network=None, + name=None, + description=None, + source_share_group_snapshot=None, + availability_zone=None, + ): return self._create_share_group( - share_group_type=share_group_type, share_types=share_types, - share_network=share_network, name=name, description=description, + share_group_type=share_group_type, + share_types=share_types, + share_network=share_network, + name=name, + description=description, source_share_group_snapshot=source_share_group_snapshot, - availability_zone=availability_zone) + availability_zone=availability_zone, + ) def _get_share_group(self, share_group): """Get a share group. @@ -141,8 +175,9 @@ def get(self, share_group): def get(self, share_group): # noqa return self._get_share_group(share_group) - def _list_share_groups(self, detailed=True, search_opts=None, - sort_key=None, sort_dir=None): + def _list_share_groups( + self, detailed=True, search_opts=None, sort_key=None, sort_dir=None + ): """Get a list of all share groups. :param detailed: Whether to return detailed share group info or not. @@ -183,8 +218,11 @@ def _list_share_groups(self, detailed=True, search_opts=None, if sort_dir in constants.SORT_DIR_VALUES: search_opts['sort_dir'] = sort_dir else: - raise ValueError('sort_dir must be one of the following: %s.' - % ', '.join(constants.SORT_DIR_VALUES)) + raise ValueError( + 'sort_dir must be one of the following: {}.'.format( + ', '.join(constants.SORT_DIR_VALUES) + ) + ) query_string = self._build_query_string(search_opts) @@ -197,18 +235,30 @@ def _list_share_groups(self, detailed=True, search_opts=None, @api_versions.wraps("2.31", "2.54") @api_versions.experimental_api - def list(self, detailed=True, search_opts=None, - sort_key=None, sort_dir=None): + def list( + self, detailed=True, search_opts=None, sort_key=None, sort_dir=None + ): return self._list_share_groups( - detailed=detailed, search_opts=search_opts, - sort_key=sort_key, sort_dir=sort_dir) + detailed=detailed, + search_opts=search_opts, + sort_key=sort_key, + sort_dir=sort_dir, + ) @api_versions.wraps(SG_GRADUATION_VERSION) # noqa - def list(self, detailed=True, search_opts=None, # noqa - sort_key=None, sort_dir=None): + def list( # noqa + self, + detailed=True, + search_opts=None, + sort_key=None, + sort_dir=None, + ): return self._list_share_groups( - detailed=detailed, search_opts=search_opts, sort_key=sort_key, - sort_dir=sort_dir) + detailed=detailed, + search_opts=search_opts, + sort_key=sort_key, + sort_dir=sort_dir, + ) def _update_share_group(self, share_group, **kwargs): """Updates a share group. @@ -225,6 +275,7 @@ def _update_share_group(self, share_group, **kwargs): return self._update(url, body, RESOURCE_NAME) @api_versions.wraps("2.31", "2.54") + @api_versions.experimental_api def update(self, share_group, **kwargs): return self._update_share_group(share_group, **kwargs) diff --git a/manilaclient/v2/share_instance_export_locations.py b/manilaclient/v2/share_instance_export_locations.py index 783d1a92..00214e4e 100644 --- a/manilaclient/v2/share_instance_export_locations.py +++ b/manilaclient/v2/share_instance_export_locations.py @@ -21,7 +21,7 @@ class ShareInstanceExportLocation(base.Resource): """Resource class for a share export location.""" def __repr__(self): - return "" % self.id + return f"" def __getitem__(self, key): return self._info[key] @@ -29,6 +29,7 @@ def __getitem__(self, key): class ShareInstanceExportLocationManager(base.ManagerWithFind): """Manage :class:`ShareInstanceExportLocation` resources.""" + resource_class = ShareInstanceExportLocation @api_versions.wraps("2.9") @@ -36,8 +37,9 @@ def list(self, share_instance, search_opts=None): """List all share export locations.""" share_instance_id = base.getid(share_instance) return self._list( - "/share_instances/%s/export_locations" % share_instance_id, - "export_locations") + f"/share_instances/{share_instance_id}/export_locations", + "export_locations", + ) @api_versions.wraps("2.9") def get(self, share_instance, export_location): @@ -45,9 +47,9 @@ def get(self, share_instance, export_location): share_instance_id = base.getid(share_instance) export_location_id = base.getid(export_location) return self._get( - ("/share_instances/%(share_instance_id)s/export_locations/" - "%(export_location_id)s") % { - "share_instance_id": share_instance_id, - "export_location_id": export_location_id, - }, - "export_location") + ( + f"/share_instances/{share_instance_id}/export_locations/" + f"{export_location_id}" + ), + "export_location", + ) diff --git a/manilaclient/v2/share_instances.py b/manilaclient/v2/share_instances.py index f248e3a3..2509bf02 100644 --- a/manilaclient/v2/share_instances.py +++ b/manilaclient/v2/share_instances.py @@ -21,8 +21,9 @@ class ShareInstance(base.Resource): """A share is an extra block level storage to the OpenStack instances.""" + def __repr__(self): - return "" % self.id + return f"" def force_delete(self): """Delete the specified share ignoring its current state.""" @@ -34,7 +35,8 @@ def reset_state(self, state): class ShareInstanceManager(base.ManagerWithFind): - """Manage :class:`ShareInstances` resources.""" + """Manage :class:`ShareInstance` resources.""" + resource_class = ShareInstance @api_versions.wraps("2.3") @@ -45,14 +47,14 @@ def get(self, instance): :rtype: :class:`ShareInstance` """ share_id = base.getid(instance) - return self._get("/share_instances/%s" % share_id, "share_instance") + return self._get(f"/share_instances/{share_id}", "share_instance") @api_versions.wraps("2.3", "2.34") def list(self, search_opts=None): """List all share instances.""" return self.do_list() - @api_versions.wraps("2.35") # noqa + @api_versions.wraps("2.35") # noqa def list(self, export_location=None, search_opts=None): # noqa """List all share instances.""" return self.do_list(export_location) @@ -78,7 +80,7 @@ def _action(self, action, instance, info=None, **kwargs): """ body = {action: info} self.run_hooks('modify_body_for_action', body, **kwargs) - url = '/share_instances/%s/action' % base.getid(instance) + url = f'/share_instances/{base.getid(instance)}/action' return self.api.client.post(url, body=body) def _do_force_delete(self, instance, action_name="force_delete"): diff --git a/manilaclient/v2/share_network_subnets.py b/manilaclient/v2/share_network_subnets.py index d1679e94..c00161e0 100644 --- a/manilaclient/v2/share_network_subnets.py +++ b/manilaclient/v2/share_network_subnets.py @@ -23,8 +23,9 @@ class ShareNetworkSubnet(base.MetadataCapableResource): """Network subnet info for Manila share networks.""" + def __repr__(self): - return "" % self.id + return f"" def __getitem__(self, key): return self._info[key] @@ -41,9 +42,14 @@ class ShareNetworkSubnetManager(base.MetadataCapableManager): resource_path = '/share-networks' subresource_path = '/subnets' - def _do_create(self, neutron_net_id=None, neutron_subnet_id=None, - availability_zone=None, share_network_id=None, - metadata=None): + def _do_create( + self, + neutron_net_id=None, + neutron_subnet_id=None, + availability_zone=None, + share_network_id=None, + metadata=None, + ): """Create share network subnet. :param neutron_net_id: ID of Neutron network @@ -63,37 +69,54 @@ def _do_create(self, neutron_net_id=None, neutron_subnet_id=None, values['metadata'] = metadata body = {'share-network-subnet': values} - url = '/share-networks/%(share_network_id)s/subnets' % { - 'share_network_id': share_network_id - } + url = f'/share-networks/{share_network_id}/subnets' return self._create(url, body, RESOURCE_NAME) @api_versions.wraps("2.0", "2.77") - def create(self, neutron_net_id=None, neutron_subnet_id=None, - availability_zone=None, share_network_id=None): - return self._do_create(neutron_net_id, neutron_subnet_id, - availability_zone, share_network_id) + def create( + self, + neutron_net_id=None, + neutron_subnet_id=None, + availability_zone=None, + share_network_id=None, + ): + return self._do_create( + neutron_net_id, + neutron_subnet_id, + availability_zone, + share_network_id, + ) @api_versions.wraps("2.78") - def create(self, neutron_net_id=None, neutron_subnet_id=None, # noqa F811 - availability_zone=None, share_network_id=None, metadata=None): - return self._do_create(neutron_net_id, neutron_subnet_id, - availability_zone, share_network_id, metadata) + def create( # noqa + self, + neutron_net_id=None, + neutron_subnet_id=None, + availability_zone=None, + share_network_id=None, + metadata=None, + ): + return self._do_create( + neutron_net_id, + neutron_subnet_id, + availability_zone, + share_network_id, + metadata, + ) def get(self, share_network, share_network_subnet): """Get a share network subnet. - :param policy: share network subnet to get. - :rtype: :class:`NetworkSubnetInfo` + :param share_network_subnet: share network subnet to get. + :rtype: :class:`ShareNetworkSubnet` """ share_network_id = base.getid(share_network) share_network_subnet_id = base.getid(share_network_subnet) - url = ('/share-networks/%(share_network_id)s/subnets' - '/%(share_network_subnet)s') % { - 'share_network_id': share_network_id, - 'share_network_subnet': share_network_subnet_id - } + url = ( + f'/share-networks/{share_network_id}/subnets' + f'/{share_network_subnet_id}' + ) return self._get(url, "share_network_subnet") def delete(self, share_network, share_network_subnet): @@ -102,29 +125,30 @@ def delete(self, share_network, share_network_subnet): :param share_network: share network that owns the subnet. :param share_network_subnet: share network subnet to be deleted. """ - url = ('/share-networks/%(share_network_id)s/subnets' - '/%(share_network_subnet)s') % { - 'share_network_id': base.getid(share_network), - 'share_network_subnet': share_network_subnet - } + url = ( + f'/share-networks/{base.getid(share_network)}/subnets' + f'/{share_network_subnet}' + ) self._delete(url) @api_versions.wraps('2.78') def get_metadata(self, share_network, share_network_subnet): - return super(ShareNetworkSubnetManager, self).get_metadata( - share_network, subresource=share_network_subnet) + return super().get_metadata( + share_network, subresource=share_network_subnet + ) @api_versions.wraps('2.78') def set_metadata(self, resource, metadata, subresource=None): - return super(ShareNetworkSubnetManager, self).set_metadata( - resource, metadata, subresource=subresource) + return super().set_metadata( + resource, metadata, subresource=subresource + ) @api_versions.wraps('2.78') def delete_metadata(self, resource, keys, subresource=None): - return super(ShareNetworkSubnetManager, self).delete_metadata( - resource, keys, subresource=subresource) + return super().delete_metadata(resource, keys, subresource=subresource) @api_versions.wraps('2.78') def update_all_metadata(self, resource, metadata, subresource=None): - return super(ShareNetworkSubnetManager, self).update_all_metadata( - resource, metadata, subresource=subresource) + return super().update_all_metadata( + resource, metadata, subresource=subresource + ) diff --git a/manilaclient/v2/share_networks.py b/manilaclient/v2/share_networks.py index ec204500..e1a738a3 100644 --- a/manilaclient/v2/share_networks.py +++ b/manilaclient/v2/share_networks.py @@ -26,8 +26,9 @@ class ShareNetwork(base.Resource): """Network info for Manila shares.""" + def __repr__(self): - return "" % self.id + return f"" def update(self, **kwargs): """Update this share network.""" @@ -40,11 +41,18 @@ def delete(self): class ShareNetworkManager(base.ManagerWithFind): """Manage :class:`ShareNetwork` resources.""" + resource_class = ShareNetwork @api_versions.wraps("1.0", "2.25") - def create(self, neutron_net_id=None, neutron_subnet_id=None, - nova_net_id=None, name=None, description=None): + def create( + self, + neutron_net_id=None, + neutron_subnet_id=None, + nova_net_id=None, + name=None, + description=None, + ): """Create share network. :param neutron_net_id: ID of Neutron network @@ -71,8 +79,13 @@ def create(self, neutron_net_id=None, neutron_subnet_id=None, return self._create(RESOURCES_PATH, body, RESOURCE_NAME) @api_versions.wraps("2.26", "2.50") # noqa - def create(self, neutron_net_id=None, neutron_subnet_id=None, # noqa - name=None, description=None): + def create( # noqa + self, + neutron_net_id=None, + neutron_subnet_id=None, + name=None, + description=None, + ): """Create share network. :param neutron_net_id: ID of Neutron network @@ -96,8 +109,14 @@ def create(self, neutron_net_id=None, neutron_subnet_id=None, # noqa return self._create(RESOURCES_PATH, body, RESOURCE_NAME) @api_versions.wraps("2.51") # noqa - def create(self, neutron_net_id=None, neutron_subnet_id=None, # noqa - name=None, description=None, availability_zone=None): + def create( # noqa + self, + neutron_net_id=None, + neutron_subnet_id=None, + name=None, + description=None, + availability_zone=None, + ): values = {} if neutron_net_id: @@ -136,16 +155,23 @@ def remove_security_service(self, share_network, security_service): def get(self, share_network): """Get a share network. - :param policy: share network to get. - :rtype: :class:`NetworkInfo` + :param share_network: share network to get. + :rtype: :class:`ShareNetwork` """ - return self._get(RESOURCE_PATH % base.getid(share_network), - RESOURCE_NAME) + return self._get( + RESOURCE_PATH % base.getid(share_network), RESOURCE_NAME + ) @api_versions.wraps("1.0", "2.25") - def update(self, share_network, neutron_net_id=None, - neutron_subnet_id=None, nova_net_id=None, - name=None, description=None): + def update( + self, + share_network, + neutron_net_id=None, + neutron_subnet_id=None, + nova_net_id=None, + name=None, + description=None, + ): """Updates a share network. :param share_network: share network to update. @@ -172,14 +198,19 @@ def update(self, share_network, neutron_net_id=None, raise exceptions.CommandError(msg) body = {RESOURCE_NAME: values} - return self._update(RESOURCE_PATH % base.getid(share_network), - body, - RESOURCE_NAME) + return self._update( + RESOURCE_PATH % base.getid(share_network), body, RESOURCE_NAME + ) @api_versions.wraps("2.26") # noqa - def update(self, share_network, neutron_net_id=None, # noqa - neutron_subnet_id=None, name=None, - description=None): + def update( # noqa + self, + share_network, + neutron_net_id=None, + neutron_subnet_id=None, + name=None, + description=None, + ): """Updates a share network. :param share_network: share network to update. @@ -204,9 +235,9 @@ def update(self, share_network, neutron_net_id=None, # noqa raise exceptions.CommandError(msg) body = {RESOURCE_NAME: values} - return self._update(RESOURCE_PATH % base.getid(share_network), - body, - RESOURCE_NAME) + return self._update( + RESOURCE_PATH % base.getid(share_network), body, RESOURCE_NAME + ) def delete(self, share_network): """Delete a share network. @@ -218,7 +249,7 @@ def delete(self, share_network): def list(self, detailed=True, search_opts=None): """Get a list of all share network. - :rtype: list of :class:`NetworkInfo` + :rtype: list of :class:`ShareNetwork` """ query_string = self._build_query_string(search_opts) @@ -254,8 +285,9 @@ def add_security_service(self, share_network, security_service): return self._action('add_security_service', share_network, info) @api_versions.wraps("2.63") - def add_security_service_check(self, share_network, security_service, - reset_operation=False): + def add_security_service_check( + self, share_network, security_service, reset_operation=False + ): """Associate given security service with a share network. :param share_network: share network name, id or ShareNetwork instance @@ -270,9 +302,9 @@ def add_security_service_check(self, share_network, security_service, return self._action('add_security_service_check', share_network, info) @api_versions.wraps("2.63") - def update_share_network_security_service(self, share_network, - current_security_service, - new_security_service): + def update_share_network_security_service( + self, share_network, current_security_service, new_security_service + ): """Update current security service to new one of a given share network. :param share_network: share network name, id or ShareNetwork instance @@ -284,14 +316,19 @@ def update_share_network_security_service(self, share_network, """ info = { 'current_service_id': base.getid(current_security_service), - 'new_service_id': base.getid(new_security_service)} + 'new_service_id': base.getid(new_security_service), + } return self._action('update_security_service', share_network, info) @api_versions.wraps("2.63") def update_share_network_security_service_check( - self, share_network, current_security_service, - new_security_service, reset_operation=False): + self, + share_network, + current_security_service, + new_security_service, + reset_operation=False, + ): """Validates if the security service update is supported by all hosts. :param share_network: share network name, id or ShareNetwork instance @@ -305,11 +342,12 @@ def update_share_network_security_service_check( info = { 'current_service_id': base.getid(current_security_service), 'new_service_id': base.getid(new_security_service), - 'reset_operation': reset_operation + 'reset_operation': reset_operation, } - return self._action('update_security_service_check', - share_network, info) + return self._action( + 'update_security_service_check', share_network, info + ) @api_versions.wraps("2.63") def reset_state(self, share_network, state): @@ -319,15 +357,17 @@ def reset_state(self, share_network, state): or name. :param state: text with new state to set for share network. """ - return self._action('reset_status', share_network, - {"status": state}) + return self._action('reset_status', share_network, {"status": state}) @api_versions.wraps("2.70") - def share_network_subnet_create_check(self, share_network_id, - neutron_net_id=None, - neutron_subnet_id=None, - availability_zone=None, - reset_operation=False): + def share_network_subnet_create_check( + self, + share_network_id, + neutron_net_id=None, + neutron_subnet_id=None, + availability_zone=None, + reset_operation=False, + ): """Check if share network subnet can be created in given share network. :param share_network_id: ID of the Share network @@ -346,5 +386,6 @@ def share_network_subnet_create_check(self, share_network_id, values['availability_zone'] = availability_zone values['reset_operation'] = reset_operation - return self._action('share_network_subnet_create_check', - share_network_id, values) + return self._action( + 'share_network_subnet_create_check', share_network_id, values + ) diff --git a/manilaclient/v2/share_replica_export_locations.py b/manilaclient/v2/share_replica_export_locations.py index 3d69bfa9..510809ca 100644 --- a/manilaclient/v2/share_replica_export_locations.py +++ b/manilaclient/v2/share_replica_export_locations.py @@ -21,14 +21,15 @@ class ShareReplicaExportLocation(base.Resource): """Resource class for a share replica export location.""" def __repr__(self): - return "" % self.id + return f"" def __getitem__(self, key): return self._info[key] class ShareReplicaExportLocationManager(base.ManagerWithFind): - """Manage :class:`ShareInstanceExportLocation` resources.""" + """Manage :class:`ShareReplicaExportLocation` resources.""" + resource_class = ShareReplicaExportLocation @api_versions.wraps("2.47", constants.REPLICA_PRE_GRADUATION_VERSION) @@ -37,36 +38,40 @@ def list(self, share_replica, search_opts=None): """List all share replica export locations.""" share_replica_id = base.getid(share_replica) return self._list( - "/share-replicas/%s/export-locations" % share_replica_id, - "export_locations") + f"/share-replicas/{share_replica_id}/export-locations", + "export_locations", + ) @api_versions.wraps(constants.REPLICA_GRADUATION_VERSION) # noqa def list(self, share_replica, search_opts=None): # noqa F811 """List all share replica export locations.""" share_replica_id = base.getid(share_replica) return self._list( - "/share-replicas/%s/export-locations" % share_replica_id, - "export_locations") + f"/share-replicas/{share_replica_id}/export-locations", + "export_locations", + ) @api_versions.wraps("2.47", constants.REPLICA_PRE_GRADUATION_VERSION) @api_versions.experimental_api def get(self, share_replica, export_location): return self._get_replica_export_location( - share_replica, export_location) + share_replica, export_location + ) @api_versions.wraps(constants.REPLICA_GRADUATION_VERSION) # noqa def get(self, share_replica, export_location): # noqa F811 return self._get_replica_export_location( - share_replica, export_location) + share_replica, export_location + ) def _get_replica_export_location(self, share_replica, export_location): """Get a share replica export location.""" share_replica_id = base.getid(share_replica) export_location_id = base.getid(export_location) return self._get( - ("/share-replicas/%(share_replica_id)s/export-locations/" - "%(export_location_id)s") % { - "share_replica_id": share_replica_id, - "export_location_id": export_location_id, - }, - "export_location") + ( + f"/share-replicas/{share_replica_id}/export-locations/" + f"{export_location_id}" + ), + "export_location", + ) diff --git a/manilaclient/v2/share_replicas.py b/manilaclient/v2/share_replicas.py index 8965e5d9..e4c0ac5e 100644 --- a/manilaclient/v2/share_replicas.py +++ b/manilaclient/v2/share_replicas.py @@ -24,10 +24,11 @@ RESOURCE_NAME = 'share_replica' -class ShareReplica(base.Resource): +class ShareReplica(base.MetadataCapableResource): """A replica is 'mirror' instance of a share at some point in time.""" + def __repr__(self): - return "" % self.id + return f"" def resync(self): """Re-sync this replica.""" @@ -46,9 +47,11 @@ def reset_replica_state(self, replica_state): self.manager.reset_replica_state(self, replica_state) -class ShareReplicaManager(base.ManagerWithFind): +class ShareReplicaManager(base.MetadataCapableManager): """Manage :class:`ShareReplica` resources.""" + resource_class = ShareReplica + resource_path = '/share-replicas' @api_versions.wraps("2.11", constants.REPLICA_PRE_GRADUATION_VERSION) @api_versions.experimental_api @@ -81,16 +84,30 @@ def _list_share_replicas(self, share=None, search_opts=None): """List all share replicas or list replicas belonging to a share. :param share: either share object or its UUID. - :param search_opts: default None + :param search_opts: dict of search options (e.g., metadata filters) + :rtype: list of :class:`ShareReplica` """ + search_opts = search_opts or {} + + # This will turn {'metadata': {'foo': 'bar', 'baz': 'qux'}} + # into ?metadata=foo:bar,baz:qux + # For nested search options like metadata, + # stringified inner dict is expected. + # e.g., {'metadata': 'foo:bar,baz:qux'} + query_string = self._build_query_string(search_opts) if share: share_id = '?share_id=' + base.getid(share) url = RESOURCES_PATH + '/detail' + share_id + if query_string: + url += '&' + query_string.lstrip('?') return self._list(url, RESOURCES_NAME) else: - return self._list(RESOURCES_PATH + '/detail', RESOURCES_NAME) + url = RESOURCES_PATH + '/detail' + if query_string: + url += query_string + return self._list(url, RESOURCES_NAME) @api_versions.wraps("2.11", constants.REPLICA_PRE_GRADUATION_VERSION) @api_versions.experimental_api @@ -125,30 +142,63 @@ def promote(self, replica, quiesce_wait_time=None): # noqa F811 @api_versions.experimental_api def create(self, share, availability_zone=None): return self._create_share_replica( - share, availability_zone=availability_zone) + share, availability_zone=availability_zone + ) @api_versions.wraps(constants.REPLICA_GRADUATION_VERSION, '2.66') # noqa def create(self, share, availability_zone=None): # noqa F811 return self._create_share_replica( - share, availability_zone=availability_zone) + share, availability_zone=availability_zone + ) @api_versions.wraps("2.67", "2.71") # noqa - def create(self, share, availability_zone=None, scheduler_hints=None): # noqa F811 + def create(self, share, availability_zone=None, scheduler_hints=None): # noqa F811 return self._create_share_replica( - share, availability_zone=availability_zone, - scheduler_hints=scheduler_hints) - - @api_versions.wraps("2.72") # noqa - def create(self, share, # pylint: disable=function-redefined # noqa F811 - availability_zone=None, scheduler_hints=None, - share_network=None): + share, + availability_zone=availability_zone, + scheduler_hints=scheduler_hints, + ) + + @api_versions.wraps("2.72", "2.94") # noqa + def create( # noqa + self, + share, # pylint: disable=function-redefined # noqa F811 + availability_zone=None, + scheduler_hints=None, + share_network=None, + ): return self._create_share_replica( - share, availability_zone=availability_zone, + share, + availability_zone=availability_zone, scheduler_hints=scheduler_hints, - share_network=share_network) - - def _create_share_replica(self, share, availability_zone=None, - scheduler_hints=None, share_network=None): + share_network=share_network, + ) + + @api_versions.wraps("2.95") # noqa + def create( # noqa + self, + share, # pylint: disable=function-redefined # noqa F811 + availability_zone=None, + scheduler_hints=None, + share_network=None, + metadata=None, + ): + return self._create_share_replica( + share, + availability_zone=availability_zone, + scheduler_hints=scheduler_hints, + share_network=share_network, + metadata=metadata, + ) + + def _create_share_replica( + self, + share, + availability_zone=None, + scheduler_hints=None, + share_network=None, + metadata=None, + ): """Create a replica for a share. :param share: The share to create the replica of. Can be the share @@ -157,11 +207,13 @@ def _create_share_replica(self, share, availability_zone=None, :param scheduler_hints: The scheduler_hints as key=value pair. Only supported key is 'only_host'. :param share_network: either share network object or its UUID. + :param metadata: dict - optional metadata to set on share replica + creation """ share_id = base.getid(share) - body = {'share_id': share_id} + body = {'share_id': share_id} if availability_zone: body['availability_zone'] = base.getid(availability_zone) @@ -171,9 +223,12 @@ def _create_share_replica(self, share, availability_zone=None, if share_network: body['share_network_id'] = base.getid(share_network) - return self._create(RESOURCES_PATH, - {RESOURCE_NAME: body}, - RESOURCE_NAME) + if metadata: + body['metadata'] = metadata + + return self._create( + RESOURCES_PATH, {RESOURCE_NAME: body}, RESOURCE_NAME + ) @api_versions.wraps("2.11", constants.REPLICA_PRE_GRADUATION_VERSION) @api_versions.experimental_api diff --git a/manilaclient/v2/share_servers.py b/manilaclient/v2/share_servers.py index 7f53142b..a61f93f4 100644 --- a/manilaclient/v2/share_servers.py +++ b/manilaclient/v2/share_servers.py @@ -24,14 +24,13 @@ class ShareServer(base.Resource): - def __repr__(self): - return "" % self.id + return f"" def __getattr__(self, attr): if attr == 'share_network': attr = 'share_network_name' - return super(ShareServer, self).__getattr__(attr) + return super().__getattr__(attr) def delete(self): """Delete this share server.""" @@ -45,19 +44,41 @@ def reset_state(self, state): """Update the share server with the provided state.""" self.manager.reset_state(self, state) - def migration_check(self, host, writable, nondisruptive, - preserve_snapshots, new_share_network_id=None): + def migration_check( + self, + host, + writable, + nondisruptive, + preserve_snapshots, + new_share_network_id=None, + ): """Check if the new host is suitable for migration.""" return self.manager.migration_check( - self, host, writable, nondisruptive, - preserve_snapshots, new_share_network_id=new_share_network_id) - - def migration_start(self, host, writable, nondisruptive, - preserve_snapshots, new_share_network_id=None): + self, + host, + writable, + nondisruptive, + preserve_snapshots, + new_share_network_id=new_share_network_id, + ) + + def migration_start( + self, + host, + writable, + nondisruptive, + preserve_snapshots, + new_share_network_id=None, + ): """Migrate the share server to a new host.""" self.manager.migration_start( - self, host, writable, nondisruptive, - preserve_snapshots, new_share_network_id=new_share_network_id) + self, + host, + writable, + nondisruptive, + preserve_snapshots, + new_share_network_id=new_share_network_id, + ) def migration_complete(self): """Complete migration of a share server.""" @@ -78,6 +99,7 @@ def reset_task_state(self, task_state): class ShareServerManager(base.ManagerWithFind): """Manage :class:`ShareServer` resources.""" + resource_class = ShareServer def get(self, server): @@ -87,8 +109,7 @@ def get(self, server): :rtype: :class:`ShareServer` """ server_id = base.getid(server) - server = self._get("%s/%s" % (RESOURCES_PATH, server_id), - RESOURCE_NAME) + server = self._get(f"{RESOURCES_PATH}/{server_id}", RESOURCE_NAME) # Split big dict 'backend_details' to separated strings # as next: # +---------------------+------------------------------------+ @@ -97,7 +118,7 @@ def get(self, server): # | details:instance_id |35203a78-c733-4b1f-b82c-faded312e537| # +---------------------+------------------------------------+ for k, v in server._info["backend_details"].items(): - server._info["details:%s" % k] = v + server._info[f"details:{k}"] = v return server def details(self, server): @@ -107,8 +128,7 @@ def details(self, server): :rtype: list of :class:`ShareServerBackendDetails """ server_id = base.getid(server) - return self._get("%s/%s/details" % (RESOURCES_PATH, server_id), - "details") + return self._get(f"{RESOURCES_PATH}/{server_id}/details", "details") def delete(self, server): """Delete share server. @@ -128,7 +148,6 @@ def list(self, search_opts=None): @api_versions.wraps("2.49", "2.50") def manage(self, host, share_network_id, identifier, driver_options=None): - driver_options = driver_options or {} body = { 'host': host, @@ -138,13 +157,19 @@ def manage(self, host, share_network_id, identifier, driver_options=None): } resource_path = RESOURCE_PATH % 'manage' - return self._create(resource_path, {'share_server': body}, - 'share_server') + return self._create( + resource_path, {'share_server': body}, 'share_server' + ) @api_versions.wraps("2.51") # noqa - def manage(self, host, share_network_id, identifier, # noqa - share_network_subnet_id=None, driver_options=None): - + def manage( # noqa + self, + host, + share_network_id, + identifier, + share_network_subnet_id=None, + driver_options=None, + ): driver_options = driver_options or {} body = { 'host': host, @@ -155,8 +180,9 @@ def manage(self, host, share_network_id, identifier, # noqa } resource_path = RESOURCE_PATH % 'manage' - return self._create(resource_path, {'share_server': body}, - 'share_server') + return self._create( + resource_path, {'share_server': body}, 'share_server' + ) @api_versions.wraps("2.49") def unmanage(self, share_server, force=False): @@ -185,8 +211,15 @@ def _action(self, action, share_server, info=None): @api_versions.wraps("2.57") @api_versions.experimental_api - def migration_check(self, share_server, host, writable, nondisruptive, - preserve_snapshots, new_share_network_id=None): + def migration_check( + self, + share_server, + host, + writable, + nondisruptive, + preserve_snapshots, + new_share_network_id=None, + ): """Check the share server migration to a new host :param share_server: either share_server object or text with its ID. @@ -197,20 +230,29 @@ def migration_check(self, share_server, host, writable, nondisruptive, :param new_share_network_id: Specify the new share network id. """ result = self._action( - "migration_check", share_server, { + "migration_check", + share_server, + { "host": host, "preserve_snapshots": preserve_snapshots, "writable": writable, "nondisruptive": nondisruptive, "new_share_network_id": new_share_network_id, - }) + }, + ) return result[1] @api_versions.wraps("2.57") @api_versions.experimental_api - def migration_start(self, share_server, host, writable, - nondisruptive, preserve_snapshots, - new_share_network_id=None): + def migration_start( + self, + share_server, + host, + writable, + nondisruptive, + preserve_snapshots, + new_share_network_id=None, + ): """Migrates share server to a new host :param share_server: either share_server object or text with its ID. @@ -221,13 +263,16 @@ def migration_start(self, share_server, host, writable, :param new_share_network_id: Specify the new share network id. """ return self._action( - "migration_start", share_server, { + "migration_start", + share_server, + { "host": host, "writable": writable, "nondisruptive": nondisruptive, "preserve_snapshots": preserve_snapshots, "new_share_network_id": new_share_network_id, - }) + }, + ) @api_versions.wraps("2.57") @api_versions.experimental_api @@ -237,8 +282,9 @@ def reset_task_state(self, share_server, task_state): :param share_server: either share_server object or text with its ID. :param task_state: text with new task state to set for share. """ - return self._action('reset_task_state', share_server, - {"task_state": task_state}) + return self._action( + 'reset_task_state', share_server, {"task_state": task_state} + ) @api_versions.wraps("2.57") @api_versions.experimental_api @@ -258,8 +304,7 @@ def migration_cancel(self, share_server): :param share_server: either share_server object or text with its ID. """ - return self._action('migration_cancel', - share_server) + return self._action('migration_cancel', share_server) @api_versions.wraps("2.57") @api_versions.experimental_api diff --git a/manilaclient/v2/share_snapshot_export_locations.py b/manilaclient/v2/share_snapshot_export_locations.py index 0775fa93..9bff10b4 100644 --- a/manilaclient/v2/share_snapshot_export_locations.py +++ b/manilaclient/v2/share_snapshot_export_locations.py @@ -21,7 +21,7 @@ class ShareSnapshotExportLocation(base.Resource): """Represent an export location snapshot of a snapshot.""" def __repr__(self): - return "" % self.id + return f"" def __getitem__(self, key): return self._info[key] @@ -29,13 +29,15 @@ def __getitem__(self, key): class ShareSnapshotExportLocationManager(base.ManagerWithFind): """Manage :class:`ShareSnapshotExportLocation` resources.""" + resource_class = ShareSnapshotExportLocation @api_versions.wraps("2.32") def list(self, snapshot=None, search_opts=None): - return self._list("/snapshots/%s/export-locations" % - base.getid(snapshot), - 'share_snapshot_export_locations') + return self._list( + f"/snapshots/{base.getid(snapshot)}/export-locations", + 'share_snapshot_export_locations', + ) @api_versions.wraps("2.32") def get(self, export_location, snapshot=None): @@ -44,6 +46,8 @@ def get(self, export_location, snapshot=None): "export_location_id": base.getid(export_location), } - return self._get("/snapshots/%(snapshot_id)s/export-locations/" - "%(export_location_id)s" % params, - "share_snapshot_export_location") + return self._get( + "/snapshots/{snapshot_id}/export-locations/" + "{export_location_id}".format(**params), + "share_snapshot_export_location", + ) diff --git a/manilaclient/v2/share_snapshot_instance_export_locations.py b/manilaclient/v2/share_snapshot_instance_export_locations.py index 73c23f76..4ba44a39 100644 --- a/manilaclient/v2/share_snapshot_instance_export_locations.py +++ b/manilaclient/v2/share_snapshot_instance_export_locations.py @@ -21,7 +21,7 @@ class ShareSnapshotInstanceExportLocation(base.Resource): """Represent an export location from a snapshot instance.""" def __repr__(self): - return "" % self.id + return f"" def __getitem__(self, key): return self._info[key] @@ -29,13 +29,15 @@ def __getitem__(self, key): class ShareSnapshotInstanceExportLocationManager(base.ManagerWithFind): """Manage :class:`ShareSnapshotInstanceExportLocation` resources.""" + resource_class = ShareSnapshotInstanceExportLocation @api_versions.wraps("2.32") def list(self, snapshot_instance=None, search_opts=None): - return self._list("/snapshot-instances/%s/export-locations" % - base.getid(snapshot_instance), - 'share_snapshot_export_locations') + return self._list( + f"/snapshot-instances/{base.getid(snapshot_instance)}/export-locations", + 'share_snapshot_export_locations', + ) @api_versions.wraps("2.32") def get(self, export_location, snapshot_instance=None): @@ -44,6 +46,8 @@ def get(self, export_location, snapshot_instance=None): "export_location_id": base.getid(export_location), } - return self._get("/snapshot-instances/%(snapshot_instance_id)s/" - "export-locations/%(export_location_id)s" % params, - "share_snapshot_export_location") + return self._get( + "/snapshot-instances/{snapshot_instance_id}/" + "export-locations/{export_location_id}".format(**params), + "share_snapshot_export_location", + ) diff --git a/manilaclient/v2/share_snapshot_instances.py b/manilaclient/v2/share_snapshot_instances.py index a4c4282d..1c9a2d3b 100644 --- a/manilaclient/v2/share_snapshot_instances.py +++ b/manilaclient/v2/share_snapshot_instances.py @@ -21,7 +21,7 @@ class ShareSnapshotInstance(base.Resource): """A snapshot instance is an instance of a snapshot.""" def __repr__(self): - return "" % self.id + return f"" def reset_state(self, state): """Update snapshot instance's 'status' attr.""" @@ -30,6 +30,7 @@ def reset_state(self, state): class ShareSnapshotInstanceManager(base.ManagerWithFind): """Manage :class:`SnapshotInstances` resources.""" + resource_class = ShareSnapshotInstance @api_versions.wraps("2.19") @@ -40,8 +41,9 @@ def get(self, instance): :rtype: :class:`ShareSnapshotInstance` """ snapshot_instance_id = base.getid(instance) - return self._get("/snapshot-instances/%s" % snapshot_instance_id, - "snapshot_instance") + return self._get( + f"/snapshot-instances/{snapshot_instance_id}", "snapshot_instance" + ) @api_versions.wraps("2.19") def list(self, detailed=False, snapshot=None, search_opts=None): @@ -52,7 +54,7 @@ def list(self, detailed=False, snapshot=None, search_opts=None): url = '/snapshot-instances' if snapshot: - url += '?snapshot_id=%s' % base.getid(snapshot) + url += f'?snapshot_id={base.getid(snapshot)}' return self._list(url, 'snapshot_instances') @api_versions.wraps("2.19") @@ -68,6 +70,5 @@ def _action(self, action, instance, info=None, **kwargs): """Perform a snapshot instance 'action'.""" body = {action: info} self.run_hooks('modify_body_for_action', body, **kwargs) - url = ('/snapshot-instances/%s/action' % - base.getid(instance)) + url = f'/snapshot-instances/{base.getid(instance)}/action' return self.api.client.post(url, body=body) diff --git a/manilaclient/v2/share_snapshots.py b/manilaclient/v2/share_snapshots.py index 72458a00..d2fb57b5 100644 --- a/manilaclient/v2/share_snapshots.py +++ b/manilaclient/v2/share_snapshots.py @@ -20,11 +20,10 @@ class ShareSnapshot(base.MetadataCapableResource): - """Represent a snapshot of a share.""" def __repr__(self): - return "" % self.id + return f"" def update(self, **kwargs): """Update this snapshot.""" @@ -60,11 +59,13 @@ def access_list(self): class ShareSnapshotManager(base.MetadataCapableManager): """Manage :class:`ShareSnapshot` resources.""" + resource_class = ShareSnapshot resource_path = '/snapshots' - def _do_create(self, share, force=False, name=None, description=None, - metadata=None): + def _do_create( + self, share, force=False, name=None, description=None, metadata=None + ): """Create a snapshot of the given share. :param share_id: The ID of the share to snapshot. @@ -77,11 +78,15 @@ def _do_create(self, share, force=False, name=None, description=None, """ metadata = metadata if metadata is not None else dict() - body = {'snapshot': {'share_id': base.getid(share), - 'force': force, - 'name': name, - 'description': description, - 'metadata': metadata}} + body = { + 'snapshot': { + 'share_id': base.getid(share), + 'force': force, + 'name': name, + 'description': description, + 'metadata': metadata, + } + } return self._create('/snapshots', body, 'snapshot') @api_versions.wraps("2.0", "2.72") @@ -89,14 +94,25 @@ def create(self, share, force=False, name=None, description=None): return self._do_create(share, force, name, description) @api_versions.wraps("2.73") - def create(self, share, force=False, name=None, description=None,# noqa F811 - metadata=None): + def create( # noqa + self, + share, + force=False, + name=None, + description=None, + metadata=None, + ): return self._do_create(share, force, name, description, metadata) @api_versions.wraps("2.12") - def manage(self, share, provider_location, - driver_options=None, - name=None, description=None): + def manage( + self, + share, + provider_location, + driver_options=None, + name=None, + description=None, + ): """Manage an existing share snapshot. :param share: The share object. @@ -114,8 +130,9 @@ def manage(self, share, provider_location, 'name': name, 'description': description, } - return self._create('/snapshots/manage', {'snapshot': body}, - 'snapshot') + return self._create( + '/snapshots/manage', {'snapshot': body}, 'snapshot' + ) @api_versions.wraps("2.12") def unmanage(self, snapshot): @@ -133,10 +150,11 @@ def get(self, snapshot): :rtype: :class:`ShareSnapshot` """ snapshot_id = base.getid(snapshot) - return self._get('/snapshots/%s' % snapshot_id, 'snapshot') + return self._get(f'/snapshots/{snapshot_id}', 'snapshot') - def list(self, detailed=True, search_opts=None, sort_key=None, - sort_dir=None): + def list( + self, detailed=True, search_opts=None, sort_key=None, sort_dir=None + ): """Get a list of snapshots of shares. :param search_opts: Search options to filter out shares. @@ -151,23 +169,27 @@ def list(self, detailed=True, search_opts=None, sort_key=None, search_opts['sort_key'] = sort_key else: raise ValueError( - 'sort_key must be one of the following: %s.' - % ', '.join(constants.SNAPSHOT_SORT_KEY_VALUES)) + 'sort_key must be one of the following: {}.'.format( + ', '.join(constants.SNAPSHOT_SORT_KEY_VALUES) + ) + ) if sort_dir is not None: if sort_dir in constants.SORT_DIR_VALUES: search_opts['sort_dir'] = sort_dir else: raise ValueError( - 'sort_dir must be one of the following: %s.' - % ', '.join(constants.SORT_DIR_VALUES)) + 'sort_dir must be one of the following: {}.'.format( + ', '.join(constants.SORT_DIR_VALUES) + ) + ) query_string = self._build_query_string(search_opts) if detailed: - path = "/snapshots/detail%s" % (query_string,) + path = f"/snapshots/detail{query_string}" else: - path = "/snapshots%s" % (query_string,) + path = f"/snapshots{query_string}" return self._list(path, 'snapshots') @@ -176,7 +198,7 @@ def delete(self, snapshot): :param snapshot: The :class:`ShareSnapshot` to delete. """ - self._delete("/snapshots/%s" % base.getid(snapshot)) + self._delete(f"/snapshots/{base.getid(snapshot)}") def _do_force_delete(self, snapshot, action_name="force_delete"): """Delete the specified snapshot ignoring its current state.""" @@ -200,9 +222,11 @@ def update(self, snapshot, **kwargs): if not kwargs: return - body = {'snapshot': kwargs, } + body = { + 'snapshot': kwargs, + } snapshot_id = base.getid(snapshot) - return self._update("/snapshots/%s" % snapshot_id, body) + return self._update(f"/snapshots/{snapshot_id}", body) def _do_reset_state(self, snapshot, state, action_name="reset_status"): """Update the specified share snapshot with the provided state.""" @@ -222,8 +246,9 @@ def _do_allow(self, snapshot, access_type, access_to): 'access_to': access_to, } - return self._action('allow_access', snapshot, - access_params)[1]['snapshot_access'] + return self._action('allow_access', snapshot, access_params)[1][ + 'snapshot_access' + ] @api_versions.wraps("2.32") def allow(self, snapshot, access_type, access_to): @@ -238,8 +263,9 @@ def deny(self, snapshot, id): def _do_access_list(self, snapshot): snapshot_id = base.getid(snapshot) - access_list = self._list("/snapshots/%s/access-list" % snapshot_id, - 'snapshot_access_list') + access_list = self._list( + f"/snapshots/{snapshot_id}/access-list", 'snapshot_access_list' + ) return access_list @api_versions.wraps("2.32") @@ -250,5 +276,5 @@ def _action(self, action, snapshot, info=None, **kwargs): """Perform a snapshot 'action'.""" body = {action: info} self.run_hooks('modify_body_for_action', body, **kwargs) - url = '/snapshots/%s/action' % base.getid(snapshot) + url = f'/snapshots/{base.getid(snapshot)}/action' return self.api.client.post(url, body=body) diff --git a/manilaclient/v2/share_transfers.py b/manilaclient/v2/share_transfers.py index 3304d89a..9720b798 100644 --- a/manilaclient/v2/share_transfers.py +++ b/manilaclient/v2/share_transfers.py @@ -22,7 +22,7 @@ class ShareTransfer(base.Resource): """Transfer a share from one tenant to another""" def __repr__(self): - return "" % self.id + return f"" def delete(self): """Delete this share transfer.""" @@ -31,6 +31,7 @@ def delete(self): class ShareTransferManager(base.ManagerWithFind): """Manage :class:`ShareTransfer` resources.""" + resource_class = ShareTransfer @api_versions.wraps(constants.SHARE_TRANSFER_VERSION) @@ -41,8 +42,7 @@ def create(self, share_id, name=None): :param name: The name of the transfer. :rtype: :class:`ShareTransfer` """ - body = {'transfer': {'share_id': share_id, - 'name': name}} + body = {'transfer': {'share_id': share_id, 'name': name}} return self._create('/share-transfers', body, 'transfer') @@ -56,10 +56,14 @@ def accept(self, transfer, auth_key, clear_access_rules=False): :rtype: :class:`ShareTransfer` """ transfer_id = base.getid(transfer) - body = {'accept': {'auth_key': auth_key, - 'clear_access_rules': clear_access_rules}} + body = { + 'accept': { + 'auth_key': auth_key, + 'clear_access_rules': clear_access_rules, + } + } - self._accept('/share-transfers/%s/accept' % transfer_id, body) + self._accept(f'/share-transfers/{transfer_id}/accept', body) @api_versions.wraps(constants.SHARE_TRANSFER_VERSION) def get(self, transfer_id): @@ -68,11 +72,12 @@ def get(self, transfer_id): :param transfer_id: The ID of the share transfer to display. :rtype: :class:`ShareTransfer` """ - return self._get("/share-transfers/%s" % transfer_id, "transfer") + return self._get(f"/share-transfers/{transfer_id}", "transfer") @api_versions.wraps(constants.SHARE_TRANSFER_VERSION) - def list(self, detailed=True, search_opts=None, - sort_key=None, sort_dir=None): + def list( + self, detailed=True, search_opts=None, sort_key=None, sort_dir=None + ): """Get a list of all share transfer. :param detailed: Get detailed object information. @@ -92,22 +97,27 @@ def list(self, detailed=True, search_opts=None, search_opts['sort_key'] = 'display_name' else: raise ValueError( - 'sort_key must be one of the following: %s.' - % ', '.join(constants.SHARE_TRANSFER_SORT_KEY_VALUES)) + 'sort_key must be one of the following: {}.'.format( + ', '.join(constants.SHARE_TRANSFER_SORT_KEY_VALUES) + ) + ) if sort_dir is not None: if sort_dir in constants.SORT_DIR_VALUES: search_opts['sort_dir'] = sort_dir else: - raise ValueError('sort_dir must be one of the following: %s.' - % ', '.join(constants.SORT_DIR_VALUES)) + raise ValueError( + 'sort_dir must be one of the following: {}.'.format( + ', '.join(constants.SORT_DIR_VALUES) + ) + ) query_string = self._build_query_string(search_opts) if detailed: - path = "/share-transfers/detail%s" % (query_string,) + path = f"/share-transfers/detail{query_string}" else: - path = "/share-transfers%s" % (query_string,) + path = f"/share-transfers{query_string}" return self._list(path, 'transfers') @@ -118,4 +128,4 @@ def delete(self, transfer_id): :param transfer_id: The :class:`ShareTransfer` to delete. """ - return self._delete("/share-transfers/%s" % base.getid(transfer_id)) + return self._delete(f"/share-transfers/{base.getid(transfer_id)}") diff --git a/manilaclient/v2/share_type_access.py b/manilaclient/v2/share_type_access.py index 56d7d266..02ff0eb0 100644 --- a/manilaclient/v2/share_type_access.py +++ b/manilaclient/v2/share_type_access.py @@ -20,7 +20,7 @@ class ShareTypeAccess(base.Resource): def __repr__(self): - return "" % self.id + return f"" class ShareTypeAccessManager(base.ManagerWithFind): @@ -33,10 +33,9 @@ def _do_list(self, share_type, action_name="share_type_access"): return None return self._list( - "/types/%(st_id)s/%(action_name)s" % { - "st_id": base.getid(share_type), - "action_name": action_name}, - "share_type_access") + f"/types/{base.getid(share_type)}/{action_name}", + "share_type_access", + ) @api_versions.wraps("1.0", "2.6") def list(self, share_type, search_opts=None): @@ -60,5 +59,5 @@ def _action(self, action, share_type, info, **kwargs): """Perform a share type action.""" body = {action: info} self.run_hooks('modify_body_for_action', body, **kwargs) - url = '/types/%s/action' % base.getid(share_type) + url = f'/types/{base.getid(share_type)}/action' return self.api.client.post(url, body=body) diff --git a/manilaclient/v2/share_types.py b/manilaclient/v2/share_types.py index e2383e76..ac2db13c 100644 --- a/manilaclient/v2/share_types.py +++ b/manilaclient/v2/share_types.py @@ -27,21 +27,22 @@ class ShareType(base.Resource): """A Share Type is the type of share to be created.""" def __init__(self, manager, info, loaded=False): - super(ShareType, self).__init__(manager, info, loaded) + super().__init__(manager, info, loaded) self._required_extra_specs = info.get('required_extra_specs', {}) self._optional_extra_specs = info.get('extra_specs', {}).copy() for key in self._required_extra_specs.keys(): self._optional_extra_specs.pop(key, None) def __repr__(self): - return "" % self.name + return f"" @property def is_public(self): """Provide a user-friendly accessor to [os-]share-type-access.""" return self._info.get( "share_type_access:is_public", - self._info.get("os-share-type-access:is_public", "N/A")) + self._info.get("os-share-type-access:is_public", "N/A"), + ) def get_keys(self, prefer_resource_data=True): """Get extra specs from a share type. @@ -56,7 +57,8 @@ def get_keys(self, prefer_resource_data=True): return extra_specs _resp, body = self.manager.api.client.get( - "/types/%s/extra_specs" % base.getid(self)) + f"/types/{base.getid(self)}/extra_specs" + ) self.extra_specs = body["extra_specs"] @@ -76,7 +78,7 @@ def set_keys(self, metadata): """ body = {'extra_specs': metadata} return self.manager._create( - "/types/%s/extra_specs" % base.getid(self), + f"/types/{base.getid(self)}/extra_specs", body, "extra_specs", return_raw=True, @@ -96,7 +98,8 @@ def unset_keys(self, keys): resp = None for k in keys: resp = self.manager._delete( - "/types/%s/extra_specs/%s" % (base.getid(self), k)) + f"/types/{base.getid(self)}/extra_specs/{k}" + ) if resp is not None: return resp @@ -119,7 +122,7 @@ def list(self, search_opts=None, show_all=True): if show_all: search_opts['is_public'] = 'all' query_string = self._build_query_string(search_opts) - return self._list("/types%s" % query_string, "share_types") + return self._list(f"/types{query_string}", "share_types") def show(self, share_type): """Get a share type. @@ -128,7 +131,7 @@ def show(self, share_type): :rtype: :class:`ShareType` """ type_id = base.getid(share_type) - return self._get("/types/%s" % type_id, "share_type") + return self._get(f"/types/{type_id}", "share_type") def get(self, share_type="default"): """Get a specific share type. @@ -136,19 +139,23 @@ def get(self, share_type="default"): :param share_type: The ID of the :class:`ShareType` to get. :rtype: :class:`ShareType` """ - return self._get("/types/%s" % base.getid(share_type), - "share_type") + return self._get(f"/types/{base.getid(share_type)}", "share_type") def delete(self, share_type): """Delete a specific share_type. :param share_type: The name or ID of the :class:`ShareType` to get. """ - self._delete("/types/%s" % base.getid(share_type)) - - def _do_create(self, name, extra_specs, is_public, - is_public_keyname="share_type_access:is_public", - description=None): + self._delete(f"/types/{base.getid(share_type)}") + + def _do_create( + self, + name, + extra_specs, + is_public, + is_public_keyname="share_type_access:is_public", + description=None, + ): """Create a share type. :param name: Descriptive name of the share type @@ -167,9 +174,14 @@ def _do_create(self, name, extra_specs, is_public, body["share_type"]["description"] = description return self._create("/types", body, "share_type") - def _do_update(self, share_type, name=None, is_public=None, - is_public_keyname="share_type_access:is_public", - description=None): + def _do_update( + self, + share_type, + name=None, + is_public=None, + is_public_keyname="share_type_access:is_public", + description=None, + ): """Update the name and/or description for a share type. :param share_type: the ID of the :class: `ShareType` to update. @@ -178,9 +190,7 @@ def _do_update(self, share_type, name=None, is_public=None, :rtype: :class:`ShareType` """ - body = { - "share_type": {} - } + body = {"share_type": {}} if name: body["share_type"]["name"] = name @@ -188,90 +198,130 @@ def _do_update(self, share_type, name=None, is_public=None, body["share_type"][is_public_keyname] = is_public if description or description == "": body["share_type"]["description"] = description - return self._update("/types/%s" % base.getid(share_type), - body, "share_type") + return self._update( + f"/types/{base.getid(share_type)}", body, "share_type" + ) @api_versions.wraps("1.0", "2.6") - def create(self, name, spec_driver_handles_share_servers, - spec_snapshot_support=None, is_public=True, extra_specs=None): - + def create( + self, + name, + spec_driver_handles_share_servers, + spec_snapshot_support=None, + is_public=True, + extra_specs=None, + ): if extra_specs is None: extra_specs = {} self._handle_spec_driver_handles_share_servers( - extra_specs, spec_driver_handles_share_servers) + extra_specs, spec_driver_handles_share_servers + ) self._handle_spec_snapshot_support( - extra_specs, spec_snapshot_support, set_default=True) + extra_specs, spec_snapshot_support, set_default=True + ) return self._do_create( - name, extra_specs, is_public, - is_public_keyname="os-share-type-access:is_public") + name, + extra_specs, + is_public, + is_public_keyname="os-share-type-access:is_public", + ) @api_versions.wraps("2.7", "2.23") # noqa - def create(self, name, spec_driver_handles_share_servers, # noqa - spec_snapshot_support=None, is_public=True, extra_specs=None): - + def create( # noqa + self, + name, + spec_driver_handles_share_servers, + spec_snapshot_support=None, + is_public=True, + extra_specs=None, + ): if extra_specs is None: extra_specs = {} self._handle_spec_driver_handles_share_servers( - extra_specs, spec_driver_handles_share_servers) + extra_specs, spec_driver_handles_share_servers + ) self._handle_spec_snapshot_support( - extra_specs, spec_snapshot_support, set_default=True) + extra_specs, spec_snapshot_support, set_default=True + ) return self._do_create(name, extra_specs, is_public) @api_versions.wraps("2.24", "2.40") # noqa - def create(self, name, spec_driver_handles_share_servers, # noqa - spec_snapshot_support=None, is_public=True, extra_specs=None): - + def create( # noqa + self, + name, + spec_driver_handles_share_servers, + spec_snapshot_support=None, + is_public=True, + extra_specs=None, + ): if extra_specs is None: extra_specs = {} self._handle_spec_driver_handles_share_servers( - extra_specs, spec_driver_handles_share_servers) + extra_specs, spec_driver_handles_share_servers + ) self._handle_spec_snapshot_support(extra_specs, spec_snapshot_support) return self._do_create(name, extra_specs, is_public) @api_versions.wraps("2.41") # noqa - def create(self, name, spec_driver_handles_share_servers, # noqa - spec_snapshot_support=None, is_public=True, extra_specs=None, - description=None): + def create( # noqa + self, + name, + spec_driver_handles_share_servers, + spec_snapshot_support=None, + is_public=True, + extra_specs=None, + description=None, + ): if extra_specs is None: extra_specs = {} self._handle_spec_driver_handles_share_servers( - extra_specs, spec_driver_handles_share_servers) + extra_specs, spec_driver_handles_share_servers + ) self._handle_spec_snapshot_support(extra_specs, spec_snapshot_support) - return self._do_create(name, extra_specs, is_public, - description=description) + return self._do_create( + name, extra_specs, is_public, description=description + ) @api_versions.wraps("2.50") def update(self, share_type, name=None, is_public=None, description=None): - return self._do_update(share_type, name, is_public, - description=description) + return self._do_update( + share_type, name, is_public, description=description + ) def _handle_spec_driver_handles_share_servers( - self, extra_specs, spec_driver_handles_share_servers): + self, extra_specs, spec_driver_handles_share_servers + ): """Validation and default for DHSS extra spec.""" if spec_driver_handles_share_servers is not None: if 'driver_handles_share_servers' in extra_specs: - msg = ("'driver_handles_share_servers' is already set via " - "positional argument.") + msg = ( + "'driver_handles_share_servers' is already set via " + "positional argument." + ) raise exceptions.CommandError(msg) else: extra_specs['driver_handles_share_servers'] = ( - spec_driver_handles_share_servers) + spec_driver_handles_share_servers + ) else: - msg = ("'driver_handles_share_servers' is not set via " - "positional argument.") + msg = ( + "'driver_handles_share_servers' is not set via " + "positional argument." + ) raise exceptions.CommandError(msg) - def _handle_spec_snapshot_support(self, extra_specs, spec_snapshot_support, - set_default=False): + def _handle_spec_snapshot_support( + self, extra_specs, spec_snapshot_support, set_default=False + ): """Validation and default for snapshot extra spec.""" if spec_snapshot_support is not None: diff --git a/manilaclient/v2/shares.py b/manilaclient/v2/shares.py index 2f419a48..805282ef 100644 --- a/manilaclient/v2/shares.py +++ b/manilaclient/v2/shares.py @@ -28,10 +28,10 @@ class Share(base.MetadataCapableResource): - """A share is an extra block level storage to the OpenStack instances.""" + def __repr__(self): - return "" % self.id + return f"" def update(self, **kwargs): """Update this share.""" @@ -41,15 +41,29 @@ def unmanage(self, **kwargs): """Unmanage this share.""" self.manager.unmanage(self, **kwargs) - def migration_start(self, host, force_host_assisted_migration, - preserve_metadata, writable, nondisruptive, - preserve_snapshots, new_share_network_id=None, - new_share_type_id=None): + def migration_start( + self, + host, + force_host_assisted_migration, + preserve_metadata, + writable, + nondisruptive, + preserve_snapshots, + new_share_network_id=None, + new_share_type_id=None, + ): """Migrate the share to a new host.""" - self.manager.migration_start(self, host, force_host_assisted_migration, - preserve_metadata, writable, - nondisruptive, preserve_snapshots, - new_share_network_id, new_share_type_id) + self.manager.migration_start( + self, + host, + force_host_assisted_migration, + preserve_metadata, + writable, + nondisruptive, + preserve_snapshots, + new_share_network_id, + new_share_type_id, + ) def migration_complete(self): """Complete migration of a share.""" @@ -118,14 +132,28 @@ def restore(self): class ShareManager(base.MetadataCapableManager): """Manage :class:`Share` resources.""" + resource_class = Share resource_path = '/shares' - def create(self, share_proto, size, snapshot_id=None, name=None, - description=None, metadata=None, share_network=None, - share_type=None, is_public=False, availability_zone=None, - share_group_id=None, scheduler_hints=None, return_raw=False, - mount_point_name=None): + def create( + self, + share_proto, + size, + snapshot_id=None, + name=None, + description=None, + metadata=None, + share_network=None, + share_type=None, + is_public=False, + availability_zone=None, + share_group_id=None, + scheduler_hints=None, + return_raw=False, + mount_point_name=None, + encryption_key_ref=None, + ): """Create a share. :param share_proto: text - share protocol for new share available @@ -146,11 +174,14 @@ def create(self, share_proto, size, snapshot_id=None, name=None, :param mount_point_name: text - share human-readable mount point name. This name will be reflected in export location once share is created. + :param encryption_key_ref: text - encryption key reference, i.e. UUID + of the secret stored in the key manager. :rtype: :class:`Share` """ share_metadata = metadata if metadata is not None else dict() - scheduler_hints = (scheduler_hints if scheduler_hints is not None - else dict()) + scheduler_hints = ( + scheduler_hints if scheduler_hints is not None else dict() + ) body = { 'size': size, 'snapshot_id': snapshot_id, @@ -170,17 +201,82 @@ def create(self, share_proto, size, snapshot_id=None, name=None, if mount_point_name: body['mount_point_name'] = mount_point_name - return self._create('/shares', {'share': body}, 'share', - return_raw=return_raw) + if encryption_key_ref: + body['encryption_key_ref'] = encryption_key_ref - @api_versions.wraps("2.29") + return self._create( + '/shares', {'share': body}, 'share', return_raw=return_raw + ) + + @api_versions.wraps( + "2.29", constants.SHARE_MIGRATION_PRE_GRADUATION_VERSION + ) @api_versions.experimental_api - def migration_start(self, share, host, force_host_assisted_migration, - preserve_metadata, writable, nondisruptive, - preserve_snapshots, new_share_network_id=None, - new_share_type_id=None): + def migration_start( + self, + share, + host, + force_host_assisted_migration, + preserve_metadata, + writable, + nondisruptive, + preserve_snapshots, + new_share_network_id=None, + new_share_type_id=None, + ): + return self._migration_start( + share, + host, + force_host_assisted_migration, + preserve_metadata, + writable, + nondisruptive, + preserve_snapshots, + new_share_network_id, + new_share_type_id, + ) + + @api_versions.wraps(constants.SHARE_MIGRATION_GRADUATION_VERSION) # noqa + def migration_start( # noqa F811 + self, + share, + host, + force_host_assisted_migration, + preserve_metadata, + writable, + nondisruptive, + preserve_snapshots, + new_share_network_id=None, + new_share_type_id=None, + ): + return self._migration_start( + share, + host, + force_host_assisted_migration, + preserve_metadata, + writable, + nondisruptive, + preserve_snapshots, + new_share_network_id, + new_share_type_id, + ) + + def _migration_start( + self, + share, + host, + force_host_assisted_migration, + preserve_metadata, + writable, + nondisruptive, + preserve_snapshots, + new_share_network_id=None, + new_share_type_id=None, + ): return self._action( - "migration_start", share, { + "migration_start", + share, + { "host": host, "force_host_assisted_migration": force_host_assisted_migration, "preserve_metadata": preserve_metadata, @@ -189,9 +285,12 @@ def migration_start(self, share, host, force_host_assisted_migration, "nondisruptive": nondisruptive, "new_share_network_id": new_share_network_id, "new_share_type_id": new_share_type_id, - }) + }, + ) - @api_versions.wraps("2.22") + @api_versions.wraps( + "2.22", constants.SHARE_MIGRATION_PRE_GRADUATION_VERSION + ) @api_versions.experimental_api def reset_task_state(self, share, task_state): """Update the provided share with the provided task state. @@ -199,10 +298,25 @@ def reset_task_state(self, share, task_state): :param share: either share object or text with its ID. :param task_state: text with new task state to set for share. """ - return self._action('reset_task_state', share, - {"task_state": task_state}) + return self._reset_task_state(share, task_state) + + @api_versions.wraps(constants.SHARE_MIGRATION_GRADUATION_VERSION) # noqa + def reset_task_state(self, share, task_state): # noqa F811 + """Update the provided share with the provided task state. + + :param share: either share object or text with its ID. + :param task_state: text with new task state to set for share. + """ + return self._reset_task_state(share, task_state) - @api_versions.wraps("2.22") + def _reset_task_state(self, share, task_state): + return self._action( + 'reset_task_state', share, {"task_state": task_state} + ) + + @api_versions.wraps( + "2.22", constants.SHARE_MIGRATION_PRE_GRADUATION_VERSION + ) @api_versions.experimental_api def migration_complete(self, share): """Completes migration for a given share. @@ -211,7 +325,17 @@ def migration_complete(self, share): """ return self._action('migration_complete', share) - @api_versions.wraps("2.22") + @api_versions.wraps(constants.SHARE_MIGRATION_GRADUATION_VERSION) # noqa + def migration_complete(self, share): # noqa F811 + """Completes migration for a given share. + + :param share: The :class:'share' to complete migration + """ + return self._action('migration_complete', share) + + @api_versions.wraps( + "2.22", constants.SHARE_MIGRATION_PRE_GRADUATION_VERSION + ) @api_versions.experimental_api def migration_cancel(self, share): """Attempts to cancel migration for a given share. @@ -220,7 +344,17 @@ def migration_cancel(self, share): """ return self._action('migration_cancel', share) - @api_versions.wraps("2.22") + @api_versions.wraps(constants.SHARE_MIGRATION_GRADUATION_VERSION) # noqa + def migration_cancel(self, share): # noqa F811 + """Attempts to cancel migration for a given share. + + :param share: The :class:'share' to cancel migration + """ + return self._action('migration_cancel', share) + + @api_versions.wraps( + "2.22", constants.SHARE_MIGRATION_PRE_GRADUATION_VERSION + ) @api_versions.experimental_api def migration_get_progress(self, share): """Obtains progress of share migration for a given share. @@ -229,10 +363,28 @@ def migration_get_progress(self, share): """ return self._action('migration_get_progress', share) - def _do_manage(self, service_host, protocol, export_path, - driver_options=None, share_type=None, - name=None, description=None, is_public=None, - share_server_id=None, resource_path="/shares/manage"): + @api_versions.wraps(constants.SHARE_MIGRATION_GRADUATION_VERSION) # noqa + def migration_get_progress(self, share): # noqa F811 + """Obtains progress of share migration for a given share. + + :param share: The :class:'share' to obtain migration progress + """ + return self._action('migration_get_progress', share) + + def _do_manage( + self, + service_host, + protocol, + export_path, + driver_options=None, + share_type=None, + name=None, + description=None, + is_public=None, + share_server_id=None, + mount_point_name=None, + resource_path="/shares/manage", + ): """Manage some existing share. :param service_host: text - host where manila share service is running @@ -244,6 +396,7 @@ def _do_manage(self, service_host, protocol, export_path, :param description: - description for new share :param is_public: - visibility for new share :param share_server_id: text - id of share server associated with share + :param mount_point_name: text - mount point name of share """ driver_options = driver_options if driver_options else dict() body = { @@ -260,41 +413,132 @@ def _do_manage(self, service_host, protocol, export_path, if is_public is not None: body['is_public'] = is_public + if mount_point_name is not None: + body['mount_point_name'] = mount_point_name + return self._create(resource_path, {'share': body}, 'share') @api_versions.wraps("1.0", "2.6") - def manage(self, service_host, protocol, export_path, driver_options=None, - share_type=None, name=None, description=None): + def manage( + self, + service_host, + protocol, + export_path, + driver_options=None, + share_type=None, + name=None, + description=None, + ): return self._do_manage( - service_host, protocol, export_path, driver_options=driver_options, - share_type=share_type, name=name, description=description, - resource_path="/os-share-manage") + service_host, + protocol, + export_path, + driver_options=driver_options, + share_type=share_type, + name=name, + description=description, + resource_path="/os-share-manage", + ) @api_versions.wraps("2.7", "2.7") # noqa - def manage(self, service_host, protocol, export_path, driver_options=None, # noqa - share_type=None, name=None, description=None): + def manage( # noqa + self, + service_host, + protocol, + export_path, + driver_options=None, + share_type=None, + name=None, + description=None, + ): return self._do_manage( - service_host, protocol, export_path, driver_options=driver_options, - share_type=share_type, name=name, description=description, - resource_path="/shares/manage") + service_host, + protocol, + export_path, + driver_options=driver_options, + share_type=share_type, + name=name, + description=description, + resource_path="/shares/manage", + ) @api_versions.wraps("2.8", "2.48") # noqa - def manage(self, service_host, protocol, export_path, driver_options=None, # noqa - share_type=None, name=None, description=None, is_public=False): + def manage( # noqa + self, + service_host, + protocol, + export_path, + driver_options=None, + share_type=None, + name=None, + description=None, + is_public=False, + ): + return self._do_manage( + service_host, + protocol, + export_path, + driver_options=driver_options, + share_type=share_type, + name=name, + description=description, + is_public=is_public, + resource_path="/shares/manage", + ) + + @api_versions.wraps("2.49", "2.91") # noqa + def manage( # noqa + self, + service_host, + protocol, + export_path, + driver_options=None, + share_type=None, + name=None, + description=None, + is_public=False, + share_server_id=None, + ): return self._do_manage( - service_host, protocol, export_path, driver_options=driver_options, - share_type=share_type, name=name, description=description, - is_public=is_public, resource_path="/shares/manage") - - @api_versions.wraps("2.49") # noqa - def manage(self, service_host, protocol, export_path, driver_options=None, # noqa - share_type=None, name=None, description=None, is_public=False, - share_server_id=None): + service_host, + protocol, + export_path, + driver_options=driver_options, + share_type=share_type, + name=name, + description=description, + is_public=is_public, + share_server_id=share_server_id, + resource_path="/shares/manage", + ) + + @api_versions.wraps("2.92") # noqa + def manage( # noqa + self, + service_host, + protocol, + export_path, + driver_options=None, + share_type=None, + name=None, + description=None, + is_public=False, + share_server_id=None, + mount_point_name=None, + ): return self._do_manage( - service_host, protocol, export_path, driver_options=driver_options, - share_type=share_type, name=name, description=description, - is_public=is_public, share_server_id=share_server_id, - resource_path="/shares/manage") + service_host, + protocol, + export_path, + driver_options=driver_options, + share_type=share_type, + name=name, + description=description, + is_public=is_public, + share_server_id=share_server_id, + mount_point_name=mount_point_name, + resource_path="/shares/manage", + ) @api_versions.wraps("1.0", "2.6") def unmanage(self, share): @@ -303,10 +547,11 @@ def unmanage(self, share): :param share: either share object or text with its ID. """ return self.api.client.post( - "/os-share-unmanage/%s/unmanage" % base.getid(share)) + f"/os-share-unmanage/{base.getid(share)}/unmanage" + ) @api_versions.wraps("2.7") # noqa - def unmanage(self, share): # noqa + def unmanage(self, share): # noqa """Unmanage a share. :param share: either share object or text with its ID. @@ -333,8 +578,7 @@ def get(self, share, return_raw=False): :rtype: :class:`Share` """ share_id = base.getid(share) - return self._get("/shares/%s" % share_id, "share", - return_raw=return_raw) + return self._get(f"/shares/{share_id}", "share", return_raw=return_raw) def update(self, share, **kwargs): """Updates a share. @@ -345,42 +589,102 @@ def update(self, share, **kwargs): if not kwargs: return - body = {'share': kwargs, } + body = { + 'share': kwargs, + } share_id = base.getid(share) - return self._update("/shares/%s" % share_id, body) + return self._update(f"/shares/{share_id}", body) @api_versions.wraps("1.0", "2.34") - def list(self, detailed=True, search_opts=None, - sort_key=None, sort_dir=None, return_raw=False): + def list( + self, + detailed=True, + search_opts=None, + sort_key=None, + sort_dir=None, + return_raw=False, + ): """Get a list of all shares.""" search_opts = search_opts or {} search_opts.pop("export_location", None) search_opts.pop("is_soft_deleted", None) - return self.do_list(detailed=detailed, search_opts=search_opts, - sort_key=sort_key, sort_dir=sort_dir, - return_raw=return_raw) + search_opts.pop("encryption_key_ref", None) + return self.do_list( + detailed=detailed, + search_opts=search_opts, + sort_key=sort_key, + sort_dir=sort_dir, + return_raw=return_raw, + ) - @api_versions.wraps("2.35", "2.68") # noqa - def list(self, detailed=True, search_opts=None, # noqa - sort_key=None, sort_dir=None, return_raw=False): + @api_versions.wraps("2.35", "2.68") # noqa + def list( # noqa + self, + detailed=True, + search_opts=None, + sort_key=None, + sort_dir=None, + return_raw=False, + ): """Get a list of all shares.""" if search_opts is None: search_opts = {} search_opts.pop("is_soft_deleted", None) - return self.do_list(detailed=detailed, search_opts=search_opts, - sort_key=sort_key, sort_dir=sort_dir, - return_raw=return_raw) + search_opts.pop("encryption_key_ref", None) + return self.do_list( + detailed=detailed, + search_opts=search_opts, + sort_key=sort_key, + sort_dir=sort_dir, + return_raw=return_raw, + ) - @api_versions.wraps("2.69") # noqa - def list(self, detailed=True, search_opts=None, # noqa - sort_key=None, sort_dir=None, return_raw=False): + @api_versions.wraps("2.69", "2.89") # noqa + def list( # noqa + self, + detailed=True, + search_opts=None, + sort_key=None, + sort_dir=None, + return_raw=False, + ): """Get a list of all shares.""" - return self.do_list(detailed=detailed, search_opts=search_opts, - sort_key=sort_key, sort_dir=sort_dir, - return_raw=return_raw) + search_opts = search_opts or {} + search_opts.pop("encryption_key_ref", None) + return self.do_list( + detailed=detailed, + search_opts=search_opts, + sort_key=sort_key, + sort_dir=sort_dir, + return_raw=return_raw, + ) + + @api_versions.wraps("2.90") # noqa + def list( # noqa + self, + detailed=True, + search_opts=None, + sort_key=None, + sort_dir=None, + return_raw=False, + ): + """Get a list of all shares.""" + return self.do_list( + detailed=detailed, + search_opts=search_opts, + sort_key=sort_key, + sort_dir=sort_dir, + return_raw=return_raw, + ) - def do_list(self, detailed=True, search_opts=None, - sort_key=None, sort_dir=None, return_raw=False): + def do_list( + self, + detailed=True, + search_opts=None, + sort_key=None, + sort_dir=None, + return_raw=False, + ): """Get a list of all shares. :param detailed: Whether to return detailed share info or not. @@ -400,6 +704,7 @@ def do_list(self, detailed=True, search_opts=None, - (('share_type_id', 'share_type'), text) - (('snapshot_id', 'snapshot'), text) - ('is_soft_deleted', bool) + - ('encryption_key_ref', text) Note, that member context will have restricted set of available search opts. For admin context filtering also available by each share attr from its Model. So, this list is not full for @@ -424,15 +729,21 @@ def do_list(self, detailed=True, search_opts=None, elif sort_key == 'availability_zone': search_opts['sort_key'] = 'availability_zone_id' else: - raise ValueError('sort_key must be one of the following: %s.' - % ', '.join(constants.SHARE_SORT_KEY_VALUES)) + raise ValueError( + 'sort_key must be one of the following: {}.'.format( + ', '.join(constants.SHARE_SORT_KEY_VALUES) + ) + ) if sort_dir is not None: if sort_dir in constants.SORT_DIR_VALUES: search_opts['sort_dir'] = sort_dir else: - raise ValueError('sort_dir must be one of the following: %s.' - % ', '.join(constants.SORT_DIR_VALUES)) + raise ValueError( + 'sort_dir must be one of the following: {}.'.format( + ', '.join(constants.SORT_DIR_VALUES) + ) + ) if 'is_public' not in search_opts: search_opts['is_public'] = True @@ -447,9 +758,9 @@ def do_list(self, detailed=True, search_opts=None, query_string = self._build_query_string(search_opts) if detailed: - path = "/shares/detail%s" % (query_string,) + path = f"/shares/detail{query_string}" else: - path = "/shares%s" % (query_string,) + path = f"/shares{query_string}" return self._list(path, 'shares', return_raw=return_raw) @@ -460,9 +771,9 @@ def delete(self, share, share_group_id=None): :param share_group_id: text - ID of the share group to which the share belongs """ - url = "/shares/%s" % base.getid(share) + url = f"/shares/{base.getid(share)}" if share_group_id: - url += "?share_group_id=%s" % share_group_id + url += f"?share_group_id={share_group_id}" self._delete(url) def _do_force_delete(self, share, action_name): @@ -477,7 +788,7 @@ def force_delete(self, share): return self._do_force_delete(share, "os-force_delete") @api_versions.wraps("2.7") # noqa - def force_delete(self, share): # noqa + def force_delete(self, share): # noqa return self._do_force_delete(share, "force_delete") @api_versions.wraps("2.69") @@ -499,7 +810,7 @@ def restore(self, share): @staticmethod def _validate_common_name(access): if len(access) == 0 or len(access) > 64: - exc_str = ('Invalid CN (common name). Must be 1-64 chars long.') + exc_str = 'Invalid CN (common name). Must be 1-64 chars long.' raise exceptions.CommandError(exc_str) ''' @@ -510,6 +821,7 @@ def _validate_common_name(access): 2:https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/ windows-server-2000/bb726984(v=technet.10) ''' + @staticmethod def _validate_username(access): sole_periods_spaces_re = r'[\s|\.]+$' @@ -517,38 +829,42 @@ def _validate_username(access): username = access if re.match(sole_periods_spaces_re, username): - exc_str = ('Invalid user or group name,cannot consist solely ' - 'of periods or spaces.') + exc_str = ( + 'Invalid user or group name,cannot consist solely ' + 'of periods or spaces.' + ) raise exceptions.CommandError(exc_str) if not re.match(valid_username_re, username): - exc_str = ('Invalid user or group name. Must be 4-255 characters ' - 'and consist of alphanumeric characters and ' - 'exclude special characters "/\\[]:;|=,+*?<>') + exc_str = ( + 'Invalid user or group name. Must be 4-255 characters ' + 'and consist of alphanumeric characters and ' + 'exclude special characters "/\\[]:;|=,+*?<>' + ) raise exceptions.CommandError(exc_str) @staticmethod def _validate_cephx_id(cephx_id): if not cephx_id: - raise exceptions.CommandError( - 'Ceph IDs may not be empty.') + raise exceptions.CommandError('Ceph IDs may not be empty.') # This restriction may be lifted in Ceph in the future: # http://tracker.ceph.com/issues/14626 if not set(cephx_id) <= set(string.printable): raise exceptions.CommandError( - 'Ceph IDs must consist of ASCII printable characters.') + 'Ceph IDs must consist of ASCII printable characters.' + ) # Periods are technically permitted, but we restrict them here # to avoid confusion where users are unsure whether they should # include the "client." prefix: otherwise they could accidentally # create "client.client.foobar". if '.' in cephx_id: - raise exceptions.CommandError( - 'Ceph IDs may not contain periods.') + raise exceptions.CommandError('Ceph IDs may not contain periods.') - def _validate_access(self, access_type, access, valid_access_types=None, - enable_ipv6=False): + def _validate_access( + self, access_type, access, valid_access_types=None, enable_ipv6=False + ): if not valid_access_types: valid_access_types = ('ip', 'user', 'cert') @@ -573,13 +889,23 @@ def _validate_access(self, access_type, access, valid_access_types=None, elif access_type == 'cephx': self._validate_cephx_id(access.strip()) else: - msg = ('Only following access types are supported: %s' % - ', '.join(valid_access_types)) + msg = 'Only following access types are supported: {}'.format( + ', '.join(valid_access_types) + ) raise exceptions.CommandError(msg) - def _do_allow(self, share, access_type, access, access_level, action_name, - metadata=None, lock_visibility=False, - lock_deletion=False, lock_reason=None): + def _do_allow( + self, + share, + access_type, + access, + access_level, + action_name, + metadata=None, + lock_visibility=False, + lock_deletion=False, + lock_reason=None, + ): """Allow access to a share. :param share: either share object or text with its ID. @@ -602,57 +928,83 @@ def _do_allow(self, share, access_type, access, access_level, action_name, access_params['lock_deletion'] = lock_deletion if lock_reason: access_params['lock_reason'] = lock_reason - access = self._action(action_name, share, - access_params)[1]["access"] + access = self._action(action_name, share, access_params)[1]["access"] return access @api_versions.wraps("1.0", "2.6") def allow(self, share, access_type, access, access_level, metadata=None): self._validate_access(access_type, access) return self._do_allow( - share, access_type, access, access_level, "os-allow_access") + share, access_type, access, access_level, "os-allow_access" + ) @api_versions.wraps("2.7", "2.12") # noqa - def allow(self, share, access_type, access, access_level, metadata=None): # noqa + def allow(self, share, access_type, access, access_level, metadata=None): # noqa self._validate_access(access_type, access) return self._do_allow( - share, access_type, access, access_level, "allow_access") + share, access_type, access, access_level, "allow_access" + ) @api_versions.wraps("2.13", "2.37") # noqa - def allow(self, share, access_type, access, access_level, metadata=None): # noqa + def allow(self, share, access_type, access, access_level, metadata=None): # noqa valid_access_types = ('ip', 'user', 'cert', 'cephx') self._validate_access(access_type, access, valid_access_types) return self._do_allow( - share, access_type, access, access_level, "allow_access") + share, access_type, access, access_level, "allow_access" + ) @api_versions.wraps("2.38", "2.44") # noqa - def allow(self, share, access_type, access, access_level, metadata=None): # noqa + def allow(self, share, access_type, access, access_level, metadata=None): # noqa valid_access_types = ('ip', 'user', 'cert', 'cephx') - self._validate_access(access_type, access, valid_access_types, - enable_ipv6=True) + self._validate_access( + access_type, access, valid_access_types, enable_ipv6=True + ) return self._do_allow( - share, access_type, access, access_level, "allow_access") + share, access_type, access, access_level, "allow_access" + ) @api_versions.wraps("2.45", "2.81") # noqa - def allow(self, share, access_type, access, access_level, metadata=None): # noqa + def allow(self, share, access_type, access, access_level, metadata=None): # noqa valid_access_types = ('ip', 'user', 'cert', 'cephx') - self._validate_access(access_type, access, valid_access_types, - enable_ipv6=True) + self._validate_access( + access_type, access, valid_access_types, enable_ipv6=True + ) return self._do_allow( - share, access_type, access, access_level, "allow_access", - metadata=metadata) + share, + access_type, + access, + access_level, + "allow_access", + metadata=metadata, + ) @api_versions.wraps("2.82") # noqa - def allow(self, share, access_type, access, access_level, # pylint: disable=function-redefined # noqa F811 - metadata=None, lock_visibility=False, lock_deletion=False, - lock_reason=None): + def allow( # noqa + self, + share, + access_type, + access, + access_level, # pylint: disable=function-redefined # noqa F811 + metadata=None, + lock_visibility=False, + lock_deletion=False, + lock_reason=None, + ): valid_access_types = ('ip', 'user', 'cert', 'cephx') - self._validate_access(access_type, access, valid_access_types, - enable_ipv6=True) + self._validate_access( + access_type, access, valid_access_types, enable_ipv6=True + ) return self._do_allow( - share, access_type, access, access_level, "allow_access", - metadata=metadata, lock_visibility=lock_visibility, - lock_deletion=lock_deletion, lock_reason=lock_reason) + share, + access_type, + access, + access_level, + "allow_access", + metadata=metadata, + lock_visibility=lock_visibility, + lock_deletion=lock_deletion, + lock_reason=lock_reason, + ) def _do_deny(self, share, access_id, action_name, unrestrict=False): """Deny access to a share. @@ -672,13 +1024,14 @@ def deny(self, share, access_id): return self._do_deny(share, access_id, "os-deny_access") @api_versions.wraps("2.7", "2.81") # noqa - def deny(self, share, access_id): # noqa + def deny(self, share, access_id): # noqa return self._do_deny(share, access_id, "deny_access") @api_versions.wraps("2.82") # noqa def deny(self, share, access_id, unrestrict=False): # noqa - return self._do_deny(share, access_id, "deny_access", - unrestrict=unrestrict) + return self._do_deny( + share, access_id, "deny_access", unrestrict=unrestrict + ) def _do_access_list(self, share, action_name): """Get access list to a share. @@ -697,7 +1050,7 @@ def access_list(self, share): return self._do_access_list(share, "os-access_list") @api_versions.wraps("2.7", "2.44") # noqa - def access_list(self, share): # noqa + def access_list(self, share): # noqa return self._do_access_list(share, "access_list") def _action(self, action, share, info=None, **kwargs): @@ -710,7 +1063,7 @@ def _action(self, action, share, info=None, **kwargs): """ body = {action: info} self.run_hooks('modify_body_for_action', body, **kwargs) - url = '/shares/%s/action' % base.getid(share) + url = f'/shares/{base.getid(share)}/action' return self.api.client.post(url, body=body) def _do_reset_state(self, share, state, action_name): @@ -768,7 +1121,7 @@ def shrink(self, share, new_size): return self._do_shrink(share, new_size, "os-shrink") @api_versions.wraps("2.7") # noqa - def shrink(self, share, new_size): # noqa + def shrink(self, share, new_size): # noqa return self._do_shrink(share, new_size, "shrink") def list_instances(self, share): @@ -777,7 +1130,7 @@ def list_instances(self, share): :param share: either share object or text with its ID. """ return self._list( - '/shares/%s/instances' % base.getid(share), + f'/shares/{base.getid(share)}/instances', 'share_instances', - manager=share_instances.ShareInstanceManager(self) + manager=share_instances.ShareInstanceManager(self), ) diff --git a/manilaclient/v2/shell.py b/manilaclient/v2/shell.py deleted file mode 100644 index b83884c1..00000000 --- a/manilaclient/v2/shell.py +++ /dev/null @@ -1,7082 +0,0 @@ -# Copyright 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -from operator import xor -import os -import re -import sys -import time - -from oslo_utils import strutils - -from manilaclient import api_versions -from manilaclient.common.apiclient import utils as apiclient_utils -from manilaclient.common import cliutils -from manilaclient.common import constants -from manilaclient import exceptions -import manilaclient.v2.shares - - -def _wait_for_resource_status(cs, - resource, - expected_status, - resource_type='share', - status_attr='status', - poll_timeout=900, - poll_interval=2): - """Waiter for resource status changes - - :param cs: command shell control - :param expected_status: a string or a list of strings containing expected - states to wait for - :param resource_type: 'share', 'snapshot', 'share_replica', 'share_group', - or 'share_group_snapshot' - :param status_attr: 'status', 'task_state', 'access_rules_status' or any - other status field that is expected to have the "expected_status" - :param poll_timeout: how long to wait for in seconds - :param poll_interval: how often to try in seconds - """ - find_resource = { - 'share': _find_share, - 'snapshot': _find_share_snapshot, - 'share_replica': _find_share_replica, - 'share_group': _find_share_group, - 'share_group_snapshot': _find_share_group_snapshot, - 'share_instance': _find_share_instance, - 'share_server': _find_share_server, - 'share_access_rule': _find_share_access_rule, - } - - print_resource = { - 'share': _print_share, - 'snapshot': _print_share_snapshot, - 'share_replica': _print_share_replica, - 'share_group': _print_share_group, - 'share_group_snapshot': _print_share_group_snapshot, - 'share_instance': _print_share_instance, - 'share_access_rule': _print_share_access_rule, - } - - expected_status = expected_status or ('available', ) - if not isinstance(expected_status, (list, tuple, set)): - expected_status = (expected_status, ) - - time_elapsed = 0 - timeout_message = ("%(resource_type)s %(resource)s did not reach " - "%(expected_states)s within %(seconds)d seconds.") - error_message = ("%(resource_type)s %(resource)s has reached a failed " - "state.") - deleted_message = ("%(resource_type)s %(resource)s has been successfully " - "deleted.") - unmanaged_message = ("%(resource_type)s %(resource)s has been " - "successfully unmanaged.") - message_payload = { - 'resource_type': resource_type.capitalize(), - 'resource': resource.id, - } - not_found_regex = "no .* exists" - while True: - if time_elapsed > poll_timeout: - print_resource[resource_type](cs, resource) - message_payload.update({'expected_states': expected_status, - 'seconds': poll_timeout}) - raise exceptions.TimeoutException( - message=timeout_message % message_payload) - try: - resource = find_resource[resource_type](cs, resource.id) - except exceptions.CommandError as e: - if (re.search(not_found_regex, str(e), flags=re.IGNORECASE)): - if 'deleted' in expected_status: - print(deleted_message % message_payload) - break - if 'unmanaged' in expected_status: - print(unmanaged_message % message_payload) - break - else: - raise e - - if getattr(resource, status_attr) in expected_status: - break - elif 'error' in getattr(resource, status_attr): - print_resource[resource_type](cs, resource) - raise exceptions.ResourceInErrorState( - message=error_message % message_payload) - time.sleep(poll_interval) - time_elapsed += poll_interval - - return resource - - -def _find_share(cs, share): - """Get a share by ID.""" - return apiclient_utils.find_resource(cs.shares, share) - - -def _find_share_transfer(cs, transfer): - """Get a share transfer by ID.""" - return apiclient_utils.find_resource(cs.transfers, transfer) - - -@api_versions.wraps("1.0", "2.8") -def _print_share(cs, share): - info = share._info.copy() - info.pop('links', None) - - # NOTE(vponomaryov): remove deprecated single field 'export_location' and - # leave only list field 'export_locations'. Also, transform the latter to - # text with new line separators to make it pretty in CLI. - # It will look like following: - # +-------------------+--------------------------------------------+ - # | Property | Value | - # +-------------------+--------------------------------------------+ - # | status | available | - # | export_locations | 1.2.3.4:/f/o/o | - # | | 5.6.7.8:/b/a/r | - # | | 9.10.11.12:/q/u/u/z | - # | id | d778d2ee-b6bb-4c5f-9f5d-6f3057d549b1 | - # | size | 1 | - # | share_proto | NFS | - # +-------------------+--------------------------------------------+ - if info.get('export_locations'): - info.pop('export_location', None) - info['export_locations'] = "\n".join(info['export_locations']) - - # No need to print both volume_type and share_type to CLI - if 'volume_type' in info and 'share_type' in info: - info.pop('volume_type', None) - - cliutils.print_dict(info) - - -@api_versions.wraps("2.9") # noqa -def _print_share(cs, share): # noqa - info = share._info.copy() - info.pop('links', None) - - # NOTE(vponomaryov): remove deprecated single field 'export_location' and - # leave only list field 'export_locations'. Also, transform the latter to - # text with new line separators to make it pretty in CLI. - # It will look like following: - # +-------------------+--------------------------------------------+ - # | Property | Value | - # +-------------------+--------------------------------------------+ - # | status | available | - # | export_locations | | - # | | uuid = FOO-UUID | - # | | path = 5.6.7.8:/foo/export/location/path | - # | | | - # | | uuid = BAR-UUID | - # | | path = 5.6.7.8:/bar/export/location/path | - # | | | - # | id | d778d2ee-b6bb-4c5f-9f5d-6f3057d549b1 | - # | size | 1 | - # | share_proto | NFS | - # +-------------------+--------------------------------------------+ - if info.get('export_locations'): - info['export_locations'] = ( - cliutils.convert_dict_list_to_string( - info['export_locations'], - ignored_keys=['replica_state', - 'availability_zone', - 'share_replica_id']) - ) - - # No need to print both volume_type and share_type to CLI - if 'volume_type' in info and 'share_type' in info: - info.pop('volume_type', None) - - cliutils.print_dict(info) - - -def _wait_for_share_status(cs, share, expected_status='available'): - return _wait_for_resource_status( - cs, share, expected_status, resource_type='share') - - -def _find_share_instance(cs, instance): - """Get a share instance by ID.""" - return apiclient_utils.find_resource(cs.share_instances, instance) - - -def _print_type_show(stype, default_share_type=None): - - if hasattr(stype, 'is_default'): - is_default = 'YES' if stype.is_default else 'NO' - elif default_share_type: - is_default = 'YES' if stype.id == default_share_type.id else 'NO' - else: - is_default = 'NO' - - stype_dict = { - 'id': stype.id, - 'name': stype.name, - 'visibility': _is_share_type_public(stype), - 'is_default': is_default, - 'description': stype.description, - 'required_extra_specs': _print_type_required_extra_specs(stype), - 'optional_extra_specs': _print_type_optional_extra_specs(stype), - } - cliutils.print_dict(stype_dict) - - -@api_versions.wraps("1.0", "2.8") -def _print_share_instance(cs, instance): - info = instance._info.copy() - info.pop('links', None) - cliutils.print_dict(info) - - -@api_versions.wraps("2.9") # noqa -def _print_share_instance(cs, instance): # noqa - info = instance._info.copy() - info.pop('links', None) - if info.get('export_locations'): - info['export_locations'] = ( - cliutils.convert_dict_list_to_string( - info['export_locations'], - ignored_keys=['replica_state', - 'availability_zone', - 'share_replica_id']) - ) - - cliutils.print_dict(info) - - -def _find_share_access_rule(cs, access_rule): - """Get share access rule state""" - return apiclient_utils.find_resource(cs.share_access_rules, access_rule) - - -def _print_share_access_rule(cs, access_rule): - info = access_rule._info.copy() - - cliutils.print_dict(info) - - -def _find_share_replica(cs, replica): - """Get a replica by ID.""" - return apiclient_utils.find_resource(cs.share_replicas, replica) - - -@api_versions.wraps("2.11", "2.46") -def _print_share_replica(cs, replica): - info = replica._info.copy() - info.pop('links', None) - cliutils.print_dict(info) - - -@api_versions.wraps("2.47") # noqa -def _print_share_replica(cs, replica): # noqa - info = replica._info.copy() - info.pop('links', None) - if info.get('export_locations'): - info['export_locations'] = ( - cliutils.convert_dict_list_to_string( - info['export_locations'], - ignored_keys=['replica_state', 'availability_zone', - 'share_replica_id'])) - cliutils.print_dict(info) - - -@api_versions.wraps("2.31") -def _find_share_group(cs, share_group): - """Get a share group ID.""" - return apiclient_utils.find_resource(cs.share_groups, share_group) - - -def _print_share_group(cs, share_group): - info = share_group._info.copy() - info.pop('links', None) - - if info.get('share_types'): - info['share_types'] = "\n".join(info['share_types']) - - cliutils.print_dict(info) - - -@api_versions.wraps("2.31") -def _find_share_group_snapshot(cs, share_group_snapshot): - """Get a share group snapshot by name or ID.""" - return apiclient_utils.find_resource( - cs.share_group_snapshots, share_group_snapshot) - - -def _print_share_group_snapshot(cs, share_group_snapshot): - info = share_group_snapshot._info.copy() - info.pop('links', None) - info.pop('members', None) - cliutils.print_dict(info) - - -def _print_share_group_snapshot_members(cs, share_group_snapshot): - info = share_group_snapshot._info.copy() - cliutils.print_dict(info.get('members', {})) - - -def _wait_for_snapshot_status(cs, snapshot, expected_status='available'): - return _wait_for_resource_status( - cs, snapshot, expected_status, resource_type='snapshot') - - -def _find_share_snapshot(cs, snapshot): - """Get a snapshot by ID.""" - return apiclient_utils.find_resource(cs.share_snapshots, snapshot) - - -def _print_share_snapshot(cs, snapshot): - info = snapshot._info.copy() - info.pop('links', None) - - if info.get('export_locations'): - info['export_locations'] = ( - cliutils.convert_dict_list_to_string( - info['export_locations'])) - - cliutils.print_dict(info) - - -def _quota_set_pretty_show(quotas): - """Convert quotas object to dict and display.""" - - new_quotas = {} - for quota_k, quota_v in sorted(quotas.to_dict().items()): - if isinstance(quota_v, dict): - quota_v = '\n'.join( - ['%s = %s' % (k, v) for k, v in sorted(quota_v.items())]) - new_quotas[quota_k] = quota_v - - cliutils.print_dict(new_quotas) - - -def _find_share_snapshot_instance(cs, snapshot_instance): - """Get a share snapshot instance by ID.""" - return apiclient_utils.find_resource( - cs.share_snapshot_instances, snapshot_instance) - - -def _find_share_network(cs, share_network): - """Get a share network by ID or name.""" - return apiclient_utils.find_resource(cs.share_networks, share_network) - - -def _find_security_service(cs, security_service): - """Get a security service by ID or name.""" - return apiclient_utils.find_resource(cs.security_services, - security_service) - - -def _find_share_server(cs, share_server): - """Get a share server by ID.""" - return apiclient_utils.find_resource(cs.share_servers, share_server) - - -def _find_message(cs, message): - """Get a message by ID.""" - return apiclient_utils.find_resource(cs.messages, message) - - -def _translate_keys(collection, convert): - for item in collection: - keys = item.__dict__ - for from_key, to_key in convert: - if from_key in keys and to_key not in keys: - setattr(item, to_key, item._info[from_key]) - - -def _extract_metadata(args, allow_empty_key=True): - return _extract_key_value_options(args, 'metadata', allow_empty_key) - - -def _extract_extra_specs(args): - return _extract_key_value_options(args, 'extra_specs') - - -def _extract_group_specs(args): - return _extract_key_value_options(args, 'group_specs') - - -def _extract_key_value_options(args, option_name, allow_empty_key=True): - result_dict = {} - duplicate_options = [] - - options = getattr(args, option_name, None) - - if options: - for option in options: - # unset doesn't require a val, so we have the if/else - if '=' in option: - (key, value) = option.split('=', 1) - elif allow_empty_key: - key = option - value = None - else: - # disallow empty key - continue - if key not in result_dict: - result_dict[key] = value - else: - duplicate_options.append(key) - - if len(duplicate_options) > 0: - duplicate_str = ', '.join(duplicate_options) - msg = "Following options were duplicated: %s" % duplicate_str - raise exceptions.CommandError(msg) - return result_dict - - -def _split_columns(columns, title=True): - if title: - list_of_keys = list(map(lambda x: x.strip().title(), - columns.split(","))) - else: - list_of_keys = list(map(lambda x: x.strip().lower(), - columns.split(","))) - return list_of_keys - - -@api_versions.wraps("2.0") -def do_api_version(cs, args): - """Display the API version information.""" - columns = ['ID', 'Status', 'Version', 'Min_version'] - column_labels = ['ID', 'Status', 'Version', 'Minimum Version'] - response = cs.services.server_api_version() - cliutils.print_list(response, columns, field_labels=column_labels) - - -def do_endpoints(cs, args): - """Discover endpoints that get returned from the authenticate services.""" - catalog = cs.keystone_client.service_catalog.catalog - for e in catalog.get('serviceCatalog', catalog.get('catalog')): - cliutils.print_dict(e['endpoints'][0], e['name']) - - -def do_credentials(cs, args): - """Show user credentials returned from auth.""" - catalog = cs.keystone_client.service_catalog.catalog - cliutils.print_dict(catalog['user'], "User Credentials") - if not catalog['version'] == 'v3': - data = catalog['token'] - else: - data = { - 'issued_at': catalog['issued_at'], - 'expires': catalog['expires_at'], - 'id': catalog['auth_token'], - 'audit_ids': catalog['audit_ids'], - 'tenant': catalog['project'], - } - cliutils.print_dict(data, "Token") - - -_quota_resources = [ - 'shares', - 'snapshots', - 'gigabytes', - 'snapshot_gigabytes', - 'share_networks', - 'share_replicas', - 'replica_gigabytes', - 'per_share_gigabytes', - 'share_groups', - 'share_group_snapshots' -] - - -def _quota_class_update(manager, identifier, args): - updates = {} - for resource in _quota_resources: - val = getattr(args, resource, None) - if val is not None: - updates[resource] = val - - if updates: - manager.update(identifier, **updates) - - -@cliutils.arg( - '--tenant-id', '--tenant', - '--project', '--project-id', - action='single_alias', - dest='project_id', - metavar='', - default=None, - help='ID of project to list the quotas for.') -@cliutils.arg( - '--user-id', - metavar='', - default=None, - help="ID of user to list the quotas for. Optional. " - "Mutually exclusive with '--share-type'.") -@cliutils.arg( - '--share-type', - '--share_type', - metavar='', - type=str, - default=None, - action='single_alias', - help="UUID or name of a share type to set the quotas for. Optional. " - "Mutually exclusive with '--user-id'. " - "Available only for microversion >= 2.39") -@cliutils.arg( - '--detail', - action='store_true', - help='Optional flag to indicate whether to show quota in detail. ' - 'Default false, available only for microversion >= 2.25.') -@api_versions.wraps("1.0") -def do_quota_show(cs, args): - """List the quotas for a project, user or share type.""" - project_id = args.project_id or cs.keystone_client.project_id - kwargs = { - "tenant_id": project_id, - "user_id": args.user_id, - "detail": args.detail, - } - if args.share_type is not None: - if cs.api_version < api_versions.APIVersion("2.39"): - raise exceptions.CommandError( - "'share type' quotas are available only starting with " - "'2.39' API microversion.") - kwargs["share_type"] = args.share_type - _quota_set_pretty_show(cs.quotas.get(**kwargs)) - - -@cliutils.arg( - '--tenant-id', '--tenant', - '--project', '--project-id', - action='single_alias', - dest='project_id', - metavar='', - default=None, - help='ID of the project to list the default quotas for.') -def do_quota_defaults(cs, args): - """List the default quotas for a project.""" - project = args.project_id or cs.keystone_client.project_id - _quota_set_pretty_show(cs.quotas.defaults(project)) - - -@cliutils.arg( - 'project_id', - metavar='', - help='UUID of project to set the quotas for.') -@cliutils.arg( - '--user-id', - metavar='', - default=None, - help="ID of a user to set the quotas for. Optional. " - "Mutually exclusive with '--share-type'.") -@cliutils.arg( - '--shares', - metavar='', - type=int, - default=None, - help='New value for the "shares" quota.') -@cliutils.arg( - '--snapshots', - metavar='', - type=int, - default=None, - help='New value for the "snapshots" quota.') -@cliutils.arg( - '--gigabytes', - metavar='', - type=int, - default=None, - help='New value for the "gigabytes" quota.') -@cliutils.arg( - '--snapshot-gigabytes', - '--snapshot_gigabytes', # alias - metavar='', - type=int, - default=None, - action='single_alias', - help='New value for the "snapshot_gigabytes" quota.') -@cliutils.arg( - '--share-networks', - '--share_networks', - metavar='', - type=int, - default=None, - action='single_alias', - help='New value for the "share_networks" quota.') -@cliutils.arg( - '--share-groups', '--share_groups', '--groups', - metavar='', - type=int, - default=None, - action='single_alias', - help='New value for the "share_groups" quota.') -@cliutils.arg( - '--share-group-snapshots', '--share_group_snapshots', - '--group-snapshots', '--group_snapshots', - metavar='', - type=int, - default=None, - action='single_alias', - help='New value for the "share_group_snapshots" quota.') -@cliutils.arg( - '--share-type', - '--share_type', - metavar='', - type=str, - default=None, - action='single_alias', - help="UUID or name of a share type to set the quotas for. Optional. " - "Mutually exclusive with '--user-id'. " - "Available only for microversion >= 2.39") -@cliutils.arg( - '--share-replicas', - '--share_replicas', - '--replicas', - metavar='', - type=int, - default=None, - help='New value for the "share_replicas" quota. Available only for ' - 'microversion >= 2.53') -@cliutils.arg( - '--replica-gigabytes', - '--replica_gigabytes', - metavar='', - type=int, - default=None, - help='New value for the "replica_gigabytes" quota. Available only for ' - 'microversion >= 2.53') -@cliutils.arg( - '--per-share-gigabytes', - '--per_share_gigabytes', - metavar='', - type=int, - default=None, - help='New value for the "per_share_gigabytes" quota. Available only for ' - 'microversion >= 2.62') -@cliutils.arg( - '--force', - dest='force', - action="store_true", - default=None, - help='Whether force update the quota even if the already used ' - 'and reserved exceeds the new quota.') -@api_versions.wraps("1.0") -def do_quota_update(cs, args): - """Update the quotas for a project/user and/or share type (Admin only).""" - kwargs = { - "tenant_id": args.project_id, - "user_id": args.user_id, - "shares": args.shares, - "gigabytes": args.gigabytes, - "snapshots": args.snapshots, - "snapshot_gigabytes": args.snapshot_gigabytes, - "share_networks": args.share_networks, - "force": args.force, - } - if args.share_type is not None: - if cs.api_version < api_versions.APIVersion("2.39"): - raise exceptions.CommandError( - "'share type' quotas are available only starting with " - "'2.39' API microversion.") - kwargs["share_type"] = args.share_type - if args.share_groups is not None or args.share_group_snapshots is not None: - if cs.api_version < api_versions.APIVersion("2.40"): - raise exceptions.CommandError( - "'share group' quotas are available only starting with " - "'2.40' API microversion.") - elif args.share_type is not None: - raise exceptions.CommandError( - "Share type quotas cannot be used to constrain share groups.") - kwargs["share_groups"] = args.share_groups - kwargs["share_group_snapshots"] = args.share_group_snapshots - if args.share_replicas is not None or args.replica_gigabytes is not None: - if cs.api_version < api_versions.APIVersion("2.53"): - raise exceptions.CommandError( - "'share replica' quotas are available only starting with " - "'2.53' API microversion.") - kwargs["share_replicas"] = args.share_replicas - kwargs["replica_gigabytes"] = args.replica_gigabytes - if args.per_share_gigabytes is not None: - if cs.api_version < api_versions.APIVersion("2.62"): - raise exceptions.CommandError( - "'per share gigabytes' quotas are available only starting " - "with '2.62' API microversion.") - kwargs["per_share_gigabytes"] = args.per_share_gigabytes - - cs.quotas.update(**kwargs) - - -@cliutils.arg( - '--tenant-id', '--tenant', - '--project', '--project-id', - action='single_alias', - dest='project_id', - metavar='', - help='ID of the project to delete quota for.') -@cliutils.arg( - '--user-id', - metavar='', - help="ID of user to delete quota for. Optional." - "Mutually exclusive with '--share-type'.") -@cliutils.arg( - '--share-type', - '--share_type', - metavar='', - type=str, - default=None, - action='single_alias', - help="UUID or name of a share type to set the quotas for. Optional. " - "Mutually exclusive with '--user-id'. " - "Available only for microversion >= 2.39") -@api_versions.wraps("1.0") -def do_quota_delete(cs, args): - """Delete quota for a project, or project/user or project/share-type. - - The quota will revert back to default (Admin only). - """ - project_id = args.project_id or cs.keystone_client.project_id - kwargs = { - "tenant_id": project_id, - "user_id": args.user_id, - } - if args.share_type is not None: - if cs.api_version < api_versions.APIVersion("2.39"): - raise exceptions.CommandError( - "'share type' quotas are available only starting with " - "'2.39' API microversion.") - kwargs["share_type"] = args.share_type - - cs.quotas.delete(**kwargs) - - -@cliutils.arg( - 'class_name', - metavar='', - help='Name of quota class to list the quotas for.') -def do_quota_class_show(cs, args): - """List the quotas for a quota class.""" - - _quota_set_pretty_show(cs.quota_classes.get(args.class_name)) - - -@cliutils.arg( - 'class_name', - metavar='', - help='Name of quota class to set the quotas for.') -@cliutils.arg( - '--shares', - metavar='', - type=int, - default=None, - help='New value for the "shares" quota.') -@cliutils.arg( - '--snapshots', - metavar='', - type=int, - default=None, - help='New value for the "snapshots" quota.') -@cliutils.arg( - '--gigabytes', - metavar='', - type=int, - default=None, - help='New value for the "gigabytes" quota.') -@cliutils.arg( - '--snapshot-gigabytes', - '--snapshot_gigabytes', # alias - metavar='', - type=int, - default=None, - action='single_alias', - help='New value for the "snapshot_gigabytes" quota.') -@cliutils.arg( - '--share-networks', - '--share_networks', # alias - metavar='', - type=int, - default=None, - action='single_alias', - help='New value for the "share_networks" quota.') -@cliutils.arg( - '--share-groups', - '--share_groups', # alias - metavar='', - type=int, - default=None, - action='single_alias', - help='New value for the "share_groups" quota. Available only for ' - 'microversion >= 2.40') -@cliutils.arg( - '--share-group-snapshots', - '--share_group_snapshots', - metavar='', - type=int, - default=None, - action='single_alias', - help='New value for the "share_group_snapshots" quota. Available only for ' - 'microversion >= 2.40') -@cliutils.arg( - '--share-replicas', - '--share_replicas', # alias - '--replicas', # alias - metavar='', - type=int, - default=None, - action='single_alias', - help='New value for the "share_replicas" quota. Available only for ' - 'microversion >= 2.53') -@cliutils.arg( - '--replica-gigabytes', - '--replica_gigabytes', # alias - metavar='', - type=int, - default=None, - action='single_alias', - help='New value for the "replica_gigabytes" quota. Available only for ' - 'microversion >= 2.53') -@cliutils.arg( - '--per-share-gigabytes', - '--per_share_gigabytes', # alias - metavar='', - type=int, - default=None, - action='single_alias', - help='New value for the "per_share_gigabytes" quota. Available only for ' - 'microversion >= 2.62') -def do_quota_class_update(cs, args): - """Update the quotas for a quota class (Admin only).""" - if args.share_groups is not None or args.share_group_snapshots is not None: - if cs.api_version < api_versions.APIVersion("2.40"): - raise exceptions.CommandError( - "'share groups' quotas are available only starting with " - "'2.40' API microversion.") - if args.share_replicas is not None or args.replica_gigabytes is not None: - if cs.api_version < api_versions.APIVersion("2.53"): - raise exceptions.CommandError( - "'share replica' quotas are available only starting with " - "'2.53' API microversion.") - if args.per_share_gigabytes is not None: - if cs.api_version < api_versions.APIVersion("2.62"): - raise exceptions.CommandError( - "'per_share_gigabytes' quota is available only starting " - "with '2.62' API microversion.") - - _quota_class_update(cs.quota_classes, args.class_name, args) - - -def do_absolute_limits(cs, args): - """Print a list of absolute limits for a user.""" - limits = cs.limits.get().absolute - columns = ['Name', 'Value'] - cliutils.print_list(limits, columns) - - -@cliutils.arg( - '--columns', - metavar='', - type=str, - default=None, - help='Comma separated list of columns to be displayed ' - 'example --columns "verb,uri,value".') -def do_rate_limits(cs, args): - """Print a list of rate limits for a user.""" - limits = cs.limits.get().rate - columns = ['Verb', 'URI', 'Value', 'Remain', 'Unit', 'Next_Available'] - - if args.columns is not None: - columns = _split_columns(columns=args.columns) - - cliutils.print_list(limits, columns) - - -@cliutils.arg( - 'share_protocol', - metavar='', - type=str, - help='Share protocol (NFS, CIFS, CephFS, GlusterFS, HDFS or MAPRFS).') -@cliutils.arg( - 'size', - metavar='', - type=int, - help='Share size in GiB.') -@cliutils.arg( - '--snapshot-id', - '--snapshot_id', - '--snapshot', - metavar='', - action='single_alias', - help='Optional snapshot ID or name to create the share from.' - ' (Default=None)', - default=None) -@cliutils.arg( - '--name', - metavar='', - help='Optional share name. (Default=None)', - default=None) -@cliutils.arg( - '--metadata', - type=str, - nargs='*', - metavar='', - help='Metadata key=value pairs (Optional, Default=None).', - default=None) -@cliutils.arg( - '--share-network', - '--share_network', - metavar='', - action='single_alias', - help='Optional network info ID or name.', - default=None) -@cliutils.arg( - '--description', - metavar='', - help='Optional share description. (Default=None)', - default=None) -@cliutils.arg( - '--share-type', '--share_type', '--volume-type', '--volume_type', - metavar='', - default=None, - action='single_alias', - help='Optional share type. Use of optional volume type is deprecated. ' - '(Default=None)') -@cliutils.arg( - '--public', - dest='public', - action='store_true', - default=False, - help="Level of visibility for share. Defines whether other projects are " - "able to see it or not. (Default=False)") -@cliutils.arg( - '--availability-zone', '--availability_zone', '--az', - metavar='', - default=None, - action='single_alias', - help='Availability zone in which share should be created.') -@cliutils.arg( - '--share-group', '--share_group', '--group', - metavar='', - action='single_alias', - help='Optional share group name or ID in which to create the share ' - '(Default=None).', - default=None) -@cliutils.arg( - '--wait', - action='store_true', - help='Wait for share creation') -@cliutils.arg( - '--scheduler-hints', '--scheduler_hints', '--sh', - metavar='', - nargs='*', - help='Scheduler hints for the share as key=value pairs, ' - 'possible keys are same_host, different_host, ' - 'value must be share_name or share_id.', - default=None) -@cliutils.service_type('sharev2') -def do_create(cs, args): - """Creates a new share (NFS, CIFS, CephFS, GlusterFS, HDFS or MAPRFS).""" - - share_metadata = None - if args.metadata is not None: - share_metadata = _extract_metadata(args) - - share_group = None - if args.share_group: - share_group = _find_share_group(cs, args.share_group).id - - share_network = None - if args.share_network: - share_network = _find_share_network(cs, args.share_network) - - snapshot = None - if args.snapshot_id: - snapshot = _find_share_snapshot(cs, args.snapshot_id).id - - if args.name: - if args.name.capitalize() == 'None': - raise exceptions.CommandError( - "Share name cannot be with the value 'None'") - - if not args.share_type: - try: - _find_share_type(cs, "default") - except exceptions.CommandError: - msg = ("There is no default share type available. You must pick " - "a valid share type to create a share.") - raise exceptions.CommandError(msg) - - scheduler_hints = {} - if args.scheduler_hints: - scheduler_hints = _extract_key_value_options(args, 'scheduler_hints') - same_host_hint_shares = scheduler_hints.get('same_host') - different_host_hint_shares = scheduler_hints.get('different_host') - if same_host_hint_shares: - same_host_hint_shares = [ - _find_share(cs, sh).id - for sh in same_host_hint_shares.split(',') - ] - scheduler_hints['same_host'] = ','.join(same_host_hint_shares) - if different_host_hint_shares: - different_host_hint_shares = [ - _find_share(cs, sh).id - for sh in different_host_hint_shares.split(',') - ] - scheduler_hints['different_host'] = ','.join( - different_host_hint_shares) - - share = cs.shares.create(args.share_protocol, args.size, snapshot, - args.name, args.description, - metadata=share_metadata, - share_network=share_network, - share_type=args.share_type, - is_public=args.public, - availability_zone=args.availability_zone, - share_group_id=share_group, - scheduler_hints=scheduler_hints) - - if args.wait: - share = _wait_for_share_status(cs, share) - - _print_share(cs, share) - - -@api_versions.wraps("2.29") -@cliutils.arg( - 'share', - metavar='', - help='Name or ID of share to migrate.') -@cliutils.arg( - 'host', - metavar='', - help="Destination host where share will be migrated to. Use the " - "format 'host@backend#pool'.") -@cliutils.arg( - '--force_host_assisted_migration', - '--force-host-assisted-migration', - metavar='', - choices=['True', 'False'], - action='single_alias', - required=False, - default=False, - help="Enforces the use of the host-assisted migration approach, " - "which bypasses driver optimizations. Default=False.") -@cliutils.arg( - '--preserve-metadata', - '--preserve_metadata', - action='single_alias', - metavar='', - choices=['True', 'False'], - required=True, - help="Enforces migration to preserve all file metadata when moving its " - "contents. If set to True, host-assisted migration will not be " - "attempted.") -@cliutils.arg( - '--preserve-snapshots', - '--preserve_snapshots', - action='single_alias', - metavar='', - choices=['True', 'False'], - required=True, - help="Enforces migration of the share snapshots to the destination. If " - "set to True, host-assisted migration will not be attempted.") -@cliutils.arg( - '--writable', - metavar='', - choices=['True', 'False'], - required=True, - help="Enforces migration to keep the share writable while contents are " - "being moved. If set to True, host-assisted migration will not be " - "attempted.") -@cliutils.arg( - '--nondisruptive', - metavar='', - choices=['True', 'False'], - required=True, - help="Enforces migration to be nondisruptive. If set to True, " - "host-assisted migration will not be attempted.") -@cliutils.arg( - '--new_share_network', - '--new-share-network', - metavar='', - action='single_alias', - required=False, - help='Specify the new share network for the share. Do not specify this ' - 'parameter if the migrating share has to be retained within its ' - 'current share network.', - default=None) -@cliutils.arg( - '--new_share_type', - '--new-share-type', - metavar='', - required=False, - action='single_alias', - help='Specify the new share type for the share. Do not specify this ' - 'parameter if the migrating share has to be retained with its ' - 'current share type.', - default=None) -def do_migration_start(cs, args): - """Migrates share to a new host (Admin only, Experimental).""" - share = _find_share(cs, args.share) - new_share_net_id = None - if args.new_share_network: - share_net = _find_share_network(cs, args.new_share_network) - new_share_net_id = share_net.id if share_net else None - new_share_type_id = None - if args.new_share_type: - share_type = _find_share_type(cs, args.new_share_type) - new_share_type_id = share_type.id if share_type else None - share.migration_start(args.host, args.force_host_assisted_migration, - args.preserve_metadata, args.writable, - args.nondisruptive, args.preserve_snapshots, - new_share_net_id, new_share_type_id) - - -@cliutils.arg( - 'share', - metavar='', - help='Name or ID of share to complete migration.') -@api_versions.wraps("2.22") -def do_migration_complete(cs, args): - """Completes migration for a given share (Admin only, Experimental).""" - share = _find_share(cs, args.share) - share.migration_complete() - - -@cliutils.arg( - 'share', - metavar='', - help='Name or ID of share to cancel migration.') -@api_versions.wraps("2.22") -def do_migration_cancel(cs, args): - """Cancels migration of a given share when copying - - (Admin only, Experimental). - """ - share = _find_share(cs, args.share) - share.migration_cancel() - - -@cliutils.arg( - 'share', - metavar='', - help='Name or ID of the share to modify.') -@cliutils.arg( - '--task-state', - '--task_state', - '--state', - metavar='', - default='None', - action='single_alias', - required=False, - help=('Indicate which task state to assign the share. Options include ' - 'migration_starting, migration_in_progress, migration_completing, ' - 'migration_success, migration_error, migration_cancelled, ' - 'migration_driver_in_progress, migration_driver_phase1_done, ' - 'data_copying_starting, data_copying_in_progress, ' - 'data_copying_completing, data_copying_completed, ' - 'data_copying_cancelled, data_copying_error. If no value is ' - 'provided, None will be used.')) -@api_versions.wraps("2.22") -def do_reset_task_state(cs, args): - """Explicitly update the task state of a share - - (Admin only, Experimental). - """ - state = args.task_state - if args.task_state == 'None': - state = None - share = _find_share(cs, args.share) - share.reset_task_state(state) - - -@cliutils.arg( - 'share', - metavar='', - help='Name or ID of the share to get share migration progress ' - 'information.') -@api_versions.wraps("2.22") -def do_migration_get_progress(cs, args): - """Gets migration progress of a given share when copying - - (Admin only, Experimental). - """ - share = _find_share(cs, args.share) - result = share.migration_get_progress() - # NOTE(ganso): result[0] is response code, result[1] is dict body - cliutils.print_dict(result[1]) - - -@cliutils.arg( - 'share_server_id', - metavar='', - help='ID of the share server to check if the migration is possible.') -@cliutils.arg( - 'host', - metavar='', - help="Destination to migrate the share server to. Use the format " - "'@'.") -@cliutils.arg( - '--preserve-snapshots', - '--preserve_snapshots', - action='single_alias', - metavar='', - choices=['True', 'False'], - required=True, - help="Set to True if snapshots must be preserved at the migration " - "destination.") -@cliutils.arg( - '--writable', - metavar='', - choices=['True', 'False'], - required=True, - help="Set to True if shares associated with the share server must be " - "writable through the first phase of the migration.") -@cliutils.arg( - '--nondisruptive', - metavar='', - choices=['True', 'False'], - required=True, - help="Set to True if migration must be non disruptive to clients that are " - "using the shares associated with the share server through both " - "phases of the migration.") -@cliutils.arg( - '--new_share_network', - '--new-share-network', - metavar='', - action='single_alias', - required=False, - help="New share network to migrate to. Optional, default=None.", - default=None) -@api_versions.wraps("2.57") -@api_versions.experimental_api -def do_share_server_migration_check(cs, args): - """Check migration compatibility for a share server with desired properties - - (Admin only, Experimental). - """ - share_server = _find_share_server(cs, args.share_server_id) - - new_share_net_id = None - if args.new_share_network: - share_net = _find_share_network(cs, args.new_share_network) - new_share_net_id = share_net.id - result = share_server.migration_check( - args.host, args.writable, args.nondisruptive, args.preserve_snapshots, - new_share_net_id) - cliutils.print_dict(result) - - -@cliutils.arg( - 'share_server_id', - metavar='', - help='ID of the share server to migrate.') -@cliutils.arg( - 'host', - metavar='', - help="Destination to migrate the share server to. Use the format " - "'@'.") -@cliutils.arg( - '--preserve-snapshots', - '--preserve_snapshots', - action='single_alias', - metavar='', - choices=['True', 'False'], - required=True, - help="Set to True if snapshots must be preserved at the migration " - "destination.") -@cliutils.arg( - '--writable', - metavar='', - choices=['True', 'False'], - required=True, - help="Enforces migration to keep all its shares writable while contents " - "are being moved.") -@cliutils.arg( - '--nondisruptive', - metavar='', - choices=['True', 'False'], - required=True, - help="Enforces migration to be nondisruptive.") -@cliutils.arg( - '--new_share_network', - '--new-share-network', - metavar='', - action='single_alias', - required=False, - help='Specify a new share network for the share server. Do not ' - 'specify this parameter if the migrating share server has ' - 'to be retained within its current share network.', - default=None) -@api_versions.wraps("2.57") -@api_versions.experimental_api -def do_share_server_migration_start(cs, args): - """Migrates share server to a new host (Admin only, Experimental).""" - share_server = _find_share_server(cs, args.share_server_id) - - new_share_net_id = None - if args.new_share_network: - share_net = _find_share_network(cs, args.new_share_network) - new_share_net_id = share_net.id - share_server.migration_start(args.host, args.writable, args.nondisruptive, - args.preserve_snapshots, new_share_net_id) - - -@cliutils.arg( - 'share_server_id', - metavar='', - help='ID of share server to complete migration.') -@api_versions.wraps("2.57") -@api_versions.experimental_api -def do_share_server_migration_complete(cs, args): - """Completes migration for a given share server - - (Admin only, Experimental). - """ - share_server = _find_share_server(cs, args.share_server_id) - result = share_server.migration_complete() - cliutils.print_dict(result) - - -@cliutils.arg( - 'share_server_id', - metavar='', - help='ID of share server to complete migration.') -@api_versions.wraps("2.57") -@api_versions.experimental_api -def do_share_server_migration_cancel(cs, args): - """Cancels migration of a given share server when copying - - (Admin only, Experimental). - """ - share_server = _find_share_server(cs, args.share_server_id) - share_server.migration_cancel() - - -@cliutils.arg( - 'share_server_id', - metavar='', - help='ID of share server to complete migration.') -@cliutils.arg( - '--task-state', - '--task_state', - '--state', - metavar='', - default='None', - action='single_alias', - required=False, - help=('Indicate which task state to assign the share server. Options: ' - 'migration_starting, migration_in_progress, migration_completing, ' - 'migration_success, migration_error, migration_cancel_in_progress, ' - 'migration_cancelled, migration_driver_in_progress, ' - 'migration_driver_phase1_done. If no value is provided, None will ' - 'be used.')) -@api_versions.wraps("2.57") -@api_versions.experimental_api -def do_share_server_reset_task_state(cs, args): - """Explicitly update the task state of a share - - (Admin only, Experimental). - """ - state = args.task_state - if args.task_state == 'None': - state = None - share_server = _find_share_server(cs, args.share_server_id) - share_server.reset_task_state(state) - - -@cliutils.arg( - 'share_server_id', - metavar='', - help='ID of share server to complete migration.') -@api_versions.wraps("2.57") -@api_versions.experimental_api -def do_share_server_migration_get_progress(cs, args): - """Gets migration progress of a given share server when copying - - (Admin only, Experimental). - """ - share_server = _find_share_server(cs, args.share_server_id) - result = share_server.migration_get_progress() - cliutils.print_dict(result) - - -@cliutils.arg( - 'share', - metavar='', - help='Name or ID of the share to update metadata on.') -@cliutils.arg( - 'action', - metavar='', - choices=['set', 'unset'], - help="Actions: 'set' or 'unset'.") -@cliutils.arg( - 'metadata', - metavar='', - nargs='+', - default=[], - help='Metadata to set or unset (only key is necessary to unset).') -def do_metadata(cs, args): - """Set or delete metadata on a share.""" - share = _find_share(cs, args.share) - metadata = _extract_metadata(args) - - if args.action == 'set': - share.set_metadata(metadata) - elif args.action == 'unset': - share.delete_metadata(sorted(list(metadata), reverse=True)) - - -@cliutils.arg( - 'share', - metavar='', - help='Name or ID of the share.') -def do_metadata_show(cs, args): - """Show metadata of given share.""" - share = _find_share(cs, args.share) - metadata = share.get_metadata()._info - cliutils.print_dict(metadata, 'Property') - - -@cliutils.arg( - 'share', - metavar='', - help='Name or ID of the share to update metadata on.') -@cliutils.arg( - 'metadata', - metavar='', - nargs='+', - default=[], - help='Metadata entry or entries to update.') -def do_metadata_update_all(cs, args): - """Update all metadata of a share.""" - share = _find_share(cs, args.share) - metadata = _extract_metadata(args) - metadata = share.update_all_metadata(metadata)._info['metadata'] - cliutils.print_dict(metadata, 'Property') - - -@api_versions.wraps("2.9") -@cliutils.arg( - 'share', - metavar='', - help='Name or ID of the share.') -@cliutils.arg( - '--columns', - metavar='', - type=str, - default=None, - help='Comma separated list of columns to be displayed ' - 'example --columns "id,host,status".') -def do_share_export_location_list(cs, args): - """List export locations of a given share.""" - if args.columns is not None: - list_of_keys = _split_columns(columns=args.columns) - else: - list_of_keys = [ - 'ID', - 'Path', - 'Preferred', - ] - share = _find_share(cs, args.share) - export_locations = cs.share_export_locations.list(share) - cliutils.print_list(export_locations, list_of_keys) - - -@api_versions.wraps("2.9") -@cliutils.arg( - 'share', - metavar='', - help='Name or ID of the share.') -@cliutils.arg( - 'export_location', - metavar='', - help='ID of the share export location.') -def do_share_export_location_show(cs, args): - """Show export location of the share.""" - share = _find_share(cs, args.share) - export_location = cs.share_export_locations.get( - share, args.export_location) - view_data = export_location._info.copy() - cliutils.print_dict(view_data) - - -@cliutils.arg( - 'service_host', - metavar='', - type=str, - help='manage-share service host: some.host@driver#pool.') -@cliutils.arg( - 'protocol', - metavar='', - type=str, - help='Protocol of the share to manage, such as NFS or CIFS.') -@cliutils.arg( - 'export_path', - metavar='', - type=str, - help='Share export path, NFS share such as: 10.0.0.1:/example_path, ' - 'CIFS share such as: \\\\10.0.0.1\\example_cifs_share.') -@cliutils.arg( - '--name', - metavar='', - help='Optional share name. (Default=None)', - default=None) -@cliutils.arg( - '--description', - metavar='', - help='Optional share description. (Default=None)', - default=None) -@cliutils.arg( - '--share_type', '--share-type', - metavar='', - default=None, - action='single_alias', - help='Optional share type assigned to share. (Default=None)') -@cliutils.arg( - '--driver_options', '--driver-options', - type=str, - nargs='*', - metavar='', - action='single_alias', - help='Driver option key=value pairs (Optional, Default=None).', - default=None) -@cliutils.arg( - '--public', - dest='public', - action='store_true', - default=False, - help="Level of visibility for share. Defines whether other projects are " - "able to see it or not. Available only for microversion >= 2.8. " - "(Default=False)") -@cliutils.arg( - '--share_server_id', '--share-server-id', - metavar='', - default=None, - action='single_alias', - help="Share server associated with share when using a share type with " - "'driver_handles_share_servers' extra_spec set to True. Available " - "only for microversion >= 2.49. (Default=None)") -@cliutils.arg( - '--wait', - action='store_true', - help='Wait for share management') -def do_manage(cs, args): - """Manage share not handled by Manila (Admin only).""" - driver_options = _extract_key_value_options(args, 'driver_options') - if cs.api_version.matches(api_versions.APIVersion("2.49"), - api_versions.APIVersion()): - share = cs.shares.manage( - args.service_host, args.protocol, args.export_path, - driver_options=driver_options, share_type=args.share_type, - name=args.name, description=args.description, - is_public=args.public, share_server_id=args.share_server_id) - else: - if args.share_server_id: - raise exceptions.CommandError("Invalid parameter " - "--share_server_id specified. This" - " parameter is only supported on" - " microversion 2.49 or newer.") - share = cs.shares.manage( - args.service_host, args.protocol, args.export_path, - driver_options=driver_options, share_type=args.share_type, - name=args.name, description=args.description, - is_public=args.public) - - if args.wait: - share = _wait_for_resource_status( - cs, share, resource_type='share', - expected_status='available' - ) - _print_share(cs, share) - - -@api_versions.wraps("2.49") -@cliutils.arg( - 'host', - metavar='', - type=str, - help='Backend name as "@".') -@cliutils.arg( - 'share_network', - metavar='', - help="Share network where share server has network allocations in.") -@cliutils.arg( - 'identifier', - metavar='', - type=str, - help='A driver-specific share server identifier required by the driver to ' - 'manage the share server.') -@cliutils.arg( - '--driver_options', '--driver-options', - type=str, - nargs='*', - metavar='', - action='single_alias', - help='One or more driver-specific key=value pairs that may be necessary to' - ' manage the share server (Optional, Default=None).', - default=None) -@cliutils.arg( - '--share-network-subnet', '--share_network_subnet', - type=str, - metavar='', - help="Share network subnet where share server has network allocations in. " - "The default subnet will be used if it's not specified. Available " - "for microversion >= 2.51 (Optional, Default=None).", - default=None) -@cliutils.arg( - '--wait', - action='store_true', - default='False', - help='Wait for share server to manage') -def do_share_server_manage(cs, args): - """Manage share server not handled by Manila (Admin only).""" - driver_options = _extract_key_value_options(args, 'driver_options') - - manage_kwargs = { - 'driver_options': driver_options, - } - if cs.api_version < api_versions.APIVersion("2.51"): - if getattr(args, 'share_network_subnet'): - raise exceptions.CommandError( - "Share network subnet option is only available with manila " - "API version >= 2.51") - else: - manage_kwargs['share_network_subnet_id'] = args.share_network_subnet - - share_server = cs.share_servers.manage( - args.host, args.share_network, args.identifier, - **manage_kwargs) - - if args.wait: - try: - _wait_for_resource_status( - cs, share_server, resource_type='share_server', - expected_status='active') - except exceptions.CommandError as e: - print(e, file=sys.stderr) - - cliutils.print_dict(share_server._info) - - -@cliutils.arg( - 'share_server_id', - metavar='', - help='ID of the share server to modify.') -@cliutils.arg( - '--state', - metavar='', - default=constants.STATUS_ACTIVE, - help=('Indicate which state to assign the share server. Options include ' - 'active, error, creating, deleting, managing, unmanaging, ' - 'manage_error and unmanage_error. If no state is provided, active ' - 'will be used.')) -@api_versions.wraps("2.49") -def do_share_server_reset_state(cs, args): - """Explicitly update the state of a share server (Admin only).""" - cs.share_servers.reset_state(args.share_server_id, args.state) - - -@api_versions.wraps("2.12") -@cliutils.arg( - 'share', - metavar='', - type=str, - help='Name or ID of the share.') -@cliutils.arg( - 'provider_location', - metavar='', - type=str, - help='Provider location of the snapshot on the backend.') -@cliutils.arg( - '--name', - metavar='', - help='Optional snapshot name (Default=None).', - default=None) -@cliutils.arg( - '--description', - metavar='', - help='Optional snapshot description (Default=None).', - default=None) -@cliutils.arg( - '--driver_options', '--driver-options', - type=str, - nargs='*', - metavar='', - action='single_alias', - help='Optional driver options as key=value pairs (Default=None).', - default=None) -@cliutils.arg( - '--wait', - action='store_true', - default=False, - help='Wait for share snapshot to be managed') -def do_snapshot_manage(cs, args): - """Manage share snapshot not handled by Manila (Admin only).""" - share_ref = _find_share(cs, args.share) - driver_options = _extract_key_value_options(args, 'driver_options') - - share_snapshot = cs.share_snapshots.manage( - share_ref, args.provider_location, - driver_options=driver_options, - name=args.name, description=args.description - ) - - if args.wait: - try: - _wait_for_snapshot_status(cs, share_snapshot, - expected_status='available') - except exceptions.CommandError as e: - print(e, file=sys.stderr) - _print_share_snapshot(cs, share_snapshot) - - -@cliutils.arg( - 'share', - metavar='', - help='Name or ID of the share(s).') -@cliutils.arg( - '--wait', - action='store_true', - help='Wait for share unmanagement') -def do_unmanage(cs, args): - """Unmanage share (Admin only).""" - share_ref = _find_share(cs, args.share) - share_ref.unmanage() - if args.wait: - _wait_for_share_status(cs, share_ref, expected_status='unmanaged') - - -@api_versions.wraps("2.49") -@cliutils.arg( - 'share_server', - metavar='', - nargs='+', - help='ID of the share server(s).') -@cliutils.arg( - '--force', - dest='force', - action="store_true", - required=False, - default=False, - help="Enforces the unmanage share server operation, even if the back-end " - "driver does not support it.") -def do_share_server_unmanage(cs, args): - """Unmanage share server (Admin only).""" - failure_count = 0 - for server in args.share_server: - try: - cs.share_servers.unmanage(server, args.force) - except Exception as e: - failure_count += 1 - print("Unmanage for share server %s failed: %s" % (server, e), - file=sys.stderr) - - if failure_count == len(args.share_server): - raise exceptions.CommandError("Unable to unmanage any of the " - "specified share servers.") - - -@api_versions.wraps("2.12") -@cliutils.arg( - 'snapshot', - metavar='', - nargs='+', - help='Name or ID of the snapshot(s).') -@cliutils.arg( - '--wait', - action='store_true', - default=False, - help='Wait for share snapshot to be unmanaged') -def do_snapshot_unmanage(cs, args): - """Unmanage one or more share snapshots (Admin only).""" - failure_count = 0 - for snapshot in args.snapshot: - try: - snapshot_ref = _find_share_snapshot(cs, snapshot) - snapshot_ref.unmanage_snapshot() - if args.wait: - _wait_for_snapshot_status(cs, snapshot_ref, - expected_status='deleted') - except Exception as e: - failure_count += 1 - print("Unmanage for share snapshot %s failed: %s" % (snapshot, e), - file=sys.stderr) - - if failure_count == len(args.snapshot): - raise exceptions.CommandError("Unable to unmanage any of the " - "specified snapshots.") - - -@api_versions.wraps("2.27") -@cliutils.arg( - 'snapshot', - metavar='', - help='Name or ID of the snapshot to restore. The snapshot must be the ' - 'most recent one known to manila.') -@cliutils.arg( - '--wait', - action='store_true', - default=False, - help='Wait for share to be reverted from snapshot.') -def do_revert_to_snapshot(cs, args): - """Revert a share to the specified snapshot.""" - snapshot = _find_share_snapshot(cs, args.snapshot) - share = _find_share(cs, snapshot.share_id) - share.revert_to_snapshot(snapshot) - if args.wait: - _wait_for_share_status(cs, share) - - -@cliutils.arg( - 'share', - metavar='', - nargs='+', - help='Name or ID of the share(s).') -@cliutils.arg( - '--share-group', '--share_group', '--group', - metavar='', - action='single_alias', - help='Optional share group name or ID which contains the share ' - '(Default=None).', - default=None) -@cliutils.arg( - '--wait', - action='store_true', - help='Wait for share deletion') -@cliutils.service_type('sharev2') -def do_delete(cs, args): - """Remove one or more shares.""" - failure_count = 0 - shares_to_delete = [] - for share in args.share: - try: - share_ref = _find_share(cs, share) - shares_to_delete.append(share_ref) - if args.share_group: - share_group_id = _find_share_group(cs, args.share_group).id - cs.shares.delete(share_ref, share_group_id=share_group_id) - else: - cs.shares.delete(share_ref) - except Exception as e: - failure_count += 1 - print("Delete for share %s failed: %s" % (share, e), - file=sys.stderr) - - if failure_count == len(args.share): - raise exceptions.CommandError("Unable to delete any of the specified " - "shares.") - - if args.wait: - for share in shares_to_delete: - try: - _wait_for_share_status(cs, share, expected_status='deleted') - except exceptions.CommandError as e: - print(e, file=sys.stderr) - - -@cliutils.arg( - 'share', - metavar='', - nargs='+', - help='Name or ID of the share(s) to force delete.') -@cliutils.arg( - '--wait', - action='store_true', - help='Wait for share to delete') -@cliutils.service_type('sharev2') -def do_force_delete(cs, args): - """Attempt force-delete of share, regardless of state (Admin only).""" - failure_count = 0 - shares_to_delete = [] - for share in args.share: - try: - share_ref = _find_share(cs, share) - shares_to_delete.append(share_ref) - share_ref.force_delete() - except Exception as e: - failure_count += 1 - print("Delete for share %s failed: %s" % (share, e), - file=sys.stderr) - if failure_count == len(args.share): - raise exceptions.CommandError("Unable to force delete any of " - "specified shares.") - if args.wait: - for share in shares_to_delete: - try: - _wait_for_share_status(cs, share, expected_status='deleted') - except exceptions.CommandError as e: - print(e, file=sys.stderr) - - -@cliutils.arg( - 'share', - metavar='', - nargs='+', - help='Name or ID of the share(s).') -@cliutils.service_type('sharev2') -@api_versions.wraps("2.69") -def do_soft_delete(cs, args): - """Soft delete one or more shares.""" - failure_count = 0 - - for share in args.share: - try: - share_ref = _find_share(cs, share) - cs.shares.soft_delete(share_ref) - except Exception as e: - failure_count += 1 - print("Soft deletion of share %s failed: %s" % (share, e), - file=sys.stderr) - - if failure_count == len(args.share): - raise exceptions.CommandError("Unable to soft delete any of the " - "specified shares.") - - -@cliutils.arg( - 'share', - metavar='', - nargs='+', - help='Name or ID of the share(s).') -@cliutils.service_type('sharev2') -@api_versions.wraps("2.69") -def do_restore(cs, args): - """Restore one or more shares from recycle bin.""" - failure_count = 0 - - for share in args.share: - try: - share_ref = _find_share(cs, share) - cs.shares.restore(share_ref) - except Exception as e: - failure_count += 1 - print("Restoration of share %s failed: %s" % (share, e), - file=sys.stderr) - - if failure_count == len(args.share): - raise exceptions.CommandError("Unable to restore any of the " - "specified shares.") - - -@api_versions.wraps("1.0", "2.8") -@cliutils.arg( - 'share', - metavar='', - help='Name or ID of the NAS share.') -def do_show(cs, args): - """Show details about a NAS share.""" - share = _find_share(cs, args.share) - _print_share(cs, share) - - -@api_versions.wraps("2.9") # noqa -@cliutils.arg( - 'share', - metavar='', - help='Name or ID of the NAS share.') -def do_show(cs, args): # noqa - """Show details about a NAS share.""" - share = _find_share(cs, args.share) - export_locations = cs.share_export_locations.list(share) - share._info['export_locations'] = export_locations - _print_share(cs, share) - - -@cliutils.arg( - 'share', - metavar='', - help='Name or ID of the NAS share to modify.') -@cliutils.arg( - 'access_type', - metavar='', - help='Access rule type (only "ip", "user"(user or group), "cert" or ' - '"cephx" are supported).') -@cliutils.arg( - 'access_to', - metavar='', - help='Value that defines access.') -@cliutils.arg( - '--access-level', - '--access_level', # alias - metavar='', - type=str, - default=None, - choices=['rw', 'ro'], - action='single_alias', - help='Share access level ("rw" and "ro" access levels are supported). ' - 'Defaults to rw.') -@cliutils.arg( - '--metadata', - type=str, - nargs='*', - metavar='', - help='Space Separated list of key=value pairs of metadata items. ' - 'OPTIONAL: Default=None. Available only for microversion >= 2.45.', - default=None) -@cliutils.arg( - '--wait', - action='store_true', - help='Wait for share access to become active') -def do_access_allow(cs, args): - """Allow access to a given share.""" - access_metadata = None - if cs.api_version.matches(api_versions.APIVersion("2.45"), - api_versions.APIVersion()): - access_metadata = _extract_metadata(args) - elif getattr(args, 'metadata'): - raise exceptions.CommandError( - "Adding metadata to access rules is supported only beyond " - "API version 2.45") - - share = _find_share(cs, args.share) - access = share.allow(args.access_type, args.access_to, args.access_level, - access_metadata) - if args.wait: - try: - if not cs.api_version.matches(api_versions.APIVersion("2.45"), - api_versions.APIVersion()): - raise exceptions.CommandError( - "Waiting on the allowing access operation is only " - "available for API versions equal to or greater than 2.45." - ) - access_id = access.get('id') - share_access_rule = cs.share_access_rules.get(access_id) - access = _wait_for_resource_status( - cs, share_access_rule, - resource_type='share_access_rule', - expected_status='active', - status_attr='state')._info - except exceptions.CommandError as e: - print(e, file=sys.stderr) - cliutils.print_dict(access) - - -@api_versions.wraps("2.45") -@cliutils.arg( - 'access_id', - metavar='', - help='ID of the NAS share access rule.') -def do_access_show(cs, args): - """Show details about a NAS share access rule.""" - access = cs.share_access_rules.get(args.access_id) - view_data = access._info.copy() - cliutils.print_dict(view_data) - - -@api_versions.wraps("2.45") -@cliutils.arg( - 'access_id', - metavar='', - help='ID of the NAS share access rule.') -@cliutils.arg( - 'action', - metavar='', - choices=['set', 'unset'], - help="Actions: 'set' or 'unset'.") -@cliutils.arg( - 'metadata', - metavar='', - nargs='+', - default=[], - help='Space separated key=value pairs of metadata items to set. ' - 'To unset only keys are required. ') -def do_access_metadata(cs, args): - """Set or delete metadata on a share access rule.""" - share_access = cs.share_access_rules.get(args.access_id) - metadata = _extract_metadata(args) - - if args.action == 'set': - cs.share_access_rules.set_metadata(share_access, metadata) - elif args.action == 'unset': - cs.share_access_rules.unset_metadata( - share_access, sorted(list(metadata), reverse=True)) - - -@api_versions.wraps("2.32") -@cliutils.arg( - 'snapshot', - metavar='', - help='Name or ID of the share snapshot to allow access to.') -@cliutils.arg( - 'access_type', - metavar='', - help='Access rule type (only "ip", "user"(user or group), "cert" or ' - '"cephx" are supported).') -@cliutils.arg( - 'access_to', - metavar='', - help='Value that defines access.') -def do_snapshot_access_allow(cs, args): - """Allow read only access to a snapshot.""" - share_snapshot = _find_share_snapshot(cs, args.snapshot) - access = share_snapshot.allow(args.access_type, args.access_to) - cliutils.print_dict(access) - - -@cliutils.arg( - 'share', - metavar='', - help='Name or ID of the NAS share to modify.') -@cliutils.arg( - 'id', - metavar='', - help='ID of the access rule to be deleted.') -def do_access_deny(cs, args): - """Deny access to a share.""" - share = _find_share(cs, args.share) - share.deny(args.id) - - -@api_versions.wraps("2.32") -@cliutils.arg( - 'snapshot', - metavar='', - help='Name or ID of the share snapshot to deny access to.') -@cliutils.arg( - 'id', - metavar='', - nargs='+', - help='ID(s) of the access rule(s) to be deleted.') -def do_snapshot_access_deny(cs, args): - """Deny access to a snapshot.""" - failure_count = 0 - snapshot = _find_share_snapshot(cs, args.snapshot) - for access_id in args.id: - try: - snapshot.deny(access_id) - except Exception as e: - failure_count += 1 - print("Failed to remove rule %(access)s: %(reason)s." - % {'access': access_id, 'reason': e}, - file=sys.stderr) - - if failure_count == len(args.id): - raise exceptions.CommandError("Unable to delete any of the specified " - "snapshot rules.") - - -@api_versions.wraps("1.0", "2.20") -@cliutils.arg( - 'share', - metavar='', - help='Name or ID of the share.') -@cliutils.arg( - '--columns', - metavar='', - type=str, - default=None, - help='Comma separated list of columns to be displayed ' - 'example --columns "access_type,access_to".') -def do_access_list(cs, args): - """Show access list for share.""" - list_of_keys = [ - 'id', 'access_type', 'access_to', 'access_level', 'state', - ] - - if args.columns is not None: - list_of_keys = _split_columns(columns=args.columns) - - share = _find_share(cs, args.share) - access_list = share.access_list() - cliutils.print_list(access_list, list_of_keys) - - -@api_versions.wraps("2.21") # noqa -@cliutils.arg( - 'share', - metavar='', - help='Name or ID of the share.') -@cliutils.arg( - '--columns', - metavar='', - type=str, - default=None, - help='Comma separated list of columns to be displayed ' - 'example --columns "access_type,access_to".') -def do_access_list(cs, args): # noqa - """Show access list for share.""" - list_of_keys = [ - 'id', 'access_type', 'access_to', 'access_level', 'state', - 'access_key' - ] - - if args.columns is not None: - list_of_keys = _split_columns(columns=args.columns) - - share = _find_share(cs, args.share) - access_list = share.access_list() - cliutils.print_list(access_list, list_of_keys) - - -@api_versions.wraps("2.33") # noqa -@cliutils.arg( - 'share', - metavar='', - help='Name or ID of the share.') -@cliutils.arg( - '--columns', - metavar='', - type=str, - default=None, - help='Comma separated list of columns to be displayed ' - 'example --columns "access_type,access_to".') -@cliutils.arg( - '--metadata', - type=str, - nargs='*', - metavar='', - help='Filters results by a metadata key and value. OPTIONAL: ' - 'Default=None. Available only for microversion >= 2.45', - default=None) -def do_access_list(cs, args): # noqa - """Show access list for share.""" - list_of_keys = [ - 'id', 'access_type', 'access_to', 'access_level', 'state', - 'access_key', 'created_at', 'updated_at', - ] - - share = _find_share(cs, args.share) - if cs.api_version < api_versions.APIVersion("2.45"): - if getattr(args, 'metadata'): - raise exceptions.CommandError( - "Filtering access rules by metadata is supported only beyond " - "API version 2.45") - access_list = share.access_list() - else: - access_list = cs.share_access_rules.access_list( - share, {'metadata': _extract_metadata(args)}) - if args.columns is not None: - list_of_keys = _split_columns(columns=args.columns) - cliutils.print_list(access_list, list_of_keys) - - -@api_versions.wraps("2.32") -@cliutils.arg( - 'snapshot', - metavar='', - help='Name or ID of the share snapshot to list access of.') -@cliutils.arg( - '--columns', - metavar='', - type=str, - default=None, - help='Comma separated list of columns to be displayed ' - 'example --columns "access_type,access_to".') -def do_snapshot_access_list(cs, args): - """Show access list for a snapshot.""" - if args.columns is not None: - list_of_keys = _split_columns(columns=args.columns) - else: - list_of_keys = ['id', 'access_type', 'access_to', 'state'] - - snapshot = _find_share_snapshot(cs, args.snapshot) - access_list = snapshot.access_list() - cliutils.print_list(access_list, list_of_keys) - - -@cliutils.arg( - '--all-tenants', '--all-projects', - action='single_alias', - dest='all_projects', - metavar='<0|1>', - nargs='?', - type=int, - const=1, - default=0, - help='Display information from all projects (Admin only).') -@cliutils.arg( - '--name', - metavar='', - type=str, - default=None, - help='Filter results by name.') -@cliutils.arg( - '--description', - metavar='', - type=str, - default=None, - help='Filter results by description. ' - 'Available only for microversion >= 2.36.') -@cliutils.arg( - '--name~', - metavar='', - type=str, - default=None, - help='Filter results matching a share name pattern. ' - 'Available only for microversion >= 2.36.') -@cliutils.arg( - '--description~', - metavar='', - type=str, - default=None, - help='Filter results matching a share description pattern. ' - 'Available only for microversion >= 2.36.') -@cliutils.arg( - '--status', - metavar='', - type=str, - default=None, - help='Filter results by status.') -@cliutils.arg( - '--share-server-id', - '--share-server_id', '--share_server-id', '--share_server_id', # aliases - metavar='', - type=str, - default=None, - action='single_alias', - help='Filter results by share server ID (Admin only).') -@cliutils.arg( - '--metadata', - type=str, - nargs='*', - metavar='', - help='Filters results by a metadata key and value. OPTIONAL: ' - 'Default=None.', - default=None) -@cliutils.arg( - '--extra-specs', - '--extra_specs', # alias - type=str, - nargs='*', - metavar='', - action='single_alias', - help='Filters results by a extra specs key and value of share type that ' - 'was used for share creation. OPTIONAL: Default=None.', - default=None) -@cliutils.arg( - '--share-type', '--volume-type', - '--share_type', '--share-type-id', '--volume-type-id', # aliases - '--share-type_id', '--share_type-id', '--share_type_id', # aliases - '--volume_type', '--volume_type_id', - metavar='', - type=str, - default=None, - action='single_alias', - help='Filter results by a share type id or name that was used for share ' - 'creation.') -@cliutils.arg( - '--limit', - metavar='', - type=int, - default=None, - help='Maximum number of shares to return. OPTIONAL: Default=None.') -@cliutils.arg( - '--offset', - metavar='', - type=int, - default=None, - help='Set offset to define start point of share listing. ' - 'OPTIONAL: Default=None.') -@cliutils.arg( - '--sort-key', - '--sort_key', # alias - metavar='', - type=str, - default=None, - action='single_alias', - help='Key to be sorted, available keys are %(keys)s. ' - 'OPTIONAL: Default=None.' % {'keys': constants.SHARE_SORT_KEY_VALUES}) -@cliutils.arg( - '--sort-dir', - '--sort_dir', # alias - metavar='', - type=str, - default=None, - action='single_alias', - help='Sort direction, available values are %(values)s. ' - 'OPTIONAL: Default=None.' % {'values': constants.SORT_DIR_VALUES}) -@cliutils.arg( - '--snapshot', - metavar='', - type=str, - default=None, - help='Filer results by snapshot name or id, that was used for share.') -@cliutils.arg( - '--host', - metavar='', - default=None, - help='Filter results by host.') -@cliutils.arg( - '--share-network', - '--share_network', # alias - metavar='', - type=str, - default=None, - action='single_alias', - help='Filter results by share-network name or id.') -@cliutils.arg( - '--project-id', - '--project_id', # alias - metavar='', - type=str, - default=None, - action='single_alias', - help="Filter results by project id. Useful with set key '--all-projects'.") -@cliutils.arg( - '--public', - dest='public', - action='store_true', - default=False, - help="Add public shares from all projects to result. (Default=False)") -@cliutils.arg( - '--share-group', '--share_group', '--group', - metavar='', - type=str, - default=None, - action='single_alias', - help='Filter results by share group name or ID (Default=None).') -@cliutils.arg( - '--columns', - metavar='', - type=str, - default=None, - help='Comma separated list of columns to be displayed ' - 'example --columns "export_location,is public".') -@cliutils.arg( - '--export-location', '--export_location', - metavar='', - type=str, - default=None, - action='single_alias', - help='ID or path of the share export location. ' - 'Available only for microversion >= 2.35.') -@cliutils.arg( - '--count', - dest='count', - metavar='', - choices=['True', 'False'], - default=False, - help='Display total number of shares to return. ' - 'Available only for microversion >= 2.42.') -@cliutils.arg( - '--soft-deleted', '--soft_deleted', - action='store_true', - help='Get shares in recycle bin. If this parameter is set to ' - 'True(Default=False), will only show shares in recycle bin. ' - 'Available only for microversion >= 2.69.') -@cliutils.service_type('sharev2') -def do_list(cs, args): - """List NAS shares with filters.""" - - columns = args.columns - all_projects = int( - os.environ.get("ALL_TENANTS", - os.environ.get("ALL_PROJECTS", - args.all_projects)) - ) - if columns is not None: - list_of_keys = _split_columns(columns=columns) - else: - list_of_keys = [ - 'ID', 'Name', 'Size', 'Share Proto', 'Status', 'Is Public', - 'Share Type Name', 'Host', 'Availability Zone' - ] - if all_projects or args.public: - list_of_keys.append('Project ID') - - empty_obj = type('Empty', (object,), {'id': None}) - share_type = (_find_share_type(cs, args.share_type) - if args.share_type else empty_obj) - - snapshot = (_find_share_snapshot(cs, args.snapshot) - if args.snapshot else empty_obj) - - share_network = (_find_share_network(cs, args.share_network) - if args.share_network else empty_obj) - - share_group = None - if args.share_group: - share_group = _find_share_group(cs, args.share_group) - - search_opts = { - 'offset': args.offset, - 'limit': args.limit, - 'all_tenants': all_projects, - 'name': args.name, - 'status': args.status, - 'host': args.host, - 'share_network_id': share_network.id, - 'snapshot_id': snapshot.id, - 'share_type_id': share_type.id, - 'metadata': _extract_metadata(args, allow_empty_key=False), - 'extra_specs': _extract_extra_specs(args), - 'share_server_id': args.share_server_id, - 'project_id': args.project_id, - 'is_public': args.public, - } - if cs.api_version.matches(api_versions.APIVersion("2.36"), - api_versions.APIVersion()): - search_opts['name~'] = getattr(args, 'name~') - search_opts['description~'] = getattr(args, 'description~') - search_opts['description'] = getattr(args, 'description') - elif (getattr(args, 'name~') or getattr(args, 'description~') or - getattr(args, 'description')): - raise exceptions.CommandError( - "Pattern based filtering (name~, description~ and description)" - " is only available with manila API version >= 2.36") - - if cs.api_version.matches(api_versions.APIVersion("2.35"), - api_versions.APIVersion()): - search_opts['export_location'] = args.export_location - elif args.export_location: - raise exceptions.CommandError( - "Filtering by export location is only " - "available with manila API version >= 2.35") - - if (args.count and - cs.api_version.matches( - api_versions.APIVersion(), api_versions.APIVersion("2.41"))): - raise exceptions.CommandError( - "Display total number of shares is only " - "available with manila API version >= 2.42") - - if cs.api_version.matches(api_versions.APIVersion("2.69"), - api_versions.APIVersion()): - if args.soft_deleted: - search_opts['is_soft_deleted'] = args.soft_deleted - elif args.soft_deleted: - raise exceptions.CommandError( - "Filtering by is_soft_deleted is only " - "available with manila API version >= 2.69") - - if share_group: - search_opts['share_group_id'] = share_group.id - - total_count = 0 - if strutils.bool_from_string(args.count, strict=True): - search_opts['with_count'] = args.count - shares, total_count = cs.shares.list( - search_opts=search_opts, sort_key=args.sort_key, - sort_dir=args.sort_dir - ) - else: - shares = cs.shares.list( - search_opts=search_opts, sort_key=args.sort_key, - sort_dir=args.sort_dir - ) - # When shell input is "--metadata None", filter metadata={} - if shares and args.metadata: - if "None" in args.metadata: - shares = [share for share in shares if share.metadata == {}] - # NOTE(vponomaryov): usage of 'export_location' and - # 'export_locations' columns may cause scaling issue using API 2.9+ and - # when lots of shares are returned. - if (shares and columns is not None and 'export_location' in columns and - not hasattr(shares[0], 'export_location')): - # NOTE(vponomaryov): we will get here only using API 2.9+ - for share in shares: - els_objs = cs.share_export_locations.list(share) - els = [el.to_dict()['path'] for el in els_objs] - setattr(share, 'export_locations', els) - setattr(share, 'export_location', els[0] if els else None) - cliutils.print_list(shares, list_of_keys, sortby_index=None) - if args.count: - print("Shares in total: %s" % total_count) - - with cs.shares.completion_cache('uuid', - manilaclient.v2.shares.Share, - mode="w"): - for share in shares: - cs.shares.write_to_completion_cache('uuid', share.id) - - with cs.shares.completion_cache('name', - manilaclient.v2.shares.Share, - mode="w"): - for share in shares: - if share.name is not None: - cs.shares.write_to_completion_cache('name', share.name) - - -@cliutils.arg( - '--share-id', - '--share_id', # alias - metavar='', - default=None, - action='single_alias', - help='Filter results by share ID.') -@cliutils.arg( - '--columns', - metavar='', - type=str, - default=None, - help='Comma separated list of columns to be displayed ' - 'example --columns "id,host,status".') -@cliutils.arg( - '--export-location', '--export_location', - metavar='', - type=str, - default=None, - action='single_alias', - help='ID or path of the share instance export location. ' - 'Available only for microversion >= 2.35.') -@api_versions.wraps("2.3") -def do_share_instance_list(cs, args): - """List share instances (Admin only).""" - share = _find_share(cs, args.share_id) if args.share_id else None - - list_of_keys = [ - 'ID', 'Share ID', 'Host', 'Status', 'Availability Zone', - 'Share Network ID', 'Share Server ID', 'Share Type ID', - ] - - if args.columns is not None: - list_of_keys = _split_columns(columns=args.columns) - - if share: - instances = cs.shares.list_instances(share) - else: - if cs.api_version.matches( - api_versions.APIVersion("2.35"), api_versions.APIVersion()): - instances = cs.share_instances.list(args.export_location) - else: - if args.export_location: - raise exceptions.CommandError( - "Filtering by export location is only " - "available with manila API version >= 2.35") - instances = cs.share_instances.list() - - cliutils.print_list(instances, list_of_keys) - - -@api_versions.wraps("2.3", "2.8") -@cliutils.arg( - 'instance', - metavar='', - help='Name or ID of the share instance.') -def do_share_instance_show(cs, args): - """Show details about a share instance.""" - instance = _find_share_instance(cs, args.instance) - _print_share_instance(cs, instance) - - -@api_versions.wraps("2.9") # noqa -@cliutils.arg( - 'instance', - metavar='', - help='Name or ID of the share instance.') -def do_share_instance_show(cs, args): # noqa - """Show details about a share instance (Admin only).""" - instance = _find_share_instance(cs, args.instance) - export_locations = cs.share_instance_export_locations.list(instance) - instance._info['export_locations'] = export_locations - _print_share_instance(cs, instance) - - -@cliutils.arg( - 'instance', - metavar='', - nargs='+', - help='Name or ID of the instance(s) to force delete.') -@api_versions.wraps("2.3") -@cliutils.arg( - '--wait', - action='store_true', - help='Wait for share instance deletion') -@cliutils.service_type('sharev2') -def do_share_instance_force_delete(cs, args): - """Force-delete the share instance, regardless of state (Admin only).""" - failure_count = 0 - instances_to_delete = [] - for instance in args.instance: - try: - instance_ref = _find_share_instance(cs, instance) - instances_to_delete.append(instance_ref) - instance_ref.force_delete() - except Exception as e: - failure_count += 1 - print("Delete for share instance %s failed: %s" % (instance, e), - file=sys.stderr) - if failure_count == len(args.instance): - raise exceptions.CommandError("Unable to force delete any of " - "specified share instances.") - if args.wait: - for instance in instances_to_delete: - try: - _wait_for_resource_status( - cs, instance, resource_type='share_instance', - expected_status='deleted') - except exceptions.CommandError as e: - print(e, file=sys.stderr) - - -@cliutils.arg( - 'instance', - metavar='', - help='Name or ID of the share instance to modify.') -@cliutils.arg( - '--state', - metavar='', - default='available', - help=('Indicate which state to assign the instance. Options include ' - 'available, error, creating, deleting, error_deleting, migrating,' - 'migrating_to. If no state is provided, available will be used.')) -@api_versions.wraps("2.3") -def do_share_instance_reset_state(cs, args): - """Explicitly update the state of a share instance (Admin only).""" - instance = _find_share_instance(cs, args.instance) - instance.reset_state(args.state) - - -@api_versions.wraps("2.9") -@cliutils.arg( - 'instance', - metavar='', - help='Name or ID of the share instance.') -@cliutils.arg( - '--columns', - metavar='', - type=str, - default=None, - help='Comma separated list of columns to be displayed ' - 'example --columns "id,host,status".') -def do_share_instance_export_location_list(cs, args): - """List export locations of a given share instance.""" - if args.columns is not None: - list_of_keys = _split_columns(columns=args.columns) - else: - list_of_keys = [ - 'ID', - 'Path', - 'Is Admin only', - 'Preferred', - ] - instance = _find_share_instance(cs, args.instance) - export_locations = cs.share_instance_export_locations.list(instance) - cliutils.print_list(export_locations, list_of_keys) - - -@api_versions.wraps("2.9") -@cliutils.arg( - 'instance', - metavar='', - help='Name or ID of the share instance.') -@cliutils.arg( - 'export_location', - metavar='', - help='ID of the share instance export location.') -def do_share_instance_export_location_show(cs, args): - """Show export location for the share instance.""" - instance = _find_share_instance(cs, args.instance) - export_location = cs.share_instance_export_locations.get( - instance, args.export_location) - view_data = export_location._info.copy() - cliutils.print_dict(view_data) - - -@cliutils.arg( - '--all-tenants', '--all-projects', - action='single_alias', - dest='all_projects', - metavar='<0|1>', - nargs='?', - type=int, - const=1, - default=0, - help='Display information from all projects (Admin only).') -@cliutils.arg( - '--name', - metavar='', - type=str, - default=None, - help='Filter results by name.') -@cliutils.arg( - '--description', - metavar='', - type=str, - default=None, - help='Filter results by description. ' - 'Available only for microversion >= 2.36.') -@cliutils.arg( - '--status', - metavar='', - default=None, - help='Filter results by status.') -@cliutils.arg( - '--share-id', - '--share_id', # alias - metavar='', - default=None, - action='single_alias', - help='Filter results by source share ID.') -@cliutils.arg( - '--usage', - dest='usage', - metavar='any|used|unused', - nargs='?', - type=str, - const='any', - default=None, - choices=['any', 'used', 'unused', ], - help='Either filter or not snapshots by its usage. OPTIONAL: Default=any.') -@cliutils.arg( - '--limit', - metavar='', - type=int, - default=None, - help='Maximum number of share snapshots to return. ' - 'OPTIONAL: Default=None.') -@cliutils.arg( - '--offset', - metavar='', - type=int, - default=None, - help='Set offset to define start point of share snapshots listing. ' - 'OPTIONAL: Default=None.') -@cliutils.arg( - '--sort-key', - '--sort_key', # alias - metavar='', - type=str, - default=None, - action='single_alias', - help='Key to be sorted, available keys are %(keys)s. ' - 'Default=None.' % {'keys': constants.SNAPSHOT_SORT_KEY_VALUES}) -@cliutils.arg( - '--sort-dir', - '--sort_dir', # alias - metavar='', - type=str, - default=None, - action='single_alias', - help='Sort direction, available values are %(values)s. ' - 'OPTIONAL: Default=None.' % {'values': constants.SORT_DIR_VALUES}) -@cliutils.arg( - '--columns', - metavar='', - type=str, - default=None, - help='Comma separated list of columns to be displayed ' - 'example --columns "id,name".') -@cliutils.arg( - '--name~', - metavar='', - type=str, - default=None, - help='Filter results matching a share snapshot name pattern. ' - 'Available only for microversion >= 2.36.') -@cliutils.arg( - '--description~', - metavar='', - type=str, - default=None, - help='Filter results matching a share snapshot description pattern. ' - 'Available only for microversion >= 2.36.') -@cliutils.arg( - '--metadata', - metavar='', - type=str, - default=None, - nargs='*', - help='Filters results by a metadata key and value. OPTIONAL: ' - 'Default=None, Available only for microversion >= 2.73. ') -@cliutils.arg( - '--count', - dest='count', - metavar='', - choices=['True', 'False'], - default=False, - help='Display total number of share snapshots to return. ' - 'Available only for microversion >= 2.79.') -def do_snapshot_list(cs, args): - """List all the snapshots.""" - all_projects = int( - os.environ.get("ALL_TENANTS", - os.environ.get("ALL_PROJECTS", - args.all_projects)) - ) - if args.columns is not None: - list_of_keys = _split_columns(columns=args.columns) - else: - list_of_keys = [ - 'ID', 'Share ID', 'Status', 'Name', 'Share Size', - ] - if all_projects: - list_of_keys.append('Project ID') - - empty_obj = type('Empty', (object,), {'id': None}) - share = _find_share(cs, args.share_id) if args.share_id else empty_obj - search_opts = { - 'offset': args.offset, - 'limit': args.limit, - 'all_tenants': all_projects, - 'name': args.name, - 'status': args.status, - 'share_id': share.id, - 'usage': args.usage, - 'metadata': _extract_metadata(args), - } - if cs.api_version.matches(api_versions.APIVersion("2.36"), - api_versions.APIVersion()): - search_opts['name~'] = getattr(args, 'name~') - search_opts['description~'] = getattr(args, 'description~') - search_opts['description'] = getattr(args, 'description') - elif (getattr(args, 'name~') or getattr(args, 'description~') or - getattr(args, 'description')): - raise exceptions.CommandError( - "Pattern based filtering (name~, description~ and description)" - " is only available with manila API version >= 2.36") - - if (args.count and - cs.api_version.matches( - api_versions.APIVersion(), api_versions.APIVersion("2.78"))): - raise exceptions.CommandError( - "Display total number of share snapshots is only " - "available with manila API version >= 2.79") - - total_count = 0 - if strutils.bool_from_string(args.count, strict=True): - search_opts['with_count'] = args.count - snapshots, total_count = cs.share_snapshots.list( - search_opts=search_opts, - sort_key=args.sort_key, - sort_dir=args.sort_dir) - else: - snapshots = cs.share_snapshots.list( - search_opts=search_opts, - sort_key=args.sort_key, - sort_dir=args.sort_dir) - - cliutils.print_list(snapshots, list_of_keys, sortby_index=None) - if args.count: - print("Share snapshots in total: %s" % total_count) - - -@cliutils.arg( - 'snapshot', - metavar='', - help='Name or ID of the snapshot.') -def do_snapshot_show(cs, args): - """Show details about a snapshot.""" - snapshot = _find_share_snapshot(cs, args.snapshot) - export_locations = cs.share_snapshot_export_locations.list( - snapshot=snapshot) - snapshot._info['export_locations'] = export_locations - _print_share_snapshot(cs, snapshot) - - -@api_versions.wraps("2.32") -@cliutils.arg( - 'snapshot', - metavar='', - help='Name or ID of the snapshot.') -@cliutils.arg( - '--columns', - metavar='', - type=str, - default=None, - help='Comma separated list of columns to be displayed ' - 'example --columns "id,path".') -def do_snapshot_export_location_list(cs, args): - """List export locations of a given snapshot.""" - if args.columns is not None: - list_of_keys = _split_columns(columns=args.columns) - else: - list_of_keys = [ - 'ID', - 'Path', - ] - snapshot = _find_share_snapshot(cs, args.snapshot) - export_locations = cs.share_snapshot_export_locations.list( - snapshot) - cliutils.print_list(export_locations, list_of_keys) - - -@api_versions.wraps("2.32") -@cliutils.arg( - 'instance', - metavar='', - help='Name or ID of the snapshot instance.') -@cliutils.arg( - '--columns', - metavar='', - type=str, - default=None, - help='Comma separated list of columns to be displayed ' - 'example --columns "id,path,is_admin_only".') -def do_snapshot_instance_export_location_list(cs, args): - """List export locations of a given snapshot instance.""" - if args.columns is not None: - list_of_keys = _split_columns(columns=args.columns) - else: - list_of_keys = [ - 'ID', - 'Path', - 'Is Admin only', - ] - instance = _find_share_snapshot_instance(cs, args.instance) - export_locations = cs.share_snapshot_instance_export_locations.list( - instance) - cliutils.print_list(export_locations, list_of_keys) - - -@api_versions.wraps("2.32") -@cliutils.arg( - 'snapshot', - metavar='', - help='Name or ID of the snapshot.') -@cliutils.arg( - 'export_location', - metavar='', - help='ID of the share snapshot export location.') -def do_snapshot_export_location_show(cs, args): - """Show export location of the share snapshot.""" - snapshot = _find_share_snapshot(cs, args.snapshot) - export_location = cs.share_snapshot_export_locations.get( - args.export_location, snapshot) - view_data = export_location._info.copy() - cliutils.print_dict(view_data) - - -@api_versions.wraps("2.32") -@cliutils.arg( - 'snapshot_instance', - metavar='', - help='ID of the share snapshot instance.') -@cliutils.arg( - 'export_location', - metavar='', - help='ID of the share snapshot instance export location.') -def do_snapshot_instance_export_location_show(cs, args): - """Show export location of the share instance snapshot.""" - snapshot_instance = _find_share_snapshot_instance(cs, - args.snapshot_instance) - export_location = cs.share_snapshot_instance_export_locations.get( - args.export_location, snapshot_instance) - - view_data = export_location._info.copy() - cliutils.print_dict(view_data) - - -@cliutils.arg( - 'share', - metavar='', - help='Name or ID of the share to snapshot.') -@cliutils.arg( - '--force', - metavar='', - help='Optional flag to indicate whether ' - 'to snapshot a share even if it\'s busy. ' - '(Default=False)', - default=False) -@cliutils.arg( - '--name', - metavar='', - default=None, - help='Optional snapshot name. (Default=None)') -@cliutils.arg( - '--description', - metavar='', - default=None, - help='Optional snapshot description. (Default=None)') -@cliutils.arg( - '--wait', - action='store_true', - default=False, - help='Wait for snapshot to be created.') -def do_snapshot_create(cs, args): - """Add a new snapshot.""" - share = _find_share(cs, args.share) - snapshot = cs.share_snapshots.create(share, - args.force, - args.name, - args.description) - if args.wait: - try: - _wait_for_snapshot_status(cs, snapshot, - expected_status='available') - except exceptions.CommandError as e: - print(e, file=sys.stderr) - _print_share_snapshot(cs, snapshot) - - -@cliutils.arg( - 'share', - metavar='', - help='Name or ID of the share to rename.') -@cliutils.arg( - '--name', - metavar='', - default=None, - help='New name for the share.') -@cliutils.arg( - '--description', - metavar='', - help='Optional share description. (Default=None)', - default=None) -@cliutils.arg( - '--is-public', - '--is_public', # alias - metavar='', - default=None, - type=str, - action="single_alias", - help='Public share is visible for all projects.') -def do_update(cs, args): - """Rename a share.""" - kwargs = {} - - if args.name is not None: - kwargs['display_name'] = args.name - if args.description is not None: - kwargs['display_description'] = args.description - if args.is_public is not None: - kwargs['is_public'] = strutils.bool_from_string(args.is_public, - strict=True) - if not kwargs: - msg = "Must supply name, description or is_public value." - raise exceptions.CommandError(msg) - _find_share(cs, args.share).update(**kwargs) - - -@cliutils.arg( - 'snapshot', - metavar='', - help='Name or ID of the snapshot to rename.') -@cliutils.arg( - 'name', - nargs='?', - metavar='', - help='New name for the snapshot.') -@cliutils.arg( - '--description', - metavar='', - help='Optional snapshot description. (Default=None)', - default=None) -def do_snapshot_rename(cs, args): - """Rename a snapshot.""" - kwargs = {} - - if args.name is not None: - kwargs['display_name'] = args.name - if args.description is not None: - kwargs['display_description'] = args.description - if not kwargs: - msg = "Must supply either name or description." - raise exceptions.CommandError(msg) - _find_share_snapshot(cs, args.snapshot).update(**kwargs) - - -@cliutils.arg( - 'snapshot', - metavar='', - nargs='+', - help='Name or ID of the snapshot(s) to delete.') -@cliutils.arg( - '--wait', - action='store_true', - default=False, - help='Wait for snapshot to be deleted') -def do_snapshot_delete(cs, args): - """Remove one or more snapshots.""" - failure_count = 0 - - for snapshot in args.snapshot: - try: - snapshot_ref = _find_share_snapshot( - cs, snapshot) - cs.share_snapshots.delete(snapshot_ref) - if args.wait: - _wait_for_snapshot_status(cs, snapshot, - expected_status='deleted') - except Exception as e: - failure_count += 1 - print("Delete for snapshot %s failed: %s" % ( - snapshot, e), file=sys.stderr) - - if failure_count == len(args.snapshot): - raise exceptions.CommandError("Unable to delete any of the specified " - "snapshots.") - - -@cliutils.arg( - 'snapshot', - metavar='', - nargs='+', - help='Name or ID of the snapshot(s) to force delete.') -@cliutils.arg( - '--wait', - action='store_true', - help='Wait for snapshot to delete') -@cliutils.service_type('sharev2') -def do_snapshot_force_delete(cs, args): - """Attempt force-deletion of one or more snapshots. - - Regardless of the state (Admin only). - """ - failure_count = 0 - snapshots_to_delete = [] - - for snapshot in args.snapshot: - try: - snapshot_ref = _find_share_snapshot( - cs, snapshot) - snapshots_to_delete.append(snapshot_ref) - snapshot_ref.force_delete() - except Exception as e: - failure_count += 1 - print("Delete for snapshot %s failed: %s" % ( - snapshot, e), file=sys.stderr) - - if failure_count == len(args.snapshot): - raise exceptions.CommandError("Unable to force delete any of the " - "specified snapshots.") - if args.wait: - for snapshot in snapshots_to_delete: - try: - _wait_for_resource_status( - cs, snapshot, resource_type='snapshot', - expected_status='deleted') - except exceptions.CommandError as e: - print(e, file=sys.stderr) - - -@cliutils.arg( - 'snapshot', - metavar='', - help='Name or ID of the snapshot to modify.') -@cliutils.arg( - '--state', - metavar='', - default='available', - help=('Indicate which state to assign the snapshot. ' - 'Options include available, error, creating, deleting, ' - 'error_deleting. If no state is provided, ' - 'available will be used.')) -def do_snapshot_reset_state(cs, args): - """Explicitly update the state of a snapshot (Admin only).""" - snapshot = _find_share_snapshot(cs, args.snapshot) - snapshot.reset_state(args.state) - - -@api_versions.wraps("2.19") -@cliutils.arg( - '--snapshot', - metavar='', - default=None, - help='Filter results by share snapshot ID.') -@cliutils.arg( - '--columns', - metavar='', - type=str, - default=None, - help='Comma separated list of columns to be displayed ' - 'example --columns "id".') -@cliutils.arg( - '--detailed', - metavar='', - default=False, - help='Show detailed information about snapshot instances.' - ' (Default=False)') -def do_snapshot_instance_list(cs, args): - """List share snapshot instances.""" - snapshot = (_find_share_snapshot(cs, args.snapshot) - if args.snapshot else None) - if args.columns is not None: - list_of_keys = _split_columns(columns=args.columns) - elif args.detailed: - list_of_keys = ['ID', 'Snapshot ID', 'Status', 'Created_at', - 'Updated_at', 'Share_id', 'Share_instance_id', - 'Progress', 'Provider_location'] - else: - list_of_keys = ['ID', 'Snapshot ID', 'Status'] - - instances = cs.share_snapshot_instances.list( - detailed=args.detailed, snapshot=snapshot) - - cliutils.print_list(instances, list_of_keys) - - -@api_versions.wraps("2.19") -@cliutils.arg( - 'snapshot_instance', - metavar='', - help='ID of the share snapshot instance.') -def do_snapshot_instance_show(cs, args): - """Show details about a share snapshot instance.""" - snapshot_instance = _find_share_snapshot_instance( - cs, args.snapshot_instance) - export_locations = ( - cs.share_snapshot_instance_export_locations.list(snapshot_instance)) - snapshot_instance._info['export_locations'] = export_locations - _print_share_snapshot(cs, snapshot_instance) - - -@cliutils.arg( - 'snapshot_instance', - metavar='', - help='ID of the snapshot instance to modify.') -@cliutils.arg( - '--state', - metavar='', - default='available', - help=('Indicate which state to assign the snapshot instance. ' - 'Options include available, error, creating, deleting, ' - 'error_deleting. If no state is provided, available ' - 'will be used.')) -@api_versions.wraps("2.19") -def do_snapshot_instance_reset_state(cs, args): - """Explicitly update the state of a share snapshot instance.""" - snapshot_instance = _find_share_snapshot_instance( - cs, args.snapshot_instance) - snapshot_instance.reset_state(args.state) - - -@cliutils.arg( - 'share', - metavar='', - help='Name or ID of the share to modify.') -@cliutils.arg( - '--state', - metavar='', - default='available', - help=('Indicate which state to assign the share. Options include ' - 'available, error, creating, deleting, error_deleting. If no ' - 'state is provided, available will be used.')) -def do_reset_state(cs, args): - """Explicitly update the state of a share (Admin only).""" - share = _find_share(cs, args.share) - share.reset_state(args.state) - - -@api_versions.wraps("1.0", "2.25") -@cliutils.arg( - '--neutron-net-id', - '--neutron-net_id', '--neutron_net_id', '--neutron_net-id', - metavar='', - default=None, - action='single_alias', - help="Neutron network ID. Used to set up network for share servers.") -@cliutils.arg( - '--neutron-subnet-id', - '--neutron-subnet_id', '--neutron_subnet_id', '--neutron_subnet-id', - metavar='', - default=None, - action='single_alias', - help="Neutron subnet ID. Used to set up network for share servers. " - "This subnet should belong to specified neutron network.") -@cliutils.arg( - '--name', - metavar='', - default=None, - help="Share network name.") -@cliutils.arg( - '--description', - metavar='', - default=None, - help="Share network description.") -def do_share_network_create(cs, args): - """Create a share network to export shares to.""" - values = { - 'neutron_net_id': args.neutron_net_id, - 'neutron_subnet_id': args.neutron_subnet_id, - 'name': args.name, - 'description': args.description, - } - share_network = cs.share_networks.create(**values) - info = share_network._info.copy() - cliutils.print_dict(info) - - -@api_versions.wraps("2.26") # noqa -@cliutils.arg( - '--neutron-net-id', - '--neutron-net_id', '--neutron_net_id', '--neutron_net-id', - metavar='', - default=None, - action='single_alias', - help="Neutron network ID. Used to set up network for share servers.") -@cliutils.arg( - '--neutron-subnet-id', - '--neutron-subnet_id', '--neutron_subnet_id', '--neutron_subnet-id', - metavar='', - default=None, - action='single_alias', - help="Neutron subnet ID. Used to set up network for share servers. " - "This subnet should belong to specified neutron network.") -@cliutils.arg( - '--name', - metavar='', - default=None, - help="Share network name.") -@cliutils.arg( - '--description', - metavar='', - default=None, - help="Share network description.") -@cliutils.arg( - '--availability-zone', '--availability_zone', '--az', - metavar='', - default=None, - action='single_alias', - help="Availability zone in which the subnet should be created. Share " - "networks can have one or more subnets in different availability " - "zones when the driver is operating with " - "'driver_handles_share_servers' extra_spec set to True. Available " - "only for microversion >= 2.51. (Default=None)") -def do_share_network_create(cs, args): # noqa - """Create a share network to export shares to.""" - values = { - 'neutron_net_id': args.neutron_net_id, - 'neutron_subnet_id': args.neutron_subnet_id, - 'name': args.name, - 'description': args.description, - } - if cs.api_version >= api_versions.APIVersion("2.51"): - values['availability_zone'] = args.availability_zone - elif args.availability_zone: - raise exceptions.CommandError( - "Creating share networks with a given az is only " - "available with manila API version >= 2.51") - share_network = cs.share_networks.create(**values) - info = share_network._info.copy() - cliutils.print_dict(info) - - -@api_versions.wraps("1.0", "2.25") -@cliutils.arg( - 'share_network', - metavar='', - help='Name or ID of share network to update.') -@cliutils.arg( - '--neutron-net-id', - '--neutron-net_id', '--neutron_net_id', '--neutron_net-id', - metavar='', - default=None, - action='single_alias', - help="Neutron network ID. Used to set up network for share servers.") -@cliutils.arg( - '--neutron-subnet-id', - '--neutron-subnet_id', '--neutron_subnet_id', '--neutron_subnet-id', - metavar='', - default=None, - action='single_alias', - help="Neutron subnet ID. Used to set up network for share servers. " - "This subnet should belong to specified neutron network.") -@cliutils.arg( - '--name', - metavar='', - default=None, - help="Share network name.") -@cliutils.arg( - '--description', - metavar='', - default=None, - help="Share network description.") -def do_share_network_update(cs, args): - """Update share network data.""" - values = { - 'neutron_net_id': args.neutron_net_id, - 'neutron_subnet_id': args.neutron_subnet_id, - 'name': args.name, - 'description': args.description, - } - share_network = _find_share_network( - cs, args.share_network).update(**values) - info = share_network._info.copy() - cliutils.print_dict(info) - - -@api_versions.wraps("2.26") # noqa -@cliutils.arg( - 'share_network', - metavar='', - help='Name or ID of share network to update.') -@cliutils.arg( - '--neutron-net-id', - '--neutron-net_id', '--neutron_net_id', '--neutron_net-id', - metavar='', - default=None, - action='single_alias', - help="Neutron network ID. Used to set up network for share servers. " - "This option is deprecated for microversion >= 2.51.") -@cliutils.arg( - '--neutron-subnet-id', - '--neutron-subnet_id', '--neutron_subnet_id', '--neutron_subnet-id', - metavar='', - default=None, - action='single_alias', - help="Neutron subnet ID. Used to set up network for share servers. " - "This subnet should belong to specified neutron network. " - "This option is deprecated for microversion >= 2.51.") -@cliutils.arg( - '--name', - metavar='', - default=None, - help="Share network name.") -@cliutils.arg( - '--description', - metavar='', - default=None, - help="Share network description.") -def do_share_network_update(cs, args): # noqa - """Update share network data.""" - - values = { - 'neutron_net_id': args.neutron_net_id, - 'neutron_subnet_id': args.neutron_subnet_id, - 'name': args.name, - 'description': args.description, - } - share_network = _find_share_network( - cs, args.share_network).update(**values) - info = share_network._info.copy() - cliutils.print_dict(info) - - -@cliutils.arg( - 'share_network', - metavar='', - help='Name or ID of the share network to show.') -def do_share_network_show(cs, args): - """Retrieve details for a share network.""" - share_network = _find_share_network(cs, args.share_network) - info = share_network._info.copy() - cliutils.print_dict(info) - - -@api_versions.wraps("1.0", "2.25") -@cliutils.arg( - '--all-tenants', '--all-projects', - action='single_alias', - dest='all_projects', - metavar='<0|1>', - nargs='?', - type=int, - const=1, - default=0, - help='Display information from all projects (Admin only).') -@cliutils.arg( - '--project-id', - '--project_id', # alias - metavar='', - action='single_alias', - default=None, - help='Filter results by project ID.') -@cliutils.arg( - '--name', - metavar='', - default=None, - help='Filter results by name.') -@cliutils.arg( - '--created-since', - '--created_since', # alias - metavar='', - action='single_alias', - default=None, - help='''Return only share networks created since given date. ''' - '''The date is in the format 'yyyy-mm-dd'.''') -@cliutils.arg( - '--created-before', - '--created_before', # alias - metavar='', - action='single_alias', - default=None, - help='''Return only share networks created until given date. ''' - '''The date is in the format 'yyyy-mm-dd'.''') -@cliutils.arg( - '--security-service', - '--security_service', # alias - metavar='', - action='single_alias', - default=None, - help='Filter results by attached security service.') -@cliutils.arg( - '--neutron-net-id', - '--neutron_net_id', '--neutron_net-id', '--neutron-net_id', # aliases - metavar='', - action='single_alias', - default=None, - help='Filter results by neutron net ID.') -@cliutils.arg( - '--neutron-subnet-id', - '--neutron_subnet_id', '--neutron-subnet_id', # aliases - '--neutron_subnet-id', # alias - metavar='', - action='single_alias', - default=None, - help='Filter results by neutron subnet ID.') -@cliutils.arg( - '--network-type', - '--network_type', # alias - metavar='', - action='single_alias', - default=None, - help='Filter results by network type.') -@cliutils.arg( - '--segmentation-id', - '--segmentation_id', # alias - metavar='', - type=int, - action='single_alias', - default=None, - help='Filter results by segmentation ID.') -@cliutils.arg( - '--cidr', - metavar='', - default=None, - help='Filter results by CIDR.') -@cliutils.arg( - '--ip-version', - '--ip_version', # alias - metavar='', - type=int, - action='single_alias', - default=None, - help='Filter results by IP version.') -@cliutils.arg( - '--offset', - metavar='', - type=int, - default=None, - help='Start position of share networks listing.') -@cliutils.arg( - '--limit', - metavar='', - type=int, - default=None, - help='Number of share networks to return per request.') -@cliutils.arg( - '--columns', - metavar='', - type=str, - default=None, - help='Comma separated list of columns to be displayed ' - 'example --columns "id".') -def do_share_network_list(cs, args): - """Get a list of network info.""" - all_projects = int( - os.environ.get("ALL_TENANTS", - os.environ.get("ALL_PROJECTS", - args.all_projects)) - ) - search_opts = { - 'all_tenants': all_projects, - 'project_id': args.project_id, - 'name': args.name, - 'created_since': args.created_since, - 'created_before': args.created_before, - 'neutron_net_id': args.neutron_net_id, - 'neutron_subnet_id': args.neutron_subnet_id, - 'network_type': args.network_type, - 'segmentation_id': args.segmentation_id, - 'cidr': args.cidr, - 'ip_version': args.ip_version, - 'offset': args.offset, - 'limit': args.limit, - } - if args.security_service: - search_opts['security_service_id'] = _find_security_service( - cs, args.security_service).id - share_networks = cs.share_networks.list(search_opts=search_opts) - fields = ['id', 'name'] - - if args.columns is not None: - fields = _split_columns(columns=args.columns) - - cliutils.print_list(share_networks, fields=fields) - - -@api_versions.wraps("2.26") # noqa -@cliutils.arg( - '--all-tenants', '--all-projects', - action='single_alias', - dest='all_projects', - metavar='<0|1>', - nargs='?', - type=int, - const=1, - default=0, - help='Display information from all projects (Admin only).') -@cliutils.arg( - '--project-id', - '--project_id', # alias - metavar='', - action='single_alias', - default=None, - help='Filter results by project ID.') -@cliutils.arg( - '--name', - metavar='', - type=str, - default=None, - help='Filter results by name.') -@cliutils.arg( - '--description', - metavar='', - type=str, - default=None, - help='Filter results by description. ' - 'Available only for microversion >= 2.36.') -@cliutils.arg( - '--created-since', - '--created_since', # alias - metavar='', - action='single_alias', - default=None, - help='''Return only share networks created since given date. ''' - '''The date is in the format 'yyyy-mm-dd'.''') -@cliutils.arg( - '--created-before', - '--created_before', # alias - metavar='', - action='single_alias', - default=None, - help='''Return only share networks created until given date. ''' - '''The date is in the format 'yyyy-mm-dd'.''') -@cliutils.arg( - '--security-service', - '--security_service', # alias - metavar='', - action='single_alias', - default=None, - help='Filter results by attached security service.') -@cliutils.arg( - '--neutron-net-id', - '--neutron_net_id', '--neutron_net-id', '--neutron-net_id', # aliases - metavar='', - action='single_alias', - default=None, - help='Filter results by neutron net ID.') -@cliutils.arg( - '--neutron-subnet-id', - '--neutron_subnet_id', '--neutron-subnet_id', # aliases - '--neutron_subnet-id', # alias - metavar='', - action='single_alias', - default=None, - help='Filter results by neutron subnet ID.') -@cliutils.arg( - '--network-type', - '--network_type', # alias - metavar='', - action='single_alias', - default=None, - help='Filter results by network type.') -@cliutils.arg( - '--segmentation-id', - '--segmentation_id', # alias - metavar='', - type=int, - action='single_alias', - default=None, - help='Filter results by segmentation ID.') -@cliutils.arg( - '--cidr', - metavar='', - default=None, - help='Filter results by CIDR.') -@cliutils.arg( - '--ip-version', - '--ip_version', # alias - metavar='', - type=int, - action='single_alias', - default=None, - help='Filter results by IP version.') -@cliutils.arg( - '--offset', - metavar='', - type=int, - default=None, - help='Start position of share networks listing.') -@cliutils.arg( - '--limit', - metavar='', - type=int, - default=None, - help='Number of share networks to return per request.') -@cliutils.arg( - '--columns', - metavar='', - type=str, - default=None, - help='Comma separated list of columns to be displayed ' - 'example --columns "id".') -@cliutils.arg( - '--name~', - metavar='', - type=str, - default=None, - help='Filter results matching a share network name pattern. ' - 'Available only for microversion >= 2.36.') -@cliutils.arg( - '--description~', - metavar='', - type=str, - default=None, - help='Filter results matching a share network description pattern. ' - 'Available only for microversion >= 2.36.') -def do_share_network_list(cs, args): # noqa - """Get a list of share networks""" - all_projects = int( - os.environ.get("ALL_TENANTS", - os.environ.get("ALL_PROJECTS", - args.all_projects)) - ) - search_opts = { - 'all_tenants': all_projects, - 'project_id': args.project_id, - 'name': args.name, - 'created_since': args.created_since, - 'created_before': args.created_before, - 'neutron_net_id': args.neutron_net_id, - 'neutron_subnet_id': args.neutron_subnet_id, - 'network_type': args.network_type, - 'segmentation_id': args.segmentation_id, - 'cidr': args.cidr, - 'ip_version': args.ip_version, - 'offset': args.offset, - 'limit': args.limit, - } - if cs.api_version.matches(api_versions.APIVersion("2.36"), - api_versions.APIVersion()): - search_opts['name~'] = getattr(args, 'name~') - search_opts['description~'] = getattr(args, 'description~') - search_opts['description'] = getattr(args, 'description') - elif (getattr(args, 'name~') or getattr(args, 'description~') or - getattr(args, 'description')): - raise exceptions.CommandError( - "Pattern based filtering (name~, description~ and description)" - " is only available with manila API version >= 2.36") - - if args.security_service: - search_opts['security_service_id'] = _find_security_service( - cs, args.security_service).id - share_networks = cs.share_networks.list(search_opts=search_opts) - fields = ['id', 'name'] - - if args.columns is not None: - fields = _split_columns(columns=args.columns) - - cliutils.print_list(share_networks, fields=fields) - - -@cliutils.arg( - 'share_network', - metavar='', - help='Share network name or ID.') -@cliutils.arg( - 'security_service', - metavar='', - help='Security service name or ID to associate with.') -def do_share_network_security_service_add(cs, args): - """Associate security service with share network.""" - share_network = _find_share_network(cs, args.share_network) - security_service = _find_security_service(cs, args.security_service) - cs.share_networks.add_security_service(share_network, security_service) - - -@cliutils.arg( - 'share_network', - metavar='', - help='Share network name or ID.') -@cliutils.arg( - 'security_service', - metavar='', - help='Security service name or ID to associate with.') -@cliutils.arg( - '--reset', - metavar='', - choices=['True', 'False'], - required=False, - default=False, - help='Reset and restart the check operation.' - '(Optional, Default=False)') -@api_versions.wraps("2.63") -def do_share_network_security_service_add_check(cs, args): - """Associate security service with share network.""" - share_network = _find_share_network(cs, args.share_network) - security_service = _find_security_service(cs, args.security_service) - add_sec_service_result = cs.share_networks.add_security_service_check( - share_network, security_service, reset_operation=args.reset) - # result[0] is response code, result[1] is dict body - cliutils.print_dict(add_sec_service_result[1]) - - -@cliutils.arg( - 'share_network', - metavar='', - help='Share network name or ID.') -@cliutils.arg( - 'security_service', - metavar='', - help='Security service name or ID to dissociate.') -def do_share_network_security_service_remove(cs, args): - """Dissociate security service from share network.""" - share_network = _find_share_network(cs, args.share_network) - security_service = _find_security_service(cs, args.security_service) - cs.share_networks.remove_security_service(share_network, security_service) - - -@cliutils.arg( - 'share_network', - metavar='', - help='Share network name or ID.') -@cliutils.arg( - '--columns', - metavar='', - type=str, - default=None, - help='Comma separated list of columns to be displayed ' - 'example --columns "id,name".') -def do_share_network_security_service_list(cs, args): - """Get list of security services associated with a given share network.""" - share_network = _find_share_network(cs, args.share_network) - search_opts = { - 'share_network_id': share_network.id, - } - security_services = cs.security_services.list(search_opts=search_opts) - fields = ['id', 'name', 'status', 'type', ] - - if args.columns is not None: - fields = _split_columns(columns=args.columns) - - cliutils.print_list(security_services, fields=fields) - - -@cliutils.arg( - 'share_network', - metavar='', - help='Share network name or ID.') -@cliutils.arg( - 'current_security_service', - metavar='', - help='Current security service name or ID.') -@cliutils.arg( - 'new_security_service', - metavar='', - help='New security service name or ID.') -@api_versions.wraps("2.63") -def do_share_network_security_service_update(cs, args): - """Update a current security service to a new security service.""" - share_network = _find_share_network(cs, args.share_network) - current_security_service = _find_security_service( - cs, args.current_security_service) - new_security_service = _find_security_service( - cs, args.new_security_service) - cs.share_networks.update_share_network_security_service( - share_network, current_security_service, new_security_service) - - -@cliutils.arg( - 'share_network', - metavar='', - help='Share network name or ID.') -@cliutils.arg( - 'current_security_service', - metavar='', - help='Current security service name or ID.') -@cliutils.arg( - 'new_security_service', - metavar='', - help='New security service name or ID.') -@cliutils.arg( - '--reset', - metavar='', - choices=['True', 'False'], - required=False, - default=False, - help='Reset and start again the check operation.' - '(Optional, Default=False)') -@api_versions.wraps("2.63") -def do_share_network_security_service_update_check(cs, args): - """Check if a security service update on the share network is supported. - - This call can be repeated until a successful result is obtained. - """ - share_network = _find_share_network(cs, args.share_network) - current_security_service = _find_security_service( - cs, args.current_security_service) - new_security_service = _find_security_service( - cs, args.new_security_service) - share_network_update_check = ( - cs.share_networks.update_share_network_security_service_check( - share_network, current_security_service, new_security_service, - reset_operation=args.reset)) - # result[0] is response code, result[1] is dict body - cliutils.print_dict(share_network_update_check[1]) - - -@cliutils.arg( - 'share_network', - metavar='', - help='Share network name or ID.') -@cliutils.arg( - '--state', - metavar='', - default=constants.STATUS_ACTIVE, - help=('Indicate which state to assign the share network. Options include ' - 'active, error, network change. If no state is provided, active ' - 'will be used.')) -@api_versions.wraps("2.63") -def do_share_network_reset_state(cs, args): - """Explicitly update the state of a share network (Admin only).""" - share_network = _find_share_network(cs, args.share_network) - cs.share_networks.reset_state(share_network, args.state) - - -@cliutils.arg( - 'share_network', - metavar='', - help='Share network name or ID.') -@cliutils.arg( - '--neutron-net-id', - '--neutron-net_id', '--neutron_net_id', '--neutron_net-id', - metavar='', - default=None, - action='single_alias', - help="Neutron network ID. Used to set up network for share servers. " - "Optional, Default = None.") -@cliutils.arg( - '--neutron-subnet-id', - '--neutron-subnet_id', '--neutron_subnet_id', '--neutron_subnet-id', - metavar='', - default=None, - action='single_alias', - help="Neutron subnet ID. Used to set up network for share servers. " - "This subnet should belong to specified neutron network. " - "Optional, Default = None.") -@cliutils.arg( - '--availability-zone', - '--availability_zone', - '--az', - default=None, - action='single_alias', - metavar='', - help='Optional availability zone that the subnet is available within ' - '(Default=None). If None, the subnet will be considered as being ' - 'available across all availability zones.') -def do_share_network_subnet_create(cs, args): - """Add a new subnet into a share network.""" - if xor(bool(args.neutron_net_id), bool(args.neutron_subnet_id)): - raise exceptions.CommandError( - "Both neutron_net_id and neutron_subnet_id should be specified. " - "Alternatively, neither of them should be specified.") - - share_network = _find_share_network(cs, args.share_network) - values = { - 'share_network_id': share_network.id, - 'neutron_net_id': args.neutron_net_id, - 'neutron_subnet_id': args.neutron_subnet_id, - 'availability_zone': args.availability_zone, - } - share_network_subnet = cs.share_network_subnets.create(**values) - info = share_network_subnet._info.copy() - cliutils.print_dict(info) - - -@cliutils.arg( - 'share_network', - metavar='', - help='Share network name or ID.') -@cliutils.arg( - '--neutron-net-id', - '--neutron-net_id', '--neutron_net_id', '--neutron_net-id', - metavar='', - default=None, - action='single_alias', - help="Neutron network ID. Used to set up network for share servers. " - "Optional, Default = None.") -@cliutils.arg( - '--neutron-subnet-id', - '--neutron-subnet_id', '--neutron_subnet_id', '--neutron_subnet-id', - metavar='', - default=None, - action='single_alias', - help="Neutron subnet ID. Used to set up network for share servers. " - "This subnet should belong to specified neutron network. " - "Optional, Default = None.") -@cliutils.arg( - '--availability-zone', - '--availability_zone', - '--az', - default=None, - action='single_alias', - metavar='', - help='Optional availability zone that the subnet is available within ' - '(Default=None). If None, the subnet will be considered as being ' - 'available across all availability zones.') -@cliutils.arg( - '--reset', - metavar='', - choices=['True', 'False'], - required=False, - default=False, - help='Reset and start again the check operation.' - '(Optional, Default=False)') -@api_versions.wraps("2.70") -def do_share_network_subnet_create_check(cs, args): - """Check if a new subnet can be added to a share network.""" - if xor(bool(args.neutron_net_id), bool(args.neutron_subnet_id)): - raise exceptions.CommandError( - "Both neutron_net_id and neutron_subnet_id should be specified. " - "Alternatively, neither of them should be specified.") - - share_network = _find_share_network(cs, args.share_network) - values = { - 'neutron_net_id': args.neutron_net_id, - 'neutron_subnet_id': args.neutron_subnet_id, - 'availability_zone': args.availability_zone, - 'reset_operation': args.reset, - } - subnet_create_check = ( - cs.share_networks.share_network_subnet_create_check( - share_network.id, **values)) - # result[0] is response code, result[1] is dict body - cliutils.print_dict(subnet_create_check[1]) - - -@cliutils.arg( - 'share_network', - metavar='', - help='Share network name or ID.') -@cliutils.arg( - 'share_network_subnet', - metavar='', - nargs='+', - help='Name or ID of share network subnet(s) to be deleted.') -def do_share_network_subnet_delete(cs, args): - """Delete one or more share network subnets.""" - failure_count = 0 - share_network_ref = _find_share_network(cs, args.share_network) - - for subnet in args.share_network_subnet: - try: - cs.share_network_subnets.delete(share_network_ref, subnet) - except Exception as e: - failure_count += 1 - print("Deletion of share network subnet %s failed: %s" % ( - subnet, e), file=sys.stderr) - - if failure_count == len(args.share_network_subnet): - raise exceptions.CommandError("Unable to delete any of the specified " - "share network subnets.") - - -@cliutils.arg( - 'share_network', - metavar='', - help='Name or ID of share network(s) to which the subnet belongs.') -@cliutils.arg( - 'share_network_subnet', - metavar='', - help='Share network subnet ID to show.') -def do_share_network_subnet_show(cs, args): - """Show share network subnet.""" - share_network = _find_share_network(cs, args.share_network) - share_network_subnet = cs.share_network_subnets.get( - share_network.id, args.share_network_subnet) - view_data = share_network_subnet._info.copy() - cliutils.print_dict(view_data) - - -@cliutils.arg( - 'share_network', - metavar='', - nargs='+', - help='Name or ID of share network(s) to be deleted.') -def do_share_network_delete(cs, args): - """Delete one or more share networks.""" - failure_count = 0 - - for share_network in args.share_network: - try: - share_ref = _find_share_network( - cs, share_network) - cs.share_networks.delete(share_ref) - except Exception as e: - failure_count += 1 - print("Delete for share network %s failed: %s" % ( - share_network, e), file=sys.stderr) - - if failure_count == len(args.share_network): - raise exceptions.CommandError("Unable to delete any of the specified " - "share networks.") - - -@cliutils.arg( - 'type', - metavar='', - help="Security service type: 'ldap', 'kerberos' or 'active_directory'.") -@cliutils.arg( - '--dns-ip', - metavar='', - default=None, - help="DNS IP address used inside project's network.") -@cliutils.arg( - '--ou', - metavar='', - default=None, - help="Security service OU (Organizational Unit). Available only for " - "microversion >= 2.44.") -@cliutils.arg( - '--server', - metavar='', - default=None, - help="Security service IP address or hostname.") -@cliutils.arg( - '--domain', - metavar='', - default=None, - help="Security service domain.") -@cliutils.arg( - '--user', - metavar='', - default=None, - help="Security service user or group used by project.") -@cliutils.arg( - '--password', - metavar='', - default=None, - help="Password used by user.") -@cliutils.arg( - '--name', - metavar='', - default=None, - help="Security service name.") -@cliutils.arg( - '--default-ad-site', - metavar='', - dest='default_ad_site', - default=None, - help="Default AD site. Available only for microversion >= 2.76. Can " - "be provided in the place of '--server' but not along with it.") -@cliutils.arg( - '--description', - metavar='', - default=None, - help="Security service description.") -def do_security_service_create(cs, args): - """Create security service used by project.""" - values = { - 'dns_ip': args.dns_ip, - 'server': args.server, - 'domain': args.domain, - 'user': args.user, - 'password': args.password, - 'name': args.name, - 'description': args.description, - } - - if cs.api_version.matches(api_versions.APIVersion("2.44"), - api_versions.APIVersion()): - values['ou'] = args.ou - elif args.ou: - raise exceptions.CommandError( - "Security service Organizational Unit (ou) option " - "is only available with manila API version >= 2.44") - - if cs.api_version.matches(api_versions.APIVersion("2.76"), - api_versions.APIVersion()): - values['default_ad_site'] = args.default_ad_site - elif args.default_ad_site: - raise exceptions.CommandError( - "Default AD site option is only available with " - "manila API version >= 2.76") - - if args.type == 'active_directory': - if args.server and args.default_ad_site: - raise exceptions.CommandError( - "Cannot create security service because both " - "server and 'default_ad_site' were provided. " - "Specify either server or 'default_ad_site'.") - - security_service = cs.security_services.create(args.type, **values) - info = security_service._info.copy() - cliutils.print_dict(info) - - -@cliutils.arg( - 'security_service', - metavar='', - help='Security service name or ID to update.') -@cliutils.arg( - '--dns-ip', - metavar='', - default=None, - help="DNS IP address used inside project's network.") -@cliutils.arg( - '--ou', - metavar='', - default=None, - help="Security service OU (Organizational Unit). Available only for " - "microversion >= 2.44.") -@cliutils.arg( - '--server', - metavar='', - default=None, - help="Security service IP address or hostname.") -@cliutils.arg( - '--domain', - metavar='', - default=None, - help="Security service domain.") -@cliutils.arg( - '--user', - metavar='', - default=None, - help="Security service user or group used by project.") -@cliutils.arg( - '--password', - metavar='', - default=None, - help="Password used by user.") -@cliutils.arg( - '--name', - metavar='', - default=None, - help="Security service name.") -@cliutils.arg( - '--default-ad-site', - metavar='', - dest='default_ad_site', - default=None, - help="Default AD site. Available only for microversion >= 2.76.") -@cliutils.arg( - '--description', - metavar='', - default=None, - help="Security service description.") -def do_security_service_update(cs, args): - """Update security service.""" - values = { - 'dns_ip': args.dns_ip, - 'server': args.server, - 'domain': args.domain, - 'user': args.user, - 'password': args.password, - 'name': args.name, - 'description': args.description, - } - - if cs.api_version.matches(api_versions.APIVersion("2.44"), - api_versions.APIVersion()): - values['ou'] = args.ou - elif args.ou: - raise exceptions.CommandError( - "Security service Organizational Unit (ou) option " - "is only available with manila API version >= 2.44") - - if cs.api_version.matches(api_versions.APIVersion("2.76"), - api_versions.APIVersion()): - values['default_ad_site'] = args.default_ad_site - elif args.default_ad_site: - raise exceptions.CommandError( - "Default AD site option is only available with " - "manila API version >= 2.76") - - security_service = _find_security_service( - cs, args.security_service).update(**values) - cliutils.print_dict(security_service._info) - - -@cliutils.arg( - 'security_service', - metavar='', - help='Security service name or ID to show.') -def do_security_service_show(cs, args): - """Show security service.""" - security_service = _find_security_service(cs, args.security_service) - info = security_service._info.copy() - cliutils.print_dict(info) - - -@cliutils.arg( - '--all-tenants', '--all-projects', - action='single_alias', - dest='all_projects', - metavar='<0|1>', - nargs='?', - type=int, - const=1, - default=0, - help='Display information from all projects (Admin only).') -@cliutils.arg( - '--share-network', - '--share_network', # alias - metavar='', - action='single_alias', - default=None, - help='Filter results by share network id or name.') -@cliutils.arg( - '--status', - metavar='', - default=None, - help='Filter results by status.') -@cliutils.arg( - '--name', - metavar='', - default=None, - help='Filter results by name.') -@cliutils.arg( - '--type', - metavar='', - default=None, - help='Filter results by type.') -@cliutils.arg( - '--user', - metavar='', - default=None, - help='Filter results by user or group used by projects.') -@cliutils.arg( - '--dns-ip', - '--dns_ip', # alias - metavar='', - action='single_alias', - default=None, - help="Filter results by DNS IP address used inside project's network.") -@cliutils.arg( - '--ou', - metavar='', - default=None, - help="Filter results by security service OU (Organizational Unit)." - " Available only for microversion >= 2.44.") -@cliutils.arg( - '--server', - metavar='', - default=None, - help="Filter results by security service IP address or hostname.") -@cliutils.arg( - '--domain', - metavar='', - default=None, - help="Filter results by domain.") -@cliutils.arg( - '--detailed', - dest='detailed', - metavar='<0|1>', - nargs='?', - type=int, - const=1, - default=0, - help="Show detailed information about filtered security services.") -@cliutils.arg( - '--offset', - metavar="", - default=None, - help='Start position of security services listing.') -@cliutils.arg( - '--limit', - metavar="", - default=None, - help='Number of security services to return per request.') -@cliutils.arg( - '--default-ad-site', - metavar='', - dest='default_ad_site', - default=None, - help="Default AD site. Available only for microversion >= 2.76.") -@cliutils.arg( - '--columns', - metavar='', - type=str, - default=None, - help='Comma separated list of columns to be displayed ' - 'example --columns "name,type".') -def do_security_service_list(cs, args): - """Get a list of security services.""" - all_projects = int( - os.environ.get("ALL_TENANTS", - os.environ.get("ALL_PROJECTS", - args.all_projects)) - ) - search_opts = { - 'all_tenants': all_projects, - 'status': args.status, - 'name': args.name, - 'type': args.type, - 'user': args.user, - 'dns_ip': args.dns_ip, - 'server': args.server, - 'domain': args.domain, - 'offset': args.offset, - 'limit': args.limit, - } - - if cs.api_version.matches(api_versions.APIVersion("2.44"), - api_versions.APIVersion()): - search_opts['ou'] = args.ou - elif args.ou: - raise exceptions.CommandError( - "Security service Organizational Unit (ou) option " - "is only available with manila API version >= 2.44") - - if cs.api_version.matches(api_versions.APIVersion("2.76"), - api_versions.APIVersion()): - search_opts['default_ad_site'] = args.default_ad_site - elif args.ou: - raise exceptions.CommandError( - "Security service Default AD site option " - "is only available with manila API version >= 2.76") - - if args.share_network: - search_opts['share_network_id'] = _find_share_network( - cs, args.share_network).id - security_services = cs.security_services.list(search_opts=search_opts, - detailed=args.detailed) - fields = ['id', 'name', 'status', 'type', ] - if args.columns is not None: - fields = _split_columns(columns=args.columns) - - if args.detailed: - fields.append('share_networks') - cliutils.print_list(security_services, fields=fields) - - -@cliutils.arg( - 'security_service', - metavar='', - nargs='+', - help='Name or ID of the security service(s) to delete.') -def do_security_service_delete(cs, args): - """Delete one or more security services.""" - failure_count = 0 - - for security_service in args.security_service: - try: - security_ref = _find_security_service( - cs, security_service) - cs.security_services.delete(security_ref) - except Exception as e: - failure_count += 1 - print("Delete for security service %s failed: %s" % ( - security_service, e), file=sys.stderr) - - if failure_count == len(args.security_service): - raise exceptions.CommandError("Unable to delete any of the specified " - "security services.") - - -@cliutils.arg( - '--host', - metavar='', - default=None, - help='Filter results by name of host.') -@cliutils.arg( - '--status', - metavar='', - default=None, - help='Filter results by status.') -@cliutils.arg( - '--share-network', - metavar='', - default=None, - help='Filter results by share network.') -@cliutils.arg( - '--project-id', - metavar='', - default=None, - help='Filter results by project ID.') -@cliutils.arg( - '--columns', - metavar='', - type=str, - default=None, - help='Comma separated list of columns to be displayed ' - 'example --columns "id,host,status".') -@cliutils.arg( - '--share-network-subnet', '--share_network_subnet', - type=str, - metavar='', - help="Filter results by share network subnet that the share server's " - "network allocation exists whithin. Available for micro version " - ">= 2.51 (Optional, Default=None).", - default=None) -def do_share_server_list(cs, args): - """List all share servers (Admin only).""" - search_opts = { - "host": args.host, - "share_network": args.share_network, - "status": args.status, - "project_id": args.project_id, - } - fields = [ - "Id", - "Host", - "Status", - "Share Network", - "Project Id", - "Updated_at", - ] - - if cs.api_version < api_versions.APIVersion("2.51"): - if getattr(args, 'share_network_subnet'): - raise exceptions.CommandError( - "Share network subnet option is only available with manila " - "API version >= 2.51") - elif cs.api_version < api_versions.APIVersion("2.70"): - search_opts.update({ - 'share_network_subnet_id': args.share_network_subnet}) - fields.append("Share Network Subnet Id") - else: - search_opts.update({ - 'share_network_subnet_id': args.share_network_subnet}) - fields.append("Share Network Subnet IDs") - - if args.columns is not None: - fields = _split_columns(columns=args.columns) - - share_servers = cs.share_servers.list(search_opts=search_opts) - cliutils.print_list(share_servers, fields=fields) - - -@cliutils.arg( - 'id', - metavar='', - type=str, - help='ID of share server.') -def do_share_server_show(cs, args): - """Show share server info (Admin only).""" - share_server = cs.share_servers.get(args.id) - # All 'backend_details' data already present as separated strings, - # so remove big dict from view. - if "backend_details" in share_server._info: - del share_server._info["backend_details"] - cliutils.print_dict(share_server._info) - - -@cliutils.arg( - 'id', - metavar='', - type=str, - help='ID of share server.') -def do_share_server_details(cs, args): - """Show share server details (Admin only).""" - details = cs.share_servers.details(args.id) - cliutils.print_dict(details._info) - - -@cliutils.arg( - 'id', - metavar='', - nargs='+', - type=str, - help='ID of the share server(s) to delete.') -@cliutils.arg( - '--wait', - action='store_true', - help='Wait for share server to delete') -@cliutils.service_type('sharev2') -def do_share_server_delete(cs, args): - """Delete one or more share servers (Admin only).""" - - failure_count = 0 - share_servers_to_delete = [] - - for server_id in args.id: - try: - id_ref = _find_share_server(cs, server_id) - share_servers_to_delete.append(id_ref) - id_ref.delete() - except Exception as e: - failure_count += 1 - print("Delete for share server %s failed: %s" % ( - server_id, e), file=sys.stderr) - - if failure_count == len(args.id): - raise exceptions.CommandError("Unable to delete any of the specified " - "share servers.") - - if args.wait: - for share_server in share_servers_to_delete: - try: - _wait_for_resource_status( - cs, share_server, resource_type='share_server', - expected_status='deleted') - except exceptions.CommandError as e: - print(e, file=sys.stderr) - - -@cliutils.arg( - '--columns', - metavar='', - type=str, - default=None, - help='Comma separated list of columns to be displayed ' - 'example --columns "id,name".') -def do_availability_zone_list(cs, args): - """List all availability zones.""" - - if args.columns is not None: - fields = _split_columns(columns=args.columns) - else: - fields = ("Id", "Name", "Created_At", "Updated_At") - - availability_zones = cs.availability_zones.list() - cliutils.print_list(availability_zones, fields=fields) - - -@cliutils.arg( - '--host', - metavar='', - default=None, - help='Name of host.') -@cliutils.arg( - '--binary', - metavar='', - default=None, - help='Service binary.') -@cliutils.arg( - '--status', - metavar='', - default=None, - help='Filter results by status.') -@cliutils.arg( - '--state', - metavar='', - default=None, - help='Filter results by state.') -@cliutils.arg( - '--zone', - metavar='', - default=None, - help='Availability zone.') -@cliutils.arg( - '--columns', - metavar='', - type=str, - default=None, - help='Comma separated list of columns to be displayed ' - 'example --columns "id,host".') -def do_service_list(cs, args): - """List all services (Admin only).""" - search_opts = { - 'status': args.status, - 'host': args.host, - 'binary': args.binary, - 'zone': args.zone, - 'state': args.state, - } - fields = ["Id", "Binary", "Host", "Zone", "Status", "State", "Updated_at"] - - if args.columns is not None: - fields = _split_columns(columns=args.columns) - - services = cs.services.list(search_opts=search_opts) - cliutils.print_list(services, fields=fields) - - -@cliutils.arg( - 'host', - metavar='', - help="Host name as 'example_host@example_backend'.") -@cliutils.arg( - 'binary', - metavar='', - help="Service binary, could be 'manila-share' or 'manila-scheduler'.") -def do_service_enable(cs, args): - """Enables 'manila-share' or 'manila-scheduler' services (Admin only).""" - columns = ("Host", "Binary", "Enabled") - result = cs.services.enable(args.host, args.binary) - result.enabled = not result.disabled - cliutils.print_list([result], columns) - - -@cliutils.arg( - 'host', - metavar='', - help="Host name as 'example_host@example_backend'.") -@cliutils.arg( - 'binary', - metavar='', - help="Service binary, could be 'manila-share' or 'manila-scheduler'.") -def do_service_disable(cs, args): - """Disables 'manila-share' or 'manila-scheduler' services (Admin only).""" - columns = ("Host", "Binary", "Enabled") - result = cs.services.disable(args.host, args.binary) - result.enabled = not result.disabled - cliutils.print_list([result], columns) - - -def _print_dict(data_dict): - formatted_data = [] - - for date in data_dict: - formatted_data.append("%s : %s" % (date, data_dict[date])) - - return "\n".join(formatted_data) - - -@cliutils.arg( - '--host', - metavar='', - type=str, - default='.*', - help='Filter results by host name. Regular expressions are supported.') -@cliutils.arg( - '--backend', - metavar='', - type=str, - default='.*', - help='Filter results by backend name. Regular expressions are supported.') -@cliutils.arg( - '--pool', - metavar='', - type=str, - default='.*', - help='Filter results by pool name. Regular expressions are supported.') -@cliutils.arg( - '--columns', - metavar='', - type=str, - default=None, - help='Comma separated list of columns to be displayed ' - 'example --columns "name,host".') -@cliutils.arg( - '--detail', '--detailed', - action='store_true', - help='Show detailed information about pools. If this parameter is set ' - 'to True, --columns parameter will be ignored if present. ' - '(Default=False)') -@cliutils.arg( - '--share-type', '--share_type', - '--share-type-id', '--share_type_id', - metavar='', - type=str, - default=None, - action='single_alias', - help='Filter results by share type name or ID. (Default=None)' - 'Available only for microversion >= 2.23.') -def do_pool_list(cs, args): - """List all backend storage pools known to the scheduler (Admin only).""" - - search_opts = { - 'host': args.host, - 'backend': args.backend, - 'pool': args.pool, - 'share_type': args.share_type, - } - - if args.detail: - fields = ["Name", "Host", "Backend", "Pool", "Capabilities"] - else: - fields = ["Name", "Host", "Backend", "Pool"] - - pools = cs.pools.list(detailed=args.detail, search_opts=search_opts) - if args.columns is not None: - fields = _split_columns(columns=args.columns) - pools = cs.pools.list(detailed=True, search_opts=search_opts) - - if args.detail: - for info in pools: - backend = dict() - backend['name'] = info.name - backend.update(info.capabilities) - cliutils.print_dict(backend) - else: - cliutils.print_list(pools, fields=fields) - - -@cliutils.arg('share', metavar='', - help='Name or ID of share to extend.') -@cliutils.arg('new_size', - metavar='', - type=int, - help='New size of share, in GiBs.') -@cliutils.arg( - '--wait', - action='store_true', - help='Wait for share extension') -@cliutils.arg( - '--force', - action='store_true', - help='Force attempt the extension of the share, only available with ' - 'microversion 2.64 and higher. (admin only)') -@cliutils.service_type('sharev2') -def do_extend(cs, args): - """Increases the size of an existing share.""" - share = _find_share(cs, args.share) - force = False - if args.force: - if cs.api_version < api_versions.APIVersion("2.64"): - raise exceptions.CommandError( - "args 'force' is available only starting with " - "'2.64' API microversion.") - force = True - if force: - cs.shares.extend(share, args.new_size, force=force) - else: - cs.shares.extend(share, args.new_size) - - if args.wait: - share = _wait_for_share_status(cs, share) - else: - share = _find_share(cs, args.share) - _print_share(cs, share) - - -@cliutils.arg('share', metavar='', - help='Name or ID of share to shrink.') -@cliutils.arg('new_size', - metavar='', - type=int, - help='New size of share, in GiBs.') -@cliutils.arg( - '--wait', - action='store_true', - help='Wait for share shrinkage') -@cliutils.service_type('sharev2') -def do_shrink(cs, args): - """Decreases the size of an existing share.""" - share = _find_share(cs, args.share) - cs.shares.shrink(share, args.new_size) - - if args.wait: - share = _wait_for_share_status(cs, share) - else: - share = _find_share(cs, args.share) - _print_share(cs, share) - -############################################################################## -# -# Share types -# -############################################################################## - - -def _print_type_extra_specs(share_type): - """Prints share type extra specs or share group type specs.""" - try: - return _print_dict(share_type.get_keys()) - except exceptions.NotFound: - return None - - -def _print_type_required_extra_specs(share_type): - try: - return _print_dict(share_type.get_required_keys()) - except exceptions.NotFound: - return "N/A" - - -def _print_type_optional_extra_specs(share_type): - try: - return _print_dict(share_type.get_optional_keys()) - except exceptions.NotFound: - return "N/A" - - -def _is_share_type_public(share_type): - return 'public' if share_type.is_public else 'private' - - -def _print_share_type_list(stypes, default_share_type=None, columns=None, - description=False): - - def _is_default(share_type): - if hasattr(share_type, 'is_default'): - return 'YES' if share_type.is_default else '-' - elif default_share_type: - default = default_share_type.id - return 'YES' if share_type.id == default else '-' - else: - return '-' - - formatters = { - 'visibility': _is_share_type_public, - 'is_default': _is_default, - 'required_extra_specs': _print_type_required_extra_specs, - 'optional_extra_specs': _print_type_optional_extra_specs, - } - - for stype in stypes: - stype = stype.to_dict() - stype['visibility'] = stype.pop('is_public', 'unknown') - - fields = [ - 'ID', - 'Name', - 'visibility', - 'is_default', - 'required_extra_specs', - 'optional_extra_specs', - ] - if description: - fields.append('Description') - if columns is not None: - fields = _split_columns(columns=columns, title=False) - - cliutils.print_list(stypes, fields, formatters) - - -def _print_share_type(stype, default_share_type=None, show_des=False): - - def _is_default(share_type): - if hasattr(share_type, 'is_default'): - return 'YES' if share_type.is_default else '-' - return '-' - - stype_dict = { - 'ID': stype.id, - 'Name': stype.name, - 'Visibility': _is_share_type_public(stype), - 'is_default': _is_default(stype), - 'required_extra_specs': _print_type_required_extra_specs(stype), - 'optional_extra_specs': _print_type_optional_extra_specs(stype), - } - if show_des: - stype_dict['Description'] = stype.description - cliutils.print_dict(stype_dict) - - -def _print_type_and_extra_specs_list(stypes, columns=None): - """Prints extra specs for a list of share types or share group types.""" - formatters = { - 'all_extra_specs': _print_type_extra_specs, - } - fields = ['ID', 'Name', 'all_extra_specs'] - - if columns is not None: - fields = _split_columns(columns=columns, title=False) - - cliutils.print_list(stypes, fields, formatters) - - -def _find_share_type(cs, stype): - """Get a share type by name or ID.""" - return apiclient_utils.find_resource(cs.share_types, stype) - - -@cliutils.arg( - '--all', - dest='all', - action='store_true', - default=False, - help='Display all share types whatever public or private ' - 'OPTIONAL: Default=False. (Admin only).') -@cliutils.arg( - '--extra-specs', - '--extra_specs', - type=str, - nargs='*', - metavar='', - action='single_alias', - default=None, - help='Filters results by a extra specs key and value of share type that ' - 'was used for share creation. Available only for microversion >= ' - '2.43. OPTIONAL: Default=None.') -@cliutils.arg( - '--columns', - metavar='', - type=str, - default=None, - help='Comma separated list of columns to be displayed ' - 'example --columns "id,name".') -def do_type_list(cs, args): - """Print a list of available 'share types'.""" - search_opts = None - show_all = args.all - extra_specs = _extract_extra_specs(args) - if extra_specs: - if cs.api_version < api_versions.APIVersion("2.43"): - raise exceptions.CommandError( - "Filter by 'extra_specs' is available only starting with " - "'2.43' API microversion.") - search_opts = { - 'extra_specs': extra_specs - } - - share_types = cs.share_types.list(show_all=show_all, - search_opts=search_opts) - default = None - if share_types and not hasattr(share_types[0], 'is_default'): - if ((args.columns and 'is_default' in args.columns) or - args.columns is None): - default = cs.share_types.get() - - show_des = cs.api_version.matches( - api_versions.APIVersion("2.41"), api_versions.APIVersion()) - _print_share_type_list(share_types, default_share_type=default, - columns=args.columns, description=show_des) - - -@cliutils.arg( - 'share_type', - metavar='', - help='Name or ID of the share type.') -def do_type_show(cs, args): - """Show share type details.""" - share_type = _find_share_type(cs, args.share_type) - default = None - if (share_type and not hasattr(share_type, 'is_default')): - default = cs.share_types.get() - _print_type_show(share_type, default_share_type=default) - - -@cliutils.arg( - '--columns', - metavar='', - type=str, - default=None, - help='Comma separated list of columns to be displayed ' - 'example --columns "id,name".') -def do_extra_specs_list(cs, args): - """Print a list of current 'share types and extra specs' (Admin Only).""" - stypes = cs.share_types.list() - _print_type_and_extra_specs_list(stypes, columns=args.columns) - - -@cliutils.arg( - 'name', - metavar='', - help="Name of the new share type.") -@cliutils.arg( - 'spec_driver_handles_share_servers', - metavar='', - type=str, - help="Required extra specification. " - "Valid values are 'true'/'1' and 'false'/'0'.") -@cliutils.arg( - '--description', - metavar='', - type=str, - default=None, - help='Filter results by description. ' - 'Available only for microversion >= 2.41.') -@cliutils.arg( - '--snapshot_support', - '--snapshot-support', - metavar='', - action='single_alias', - help="Boolean extra spec used for filtering of back ends by their " - "capability to create share snapshots.") -@cliutils.arg( - '--create_share_from_snapshot_support', - '--create-share-from-snapshot-support', - metavar='', - action='single_alias', - help="Boolean extra spec used for filtering of back ends by their " - "capability to create shares from snapshots.") -@cliutils.arg( - '--revert_to_snapshot_support', - '--revert-to-snapshot-support', - metavar='', - action='single_alias', - help="Boolean extra spec used for filtering of back ends by their " - "capability to revert shares to snapshots. (Default is False).") -@cliutils.arg( - '--mount_snapshot_support', - '--mount-snapshot-support', - metavar='', - action='single_alias', - help="Boolean extra spec used for filtering of back ends by their " - "capability to mount share snapshots. (Default is False).") -@cliutils.arg( - '--extra-specs', - '--extra_specs', # alias - type=str, - nargs='*', - metavar='', - action='single_alias', - help="Extra specs key and value of share type that will be" - " used for share type creation. OPTIONAL: Default=None." - " example --extra-specs thin_provisioning=' True', " - "replication_type=readable.", - default=None) -@cliutils.arg( - '--is_public', - '--is-public', - metavar='', - action='single_alias', - help="Make type accessible to the public (default true).") -def do_type_create(cs, args): - """Create a new share type (Admin only).""" - kwargs = { - "name": args.name, - "is_public": strutils.bool_from_string(args.is_public, default=True), - } - try: - kwargs['spec_driver_handles_share_servers'] = ( - strutils.bool_from_string( - args.spec_driver_handles_share_servers, strict=True)) - except ValueError as e: - msg = ("Argument spec_driver_handles_share_servers " - "argument is not valid: %s" % str(e)) - raise exceptions.CommandError(msg) - - kwargs['extra_specs'] = _extract_extra_specs(args) - - if 'driver_handles_share_servers' in kwargs['extra_specs']: - msg = ("Argument 'driver_handles_share_servers' is already " - "set via positional argument.") - raise exceptions.CommandError(msg) - - show_des = False - if cs.api_version.matches(api_versions.APIVersion("2.41"), - api_versions.APIVersion()): - show_des = True - kwargs['description'] = getattr(args, 'description') - elif getattr(args, 'description'): - raise exceptions.CommandError( - "Pattern based option (description)" - " is only available with manila API version >= 2.41") - - boolean_keys = ( - 'snapshot_support', - 'create_share_from_snapshot_support', - 'revert_to_snapshot_support', - 'mount_snapshot_support' - ) - for key in boolean_keys: - value = getattr(args, key) - - if value is not None and key in kwargs['extra_specs']: - msg = ("Argument '%s' value specified twice." % key) - raise exceptions.CommandError(msg) - - try: - if value: - kwargs['extra_specs'][key] = ( - strutils.bool_from_string(value, strict=True)) - elif key in kwargs['extra_specs']: - kwargs['extra_specs'][key] = ( - strutils.bool_from_string( - kwargs['extra_specs'][key], strict=True)) - except ValueError as e: - msg = ("Argument '%s' is of boolean " - "type and has invalid value: %s" % (key, str(e))) - raise exceptions.CommandError(msg) - - stype = cs.share_types.create(**kwargs) - _print_share_type(stype, show_des=show_des) - - -@cliutils.arg( - 'id', - metavar='', - help="Name or ID of the share type to update.") -@cliutils.arg( - '--name', - metavar='', - type=str, - help="New name of share type.") -@cliutils.arg( - '--description', - metavar='', - type=str, - default=None, - help="New description of share type.") -@cliutils.arg( - '--is-public', - '--is_public', - metavar='', - action='single_alias', - help="New visibility of the share type. If set to True, share type will " - "be available to all projects in the cloud.") -@api_versions.wraps("2.50") -def do_type_update(cs, args): - """Update share type name, description, and/or visibility. (Admin only).""" - name = getattr(args, 'name') - description = getattr(args, 'description') - is_public = getattr(args, 'is_public') - if not name and description is None and is_public is None: - msg = ("A description and/or non-empty name and/or boolean is_public " - "must be supplied to update the respective attributes of the " - "share type.") - raise exceptions.CommandError(msg) - kwargs = {} - kwargs['name'] = name - if is_public: - try: - kwargs['is_public'] = strutils.bool_from_string(is_public, - strict=True) - except ValueError as e: - raise exceptions.CommandError("The value of 'is_public' is" - " invalid: %s", str(e)) - - kwargs['description'] = description - stype = _find_share_type(cs, args.id) - stype = stype.update(**kwargs) - _print_share_type(stype, show_des=True) - - -@cliutils.arg( - 'id', - metavar='', - nargs='+', - help="Name or ID of the share type(s) to delete.") -def do_type_delete(cs, args): - """Delete one or more specific share types (Admin only).""" - - failure_count = 0 - - for name_or_id in args.id: - try: - id_ref = _find_share_type(cs, name_or_id) - cs.share_types.delete(id_ref) - except Exception as e: - failure_count += 1 - print("Delete for share type %s failed: %s" % ( - name_or_id, e), file=sys.stderr) - - if failure_count == len(args.id): - raise exceptions.CommandError("Unable to delete any of the specified " - "share types.") - - -@cliutils.arg( - 'stype', - metavar='', - help="Name or ID of the share type.") -@cliutils.arg( - 'action', - metavar='', - choices=['set', 'unset'], - help="Actions: 'set' or 'unset'.") -@cliutils.arg( - 'metadata', - metavar='', - nargs='*', - default=None, - help='Extra_specs to set or unset (only key is necessary to unset).') -def do_type_key(cs, args): - """Set or unset extra_spec for a share type (Admin only).""" - stype = _find_share_type(cs, args.stype) - - if args.metadata is not None: - keypair = _extract_metadata(args) - - if args.action == 'set': - stype.set_keys(keypair) - elif args.action == 'unset': - stype.unset_keys(list(keypair)) - - -@cliutils.arg( - 'share_type', - metavar='', - help="Filter results by share type name or ID.") -def do_type_access_list(cs, args): - """Print access information about the given share type (Admin only).""" - share_type = _find_share_type(cs, args.share_type) - if share_type.is_public: - raise exceptions.CommandError("Forbidden to get access list " - "for public share type.") - access_list = cs.share_type_access.list(share_type) - - columns = ['Project_ID'] - cliutils.print_list(access_list, columns) - - -@cliutils.arg( - 'share_type', - metavar='', - help="Share type name or ID to add access" - " for the given project.") -@cliutils.arg( - 'project_id', - metavar='', - help='Project ID to add share type access for.') -def do_type_access_add(cs, args): - """Adds share type access for the given project (Admin only).""" - vtype = _find_share_type(cs, args.share_type) - cs.share_type_access.add_project_access(vtype, args.project_id) - - -@cliutils.arg( - 'share_type', - metavar='', - help=('Share type name or ID to remove access ' - 'for the given project.')) -@cliutils.arg( - 'project_id', - metavar='', - help='Project ID to remove share type access for.') -def do_type_access_remove(cs, args): - """Removes share type access for the given project (Admin only).""" - vtype = _find_share_type(cs, args.share_type) - cs.share_type_access.remove_project_access( - vtype, args.project_id) - - -############################################################################## -# -# Share group types -# -############################################################################## - - -def _print_share_group_type_list(share_group_types, - default_share_group_type=None, columns=None): - - def _is_default(share_group_type): - if hasattr(share_group_type, 'is_default'): - return 'YES' if share_group_type.is_default else '-' - elif default_share_group_type: - default = default_share_group_type.id - return 'YES' if share_group_type.id == default else '-' - else: - return '-' - - formatters = { - 'visibility': _is_share_type_public, - 'is_default': _is_default, - } - - for sg_type in share_group_types: - sg_type = sg_type.to_dict() - sg_type['visibility'] = sg_type.pop('is_public', 'unknown') - - fields = [ - 'ID', - 'Name', - 'visibility', - 'is_default', - ] - if columns is not None: - fields = _split_columns(columns=columns, title=False) - - cliutils.print_list(share_group_types, fields, formatters, - sortby_index=None) - - -def _print_share_group_type(share_group_type, default_share_type=None): - - def _is_default(share_group_type): - if hasattr(share_group_type, 'is_default'): - return 'YES' if share_group_type.is_default else '-' - return '-' - - share_group_type_dict = { - 'ID': share_group_type.id, - 'Name': share_group_type.name, - 'Visibility': _is_share_type_public(share_group_type), - 'is_default': _is_default(share_group_type) - } - cliutils.print_dict(share_group_type_dict) - - -def _find_share_group_type(cs, sg_type): - """Get a share group type by name or ID.""" - return apiclient_utils.find_resource(cs.share_group_types, sg_type) - - -@cliutils.arg( - '--all', - dest='all', - action='store_true', - default=False, - help='Display all share group types (Admin only).') -@cliutils.arg( - '--columns', - metavar='', - type=str, - default=None, - help='Comma separated list of columns to be displayed ' - 'example --columns "id,name".') -@cliutils.service_type('sharev2') -def do_share_group_type_list(cs, args): - """Print a list of available 'share group types'.""" - - sg_types = cs.share_group_types.list(show_all=args.all) - - default = None - if sg_types and not hasattr(sg_types[0], 'is_default'): - if ((args.columns and 'is_default' in args.columns) or - args.columns is None): - default = cs.share_group_types.get() - - _print_share_group_type_list( - sg_types, default_share_group_type=default, columns=args.columns) - - -@cliutils.arg( - '--columns', - metavar='', - type=str, - default=None, - help='Comma separated list of columns to be displayed ' - 'example --columns "id,name".') -@cliutils.service_type('sharev2') -def do_share_group_type_specs_list(cs, args): - """Print a list of 'share group types specs' (Admin Only).""" - - sg_types = cs.share_group_types.list() - _print_type_and_extra_specs_list(sg_types, columns=args.columns) - - -@cliutils.arg( - 'name', - metavar='', - help='Name of the new share group type.') -@cliutils.arg( - 'share_types', - metavar='', - type=str, - help='Comma-separated list of share type names or IDs.') -@cliutils.arg( - '--is_public', - '--is-public', - metavar='', - action='single_alias', - help='Make type accessible to the public (default true).') -@cliutils.arg( - '--group-specs', - '--group_specs', - metavar='', - type=str, - nargs='*', - action='single_alias', - default=None, - help='Share Group type extra specs by key and value. ' - 'OPTIONAL: Default=None. ' - 'Example: "--group-specs consistent_snapshot_support=host".',) -@cliutils.service_type('sharev2') -def do_share_group_type_create(cs, args): - """Create a new share group type (Admin only).""" - - share_types = [_find_share_type(cs, share_type) - for share_type in args.share_types.split(',')] - - kwargs = { - 'share_types': share_types, - 'name': args.name, - 'is_public': strutils.bool_from_string(args.is_public, default=True), - } - if args.group_specs is not None: - kwargs['group_specs'] = _extract_group_specs(args) - - sg_type = cs.share_group_types.create(**kwargs) - _print_share_group_type(sg_type) - - -@cliutils.arg( - 'id', - metavar='', - help="Name or ID of the share group type to delete.") -@cliutils.service_type('sharev2') -def do_share_group_type_delete(cs, args): - """Delete a specific share group type (Admin only).""" - share_group_type = _find_share_group_type(cs, args.id) - cs.share_group_types.delete(share_group_type) - - -@cliutils.arg( - 'share_group_type', - metavar='', - help="Name or ID of the share group type.") -@cliutils.arg( - 'action', - metavar='', - choices=['set', 'unset'], - help="Actions: 'set' or 'unset'.") -@cliutils.arg( - 'group_specs', - metavar='', - nargs='*', - default=None, - help='Group specs to set or unset (only key is necessary to unset).') -@cliutils.service_type('sharev2') -def do_share_group_type_key(cs, args): - """Set or unset group_spec for a share group type (Admin only).""" - sg_type = _find_share_group_type(cs, args.share_group_type) - if args.group_specs is not None: - keypair = _extract_group_specs(args) - if args.action == 'set': - sg_type.set_keys(keypair) - elif args.action == 'unset': - sg_type.unset_keys(list(keypair)) - - -@cliutils.arg( - 'share_group_type', - metavar='', - help="Filter results by share group type name or ID.") -def do_share_group_type_access_list(cs, args): - """Print access information about a share group type (Admin only).""" - share_group_type = _find_share_group_type(cs, args.share_group_type) - if share_group_type.is_public: - raise exceptions.CommandError( - "Forbidden to get access list for public share group type.") - access_list = cs.share_group_type_access.list(share_group_type) - columns = ['Project_ID'] - cliutils.print_list(access_list, columns) - - -@cliutils.arg( - 'share_group_type', - metavar='', - help='Share group type name or ID to add access for the given project.') -@cliutils.arg( - 'project_id', - metavar='', - help='Project ID to add share group type access for.') -def do_share_group_type_access_add(cs, args): - """Adds share group type access for the given project (Admin only).""" - share_group_type = _find_share_group_type(cs, args.share_group_type) - cs.share_group_type_access.add_project_access( - share_group_type, args.project_id) - - -@cliutils.arg( - 'share_group_type', - metavar='', - help='Share group type name or ID to remove access for the given project.') -@cliutils.arg( - 'project_id', - metavar='', - help='Project ID to remove share group type access for.') -def do_share_group_type_access_remove(cs, args): - """Removes share group type access for the given project (Admin only).""" - share_group_type = _find_share_group_type(cs, args.share_group_type) - cs.share_group_type_access.remove_project_access( - share_group_type, args.project_id) - - -############################################################################## -# -# Share groups -# -############################################################################## - - -@cliutils.arg( - '--name', - metavar='', - help='Optional share group name. (Default=None)', - default=None) -@cliutils.arg( - '--description', - metavar='', - help='Optional share group description. (Default=None)', - default=None) -@cliutils.arg( - '--share-types', '--share_types', - metavar='', - type=str, - default=None, - action='single_alias', - help='Comma-separated list of share types. (Default=None)') -@cliutils.arg( - '--share-group-type', '--share_group_type', '--type', - metavar='', - type=str, - default=None, - action='single_alias', - help="Share group type name or ID of the share group to be created. " - "(Default=None)") -@cliutils.arg( - '--share-network', - '--share_network', - metavar='', - type=str, - default=None, - action='single_alias', - help='Specify share network name or id.') -@cliutils.arg( - '--source-share-group-snapshot', - '--source_share_group_snapshot', - metavar='', - type=str, - action='single_alias', - help='Optional share group snapshot name or ID to create the share group ' - 'from. (Default=None)', - default=None) -@cliutils.arg( - '--availability-zone', - '--availability_zone', - '--az', - default=None, - action='single_alias', - metavar='', - help='Optional availability zone in which group should be created. ' - '(Default=None)') -@cliutils.arg( - '--wait', - action='store_true', - default=False, - help='Wait for share group to create') -@cliutils.service_type('sharev2') -def do_share_group_create(cs, args): - """Creates a new share group.""" - share_types = [] - if args.share_types: - s_types = args.share_types.split(',') - for s_type in s_types: - share_type = _find_share_type(cs, s_type) - share_types.append(share_type) - - share_group_type = None - if args.share_group_type: - share_group_type = _find_share_group_type(cs, args.share_group_type) - - share_network = None - if args.share_network: - share_network = _find_share_network(cs, args.share_network) - - share_group_snapshot = None - if args.source_share_group_snapshot: - share_group_snapshot = _find_share_group_snapshot( - cs, args.source_share_group_snapshot) - - kwargs = { - 'share_group_type': share_group_type, - 'share_types': share_types or None, - 'name': args.name, - 'description': args.description, - 'availability_zone': args.availability_zone, - 'source_share_group_snapshot': share_group_snapshot, - 'share_network': share_network, - } - - share_group = cs.share_groups.create(**kwargs) - - if args.wait: - try: - share_group = _wait_for_resource_status( - cs, share_group, resource_type='share_group', - expected_status='available') - except exceptions.CommandError as e: - print(e, file=sys.stderr) - - _print_share_group(cs, share_group) - - -@cliutils.arg( - '--all-tenants', '--all-projects', - action='single_alias', - dest='all_projects', - metavar='<0|1>', - nargs='?', - type=int, - const=1, - default=0, - help='Display information from all projects (Admin only).') -@cliutils.arg( - '--name', - metavar='', - type=str, - default=None, - help='Filter results by name.') -@cliutils.arg( - '--description', - metavar='', - type=str, - default=None, - help='Filter results by description. ' - 'Available only for microversion >= 2.36.') -@cliutils.arg( - '--status', - metavar='', - type=str, - default=None, - help='Filter results by status.') -@cliutils.arg( - '--share-server-id', '--share-server_id', - '--share_server-id', '--share_server_id', - metavar='', - type=str, - default=None, - action='single_alias', - help='Filter results by share server ID (Admin only).') -@cliutils.arg( - '--share-group-type', '--share-group-type-id', - '--share_group_type', '--share_group_type_id', - metavar='', - type=str, - default=None, - action='single_alias', - help='Filter results by a share group type ID or name that was used for ' - 'share group creation.') -@cliutils.arg( - '--snapshot', - metavar='', - type=str, - default=None, - help='Filter results by share group snapshot name or ID that was used to ' - 'create the share group.') -@cliutils.arg( - '--host', - metavar='', - default=None, - help='Filter results by host.') -@cliutils.arg( - '--share-network', '--share_network', - metavar='', - type=str, - default=None, - action='single_alias', - help='Filter results by share-network name or ID.') -@cliutils.arg( - '--project-id', '--project_id', - metavar='', - type=str, - default=None, - action='single_alias', - help="Filter results by project ID. Useful with set key '--all-projects'.") -@cliutils.arg( - '--limit', - metavar='', - type=int, - default=None, - help='Maximum number of share groups to return. (Default=None)') -@cliutils.arg( - '--offset', - metavar="", - default=None, - help='Start position of share group listing.') -@cliutils.arg( - '--sort-key', '--sort_key', - metavar='', - type=str, - default=None, - action='single_alias', - help='Key to be sorted, available keys are %(keys)s. Default=None.' % { - 'keys': constants.SHARE_GROUP_SORT_KEY_VALUES}) -@cliutils.arg( - '--sort-dir', '--sort_dir', - metavar='', - type=str, - default=None, - action='single_alias', - help='Sort direction, available values are %(values)s. ' - 'OPTIONAL: Default=None.' % {'values': constants.SORT_DIR_VALUES}) -@cliutils.arg( - '--columns', - metavar='', - type=str, - default=None, - help='Comma separated list of columns to be displayed ' - 'example --columns "id,name".') -@cliutils.arg( - '--name~', - metavar='', - type=str, - default=None, - help='Filter results matching a share group name pattern. ' - 'Available only for microversion >= 2.36.') -@cliutils.arg( - '--description~', - metavar='', - type=str, - default=None, - help='Filter results matching a share group description pattern. ' - 'Available only for microversion >= 2.36.') -@cliutils.service_type('sharev2') -def do_share_group_list(cs, args): - """List share groups with filters.""" - if args.columns is not None: - list_of_keys = _split_columns(columns=args.columns) - else: - list_of_keys = ('ID', 'Name', 'Status', 'Description') - - all_projects = int( - os.environ.get("ALL_TENANTS", - os.environ.get("ALL_PROJECTS", - args.all_projects)) - ) - empty_obj = type('Empty', (object,), {'id': None}) - sg_type = (_find_share_group_type(cs, args.share_group_type) - if args.share_group_type else empty_obj) - snapshot = (_find_share_snapshot(cs, args.snapshot) - if args.snapshot else empty_obj) - share_network = (_find_share_network(cs, args.share_network) - if args.share_network else empty_obj) - - search_opts = { - 'offset': args.offset, - 'limit': args.limit, - 'all_tenants': all_projects, - 'name': args.name, - 'status': args.status, - 'share_server_id': args.share_server_id, - 'share_group_type_id': sg_type.id, - 'source_share_group_snapshot_id': snapshot.id, - 'host': args.host, - 'share_network_id': share_network.id, - 'project_id': args.project_id, - } - if cs.api_version.matches(api_versions.APIVersion("2.36"), - api_versions.APIVersion()): - search_opts['name~'] = getattr(args, 'name~') - search_opts['description~'] = getattr(args, 'description~') - search_opts['description'] = getattr(args, 'description') - elif (getattr(args, 'name~') or getattr(args, 'description~') or - getattr(args, 'description')): - raise exceptions.CommandError( - "Pattern based filtering (name~, description~ and description)" - " is only available with manila API version >= 2.36") - - share_groups = cs.share_groups.list( - search_opts=search_opts, sort_key=args.sort_key, - sort_dir=args.sort_dir) - cliutils.print_list(share_groups, fields=list_of_keys, - sortby_index=None) - - -@cliutils.arg( - 'share_group', - metavar='', - help='Name or ID of the share group.') -@cliutils.service_type('sharev2') -def do_share_group_show(cs, args): - """Show details about a share group.""" - share_group = _find_share_group(cs, args.share_group) - _print_share_group(cs, share_group) - - -@cliutils.arg( - 'share_group', - metavar='', - help='Name or ID of the share group to update.') -@cliutils.arg( - '--name', - metavar='', - default=None, - help='Optional new name for the share group. (Default=None)') -@cliutils.arg( - '--description', - metavar='', - help='Optional share group description. (Default=None)', - default=None) -@cliutils.service_type('sharev2') -def do_share_group_update(cs, args): - """Update a share group.""" - kwargs = {} - - if args.name is not None: - kwargs['name'] = args.name - if args.description is not None: - kwargs['description'] = args.description - - if not kwargs: - msg = "Must supply name and/or description" - raise exceptions.CommandError(msg) - share_group = _find_share_group(cs, args.share_group) - share_group = cs.share_groups.update(share_group, **kwargs) - _print_share_group(cs, share_group) - - -@cliutils.arg( - 'share_group', - metavar='', - nargs='+', - help='Name or ID of the share group(s).') -@cliutils.arg( - '--force', - action='store_true', - default=False, - help='Attempt to force delete the share group (Default=False)' - ' (Admin only).') -@cliutils.arg( - '--wait', - action='store_true', - default=False, - help='Wait for share group to delete') -@cliutils.service_type('sharev2') -def do_share_group_delete(cs, args): - """Delete one or more share groups.""" - failure_count = 0 - share_group_to_delete = [] - - for share_group in args.share_group: - try: - share_group_ref = _find_share_group(cs, share_group) - share_group_to_delete.append(share_group_ref) - share_group_ref.delete(args.force) - except Exception as e: - failure_count += 1 - print("Delete for share group %s failed: %s" % ( - share_group, e), file=sys.stderr) - - if failure_count == len(args.share_group): - raise exceptions.CommandError("Unable to delete any of the specified " - "share groups.") - - if args.wait: - for share_group in share_group_to_delete: - try: - _wait_for_resource_status( - cs, share_group, resource_type='share_group', - expected_status='deleted') - except exceptions.CommandError as e: - print(e, file=sys.stderr) - - -@cliutils.arg( - 'share_group', - metavar='', - help='Name or ID of the share group to modify.') -@cliutils.arg( - '--state', - metavar='', - default='available', - help=('Indicate which state to assign the share group. ' - 'Options include available, error, creating, deleting, ' - 'error_deleting. If no state is provided, ' - 'available will be used.')) -@cliutils.service_type('sharev2') -def do_share_group_reset_state(cs, args): - """Explicitly update the state of a share group - - (Admin only). - """ - share_group = _find_share_group(cs, args.share_group) - cs.share_groups.reset_state(share_group, args.state) - - -############################################################################## -# -# Share group snapshots -# -############################################################################## - - -@cliutils.arg( - 'share_group', - metavar='', - help='Name or ID of the share group.') -@cliutils.arg( - '--name', - metavar='', - help='Optional share group snapshot name. (Default=None)', - default=None) -@cliutils.arg( - '--description', - metavar='', - help='Optional share group snapshot description. (Default=None)', - default=None) -@cliutils.arg( - '--wait', - action='store_true', - default=False, - help='Wait for share group snapshot to be created') -@cliutils.service_type('sharev2') -def do_share_group_snapshot_create(cs, args): - """Creates a new share group snapshot.""" - kwargs = {'name': args.name, 'description': args.description} - share_group = _find_share_group(cs, args.share_group) - sg_snapshot = cs.share_group_snapshots.create(share_group.id, **kwargs) - if args.wait: - _wait_for_resource_status( - cs, sg_snapshot, resource_type='share_group_snapshot', - expected_status='available') - _print_share_group_snapshot(cs, sg_snapshot) - - -@cliutils.arg( - '--all-tenants', '--all-projects', - action='single_alias', - dest='all_projects', - metavar='<0|1>', - nargs='?', - type=int, - const=1, - default=0, - help='Display information from all projects (Admin only).') -@cliutils.arg( - '--name', - metavar='', - default=None, - help='Filter results by name.') -@cliutils.arg( - '--status', - metavar='', - default=None, - help='Filter results by status.') -@cliutils.arg( - '--share-group-id', '--share_group_id', - metavar='', - default=None, - action='single_alias', - help='Filter results by share group ID.') -@cliutils.arg( - '--limit', - metavar='', - type=int, - default=None, - help='Maximum number of share group snapshots to return. ' - '(Default=None)') -@cliutils.arg( - '--offset', - metavar="", - default=None, - help='Start position of share group snapshot listing.') -@cliutils.arg( - '--sort-key', '--sort_key', - metavar='', - type=str, - default=None, - action='single_alias', - help='Key to be sorted, available keys are %(keys)s. Default=None.' % { - 'keys': constants.SHARE_GROUP_SNAPSHOT_SORT_KEY_VALUES}) -@cliutils.arg( - '--sort-dir', '--sort_dir', - metavar='', - type=str, - default=None, - action='single_alias', - help='Sort direction, available values are %(values)s. ' - 'OPTIONAL: Default=None.' % {'values': constants.SORT_DIR_VALUES}) -@cliutils.arg( - '--detailed', - dest='detailed', - default=True, - help='Show detailed information about share group snapshots.') -@cliutils.arg( - '--columns', - metavar='', - type=str, - default=None, - help='Comma separated list of columns to be displayed ' - 'example --columns "id,name".') -@cliutils.service_type('sharev2') -def do_share_group_snapshot_list(cs, args): - """List share group snapshots with filters.""" - if args.columns is not None: - list_of_keys = _split_columns(columns=args.columns) - else: - list_of_keys = ('id', 'name', 'status', 'description') - - all_projects = int( - os.environ.get("ALL_TENANTS", - os.environ.get("ALL_PROJECTS", - args.all_projects)) - ) - - search_opts = { - 'offset': args.offset, - 'limit': args.limit, - 'all_tenants': all_projects, - 'name': args.name, - 'status': args.status, - 'share_group_id': args.share_group_id, - } - share_group_snapshots = cs.share_group_snapshots.list( - detailed=args.detailed, search_opts=search_opts, - sort_key=args.sort_key, sort_dir=args.sort_dir) - cliutils.print_list(share_group_snapshots, fields=list_of_keys, - sortby_index=None) - - -@cliutils.arg( - 'share_group_snapshot', - metavar='', - help='Name or ID of the share group snapshot.') -@cliutils.service_type('sharev2') -def do_share_group_snapshot_show(cs, args): - """Show details about a share group snapshot.""" - sg_snapshot = _find_share_group_snapshot(cs, args.share_group_snapshot) - _print_share_group_snapshot(cs, sg_snapshot) - - -@cliutils.arg( - 'share_group_snapshot', - metavar='', - help='Name or ID of the share group snapshot.') -@cliutils.arg( - '--columns', - metavar='', - type=str, - default=None, - help='Comma separated list of columns to be displayed ' - 'example --columns "id,name".') -@cliutils.service_type('sharev2') -def do_share_group_snapshot_list_members(cs, args): - """List members of a share group snapshot.""" - if args.columns is not None: - list_of_keys = _split_columns(columns=args.columns) - else: - list_of_keys = ('Share ID', 'Size') - - sg_snapshot = _find_share_group_snapshot(cs, args.share_group_snapshot) - members = [type('ShareGroupSnapshotMember', (object,), member) - for member in sg_snapshot._info.get('members', [])] - cliutils.print_list(members, fields=list_of_keys) - - -@cliutils.arg( - '--state', - metavar='', - default='available', - help=('Indicate which state to assign the share group snapshot. ' - 'Options include available, error, creating, deleting, ' - 'error_deleting. If no state is provided, ' - 'available will be used.')) -@cliutils.arg( - 'share_group_snapshot', - metavar='', - help='Name or ID of the share group snapshot.') -@cliutils.service_type('sharev2') -def do_share_group_snapshot_reset_state(cs, args): - """Explicitly update the state of a share group snapshot - - (Admin only). - """ - sg_snapshot = _find_share_group_snapshot(cs, args.share_group_snapshot) - cs.share_group_snapshots.reset_state(sg_snapshot, args.state) - - -@cliutils.arg( - 'share_group_snapshot', - metavar='', - help='Name or ID of the share group snapshot to update.') -@cliutils.arg( - '--name', - metavar='', - default=None, - help='Optional new name for the share group snapshot. (Default=None)') -@cliutils.arg( - '--description', - metavar='', - help='Optional share group snapshot description. (Default=None)', - default=None) -@cliutils.service_type('sharev2') -def do_share_group_snapshot_update(cs, args): - """Update a share group snapshot.""" - kwargs = {} - - if args.name is not None: - kwargs['name'] = args.name - - if args.description is not None: - kwargs['description'] = args.description - - if not kwargs: - msg = "Must supply name and/or description" - raise exceptions.CommandError(msg) - - sg_snapshot = _find_share_group_snapshot(cs, args.share_group_snapshot) - cs.share_group_snapshots.update(sg_snapshot, **kwargs) - - -@cliutils.arg( - 'share_group_snapshot', - metavar='', - nargs='+', - help='Name or ID of the share group snapshot(s) to delete.') -@cliutils.arg( - '--force', - action='store_true', - default=False, - help='Attempt to force delete the share group snapshot(s) (Default=False)' - ' (Admin only).') -@cliutils.arg( - '--wait', - action='store_true', - default=False, - help='Wait for share group snapshot to be deleted') -@cliutils.service_type('sharev2') -def do_share_group_snapshot_delete(cs, args): - """Remove one or more share group snapshots.""" - failure_count = 0 - kwargs = {} - - kwargs['force'] = args.force - - for sg_snapshot in args.share_group_snapshot: - try: - sg_snapshot_ref = _find_share_group_snapshot(cs, sg_snapshot) - cs.share_group_snapshots.delete(sg_snapshot_ref, **kwargs) - if args.wait: - _wait_for_resource_status( - cs, sg_snapshot, resource_type='share_group_snapshot', - expected_status='deleted') - except Exception as e: - failure_count += 1 - print("Delete for share group snapshot %s failed: %s" % ( - sg_snapshot, e), file=sys.stderr) - - if failure_count == len(args.share_group_snapshot): - raise exceptions.CommandError("Unable to delete any of the specified " - "share group snapshots.") - - -############################################################################## -# -# Share replicas -# -############################################################################## - - -@cliutils.arg( - '--share-id', - '--share_id', - '--si', # alias - metavar='', - default=None, - action='single_alias', - help='List replicas belonging to share.') -@cliutils.arg( - '--columns', - metavar='', - type=str, - default=None, - help='Comma separated list of columns to be displayed ' - 'example --columns "replica_state,id".') -@api_versions.wraps("2.11") -def do_share_replica_list(cs, args): - """List share replicas.""" - share = _find_share(cs, args.share_id) if args.share_id else None - - if args.columns is not None: - list_of_keys = _split_columns(columns=args.columns) - else: - list_of_keys = [ - 'ID', - 'Status', - 'Replica State', - 'Share ID', - 'Host', - 'Availability Zone', - 'Updated At', - ] - - if share: - replicas = cs.share_replicas.list(share) - else: - replicas = cs.share_replicas.list() - - cliutils.print_list(replicas, list_of_keys) - - -@api_versions.wraps("2.11", "2.66") -@cliutils.arg( - 'share', - metavar='', - help='Name or ID of the share to replicate.') -@cliutils.arg( - '--availability-zone', - '--availability_zone', - '--az', - default=None, - action='single_alias', - metavar='', - help='Optional Availability zone in which replica should be created.') -def do_share_replica_create(cs, args): - """Create a share replica.""" - share = _find_share(cs, args.share) - - body = { - 'share': share, - 'availability_zone': args.availability_zone, - } - replica = cs.share_replicas.create(**body) - _print_share_replica(cs, replica) - - -@api_versions.wraps("2.67", "2.71") -@cliutils.arg( - 'share', - metavar='', - help='Name or ID of the share to replicate.') -@cliutils.arg( - '--availability-zone', - '--availability_zone', - '--az', - default=None, - action='single_alias', - metavar='', - help='Optional Availability zone in which replica should be created.') -@cliutils.arg( - '--scheduler-hints', - '--scheduler_hints', - '--sh', - metavar='', - nargs='*', - help='Scheduler hints for the share replica as key=value pairs, ' - 'Supported key is only_host. Available for microversion >= 2.67. ', - default=None) -def do_share_replica_create(cs, args): # noqa - """Create a share replica.""" - share = _find_share(cs, args.share) - - scheduler_hints = {} - if args.scheduler_hints: - hints = _extract_key_value_options(args, 'scheduler_hints') - if 'only_host' not in hints.keys() or len(hints) > 1: - raise exceptions.CommandError( - "The only valid key supported with the --scheduler-hints " - "argument is 'only_host'.") - scheduler_hints['only_host'] = hints.get('only_host') - - body = { - 'share': share, - 'availability_zone': args.availability_zone, - } - if scheduler_hints: - body['scheduler_hints'] = scheduler_hints - - replica = cs.share_replicas.create(**body) - _print_share_replica(cs, replica) - - -@api_versions.wraps("2.72") -@cliutils.arg( - 'share', - metavar='', - help='Name or ID of the share to replicate.') -@cliutils.arg( - '--availability-zone', - '--availability_zone', - '--az', - default=None, - action='single_alias', - metavar='', - help='Optional Availability zone in which replica should be created.') -@cliutils.arg( - '--scheduler-hints', - '--scheduler_hints', - '--sh', - metavar='', - nargs='*', - help='Scheduler hints for the share replica as key=value pairs, ' - 'Supported key is only_host. Available for microversion >= 2.67. ', - default=None) -@cliutils.arg( - '--share-network', - '--share_network', - metavar='', - default=None, - action='single_alias', - help='Optional network info ID or name. ' - 'Available only for microversion >= 2.72') -@cliutils.arg( - '--wait', - action='store_true', - default=False, - help='Wait for share replica to be created') -def do_share_replica_create(cs, args): # noqa - """Create a share replica.""" - share = _find_share(cs, args.share) - - scheduler_hints = {} - if args.scheduler_hints: - hints = _extract_key_value_options(args, 'scheduler_hints') - if 'only_host' not in hints.keys() or len(hints) > 1: - raise exceptions.CommandError( - "The only valid key supported with the --scheduler-hints " - "argument is 'only_host'.") - scheduler_hints['only_host'] = hints.get('only_host') - - share_network = None - if args.share_network: - share_network = _find_share_network(cs, args.share_network) - - body = { - 'share': share, - 'availability_zone': args.availability_zone, - } - if scheduler_hints: - body['scheduler_hints'] = scheduler_hints - - if share_network: - body['share_network'] = share_network - - replica = cs.share_replicas.create(**body) - if args.wait: - _wait_for_resource_status( - cs, replica, resource_type='share_replica', - expected_status='available') - _print_share_replica(cs, replica) - - -@cliutils.arg( - 'replica', - metavar='', - help='ID of the share replica.') -@api_versions.wraps("2.11", "2.46") -def do_share_replica_show(cs, args): - """Show details about a replica.""" - - replica = cs.share_replicas.get(args.replica) - _print_share_replica(cs, replica) - - -@api_versions.wraps("2.47") # noqa -@cliutils.arg( - 'replica', - metavar='', - help='ID of the share replica.') -def do_share_replica_show(cs, args): # noqa - """Show details about a replica.""" - - replica = cs.share_replicas.get(args.replica) - export_locations = cs.share_replica_export_locations.list(replica) - replica._info['export_locations'] = export_locations - _print_share_replica(cs, replica) - - -@cliutils.arg( - 'replica', - metavar='', - nargs='+', - help='ID of the share replica.') -@cliutils.arg( - '--force', - action='store_true', - default=False, - help='Attempt to force deletion of a replica on its backend. Using ' - 'this option will purge the replica from Manila even if it ' - 'is not cleaned up on the backend. Defaults to False.') -@cliutils.arg( - '--wait', - action='store_true', - default=False, - help='Wait for share replica to be deleted') -@api_versions.wraps("2.11") -def do_share_replica_delete(cs, args): - """Remove one or more share replicas.""" - failure_count = 0 - kwargs = { - "force": args.force - } - - for replica in args.replica: - try: - replica_ref = _find_share_replica(cs, replica) - cs.share_replicas.delete(replica_ref, **kwargs) - if args.wait: - _wait_for_resource_status( - cs, replica_ref, resource_type='share_replica', - expected_status='deleted') - except Exception as e: - failure_count += 1 - print("Delete for share replica %s failed: %s" % (replica, e), - file=sys.stderr) - - if failure_count == len(args.replica): - raise exceptions.CommandError("Unable to delete any of the specified " - "replicas.") - - -@cliutils.arg( - 'replica', - metavar='', - help='ID of the share replica.') -@api_versions.wraps("2.11", "2.74") -def do_share_replica_promote(cs, args): - """Promote specified replica to 'active' replica_state.""" - replica = _find_share_replica(cs, args.replica) - cs.share_replicas.promote(replica) - - -@cliutils.arg( - 'replica', - metavar='', - help='ID of the share replica.') -@cliutils.arg( - '--quiesce-wait-time', - metavar='', - default=None, - help='Quiesce wait time in seconds. Available for ' - 'microversion >= 2.75') -@cliutils.arg( - '--wait', - action='store_true', - default=False, - help='Wait for share replica to be promoted') -@api_versions.wraps("2.75") # noqa -def do_share_replica_promote(cs, args): # noqa - """Promote specified replica to 'active' replica_state.""" - replica = _find_share_replica(cs, args.replica) - - quiesce_wait_time = None - if args.quiesce_wait_time: - quiesce_wait_time = args.quiesce_wait_time - cs.share_replicas.promote(replica, quiesce_wait_time) - if args.wait: - _wait_for_resource_status( - cs, replica, - resource_type='share_replica', - expected_status='active', - status_attr='replica_state') - - -@api_versions.wraps("2.47") -@cliutils.arg( - 'replica', - metavar='', - help='ID of the share replica.') -@cliutils.arg( - '--columns', - metavar='', - type=str, - default=None, - help='Comma separated list of columns to be displayed ' - 'example --columns "id,path,replica_state".') -def do_share_replica_export_location_list(cs, args): - """List export locations of a share replica.""" - if args.columns is not None: - list_of_keys = _split_columns(columns=args.columns) - else: - list_of_keys = [ - 'ID', - 'Availability Zone', - 'Replica State', - 'Preferred', - 'Path', - ] - replica = _find_share_replica(cs, args.replica) - export_locations = cs.share_replica_export_locations.list(replica) - cliutils.print_list(export_locations, list_of_keys) - - -@api_versions.wraps("2.47") -@cliutils.arg( - 'replica', - metavar='', - help='Name or ID of the share replica.') -@cliutils.arg( - 'export_location', - metavar='', - help='ID of the share replica export location.') -def do_share_replica_export_location_show(cs, args): - """Show details of a share replica's export location.""" - replica = _find_share_replica(cs, args.replica) - export_location = cs.share_replica_export_locations.get( - replica, args.export_location) - view_data = export_location._info.copy() - cliutils.print_dict(view_data) - - -@cliutils.arg( - 'replica', - metavar='', - help='ID of the share replica to modify.') -@cliutils.arg( - '--state', - metavar='', - default='available', - help=('Indicate which state to assign the replica. Options include ' - 'available, error, creating, deleting, error_deleting. If no ' - 'state is provided, available will be used.')) -@api_versions.wraps("2.11") -def do_share_replica_reset_state(cs, args): - """Explicitly update the 'status' of a share replica.""" - replica = _find_share_replica(cs, args.replica) - cs.share_replicas.reset_state(replica, args.state) - - -@cliutils.arg( - 'replica', - metavar='', - help='ID of the share replica to modify.') -@cliutils.arg( - '--replica-state', - '--replica_state', - '--state', # alias for user sanity - metavar='', - default='out_of_sync', - action='single_alias', - help=('Indicate which replica_state to assign the replica. Options ' - 'include in_sync, out_of_sync, active, error. If no ' - 'state is provided, out_of_sync will be used.')) -@api_versions.wraps("2.11") -def do_share_replica_reset_replica_state(cs, args): - """Explicitly update the 'replica_state' of a share replica.""" - replica = _find_share_replica(cs, args.replica) - cs.share_replicas.reset_replica_state(replica, args.replica_state) - - -@cliutils.arg( - 'replica', - metavar='', - help='ID of the share replica to resync.') -@api_versions.wraps("2.11") -def do_share_replica_resync(cs, args): - """Attempt to update the share replica with its 'active' mirror.""" - replica = _find_share_replica(cs, args.replica) - cs.share_replicas.resync(replica) - - -############################################################################## -# -# Share Transfer -# -############################################################################## - - -def _print_share_transfer(transfer): - info = transfer._info.copy() - info.pop('links', None) - - cliutils.print_dict(info) - - -@api_versions.wraps("2.77") -@cliutils.arg( - 'share', - metavar='', - help='Name or ID of share to transfer.') -@cliutils.arg( - '--name', - metavar='', - default=None, - help='Transfer name. Default=None.') -def do_share_transfer_create(cs, args): - """Creates a share transfer.""" - share = _find_share(cs, args.share) - transfer = cs.transfers.create(share.id, - args.name) - _print_share_transfer(transfer) - - -@api_versions.wraps("2.77") -@cliutils.arg( - 'transfer', - metavar='', - nargs='+', - help='ID or name of the transfer(s).') -def do_share_transfer_delete(cs, args): - """Remove one or more transfers.""" - failure_count = 0 - - for transfer in args.transfer: - try: - transfer_ref = _find_share_transfer(cs, transfer) - transfer_ref.delete() - except Exception as e: - failure_count += 1 - print("Delete for share transfer %s failed: %s" % (transfer, e), - file=sys.stderr) - - if failure_count == len(args.transfer): - raise exceptions.CommandError("Unable to delete any of the specified " - "transfers.") - - -@api_versions.wraps("2.77") -@cliutils.arg( - 'transfer', - metavar='', - help='ID of transfer to accept.') -@cliutils.arg( - 'auth_key', - metavar='', - help='Authentication key of transfer to accept.') -@cliutils.arg( - '--clear-rules', - '--clear_rules', - dest='clear_rules', - action='store_true', - default=False, - help="Whether manila should clean up the access rules after the " - "transfer is complete. (Default=False)") -def do_share_transfer_accept(cs, args): - """Accepts a share transfer.""" - cs.transfers.accept(args.transfer, args.auth_key, - clear_access_rules=args.clear_rules) - - -@api_versions.wraps("2.77") -@cliutils.arg( - '--all-tenants', '--all-projects', - action='single_alias', - dest='all_projects', - metavar='<0|1>', - nargs='?', - type=int, - const=1, - default=0, - help='Shows details for all tenants. (Admin only).') -@cliutils.arg( - '--name', - metavar='', - default=None, - action='single_alias', - help='Transfer name. Default=None.') -@cliutils.arg( - '--id', - metavar='', - default=None, - action='single_alias', - help='Transfer ID. Default=None.') -@cliutils.arg( - '--resource-type', '--resource_type', - metavar='', - default=None, - action='single_alias', - help='Transfer type, which can be share or network. Default=None.') -@cliutils.arg( - '--resource-id', '--resource_id', - metavar='', - default=None, - action='single_alias', - help='Transfer resource id. Default=None.') -@cliutils.arg( - '--source-project-id', '--source_project_id', - metavar='', - default=None, - action='single_alias', - help='Transfer source project id. Default=None.') -@cliutils.arg( - '--limit', - metavar='', - type=int, - default=None, - help='Maximum number of messages to return. (Default=None)') -@cliutils.arg( - '--offset', - metavar="", - default=None, - help='Start position of message listing.') -@cliutils.arg( - '--sort-key', '--sort_key', - metavar='', - type=str, - default=None, - action='single_alias', - help='Key to be sorted, available keys are %(keys)s. Default=None.' - % {'keys': constants.SHARE_TRANSFER_SORT_KEY_VALUES}) -@cliutils.arg( - '--sort-dir', '--sort_dir', - metavar='', - type=str, - default=None, - action='single_alias', - help='Sort direction, available values are %(values)s. ' - 'Optional: Default=None.' % {'values': constants.SORT_DIR_VALUES}) -@cliutils.arg( - '--detailed', - dest='detailed', - metavar='<0|1>', - nargs='?', - type=int, - const=1, - default=0, - help="Show detailed information about filtered share transfers.") -@cliutils.arg( - '--columns', - metavar='', - type=str, - default=None, - help='Comma separated list of columns to be displayed ' - 'example --columns "id,resource_id".') -def do_share_transfer_list(cs, args): - """Lists all transfers.""" - if args.columns is not None: - list_of_keys = _split_columns(columns=args.columns) - else: - list_of_keys = ['ID', 'Name', 'Resource Type', 'Resource Id'] - - if args.detailed: - list_of_keys.extend(['Created At', 'Expires At', 'Source Project Id', - 'Destination Project Id', 'Accepted']) - - all_projects = int( - os.environ.get("ALL_TENANTS", - os.environ.get("ALL_PROJECTS", - args.all_projects)) - ) - - search_opts = { - 'offset': args.offset, - 'limit': args.limit, - 'all_tenants': all_projects, - 'id': args.id, - 'name': args.name, - 'resource_type': args.resource_type, - 'resource_id': args.resource_id, - 'source_project_id': args.source_project_id, - } - share_transfers = cs.transfers.list( - detailed=args.detailed, search_opts=search_opts, - sort_key=args.sort_key, sort_dir=args.sort_dir) - cliutils.print_list(share_transfers, fields=list_of_keys, - sortby_index=None) - - -@api_versions.wraps("2.77") -@cliutils.arg( - 'transfer', - metavar='', - help='Name or ID of transfer to show.') -def do_share_transfer_show(cs, args): - """Delete a transfer.""" - transfer = _find_share_transfer(cs, args.transfer) - _print_share_transfer(transfer) -############################################################################## -# -# User Messages -# -############################################################################## - - -@api_versions.wraps("2.37") -@cliutils.arg( - '--resource_id', - '--resource-id', - '--resource', - metavar='', - default=None, - action='single_alias', - help='Filters results by a resource uuid. Default=None.') -@cliutils.arg( - '--resource_type', - '--resource-type', - metavar='', - default=None, - action='single_alias', - help='Filters results by a resource type. Default=None. ' - 'Example: "manila message-list --resource_type share"') -@cliutils.arg( - '--action_id', - '--action-id', - '--action', - metavar='', - default=None, - action='single_alias', - help='Filters results by action id. Default=None.') -@cliutils.arg( - '--detail_id', - '--detail-id', - '--detail', - metavar='', - default=None, - action='single_alias', - help='Filters results by detail id. Default=None.') -@cliutils.arg( - '--request_id', - '--request-id', - '--request', - metavar='', - default=None, - action='single_alias', - help='Filters results by request id. Default=None.') -@cliutils.arg( - '--level', - '--message_level', - '--message-level', - metavar='', - default=None, - action='single_alias', - help='Filters results by the message level. Default=None. ' - 'Example: "manila message-list --level ERROR".') -@cliutils.arg( - '--limit', - metavar='', - type=int, - default=None, - help='Maximum number of messages to return. (Default=None)') -@cliutils.arg( - '--offset', - metavar="", - default=None, - help='Start position of message listing.') -@cliutils.arg( - '--sort-key', '--sort_key', - metavar='', - type=str, - default=None, - action='single_alias', - help='Key to be sorted, available keys are %(keys)s. Default=desc.' % { - 'keys': constants.MESSAGE_SORT_KEY_VALUES}) -@cliutils.arg( - '--sort-dir', '--sort_dir', - metavar='', - type=str, - default=None, - action='single_alias', - help='Sort direction, available values are %(values)s. ' - 'OPTIONAL: Default=None.' % {'values': constants.SORT_DIR_VALUES}) -@cliutils.arg( - '--columns', - metavar='', - type=str, - default=None, - help='Comma separated list of columns to be displayed ' - 'example --columns "resource_id,user_message".') -@cliutils.arg( - '--since', - metavar='', - default=None, - help='Return only user messages created since given date. ' - 'The date format must be conforming to ISO8601. ' - 'Available only for microversion >= 2.52.') -@cliutils.arg( - '--before', - metavar='', - default=None, - help='Return only user messages created before given date. ' - 'The date format must be conforming to ISO8601. ' - 'Available only for microversion >= 2.52.') -def do_message_list(cs, args): - """Lists all messages.""" - if args.columns is not None: - list_of_keys = _split_columns(columns=args.columns) - else: - list_of_keys = ['ID', 'Resource Type', 'Resource ID', 'Action ID', - 'User Message', 'Detail ID', 'Created At'] - - search_opts = { - 'offset': args.offset, - 'limit': args.limit, - 'request_id': args.request_id, - 'resource_type': args.resource_type, - 'resource_id': args.resource_id, - 'action_id': args.action_id, - 'detail_id': args.detail_id, - 'message_level': args.level - } - if cs.api_version < api_versions.APIVersion("2.52"): - msg = ("Filtering messages by 'since' and 'before' is possible only " - "with Manila API version >=2.52") - if getattr(args, 'since') or getattr(args, 'before'): - raise exceptions.CommandError(msg) - else: - search_opts['created_since'] = args.since - search_opts['created_before'] = args.before - - messages = cs.messages.list( - search_opts=search_opts, sort_key=args.sort_key, - sort_dir=args.sort_dir) - cliutils.print_list(messages, fields=list_of_keys, sortby_index=None) - - -@cliutils.arg( - 'message', - metavar='', - help='ID of the message.') -@api_versions.wraps("2.37") -def do_message_show(cs, args): - """Show details about a message.""" - - message = cs.messages.get(args.message) - _print_message(message) - - -@api_versions.wraps("2.37") -@cliutils.arg( - 'message', - metavar='', - nargs='+', - help='ID of the message(s).') -def do_message_delete(cs, args): - """Remove one or more messages.""" - failure_count = 0 - - for message in args.message: - try: - message_ref = _find_message(cs, message) - cs.messages.delete(message_ref) - except Exception as e: - failure_count += 1 - print("Delete for message %s failed: %s" % (message, e), - file=sys.stderr) - - if failure_count == len(args.message): - raise exceptions.CommandError("Unable to delete any of the specified " - "messages.") - - -def _print_message(message): - message_dict = { - 'id': message.id, - 'resource_type': message.resource_type, - 'resource_id': message.resource_id, - 'action_id': message.action_id, - 'user_message': message.user_message, - 'message_level': message.message_level, - 'detail_id': message.detail_id, - 'created_at': message.created_at, - 'expires_at': message.expires_at, - 'request_id': message.request_id, - } - cliutils.print_dict(message_dict) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..69068e91 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,217 @@ +[build-system] +requires = ["pbr>=6.1.1"] +build-backend = "pbr.build" + +[project] +name = "python-manilaclient" +description = "Client library for OpenStack Shared File System Storage" +authors = [ + {name = "OpenStack", email = "openstack-discuss@lists.openstack.org"}, +] +readme = {file = "README.rst", content-type = "text/x-rst"} +license = {text = "Apache-2.0"} +dynamic = ["version", "dependencies"] +requires-python = ">=3.10" +classifiers = [ + "Environment :: OpenStack", + "Intended Audience :: Information Technology", + "Intended Audience :: System Administrators", + "License :: OSI Approved :: Apache Software License", + "Operating System :: POSIX :: Linux", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", +] + +[project.urls] +Homepage = "https://docs.openstack.org/python-manilaclient/" +Repository = "https://opendev.org/openstack/python-manilaclient/" + +[project.entry-points."oslo.config.opts"] +"manilaclient.config" = "manilaclient.config:list_opts" + +[project.entry-points."openstack.cli.extension"] +share = "manilaclient.osc.plugin" + +[project.entry-points."openstack.share.v2"] +share_list = "manilaclient.osc.v2.share:ListShare" +share_create = "manilaclient.osc.v2.share:CreateShare" +share_delete = "manilaclient.osc.v2.share:DeleteShare" +share_show = "manilaclient.osc.v2.share:ShowShare" +share_set = "manilaclient.osc.v2.share:SetShare" +share_unset = "manilaclient.osc.v2.share:UnsetShare" +share_resize = "manilaclient.osc.v2.share:ResizeShare" +share_adopt = "manilaclient.osc.v2.share:AdoptShare" +share_abandon = "manilaclient.osc.v2.share:AbandonShare" +share_migration_start = "manilaclient.osc.v2.share:ShareMigrationStart" +share_migration_cancel = "manilaclient.osc.v2.share:ShareMigrationCancel" +share_migration_complete = "manilaclient.osc.v2.share:ShareMigrationComplete" +share_migration_show = "manilaclient.osc.v2.share:ShareMigrationShow" +share_export_location_show = "manilaclient.osc.v2.share:ShareExportLocationShow" +share_export_location_list = "manilaclient.osc.v2.share:ShareExportLocationList" +share_export_location_set = "manilaclient.osc.v2.share:ShareExportLocationSet" +share_export_location_unset = "manilaclient.osc.v2.share:ShareExportLocationUnset" +share_properties_show = "manilaclient.osc.v2.share:ShowShareProperties" +share_restore = "manilaclient.osc.v2.share:RestoreShare" +share_revert = "manilaclient.osc.v2.share:RevertShare" +share_access_create = "manilaclient.osc.v2.share_access_rules:ShareAccessAllow" +share_access_delete = "manilaclient.osc.v2.share_access_rules:ShareAccessDeny" +share_access_list = "manilaclient.osc.v2.share_access_rules:ListShareAccess" +share_access_show = "manilaclient.osc.v2.share_access_rules:ShowShareAccess" +share_access_set = "manilaclient.osc.v2.share_access_rules:SetShareAccess" +share_access_unset = "manilaclient.osc.v2.share_access_rules:UnsetShareAccess" +share_backup_create = "manilaclient.osc.v2.share_backups:CreateShareBackup" +share_backup_delete = "manilaclient.osc.v2.share_backups:DeleteShareBackup" +share_backup_list = "manilaclient.osc.v2.share_backups:ListShareBackup" +share_backup_show = "manilaclient.osc.v2.share_backups:ShowShareBackup" +share_backup_restore = "manilaclient.osc.v2.share_backups:RestoreShareBackup" +share_backup_set = "manilaclient.osc.v2.share_backups:SetShareBackup" +share_backup_unset = "manilaclient.osc.v2.share_backups:UnsetShareBackup" +share_type_create = "manilaclient.osc.v2.share_types:CreateShareType" +share_type_delete = "manilaclient.osc.v2.share_types:DeleteShareType" +share_type_set = "manilaclient.osc.v2.share_types:SetShareType" +share_type_unset = "manilaclient.osc.v2.share_types:UnsetShareType" +share_type_list = "manilaclient.osc.v2.share_types:ListShareType" +share_type_show = "manilaclient.osc.v2.share_types:ShowShareType" +share_type_access_create = "manilaclient.osc.v2.share_type_access:ShareTypeAccessAllow" +share_type_access_list = "manilaclient.osc.v2.share_type_access:ListShareTypeAccess" +share_type_access_delete = "manilaclient.osc.v2.share_type_access:ShareTypeAccessDeny" +share_quota_set = "manilaclient.osc.v2.quotas:QuotaSet" +share_quota_show = "manilaclient.osc.v2.quotas:QuotaShow" +share_quota_delete = "manilaclient.osc.v2.quotas:QuotaDelete" +share_snapshot_create = "manilaclient.osc.v2.share_snapshots:CreateShareSnapshot" +share_snapshot_delete = "manilaclient.osc.v2.share_snapshots:DeleteShareSnapshot" +share_snapshot_show = "manilaclient.osc.v2.share_snapshots:ShowShareSnapshot" +share_snapshot_set = "manilaclient.osc.v2.share_snapshots:SetShareSnapshot" +share_snapshot_unset = "manilaclient.osc.v2.share_snapshots:UnsetShareSnapshot" +share_snapshot_list = "manilaclient.osc.v2.share_snapshots:ListShareSnapshot" +share_snapshot_adopt = "manilaclient.osc.v2.share_snapshots:AdoptShareSnapshot" +share_snapshot_abandon = "manilaclient.osc.v2.share_snapshots:AbandonShareSnapshot" +share_snapshot_access_create = "manilaclient.osc.v2.share_snapshots:ShareSnapshotAccessAllow" +share_snapshot_access_delete = "manilaclient.osc.v2.share_snapshots:ShareSnapshotAccessDeny" +share_snapshot_access_list = "manilaclient.osc.v2.share_snapshots:ShareSnapshotAccessList" +share_snapshot_export_location_list = "manilaclient.osc.v2.share_snapshots:ShareSnapshotListExportLocation" +share_snapshot_export_location_show = "manilaclient.osc.v2.share_snapshots:ShareSnapshotShowExportLocation" +share_snapshot_instance_list = "manilaclient.osc.v2.share_snapshot_instances:ListShareSnapshotInstance" +share_snapshot_instance_show = "manilaclient.osc.v2.share_snapshot_instances:ShowShareSnapshotInstance" +share_snapshot_instance_set = "manilaclient.osc.v2.share_snapshot_instances:SetShareSnapshotInstance" +share_snapshot_instance_export_location_list = "manilaclient.osc.v2.share_snapshot_instance_export_locations:ShareSnapshotInstanceExportLocationList" +share_snapshot_instance_export_location_show = "manilaclient.osc.v2.share_snapshot_instance_export_locations:ShareSnapshotInstanceExportLocationShow" +share_message_delete = "manilaclient.osc.v2.messages:DeleteMessage" +share_message_list = "manilaclient.osc.v2.messages:ListMessage" +share_message_show = "manilaclient.osc.v2.messages:ShowMessage" +share_replica_create = "manilaclient.osc.v2.share_replicas:CreateShareReplica" +share_replica_delete = "manilaclient.osc.v2.share_replicas:DeleteShareReplica" +share_replica_list = "manilaclient.osc.v2.share_replicas:ListShareReplica" +share_replica_show = "manilaclient.osc.v2.share_replicas:ShowShareReplica" +share_replica_set = "manilaclient.osc.v2.share_replicas:SetShareReplica" +share_replica_unset = "manilaclient.osc.v2.share_replicas:UnsetShareReplica" +share_replica_promote = "manilaclient.osc.v2.share_replicas:PromoteShareReplica" +share_replica_resync = "manilaclient.osc.v2.share_replicas:ResyncShareReplica" +share_replica_export_location_list = "manilaclient.osc.v2.share_replica_export_locations:ShareReplicaListExportLocation" +share_replica_export_location_show = "manilaclient.osc.v2.share_replica_export_locations:ShareReplicaShowExportLocation" +share_availability_zone_list = "manilaclient.osc.v2.availability_zones:ShareAvailabilityZoneList" +share_service_set = "manilaclient.osc.v2.services:SetShareService" +share_service_list = "manilaclient.osc.v2.services:ListShareService" +share_service_ensure_shares = "manilaclient.osc.v2.services:EnsureShareService" +share_security_service_create = "manilaclient.osc.v2.security_services:CreateShareSecurityService" +share_security_service_delete = "manilaclient.osc.v2.security_services:DeleteShareSecurityService" +share_security_service_show = "manilaclient.osc.v2.security_services:ShowShareSecurityService" +share_security_service_set = "manilaclient.osc.v2.security_services:SetShareSecurityService" +share_security_service_unset = "manilaclient.osc.v2.security_services:UnsetShareSecurityService" +share_security_service_list = "manilaclient.osc.v2.security_services:ListShareSecurityService" +share_pool_list = "manilaclient.osc.v2.share_pools:ListSharePools" +share_instance_delete = "manilaclient.osc.v2.share_instances:ShareInstanceDelete" +share_instance_list = "manilaclient.osc.v2.share_instances:ShareInstanceList" +share_instance_set = "manilaclient.osc.v2.share_instances:ShareInstanceSet" +share_instance_show = "manilaclient.osc.v2.share_instances:ShareInstanceShow" +share_instance_export_location_show = "manilaclient.osc.v2.share_instance_export_locations:ShareInstanceShowExportLocation" +share_instance_export_location_list = "manilaclient.osc.v2.share_instance_export_locations:ShareInstanceListExportLocation" +share_limits_show = "manilaclient.osc.v2.share_limits:ShareLimitsShow" +share_network_list = "manilaclient.osc.v2.share_networks:ListShareNetwork" +share_network_show = "manilaclient.osc.v2.share_networks:ShowShareNetwork" +share_network_create = "manilaclient.osc.v2.share_networks:CreateShareNetwork" +share_network_delete = "manilaclient.osc.v2.share_networks:DeleteShareNetwork" +share_network_set = "manilaclient.osc.v2.share_networks:SetShareNetwork" +share_network_unset = "manilaclient.osc.v2.share_networks:UnsetShareNetwork" +share_network_subnet_create = "manilaclient.osc.v2.share_network_subnets:CreateShareNetworkSubnet" +share_network_subnet_delete = "manilaclient.osc.v2.share_network_subnets:DeleteShareNetworkSubnet" +share_network_subnet_show = "manilaclient.osc.v2.share_network_subnets:ShowShareNetworkSubnet" +share_network_subnet_set = "manilaclient.osc.v2.share_network_subnets:SetShareNetworkSubnet" +share_network_subnet_unset = "manilaclient.osc.v2.share_network_subnets:UnsetShareNetworkSubnet" +share_group_create = "manilaclient.osc.v2.share_groups:CreateShareGroup" +share_group_delete = "manilaclient.osc.v2.share_groups:DeleteShareGroup" +share_group_list = "manilaclient.osc.v2.share_groups:ListShareGroup" +share_group_show = "manilaclient.osc.v2.share_groups:ShowShareGroup" +share_group_set = "manilaclient.osc.v2.share_groups:SetShareGroup" +share_group_unset = "manilaclient.osc.v2.share_groups:UnsetShareGroup" +share_group_type_create = "manilaclient.osc.v2.share_group_types:CreateShareGroupType" +share_group_type_delete = "manilaclient.osc.v2.share_group_types:DeleteShareGroupType" +share_group_type_list = "manilaclient.osc.v2.share_group_types:ListShareGroupType" +share_group_type_show = "manilaclient.osc.v2.share_group_types:ShowShareGroupType" +share_group_type_set = "manilaclient.osc.v2.share_group_types:SetShareGroupType" +share_group_type_unset = "manilaclient.osc.v2.share_group_types:UnsetShareGroupType" +share_group_type_access_create = "manilaclient.osc.v2.share_group_type_access:ShareGroupTypeAccessAllow" +share_group_type_access_list = "manilaclient.osc.v2.share_group_type_access:ListShareGroupTypeAccess" +share_group_type_access_delete = "manilaclient.osc.v2.share_group_type_access:ShareGroupTypeAccessDeny" +share_group_snapshot_create = "manilaclient.osc.v2.share_group_snapshots:CreateShareGroupSnapshot" +share_group_snapshot_delete = "manilaclient.osc.v2.share_group_snapshots:DeleteShareGroupSnapshot" +share_group_snapshot_show = "manilaclient.osc.v2.share_group_snapshots:ShowShareGroupSnapshot" +share_group_snapshot_list = "manilaclient.osc.v2.share_group_snapshots:ListShareGroupSnapshot" +share_group_snapshot_set = "manilaclient.osc.v2.share_group_snapshots:SetShareGroupSnapshot" +share_group_snapshot_unset = "manilaclient.osc.v2.share_group_snapshots:UnsetShareGroupSnapshot" +share_group_snapshot_members_list = "manilaclient.osc.v2.share_group_snapshots:ListShareGroupSnapshotMembers" +share_server_delete = "manilaclient.osc.v2.share_servers:DeleteShareServer" +share_server_show = "manilaclient.osc.v2.share_servers:ShowShareServer" +share_server_list = "manilaclient.osc.v2.share_servers:ListShareServer" +share_server_adopt = "manilaclient.osc.v2.share_servers:AdoptShareServer" +share_server_abandon = "manilaclient.osc.v2.share_servers:AbandonShareServer" +share_server_set = "manilaclient.osc.v2.share_servers:SetShareServer" +share_server_migration_cancel = "manilaclient.osc.v2.share_servers:ShareServerMigrationCancel" +share_server_migration_complete = "manilaclient.osc.v2.share_servers:ShareServerMigrationComplete" +share_server_migration_show = "manilaclient.osc.v2.share_servers:ShareServerMigrationShow" +share_server_migration_start = "manilaclient.osc.v2.share_servers:ShareServerMigrationStart" +share_transfer_create = "manilaclient.osc.v2.share_transfers:CreateShareTransfer" +share_transfer_delete = "manilaclient.osc.v2.share_transfers:DeleteShareTransfer" +share_transfer_list = "manilaclient.osc.v2.share_transfers:ListShareTransfer" +share_transfer_show = "manilaclient.osc.v2.share_transfers:ShowShareTransfer" +share_transfer_accept = "manilaclient.osc.v2.share_transfers:AcceptShareTransfer" +share_lock_create = "manilaclient.osc.v2.resource_locks:CreateResourceLock" +share_lock_list = "manilaclient.osc.v2.resource_locks:ListResourceLock" +share_lock_show = "manilaclient.osc.v2.resource_locks:ShowResourceLock" +share_lock_set = "manilaclient.osc.v2.resource_locks:SetResourceLock" +share_lock_unset = "manilaclient.osc.v2.resource_locks:UnsetResourceLock" +share_lock_delete = "manilaclient.osc.v2.resource_locks:DeleteResourceLock" +share_qos_type_create = "manilaclient.osc.v2.qos_types:CreateQosType" +share_qos_type_list = "manilaclient.osc.v2.qos_types:ListQosType" +share_qos_type_show = "manilaclient.osc.v2.qos_types:ShowQosType" +share_qos_type_set = "manilaclient.osc.v2.qos_types:SetQosType" +share_qos_type_unset = "manilaclient.osc.v2.qos_types:UnsetQosType" +share_qos_type_delete = "manilaclient.osc.v2.qos_types:DeleteQosType" + +[tool.setuptools] +packages = [ + "manilaclient" +] + +[tool.coverage.run] +omit = [ + "manilaclient/tests/*", +] +branch = true + +[tool.ruff] +line-length = 79 + +[tool.ruff.format] +quote-style = "preserve" +docstring-code-format = true + +[tool.ruff.lint] +select = ["E4", "E5", "E7", "E9", "F", "S", "UP"] + +[tool.ruff.lint.per-file-ignores] +"manilaclient/tests/*" = ["S"] diff --git a/releasenotes/notes/add-encryption-key-ref-option-for-share-create-api-035aec5b31d7c37b.yaml b/releasenotes/notes/add-encryption-key-ref-option-for-share-create-api-035aec5b31d7c37b.yaml new file mode 100644 index 00000000..621dfc58 --- /dev/null +++ b/releasenotes/notes/add-encryption-key-ref-option-for-share-create-api-035aec5b31d7c37b.yaml @@ -0,0 +1,11 @@ +--- +features: + - | + Starting microversion 2.90, Manila supports 'bring your own key' feature + that allows user to pass encryption key reference in share creation. The + encryption key reference must be the UUID of a secret encryption key that + is stored on a key manager configured in the Shared File Systems service. + Encryption key reference can belongs to either share or share-server which + will be decided by storage driver capability and the share type. + Added 'encryption_keys' per project quota which controls how many share + and share server encryption keys will be created within project. diff --git a/releasenotes/notes/add-ensuring-filter-for-services-eedbead009d3505f.yaml b/releasenotes/notes/add-ensuring-filter-for-services-eedbead009d3505f.yaml new file mode 100644 index 00000000..3f560b6c --- /dev/null +++ b/releasenotes/notes/add-ensuring-filter-for-services-eedbead009d3505f.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + It is now possible to filter services that have their status set to + `ensuring` with a new option in the `service list` command. diff --git a/releasenotes/notes/add-export-variable-for-api-endpoint-override-c00ea54e1670cb90.yaml b/releasenotes/notes/add-export-variable-for-api-endpoint-override-c00ea54e1670cb90.yaml new file mode 100644 index 00000000..a426db72 --- /dev/null +++ b/releasenotes/notes/add-export-variable-for-api-endpoint-override-c00ea54e1670cb90.yaml @@ -0,0 +1,7 @@ +--- +fixes: + - | + In addition to existing "--os-endpoint-override" option to override API + endpoint, user can also use export variable. For example, use + "export OS_SHARED_FILE_SYSTEM_ENDPOINT_OVERRIDE=" and then + use "openstack share list" command to refer different Manila API endpoint. diff --git a/releasenotes/notes/add-share-replica-metadata-e6c1c2e00295d2dd.yaml b/releasenotes/notes/add-share-replica-metadata-e6c1c2e00295d2dd.yaml new file mode 100644 index 00000000..e06e41df --- /dev/null +++ b/releasenotes/notes/add-share-replica-metadata-e6c1c2e00295d2dd.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + Adds support to create/update/delete replica metadata (properties) + with set and unset command. diff --git a/releasenotes/notes/add-support-for-qos-type-and-specs-2b5ce0002721cdb3.yaml b/releasenotes/notes/add-support-for-qos-type-and-specs-2b5ce0002721cdb3.yaml new file mode 100644 index 00000000..7bec9025 --- /dev/null +++ b/releasenotes/notes/add-support-for-qos-type-and-specs-2b5ce0002721cdb3.yaml @@ -0,0 +1,6 @@ +--- +features: + - | + Added support for QoS types and specs via the Python SDK and the + ``openstack share qos type`` CLI commands (create, delete, list, show, + set, unset). Available from microversion 2.94 and above. diff --git a/releasenotes/notes/add-support-of-api-endpoint-override-e36e75246d39a367.yaml b/releasenotes/notes/add-support-of-api-endpoint-override-e36e75246d39a367.yaml new file mode 100644 index 00000000..9eddf873 --- /dev/null +++ b/releasenotes/notes/add-support-of-api-endpoint-override-e36e75246d39a367.yaml @@ -0,0 +1,6 @@ +--- +features: + - Manilaclient is updated to consider API endpoint override option + `--os-endpoint-override`. For example, "openstack share list" command + for different API endpoint will be "openstack --os-endpoint-override + share list". diff --git a/releasenotes/notes/add-wait-flag-share-server-unmanage-819dd42abc2a4d2b.yaml b/releasenotes/notes/add-wait-flag-share-server-unmanage-819dd42abc2a4d2b.yaml new file mode 100644 index 00000000..8d5543bc --- /dev/null +++ b/releasenotes/notes/add-wait-flag-share-server-unmanage-819dd42abc2a4d2b.yaml @@ -0,0 +1,6 @@ +--- +features: + - | + The command "manila share-server-unmanage" now accepts an optional + "--wait" flag that allows users to let the client poll for the + completion of the operation. diff --git a/releasenotes/notes/bp-manage-with-mount-point-name-69be3a8aa4fcaa1f.yaml b/releasenotes/notes/bp-manage-with-mount-point-name-69be3a8aa4fcaa1f.yaml new file mode 100644 index 00000000..d8f70817 --- /dev/null +++ b/releasenotes/notes/bp-manage-with-mount-point-name-69be3a8aa4fcaa1f.yaml @@ -0,0 +1,4 @@ +--- +features: + - Updated CLI command for managing shares to accept + ``mount_point_name`` parameter as a option. diff --git a/releasenotes/notes/bug-2051394-fix-validate-neutron-info-ebe679675111eec9.yaml b/releasenotes/notes/bug-2051394-fix-validate-neutron-info-ebe679675111eec9.yaml new file mode 100644 index 00000000..f1e47c58 --- /dev/null +++ b/releasenotes/notes/bug-2051394-fix-validate-neutron-info-ebe679675111eec9.yaml @@ -0,0 +1,12 @@ +fixes: + - | + The "openstack share network create" and + "openstack share network subnet create" commands + now validate Neutron network information provided + before sending the request. + + Previously, validation only occurred in the Manila service + which could result in client-side errors when invalid network + or subnet IDs were supplied. The client now performs + proper validation and handles missing or invalid + network data gracefully. \ No newline at end of file diff --git a/releasenotes/notes/bug-2057951-fix-client-region-name-67fed93b76429b63.yaml b/releasenotes/notes/bug-2057951-fix-client-region-name-67fed93b76429b63.yaml new file mode 100644 index 00000000..e4955f1b --- /dev/null +++ b/releasenotes/notes/bug-2057951-fix-client-region-name-67fed93b76429b63.yaml @@ -0,0 +1,9 @@ +fixes: + - | + Fixed Bug #2057951: The manila python client previously + ignored the "region_name" parameter when initializing a + client session. This caused the client to use wrong API + endpoint in multi-region deployments. The client now + correctly respects the "region_name" value ensuring + requests are routed to the intended region + diff --git a/releasenotes/notes/bug-2068732-fix-migration-get-progress-on-source-share-server-7ef327dcdedcfbd6.yaml b/releasenotes/notes/bug-2068732-fix-migration-get-progress-on-source-share-server-7ef327dcdedcfbd6.yaml new file mode 100644 index 00000000..fbe7711d --- /dev/null +++ b/releasenotes/notes/bug-2068732-fix-migration-get-progress-on-source-share-server-7ef327dcdedcfbd6.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - | + Fixed an issue while getting share server migration progress for source + share server after migration is completed. diff --git a/releasenotes/notes/bug-2108991-fix-task-state-none-handling-in-osc-share-set-307f3f4a2b232dd8.yaml b/releasenotes/notes/bug-2108991-fix-task-state-none-handling-in-osc-share-set-307f3f4a2b232dd8.yaml new file mode 100644 index 00000000..1b2d4a80 --- /dev/null +++ b/releasenotes/notes/bug-2108991-fix-task-state-none-handling-in-osc-share-set-307f3f4a2b232dd8.yaml @@ -0,0 +1,7 @@ +--- +fixes: + - | + The `openstack share set` and `openstack share server set` commands now + properly handle the `--task-state` argument when given no value or "None", + sending a proper null value to the API. For more details, please refer to + `Launchpad bug #2108991 `_. diff --git a/releasenotes/notes/bug-2109376-fix-ensure-shares-command-69feb1794fea418a.yaml b/releasenotes/notes/bug-2109376-fix-ensure-shares-command-69feb1794fea418a.yaml new file mode 100644 index 00000000..03cf4ac9 --- /dev/null +++ b/releasenotes/notes/bug-2109376-fix-ensure-shares-command-69feb1794fea418a.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - | + Fixed an issue while running ensure shares and getting a not found + response. The command should now work properly. diff --git a/releasenotes/notes/bug-2132937-update-share-group-fix-41558fef427c84a2.yaml b/releasenotes/notes/bug-2132937-update-share-group-fix-41558fef427c84a2.yaml new file mode 100644 index 00000000..80d6a0d8 --- /dev/null +++ b/releasenotes/notes/bug-2132937-update-share-group-fix-41558fef427c84a2.yaml @@ -0,0 +1,8 @@ +--- +fixes: + - | + Fixed an issue where the ``share group update`` command (and the + underlying ``share_groups.update()`` python binding) was missing + the experimental API flag. The client now correctly treats this + action as experimental and sends the required headers. (Bug `2132937 + `_) diff --git a/releasenotes/notes/deprecate-keystoneauth-params-ebbaaf6be4df4bb7.yaml b/releasenotes/notes/deprecate-keystoneauth-params-ebbaaf6be4df4bb7.yaml new file mode 100644 index 00000000..14065910 --- /dev/null +++ b/releasenotes/notes/deprecate-keystoneauth-params-ebbaaf6be4df4bb7.yaml @@ -0,0 +1,12 @@ +--- +deprecations: + - | + Legacy keystoneclient options "use_keyring", "force_new_token" + and "cached_token_lifetime" were dropped. Using these options + will have no effect with this release and will cause an error + in a future release. +security: + - | + The use of the keystoneclient library has been replaced with keystoneauth. + The latter library is better maintained and has more auth options that are + now usable with manilaclient. diff --git a/releasenotes/notes/graduate-share-migration-feature-3b8fa72d4e91a517.yaml b/releasenotes/notes/graduate-share-migration-feature-3b8fa72d4e91a517.yaml new file mode 100644 index 00000000..fd04a103 --- /dev/null +++ b/releasenotes/notes/graduate-share-migration-feature-3b8fa72d4e91a517.yaml @@ -0,0 +1,11 @@ +--- +prelude: > + - | + Share migration APIs have graduated from their `experimental feature + state `_ + from API version ``2.96``. The share migration actions + (``migration_start``, ``migration_complete``, ``migration_cancel``, + ``migration_get_progress`` and ``reset_task_state``) no longer require + the inclusion of the ``X-OpenStack-Manila-API-Experimental`` header in + API requests starting at version ``2.96``. Older microversions continue + to send the experimental header for backward compatibility. diff --git a/releasenotes/notes/remove-py39-5278e896dc045854.yaml b/releasenotes/notes/remove-py39-5278e896dc045854.yaml new file mode 100644 index 00000000..eaf3014b --- /dev/null +++ b/releasenotes/notes/remove-py39-5278e896dc045854.yaml @@ -0,0 +1,5 @@ +--- +upgrade: + - | + Support for Python 3.9 has been removed. Now Python 3.10 is the minimum + version supported. diff --git a/releasenotes/notes/remove-python-client-a142b99ccc89731c.yaml b/releasenotes/notes/remove-python-client-a142b99ccc89731c.yaml new file mode 100644 index 00000000..7dd6380e --- /dev/null +++ b/releasenotes/notes/remove-python-client-a142b99ccc89731c.yaml @@ -0,0 +1,5 @@ +--- +upgrade: + The "manila" CLI utility has been removed in this release. The + mapping/decoder documentation still exists to provide transition + to users that are unfamiliar with the "openstack" CLI. diff --git a/releasenotes/notes/share-backup-out-of-place-restore-98740badef59ba32.yaml b/releasenotes/notes/share-backup-out-of-place-restore-98740badef59ba32.yaml new file mode 100644 index 00000000..9481b1cb --- /dev/null +++ b/releasenotes/notes/share-backup-out-of-place-restore-98740badef59ba32.yaml @@ -0,0 +1,7 @@ +--- +features: + - | + Added support for targeted share backup restores via the openstackclient + plugin. You can use the openstack client to restore a share backup from + one source share to another target share, given the backup or share driver + provides support for the operation. Available from microversion 2.91. diff --git a/releasenotes/source/2024.1.rst b/releasenotes/source/2024.1.rst index 4977a4f1..6896656b 100644 --- a/releasenotes/source/2024.1.rst +++ b/releasenotes/source/2024.1.rst @@ -3,4 +3,4 @@ =========================== .. release-notes:: - :branch: stable/2024.1 + :branch: unmaintained/2024.1 diff --git a/releasenotes/source/2025.2.rst b/releasenotes/source/2025.2.rst new file mode 100644 index 00000000..4dae18d8 --- /dev/null +++ b/releasenotes/source/2025.2.rst @@ -0,0 +1,6 @@ +=========================== +2025.2 Series Release Notes +=========================== + +.. release-notes:: + :branch: stable/2025.2 diff --git a/releasenotes/source/2026.1.rst b/releasenotes/source/2026.1.rst new file mode 100644 index 00000000..3d286158 --- /dev/null +++ b/releasenotes/source/2026.1.rst @@ -0,0 +1,6 @@ +=========================== +2026.1 Series Release Notes +=========================== + +.. release-notes:: + :branch: stable/2026.1 diff --git a/releasenotes/source/conf.py b/releasenotes/source/conf.py index 8ff2ac89..ec17975f 100644 --- a/releasenotes/source/conf.py +++ b/releasenotes/source/conf.py @@ -190,10 +190,8 @@ latex_elements = { # The paper size ('letterpaper' or 'a4paper'). # 'papersize': 'letterpaper', - # The font size ('10pt', '11pt' or '12pt'). # 'pointsize': '10pt', - # Additional stuff for the LaTeX preamble. # 'preamble': '', } @@ -202,9 +200,13 @@ # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - ('index', 'PythonManilaclientReleaseNotes.tex', - 'python-manilaclient Release Notes Documentation', - 'Manila Developers', 'manual'), + ( + 'index', + 'PythonManilaclientReleaseNotes.tex', + 'python-manilaclient Release Notes Documentation', + 'Manila Developers', + 'manual', + ), ] # The name of an image file (relative to this directory) to place at the top of @@ -233,9 +235,13 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - ('index', 'python-manilaclientreleasenotes', - 'python-manilaclient Release Notes Documentation', - ['Manila Developers'], 1) + ( + 'index', + 'python-manilaclientreleasenotes', + 'python-manilaclient Release Notes Documentation', + ['Manila Developers'], + 1, + ) ] # If true, show URL addresses after external links. @@ -248,11 +254,15 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - ('index', 'PythonManilaclientReleaseNotes', - 'python-manilaclient Release Notes Documentation', - 'Manila Developers', 'PythonManilaclientReleaseNotes', - 'One line description of project.', - 'Miscellaneous'), + ( + 'index', + 'PythonManilaclientReleaseNotes', + 'python-manilaclient Release Notes Documentation', + 'Manila Developers', + 'PythonManilaclientReleaseNotes', + 'One line description of project.', + 'Miscellaneous', + ), ] # Documents to append as an appendix to all manuals. diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst index ba7efdbe..9233d8d2 100644 --- a/releasenotes/source/index.rst +++ b/releasenotes/source/index.rst @@ -7,6 +7,8 @@ python-manilaclient Release Notes :maxdepth: 1 unreleased + 2026.1 + 2025.2 2025.1 2024.2 2024.1 diff --git a/requirements.txt b/requirements.txt index 643648ee..68a76f22 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,5 +11,5 @@ oslo.utils>=3.33.0 # Apache-2.0 PrettyTable>=0.7.1 # BSD requests>=2.14.2 # Apache-2.0 osc-lib>=3.2.0 # Apache-2.0 -python-keystoneclient>=3.8.0 # Apache-2.0 +keystoneauth1>=3.0.0 # Apache-2.0 debtcollector>=1.2.0 # Apache-2.0 diff --git a/setup.cfg b/setup.cfg index 0045e07b..3ad97f23 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,190 +1,2 @@ [metadata] name = python-manilaclient -summary = Client library for OpenStack Manila API. -description_file = - README.rst -author = OpenStack -author_email = openstack-discuss@lists.openstack.org -home_page = https://docs.openstack.org/python-manilaclient/latest/ -python_requires = >=3.9 -classifier = - Development Status :: 5 - Production/Stable - Environment :: Console - Environment :: OpenStack - Intended Audience :: Developers - Intended Audience :: Information Technology - License :: OSI Approved :: Apache Software License - Operating System :: OS Independent - Programming Language :: Python - Programming Language :: Python :: 3 :: Only - Programming Language :: Python :: 3 - Programming Language :: Python :: 3.9 - Programming Language :: Python :: 3.10 - Programming Language :: Python :: 3.11 - Programming Language :: Python :: 3.12 - -[files] -packages = - manilaclient - -[entry_points] -console_scripts = - manila = manilaclient.shell:main -oslo.config.opts = - manilaclient.config = manilaclient.config:list_opts - -openstack.cli.extension = - share = manilaclient.osc.plugin - -openstack.share.v2 = - share_list = manilaclient.osc.v2.share:ListShare - share_create = manilaclient.osc.v2.share:CreateShare - share_delete = manilaclient.osc.v2.share:DeleteShare - share_show = manilaclient.osc.v2.share:ShowShare - share_set = manilaclient.osc.v2.share:SetShare - share_unset = manilaclient.osc.v2.share:UnsetShare - share_resize = manilaclient.osc.v2.share:ResizeShare - share_adopt = manilaclient.osc.v2.share:AdoptShare - share_abandon = manilaclient.osc.v2.share:AbandonShare - share_migration_start = manilaclient.osc.v2.share:ShareMigrationStart - share_migration_cancel = manilaclient.osc.v2.share:ShareMigrationCancel - share_migration_complete = manilaclient.osc.v2.share:ShareMigrationComplete - share_migration_show = manilaclient.osc.v2.share:ShareMigrationShow - share_export_location_show = manilaclient.osc.v2.share:ShareExportLocationShow - share_export_location_list = manilaclient.osc.v2.share:ShareExportLocationList - share_export_location_set = manilaclient.osc.v2.share:ShareExportLocationSet - share_export_location_unset = manilaclient.osc.v2.share:ShareExportLocationUnset - share_properties_show = manilaclient.osc.v2.share:ShowShareProperties - share_restore = manilaclient.osc.v2.share:RestoreShare - share_revert = manilaclient.osc.v2.share:RevertShare - share_access_create = manilaclient.osc.v2.share_access_rules:ShareAccessAllow - share_access_delete = manilaclient.osc.v2.share_access_rules:ShareAccessDeny - share_access_list = manilaclient.osc.v2.share_access_rules:ListShareAccess - share_access_show = manilaclient.osc.v2.share_access_rules:ShowShareAccess - share_access_set = manilaclient.osc.v2.share_access_rules:SetShareAccess - share_access_unset = manilaclient.osc.v2.share_access_rules:UnsetShareAccess - share_backup_create = manilaclient.osc.v2.share_backups:CreateShareBackup - share_backup_delete = manilaclient.osc.v2.share_backups:DeleteShareBackup - share_backup_list = manilaclient.osc.v2.share_backups:ListShareBackup - share_backup_show = manilaclient.osc.v2.share_backups:ShowShareBackup - share_backup_restore = manilaclient.osc.v2.share_backups:RestoreShareBackup - share_backup_set = manilaclient.osc.v2.share_backups:SetShareBackup - share_backup_unset = manilaclient.osc.v2.share_backups:UnsetShareBackup - share_type_create = manilaclient.osc.v2.share_types:CreateShareType - share_type_delete = manilaclient.osc.v2.share_types:DeleteShareType - share_type_set = manilaclient.osc.v2.share_types:SetShareType - share_type_unset = manilaclient.osc.v2.share_types:UnsetShareType - share_type_list = manilaclient.osc.v2.share_types:ListShareType - share_type_show = manilaclient.osc.v2.share_types:ShowShareType - share_type_access_create = manilaclient.osc.v2.share_type_access:ShareTypeAccessAllow - share_type_access_list = manilaclient.osc.v2.share_type_access:ListShareTypeAccess - share_type_access_delete = manilaclient.osc.v2.share_type_access:ShareTypeAccessDeny - share_quota_set = manilaclient.osc.v2.quotas:QuotaSet - share_quota_show = manilaclient.osc.v2.quotas:QuotaShow - share_quota_delete = manilaclient.osc.v2.quotas:QuotaDelete - share_snapshot_create = manilaclient.osc.v2.share_snapshots:CreateShareSnapshot - share_snapshot_delete = manilaclient.osc.v2.share_snapshots:DeleteShareSnapshot - share_snapshot_show = manilaclient.osc.v2.share_snapshots:ShowShareSnapshot - share_snapshot_set = manilaclient.osc.v2.share_snapshots:SetShareSnapshot - share_snapshot_unset = manilaclient.osc.v2.share_snapshots:UnsetShareSnapshot - share_snapshot_list = manilaclient.osc.v2.share_snapshots:ListShareSnapshot - share_snapshot_adopt = manilaclient.osc.v2.share_snapshots:AdoptShareSnapshot - share_snapshot_abandon = manilaclient.osc.v2.share_snapshots:AbandonShareSnapshot - share_snapshot_access_create = manilaclient.osc.v2.share_snapshots:ShareSnapshotAccessAllow - share_snapshot_access_delete = manilaclient.osc.v2.share_snapshots:ShareSnapshotAccessDeny - share_snapshot_access_list = manilaclient.osc.v2.share_snapshots:ShareSnapshotAccessList - share_snapshot_export_location_list = manilaclient.osc.v2.share_snapshots:ShareSnapshotListExportLocation - share_snapshot_export_location_show = manilaclient.osc.v2.share_snapshots:ShareSnapshotShowExportLocation - share_snapshot_instance_list = manilaclient.osc.v2.share_snapshot_instances:ListShareSnapshotInstance - share_snapshot_instance_show = manilaclient.osc.v2.share_snapshot_instances:ShowShareSnapshotInstance - share_snapshot_instance_set = manilaclient.osc.v2.share_snapshot_instances:SetShareSnapshotInstance - share_snapshot_instance_export_location_list = manilaclient.osc.v2.share_snapshot_instance_export_locations:ShareSnapshotInstanceExportLocationList - share_snapshot_instance_export_location_show = manilaclient.osc.v2.share_snapshot_instance_export_locations:ShareSnapshotInstanceExportLocationShow - share_message_delete = manilaclient.osc.v2.messages:DeleteMessage - share_message_list = manilaclient.osc.v2.messages:ListMessage - share_message_show = manilaclient.osc.v2.messages:ShowMessage - share_replica_create = manilaclient.osc.v2.share_replicas:CreateShareReplica - share_replica_delete = manilaclient.osc.v2.share_replicas:DeleteShareReplica - share_replica_list = manilaclient.osc.v2.share_replicas:ListShareReplica - share_replica_show = manilaclient.osc.v2.share_replicas:ShowShareReplica - share_replica_set = manilaclient.osc.v2.share_replicas:SetShareReplica - share_replica_promote = manilaclient.osc.v2.share_replicas:PromoteShareReplica - share_replica_resync = manilaclient.osc.v2.share_replicas:ResyncShareReplica - share_replica_export_location_list = manilaclient.osc.v2.share_replica_export_locations:ShareReplicaListExportLocation - share_replica_export_location_show = manilaclient.osc.v2.share_replica_export_locations:ShareReplicaShowExportLocation - share_availability_zone_list = manilaclient.osc.v2.availability_zones:ShareAvailabilityZoneList - share_service_set = manilaclient.osc.v2.services:SetShareService - share_service_list = manilaclient.osc.v2.services:ListShareService - share_service_ensure_shares = manilaclient.osc.v2.services:EnsureShareService - share_security_service_create = manilaclient.osc.v2.security_services:CreateShareSecurityService - share_security_service_delete = manilaclient.osc.v2.security_services:DeleteShareSecurityService - share_security_service_show = manilaclient.osc.v2.security_services:ShowShareSecurityService - share_security_service_set = manilaclient.osc.v2.security_services:SetShareSecurityService - share_security_service_unset = manilaclient.osc.v2.security_services:UnsetShareSecurityService - share_security_service_list = manilaclient.osc.v2.security_services:ListShareSecurityService - share_pool_list = manilaclient.osc.v2.share_pools:ListSharePools - share_instance_delete = manilaclient.osc.v2.share_instances:ShareInstanceDelete - share_instance_list = manilaclient.osc.v2.share_instances:ShareInstanceList - share_instance_set = manilaclient.osc.v2.share_instances:ShareInstanceSet - share_instance_show = manilaclient.osc.v2.share_instances:ShareInstanceShow - share_instance_export_location_show = manilaclient.osc.v2.share_instance_export_locations:ShareInstanceShowExportLocation - share_instance_export_location_list = manilaclient.osc.v2.share_instance_export_locations:ShareInstanceListExportLocation - share_limits_show = manilaclient.osc.v2.share_limits:ShareLimitsShow - share_network_list = manilaclient.osc.v2.share_networks:ListShareNetwork - share_network_show = manilaclient.osc.v2.share_networks:ShowShareNetwork - share_network_create = manilaclient.osc.v2.share_networks:CreateShareNetwork - share_network_delete = manilaclient.osc.v2.share_networks:DeleteShareNetwork - share_network_set = manilaclient.osc.v2.share_networks:SetShareNetwork - share_network_unset = manilaclient.osc.v2.share_networks:UnsetShareNetwork - share_network_subnet_create = manilaclient.osc.v2.share_network_subnets:CreateShareNetworkSubnet - share_network_subnet_delete = manilaclient.osc.v2.share_network_subnets:DeleteShareNetworkSubnet - share_network_subnet_show = manilaclient.osc.v2.share_network_subnets:ShowShareNetworkSubnet - share_network_subnet_set = manilaclient.osc.v2.share_network_subnets:SetShareNetworkSubnet - share_network_subnet_unset = manilaclient.osc.v2.share_network_subnets:UnsetShareNetworkSubnet - share_group_create = manilaclient.osc.v2.share_groups:CreateShareGroup - share_group_delete = manilaclient.osc.v2.share_groups:DeleteShareGroup - share_group_list = manilaclient.osc.v2.share_groups:ListShareGroup - share_group_show = manilaclient.osc.v2.share_groups:ShowShareGroup - share_group_set = manilaclient.osc.v2.share_groups:SetShareGroup - share_group_unset = manilaclient.osc.v2.share_groups:UnsetShareGroup - share_group_type_create = manilaclient.osc.v2.share_group_types:CreateShareGroupType - share_group_type_delete = manilaclient.osc.v2.share_group_types:DeleteShareGroupType - share_group_type_list = manilaclient.osc.v2.share_group_types:ListShareGroupType - share_group_type_show = manilaclient.osc.v2.share_group_types:ShowShareGroupType - share_group_type_set = manilaclient.osc.v2.share_group_types:SetShareGroupType - share_group_type_unset = manilaclient.osc.v2.share_group_types:UnsetShareGroupType - share_group_type_access_create = manilaclient.osc.v2.share_group_type_access:ShareGroupTypeAccessAllow - share_group_type_access_list = manilaclient.osc.v2.share_group_type_access:ListShareGroupTypeAccess - share_group_type_access_delete = manilaclient.osc.v2.share_group_type_access:ShareGroupTypeAccessDeny - share_group_snapshot_create = manilaclient.osc.v2.share_group_snapshots:CreateShareGroupSnapshot - share_group_snapshot_delete = manilaclient.osc.v2.share_group_snapshots:DeleteShareGroupSnapshot - share_group_snapshot_show= manilaclient.osc.v2.share_group_snapshots:ShowShareGroupSnapshot - share_group_snapshot_list = manilaclient.osc.v2.share_group_snapshots:ListShareGroupSnapshot - share_group_snapshot_set = manilaclient.osc.v2.share_group_snapshots:SetShareGroupSnapshot - share_group_snapshot_unset = manilaclient.osc.v2.share_group_snapshots:UnsetShareGroupSnapshot - share_group_snapshot_members_list = manilaclient.osc.v2.share_group_snapshots:ListShareGroupSnapshotMembers - share_server_delete = manilaclient.osc.v2.share_servers:DeleteShareServer - share_server_show = manilaclient.osc.v2.share_servers:ShowShareServer - share_server_list = manilaclient.osc.v2.share_servers:ListShareServer - share_server_adopt = manilaclient.osc.v2.share_servers:AdoptShareServer - share_server_abandon = manilaclient.osc.v2.share_servers:AbandonShareServer - share_server_set = manilaclient.osc.v2.share_servers:SetShareServer - share_server_migration_cancel = manilaclient.osc.v2.share_servers:ShareServerMigrationCancel - share_server_migration_complete = manilaclient.osc.v2.share_servers:ShareServerMigrationComplete - share_server_migration_show = manilaclient.osc.v2.share_servers:ShareServerMigrationShow - share_server_migration_start = manilaclient.osc.v2.share_servers:ShareServerMigrationStart - share_transfer_create = manilaclient.osc.v2.share_transfers:CreateShareTransfer - share_transfer_delete = manilaclient.osc.v2.share_transfers:DeleteShareTransfer - share_transfer_list = manilaclient.osc.v2.share_transfers:ListShareTransfer - share_transfer_show = manilaclient.osc.v2.share_transfers:ShowShareTransfer - share_transfer_accept = manilaclient.osc.v2.share_transfers:AcceptShareTransfer - share_lock_create = manilaclient.osc.v2.resource_locks:CreateResourceLock - share_lock_list = manilaclient.osc.v2.resource_locks:ListResourceLock - share_lock_show = manilaclient.osc.v2.resource_locks:ShowResourceLock - share_lock_set = manilaclient.osc.v2.resource_locks:SetResourceLock - share_lock_unset = manilaclient.osc.v2.resource_locks:UnsetResourceLock - share_lock_delete = manilaclient.osc.v2.resource_locks:DeleteResourceLock - -[coverage:run] -omit = manilaclient/tests/* -branch = true diff --git a/setup.py b/setup.py index cd35c3c3..481505b0 100644 --- a/setup.py +++ b/setup.py @@ -15,6 +15,4 @@ import setuptools -setuptools.setup( - setup_requires=['pbr>=2.0.0'], - pbr=True) +setuptools.setup(setup_requires=['pbr>=2.0.0'], pbr=True) diff --git a/test-requirements.txt b/test-requirements.txt index 79d70223..da2474ff 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,6 +1,7 @@ coverage!=4.4,>=4.0 # Apache-2.0 ddt>=1.0.1 # MIT fixtures>=3.0.0 # Apache-2.0/BSD +requests-mock>=1.2.0 # Apache-2.0 stestr>=2.0.0 # Apache-2.0 tempest>=17.1.0 # Apache-2.0 testtools>=2.2.0 # MIT diff --git a/tools/manila.bash_completion b/tools/manila.bash_completion deleted file mode 100644 index 8491e8ab..00000000 --- a/tools/manila.bash_completion +++ /dev/null @@ -1,15 +0,0 @@ -_manila() -{ - local cur prev opts - COMPREPLY=() - cur="${COMP_WORDS[COMP_CWORD]}" - prev="${COMP_WORDS[COMP_CWORD-1]}" - - opts="$(manila bash_completion)" - - COMPLETION_CACHE=~/.cache/manilaclient/*/*-cache - opts+=" "$(cat $COMPLETION_CACHE 2> /dev/null | tr '\n' ' ') - - COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) -} -complete -F _manila manila diff --git a/tox.ini b/tox.ini index 72c8a2ce..e787e52c 100644 --- a/tox.ini +++ b/tox.ini @@ -1,14 +1,8 @@ [tox] -distribute = False envlist = py3,pep8 minversion = 4.11.0 -# Automatic envs (pyXX) will only use the python version appropriate to that -# env and ignore basepython inherited from [testenv] if we set -# ignore_basepython_conflict. -ignore_basepython_conflict = true [testenv] -basepython = python3 usedevelop = true setenv = VIRTUAL_ENV={envdir} OS_STDOUT_CAPTURE=1 @@ -31,11 +25,11 @@ deps = commands = reno new {posargs} [testenv:pep8] +skip_install = true deps = - pre-commit - + pre-commit commands = - pre-commit run --all-files --show-diff-on-failure + pre-commit run --all-files --show-diff-on-failure [testenv:venv] commands = {posargs} @@ -98,13 +92,14 @@ deps = bandit commands = bandit -r manilaclient -x manilaclient/tests/* -n5 -ll [flake8] -# F821: undefined name -# W503 line break before binary operator -# W504 line break after binary operator -ignore = F821,W503,W504 -builtins = _ -# [H106] Don't put vim configuration in source files. -# [H203] Use assertIs(Not)None to check for None. -# [H904] Delay string interpolations at logging calls. +show-source = true +exclude = .venv,.git,.tox,dist,doc,*lib/python*,*egg,build,tools,releasenotes +# We only enable the hacking (H) checks +select = H +# H301 Black will put commas after imports that can't fit on one line +ignore = H301 +# H106 Don't put vim configuration in source files. +# H203 Use assertIs(Not)None to check for None. +# H904 Delay string interpolations at logging calls. enable-extensions = H106,H203,H904 -exclude = .venv,.tox,dist,doc,*egg,build +application_import_names = manilaclient diff --git a/zuul.d/python-manilaclient-jobs.yaml b/zuul.d/python-manilaclient-jobs.yaml index 0984a95f..4013638c 100644 --- a/zuul.d/python-manilaclient-jobs.yaml +++ b/zuul.d/python-manilaclient-jobs.yaml @@ -23,7 +23,6 @@ devstack_plugins: manila: https://opendev.org/openstack/manila devstack_localrc: - USE_PYTHON3: true INSTALL_TEMPEST: false # Enable manila with a fake driver that supports all capabilities MANILA_CONFIGURE_DEFAULT_TYPES: true @@ -81,7 +80,7 @@ ovsdb-server: true # Neutron services q-svc: true - q-ovn-metadata-agent: true + q-ovn-agent: true # openstack-cli-server causes problem with credential switch in ansible # task openstack-cli-server: false